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