diff options
Diffstat (limited to 'arch/xtensa/kernel/traps.c')
| -rw-r--r-- | arch/xtensa/kernel/traps.c | 56 | 
1 files changed, 34 insertions, 22 deletions
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c index 3e8a05c874c..eebbfd8c26f 100644 --- a/arch/xtensa/kernel/traps.c +++ b/arch/xtensa/kernel/traps.c @@ -157,7 +157,7 @@ COPROCESSOR(7),   * 2. it is a temporary memory buffer for the exception handlers.   */ -unsigned long exc_table[EXC_TABLE_SIZE/4]; +DEFINE_PER_CPU(unsigned long, exc_table[EXC_TABLE_SIZE/4]);  void die(const char*, struct pt_regs*, long); @@ -212,6 +212,9 @@ void do_interrupt(struct pt_regs *regs)  		XCHAL_INTLEVEL6_MASK,  		XCHAL_INTLEVEL7_MASK,  	}; +	struct pt_regs *old_regs = set_irq_regs(regs); + +	irq_enter();  	for (;;) {  		unsigned intread = get_sr(interrupt); @@ -227,21 +230,13 @@ void do_interrupt(struct pt_regs *regs)  		}  		if (level == 0) -			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); -		} +			break; + +		do_IRQ(__ffs(int_at_level), regs);  	} + +	irq_exit(); +	set_irq_regs(old_regs);  }  /* @@ -318,17 +313,31 @@ do_debug(struct pt_regs *regs)  } +static void set_handler(int idx, void *handler) +{ +	unsigned int cpu; + +	for_each_possible_cpu(cpu) +		per_cpu(exc_table, cpu)[idx] = (unsigned long)handler; +} +  /* Set exception C handler - for temporary use when probing exceptions */  void * __init trap_set_handler(int cause, void *handler)  { -	unsigned long *entry = &exc_table[EXC_TABLE_DEFAULT / 4 + cause]; -	void *previous = (void *)*entry; -	*entry = (unsigned long)handler; +	void *previous = (void *)per_cpu(exc_table, 0)[ +		EXC_TABLE_DEFAULT / 4 + cause]; +	set_handler(EXC_TABLE_DEFAULT / 4 + cause, handler);  	return previous;  } +static void trap_init_excsave(void) +{ +	unsigned long excsave1 = (unsigned long)this_cpu_ptr(exc_table); +	__asm__ __volatile__("wsr  %0, excsave1\n" : : "a" (excsave1)); +} +  /*   * Initialize dispatch tables.   * @@ -342,8 +351,6 @@ void * __init trap_set_handler(int cause, void *handler)   * See vectors.S for more details.   */ -#define set_handler(idx,handler) (exc_table[idx] = (unsigned long) (handler)) -  void __init trap_init(void)  {  	int i; @@ -373,10 +380,15 @@ void __init trap_init(void)  	}  	/* Initialize EXCSAVE_1 to hold the address of the exception table. */ +	trap_init_excsave(); +} -	i = (unsigned long)exc_table; -	__asm__ __volatile__("wsr  %0, excsave1\n" : : "a" (i)); +#ifdef CONFIG_SMP +void secondary_trap_init(void) +{ +	trap_init_excsave();  } +#endif  /*   * This function dumps the current valid window frame and other base registers.  | 
