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 3e8a05c874cd..eebbfd8c26fc 100644 --- a/arch/xtensa/kernel/traps.c +++ b/arch/xtensa/kernel/traps.c | |||
@@ -157,7 +157,7 @@ COPROCESSOR(7), | |||
157 | * 2. it is a temporary memory buffer for the exception handlers. | 157 | * 2. it is a temporary memory buffer for the exception handlers. |
158 | */ | 158 | */ |
159 | 159 | ||
160 | unsigned long exc_table[EXC_TABLE_SIZE/4]; | 160 | DEFINE_PER_CPU(unsigned long, exc_table[EXC_TABLE_SIZE/4]); |
161 | 161 | ||
162 | void die(const char*, struct pt_regs*, long); | 162 | void die(const char*, struct pt_regs*, long); |
163 | 163 | ||
@@ -212,6 +212,9 @@ void do_interrupt(struct pt_regs *regs) | |||
212 | XCHAL_INTLEVEL6_MASK, | 212 | XCHAL_INTLEVEL6_MASK, |
213 | XCHAL_INTLEVEL7_MASK, | 213 | XCHAL_INTLEVEL7_MASK, |
214 | }; | 214 | }; |
215 | struct pt_regs *old_regs = set_irq_regs(regs); | ||
216 | |||
217 | irq_enter(); | ||
215 | 218 | ||
216 | for (;;) { | 219 | for (;;) { |
217 | unsigned intread = get_sr(interrupt); | 220 | unsigned intread = get_sr(interrupt); |
@@ -227,21 +230,13 @@ void do_interrupt(struct pt_regs *regs) | |||
227 | } | 230 | } |
228 | 231 | ||
229 | if (level == 0) | 232 | if (level == 0) |
230 | return; | 233 | break; |
231 | 234 | ||
232 | /* | 235 | do_IRQ(__ffs(int_at_level), regs); |
233 | * Clear the interrupt before processing, in case it's | ||
234 | * edge-triggered or software-generated | ||
235 | */ | ||
236 | while (int_at_level) { | ||
237 | unsigned i = __ffs(int_at_level); | ||
238 | unsigned mask = 1 << i; | ||
239 | |||
240 | int_at_level ^= mask; | ||
241 | set_sr(mask, intclear); | ||
242 | do_IRQ(i, regs); | ||
243 | } | ||
244 | } | 236 | } |
237 | |||
238 | irq_exit(); | ||
239 | set_irq_regs(old_regs); | ||
245 | } | 240 | } |
246 | 241 | ||
247 | /* | 242 | /* |
@@ -318,17 +313,31 @@ do_debug(struct pt_regs *regs) | |||
318 | } | 313 | } |
319 | 314 | ||
320 | 315 | ||
316 | static void set_handler(int idx, void *handler) | ||
317 | { | ||
318 | unsigned int cpu; | ||
319 | |||
320 | for_each_possible_cpu(cpu) | ||
321 | per_cpu(exc_table, cpu)[idx] = (unsigned long)handler; | ||
322 | } | ||
323 | |||
321 | /* Set exception C handler - for temporary use when probing exceptions */ | 324 | /* Set exception C handler - for temporary use when probing exceptions */ |
322 | 325 | ||
323 | void * __init trap_set_handler(int cause, void *handler) | 326 | void * __init trap_set_handler(int cause, void *handler) |
324 | { | 327 | { |
325 | unsigned long *entry = &exc_table[EXC_TABLE_DEFAULT / 4 + cause]; | 328 | void *previous = (void *)per_cpu(exc_table, 0)[ |
326 | void *previous = (void *)*entry; | 329 | EXC_TABLE_DEFAULT / 4 + cause]; |
327 | *entry = (unsigned long)handler; | 330 | set_handler(EXC_TABLE_DEFAULT / 4 + cause, handler); |
328 | return previous; | 331 | return previous; |
329 | } | 332 | } |
330 | 333 | ||
331 | 334 | ||
335 | static void trap_init_excsave(void) | ||
336 | { | ||
337 | unsigned long excsave1 = (unsigned long)this_cpu_ptr(exc_table); | ||
338 | __asm__ __volatile__("wsr %0, excsave1\n" : : "a" (excsave1)); | ||
339 | } | ||
340 | |||
332 | /* | 341 | /* |
333 | * Initialize dispatch tables. | 342 | * Initialize dispatch tables. |
334 | * | 343 | * |
@@ -342,8 +351,6 @@ void * __init trap_set_handler(int cause, void *handler) | |||
342 | * See vectors.S for more details. | 351 | * See vectors.S for more details. |
343 | */ | 352 | */ |
344 | 353 | ||
345 | #define set_handler(idx,handler) (exc_table[idx] = (unsigned long) (handler)) | ||
346 | |||
347 | void __init trap_init(void) | 354 | void __init trap_init(void) |
348 | { | 355 | { |
349 | int i; | 356 | int i; |
@@ -373,10 +380,15 @@ void __init trap_init(void) | |||
373 | } | 380 | } |
374 | 381 | ||
375 | /* Initialize EXCSAVE_1 to hold the address of the exception table. */ | 382 | /* Initialize EXCSAVE_1 to hold the address of the exception table. */ |
383 | trap_init_excsave(); | ||
384 | } | ||
376 | 385 | ||
377 | i = (unsigned long)exc_table; | 386 | #ifdef CONFIG_SMP |
378 | __asm__ __volatile__("wsr %0, excsave1\n" : : "a" (i)); | 387 | void secondary_trap_init(void) |
388 | { | ||
389 | trap_init_excsave(); | ||
379 | } | 390 | } |
391 | #endif | ||
380 | 392 | ||
381 | /* | 393 | /* |
382 | * This function dumps the current valid window frame and other base registers. | 394 | * This function dumps the current valid window frame and other base registers. |