[PATCH 1/2] powerpc/book3e-64: hv exceptions aren't MASKABLE
Scott Wood
scottwood at freescale.com
Sat May 21 05:00:30 EST 2011
In general we will not have EE soft-disabled or be napping when
these exceptions happen, but still it is not correct.
The guest doorbell exceptions can only be triggered with MSR[GS]=1,
and thus for host kernel nesting purposes are base-level exceptions.
Note that ehpriv and hypercall are triggerable from normal userspace.
I tested that the process gets properly signalled in this case.
Signed-off-by: Scott Wood <scottwood at freescale.com>
---
arch/powerpc/include/asm/reg_booke.h | 2 +
arch/powerpc/kernel/exceptions-64e.S | 67 ++++++++++++++++++++++++++--------
2 files changed, 53 insertions(+), 16 deletions(-)
diff --git a/arch/powerpc/include/asm/reg_booke.h b/arch/powerpc/include/asm/reg_booke.h
index 0f0ad9f..e438286 100644
--- a/arch/powerpc/include/asm/reg_booke.h
+++ b/arch/powerpc/include/asm/reg_booke.h
@@ -67,6 +67,8 @@
#define SPRN_EPTCFG 0x15e /* Embedded Page Table Config */
#define SPRN_MAS7_MAS3 0x174 /* MMU Assist Register 7 || 3 */
#define SPRN_MAS0_MAS1 0x175 /* MMU Assist Register 0 || 1 */
+#define SPRN_GSRR0 0x17a /* Guest Save and Restore Register 0 */
+#define SPRN_GSRR1 0x17b /* Guest Save and Restore Register 1 */
#define SPRN_IVOR0 0x190 /* Interrupt Vector Offset Register 0 */
#define SPRN_IVOR1 0x191 /* Interrupt Vector Offset Register 1 */
#define SPRN_IVOR2 0x192 /* Interrupt Vector Offset Register 2 */
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S
index 69de473..b60f49e 100644
--- a/arch/powerpc/kernel/exceptions-64e.S
+++ b/arch/powerpc/kernel/exceptions-64e.S
@@ -34,17 +34,17 @@
#define SPECIAL_EXC_FRAME_SIZE INT_FRAME_SIZE
/* Exception prolog code for all exceptions */
-#define EXCEPTION_PROLOG(n, type, addition) \
- mtspr SPRN_SPRG_##type##_SCRATCH,r13; /* get spare registers */ \
+#define EXCEPTION_PROLOG(n, level, type, addition) \
+ mtspr SPRN_SPRG_##level##_SCRATCH,r13; /* get spare registers */ \
mfspr r13,SPRN_SPRG_PACA; /* get PACA */ \
- std r10,PACA_EX##type+EX_R10(r13); \
- std r11,PACA_EX##type+EX_R11(r13); \
+ std r10,PACA_EX##level+EX_R10(r13); \
+ std r11,PACA_EX##level+EX_R11(r13); \
mfcr r10; /* save CR */ \
addition; /* additional code for that exc. */ \
- std r1,PACA_EX##type+EX_R1(r13); /* save old r1 in the PACA */ \
- stw r10,PACA_EX##type+EX_CR(r13); /* save old CR in the PACA */ \
+ std r1,PACA_EX##level+EX_R1(r13); /* save old r1 in the PACA */ \
+ stw r10,PACA_EX##level+EX_CR(r13); /* save old CR in the PACA */\
mfspr r11,SPRN_##type##_SRR1;/* what are we coming from */ \
- type##_SET_KSTACK; /* get special stack if necessary */\
+ level##_SET_KSTACK; /* get special stack if necessary */\
andi. r10,r11,MSR_PR; /* save stack pointer */ \
beq 1f; /* branch around if supervisor */ \
ld r1,PACAKSAVE(r13); /* get kernel stack coming from usr */\
@@ -76,17 +76,20 @@
#define SPRN_MC_SRR0 SPRN_MCSRR0
#define SPRN_MC_SRR1 SPRN_MCSRR1
+#define SPRN_GUEST_SRR0 SPRN_GSRR0
+#define SPRN_GUEST_SRR1 SPRN_GSRR1
+
#define NORMAL_EXCEPTION_PROLOG(n, addition) \
- EXCEPTION_PROLOG(n, GEN, addition##_GEN)
+ EXCEPTION_PROLOG(n, GEN, GEN, addition##_GEN)
#define CRIT_EXCEPTION_PROLOG(n, addition) \
- EXCEPTION_PROLOG(n, CRIT, addition##_CRIT)
+ EXCEPTION_PROLOG(n, CRIT, CRIT, addition##_CRIT)
#define DBG_EXCEPTION_PROLOG(n, addition) \
- EXCEPTION_PROLOG(n, DBG, addition##_DBG)
+ EXCEPTION_PROLOG(n, DBG, DBG, addition##_DBG)
#define MC_EXCEPTION_PROLOG(n, addition) \
- EXCEPTION_PROLOG(n, MC, addition##_MC)
+ EXCEPTION_PROLOG(n, MC, MC, addition##_MC)
/* Variants of the "addition" argument for the prolog
@@ -228,7 +231,7 @@ exc_##n##_bad_stack: \
std r7,TI_LOCAL_FLAGS(r11); \
1:
-
+/* Use for interrupts that should be masked by soft-EE */
#define MASKABLE_EXCEPTION(trapnum, label, hdlr, ack) \
START_EXCEPTION(label); \
NORMAL_EXCEPTION_PROLOG(trapnum, PROLOG_ADDITION_MASKABLE) \
@@ -476,11 +479,43 @@ kernel_dbg_exc:
// b ret_from_crit_except
b .
- MASKABLE_EXCEPTION(0x2c0, guest_doorbell, .unknown_exception, ACK_NONE)
- MASKABLE_EXCEPTION(0x2e0, guest_doorbell_crit, .unknown_exception, ACK_NONE)
- MASKABLE_EXCEPTION(0x310, hypercall, .unknown_exception, ACK_NONE)
- MASKABLE_EXCEPTION(0x320, ehpriv, .unknown_exception, ACK_NONE)
+ START_EXCEPTION(guest_doorbell);
+ EXCEPTION_PROLOG(0x2c0, GEN, GUEST, PROLOG_ADDITION_NONE_GEN)
+ EXCEPTION_COMMON(0x2c0, PACA_EXGEN, INTS_DISABLE_ALL)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ bl .save_nvgprs
+ bl .unknown_exception
+ b .ret_from_except
+
+ /*
+ * Not really critical as far as host kernel exception nesting is
+ * concerned, but uses crit registers.
+ */
+ START_EXCEPTION(guest_doorbell_crit);
+ EXCEPTION_PROLOG(0x2e0, GEN, CRIT, PROLOG_ADDITION_NONE_GEN)
+ EXCEPTION_COMMON(0x2e0, PACA_EXGEN, INTS_DISABLE_ALL)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ bl .save_nvgprs
+ bl .unknown_exception
+ b .ret_from_except
+
+ START_EXCEPTION(hypercall);
+ NORMAL_EXCEPTION_PROLOG(0x310, PROLOG_ADDITION_NONE)
+ EXCEPTION_COMMON(0x310, PACA_EXGEN, INTS_KEEP)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ bl .save_nvgprs
+ INTS_RESTORE_HARD
+ bl .unknown_exception
+ b .ret_from_except
+ START_EXCEPTION(ehpriv);
+ NORMAL_EXCEPTION_PROLOG(0x320, PROLOG_ADDITION_NONE)
+ EXCEPTION_COMMON(0x320, PACA_EXGEN, INTS_KEEP)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ bl .save_nvgprs
+ INTS_RESTORE_HARD
+ bl .unknown_exception
+ b .ret_from_except
/*
* An interrupt came in while soft-disabled; clear EE in SRR1,
--
1.7.4.1
More information about the Linuxppc-dev
mailing list