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(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

source code of linux/tools/testing/selftests/powerpc/dexcr/lsdexcr.c