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: Benjamin Gray <bg...@linux.ibm.com> --- .../testing/selftests/powerpc/dexcr/lsdexcr.c | 113 +++++++++++++++++- 1 file changed, 111 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/powerpc/dexcr/lsdexcr.c b/tools/testing/selftests/powerpc/dexcr/lsdexcr.c index 94abbfcc389e..a63db47b6610 100644 --- a/tools/testing/selftests/powerpc/dexcr/lsdexcr.c +++ b/tools/testing/selftests/powerpc/dexcr/lsdexcr.c @@ -1,9 +1,9 @@ // 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; } -- 2.44.0