brintos

brintos / linux-shallow public Read only

0
0
Text · 3.8 KiB · 7588929 Raw
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