diff options
author | Vineet Gupta <vgupta@synopsys.com> | 2014-09-22 15:21:47 +0400 |
---|---|---|
committer | Vineet Gupta <vgupta@synopsys.com> | 2015-06-22 11:36:55 +0300 |
commit | 4255b07f2c9c43540149ed823faf5ac8476cccee (patch) | |
tree | 9d9fa4ad088b92a28987d3b89a1fe142cf828766 | |
parent | 1f6ccfff6314672743ad7252160654709e997a2a (diff) | |
download | linux-4255b07f2c9c43540149ed823faf5ac8476cccee.tar.xz |
ARCv2: STAR 9000793984: Handle return from intr to Delay Slot
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
-rw-r--r-- | arch/arc/kernel/asm-offsets.c | 1 | ||||
-rw-r--r-- | arch/arc/kernel/entry-arcv2.S | 50 | ||||
-rw-r--r-- | arch/arc/kernel/setup.c | 2 |
3 files changed, 53 insertions, 0 deletions
diff --git a/arch/arc/kernel/asm-offsets.c b/arch/arc/kernel/asm-offsets.c index 6c3aa0edb9b5..b9cf23313273 100644 --- a/arch/arc/kernel/asm-offsets.c +++ b/arch/arc/kernel/asm-offsets.c @@ -56,6 +56,7 @@ int main(void) DEFINE(PT_r5, offsetof(struct pt_regs, r5)); DEFINE(PT_r6, offsetof(struct pt_regs, r6)); DEFINE(PT_r7, offsetof(struct pt_regs, r7)); + DEFINE(PT_ret, offsetof(struct pt_regs, ret)); DEFINE(SZ_CALLEE_REGS, sizeof(struct callee_regs)); DEFINE(SZ_PT_REGS, sizeof(struct pt_regs)); diff --git a/arch/arc/kernel/entry-arcv2.S b/arch/arc/kernel/entry-arcv2.S index c59a396b7b98..bd7105d3172f 100644 --- a/arch/arc/kernel/entry-arcv2.S +++ b/arch/arc/kernel/entry-arcv2.S @@ -163,6 +163,9 @@ END(EV_TLBProtV) ;####### Return from Intr ####### debug_marker_l1: + bbit1.nt r0, STATUS_DE_BIT, .Lintr_ret_to_delay_slot + +.Lisr_ret_fast_path: ; Handle special case #1: (Entry via Exception, Return via IRQ) ; ; Exception in U mode, preempted in kernel, Intr taken (K mode), orig @@ -186,4 +189,51 @@ debug_marker_syscall: EXCEPTION_EPILOGUE rtie +;####### Return from Intr to insn in delay slot ####### + +; Handle special case #2: (Entry via Exception in Delay Slot, Return via IRQ) +; +; Intr returning to a Delay Slot (DS) insn +; (since IRQ NOT allowed in DS in ARCv2, this can only happen if orig +; entry was via Exception in DS which got preempted in kernel). +; +; IRQ RTIE won't reliably restore DE bit and/or BTA, needs handling +.Lintr_ret_to_delay_slot: +debug_marker_ds: + + ld r2, [@intr_to_DE_cnt] + add r2, r2, 1 + st r2, [@intr_to_DE_cnt] + + ld r2, [sp, PT_ret] + ld r3, [sp, PT_status32] + + bic r0, r3, STATUS_U_MASK|STATUS_DE_MASK|STATUS_IE_MASK|STATUS_L_MASK + st r0, [sp, PT_status32] + + mov r1, .Lintr_ret_to_delay_slot_2 + st r1, [sp, PT_ret] + + st r2, [sp, 0] + st r3, [sp, 4] + + b .Lisr_ret_fast_path + +.Lintr_ret_to_delay_slot_2: + sub sp, sp, SZ_PT_REGS + st r9, [sp, -4] + + ld r9, [sp, 0] + sr r9, [eret] + + ld r9, [sp, 4] + sr r9, [erstatus] + + ld r9, [sp, 8] + sr r9, [erbta] + + ld r9, [sp, -4] + add sp, sp, SZ_PT_REGS + rtie + END(ret_from_exception) diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c index d6fe80070bbf..ca71cef4bafd 100644 --- a/arch/arc/kernel/setup.c +++ b/arch/arc/kernel/setup.c @@ -30,6 +30,8 @@ #define FIX_PTR(x) __asm__ __volatile__(";" : "+r"(x)) +unsigned int intr_to_DE_cnt; + /* Part of U-boot ABI: see head.S */ int __initdata uboot_tag; char __initdata *uboot_arg; |