aboutsummaryrefslogtreecommitdiffstats
path: root/arch/xtensa/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/xtensa/kernel/traps.c')
-rw-r--r--arch/xtensa/kernel/traps.c56
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
160unsigned long exc_table[EXC_TABLE_SIZE/4]; 160DEFINE_PER_CPU(unsigned long, exc_table[EXC_TABLE_SIZE/4]);
161 161
162void die(const char*, struct pt_regs*, long); 162void 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
316static 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
323void * __init trap_set_handler(int cause, void *handler) 326void * __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
335static 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
347void __init trap_init(void) 354void __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)); 387void 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.