hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/arch/arc/include/asm/entry-arcv2.h
....@@ -4,240 +4,267 @@
44 #define __ASM_ARC_ENTRY_ARCV2_H
55
66 #include <asm/asm-offsets.h>
7
+#include <asm/dsp-impl.h>
78 #include <asm/irqflags-arcv2.h>
89 #include <asm/thread_info.h> /* For THREAD_SIZE */
910
10
-/*------------------------------------------------------------------------*/
11
-.macro INTERRUPT_PROLOGUE called_from
11
+/*
12
+ * Interrupt/Exception stack layout (pt_regs) for ARCv2
13
+ * (End of struct aligned to end of page [unless nested])
14
+ *
15
+ * INTERRUPT EXCEPTION
16
+ *
17
+ * manual --------------------- manual
18
+ * | orig_r0 |
19
+ * | event/ECR |
20
+ * | bta |
21
+ * | user_r25 |
22
+ * | gp |
23
+ * | fp |
24
+ * | sp |
25
+ * | r12 |
26
+ * | r30 |
27
+ * | r58 |
28
+ * | r59 |
29
+ * hw autosave ---------------------
30
+ * optional | r0 |
31
+ * | r1 |
32
+ * ~ ~
33
+ * | r9 |
34
+ * | r10 |
35
+ * | r11 |
36
+ * | blink |
37
+ * | lpe |
38
+ * | lps |
39
+ * | lpc |
40
+ * | ei base |
41
+ * | ldi base |
42
+ * | jli base |
43
+ * ---------------------
44
+ * hw autosave | pc / eret |
45
+ * mandatory | stat32 / erstatus |
46
+ * ---------------------
47
+ */
1248
13
- ; Before jumping to Interrupt Vector, hardware micro-ops did following:
49
+/*------------------------------------------------------------------------*/
50
+.macro INTERRUPT_PROLOGUE
51
+
52
+ ; (A) Before jumping to Interrupt Vector, hardware micro-ops did following:
1453 ; 1. SP auto-switched to kernel mode stack
15
- ; 2. STATUS32.Z flag set to U mode at time of interrupt (U:1, K:0)
16
- ; 3. Auto saved: r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI, PC, STAT32
54
+ ; 2. STATUS32.Z flag set if in U mode at time of interrupt (U:1,K:0)
55
+ ; 3. Auto save: (mandatory) Push PC and STAT32 on stack
56
+ ; hardware does even if CONFIG_ARC_IRQ_NO_AUTOSAVE
57
+ ; 4. Auto save: (optional) r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI
1758 ;
18
- ; Now manually save: r12, sp, fp, gp, r25
59
+ ; (B) Manually saved some regs: r12,r25,r30, sp,fp,gp, ACCL pair
1960
2061 #ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
21
-.ifnc \called_from, exception
22
- st.as r9, [sp, -10] ; save r9 in it's final stack slot
23
- sub sp, sp, 12 ; skip JLI, LDI, EI
62
+ ; carve pt_regs on stack (case #3), PC/STAT32 already on stack
63
+ sub sp, sp, SZ_PT_REGS - 8
2464
25
- PUSH lp_count
26
- PUSHAX lp_start
27
- PUSHAX lp_end
28
- PUSH blink
29
-
30
- PUSH r11
31
- PUSH r10
32
-
33
- sub sp, sp, 4 ; skip r9
34
-
35
- PUSH r8
36
- PUSH r7
37
- PUSH r6
38
- PUSH r5
39
- PUSH r4
40
- PUSH r3
41
- PUSH r2
42
- PUSH r1
43
- PUSH r0
44
-.endif
65
+ __SAVE_REGFILE_HARD
66
+#else
67
+ ; carve pt_regs on stack (case #4), which grew partially already
68
+ sub sp, sp, PT_r0
4569 #endif
4670
47
-#ifdef CONFIG_ARC_HAS_ACCL_REGS
48
- PUSH r59
49
- PUSH r58
50
-#endif
71
+ __SAVE_REGFILE_SOFT
72
+.endm
5173
52
- PUSH r30
53
- PUSH r12
74
+/*------------------------------------------------------------------------*/
75
+.macro EXCEPTION_PROLOGUE
76
+
77
+ ; (A) Before jumping to Exception Vector, hardware micro-ops did following:
78
+ ; 1. SP auto-switched to kernel mode stack
79
+ ; 2. STATUS32.Z flag set if in U mode at time of exception (U:1,K:0)
80
+ ;
81
+ ; (B) Manually save the complete reg file below
82
+
83
+ sub sp, sp, SZ_PT_REGS ; carve pt_regs
84
+
85
+ ; _HARD saves r10 clobbered by _SOFT as scratch hence comes first
86
+
87
+ __SAVE_REGFILE_HARD
88
+ __SAVE_REGFILE_SOFT
89
+
90
+ st r0, [sp] ; orig_r0
91
+
92
+ lr r10, [eret]
93
+ lr r11, [erstatus]
94
+ ST2 r10, r11, PT_ret
95
+
96
+ lr r10, [ecr]
97
+ lr r11, [erbta]
98
+ ST2 r10, r11, PT_event
99
+
100
+ ; OUTPUT: r10 has ECR expected by EV_Trap
101
+.endm
102
+
103
+/*------------------------------------------------------------------------
104
+ * This macro saves the registers manually which would normally be autosaved
105
+ * by hardware on taken interrupts. It is used by
106
+ * - exception handlers (which don't have autosave)
107
+ * - interrupt autosave disabled due to CONFIG_ARC_IRQ_NO_AUTOSAVE
108
+ */
109
+.macro __SAVE_REGFILE_HARD
110
+
111
+ ST2 r0, r1, PT_r0
112
+ ST2 r2, r3, PT_r2
113
+ ST2 r4, r5, PT_r4
114
+ ST2 r6, r7, PT_r6
115
+ ST2 r8, r9, PT_r8
116
+ ST2 r10, r11, PT_r10
117
+
118
+ st blink, [sp, PT_blink]
119
+
120
+ lr r10, [lp_end]
121
+ lr r11, [lp_start]
122
+ ST2 r10, r11, PT_lpe
123
+
124
+ st lp_count, [sp, PT_lpc]
125
+
126
+ ; skip JLI, LDI, EI for now
127
+.endm
128
+
129
+/*------------------------------------------------------------------------
130
+ * This macros saves a bunch of other registers which can't be autosaved for
131
+ * various reasons:
132
+ * - r12: the last caller saved scratch reg since hardware saves in pairs so r0-r11
133
+ * - r30: free reg, used by gcc as scratch
134
+ * - ACCL/ACCH pair when they exist
135
+ */
136
+.macro __SAVE_REGFILE_SOFT
137
+
138
+ ST2 gp, fp, PT_r26 ; gp (r26), fp (r27)
139
+
140
+ st r12, [sp, PT_sp + 4]
141
+ st r30, [sp, PT_sp + 8]
54142
55143 ; Saving pt_regs->sp correctly requires some extra work due to the way
56144 ; Auto stack switch works
57145 ; - U mode: retrieve it from AUX_USER_SP
58146 ; - K mode: add the offset from current SP where H/w starts auto push
59147 ;
60
- ; Utilize the fact that Z bit is set if Intr taken in U mode
61
- mov.nz r9, sp
62
- add.nz r9, r9, SZ_PT_REGS - PT_sp - 4
63
- bnz 1f
148
+ ; 1. Utilize the fact that Z bit is set if Intr taken in U mode
149
+ ; 2. Upon entry SP is always saved (for any inspection, unwinding etc),
150
+ ; but on return, restored only if U mode
64151
65
- lr r9, [AUX_USER_SP]
66
-1:
67
- PUSH r9 ; SP
152
+ lr r10, [AUX_USER_SP] ; U mode SP
68153
69
- PUSH fp
70
- PUSH gp
154
+ ; ISA requires ADD.nz to have same dest and src reg operands
155
+ mov.nz r10, sp
156
+ add.nz r10, r10, SZ_PT_REGS ; K mode SP
157
+
158
+ st r10, [sp, PT_sp] ; SP (pt_regs->sp)
71159
72160 #ifdef CONFIG_ARC_CURR_IN_REG
73
- PUSH r25 ; user_r25
161
+ st r25, [sp, PT_user_r25]
74162 GET_CURR_TASK_ON_CPU r25
75
-#else
76
- sub sp, sp, 4
77163 #endif
78
-
79
-.ifnc \called_from, exception
80
- sub sp, sp, 12 ; BTA/ECR/orig_r0 placeholder per pt_regs
81
-.endif
82
-
83
-.endm
84
-
85
-/*------------------------------------------------------------------------*/
86
-.macro INTERRUPT_EPILOGUE called_from
87
-
88
-.ifnc \called_from, exception
89
- add sp, sp, 12 ; skip BTA/ECR/orig_r0 placeholderss
90
-.endif
91
-
92
-#ifdef CONFIG_ARC_CURR_IN_REG
93
- POP r25
94
-#else
95
- add sp, sp, 4
96
-#endif
97
-
98
- POP gp
99
- POP fp
100
-
101
- ; Don't touch AUX_USER_SP if returning to K mode (Z bit set)
102
- ; (Z bit set on K mode is inverse of INTERRUPT_PROLOGUE)
103
- add.z sp, sp, 4
104
- bz 1f
105
-
106
- POPAX AUX_USER_SP
107
-1:
108
- POP r12
109
- POP r30
110164
111165 #ifdef CONFIG_ARC_HAS_ACCL_REGS
112
- POP r58
113
- POP r59
166
+ ST2 r58, r59, PT_r58
114167 #endif
115168
116
-#ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
117
-.ifnc \called_from, exception
118
- POP r0
119
- POP r1
120
- POP r2
121
- POP r3
122
- POP r4
123
- POP r5
124
- POP r6
125
- POP r7
126
- POP r8
127
- POP r9
128
- POP r10
129
- POP r11
130
-
131
- POP blink
132
- POPAX lp_end
133
- POPAX lp_start
134
-
135
- POP r9
136
- mov lp_count, r9
137
-
138
- add sp, sp, 12 ; skip JLI, LDI, EI
139
- ld.as r9, [sp, -10] ; reload r9 which got clobbered
140
-.endif
141
-#endif
142
-
169
+ /* clobbers r10, r11 registers pair */
170
+ DSP_SAVE_REGFILE_IRQ
143171 .endm
144172
145173 /*------------------------------------------------------------------------*/
146
-.macro EXCEPTION_PROLOGUE
174
+.macro __RESTORE_REGFILE_SOFT
147175
148
- ; Before jumping to Exception Vector, hardware micro-ops did following:
149
- ; 1. SP auto-switched to kernel mode stack
150
- ; 2. STATUS32.Z flag set to U mode at time of interrupt (U:1,K:0)
151
- ;
152
- ; Now manually save the complete reg file
176
+ LD2 gp, fp, PT_r26 ; gp (r26), fp (r27)
153177
154
- PUSH r9 ; freeup a register: slot of erstatus
178
+ ld r12, [sp, PT_r12]
179
+ ld r30, [sp, PT_r30]
155180
156
- PUSHAX eret
157
- sub sp, sp, 12 ; skip JLI, LDI, EI
158
- PUSH lp_count
159
- PUSHAX lp_start
160
- PUSHAX lp_end
161
- PUSH blink
181
+ ; Restore SP (into AUX_USER_SP) only if returning to U mode
182
+ ; - for K mode, it will be implicitly restored as stack is unwound
183
+ ; - Z flag set on K is inverse of what hardware does on interrupt entry
184
+ ; but that doesn't really matter
185
+ bz 1f
162186
163
- PUSH r11
164
- PUSH r10
187
+ ld r10, [sp, PT_sp] ; SP (pt_regs->sp)
188
+ sr r10, [AUX_USER_SP]
189
+1:
165190
166
- ld.as r9, [sp, 10] ; load stashed r9 (status32 stack slot)
167
- lr r10, [erstatus]
168
- st.as r10, [sp, 10] ; save status32 at it's right stack slot
191
+#ifdef CONFIG_ARC_CURR_IN_REG
192
+ ld r25, [sp, PT_user_r25]
193
+#endif
169194
170
- PUSH r9
171
- PUSH r8
172
- PUSH r7
173
- PUSH r6
174
- PUSH r5
175
- PUSH r4
176
- PUSH r3
177
- PUSH r2
178
- PUSH r1
179
- PUSH r0
195
+ /* clobbers r10, r11 registers pair */
196
+ DSP_RESTORE_REGFILE_IRQ
180197
181
- ; -- for interrupts, regs above are auto-saved by h/w in that order --
182
- ; Now do what ISR prologue does (manually save r12, sp, fp, gp, r25)
183
- ;
184
- ; Set Z flag if this was from U mode (expected by INTERRUPT_PROLOGUE)
185
- ; Although H/w exception micro-ops do set Z flag for U mode (just like
186
- ; for interrupts), it could get clobbered in case we soft land here from
187
- ; a TLB Miss exception handler (tlbex.S)
198
+#ifdef CONFIG_ARC_HAS_ACCL_REGS
199
+ LD2 r58, r59, PT_r58
200
+#endif
201
+.endm
188202
189
- and r10, r10, STATUS_U_MASK
190
- xor.f 0, r10, STATUS_U_MASK
203
+/*------------------------------------------------------------------------*/
204
+.macro __RESTORE_REGFILE_HARD
191205
192
- INTERRUPT_PROLOGUE exception
206
+ ld blink, [sp, PT_blink]
193207
194
- PUSHAX erbta
195
- PUSHAX ecr ; r9 contains ECR, expected by EV_Trap
208
+ LD2 r10, r11, PT_lpe
209
+ sr r10, [lp_end]
210
+ sr r11, [lp_start]
196211
197
- PUSH r0 ; orig_r0
212
+ ld r10, [sp, PT_lpc] ; lp_count can't be target of LD
213
+ mov lp_count, r10
214
+
215
+ LD2 r0, r1, PT_r0
216
+ LD2 r2, r3, PT_r2
217
+ LD2 r4, r5, PT_r4
218
+ LD2 r6, r7, PT_r6
219
+ LD2 r8, r9, PT_r8
220
+ LD2 r10, r11, PT_r10
221
+.endm
222
+
223
+
224
+/*------------------------------------------------------------------------*/
225
+.macro INTERRUPT_EPILOGUE
226
+
227
+ ; INPUT: r0 has STAT32 of calling context
228
+ ; INPUT: Z flag set if returning to K mode
229
+
230
+ ; _SOFT clobbers r10 restored by _HARD hence the order
231
+
232
+ __RESTORE_REGFILE_SOFT
233
+
234
+#ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
235
+ __RESTORE_REGFILE_HARD
236
+
237
+ ; SP points to PC/STAT32: hw restores them despite NO_AUTOSAVE
238
+ add sp, sp, SZ_PT_REGS - 8
239
+#else
240
+ add sp, sp, PT_r0
241
+#endif
242
+
198243 .endm
199244
200245 /*------------------------------------------------------------------------*/
201246 .macro EXCEPTION_EPILOGUE
202247
203
- ; Assumes r0 has PT_status32
204
- btst r0, STATUS_U_BIT ; Z flag set if K, used in INTERRUPT_EPILOGUE
248
+ ; INPUT: r0 has STAT32 of calling context
205249
206
- add sp, sp, 8 ; orig_r0/ECR don't need restoring
207
- POPAX erbta
250
+ btst r0, STATUS_U_BIT ; Z flag set if K, used in restoring SP
208251
209
- INTERRUPT_EPILOGUE exception
252
+ ld r10, [sp, PT_event + 4]
253
+ sr r10, [erbta]
210254
211
- POP r0
212
- POP r1
213
- POP r2
214
- POP r3
215
- POP r4
216
- POP r5
217
- POP r6
218
- POP r7
219
- POP r8
220
- POP r9
221
- POP r10
222
- POP r11
255
+ LD2 r10, r11, PT_ret
256
+ sr r10, [eret]
257
+ sr r11, [erstatus]
223258
224
- POP blink
225
- POPAX lp_end
226
- POPAX lp_start
259
+ __RESTORE_REGFILE_SOFT
260
+ __RESTORE_REGFILE_HARD
227261
228
- POP r9
229
- mov lp_count, r9
230
-
231
- add sp, sp, 12 ; skip JLI, LDI, EI
232
- POPAX eret
233
- POPAX erstatus
234
-
235
- ld.as r9, [sp, -12] ; reload r9 which got clobbered
262
+ add sp, sp, SZ_PT_REGS
236263 .endm
237264
238265 .macro FAKE_RET_FROM_EXCPN
239266 lr r9, [status32]
240
- bic r9, r9, (STATUS_U_MASK|STATUS_DE_MASK|STATUS_AE_MASK)
267
+ bic r9, r9, STATUS_AE_MASK
241268 or r9, r9, STATUS_IE_MASK
242269 kflag r9
243270 .endm