From: Alistair Popple <alist...@popple.id.au>

Prefix instructions have their own FSCR bit which needs to enabled via
a CPU feature. The kernel will save the FSCR for problem state but it
needs to be enabled initially.

Signed-off-by: Alistair Popple <alist...@popple.id.au>
---
 arch/powerpc/include/asm/reg.h    |  3 +++
 arch/powerpc/kernel/dt_cpu_ftrs.c | 23 +++++++++++++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 0b7900f194c8..521ecbe35507 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -397,6 +397,7 @@
 #define SPRN_RWMR      0x375   /* Region-Weighting Mode Register */
 
 /* HFSCR and FSCR bit numbers are the same */
+#define FSCR_PREFIX_LG 13      /* Enable Prefix Instructions */
 #define FSCR_SCV_LG    12      /* Enable System Call Vectored */
 #define FSCR_MSGP_LG   10      /* Enable MSGP */
 #define FSCR_TAR_LG    8       /* Enable Target Address Register */
@@ -408,11 +409,13 @@
 #define FSCR_VECVSX_LG 1       /* Enable VMX/VSX  */
 #define FSCR_FP_LG     0       /* Enable Floating Point */
 #define SPRN_FSCR      0x099   /* Facility Status & Control Register */
+#define   FSCR_PREFIX  __MASK(FSCR_PREFIX_LG)
 #define   FSCR_SCV     __MASK(FSCR_SCV_LG)
 #define   FSCR_TAR     __MASK(FSCR_TAR_LG)
 #define   FSCR_EBB     __MASK(FSCR_EBB_LG)
 #define   FSCR_DSCR    __MASK(FSCR_DSCR_LG)
 #define SPRN_HFSCR     0xbe    /* HV=1 Facility Status & Control Register */
+#define   HFSCR_PREFIX __MASK(FSCR_PREFIX_LG)
 #define   HFSCR_MSGP   __MASK(FSCR_MSGP_LG)
 #define   HFSCR_TAR    __MASK(FSCR_TAR_LG)
 #define   HFSCR_EBB    __MASK(FSCR_EBB_LG)
diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c 
b/arch/powerpc/kernel/dt_cpu_ftrs.c
index 180b3a5d1001..f5ca7dd8fbaf 100644
--- a/arch/powerpc/kernel/dt_cpu_ftrs.c
+++ b/arch/powerpc/kernel/dt_cpu_ftrs.c
@@ -553,6 +553,28 @@ static int __init feat_enable_large_ci(struct 
dt_cpu_feature *f)
        return 1;
 }
 
+static int __init feat_enable_prefix(struct dt_cpu_feature *f)
+{
+       u64 fscr, hfscr;
+
+       if (f->usable_privilege & USABLE_HV) {
+               hfscr = mfspr(SPRN_HFSCR);
+               hfscr |= HFSCR_PREFIX;
+               mtspr(SPRN_HFSCR, hfscr);
+       }
+
+       if (f->usable_privilege & USABLE_OS) {
+               fscr = mfspr(SPRN_FSCR);
+               fscr |= FSCR_PREFIX;
+               mtspr(SPRN_FSCR, fscr);
+
+               if (f->usable_privilege & USABLE_PR)
+                       current->thread.fscr |= FSCR_PREFIX;
+       }
+
+       return 1;
+}
+
 struct dt_cpu_feature_match {
        const char *name;
        int (*enable)(struct dt_cpu_feature *f);
@@ -626,6 +648,7 @@ static struct dt_cpu_feature_match __initdata
        {"vector-binary128", feat_enable, 0},
        {"vector-binary16", feat_enable, 0},
        {"wait-v3", feat_enable, 0},
+       {"prefix-instructions", feat_enable_prefix, 0},
 };
 
 static bool __initdata using_dt_cpu_ftrs;
-- 
2.20.1

Reply via email to