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
11static unsigned int dexcr;
12static unsigned int hdexcr;
13static unsigned int effective;
14
15struct dexcr_aspect {
16	const char *name;
17	const char *desc;
18	unsigned int index;
19};
20
21static 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
49static 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
58static 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
87static 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
106int 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