173 lines · c
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 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}23 24static void print_dexcr(char *name, unsigned int bits)25{26 const char *enabled_aspects[ARRAY_SIZE(aspects) + 1] = {NULL};27 size_t j = 0;28 29 printf("%s: 0x%08x", name, bits);30 31 if (bits == 0) {32 printf("\n");33 return;34 }35 36 for (size_t i = 0; i < ARRAY_SIZE(aspects); i++) {37 unsigned int mask = DEXCR_PR_BIT(aspects[i].index);38 39 if (bits & mask) {40 enabled_aspects[j++] = aspects[i].name;41 bits &= ~mask;42 }43 }44 45 if (bits)46 enabled_aspects[j++] = "unknown";47 48 printf(" (");49 print_list(enabled_aspects, j);50 printf(")\n");51}52 53static void print_aspect(const struct dexcr_aspect *aspect)54{55 const char *attributes[8] = {NULL};56 size_t j = 0;57 unsigned long mask;58 59 mask = DEXCR_PR_BIT(aspect->index);60 if (dexcr & mask)61 attributes[j++] = "set";62 if (hdexcr & mask)63 attributes[j++] = "set (hypervisor)";64 if (!(effective & mask))65 attributes[j++] = "clear";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{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 */79 80 if (actual)81 reason = "set by unknown";82 else83 reason = "cleared by unknown";84 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) {92 reason_prctl = "set by prctl";93 expected = true;94 } else if (ctrl & PR_PPC_DEXCR_CTRL_CLEAR) {95 reason_prctl = "cleared by prctl";96 expected = false;97 } else {98 reason_prctl = "unknown prctl";99 }100 101 reason = reason_prctl;102 }103 }104 105 if (hdexcr & DEXCR_PR_BIT(aspect->index)) {106 reason_hyp = "set by hypervisor";107 reason = reason_hyp;108 expected = true;109 } else {110 reason_hyp = "not modified by hypervisor";111 }112 113 printf("%12s (%d): %-28s (%s, %s)\n",114 aspect->name,115 aspect->index,116 reason,117 reason_hyp,118 reason_prctl);119 120 /*121 * The checks are not atomic, so this can technically trigger if the122 * hypervisor makes a change while we are checking each source. It's123 * far more likely to be a bug if we see this though.124 */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");133 return 1;134 }135 136 dexcr = get_dexcr(DEXCR);137 hdexcr = get_dexcr(HDEXCR);138 effective = dexcr | hdexcr;139 140 printf("current status:\n");141 142 print_dexcr(" DEXCR", dexcr);143 print_dexcr(" HDEXCR", hdexcr);144 print_dexcr("Effective", effective);145 printf("\n");146 147 for (size_t i = 0; i < ARRAY_SIZE(aspects); i++)148 print_aspect(&aspects[i]);149 printf("\n");150 151 if (effective & DEXCR_PR_NPHIE) {152 printf("DEXCR[NPHIE] enabled: hashst/hashchk ");153 if (hashchk_triggers())154 printf("working\n");155 else156 printf("failed to trigger\n");157 } else {158 printf("DEXCR[NPHIE] disabled: hashst/hashchk ");159 if (hashchk_triggers())160 printf("unexpectedly triggered\n");161 else162 printf("ignored\n");163 }164 printf("\n");165 166 printf("configuration:\n");167 for (size_t i = 0; i < ARRAY_SIZE(aspects); i++)168 print_aspect_config(&aspects[i]);169 printf("\n");170 171 return 0;172}173