Commit 9c4866b2 authored by Benjamin Gray's avatar Benjamin Gray Committed by Michael Ellerman
Browse files

selftests/powerpc/dexcr: Add DEXCR config details to lsdexcr



Now that the DEXCR can be configured with prctl, add a section in
lsdexcr that explains why each aspect is set the way it is.

Signed-off-by: default avatarBenjamin Gray <bgray@linux.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/20240417112325.728010-8-bgray@linux.ibm.com
parent 9930fba0
Loading
Loading
Loading
Loading
+111 −2
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0+

#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <sys/prctl.h>

#include "dexcr.h"
#include "utils.h"
@@ -16,6 +16,8 @@ struct dexcr_aspect {
	const char *name;
	const char *desc;
	unsigned int index;
	unsigned long prctl;
	const char *sysctl;
};

static const struct dexcr_aspect aspects[] = {
@@ -23,26 +25,36 @@ static const struct dexcr_aspect aspects[] = {
		.name = "SBHE",
		.desc = "Speculative branch hint enable",
		.index = 0,
		.prctl = PR_PPC_DEXCR_SBHE,
		.sysctl = "speculative_branch_hint_enable",
	},
	{
		.name = "IBRTPD",
		.desc = "Indirect branch recurrent target prediction disable",
		.index = 3,
		.prctl = PR_PPC_DEXCR_IBRTPD,
		.sysctl = "indirect_branch_recurrent_target_prediction_disable",
	},
	{
		.name = "SRAPD",
		.desc = "Subroutine return address prediction disable",
		.index = 4,
		.prctl = PR_PPC_DEXCR_SRAPD,
		.sysctl = "subroutine_return_address_prediction_disable",
	},
	{
		.name = "NPHIE",
		.desc = "Non-privileged hash instruction enable",
		.index = 5,
		.prctl = PR_PPC_DEXCR_NPHIE,
		.sysctl = "nonprivileged_hash_instruction_enable",
	},
	{
		.name = "PHIE",
		.desc = "Privileged hash instruction enable",
		.index = 6,
		.prctl = -1,
		.sysctl = NULL,
	},
};

@@ -60,7 +72,7 @@ static void print_dexcr(char *name, unsigned int bits)
	const char *enabled_aspects[ARRAY_SIZE(aspects) + 1] = {NULL};
	size_t j = 0;

	printf("%s: %08x", name, bits);
	printf("%s: 0x%08x", name, bits);

	if (bits == 0) {
		printf("\n");
@@ -103,6 +115,95 @@ static void print_aspect(const struct dexcr_aspect *aspect)
	printf("  \t(%s)\n", aspect->desc);
}

static void print_aspect_config(const struct dexcr_aspect *aspect)
{
	char sysctl_path[128] = "/proc/sys/kernel/dexcr/";
	const char *reason = "unknown";
	const char *reason_hyp = NULL;
	const char *reason_sysctl = "no sysctl";
	const char *reason_prctl = "no prctl";
	bool actual = effective & DEXCR_PR_BIT(aspect->index);
	bool expected = false;

	long sysctl_ctrl = 0;
	int prctl_ctrl = 0;
	int err;

	if (aspect->prctl >= 0) {
		prctl_ctrl = pr_get_dexcr(aspect->prctl);
		if (prctl_ctrl < 0)
			reason_prctl = "(failed to read prctl)";
		else {
			if (prctl_ctrl & PR_PPC_DEXCR_CTRL_SET) {
				reason_prctl = "set by prctl";
				expected = true;
			} else if (prctl_ctrl & PR_PPC_DEXCR_CTRL_CLEAR) {
				reason_prctl = "cleared by prctl";
				expected = false;
			} else
				reason_prctl = "unknown prctl";

			reason = reason_prctl;
		}
	}

	if (aspect->sysctl) {
		strcat(sysctl_path, aspect->sysctl);
		err = read_long(sysctl_path, &sysctl_ctrl, 10);
		if (err)
			reason_sysctl = "(failed to read sysctl)";
		else {
			switch (sysctl_ctrl) {
			case 0:
				reason_sysctl = "cleared by sysctl";
				reason = reason_sysctl;
				expected = false;
				break;
			case 1:
				reason_sysctl = "set by sysctl";
				reason = reason_sysctl;
				expected = true;
				break;
			case 2:
				reason_sysctl = "not modified by sysctl";
				break;
			case 3:
				reason_sysctl = "cleared by sysctl (permanent)";
				reason = reason_sysctl;
				expected = false;
				break;
			case 4:
				reason_sysctl = "set by sysctl (permanent)";
				reason = reason_sysctl;
				expected = true;
				break;
			default:
				reason_sysctl = "unknown sysctl";
				break;
			}
		}
	}


	if (hdexcr & DEXCR_PR_BIT(aspect->index)) {
		reason_hyp = "set by hypervisor";
		reason = reason_hyp;
		expected = true;
	} else
		reason_hyp = "not modified by hypervisor";

	printf("%12s (%d): %-28s (%s, %s, %s)\n",
	       aspect->name,
	       aspect->index,
	       reason,
	       reason_hyp,
	       reason_sysctl,
	       reason_prctl);

	if (actual != expected)
		printf("                : ! actual %s does not match config\n", aspect->name);
}

int main(int argc, char *argv[])
{
	if (!dexcr_exists()) {
@@ -114,6 +215,8 @@ int main(int argc, char *argv[])
	hdexcr = get_dexcr(HDEXCR);
	effective = dexcr | hdexcr;

	printf("current status:\n");

	print_dexcr("    DEXCR", dexcr);
	print_dexcr("   HDEXCR", hdexcr);
	print_dexcr("Effective", effective);
@@ -136,6 +239,12 @@ int main(int argc, char *argv[])
		else
			printf("ignored\n");
	}
	printf("\n");

	printf("configuration:\n");
	for (size_t i = 0; i < ARRAY_SIZE(aspects); i++)
		print_aspect_config(&aspects[i]);
	printf("\n");

	return 0;
}