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 }
142