]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
powerpc: Emulate non privileged DSCR read and write
authorAnton Blanchard <anton@samba.org>
Wed, 1 May 2013 20:06:33 +0000 (20:06 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 11 May 2013 14:18:16 +0000 (07:18 -0700)
commit 73d2fb758e678c93bc76d40876c2359f0729b0ef upstream.

POWER8 allows read and write of the DSCR in userspace. We added
kernel emulation so applications could always use the instructions
regardless of the CPU type.

Unfortunately there are two SPRs for the DSCR and we only added
emulation for the privileged one. Add code to match the non
privileged one.

A simple test was created to verify the fix:

http://ozlabs.org/~anton/junkcode/user_dscr_test.c

Without the patch we get a SIGILL and it passes with the patch.

Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/powerpc/include/asm/ppc-opcode.h
arch/powerpc/kernel/traps.c

index 8752bc8e34a33a99af07de3e11f874045dc09d65..8cbc6e54e4c43536ae64dc33afbad034baf1a8a0 100644 (file)
 #define PPC_INST_MFSPR_DSCR_MASK       0xfc1fffff
 #define PPC_INST_MTSPR_DSCR            0x7c1103a6
 #define PPC_INST_MTSPR_DSCR_MASK       0xfc1fffff
+#define PPC_INST_MFSPR_DSCR_USER       0x7c0302a6
+#define PPC_INST_MFSPR_DSCR_USER_MASK  0xfc1fffff
+#define PPC_INST_MTSPR_DSCR_USER       0x7c0303a6
+#define PPC_INST_MTSPR_DSCR_USER_MASK  0xfc1fffff
 #define PPC_INST_SLBFEE                        0x7c0007a7
 
 #define PPC_INST_STRING                        0x7c00042a
index 37cc40ef5043f26ba0b0fb930ce0ae523d805ea0..83efa2f7d9266ced97726aa6b26c1739076a6ec1 100644 (file)
@@ -970,7 +970,10 @@ static int emulate_instruction(struct pt_regs *regs)
 
 #ifdef CONFIG_PPC64
        /* Emulate the mfspr rD, DSCR. */
-       if (((instword & PPC_INST_MFSPR_DSCR_MASK) == PPC_INST_MFSPR_DSCR) &&
+       if ((((instword & PPC_INST_MFSPR_DSCR_USER_MASK) ==
+               PPC_INST_MFSPR_DSCR_USER) ||
+            ((instword & PPC_INST_MFSPR_DSCR_MASK) ==
+               PPC_INST_MFSPR_DSCR)) &&
                        cpu_has_feature(CPU_FTR_DSCR)) {
                PPC_WARN_EMULATED(mfdscr, regs);
                rd = (instword >> 21) & 0x1f;
@@ -978,7 +981,10 @@ static int emulate_instruction(struct pt_regs *regs)
                return 0;
        }
        /* Emulate the mtspr DSCR, rD. */
-       if (((instword & PPC_INST_MTSPR_DSCR_MASK) == PPC_INST_MTSPR_DSCR) &&
+       if ((((instword & PPC_INST_MTSPR_DSCR_USER_MASK) ==
+               PPC_INST_MTSPR_DSCR_USER) ||
+            ((instword & PPC_INST_MTSPR_DSCR_MASK) ==
+               PPC_INST_MTSPR_DSCR)) &&
                        cpu_has_feature(CPU_FTR_DSCR)) {
                PPC_WARN_EMULATED(mtdscr, regs);
                rd = (instword >> 21) & 0x1f;