Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/powerpc/dexcr: Add DEXCR status utility lsdexcr

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

authored by

Benjamin Gray and committed by
Michael Ellerman
a16e472c bdb07f35

+144
+1
tools/testing/selftests/powerpc/dexcr/.gitignore
··· 1 1 hashchk_test 2 + lsdexcr
+2
tools/testing/selftests/powerpc/dexcr/Makefile
··· 1 1 TEST_GEN_PROGS := hashchk_test 2 + TEST_GEN_FILES := lsdexcr 2 3 3 4 include ../../lib.mk 4 5 5 6 $(OUTPUT)/hashchk_test: CFLAGS += -fno-pie $(call cc-option,-mno-rop-protect) 6 7 7 8 $(TEST_GEN_PROGS): ../harness.c ../utils.c ./dexcr.c 9 + $(TEST_GEN_FILES): ../utils.c ./dexcr.c
+141
tools/testing/selftests/powerpc/dexcr/lsdexcr.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + 3 + #include <errno.h> 4 + #include <stddef.h> 5 + #include <stdio.h> 6 + #include <string.h> 7 + 8 + #include "dexcr.h" 9 + #include "utils.h" 10 + 11 + static unsigned int dexcr; 12 + static unsigned int hdexcr; 13 + static unsigned int effective; 14 + 15 + struct dexcr_aspect { 16 + const char *name; 17 + const char *desc; 18 + unsigned int index; 19 + }; 20 + 21 + static const struct dexcr_aspect aspects[] = { 22 + { 23 + .name = "SBHE", 24 + .desc = "Speculative branch hint enable", 25 + .index = 0, 26 + }, 27 + { 28 + .name = "IBRTPD", 29 + .desc = "Indirect branch recurrent target prediction disable", 30 + .index = 3, 31 + }, 32 + { 33 + .name = "SRAPD", 34 + .desc = "Subroutine return address prediction disable", 35 + .index = 4, 36 + }, 37 + { 38 + .name = "NPHIE", 39 + .desc = "Non-privileged hash instruction enable", 40 + .index = 5, 41 + }, 42 + { 43 + .name = "PHIE", 44 + .desc = "Privileged hash instruction enable", 45 + .index = 6, 46 + }, 47 + }; 48 + 49 + static void print_list(const char *list[], size_t len) 50 + { 51 + for (size_t i = 0; i < len; i++) { 52 + printf("%s", list[i]); 53 + if (i + 1 < len) 54 + printf(", "); 55 + } 56 + } 57 + 58 + static void print_dexcr(char *name, unsigned int bits) 59 + { 60 + const char *enabled_aspects[ARRAY_SIZE(aspects) + 1] = {NULL}; 61 + size_t j = 0; 62 + 63 + printf("%s: %08x", name, bits); 64 + 65 + if (bits == 0) { 66 + printf("\n"); 67 + return; 68 + } 69 + 70 + for (size_t i = 0; i < ARRAY_SIZE(aspects); i++) { 71 + unsigned int mask = DEXCR_PR_BIT(aspects[i].index); 72 + 73 + if (bits & mask) { 74 + enabled_aspects[j++] = aspects[i].name; 75 + bits &= ~mask; 76 + } 77 + } 78 + 79 + if (bits) 80 + enabled_aspects[j++] = "unknown"; 81 + 82 + printf(" ("); 83 + print_list(enabled_aspects, j); 84 + printf(")\n"); 85 + } 86 + 87 + static void print_aspect(const struct dexcr_aspect *aspect) 88 + { 89 + const char *attributes[8] = {NULL}; 90 + size_t j = 0; 91 + unsigned long mask; 92 + 93 + mask = DEXCR_PR_BIT(aspect->index); 94 + if (dexcr & mask) 95 + attributes[j++] = "set"; 96 + if (hdexcr & mask) 97 + attributes[j++] = "set (hypervisor)"; 98 + if (!(effective & mask)) 99 + attributes[j++] = "clear"; 100 + 101 + printf("%12s %c (%d): ", aspect->name, effective & mask ? '*' : ' ', aspect->index); 102 + print_list(attributes, j); 103 + printf(" \t(%s)\n", aspect->desc); 104 + } 105 + 106 + int main(int argc, char *argv[]) 107 + { 108 + if (!dexcr_exists()) { 109 + printf("DEXCR not detected on this hardware\n"); 110 + return 1; 111 + } 112 + 113 + dexcr = get_dexcr(DEXCR); 114 + hdexcr = get_dexcr(HDEXCR); 115 + effective = dexcr | hdexcr; 116 + 117 + print_dexcr(" DEXCR", dexcr); 118 + print_dexcr(" HDEXCR", hdexcr); 119 + print_dexcr("Effective", effective); 120 + printf("\n"); 121 + 122 + for (size_t i = 0; i < ARRAY_SIZE(aspects); i++) 123 + print_aspect(&aspects[i]); 124 + printf("\n"); 125 + 126 + if (effective & DEXCR_PR_NPHIE) { 127 + printf("DEXCR[NPHIE] enabled: hashst/hashchk "); 128 + if (hashchk_triggers()) 129 + printf("working\n"); 130 + else 131 + printf("failed to trigger\n"); 132 + } else { 133 + printf("DEXCR[NPHIE] disabled: hashst/hashchk "); 134 + if (hashchk_triggers()) 135 + printf("unexpectedly triggered\n"); 136 + else 137 + printf("ignored\n"); 138 + } 139 + 140 + return 0; 141 + }