aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arc/include/asm/entry-arcv2.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arc/include/asm/entry-arcv2.h')
-rw-r--r--arch/arc/include/asm/entry-arcv2.h361
1 files changed, 190 insertions, 171 deletions
diff --git a/arch/arc/include/asm/entry-arcv2.h b/arch/arc/include/asm/entry-arcv2.h
index 225e7df2d8ed..f5ae394ebe06 100644
--- a/arch/arc/include/asm/entry-arcv2.h
+++ b/arch/arc/include/asm/entry-arcv2.h
@@ -7,232 +7,251 @@
7#include <asm/irqflags-arcv2.h> 7#include <asm/irqflags-arcv2.h>
8#include <asm/thread_info.h> /* For THREAD_SIZE */ 8#include <asm/thread_info.h> /* For THREAD_SIZE */
9 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
10/*------------------------------------------------------------------------*/ 48/*------------------------------------------------------------------------*/
11.macro INTERRUPT_PROLOGUE called_from 49.macro INTERRUPT_PROLOGUE
12 50
13 ; Before jumping to Interrupt Vector, hardware micro-ops did following: 51 ; (A) Before jumping to Interrupt Vector, hardware micro-ops did following:
14 ; 1. SP auto-switched to kernel mode stack 52 ; 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) 53 ; 2. STATUS32.Z flag set if in 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 ; 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
17 ; 57 ;
18 ; Now manually save: r12, sp, fp, gp, r25 58 ; (B) Manually saved some regs: r12,r25,r30, sp,fp,gp, ACCL pair
19 59
20#ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE 60#ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
21.ifnc \called_from, exception 61 ; carve pt_regs on stack (case #3), PC/STAT32 already on stack
22 st.as r9, [sp, -10] ; save r9 in it's final stack slot 62 sub sp, sp, SZ_PT_REGS - 8
23 sub sp, sp, 12 ; skip JLI, LDI, EI
24
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
45#endif
46 63
47#ifdef CONFIG_ARC_HAS_ACCL_REGS 64 __SAVE_REGFILE_HARD
48 PUSH r59 65#else
49 PUSH r58 66 ; carve pt_regs on stack (case #4), which grew partially already
67 sub sp, sp, PT_r0
50#endif 68#endif
51 69
52 PUSH r30 70 __SAVE_REGFILE_SOFT
53 PUSH r12 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]
54 141
55 ; Saving pt_regs->sp correctly requires some extra work due to the way 142 ; Saving pt_regs->sp correctly requires some extra work due to the way
56 ; Auto stack switch works 143 ; Auto stack switch works
57 ; - U mode: retrieve it from AUX_USER_SP 144 ; - U mode: retrieve it from AUX_USER_SP
58 ; - K mode: add the offset from current SP where H/w starts auto push 145 ; - K mode: add the offset from current SP where H/w starts auto push
59 ; 146 ;
60 ; Utilize the fact that Z bit is set if Intr taken in U mode 147 ; 1. Utilize the fact that Z bit is set if Intr taken in U mode
61 mov.nz r9, sp 148 ; 2. Upon entry SP is always saved (for any inspection, unwinding etc),
62 add.nz r9, r9, SZ_PT_REGS - PT_sp - 4 149 ; but on return, restored only if U mode
63 bnz 1f
64 150
65 lr r9, [AUX_USER_SP] 151 lr r10, [AUX_USER_SP] ; U mode SP
661: 152
67 PUSH r9 ; SP 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
68 156
69 PUSH fp 157 st r10, [sp, PT_sp] ; SP (pt_regs->sp)
70 PUSH gp
71 158
72#ifdef CONFIG_ARC_CURR_IN_REG 159#ifdef CONFIG_ARC_CURR_IN_REG
73 PUSH r25 ; user_r25 160 st r25, [sp, PT_user_r25]
74 GET_CURR_TASK_ON_CPU r25 161 GET_CURR_TASK_ON_CPU r25
75#else
76 sub sp, sp, 4
77#endif 162#endif
78 163
79.ifnc \called_from, exception 164#ifdef CONFIG_ARC_HAS_ACCL_REGS
80 sub sp, sp, 12 ; BTA/ECR/orig_r0 placeholder per pt_regs 165 ST2 r58, r59, PT_sp + 12
81.endif 166#endif
82 167
83.endm 168.endm
84 169
85/*------------------------------------------------------------------------*/ 170/*------------------------------------------------------------------------*/
86.macro INTERRUPT_EPILOGUE called_from 171.macro __RESTORE_REGFILE_SOFT
87 172
88.ifnc \called_from, exception 173 LD2 gp, fp, PT_r26 ; gp (r26), fp (r27)
89 add sp, sp, 12 ; skip BTA/ECR/orig_r0 placeholderss
90.endif
91 174
92#ifdef CONFIG_ARC_CURR_IN_REG 175 ld r12, [sp, PT_sp + 4]
93 POP r25 176 ld r30, [sp, PT_sp + 8]
94#else
95 add sp, sp, 4
96#endif
97 177
98 POP gp 178 ; Restore SP (into AUX_USER_SP) only if returning to U mode
99 POP fp 179 ; - for K mode, it will be implicitly restored as stack is unwound
100 180 ; - Z flag set on K is inverse of what hardware does on interrupt entry
101 ; Don't touch AUX_USER_SP if returning to K mode (Z bit set) 181 ; but that doesn't really matter
102 ; (Z bit set on K mode is inverse of INTERRUPT_PROLOGUE)
103 add.z sp, sp, 4
104 bz 1f 182 bz 1f
105 183
106 POPAX AUX_USER_SP 184 ld r10, [sp, PT_sp] ; SP (pt_regs->sp)
185 sr r10, [AUX_USER_SP]
1071: 1861:
108 POP r12
109 POP r30
110 187
111#ifdef CONFIG_ARC_HAS_ACCL_REGS 188#ifdef CONFIG_ARC_CURR_IN_REG
112 POP r58 189 ld r25, [sp, PT_user_r25]
113 POP r59
114#endif 190#endif
115 191
116#ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE 192#ifdef CONFIG_ARC_HAS_ACCL_REGS
117.ifnc \called_from, exception 193 LD2 r58, r59, PT_sp + 12
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 194#endif
195.endm
142 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
143.endm 215.endm
144 216
217
145/*------------------------------------------------------------------------*/ 218/*------------------------------------------------------------------------*/
146.macro EXCEPTION_PROLOGUE 219.macro INTERRUPT_EPILOGUE
147 220
148 ; Before jumping to Exception Vector, hardware micro-ops did following: 221 ; INPUT: r0 has STAT32 of calling context
149 ; 1. SP auto-switched to kernel mode stack 222 ; INPUT: Z flag set if returning to K mode
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
153
154 PUSH r9 ; freeup a register: slot of erstatus
155
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
162
163 PUSH r11
164 PUSH r10
165
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
169
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
180
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)
188 223
189 and r10, r10, STATUS_U_MASK 224 ; _SOFT clobbers r10 restored by _HARD hence the order
190 xor.f 0, r10, STATUS_U_MASK
191 225
192 INTERRUPT_PROLOGUE exception 226 __RESTORE_REGFILE_SOFT
193 227
194 PUSHAX erbta 228#ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
195 PUSHAX ecr ; r9 contains ECR, expected by EV_Trap 229 __RESTORE_REGFILE_HARD
230 add sp, sp, SZ_PT_REGS - 8
231#else
232 add sp, sp, PT_r0
233#endif
196 234
197 PUSH r0 ; orig_r0
198.endm 235.endm
199 236
200/*------------------------------------------------------------------------*/ 237/*------------------------------------------------------------------------*/
201.macro EXCEPTION_EPILOGUE 238.macro EXCEPTION_EPILOGUE
202 239
203 ; Assumes r0 has PT_status32 240 ; INPUT: r0 has STAT32 of calling context
204 btst r0, STATUS_U_BIT ; Z flag set if K, used in INTERRUPT_EPILOGUE
205
206 add sp, sp, 8 ; orig_r0/ECR don't need restoring
207 POPAX erbta
208
209 INTERRUPT_EPILOGUE exception
210 241
211 POP r0 242 btst r0, STATUS_U_BIT ; Z flag set if K, used in restoring SP
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
223 243
224 POP blink 244 ld r10, [sp, PT_event + 4]
225 POPAX lp_end 245 sr r10, [erbta]
226 POPAX lp_start
227 246
228 POP r9 247 LD2 r10, r11, PT_ret
229 mov lp_count, r9 248 sr r10, [eret]
249 sr r11, [erstatus]
230 250
231 add sp, sp, 12 ; skip JLI, LDI, EI 251 __RESTORE_REGFILE_SOFT
232 POPAX eret 252 __RESTORE_REGFILE_HARD
233 POPAX erstatus
234 253
235 ld.as r9, [sp, -12] ; reload r9 which got clobbered 254 add sp, sp, SZ_PT_REGS
236.endm 255.endm
237 256
238.macro FAKE_RET_FROM_EXCPN 257.macro FAKE_RET_FROM_EXCPN