// SPDX-License-Identifier: GPL-2.0+ #include <errno.h> #include <stddef.h> #include <stdio.h> #include <string.h> #include "dexcr.h" #include "utils.h" static unsigned int dexcr; static unsigned int hdexcr; static unsigned int effective; struct dexcr_aspect { const char *name; const char *desc; unsigned int index; }; static const struct dexcr_aspect aspects[] = { { .name = "SBHE", .desc = "Speculative branch hint enable", .index = 0, }, { .name = "IBRTPD", .desc = "Indirect branch recurrent target prediction disable", .index = 3, }, { .name = "SRAPD", .desc = "Subroutine return address prediction disable", .index = 4, }, { .name = "NPHIE", .desc = "Non-privileged hash instruction enable", .index = 5, }, { .name = "PHIE", .desc = "Privileged hash instruction enable", .index = 6, }, }; static void print_list(const char *list[], size_t len) { for (size_t i = 0; i < len; i++) { printf("%s", list[i]); if (i + 1 < len) printf(", "); } } static void print_dexcr(char *name, unsigned int bits) { const char *enabled_aspects[ARRAY_SIZE(aspects) + 1] = {NULL}; size_t j = 0; printf("%s: %08x", name, bits); if (bits == 0) { printf("\n"); return; } for (size_t i = 0; i < ARRAY_SIZE(aspects); i++) { unsigned int mask = DEXCR_PR_BIT(aspects[i].index); if (bits & mask) { enabled_aspects[j++] = aspects[i].name; bits &= ~mask; } } if (bits) enabled_aspects[j++] = "unknown"; printf(" ("); print_list(enabled_aspects, j); printf(")\n"); } static void print_aspect(const struct dexcr_aspect *aspect) { const char *attributes[8] = {NULL}; size_t j = 0; unsigned long mask; mask = DEXCR_PR_BIT(aspect->index); if (dexcr & mask) attributes[j++] = "set"; if (hdexcr & mask) attributes[j++] = "set (hypervisor)"; if (!(effective & mask)) attributes[j++] = "clear"; printf("%12s %c (%d): ", aspect->name, effective & mask ? '*' : ' ', aspect->index); print_list(attributes, j); printf(" \t(%s)\n", aspect->desc); } int main(int argc, char *argv[]) { if (!dexcr_exists()) { printf("DEXCR not detected on this hardware\n"); return 1; } dexcr = get_dexcr(DEXCR); hdexcr = get_dexcr(HDEXCR); effective = dexcr | hdexcr; print_dexcr(" DEXCR", dexcr); print_dexcr(" HDEXCR", hdexcr); print_dexcr("Effective", effective); printf("\n"); for (size_t i = 0; i < ARRAY_SIZE(aspects); i++) print_aspect(&aspects[i]); printf("\n"); if (effective & DEXCR_PR_NPHIE) { printf("DEXCR[NPHIE] enabled: hashst/hashchk "); if (hashchk_triggers()) printf("working\n"); else printf("failed to trigger\n"); } else { printf("DEXCR[NPHIE] disabled: hashst/hashchk "); if (hashchk_triggers()) printf("unexpectedly triggered\n"); else printf("ignored\n"); } return 0; }