summaryrefslogtreecommitdiffstats
path: root/arch/openrisc
diff options
context:
space:
mode:
authorStafford Horne <shorne@gmail.com>2018-07-01 01:17:36 -0400
committerStafford Horne <shorne@gmail.com>2018-07-01 03:48:24 -0400
commitae15a41a641449f536578b0d9ec0e4ade130deb5 (patch)
treeaeee6525fa9d315c05c4273bfc5d415e211baf36 /arch/openrisc
parent560b423dd9af4272a1f3685c2d6b073fdc4af7c7 (diff)
openrisc: entry: Fix delay slot exception detection
Originally in patch e6d20c55a4 ("openrisc: entry: Fix delay slot detection") I fixed delay slot detection, but only for QEMU. We missed that hardware delay slot detection using delay slot exception flag (DSX) was still broken. This was because QEMU set the DSX flag in both pre-exception supervision register (ESR) and supervision register (SR) register, but on real hardware the DSX flag is only set on the SR register during exceptions. Fix this by carrying the DSX flag into the SR register during exception. We also update the DSX flag read locations to read the value from the SR register not the pt_regs SR register which represents ESR. The ESR should never have the DSX flag set. In the process I updated/removed a few comments to match the current state. Including removing a comment saying that the DSX detection logic was inefficient and needed to be rewritten. I have tested this on QEMU with a patch ensuring it matches the hardware specification. Link: https://lists.gnu.org/archive/html/qemu-devel/2018-07/msg00000.html Fixes: e6d20c55a4 ("openrisc: entry: Fix delay slot detection") Signed-off-by: Stafford Horne <shorne@gmail.com>
Diffstat (limited to 'arch/openrisc')
-rw-r--r--arch/openrisc/kernel/entry.S8
-rw-r--r--arch/openrisc/kernel/head.S9
-rw-r--r--arch/openrisc/kernel/traps.c2
3 files changed, 8 insertions, 11 deletions
diff --git a/arch/openrisc/kernel/entry.S b/arch/openrisc/kernel/entry.S
index 690d55272ba6..0c826ad6e994 100644
--- a/arch/openrisc/kernel/entry.S
+++ b/arch/openrisc/kernel/entry.S
@@ -277,12 +277,6 @@ EXCEPTION_ENTRY(_data_page_fault_handler)
277 l.addi r3,r1,0 // pt_regs 277 l.addi r3,r1,0 // pt_regs
278 /* r4 set be EXCEPTION_HANDLE */ // effective address of fault 278 /* r4 set be EXCEPTION_HANDLE */ // effective address of fault
279 279
280 /*
281 * __PHX__: TODO
282 *
283 * all this can be written much simpler. look at
284 * DTLB miss handler in the CONFIG_GUARD_PROTECTED_CORE part
285 */
286#ifdef CONFIG_OPENRISC_NO_SPR_SR_DSX 280#ifdef CONFIG_OPENRISC_NO_SPR_SR_DSX
287 l.lwz r6,PT_PC(r3) // address of an offending insn 281 l.lwz r6,PT_PC(r3) // address of an offending insn
288 l.lwz r6,0(r6) // instruction that caused pf 282 l.lwz r6,0(r6) // instruction that caused pf
@@ -314,7 +308,7 @@ EXCEPTION_ENTRY(_data_page_fault_handler)
314 308
315#else 309#else
316 310
317 l.lwz r6,PT_SR(r3) // SR 311 l.mfspr r6,r0,SPR_SR // SR
318 l.andi r6,r6,SPR_SR_DSX // check for delay slot exception 312 l.andi r6,r6,SPR_SR_DSX // check for delay slot exception
319 l.sfne r6,r0 // exception happened in delay slot 313 l.sfne r6,r0 // exception happened in delay slot
320 l.bnf 7f 314 l.bnf 7f
diff --git a/arch/openrisc/kernel/head.S b/arch/openrisc/kernel/head.S
index fb02b2a1d6f2..9fc6b60140f0 100644
--- a/arch/openrisc/kernel/head.S
+++ b/arch/openrisc/kernel/head.S
@@ -210,8 +210,7 @@
210 * r4 - EEAR exception EA 210 * r4 - EEAR exception EA
211 * r10 - current pointing to current_thread_info struct 211 * r10 - current pointing to current_thread_info struct
212 * r12 - syscall 0, since we didn't come from syscall 212 * r12 - syscall 0, since we didn't come from syscall
213 * r13 - temp it actually contains new SR, not needed anymore 213 * r30 - handler address of the handler we'll jump to
214 * r31 - handler address of the handler we'll jump to
215 * 214 *
216 * handler has to save remaining registers to the exception 215 * handler has to save remaining registers to the exception
217 * ksp frame *before* tainting them! 216 * ksp frame *before* tainting them!
@@ -244,6 +243,7 @@
244 /* r1 is KSP, r30 is __pa(KSP) */ ;\ 243 /* r1 is KSP, r30 is __pa(KSP) */ ;\
245 tophys (r30,r1) ;\ 244 tophys (r30,r1) ;\
246 l.sw PT_GPR12(r30),r12 ;\ 245 l.sw PT_GPR12(r30),r12 ;\
246 /* r4 use for tmp before EA */ ;\
247 l.mfspr r12,r0,SPR_EPCR_BASE ;\ 247 l.mfspr r12,r0,SPR_EPCR_BASE ;\
248 l.sw PT_PC(r30),r12 ;\ 248 l.sw PT_PC(r30),r12 ;\
249 l.mfspr r12,r0,SPR_ESR_BASE ;\ 249 l.mfspr r12,r0,SPR_ESR_BASE ;\
@@ -263,7 +263,10 @@
263 /* r12 == 1 if we come from syscall */ ;\ 263 /* r12 == 1 if we come from syscall */ ;\
264 CLEAR_GPR(r12) ;\ 264 CLEAR_GPR(r12) ;\
265 /* ----- turn on MMU ----- */ ;\ 265 /* ----- turn on MMU ----- */ ;\
266 l.ori r30,r0,(EXCEPTION_SR) ;\ 266 /* Carry DSX into exception SR */ ;\
267 l.mfspr r30,r0,SPR_SR ;\
268 l.andi r30,r30,SPR_SR_DSX ;\
269 l.ori r30,r30,(EXCEPTION_SR) ;\
267 l.mtspr r0,r30,SPR_ESR_BASE ;\ 270 l.mtspr r0,r30,SPR_ESR_BASE ;\
268 /* r30: EA address of handler */ ;\ 271 /* r30: EA address of handler */ ;\
269 LOAD_SYMBOL_2_GPR(r30,handler) ;\ 272 LOAD_SYMBOL_2_GPR(r30,handler) ;\
diff --git a/arch/openrisc/kernel/traps.c b/arch/openrisc/kernel/traps.c
index fac246e6f37a..d8981cbb852a 100644
--- a/arch/openrisc/kernel/traps.c
+++ b/arch/openrisc/kernel/traps.c
@@ -300,7 +300,7 @@ static inline int in_delay_slot(struct pt_regs *regs)
300 return 0; 300 return 0;
301 } 301 }
302#else 302#else
303 return regs->sr & SPR_SR_DSX; 303 return mfspr(SPR_SR) & SPR_SR_DSX;
304#endif 304#endif
305} 305}
306 306