~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arc/include/asm/entry-compact.h

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php