diff options
author | Vineet Gupta <vgupta@synopsys.com> | 2013-01-18 04:42:22 -0500 |
---|---|---|
committer | Vineet Gupta <vgupta@synopsys.com> | 2013-02-15 12:46:01 -0500 |
commit | 4788a5942bc896803c87005be8c6dd14c373a2d3 (patch) | |
tree | 0999ce29d94a3517a30df1b1463fdd9c9d200b28 /arch/arc/include/asm | |
parent | 769bc1fd7b8591a312d4c5c8834bc6510272938e (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.h | 95 | ||||
-rw-r--r-- | arch/arc/include/asm/irqflags.h | 6 |
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 | */ |
96 | static inline int arch_irqs_disabled_flags(unsigned long flags) | 96 | static 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 | ||
101 | static inline int arch_irqs_disabled(void) | 105 | static inline int arch_irqs_disabled(void) |