Loading...
1/* SPDX-License-Identifier: GPL-2.0 */
2
3#ifndef __ASM_ARC_ENTRY_ARCV2_H
4#define __ASM_ARC_ENTRY_ARCV2_H
5
6#include <asm/asm-offsets.h>
7#include <asm/dsp-impl.h>
8#include <asm/irqflags-arcv2.h>
9#include <asm/thread_info.h> /* For THREAD_SIZE */
10
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 * | gp |
22 * | fp |
23 * | sp |
24 * | r12 |
25 * | r30 |
26 * | r58 |
27 * | r59 |
28 * hw autosave ---------------------
29 * optional | r0 |
30 * | r1 |
31 * ~ ~
32 * | r9 |
33 * | r10 |
34 * | r11 |
35 * | blink |
36 * | lpe |
37 * | lps |
38 * | lpc |
39 * | ei base |
40 * | ldi base |
41 * | jli base |
42 * ---------------------
43 * hw autosave | pc / eret |
44 * mandatory | stat32 / erstatus |
45 * ---------------------
46 */
47
48/*------------------------------------------------------------------------*/
49.macro INTERRUPT_PROLOGUE
50
51 ; Before jumping to Interrupt Vector, hardware micro-ops did following:
52 ; 1. SP auto-switched to kernel mode stack
53 ; 2. STATUS32.Z flag set if in U mode at time of interrupt (U:1,K:0)
54 ; 3. Auto save: (mandatory) Push PC and STAT32 on stack
55 ; hardware does even if CONFIG_ARC_IRQ_NO_AUTOSAVE
56 ; 4a. Auto save: (optional) r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI
57 ;
58 ; Now
59 ; 4b. If Auto-save (optional) not enabled in hw, manually save them
60 ; 5. Manually save: r12,r30, sp,fp,gp, ACCL pair
61 ;
62 ; At the end, SP points to pt_regs
63
64#ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
65 ; carve pt_regs on stack (case #3), PC/STAT32 already on stack
66 sub sp, sp, SZ_PT_REGS - 8
67
68 __SAVE_REGFILE_HARD
69#else
70 ; carve pt_regs on stack (case #4), which grew partially already
71 sub sp, sp, PT_r0
72#endif
73
74 __SAVE_REGFILE_SOFT
75.endm
76
77/*------------------------------------------------------------------------*/
78.macro EXCEPTION_PROLOGUE_KEEP_AE
79
80 ; Before jumping to Exception Vector, hardware micro-ops did following:
81 ; 1. SP auto-switched to kernel mode stack
82 ; 2. STATUS32.Z flag set if in U mode at time of exception (U:1,K:0)
83 ;
84 ; Now manually save rest of reg file
85 ; At the end, SP points to pt_regs
86
87 sub sp, sp, SZ_PT_REGS ; carve space for pt_regs
88
89 ; _HARD saves r10 clobbered by _SOFT as scratch hence comes first
90
91 __SAVE_REGFILE_HARD
92 __SAVE_REGFILE_SOFT
93
94 st r0, [sp] ; orig_r0
95
96 lr r10, [eret]
97 lr r11, [erstatus]
98 ST2 r10, r11, PT_ret
99
100 lr r10, [ecr]
101 lr r11, [erbta]
102 ST2 r10, r11, PT_event
103
104 ; OUTPUT: r10 has ECR expected by EV_Trap
105.endm
106
107.macro EXCEPTION_PROLOGUE
108
109 EXCEPTION_PROLOGUE_KEEP_AE ; return ECR in r10
110
111 lr r0, [efa]
112 mov r1, sp
113
114 FAKE_RET_FROM_EXCPN ; clobbers r9
115.endm
116
117/*------------------------------------------------------------------------
118 * This macro saves the registers manually which would normally be autosaved
119 * by hardware on taken interrupts. It is used by
120 * - exception handlers (which don't have autosave)
121 * - interrupt autosave disabled due to CONFIG_ARC_IRQ_NO_AUTOSAVE
122 */
123.macro __SAVE_REGFILE_HARD
124
125 ST2 r0, r1, PT_r0
126 ST2 r2, r3, PT_r2
127 ST2 r4, r5, PT_r4
128 ST2 r6, r7, PT_r6
129 ST2 r8, r9, PT_r8
130 ST2 r10, r11, PT_r10
131
132 st blink, [sp, PT_blink]
133
134 lr r10, [lp_end]
135 lr r11, [lp_start]
136 ST2 r10, r11, PT_lpe
137
138 st lp_count, [sp, PT_lpc]
139
140 ; skip JLI, LDI, EI for now
141.endm
142
143/*------------------------------------------------------------------------
144 * This macros saves a bunch of other registers which can't be autosaved for
145 * various reasons:
146 * - r12: the last caller saved scratch reg since hardware saves in pairs so r0-r11
147 * - r30: free reg, used by gcc as scratch
148 * - ACCL/ACCH pair when they exist
149 */
150.macro __SAVE_REGFILE_SOFT
151
152 st fp, [sp, PT_fp] ; r27
153 st r30, [sp, PT_r30]
154 st r12, [sp, PT_r12]
155 st r26, [sp, PT_r26] ; gp
156
157 ; Saving pt_regs->sp correctly requires some extra work due to the way
158 ; Auto stack switch works
159 ; - U mode: retrieve it from AUX_USER_SP
160 ; - K mode: add the offset from current SP where H/w starts auto push
161 ;
162 ; 1. Utilize the fact that Z bit is set if Intr taken in U mode
163 ; 2. Upon entry SP is always saved (for any inspection, unwinding etc),
164 ; but on return, restored only if U mode
165
166 lr r10, [AUX_USER_SP] ; U mode SP
167
168 ; ISA requires ADD.nz to have same dest and src reg operands
169 mov.nz r10, sp
170 add2.nz r10, r10, SZ_PT_REGS/4 ; K mode SP
171
172 st r10, [sp, PT_sp] ; SP (pt_regs->sp)
173
174#ifdef CONFIG_ARC_HAS_ACCL_REGS
175 ST2 r58, r59, PT_r58
176#endif
177
178 /* clobbers r10, r11 registers pair */
179 DSP_SAVE_REGFILE_IRQ
180
181#ifdef CONFIG_ARC_CURR_IN_REG
182 GET_CURR_TASK_ON_CPU gp
183#endif
184
185.endm
186
187/*------------------------------------------------------------------------*/
188.macro __RESTORE_REGFILE_SOFT
189
190 ld fp, [sp, PT_fp]
191 ld r30, [sp, PT_r30]
192 ld r12, [sp, PT_r12]
193 ld r26, [sp, PT_r26]
194
195 ; Restore SP (into AUX_USER_SP) only if returning to U mode
196 ; - for K mode, it will be implicitly restored as stack is unwound
197 ; - Z flag set on K is inverse of what hardware does on interrupt entry
198 ; but that doesn't really matter
199 bz 1f
200
201 ld r10, [sp, PT_sp] ; SP (pt_regs->sp)
202 sr r10, [AUX_USER_SP]
2031:
204
205 /* clobbers r10, r11 registers pair */
206 DSP_RESTORE_REGFILE_IRQ
207
208#ifdef CONFIG_ARC_HAS_ACCL_REGS
209 LD2 r58, r59, PT_r58
210#endif
211.endm
212
213/*------------------------------------------------------------------------*/
214.macro __RESTORE_REGFILE_HARD
215
216 ld blink, [sp, PT_blink]
217
218 LD2 r10, r11, PT_lpe
219 sr r10, [lp_end]
220 sr r11, [lp_start]
221
222 ld r10, [sp, PT_lpc] ; lp_count can't be target of LD
223 mov lp_count, r10
224
225 LD2 r0, r1, PT_r0
226 LD2 r2, r3, PT_r2
227 LD2 r4, r5, PT_r4
228 LD2 r6, r7, PT_r6
229 LD2 r8, r9, PT_r8
230 LD2 r10, r11, PT_r10
231.endm
232
233
234/*------------------------------------------------------------------------*/
235.macro INTERRUPT_EPILOGUE
236
237 ; INPUT: r0 has STAT32 of calling context
238 ; INPUT: Z flag set if returning to K mode
239
240 ; _SOFT clobbers r10 restored by _HARD hence the order
241
242 __RESTORE_REGFILE_SOFT
243
244#ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
245 __RESTORE_REGFILE_HARD
246
247 ; SP points to PC/STAT32: hw restores them despite NO_AUTOSAVE
248 add sp, sp, SZ_PT_REGS - 8
249#else
250 add sp, sp, PT_r0
251#endif
252
253.endm
254
255/*------------------------------------------------------------------------*/
256.macro EXCEPTION_EPILOGUE
257
258 ; INPUT: r0 has STAT32 of calling context
259
260 btst r0, STATUS_U_BIT ; Z flag set if K, used in restoring SP
261
262 ld r10, [sp, PT_bta]
263 sr r10, [erbta]
264
265 LD2 r10, r11, PT_ret
266 sr r10, [eret]
267 sr r11, [erstatus]
268
269 __RESTORE_REGFILE_SOFT
270 __RESTORE_REGFILE_HARD
271
272 add sp, sp, SZ_PT_REGS
273.endm
274
275.macro FAKE_RET_FROM_EXCPN
276 lr r9, [status32]
277 bclr r9, r9, STATUS_AE_BIT
278 bset r9, r9, STATUS_IE_BIT
279 kflag r9
280.endm
281
282/* Get thread_info of "current" tsk */
283.macro GET_CURR_THR_INFO_FROM_SP reg
284 bmskn \reg, sp, THREAD_SHIFT - 1
285.endm
286
287/* Get CPU-ID of this core */
288.macro GET_CPU_ID reg
289 lr \reg, [identity]
290 xbfu \reg, \reg, 0xE8 /* 00111 01000 */
291 /* M = 8-1 N = 8 */
292.endm
293
294.macro SAVE_ABI_CALLEE_REGS
295 push r13
296 push r14
297 push r15
298 push r16
299 push r17
300 push r18
301 push r19
302 push r20
303 push r21
304 push r22
305 push r23
306 push r24
307 push r25
308.endm
309
310.macro RESTORE_ABI_CALLEE_REGS
311 pop r25
312 pop r24
313 pop r23
314 pop r22
315 pop r21
316 pop r20
317 pop r19
318 pop r18
319 pop r17
320 pop r16
321 pop r15
322 pop r14
323 pop r13
324.endm
325
326#endif
1/* SPDX-License-Identifier: GPL-2.0 */
2
3#ifndef __ASM_ARC_ENTRY_ARCV2_H
4#define __ASM_ARC_ENTRY_ARCV2_H
5
6#include <asm/asm-offsets.h>
7#include <asm/irqflags-arcv2.h>
8#include <asm/thread_info.h> /* For THREAD_SIZE */
9
10/*
11 * Interrupt/Exception stack layout (pt_regs) for ARCv2
12 * (End of struct aligned to end of page [unless nested])
13 *
14 * INTERRUPT EXCEPTION
15 *
16 * manual --------------------- manual
17 * | orig_r0 |
18 * | event/ECR |
19 * | bta |
20 * | user_r25 |
21 * | gp |
22 * | fp |
23 * | sp |
24 * | r12 |
25 * | r30 |
26 * | r58 |
27 * | r59 |
28 * hw autosave ---------------------
29 * optional | r0 |
30 * | r1 |
31 * ~ ~
32 * | r9 |
33 * | r10 |
34 * | r11 |
35 * | blink |
36 * | lpe |
37 * | lps |
38 * | lpc |
39 * | ei base |
40 * | ldi base |
41 * | jli base |
42 * ---------------------
43 * hw autosave | pc / eret |
44 * mandatory | stat32 / erstatus |
45 * ---------------------
46 */
47
48/*------------------------------------------------------------------------*/
49.macro INTERRUPT_PROLOGUE
50
51 ; (A) Before jumping to Interrupt Vector, hardware micro-ops did following:
52 ; 1. SP auto-switched to kernel mode stack
53 ; 2. STATUS32.Z flag set if in U mode at time of interrupt (U:1,K:0)
54 ; 3. Auto save: (mandatory) Push PC and STAT32 on stack
55 ; hardware does even if CONFIG_ARC_IRQ_NO_AUTOSAVE
56 ; 4. Auto save: (optional) r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI
57 ;
58 ; (B) Manually saved some regs: r12,r25,r30, sp,fp,gp, ACCL pair
59
60#ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
61 ; carve pt_regs on stack (case #3), PC/STAT32 already on stack
62 sub sp, sp, SZ_PT_REGS - 8
63
64 __SAVE_REGFILE_HARD
65#else
66 ; carve pt_regs on stack (case #4), which grew partially already
67 sub sp, sp, PT_r0
68#endif
69
70 __SAVE_REGFILE_SOFT
71.endm
72
73/*------------------------------------------------------------------------*/
74.macro EXCEPTION_PROLOGUE
75
76 ; (A) Before jumping to Exception Vector, hardware micro-ops did following:
77 ; 1. SP auto-switched to kernel mode stack
78 ; 2. STATUS32.Z flag set if in U mode at time of exception (U:1,K:0)
79 ;
80 ; (B) Manually save the complete reg file below
81
82 sub sp, sp, SZ_PT_REGS ; carve pt_regs
83
84 ; _HARD saves r10 clobbered by _SOFT as scratch hence comes first
85
86 __SAVE_REGFILE_HARD
87 __SAVE_REGFILE_SOFT
88
89 st r0, [sp] ; orig_r0
90
91 lr r10, [eret]
92 lr r11, [erstatus]
93 ST2 r10, r11, PT_ret
94
95 lr r10, [ecr]
96 lr r11, [erbta]
97 ST2 r10, r11, PT_event
98
99 ; OUTPUT: r10 has ECR expected by EV_Trap
100.endm
101
102/*------------------------------------------------------------------------
103 * This macro saves the registers manually which would normally be autosaved
104 * by hardware on taken interrupts. It is used by
105 * - exception handlers (which don't have autosave)
106 * - interrupt autosave disabled due to CONFIG_ARC_IRQ_NO_AUTOSAVE
107 */
108.macro __SAVE_REGFILE_HARD
109
110 ST2 r0, r1, PT_r0
111 ST2 r2, r3, PT_r2
112 ST2 r4, r5, PT_r4
113 ST2 r6, r7, PT_r6
114 ST2 r8, r9, PT_r8
115 ST2 r10, r11, PT_r10
116
117 st blink, [sp, PT_blink]
118
119 lr r10, [lp_end]
120 lr r11, [lp_start]
121 ST2 r10, r11, PT_lpe
122
123 st lp_count, [sp, PT_lpc]
124
125 ; skip JLI, LDI, EI for now
126.endm
127
128/*------------------------------------------------------------------------
129 * This macros saves a bunch of other registers which can't be autosaved for
130 * various reasons:
131 * - r12: the last caller saved scratch reg since hardware saves in pairs so r0-r11
132 * - r30: free reg, used by gcc as scratch
133 * - ACCL/ACCH pair when they exist
134 */
135.macro __SAVE_REGFILE_SOFT
136
137 ST2 gp, fp, PT_r26 ; gp (r26), fp (r27)
138
139 st r12, [sp, PT_sp + 4]
140 st r30, [sp, PT_sp + 8]
141
142 ; Saving pt_regs->sp correctly requires some extra work due to the way
143 ; Auto stack switch works
144 ; - U mode: retrieve it from AUX_USER_SP
145 ; - K mode: add the offset from current SP where H/w starts auto push
146 ;
147 ; 1. Utilize the fact that Z bit is set if Intr taken in U mode
148 ; 2. Upon entry SP is always saved (for any inspection, unwinding etc),
149 ; but on return, restored only if U mode
150
151 lr r10, [AUX_USER_SP] ; U mode SP
152
153 ; ISA requires ADD.nz to have same dest and src reg operands
154 mov.nz r10, sp
155 add.nz r10, r10, SZ_PT_REGS ; K mode SP
156
157 st r10, [sp, PT_sp] ; SP (pt_regs->sp)
158
159#ifdef CONFIG_ARC_CURR_IN_REG
160 st r25, [sp, PT_user_r25]
161 GET_CURR_TASK_ON_CPU r25
162#endif
163
164#ifdef CONFIG_ARC_HAS_ACCL_REGS
165 ST2 r58, r59, PT_sp + 12
166#endif
167
168.endm
169
170/*------------------------------------------------------------------------*/
171.macro __RESTORE_REGFILE_SOFT
172
173 LD2 gp, fp, PT_r26 ; gp (r26), fp (r27)
174
175 ld r12, [sp, PT_sp + 4]
176 ld r30, [sp, PT_sp + 8]
177
178 ; Restore SP (into AUX_USER_SP) only if returning to U mode
179 ; - for K mode, it will be implicitly restored as stack is unwound
180 ; - Z flag set on K is inverse of what hardware does on interrupt entry
181 ; but that doesn't really matter
182 bz 1f
183
184 ld r10, [sp, PT_sp] ; SP (pt_regs->sp)
185 sr r10, [AUX_USER_SP]
1861:
187
188#ifdef CONFIG_ARC_CURR_IN_REG
189 ld r25, [sp, PT_user_r25]
190#endif
191
192#ifdef CONFIG_ARC_HAS_ACCL_REGS
193 LD2 r58, r59, PT_sp + 12
194#endif
195.endm
196
197/*------------------------------------------------------------------------*/
198.macro __RESTORE_REGFILE_HARD
199
200 ld blink, [sp, PT_blink]
201
202 LD2 r10, r11, PT_lpe
203 sr r10, [lp_end]
204 sr r11, [lp_start]
205
206 ld r10, [sp, PT_lpc] ; lp_count can't be target of LD
207 mov lp_count, r10
208
209 LD2 r0, r1, PT_r0
210 LD2 r2, r3, PT_r2
211 LD2 r4, r5, PT_r4
212 LD2 r6, r7, PT_r6
213 LD2 r8, r9, PT_r8
214 LD2 r10, r11, PT_r10
215.endm
216
217
218/*------------------------------------------------------------------------*/
219.macro INTERRUPT_EPILOGUE
220
221 ; INPUT: r0 has STAT32 of calling context
222 ; INPUT: Z flag set if returning to K mode
223
224 ; _SOFT clobbers r10 restored by _HARD hence the order
225
226 __RESTORE_REGFILE_SOFT
227
228#ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
229 __RESTORE_REGFILE_HARD
230 add sp, sp, SZ_PT_REGS - 8
231#else
232 add sp, sp, PT_r0
233#endif
234
235.endm
236
237/*------------------------------------------------------------------------*/
238.macro EXCEPTION_EPILOGUE
239
240 ; INPUT: r0 has STAT32 of calling context
241
242 btst r0, STATUS_U_BIT ; Z flag set if K, used in restoring SP
243
244 ld r10, [sp, PT_event + 4]
245 sr r10, [erbta]
246
247 LD2 r10, r11, PT_ret
248 sr r10, [eret]
249 sr r11, [erstatus]
250
251 __RESTORE_REGFILE_SOFT
252 __RESTORE_REGFILE_HARD
253
254 add sp, sp, SZ_PT_REGS
255.endm
256
257.macro FAKE_RET_FROM_EXCPN
258 lr r9, [status32]
259 bic r9, r9, STATUS_AE_MASK
260 or r9, r9, STATUS_IE_MASK
261 kflag r9
262.endm
263
264/* Get thread_info of "current" tsk */
265.macro GET_CURR_THR_INFO_FROM_SP reg
266 bmskn \reg, sp, THREAD_SHIFT - 1
267.endm
268
269/* Get CPU-ID of this core */
270.macro GET_CPU_ID reg
271 lr \reg, [identity]
272 xbfu \reg, \reg, 0xE8 /* 00111 01000 */
273 /* M = 8-1 N = 8 */
274.endm
275
276#endif