diff options
author | Max Filippov <jcmvbkbc@gmail.com> | 2013-03-25 18:51:43 -0400 |
---|---|---|
committer | Chris Zankel <chris@zankel.net> | 2013-05-09 04:07:11 -0400 |
commit | 895666a9920f19bc256340aaf58d01da6e677a16 (patch) | |
tree | ff0b0fc50790d6ae5a37c5317e67523985f87bbd /arch/xtensa/kernel/entry.S | |
parent | 8f371c7521545ee120364466514a4a2fc156c64f (diff) |
xtensa: disable IRQs while IRQ handler is running
IRQ handlers are expected to run with IRQs disabled.
See e.g. http://lwn.net/Articles/380931/ for a longer story.
This was overlooked in the commit
2d1c645 xtensa: dispatch medium-priority interrupts
Revert to old behavior and simplify interrupt entry and exit code.
Interrupt handler still honours IRQ priority.
do_notify_resume/schedule must be called with interrupts enabled, enable
interrupts if we return from user exception.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Chris Zankel <chris@zankel.net>
Diffstat (limited to 'arch/xtensa/kernel/entry.S')
-rw-r--r-- | arch/xtensa/kernel/entry.S | 52 |
1 files changed, 11 insertions, 41 deletions
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index 3729b48d798d..5082507d5631 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S | |||
@@ -354,16 +354,16 @@ common_exception: | |||
354 | * so we can allow exceptions and interrupts (*) again. | 354 | * so we can allow exceptions and interrupts (*) again. |
355 | * Set PS(EXCM = 0, UM = 0, RING = 0, OWB = 0, WOE = 1, INTLEVEL = X) | 355 | * Set PS(EXCM = 0, UM = 0, RING = 0, OWB = 0, WOE = 1, INTLEVEL = X) |
356 | * | 356 | * |
357 | * (*) We only allow interrupts of higher priority than current IRQ | 357 | * (*) We only allow interrupts if they were previously enabled and |
358 | * we're not handling an IRQ | ||
358 | */ | 359 | */ |
359 | 360 | ||
360 | rsr a3, ps | 361 | rsr a3, ps |
361 | addi a0, a0, -4 | 362 | addi a0, a0, -EXCCAUSE_LEVEL1_INTERRUPT |
362 | movi a2, 1 | 363 | movi a2, LOCKLEVEL |
363 | extui a3, a3, PS_INTLEVEL_SHIFT, PS_INTLEVEL_WIDTH | 364 | extui a3, a3, PS_INTLEVEL_SHIFT, PS_INTLEVEL_WIDTH |
364 | # a3 = PS.INTLEVEL | 365 | # a3 = PS.INTLEVEL |
365 | movnez a2, a3, a3 # a2 = 1: level-1, > 1: high priority | 366 | moveqz a3, a2, a0 # a3 = LOCKLEVEL iff interrupt |
366 | moveqz a3, a2, a0 # a3 = IRQ level iff interrupt | ||
367 | movi a2, 1 << PS_WOE_BIT | 367 | movi a2, 1 << PS_WOE_BIT |
368 | or a3, a3, a2 | 368 | or a3, a3, a2 |
369 | rsr a0, exccause | 369 | rsr a0, exccause |
@@ -444,6 +444,8 @@ common_exception_return: | |||
444 | 1: l32i a3, a1, PT_PS | 444 | 1: l32i a3, a1, PT_PS |
445 | _bbci.l a3, PS_UM_BIT, 4f | 445 | _bbci.l a3, PS_UM_BIT, 4f |
446 | 446 | ||
447 | rsil a2, 0 | ||
448 | |||
447 | /* Specific to a user exception exit: | 449 | /* Specific to a user exception exit: |
448 | * We need to check some flags for signal handling and rescheduling, | 450 | * We need to check some flags for signal handling and rescheduling, |
449 | * and have to restore WB and WS, extra states, and all registers | 451 | * and have to restore WB and WS, extra states, and all registers |
@@ -684,51 +686,19 @@ common_exception_exit: | |||
684 | 686 | ||
685 | l32i a0, a1, PT_DEPC | 687 | l32i a0, a1, PT_DEPC |
686 | l32i a3, a1, PT_AREG3 | 688 | l32i a3, a1, PT_AREG3 |
687 | _bltui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f | ||
688 | |||
689 | wsr a0, depc | ||
690 | l32i a2, a1, PT_AREG2 | 689 | l32i a2, a1, PT_AREG2 |
691 | l32i a0, a1, PT_AREG0 | 690 | _bgeui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f |
692 | l32i a1, a1, PT_AREG1 | ||
693 | rfde | ||
694 | 691 | ||
695 | 1: | ||
696 | /* Restore a0...a3 and return */ | 692 | /* Restore a0...a3 and return */ |
697 | 693 | ||
698 | rsr a0, ps | ||
699 | extui a2, a0, PS_INTLEVEL_SHIFT, PS_INTLEVEL_WIDTH | ||
700 | movi a0, 2f | ||
701 | slli a2, a2, 4 | ||
702 | add a0, a2, a0 | ||
703 | l32i a2, a1, PT_AREG2 | ||
704 | jx a0 | ||
705 | |||
706 | .macro irq_exit_level level | ||
707 | .align 16 | ||
708 | .if XCHAL_EXCM_LEVEL >= \level | ||
709 | l32i a0, a1, PT_PC | ||
710 | wsr a0, epc\level | ||
711 | l32i a0, a1, PT_AREG0 | 694 | l32i a0, a1, PT_AREG0 |
712 | l32i a1, a1, PT_AREG1 | 695 | l32i a1, a1, PT_AREG1 |
713 | rfi \level | 696 | rfe |
714 | .endif | ||
715 | .endm | ||
716 | 697 | ||
717 | .align 16 | 698 | 1: wsr a0, depc |
718 | 2: | ||
719 | l32i a0, a1, PT_AREG0 | 699 | l32i a0, a1, PT_AREG0 |
720 | l32i a1, a1, PT_AREG1 | 700 | l32i a1, a1, PT_AREG1 |
721 | rfe | 701 | rfde |
722 | |||
723 | .align 16 | ||
724 | /* no rfi for level-1 irq, handled by rfe above*/ | ||
725 | nop | ||
726 | |||
727 | irq_exit_level 2 | ||
728 | irq_exit_level 3 | ||
729 | irq_exit_level 4 | ||
730 | irq_exit_level 5 | ||
731 | irq_exit_level 6 | ||
732 | 702 | ||
733 | ENDPROC(kernel_exception) | 703 | ENDPROC(kernel_exception) |
734 | 704 | ||