Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/arc/include/asm/entry-compact.h
26481 views
1
/* SPDX-License-Identifier: GPL-2.0-only */
2
/*
3
* Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
4
* Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
5
*
6
* Vineetg: March 2009 (Supporting 2 levels of Interrupts)
7
* Stack switching code can no longer reliably rely on the fact that
8
* if we are NOT in user mode, stack is switched to kernel mode.
9
* e.g. L2 IRQ interrupted a L1 ISR which had not yet completed
10
* its prologue including stack switching from user mode
11
*
12
* Vineetg: Aug 28th 2008: Bug #94984
13
* -Zero Overhead Loop Context shd be cleared when entering IRQ/EXcp/Trap
14
* Normally CPU does this automatically, however when doing FAKE rtie,
15
* we also need to explicitly do this. The problem in macros
16
* FAKE_RET_FROM_EXCPN and FAKE_RET_FROM_EXCPN_LOCK_IRQ was that this bit
17
* was being "CLEARED" rather then "SET". Actually "SET" clears ZOL context
18
*
19
* Vineetg: May 5th 2008
20
* -Modified CALLEE_REG save/restore macros to handle the fact that
21
* r25 contains the kernel current task ptr
22
* - Defined Stack Switching Macro to be reused in all intr/excp hdlrs
23
* - Shaved off 11 instructions from RESTORE_ALL_INT1 by using the
24
* address Write back load ld.ab instead of separate ld/add instn
25
*
26
* Amit Bhor, Sameer Dhavale: Codito Technologies 2004
27
*/
28
29
#ifndef __ASM_ARC_ENTRY_COMPACT_H
30
#define __ASM_ARC_ENTRY_COMPACT_H
31
32
#include <asm/asm-offsets.h>
33
#include <asm/irqflags-compact.h>
34
#include <asm/thread_info.h> /* For THREAD_SIZE */
35
36
/* Note on the LD/ST addr modes with addr reg wback
37
*
38
* LD.a same as LD.aw
39
*
40
* LD.a reg1, [reg2, x] => Pre Incr
41
* Eff Addr for load = [reg2 + x]
42
*
43
* LD.ab reg1, [reg2, x] => Post Incr
44
* Eff Addr for load = [reg2]
45
*/
46
47
.macro PUSHAX aux
48
lr r9, [\aux]
49
push r9
50
.endm
51
52
.macro POPAX aux
53
pop r9
54
sr r9, [\aux]
55
.endm
56
57
.macro SAVE_R0_TO_R12
58
push r0
59
push r1
60
push r2
61
push r3
62
push r4
63
push r5
64
push r6
65
push r7
66
push r8
67
push r9
68
push r10
69
push r11
70
push r12
71
.endm
72
73
.macro RESTORE_R12_TO_R0
74
pop r12
75
pop r11
76
pop r10
77
pop r9
78
pop r8
79
pop r7
80
pop r6
81
pop r5
82
pop r4
83
pop r3
84
pop r2
85
pop r1
86
pop r0
87
.endm
88
89
.macro SAVE_ABI_CALLEE_REGS
90
push r13
91
push r14
92
push r15
93
push r16
94
push r17
95
push r18
96
push r19
97
push r20
98
push r21
99
push r22
100
push r23
101
push r24
102
push r25
103
.endm
104
105
.macro RESTORE_ABI_CALLEE_REGS
106
pop r25
107
pop r24
108
pop r23
109
pop r22
110
pop r21
111
pop r20
112
pop r19
113
pop r18
114
pop r17
115
pop r16
116
pop r15
117
pop r14
118
pop r13
119
.endm
120
121
/*--------------------------------------------------------------
122
* Switch to Kernel Mode stack if SP points to User Mode stack
123
*
124
* Entry : r9 contains pre-IRQ/exception/trap status32
125
* Exit : SP set to K mode stack
126
* SP at the time of entry (K/U) saved @ pt_regs->sp
127
* Clobbers: r9
128
*-------------------------------------------------------------*/
129
130
.macro SWITCH_TO_KERNEL_STK
131
132
/* User Mode when this happened ? Yes: Proceed to switch stack */
133
bbit1 r9, STATUS_U_BIT, 88f
134
135
/* OK we were already in kernel mode when this event happened, thus can
136
* assume SP is kernel mode SP. _NO_ need to do any stack switching
137
*/
138
139
#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
140
/* However....
141
* If Level 2 Interrupts enabled, we may end up with a corner case:
142
* 1. User Task executing
143
* 2. L1 IRQ taken, ISR starts (CPU auto-switched to KERNEL mode)
144
* 3. But before it could switch SP from USER to KERNEL stack
145
* a L2 IRQ "Interrupts" L1
146
* That way although L2 IRQ happened in Kernel mode, stack is still
147
* not switched.
148
* To handle this, we may need to switch stack even if in kernel mode
149
* provided SP has values in range of USER mode stack ( < 0x7000_0000 )
150
*/
151
brlo sp, VMALLOC_START, 88f
152
153
/* TODO: vineetg:
154
* We need to be a bit more cautious here. What if a kernel bug in
155
* L1 ISR, caused SP to go whaco (some small value which looks like
156
* USER stk) and then we take L2 ISR.
157
* Above brlo alone would treat it as a valid L1-L2 scenario
158
* instead of shouting around
159
* The only feasible way is to make sure this L2 happened in
160
* L1 prelogue ONLY i.e. ilink2 is less than a pre-set marker in
161
* L1 ISR before it switches stack
162
*/
163
164
#endif
165
166
/*------Intr/Ecxp happened in kernel mode, SP already setup ------ */
167
/* save it nevertheless @ pt_regs->sp for uniformity */
168
169
b.d 66f
170
st sp, [sp, PT_sp - SZ_PT_REGS]
171
172
88: /*------Intr/Ecxp happened in user mode, "switch" stack ------ */
173
174
GET_CURR_TASK_ON_CPU r9
175
176
/* With current tsk in r9, get its kernel mode stack base */
177
GET_TSK_STACK_BASE r9, r9
178
179
/* save U mode SP @ pt_regs->sp */
180
st sp, [r9, PT_sp - SZ_PT_REGS]
181
182
/* final SP switch */
183
mov sp, r9
184
66:
185
.endm
186
187
/*------------------------------------------------------------
188
* "FAKE" a rtie to return from CPU Exception context
189
* This is to re-enable Exceptions within exception
190
* Look at EV_ProtV to see how this is actually used
191
*-------------------------------------------------------------*/
192
193
.macro FAKE_RET_FROM_EXCPN
194
195
lr r9, [status32]
196
bclr r9, r9, STATUS_AE_BIT
197
or r9, r9, (STATUS_E1_MASK|STATUS_E2_MASK)
198
sr r9, [erstatus]
199
mov r9, 55f
200
sr r9, [eret]
201
rtie
202
55:
203
.endm
204
205
/*--------------------------------------------------------------
206
* For early Exception/ISR Prologue, a core reg is temporarily needed to
207
* code the rest of prolog (stack switching). This is done by stashing
208
* it to memory (non-SMP case) or SCRATCH0 Aux Reg (SMP).
209
*
210
* Before saving the full regfile - this reg is restored back, only
211
* to be saved again on kernel mode stack, as part of pt_regs.
212
*-------------------------------------------------------------*/
213
.macro PROLOG_FREEUP_REG reg, mem
214
st \reg, [\mem]
215
.endm
216
217
.macro PROLOG_RESTORE_REG reg, mem
218
ld \reg, [\mem]
219
.endm
220
221
/*--------------------------------------------------------------
222
* Exception Entry prologue
223
* -Switches stack to K mode (if not already)
224
* -Saves the register file
225
*
226
* After this it is safe to call the "C" handlers
227
*-------------------------------------------------------------*/
228
.macro EXCEPTION_PROLOGUE_KEEP_AE
229
230
/* Need at least 1 reg to code the early exception prologue */
231
PROLOG_FREEUP_REG r9, @ex_saved_reg1
232
233
/* U/K mode at time of exception (stack not switched if already K) */
234
lr r9, [erstatus]
235
236
/* ARC700 doesn't provide auto-stack switching */
237
SWITCH_TO_KERNEL_STK
238
239
st.a r0, [sp, -8] /* orig_r0 needed for syscall (skip ECR slot) */
240
sub sp, sp, 4 /* skip pt_regs->sp, already saved above */
241
242
/* Restore r9 used to code the early prologue */
243
PROLOG_RESTORE_REG r9, @ex_saved_reg1
244
245
/* now we are ready to save the regfile */
246
SAVE_R0_TO_R12
247
PUSH gp
248
PUSH fp
249
PUSH blink
250
PUSHAX eret
251
PUSHAX erstatus
252
PUSH lp_count
253
PUSHAX lp_end
254
PUSHAX lp_start
255
PUSHAX erbta
256
257
lr r10, [ecr]
258
st r10, [sp, PT_event]
259
260
#ifdef CONFIG_ARC_CURR_IN_REG
261
/* gp already saved on stack: now load with "current" */
262
GET_CURR_TASK_ON_CPU gp
263
#endif
264
; OUTPUT: r10 has ECR expected by EV_Trap
265
.endm
266
267
.macro EXCEPTION_PROLOGUE
268
269
EXCEPTION_PROLOGUE_KEEP_AE ; return ECR in r10
270
271
lr r0, [efa]
272
mov r1, sp
273
274
FAKE_RET_FROM_EXCPN ; clobbers r9
275
.endm
276
277
/*--------------------------------------------------------------
278
* Restore all registers used by system call or Exceptions
279
* SP should always be pointing to the next free stack element
280
* when entering this macro.
281
*
282
* NOTE:
283
*
284
* It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg
285
* for memory load operations. If used in that way interrupts are deferred
286
* by hardware and that is not good.
287
*-------------------------------------------------------------*/
288
.macro EXCEPTION_EPILOGUE
289
290
POPAX erbta
291
POPAX lp_start
292
POPAX lp_end
293
294
POP r9
295
mov lp_count, r9 ;LD to lp_count is not allowed
296
297
POPAX erstatus
298
POPAX eret
299
POP blink
300
POP fp
301
POP gp
302
RESTORE_R12_TO_R0
303
304
ld sp, [sp] /* restore original sp */
305
/* orig_r0, ECR skipped automatically */
306
.endm
307
308
/* Dummy ECR values for Interrupts */
309
#define event_IRQ1 0x0031abcd
310
#define event_IRQ2 0x0032abcd
311
312
.macro INTERRUPT_PROLOGUE LVL
313
314
/* free up r9 as scratchpad */
315
PROLOG_FREEUP_REG r9, @int\LVL\()_saved_reg
316
317
/* Which mode (user/kernel) was the system in when intr occurred */
318
lr r9, [status32_l\LVL\()]
319
320
SWITCH_TO_KERNEL_STK
321
322
323
st.a 0x003\LVL\()abcd, [sp, -4] /* Dummy ECR */
324
sub sp, sp, 8 /* skip orig_r0 (not needed)
325
skip pt_regs->sp, already saved above */
326
327
/* Restore r9 used to code the early prologue */
328
PROLOG_RESTORE_REG r9, @int\LVL\()_saved_reg
329
330
SAVE_R0_TO_R12
331
PUSH gp
332
PUSH fp
333
PUSH blink
334
PUSH ilink\LVL\()
335
PUSHAX status32_l\LVL\()
336
PUSH lp_count
337
PUSHAX lp_end
338
PUSHAX lp_start
339
PUSHAX bta_l\LVL\()
340
341
#ifdef CONFIG_ARC_CURR_IN_REG
342
/* gp already saved on stack: now load with "current" */
343
GET_CURR_TASK_ON_CPU gp
344
#endif
345
.endm
346
347
/*--------------------------------------------------------------
348
* Restore all registers used by interrupt handlers.
349
*
350
* NOTE:
351
*
352
* It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg
353
* for memory load operations. If used in that way interrupts are deferred
354
* by hardware and that is not good.
355
*-------------------------------------------------------------*/
356
.macro INTERRUPT_EPILOGUE LVL
357
358
POPAX bta_l\LVL\()
359
POPAX lp_start
360
POPAX lp_end
361
362
POP r9
363
mov lp_count, r9 ;LD to lp_count is not allowed
364
365
POPAX status32_l\LVL\()
366
POP ilink\LVL\()
367
POP blink
368
POP fp
369
POP gp
370
RESTORE_R12_TO_R0
371
372
ld sp, [sp] /* restore original sp; orig_r0, ECR skipped implicitly */
373
.endm
374
375
/* Get thread_info of "current" tsk */
376
.macro GET_CURR_THR_INFO_FROM_SP reg
377
bic \reg, sp, (THREAD_SIZE - 1)
378
.endm
379
380
/* Get CPU-ID of this core */
381
.macro GET_CPU_ID reg
382
lr \reg, [identity]
383
lsr \reg, \reg, 8
384
bmsk \reg, \reg, 7
385
.endm
386
387
#endif /* __ASM_ARC_ENTRY_COMPACT_H */
388
389