diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-26 19:53:12 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-26 19:53:12 -0800 |
commit | 9626357371b519f2b955fef399647181034a77fe (patch) | |
tree | 232abd741e773c7d3afb4ba6b02fcba03b82214d /arch/xtensa/kernel/traps.c | |
parent | 2b37e9a28afbd11f899738e912fb4a617a74b462 (diff) | |
parent | 9cf81c759b7db1db593b2ca60b74ec350d5f9205 (diff) |
Merge tag 'xtensa-next-20130225' of git://github.com/czankel/xtensa-linux
Pull xtensa update from Chris Zankel:
"Added features:
- add support for thread local storage (TLS)
- add accept4 and finit_module syscalls
- support medium-priority interrupts
- add support for dc232c processor variant
- support file-base simulated disk for ISS simulator
Bug fixes:
- fix return values returned by the str[n]cmp functions
- avoid mmap cache aliasing
- fix handling of 'windowed registers' in ptrace"
* tag 'xtensa-next-20130225' of git://github.com/czankel/xtensa-linux:
xtensa: add accept4 syscall
xtensa: add support for TLS
xtensa: add missing include asm/uaccess.h to checksum.h
xtensa: do not enable GENERIC_GPIO by default
xtensa: complete ptrace handling of register windows
xtensa: add support for oprofile
xtensa: move spill_registers to traps.h
xtensa: ISS: add host file-based simulated disk
xtensa: fix str[n]cmp return value
xtensa: avoid mmap cache aliasing
xtensa: add finit_module syscall
xtensa: pull signal definitions from signal-defs.h
xtensa: fix ipc_parse_version selection
xtensa: dispatch medium-priority interrupts
xtensa: Add config files for Diamond 233L - Rev C processor variant
xtensa: use new common dtc rule
xtensa: rename prom_update_property to of_update_property
Diffstat (limited to 'arch/xtensa/kernel/traps.c')
-rw-r--r-- | arch/xtensa/kernel/traps.c | 74 |
1 files changed, 38 insertions, 36 deletions
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c index ded955d45155..923db5c15278 100644 --- a/arch/xtensa/kernel/traps.c +++ b/arch/xtensa/kernel/traps.c @@ -37,6 +37,7 @@ #include <asm/uaccess.h> #include <asm/pgtable.h> #include <asm/processor.h> +#include <asm/traps.h> #ifdef CONFIG_KGDB extern int gdb_enter; @@ -193,28 +194,49 @@ void do_multihit(struct pt_regs *regs, unsigned long exccause) } /* - * Level-1 interrupt. - * We currently have no priority encoding. + * IRQ handler. + * PS.INTLEVEL is the current IRQ priority level. */ -unsigned long ignored_level1_interrupts; extern void do_IRQ(int, struct pt_regs *); -void do_interrupt (struct pt_regs *regs) +void do_interrupt(struct pt_regs *regs) { - unsigned long intread = get_sr (interrupt); - unsigned long intenable = get_sr (intenable); - int i, mask; - - /* Handle all interrupts (no priorities). - * (Clear the interrupt before processing, in case it's - * edge-triggered or software-generated) - */ + static const unsigned int_level_mask[] = { + 0, + XCHAL_INTLEVEL1_MASK, + XCHAL_INTLEVEL2_MASK, + XCHAL_INTLEVEL3_MASK, + XCHAL_INTLEVEL4_MASK, + XCHAL_INTLEVEL5_MASK, + XCHAL_INTLEVEL6_MASK, + XCHAL_INTLEVEL7_MASK, + }; + unsigned level = get_sr(ps) & PS_INTLEVEL_MASK; + + if (WARN_ON_ONCE(level >= ARRAY_SIZE(int_level_mask))) + return; - for (i=0, mask = 1; i < XCHAL_NUM_INTERRUPTS; i++, mask <<= 1) { - if (mask & (intread & intenable)) { - set_sr (mask, intclear); - do_IRQ (i,regs); + for (;;) { + unsigned intread = get_sr(interrupt); + unsigned intenable = get_sr(intenable); + unsigned int_at_level = intread & intenable & + int_level_mask[level]; + + if (!int_at_level) + return; + + /* + * Clear the interrupt before processing, in case it's + * edge-triggered or software-generated + */ + while (int_at_level) { + unsigned i = __ffs(int_at_level); + unsigned mask = 1 << i; + + int_at_level ^= mask; + set_sr(mask, intclear); + do_IRQ(i, regs); } } } @@ -392,26 +414,6 @@ static __always_inline unsigned long *stack_pointer(struct task_struct *task) return sp; } -static inline void spill_registers(void) -{ - unsigned int a0, ps; - - __asm__ __volatile__ ( - "movi a14, " __stringify(PS_EXCM_BIT | 1) "\n\t" - "mov a12, a0\n\t" - "rsr a13, sar\n\t" - "xsr a14, ps\n\t" - "movi a0, _spill_registers\n\t" - "rsync\n\t" - "callx0 a0\n\t" - "mov a0, a12\n\t" - "wsr a13, sar\n\t" - "wsr a14, ps\n\t" - :: "a" (&a0), "a" (&ps) - : "a2", "a3", "a4", "a7", "a11", "a12", "a13", "a14", "a15", - "memory"); -} - void show_trace(struct task_struct *task, unsigned long *sp) { unsigned long a0, a1, pc; |