Patchwork powerpc: Fix emulation of illegal instructions on PowerNV platform

login
register
mail settings
Submitter Paul Mackerras
Date June 14, 2013, 10:07 a.m.
Message ID <20130614100741.GA612@iris.ozlabs.ibm.com>
Download mbox | patch
Permalink /patch/251320/
State Accepted
Commit bf593907f7236e95698a76b7c7a2bbf8b1165327
Headers show

Comments

Paul Mackerras - June 14, 2013, 10:07 a.m.
Normally, the kernel emulates a few instructions that are unimplemented
on some processors (e.g. the old dcba instruction), or privileged (e.g.
mfpvr).  The emulation of unimplemented instructions is currently not
working on the PowerNV platform.  The reason is that on these machines,
unimplemented and illegal instructions cause a hypervisor emulation
assist interrupt, rather than a program interrupt as on older CPUs.
Our vector for the emulation assist interrupt just calls
program_check_exception() directly, without setting the bit in SRR1
that indicates an illegal instruction interrupt.  This fixes it by
making the emulation assist interrupt set that bit before calling
program_check_interrupt().  With this, old programs that use no-longer
implemented instructions such as dcba now work again.

Signed-off-by: Paul Mackerras <paulus@samba.org>
---
 arch/powerpc/kernel/exceptions-64s.S |    2 +-
 arch/powerpc/kernel/traps.c          |   10 ++++++++++
 2 files changed, 11 insertions(+), 1 deletion(-)
Anshuman Khandual - June 17, 2013, 9:32 a.m.
On 06/14/2013 03:37 PM, Paul Mackerras wrote:
> Normally, the kernel emulates a few instructions that are unimplemented
> on some processors (e.g. the old dcba instruction), or privileged (e.g.
> mfpvr).  The emulation of unimplemented instructions is currently not
> working on the PowerNV platform.  The reason is that on these machines,
> unimplemented and illegal instructions cause a hypervisor emulation
> assist interrupt, rather than a program interrupt as on older CPUs.
> Our vector for the emulation assist interrupt just calls
> program_check_exception() directly, without setting the bit in SRR1
> that indicates an illegal instruction interrupt.  

Hey Paul,

The only difference between (1) Program interrupt and (2) Hypervisor
emulation assist interrupt is that in the earlier, HW sets "illegal
instruction" as the reason code in the SRR1 registers implicitly.
We fix it in the later interrupt vector by doing the same explicitly
in SW ? The cause of the problem before was not having the appropriate
reason code ("illegal instruction") in the SRR1 register for program_
check_exception() function to take it forward ?

Regards
Anshuman

Patch

diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index e783453..40e4a17 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -683,7 +683,7 @@  machine_check_common:
 	STD_EXCEPTION_COMMON(0xb00, trap_0b, .unknown_exception)
 	STD_EXCEPTION_COMMON(0xd00, single_step, .single_step_exception)
 	STD_EXCEPTION_COMMON(0xe00, trap_0e, .unknown_exception)
-	STD_EXCEPTION_COMMON(0xe40, emulation_assist, .program_check_exception)
+	STD_EXCEPTION_COMMON(0xe40, emulation_assist, .emulation_assist_interrupt)
 	STD_EXCEPTION_COMMON(0xe60, hmi_exception, .unknown_exception)
 #ifdef CONFIG_PPC_DOORBELL
 	STD_EXCEPTION_COMMON_ASYNC(0xe80, h_doorbell, .doorbell_exception)
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index f18c79c..c0e5caf 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -1165,6 +1165,16 @@  bail:
 	exception_exit(prev_state);
 }
 
+/*
+ * This occurs when running in hypervisor mode on POWER6 or later
+ * and an illegal instruction is encountered.
+ */
+void __kprobes emulation_assist_interrupt(struct pt_regs *regs)
+{
+	regs->msr |= REASON_ILLEGAL;
+	program_check_exception(regs);
+}
+
 void alignment_exception(struct pt_regs *regs)
 {
 	enum ctx_state prev_state = exception_enter();