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

Reply via email to