lsdexcr.c (9c4866b209ad31cae7c832d45c6137ce6a993ca0) lsdexcr.c (f88723a609787254f7645eb6ac261b8363e8a5bc)
1// SPDX-License-Identifier: GPL-2.0+
2
3#include <stddef.h>
4#include <stdio.h>
5#include <string.h>
6#include <sys/prctl.h>
7
8#include "dexcr.h"
9#include "utils.h"
10
11static unsigned int dexcr;
12static unsigned int hdexcr;
13static unsigned int effective;
14
1// SPDX-License-Identifier: GPL-2.0+
2
3#include <stddef.h>
4#include <stdio.h>
5#include <string.h>
6#include <sys/prctl.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 unsigned long prctl;
20 const char *sysctl;
21};
22
23static const struct dexcr_aspect aspects[] = {
24 {
25 .name = "SBHE",
26 .desc = "Speculative branch hint enable",
27 .index = 0,
28 .prctl = PR_PPC_DEXCR_SBHE,
29 .sysctl = "speculative_branch_hint_enable",
30 },
31 {
32 .name = "IBRTPD",
33 .desc = "Indirect branch recurrent target prediction disable",
34 .index = 3,
35 .prctl = PR_PPC_DEXCR_IBRTPD,
36 .sysctl = "indirect_branch_recurrent_target_prediction_disable",
37 },
38 {
39 .name = "SRAPD",
40 .desc = "Subroutine return address prediction disable",
41 .index = 4,
42 .prctl = PR_PPC_DEXCR_SRAPD,
43 .sysctl = "subroutine_return_address_prediction_disable",
44 },
45 {
46 .name = "NPHIE",
47 .desc = "Non-privileged hash instruction enable",
48 .index = 5,
49 .prctl = PR_PPC_DEXCR_NPHIE,
50 .sysctl = "nonprivileged_hash_instruction_enable",
51 },
52 {
53 .name = "PHIE",
54 .desc = "Privileged hash instruction enable",
55 .index = 6,
56 .prctl = -1,
57 .sysctl = NULL,
58 },
59};
60
61static void print_list(const char *list[], size_t len)
62{
63 for (size_t i = 0; i < len; i++) {
64 printf("%s", list[i]);
65 if (i + 1 < len)
66 printf(", ");
67 }
68}

--- 43 unchanged lines hidden (view full) ---

112
113 printf("%12s %c (%d): ", aspect->name, effective & mask ? '*' : ' ', aspect->index);
114 print_list(attributes, j);
115 printf(" \t(%s)\n", aspect->desc);
116}
117
118static void print_aspect_config(const struct dexcr_aspect *aspect)
119{
15static void print_list(const char *list[], size_t len)
16{
17 for (size_t i = 0; i < len; i++) {
18 printf("%s", list[i]);
19 if (i + 1 < len)
20 printf(", ");
21 }
22}

--- 43 unchanged lines hidden (view full) ---

66
67 printf("%12s %c (%d): ", aspect->name, effective & mask ? '*' : ' ', aspect->index);
68 print_list(attributes, j);
69 printf(" \t(%s)\n", aspect->desc);
70}
71
72static void print_aspect_config(const struct dexcr_aspect *aspect)
73{
120 char sysctl_path[128] = "/proc/sys/kernel/dexcr/";
121 const char *reason = "unknown";
74 const char *reason = NULL;
122 const char *reason_hyp = NULL;
75 const char *reason_hyp = NULL;
123 const char *reason_sysctl = "no sysctl";
124 const char *reason_prctl = "no prctl";
125 bool actual = effective & DEXCR_PR_BIT(aspect->index);
76 const char *reason_prctl = "no prctl";
77 bool actual = effective & DEXCR_PR_BIT(aspect->index);
126 bool expected = false;
78 bool expected = actual; /* Assume it's fine if we don't expect a specific set/clear value */
127
79
128 long sysctl_ctrl = 0;
129 int prctl_ctrl = 0;
130 int err;
80 if (actual)
81 reason = "set by unknown";
82 else
83 reason = "cleared by unknown";
131
84
132 if (aspect->prctl >= 0) {
133 prctl_ctrl = pr_get_dexcr(aspect->prctl);
134 if (prctl_ctrl < 0)
135 reason_prctl = "(failed to read prctl)";
136 else {
137 if (prctl_ctrl & PR_PPC_DEXCR_CTRL_SET) {
85 if (aspect->prctl != -1) {
86 int ctrl = pr_get_dexcr(aspect->prctl);
87
88 if (ctrl < 0) {
89 reason_prctl = "failed to read prctl";
90 } else {
91 if (ctrl & PR_PPC_DEXCR_CTRL_SET) {
138 reason_prctl = "set by prctl";
139 expected = true;
92 reason_prctl = "set by prctl";
93 expected = true;
140 } else if (prctl_ctrl & PR_PPC_DEXCR_CTRL_CLEAR) {
94 } else if (ctrl & PR_PPC_DEXCR_CTRL_CLEAR) {
141 reason_prctl = "cleared by prctl";
142 expected = false;
95 reason_prctl = "cleared by prctl";
96 expected = false;
143 } else
97 } else {
144 reason_prctl = "unknown prctl";
98 reason_prctl = "unknown prctl";
99 }
145
146 reason = reason_prctl;
147 }
148 }
149
100
101 reason = reason_prctl;
102 }
103 }
104
150 if (aspect->sysctl) {
151 strcat(sysctl_path, aspect->sysctl);
152 err = read_long(sysctl_path, &sysctl_ctrl, 10);
153 if (err)
154 reason_sysctl = "(failed to read sysctl)";
155 else {
156 switch (sysctl_ctrl) {
157 case 0:
158 reason_sysctl = "cleared by sysctl";
159 reason = reason_sysctl;
160 expected = false;
161 break;
162 case 1:
163 reason_sysctl = "set by sysctl";
164 reason = reason_sysctl;
165 expected = true;
166 break;
167 case 2:
168 reason_sysctl = "not modified by sysctl";
169 break;
170 case 3:
171 reason_sysctl = "cleared by sysctl (permanent)";
172 reason = reason_sysctl;
173 expected = false;
174 break;
175 case 4:
176 reason_sysctl = "set by sysctl (permanent)";
177 reason = reason_sysctl;
178 expected = true;
179 break;
180 default:
181 reason_sysctl = "unknown sysctl";
182 break;
183 }
184 }
185 }
186
187
188 if (hdexcr & DEXCR_PR_BIT(aspect->index)) {
189 reason_hyp = "set by hypervisor";
190 reason = reason_hyp;
191 expected = true;
105 if (hdexcr & DEXCR_PR_BIT(aspect->index)) {
106 reason_hyp = "set by hypervisor";
107 reason = reason_hyp;
108 expected = true;
192 } else
109 } else {
193 reason_hyp = "not modified by hypervisor";
110 reason_hyp = "not modified by hypervisor";
111 }
194
112
195 printf("%12s (%d): %-28s (%s, %s, %s)\n",
113 printf("%12s (%d): %-28s (%s, %s)\n",
196 aspect->name,
197 aspect->index,
198 reason,
199 reason_hyp,
114 aspect->name,
115 aspect->index,
116 reason,
117 reason_hyp,
200 reason_sysctl,
201 reason_prctl);
202
118 reason_prctl);
119
120 /*
121 * The checks are not atomic, so this can technically trigger if the
122 * hypervisor makes a change while we are checking each source. It's
123 * far more likely to be a bug if we see this though.
124 */
203 if (actual != expected)
204 printf(" : ! actual %s does not match config\n", aspect->name);
205}
206
207int main(int argc, char *argv[])
208{
209 if (!dexcr_exists()) {
210 printf("DEXCR not detected on this hardware\n");

--- 40 unchanged lines hidden ---
125 if (actual != expected)
126 printf(" : ! actual %s does not match config\n", aspect->name);
127}
128
129int main(int argc, char *argv[])
130{
131 if (!dexcr_exists()) {
132 printf("DEXCR not detected on this hardware\n");

--- 40 unchanged lines hidden ---