| From 73d2fb758e678c93bc76d40876c2359f0729b0ef Mon Sep 17 00:00:00 2001 |
| From: Anton Blanchard <anton@samba.org> |
| Date: Wed, 1 May 2013 20:06:33 +0000 |
| Subject: powerpc: Emulate non privileged DSCR read and write |
| |
| From: Anton Blanchard <anton@samba.org> |
| |
| 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 | 4 ++++ |
| arch/powerpc/kernel/traps.c | 10 ++++++++-- |
| 2 files changed, 12 insertions(+), 2 deletions(-) |
| |
| --- a/arch/powerpc/include/asm/ppc-opcode.h |
| +++ b/arch/powerpc/include/asm/ppc-opcode.h |
| @@ -113,6 +113,10 @@ |
| #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 |
| --- a/arch/powerpc/kernel/traps.c |
| +++ b/arch/powerpc/kernel/traps.c |
| @@ -970,7 +970,10 @@ static int emulate_instruction(struct pt |
| |
| #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 |
| 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; |