aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arc/include/asm
diff options
context:
space:
mode:
authorVineet Gupta <vgupta@synopsys.com>2013-01-18 04:42:22 -0500
committerVineet Gupta <vgupta@synopsys.com>2013-02-15 12:46:01 -0500
commit4788a5942bc896803c87005be8c6dd14c373a2d3 (patch)
tree0999ce29d94a3517a30df1b1463fdd9c9d200b28 /arch/arc/include/asm
parent769bc1fd7b8591a312d4c5c8834bc6510272938e (diff)
ARC: Support for high priority interrupts in the in-core intc
There is a bit of hack/kludge right now where we disable preemption if a L2 (High prio) IRQ is taken while L1 (Low prio) is active. Need to revisit this Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Diffstat (limited to 'arch/arc/include/asm')
-rw-r--r--arch/arc/include/asm/entry.h95
-rw-r--r--arch/arc/include/asm/irqflags.h6
2 files changed, 100 insertions, 1 deletions
diff --git a/arch/arc/include/asm/entry.h b/arch/arc/include/asm/entry.h
index 716f4f7b5cd2..23ef2de1e09f 100644
--- a/arch/arc/include/asm/entry.h
+++ b/arch/arc/include/asm/entry.h
@@ -5,6 +5,12 @@
5 * it under the terms of the GNU General Public License version 2 as 5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation. 6 * published by the Free Software Foundation.
7 * 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 *
8 * Vineetg: Aug 28th 2008: Bug #94984 14 * Vineetg: Aug 28th 2008: Bug #94984
9 * -Zero Overhead Loop Context shd be cleared when entering IRQ/EXcp/Trap 15 * -Zero Overhead Loop Context shd be cleared when entering IRQ/EXcp/Trap
10 * Normally CPU does this automatically, however when doing FAKE rtie, 16 * Normally CPU does this automatically, however when doing FAKE rtie,
@@ -268,6 +274,33 @@
268 * assume SP is kernel mode SP. _NO_ need to do any stack switching 274 * assume SP is kernel mode SP. _NO_ need to do any stack switching
269 */ 275 */
270 276
277#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
278 /* However....
279 * If Level 2 Interrupts enabled, we may end up with a corner case:
280 * 1. User Task executing
281 * 2. L1 IRQ taken, ISR starts (CPU auto-switched to KERNEL mode)
282 * 3. But before it could switch SP from USER to KERNEL stack
283 * a L2 IRQ "Interrupts" L1
284 * Thay way although L2 IRQ happened in Kernel mode, stack is still
285 * not switched.
286 * To handle this, we may need to switch stack even if in kernel mode
287 * provided SP has values in range of USER mode stack ( < 0x7000_0000 )
288 */
289 brlo sp, VMALLOC_START, 88f
290
291 /* TODO: vineetg:
292 * We need to be a bit more cautious here. What if a kernel bug in
293 * L1 ISR, caused SP to go whaco (some small value which looks like
294 * USER stk) and then we take L2 ISR.
295 * Above brlo alone would treat it as a valid L1-L2 sceanrio
296 * instead of shouting alound
297 * The only feasible way is to make sure this L2 happened in
298 * L1 prelogue ONLY i.e. ilink2 is less than a pre-set marker in
299 * L1 ISR before it switches stack
300 */
301
302#endif
303
271 /* Save Pre Intr/Exception KERNEL MODE SP on kernel stack 304 /* Save Pre Intr/Exception KERNEL MODE SP on kernel stack
272 * safe-keeping not really needed, but it keeps the epilogue code 305 * safe-keeping not really needed, but it keeps the epilogue code
273 * (SP restore) simpler/uniform. 306 * (SP restore) simpler/uniform.
@@ -503,6 +536,42 @@
503 sub sp, sp, 4 536 sub sp, sp, 4
504.endm 537.endm
505 538
539.macro SAVE_ALL_INT2
540
541 /* TODO-vineetg: SMP we can't use global nor can we use
542 * SCRATCH0 as we do for int1 because while int1 is using
543 * it, int2 can come
544 */
545 /* retsore original r9 , saved in sys_saved_r9 */
546 ld r9, [@int2_saved_reg]
547
548 /* now we are ready to save the remaining context :) */
549 st orig_r8_IS_IRQ2, [sp, 8] /* Event Type */
550 st 0, [sp, 4] /* orig_r0 , N/A for IRQ */
551 SAVE_CALLER_SAVED
552 st.a r26, [sp, -4] /* gp */
553 st.a fp, [sp, -4]
554 st.a blink, [sp, -4]
555 st.a ilink2, [sp, -4]
556 lr r9, [status32_l2]
557 st.a r9, [sp, -4]
558 st.a lp_count, [sp, -4]
559 lr r9, [lp_end]
560 st.a r9, [sp, -4]
561 lr r9, [lp_start]
562 st.a r9, [sp, -4]
563 lr r9, [bta_l2]
564 st.a r9, [sp, -4]
565
566#ifdef PT_REGS_CANARY
567 mov r9, 0xdeadbee2
568 st r9, [sp, -4]
569#endif
570
571 /* move up by 1 word to "create" pt_regs->"stack_place_holder" */
572 sub sp, sp, 4
573.endm
574
506/*-------------------------------------------------------------- 575/*--------------------------------------------------------------
507 * Restore all registers used by interrupt handlers. 576 * Restore all registers used by interrupt handlers.
508 * 577 *
@@ -537,6 +606,32 @@
537 /* orig_r0 and orig_r8 skipped automatically */ 606 /* orig_r0 and orig_r8 skipped automatically */
538.endm 607.endm
539 608
609.macro RESTORE_ALL_INT2
610 add sp, sp, 4 /* hop over unused "pt_regs->stack_place_holder" */
611
612 ld.ab r9, [sp, 4]
613 sr r9, [bta_l2]
614 ld.ab r9, [sp, 4]
615 sr r9, [lp_start]
616 ld.ab r9, [sp, 4]
617 sr r9, [lp_end]
618 ld.ab r9, [sp, 4]
619 mov lp_count, r9
620 ld.ab r9, [sp, 4]
621 sr r9, [status32_l2]
622 ld.ab r9, [sp, 4]
623 mov ilink2, r9
624 ld.ab blink, [sp, 4]
625 ld.ab fp, [sp, 4]
626 ld.ab r26, [sp, 4] /* gp */
627 RESTORE_CALLER_SAVED
628
629 ld sp, [sp] /* restore original sp */
630 /* orig_r0 and orig_r8 skipped automatically */
631
632.endm
633
634
540/* Get CPU-ID of this core */ 635/* Get CPU-ID of this core */
541.macro GET_CPU_ID reg 636.macro GET_CPU_ID reg
542 lr \reg, [identity] 637 lr \reg, [identity]
diff --git a/arch/arc/include/asm/irqflags.h b/arch/arc/include/asm/irqflags.h
index 5cc1080d7c26..ccd84806b62f 100644
--- a/arch/arc/include/asm/irqflags.h
+++ b/arch/arc/include/asm/irqflags.h
@@ -95,7 +95,11 @@ static inline long arch_local_save_flags(void)
95 */ 95 */
96static inline int arch_irqs_disabled_flags(unsigned long flags) 96static inline int arch_irqs_disabled_flags(unsigned long flags)
97{ 97{
98 return !(flags & (STATUS_E1_MASK)); 98 return !(flags & (STATUS_E1_MASK
99#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
100 | STATUS_E2_MASK
101#endif
102 ));
99} 103}
100 104
101static inline int arch_irqs_disabled(void) 105static inline int arch_irqs_disabled(void)