aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/tools/testing/selftests/powerpc/dexcr/lsdexcr.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/testing/selftests/powerpc/dexcr/lsdexcr.c')
-rw-r--r--tools/testing/selftests/powerpc/dexcr/lsdexcr.c141
1 files changed, 141 insertions, 0 deletions
diff --git a/tools/testing/selftests/powerpc/dexcr/lsdexcr.c b/tools/testing/selftests/powerpc/dexcr/lsdexcr.c
new file mode 100644
index 000000000000..94abbfcc389e
--- /dev/null
+++ b/tools/testing/selftests/powerpc/dexcr/lsdexcr.c
@@ -0,0 +1,141 @@
+// 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;
+}