selftests/powerpc/dexcr: Add DEXCR status utility lsdexcr
authorBenjamin Gray <bgray@linux.ibm.com>
Mon, 19 Jun 2023 07:36:28 +0000 (17:36 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Mon, 19 Jun 2023 07:36:28 +0000 (17:36 +1000)
Add a utility 'lsdexcr' to print the current DEXCR status. Useful for
quickly checking the status such as when debugging test failures or
verifying the new default DEXCR does what you want (for userspace at
least). Example output:

    # ./lsdexcr
       uDEXCR: 04000000 (NPHIE)
       HDEXCR: 00000000
    Effective: 04000000 (NPHIE)

            SBHE   (0): clear   (Speculative branch hint enable)
          IBRTPD   (3): clear   (Indirect branch recurrent target ...)
           SRAPD   (4): clear   (Subroutine return address ...)
           NPHIE * (5): set   (Non-privileged hash instruction enable)
            PHIE   (6): clear   (Privileged hash instruction enable)

    DEXCR[NPHIE] enabled: hashst/hashchk working

Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/20230616034846.311705-12-bgray@linux.ibm.com
tools/testing/selftests/powerpc/dexcr/.gitignore
tools/testing/selftests/powerpc/dexcr/Makefile
tools/testing/selftests/powerpc/dexcr/lsdexcr.c [new file with mode: 0644]

index d12e4560aca9d1931c9630b7fb281e3e0d62755a..b82f45dd46b9c8d828a42d0845b2200f30b75091 100644 (file)
@@ -1 +1,2 @@
 hashchk_test
+lsdexcr
index 16c8b489948a5af31a362275e5710189dce11660..76210f2bcec3c89e2e6a03c94c70ecfb257c6a2d 100644 (file)
@@ -1,7 +1,9 @@
 TEST_GEN_PROGS := hashchk_test
+TEST_GEN_FILES := lsdexcr
 
 include ../../lib.mk
 
 $(OUTPUT)/hashchk_test: CFLAGS += -fno-pie $(call cc-option,-mno-rop-protect)
 
 $(TEST_GEN_PROGS): ../harness.c ../utils.c ./dexcr.c
+$(TEST_GEN_FILES): ../utils.c ./dexcr.c
diff --git a/tools/testing/selftests/powerpc/dexcr/lsdexcr.c b/tools/testing/selftests/powerpc/dexcr/lsdexcr.c
new file mode 100644 (file)
index 0000000..94abbfc
--- /dev/null
@@ -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;
+}