Recognise and pass the appropriate signal to the user program when a
hashchk instruction triggers. This is independent of allowing
configuration of DEXCR[NPHIE], as a hypervisor can enforce this aspect
regardless of the kernel.

The signal mirrors how ARM reports their similar check failure. For
example, their FPAC handler in arch/arm64/kernel/traps.c do_el0_fpac()
does this. When we fail to read the instruction that caused the fault
we send a segfault, similar to how emulate_math() does it.

Signed-off-by: Benjamin Gray <bg...@linux.ibm.com>

---

v3:     * Inline hashchk detection, remove dexcr.c and associated files
v1:     * Refactor the hashchk check to return 0 on success, an error
          code on failure. Determine what to do based on specific error
          code.
        * Motivate signal and code
---
 arch/powerpc/include/asm/ppc-opcode.h |  1 +
 arch/powerpc/kernel/traps.c           | 16 ++++++++++++++++
 2 files changed, 17 insertions(+)

diff --git a/arch/powerpc/include/asm/ppc-opcode.h 
b/arch/powerpc/include/asm/ppc-opcode.h
index ca5a0da7df4e..ef6972aa33b9 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -222,6 +222,7 @@
 #define OP_31_XOP_STFSX            663
 #define OP_31_XOP_STFSUX    695
 #define OP_31_XOP_STFDX     727
+#define OP_31_XOP_HASHCHK   754
 #define OP_31_XOP_STFDUX    759
 #define OP_31_XOP_LHBRX     790
 #define OP_31_XOP_LFIWAX    855
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 9bdd79aa51cf..e59ec6d32d37 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -1516,6 +1516,22 @@ static void do_program_check(struct pt_regs *regs)
                                return;
                        }
                }
+
+               if (cpu_has_feature(CPU_FTR_DEXCR_NPHIE) && user_mode(regs)) {
+                       ppc_inst_t insn;
+
+                       if (get_user_instr(insn, (void __user *)regs->nip)) {
+                               _exception(SIGSEGV, regs, SEGV_MAPERR, 
regs->nip);
+                               return;
+                       }
+
+                       if (ppc_inst_primary_opcode(insn) == 31 &&
+                           get_xop(ppc_inst_val(insn)) == OP_31_XOP_HASHCHK) {
+                               _exception(SIGILL, regs, ILL_ILLOPN, regs->nip);
+                               return;
+                       }
+               }
+
                _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
                return;
        }
-- 
2.40.1

Reply via email to