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(source: DEXCR); |
114 | hdexcr = get_dexcr(source: HDEXCR); |
115 | effective = dexcr | hdexcr; |
116 | |
117 | print_dexcr(name: " DEXCR" , bits: dexcr); |
118 | print_dexcr(name: " HDEXCR" , bits: hdexcr); |
119 | print_dexcr(name: "Effective" , bits: 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 | } |
142 | |