Skip to content

Commit ae15a41

Browse files
committed
openrisc: entry: Fix delay slot exception detection
Originally in patch e6d20c5 ("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: e6d20c5 ("openrisc: entry: Fix delay slot detection") Signed-off-by: Stafford Horne <[email protected]>
1 parent 560b423 commit ae15a41

File tree

3 files changed

+8
-11
lines changed

3 files changed

+8
-11
lines changed

arch/openrisc/kernel/entry.S

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -277,12 +277,6 @@ EXCEPTION_ENTRY(_data_page_fault_handler)
277277
l.addi r3,r1,0 // pt_regs
278278
/* r4 set be EXCEPTION_HANDLE */ // effective address of fault
279279

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-
*/
286280
#ifdef CONFIG_OPENRISC_NO_SPR_SR_DSX
287281
l.lwz r6,PT_PC(r3) // address of an offending insn
288282
l.lwz r6,0(r6) // instruction that caused pf
@@ -314,7 +308,7 @@ EXCEPTION_ENTRY(_data_page_fault_handler)
314308

315309
#else
316310

317-
l.lwz r6,PT_SR(r3) // SR
311+
l.mfspr r6,r0,SPR_SR // SR
318312
l.andi r6,r6,SPR_SR_DSX // check for delay slot exception
319313
l.sfne r6,r0 // exception happened in delay slot
320314
l.bnf 7f

arch/openrisc/kernel/head.S

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,7 @@
210210
* r4 - EEAR exception EA
211211
* r10 - current pointing to current_thread_info struct
212212
* r12 - syscall 0, since we didn't come from syscall
213-
* r13 - temp it actually contains new SR, not needed anymore
214-
* r31 - handler address of the handler we'll jump to
213+
* r30 - handler address of the handler we'll jump to
215214
*
216215
* handler has to save remaining registers to the exception
217216
* ksp frame *before* tainting them!
@@ -244,6 +243,7 @@
244243
/* r1 is KSP, r30 is __pa(KSP) */ ;\
245244
tophys (r30,r1) ;\
246245
l.sw PT_GPR12(r30),r12 ;\
246+
/* r4 use for tmp before EA */ ;\
247247
l.mfspr r12,r0,SPR_EPCR_BASE ;\
248248
l.sw PT_PC(r30),r12 ;\
249249
l.mfspr r12,r0,SPR_ESR_BASE ;\
@@ -263,7 +263,10 @@
263263
/* r12 == 1 if we come from syscall */ ;\
264264
CLEAR_GPR(r12) ;\
265265
/* ----- 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) ;\
267270
l.mtspr r0,r30,SPR_ESR_BASE ;\
268271
/* r30: EA address of handler */ ;\
269272
LOAD_SYMBOL_2_GPR(r30,handler) ;\

arch/openrisc/kernel/traps.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ static inline int in_delay_slot(struct pt_regs *regs)
300300
return 0;
301301
}
302302
#else
303-
return regs->sr & SPR_SR_DSX;
303+
return mfspr(SPR_SR) & SPR_SR_DSX;
304304
#endif
305305
}
306306

0 commit comments

Comments
 (0)