1 // SPDX-License-Identifier: GPL-2.0+
11 static unsigned int dexcr
;
12 static unsigned int hdexcr
;
13 static unsigned int effective
;
15 static void print_list(const char *list
[], size_t len
)
17 for (size_t i
= 0; i
< len
; i
++) {
18 printf("%s", list
[i
]);
24 static void print_dexcr(char *name
, unsigned int bits
)
26 const char *enabled_aspects
[ARRAY_SIZE(aspects
) + 1] = {NULL
};
29 printf("%s: 0x%08x", name
, bits
);
36 for (size_t i
= 0; i
< ARRAY_SIZE(aspects
); i
++) {
37 unsigned int mask
= DEXCR_PR_BIT(aspects
[i
].index
);
40 enabled_aspects
[j
++] = aspects
[i
].name
;
46 enabled_aspects
[j
++] = "unknown";
49 print_list(enabled_aspects
, j
);
53 static void print_aspect(const struct dexcr_aspect
*aspect
)
55 const char *attributes
[8] = {NULL
};
59 mask
= DEXCR_PR_BIT(aspect
->index
);
61 attributes
[j
++] = "set";
63 attributes
[j
++] = "set (hypervisor)";
64 if (!(effective
& mask
))
65 attributes
[j
++] = "clear";
67 printf("%12s %c (%d): ", aspect
->name
, effective
& mask
? '*' : ' ', aspect
->index
);
68 print_list(attributes
, j
);
69 printf(" \t(%s)\n", aspect
->desc
);
72 static void print_aspect_config(const struct dexcr_aspect
*aspect
)
74 const char *reason
= NULL
;
75 const char *reason_hyp
= NULL
;
76 const char *reason_prctl
= "no prctl";
77 bool actual
= effective
& DEXCR_PR_BIT(aspect
->index
);
78 bool expected
= actual
; /* Assume it's fine if we don't expect a specific set/clear value */
81 reason
= "set by unknown";
83 reason
= "cleared by unknown";
85 if (aspect
->prctl
!= -1) {
86 int ctrl
= pr_get_dexcr(aspect
->prctl
);
89 reason_prctl
= "failed to read prctl";
91 if (ctrl
& PR_PPC_DEXCR_CTRL_SET
) {
92 reason_prctl
= "set by prctl";
94 } else if (ctrl
& PR_PPC_DEXCR_CTRL_CLEAR
) {
95 reason_prctl
= "cleared by prctl";
98 reason_prctl
= "unknown prctl";
101 reason
= reason_prctl
;
105 if (hdexcr
& DEXCR_PR_BIT(aspect
->index
)) {
106 reason_hyp
= "set by hypervisor";
110 reason_hyp
= "not modified by hypervisor";
113 printf("%12s (%d): %-28s (%s, %s)\n",
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.
125 if (actual
!= expected
)
126 printf(" : ! actual %s does not match config\n", aspect
->name
);
129 int main(int argc
, char *argv
[])
131 if (!dexcr_exists()) {
132 printf("DEXCR not detected on this hardware\n");
136 dexcr
= get_dexcr(DEXCR
);
137 hdexcr
= get_dexcr(HDEXCR
);
138 effective
= dexcr
| hdexcr
;
140 printf("current status:\n");
142 print_dexcr(" DEXCR", dexcr
);
143 print_dexcr(" HDEXCR", hdexcr
);
144 print_dexcr("Effective", effective
);
147 for (size_t i
= 0; i
< ARRAY_SIZE(aspects
); i
++)
148 print_aspect(&aspects
[i
]);
151 if (effective
& DEXCR_PR_NPHIE
) {
152 printf("DEXCR[NPHIE] enabled: hashst/hashchk ");
153 if (hashchk_triggers())
156 printf("failed to trigger\n");
158 printf("DEXCR[NPHIE] disabled: hashst/hashchk ");
159 if (hashchk_triggers())
160 printf("unexpectedly triggered\n");
166 printf("configuration:\n");
167 for (size_t i
= 0; i
< ARRAY_SIZE(aspects
); i
++)
168 print_aspect_config(&aspects
[i
]);