entry.h (9b8c7d1e7107c30a50aae27c1f33fe706c8c6c67) entry.h (6d1a20b1d237db29878ae54142e39c87a36d0e95)
1/*
1/*
2 * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
2 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
3 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
7 *
8 * Vineetg: March 2009 (Supporting 2 levels of Interrupts)
9 * Stack switching code can no longer reliably rely on the fact that
10 * if we are NOT in user mode, stack is switched to kernel mode.
11 * e.g. L2 IRQ interrupted a L1 ISR which had not yet completed
12 * it's prologue including stack switching from user mode
13 *
14 * Vineetg: Aug 28th 2008: Bug #94984
15 * -Zero Overhead Loop Context shd be cleared when entering IRQ/EXcp/Trap
16 * Normally CPU does this automatically, however when doing FAKE rtie,
17 * we also need to explicitly do this. The problem in macros
18 * FAKE_RET_FROM_EXCPN and FAKE_RET_FROM_EXCPN_LOCK_IRQ was that this bit
19 * was being "CLEARED" rather then "SET". Actually "SET" clears ZOL context
20 *
21 * Vineetg: May 5th 2008
22 * -Modified CALLEE_REG save/restore macros to handle the fact that
23 * r25 contains the kernel current task ptr
24 * - Defined Stack Switching Macro to be reused in all intr/excp hdlrs
25 * - Shaved off 11 instructions from RESTORE_ALL_INT1 by using the
26 * address Write back load ld.ab instead of seperate ld/add instn
27 *
28 * Amit Bhor, Sameer Dhavale: Codito Technologies 2004
29 */
30
31#ifndef __ASM_ARC_ENTRY_H
32#define __ASM_ARC_ENTRY_H
33
8 */
9
10#ifndef __ASM_ARC_ENTRY_H
11#define __ASM_ARC_ENTRY_H
12
34#ifdef __ASSEMBLY__
35#include <asm/unistd.h> /* For NR_syscalls defination */
13#include <asm/unistd.h> /* For NR_syscalls defination */
36#include <asm/asm-offsets.h>
37#include <asm/arcregs.h>
38#include <asm/ptrace.h>
39#include <asm/processor.h> /* For VMALLOC_START */
14#include <asm/arcregs.h>
15#include <asm/ptrace.h>
16#include <asm/processor.h> /* For VMALLOC_START */
40#include <asm/thread_info.h> /* For THREAD_SIZE */
41#include <asm/mmu.h>
42
17#include <asm/mmu.h>
18
19#include <asm/entry-compact.h> /* ISA specific bits */
20
43/* Note on the LD/ST addr modes with addr reg wback
44 *
45 * LD.a same as LD.aw
46 *
47 * LD.a reg1, [reg2, x] => Pre Incr
48 * Eff Addr for load = [reg2 + x]
49 *
50 * LD.ab reg1, [reg2, x] => Post Incr

--- 184 unchanged lines hidden (view full) ---

235 /* Get task->thread_info (this is essentially start of a PAGE) */
236 ld \out, [\tsk, TASK_THREAD_INFO]
237
238 /* Go to end of page where stack begins (grows upwards) */
239 add2 \out, \out, (THREAD_SIZE)/4
240
241.endm
242
21/* Note on the LD/ST addr modes with addr reg wback
22 *
23 * LD.a same as LD.aw
24 *
25 * LD.a reg1, [reg2, x] => Pre Incr
26 * Eff Addr for load = [reg2 + x]
27 *
28 * LD.ab reg1, [reg2, x] => Post Incr

--- 184 unchanged lines hidden (view full) ---

213 /* Get task->thread_info (this is essentially start of a PAGE) */
214 ld \out, [\tsk, TASK_THREAD_INFO]
215
216 /* Go to end of page where stack begins (grows upwards) */
217 add2 \out, \out, (THREAD_SIZE)/4
218
219.endm
220
243/*--------------------------------------------------------------
244 * Switch to Kernel Mode stack if SP points to User Mode stack
245 *
246 * Entry : r9 contains pre-IRQ/exception/trap status32
247 * Exit : SP is set to kernel mode stack pointer
248 * If CURR_IN_REG, r25 set to "current" task pointer
249 * Clobbers: r9
250 *-------------------------------------------------------------*/
251
252.macro SWITCH_TO_KERNEL_STK
253
254 /* User Mode when this happened ? Yes: Proceed to switch stack */
255 bbit1 r9, STATUS_U_BIT, 88f
256
257 /* OK we were already in kernel mode when this event happened, thus can
258 * assume SP is kernel mode SP. _NO_ need to do any stack switching
259 */
260
261#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
262 /* However....
263 * If Level 2 Interrupts enabled, we may end up with a corner case:
264 * 1. User Task executing
265 * 2. L1 IRQ taken, ISR starts (CPU auto-switched to KERNEL mode)
266 * 3. But before it could switch SP from USER to KERNEL stack
267 * a L2 IRQ "Interrupts" L1
268 * Thay way although L2 IRQ happened in Kernel mode, stack is still
269 * not switched.
270 * To handle this, we may need to switch stack even if in kernel mode
271 * provided SP has values in range of USER mode stack ( < 0x7000_0000 )
272 */
273 brlo sp, VMALLOC_START, 88f
274
275 /* TODO: vineetg:
276 * We need to be a bit more cautious here. What if a kernel bug in
277 * L1 ISR, caused SP to go whaco (some small value which looks like
278 * USER stk) and then we take L2 ISR.
279 * Above brlo alone would treat it as a valid L1-L2 sceanrio
280 * instead of shouting alound
281 * The only feasible way is to make sure this L2 happened in
282 * L1 prelogue ONLY i.e. ilink2 is less than a pre-set marker in
283 * L1 ISR before it switches stack
284 */
285
286#endif
287
288 /* Save Pre Intr/Exception KERNEL MODE SP on kernel stack
289 * safe-keeping not really needed, but it keeps the epilogue code
290 * (SP restore) simpler/uniform.
291 */
292 b.d 66f
293 mov r9, sp
294
29588: /*------Intr/Ecxp happened in user mode, "switch" stack ------ */
296
297 GET_CURR_TASK_ON_CPU r9
298
299 /* With current tsk in r9, get it's kernel mode stack base */
300 GET_TSK_STACK_BASE r9, r9
301
30266:
303#ifdef CONFIG_ARC_CURR_IN_REG
304 /*
305 * Treat r25 as scratch reg, save it on stack first
306 * Load it with current task pointer
307 */
308 st r25, [r9, -4]
309 GET_CURR_TASK_ON_CPU r25
310#endif
311
312 /* Save Pre Intr/Exception User SP on kernel stack */
313 st.a sp, [r9, -16] ; Make room for orig_r0, ECR, user_r25
314
315 /* CAUTION:
316 * SP should be set at the very end when we are done with everything
317 * In case of 2 levels of interrupt we depend on value of SP to assume
318 * that everything else is done (loading r25 etc)
319 */
320
321 /* set SP to point to kernel mode stack */
322 mov sp, r9
323
324 /* ----- Stack Switched to kernel Mode, Now save REG FILE ----- */
325
326.endm
327
328/*------------------------------------------------------------
329 * "FAKE" a rtie to return from CPU Exception context
330 * This is to re-enable Exceptions within exception
331 * Look at EV_ProtV to see how this is actually used
332 *-------------------------------------------------------------*/
333
334.macro FAKE_RET_FROM_EXCPN
335
336 ld r9, [sp, PT_status32]
337 bic r9, r9, (STATUS_U_MASK|STATUS_DE_MASK)
338 bset r9, r9, STATUS_L_BIT
339 sr r9, [erstatus]
340 mov r9, 55f
341 sr r9, [eret]
342
343 rtie
34455:
345.endm
346
347/*
221/*
348 * @reg [OUT] &thread_info of "current"
349 */
350.macro GET_CURR_THR_INFO_FROM_SP reg
351 bic \reg, sp, (THREAD_SIZE - 1)
352.endm
353
354/*
355 * @reg [OUT] thread_info->flags of "current"
356 */
357.macro GET_CURR_THR_INFO_FLAGS reg
358 GET_CURR_THR_INFO_FROM_SP \reg
359 ld \reg, [\reg, THREAD_INFO_FLAGS]
360.endm
361
222 * @reg [OUT] thread_info->flags of "current"
223 */
224.macro GET_CURR_THR_INFO_FLAGS reg
225 GET_CURR_THR_INFO_FROM_SP \reg
226 ld \reg, [\reg, THREAD_INFO_FLAGS]
227.endm
228
362/*--------------------------------------------------------------
363 * For early Exception/ISR Prologue, a core reg is temporarily needed to
364 * code the rest of prolog (stack switching). This is done by stashing
365 * it to memory (non-SMP case) or SCRATCH0 Aux Reg (SMP).
366 *
367 * Before saving the full regfile - this reg is restored back, only
368 * to be saved again on kernel mode stack, as part of pt_regs.
369 *-------------------------------------------------------------*/
370.macro PROLOG_FREEUP_REG reg, mem
371#ifdef CONFIG_SMP
229#ifdef CONFIG_SMP
372 sr \reg, [ARC_REG_SCRATCH_DATA0]
373#else
374 st \reg, [\mem]
375#endif
376.endm
377
230
378.macro PROLOG_RESTORE_REG reg, mem
379#ifdef CONFIG_SMP
380 lr \reg, [ARC_REG_SCRATCH_DATA0]
381#else
382 ld \reg, [\mem]
383#endif
384.endm
385
386/*--------------------------------------------------------------
387 * Exception Entry prologue
388 * -Switches stack to K mode (if not already)
389 * -Saves the register file
390 *
391 * After this it is safe to call the "C" handlers
392 *-------------------------------------------------------------*/
393.macro EXCEPTION_PROLOGUE
394
395 /* Need at least 1 reg to code the early exception prologue */
396 PROLOG_FREEUP_REG r9, @ex_saved_reg1
397
398 /* U/K mode at time of exception (stack not switched if already K) */
399 lr r9, [erstatus]
400
401 /* ARC700 doesn't provide auto-stack switching */
402 SWITCH_TO_KERNEL_STK
403
404 lr r9, [ecr]
405 st r9, [sp, 8] /* ECR */
406 st r0, [sp, 4] /* orig_r0, needed only for sys calls */
407
408 /* Restore r9 used to code the early prologue */
409 PROLOG_RESTORE_REG r9, @ex_saved_reg1
410
411 SAVE_R0_TO_R12
412 PUSH gp
413 PUSH fp
414 PUSH blink
415 PUSHAX eret
416 PUSHAX erstatus
417 PUSH lp_count
418 PUSHAX lp_end
419 PUSHAX lp_start
420 PUSHAX erbta
421.endm
422
423/*--------------------------------------------------------------
424 * Restore all registers used by system call or Exceptions
425 * SP should always be pointing to the next free stack element
426 * when entering this macro.
427 *
428 * NOTE:
429 *
430 * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg
431 * for memory load operations. If used in that way interrupts are deffered
432 * by hardware and that is not good.
433 *-------------------------------------------------------------*/
434.macro EXCEPTION_EPILOGUE
435 POPAX erbta
436 POPAX lp_start
437 POPAX lp_end
438
439 POP r9
440 mov lp_count, r9 ;LD to lp_count is not allowed
441
442 POPAX erstatus
443 POPAX eret
444 POP blink
445 POP fp
446 POP gp
447 RESTORE_R12_TO_R0
448
449 ld sp, [sp] /* restore original sp */
450 /* orig_r0, ECR, user_r25 skipped automatically */
451.endm
452
453/* Dummy ECR values for Interrupts */
454#define event_IRQ1 0x0031abcd
455#define event_IRQ2 0x0032abcd
456
457.macro INTERRUPT_PROLOGUE LVL
458
459 /* free up r9 as scratchpad */
460 PROLOG_FREEUP_REG r9, @int\LVL\()_saved_reg
461
462 /* Which mode (user/kernel) was the system in when intr occurred */
463 lr r9, [status32_l\LVL\()]
464
465 SWITCH_TO_KERNEL_STK
466
467 /* restore original r9 */
468 PROLOG_RESTORE_REG r9, @int\LVL\()_saved_reg
469
470 /* now we are ready to save the remaining context */
471 st 0x003\LVL\()abcd, [sp, 8] /* Dummy ECR */
472 st 0, [sp, 4] /* orig_r0 , N/A for IRQ */
473
474 SAVE_R0_TO_R12
475 PUSH gp
476 PUSH fp
477 PUSH blink
478 PUSH ilink\LVL\()
479 PUSHAX status32_l\LVL\()
480 PUSH lp_count
481 PUSHAX lp_end
482 PUSHAX lp_start
483 PUSHAX bta_l\LVL\()
484.endm
485
486/*--------------------------------------------------------------
487 * Restore all registers used by interrupt handlers.
488 *
489 * NOTE:
490 *
491 * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg
492 * for memory load operations. If used in that way interrupts are deffered
493 * by hardware and that is not good.
494 *-------------------------------------------------------------*/
495.macro INTERRUPT_EPILOGUE LVL
496 POPAX bta_l\LVL\()
497 POPAX lp_start
498 POPAX lp_end
499
500 POP r9
501 mov lp_count, r9 ;LD to lp_count is not allowed
502
503 POPAX status32_l\LVL\()
504 POP ilink\LVL\()
505 POP blink
506 POP fp
507 POP gp
508 RESTORE_R12_TO_R0
509
510 ld sp, [sp] /* restore original sp */
511 /* orig_r0, ECR, user_r25 skipped automatically */
512.endm
513
514/* Get CPU-ID of this core */
515.macro GET_CPU_ID reg
516 lr \reg, [identity]
517 lsr \reg, \reg, 8
518 bmsk \reg, \reg, 7
519.endm
520
521#ifdef CONFIG_SMP
522
523/*-------------------------------------------------
524 * Retrieve the current running task on this CPU
525 * 1. Determine curr CPU id.
526 * 2. Use it to index into _current_task[ ]
527 */
528.macro GET_CURR_TASK_ON_CPU reg
529 GET_CPU_ID \reg
530 ld.as \reg, [@_current_task, \reg]

--- 50 unchanged lines hidden (view full) ---

581
582.macro GET_CURR_TASK_FIELD_PTR off, reg
583 GET_CURR_TASK_ON_CPU \reg
584 add \reg, \reg, \off
585.endm
586
587#endif /* CONFIG_ARC_CURR_IN_REG */
588
231/*-------------------------------------------------
232 * Retrieve the current running task on this CPU
233 * 1. Determine curr CPU id.
234 * 2. Use it to index into _current_task[ ]
235 */
236.macro GET_CURR_TASK_ON_CPU reg
237 GET_CPU_ID \reg
238 ld.as \reg, [@_current_task, \reg]

--- 50 unchanged lines hidden (view full) ---

289
290.macro GET_CURR_TASK_FIELD_PTR off, reg
291 GET_CURR_TASK_ON_CPU \reg
292 add \reg, \reg, \off
293.endm
294
295#endif /* CONFIG_ARC_CURR_IN_REG */
296
589#endif /* __ASSEMBLY__ */
590
591#endif /* __ASM_ARC_ENTRY_H */
297#endif /* __ASM_ARC_ENTRY_H */