diff options
author | Marc Gauthier <marc@tensilica.com> | 2013-01-04 19:57:17 -0500 |
---|---|---|
committer | Chris Zankel <chris@zankel.net> | 2013-02-23 22:12:52 -0500 |
commit | 2d1c645cc50b8f5a718b24bad9eb3931e7105d12 (patch) | |
tree | c385e5064cee10f79b9c359ddd99bd5d1b9f838a /arch/xtensa/kernel/entry.S | |
parent | d0b73b488c55df905ea8faaad079f8535629ed26 (diff) |
xtensa: dispatch medium-priority interrupts
Add support for dispatching medium-priority interrupts, that is,
interrupts of priority levels 2 to EXCM_LEVEL. IRQ handling may be
preempted by higher priority IRQ.
Signed-off-by: Marc Gauthier <marc@tensilica.com>
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 | 55 |
1 files changed, 44 insertions, 11 deletions
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index 3777fec85e7c..0ace2acbbad0 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S | |||
@@ -7,7 +7,7 @@ | |||
7 | * License. See the file "COPYING" in the main directory of this archive | 7 | * License. See the file "COPYING" in the main directory of this archive |
8 | * for more details. | 8 | * for more details. |
9 | * | 9 | * |
10 | * Copyright (C) 2004-2007 by Tensilica Inc. | 10 | * Copyright (C) 2004 - 2008 by Tensilica Inc. |
11 | * | 11 | * |
12 | * Chris Zankel <chris@zankel.net> | 12 | * Chris Zankel <chris@zankel.net> |
13 | * | 13 | * |
@@ -349,15 +349,16 @@ common_exception: | |||
349 | * so we can allow exceptions and interrupts (*) again. | 349 | * so we can allow exceptions and interrupts (*) again. |
350 | * Set PS(EXCM = 0, UM = 0, RING = 0, OWB = 0, WOE = 1, INTLEVEL = X) | 350 | * Set PS(EXCM = 0, UM = 0, RING = 0, OWB = 0, WOE = 1, INTLEVEL = X) |
351 | * | 351 | * |
352 | * (*) We only allow interrupts if PS.INTLEVEL was not set to 1 before | 352 | * (*) We only allow interrupts of higher priority than current IRQ |
353 | * (interrupts disabled) and if this exception is not an interrupt. | ||
354 | */ | 353 | */ |
355 | 354 | ||
356 | rsr a3, ps | 355 | rsr a3, ps |
357 | addi a0, a0, -4 | 356 | addi a0, a0, -4 |
358 | movi a2, 1 | 357 | movi a2, 1 |
359 | extui a3, a3, 0, 1 # a3 = PS.INTLEVEL[0] | 358 | extui a3, a3, PS_INTLEVEL_SHIFT, PS_INTLEVEL_WIDTH |
360 | moveqz a3, a2, a0 # a3 = 1 iff interrupt exception | 359 | # a3 = PS.INTLEVEL |
360 | movnez a2, a3, a3 # a2 = 1: level-1, > 1: high priority | ||
361 | moveqz a3, a2, a0 # a3 = IRQ level iff interrupt | ||
361 | movi a2, 1 << PS_WOE_BIT | 362 | movi a2, 1 << PS_WOE_BIT |
362 | or a3, a3, a2 | 363 | or a3, a3, a2 |
363 | rsr a0, exccause | 364 | rsr a0, exccause |
@@ -641,19 +642,51 @@ common_exception_exit: | |||
641 | 642 | ||
642 | l32i a0, a1, PT_DEPC | 643 | l32i a0, a1, PT_DEPC |
643 | l32i a3, a1, PT_AREG3 | 644 | l32i a3, a1, PT_AREG3 |
645 | _bltui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f | ||
646 | |||
647 | wsr a0, depc | ||
644 | l32i a2, a1, PT_AREG2 | 648 | l32i a2, a1, PT_AREG2 |
645 | _bgeui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f | 649 | l32i a0, a1, PT_AREG0 |
650 | l32i a1, a1, PT_AREG1 | ||
651 | rfde | ||
646 | 652 | ||
653 | 1: | ||
647 | /* Restore a0...a3 and return */ | 654 | /* Restore a0...a3 and return */ |
648 | 655 | ||
656 | rsr a0, ps | ||
657 | extui a2, a0, PS_INTLEVEL_SHIFT, PS_INTLEVEL_WIDTH | ||
658 | movi a0, 2f | ||
659 | slli a2, a2, 4 | ||
660 | add a0, a2, a0 | ||
661 | l32i a2, a1, PT_AREG2 | ||
662 | jx a0 | ||
663 | |||
664 | .macro irq_exit_level level | ||
665 | .align 16 | ||
666 | .if XCHAL_EXCM_LEVEL >= \level | ||
667 | l32i a0, a1, PT_PC | ||
668 | wsr a0, epc\level | ||
649 | l32i a0, a1, PT_AREG0 | 669 | l32i a0, a1, PT_AREG0 |
650 | l32i a1, a1, PT_AREG1 | 670 | l32i a1, a1, PT_AREG1 |
651 | rfe | 671 | rfi \level |
672 | .endif | ||
673 | .endm | ||
652 | 674 | ||
653 | 1: wsr a0, depc | 675 | .align 16 |
676 | 2: | ||
654 | l32i a0, a1, PT_AREG0 | 677 | l32i a0, a1, PT_AREG0 |
655 | l32i a1, a1, PT_AREG1 | 678 | l32i a1, a1, PT_AREG1 |
656 | rfde | 679 | rfe |
680 | |||
681 | .align 16 | ||
682 | /* no rfi for level-1 irq, handled by rfe above*/ | ||
683 | nop | ||
684 | |||
685 | irq_exit_level 2 | ||
686 | irq_exit_level 3 | ||
687 | irq_exit_level 4 | ||
688 | irq_exit_level 5 | ||
689 | irq_exit_level 6 | ||
657 | 690 | ||
658 | ENDPROC(kernel_exception) | 691 | ENDPROC(kernel_exception) |
659 | 692 | ||
@@ -753,7 +786,7 @@ ENTRY(unrecoverable_exception) | |||
753 | wsr a1, windowbase | 786 | wsr a1, windowbase |
754 | rsync | 787 | rsync |
755 | 788 | ||
756 | movi a1, (1 << PS_WOE_BIT) | 1 | 789 | movi a1, (1 << PS_WOE_BIT) | LOCKLEVEL |
757 | wsr a1, ps | 790 | wsr a1, ps |
758 | rsync | 791 | rsync |
759 | 792 | ||
@@ -1474,7 +1507,7 @@ ENTRY(_spill_registers) | |||
1474 | l32i a1, a3, EXC_TABLE_KSTK | 1507 | l32i a1, a3, EXC_TABLE_KSTK |
1475 | wsr a3, excsave1 | 1508 | wsr a3, excsave1 |
1476 | 1509 | ||
1477 | movi a4, (1 << PS_WOE_BIT) | 1 | 1510 | movi a4, (1 << PS_WOE_BIT) | LOCKLEVEL |
1478 | wsr a4, ps | 1511 | wsr a4, ps |
1479 | rsync | 1512 | rsync |
1480 | 1513 | ||