]>
Commit | Line | Data |
---|---|---|
f5ab4f51 GKH |
1 | From foo@baz Wed Aug 22 09:33:46 CEST 2018 |
2 | From: Stafford Horne <shorne@gmail.com> | |
3 | Date: Sun, 1 Jul 2018 14:17:36 +0900 | |
4 | Subject: openrisc: entry: Fix delay slot exception detection | |
5 | ||
6 | From: Stafford Horne <shorne@gmail.com> | |
7 | ||
8 | [ Upstream commit ae15a41a641449f536578b0d9ec0e4ade130deb5 ] | |
9 | ||
10 | Originally in patch e6d20c55a4 ("openrisc: entry: Fix delay slot | |
11 | detection") I fixed delay slot detection, but only for QEMU. We missed | |
12 | that hardware delay slot detection using delay slot exception flag (DSX) | |
13 | was still broken. This was because QEMU set the DSX flag in both | |
14 | pre-exception supervision register (ESR) and supervision register (SR) | |
15 | register, but on real hardware the DSX flag is only set on the SR | |
16 | register during exceptions. | |
17 | ||
18 | Fix this by carrying the DSX flag into the SR register during exception. | |
19 | We also update the DSX flag read locations to read the value from the SR | |
20 | register not the pt_regs SR register which represents ESR. The ESR | |
21 | should never have the DSX flag set. | |
22 | ||
23 | In the process I updated/removed a few comments to match the current | |
24 | state. Including removing a comment saying that the DSX detection logic | |
25 | was inefficient and needed to be rewritten. | |
26 | ||
27 | I have tested this on QEMU with a patch ensuring it matches the hardware | |
28 | specification. | |
29 | ||
30 | Link: https://lists.gnu.org/archive/html/qemu-devel/2018-07/msg00000.html | |
31 | Fixes: e6d20c55a4 ("openrisc: entry: Fix delay slot detection") | |
32 | Signed-off-by: Stafford Horne <shorne@gmail.com> | |
33 | Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> | |
34 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
35 | --- | |
36 | arch/openrisc/kernel/entry.S | 8 +------- | |
37 | arch/openrisc/kernel/head.S | 9 ++++++--- | |
38 | arch/openrisc/kernel/traps.c | 2 +- | |
39 | 3 files changed, 8 insertions(+), 11 deletions(-) | |
40 | ||
41 | --- a/arch/openrisc/kernel/entry.S | |
42 | +++ b/arch/openrisc/kernel/entry.S | |
43 | @@ -221,12 +221,6 @@ EXCEPTION_ENTRY(_data_page_fault_handler | |
44 | l.addi r3,r1,0 // pt_regs | |
45 | /* r4 set be EXCEPTION_HANDLE */ // effective address of fault | |
46 | ||
47 | - /* | |
48 | - * __PHX__: TODO | |
49 | - * | |
50 | - * all this can be written much simpler. look at | |
51 | - * DTLB miss handler in the CONFIG_GUARD_PROTECTED_CORE part | |
52 | - */ | |
53 | #ifdef CONFIG_OPENRISC_NO_SPR_SR_DSX | |
54 | l.lwz r6,PT_PC(r3) // address of an offending insn | |
55 | l.lwz r6,0(r6) // instruction that caused pf | |
56 | @@ -258,7 +252,7 @@ EXCEPTION_ENTRY(_data_page_fault_handler | |
57 | ||
58 | #else | |
59 | ||
60 | - l.lwz r6,PT_SR(r3) // SR | |
61 | + l.mfspr r6,r0,SPR_SR // SR | |
62 | l.andi r6,r6,SPR_SR_DSX // check for delay slot exception | |
63 | l.sfne r6,r0 // exception happened in delay slot | |
64 | l.bnf 7f | |
65 | --- a/arch/openrisc/kernel/head.S | |
66 | +++ b/arch/openrisc/kernel/head.S | |
67 | @@ -141,8 +141,7 @@ | |
68 | * r4 - EEAR exception EA | |
69 | * r10 - current pointing to current_thread_info struct | |
70 | * r12 - syscall 0, since we didn't come from syscall | |
71 | - * r13 - temp it actually contains new SR, not needed anymore | |
72 | - * r31 - handler address of the handler we'll jump to | |
73 | + * r30 - handler address of the handler we'll jump to | |
74 | * | |
75 | * handler has to save remaining registers to the exception | |
76 | * ksp frame *before* tainting them! | |
77 | @@ -178,6 +177,7 @@ | |
78 | /* r1 is KSP, r30 is __pa(KSP) */ ;\ | |
79 | tophys (r30,r1) ;\ | |
80 | l.sw PT_GPR12(r30),r12 ;\ | |
81 | + /* r4 use for tmp before EA */ ;\ | |
82 | l.mfspr r12,r0,SPR_EPCR_BASE ;\ | |
83 | l.sw PT_PC(r30),r12 ;\ | |
84 | l.mfspr r12,r0,SPR_ESR_BASE ;\ | |
85 | @@ -197,7 +197,10 @@ | |
86 | /* r12 == 1 if we come from syscall */ ;\ | |
87 | CLEAR_GPR(r12) ;\ | |
88 | /* ----- turn on MMU ----- */ ;\ | |
89 | - l.ori r30,r0,(EXCEPTION_SR) ;\ | |
90 | + /* Carry DSX into exception SR */ ;\ | |
91 | + l.mfspr r30,r0,SPR_SR ;\ | |
92 | + l.andi r30,r30,SPR_SR_DSX ;\ | |
93 | + l.ori r30,r30,(EXCEPTION_SR) ;\ | |
94 | l.mtspr r0,r30,SPR_ESR_BASE ;\ | |
95 | /* r30: EA address of handler */ ;\ | |
96 | LOAD_SYMBOL_2_GPR(r30,handler) ;\ | |
97 | --- a/arch/openrisc/kernel/traps.c | |
98 | +++ b/arch/openrisc/kernel/traps.c | |
99 | @@ -358,7 +358,7 @@ static inline int in_delay_slot(struct p | |
100 | return 0; | |
101 | } | |
102 | #else | |
103 | - return regs->sr & SPR_SR_DSX; | |
104 | + return mfspr(SPR_SR) & SPR_SR_DSX; | |
105 | #endif | |
106 | } | |
107 |