142 lines
2.7 KiB
C
142 lines
2.7 KiB
C
|
// 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;
|
||
|
}
|