aboutsummaryrefslogtreecommitdiffstats
path: root/arch/xtensa/kernel/traps.c
diff options
context:
space:
mode:
authorMax Filippov <jcmvbkbc@gmail.com>2013-10-16 18:42:26 -0400
committerChris Zankel <chris@zankel.net>2014-01-14 13:19:58 -0500
commitf615136c06a791364f5afa8b8ba965315a6440f1 (patch)
treed9ced4cfdfd13438ce23384fbd64006bb74fd8b6 /arch/xtensa/kernel/traps.c
parent26a8e96a8b37e8070fa9dcb1b7490cf4d4492d50 (diff)
xtensa: add SMP support
This is largely based on SMP code from the xtensa-2.6.29-smp tree by Piet Delaney, Marc Gauthier, Joe Taylor, Christian Zankel (and possibly other Tensilica folks). Signed-off-by: Max Filippov <jcmvbkbc@gmail.com> Signed-off-by: Chris Zankel <chris@zankel.net>
Diffstat (limited to 'arch/xtensa/kernel/traps.c')
-rw-r--r--arch/xtensa/kernel/traps.c33
1 files changed, 25 insertions, 8 deletions
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c
index 3dbe8648df1f..3c0ff5746fe2 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
@@ -313,17 +313,31 @@ do_debug(struct pt_regs *regs)
313} 313}
314 314
315 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
316/* Set exception C handler - for temporary use when probing exceptions */ 324/* Set exception C handler - for temporary use when probing exceptions */
317 325
318void * __init trap_set_handler(int cause, void *handler) 326void * __init trap_set_handler(int cause, void *handler)
319{ 327{
320 unsigned long *entry = &exc_table[EXC_TABLE_DEFAULT / 4 + cause]; 328 void *previous = (void *)per_cpu(exc_table, 0)[
321 void *previous = (void *)*entry; 329 EXC_TABLE_DEFAULT / 4 + cause];
322 *entry = (unsigned long)handler; 330 set_handler(EXC_TABLE_DEFAULT / 4 + cause, handler);
323 return previous; 331 return previous;
324} 332}
325 333
326 334
335static void __init 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
327/* 341/*
328 * Initialize dispatch tables. 342 * Initialize dispatch tables.
329 * 343 *
@@ -337,8 +351,6 @@ void * __init trap_set_handler(int cause, void *handler)
337 * See vectors.S for more details. 351 * See vectors.S for more details.
338 */ 352 */
339 353
340#define set_handler(idx,handler) (exc_table[idx] = (unsigned long) (handler))
341
342void __init trap_init(void) 354void __init trap_init(void)
343{ 355{
344 int i; 356 int i;
@@ -368,10 +380,15 @@ void __init trap_init(void)
368 } 380 }
369 381
370 /* 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}
371 385
372 i = (unsigned long)exc_table; 386#ifdef CONFIG_SMP
373 __asm__ __volatile__("wsr %0, excsave1\n" : : "a" (i)); 387void __init secondary_trap_init(void)
388{
389 trap_init_excsave();
374} 390}
391#endif
375 392
376/* 393/*
377 * 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.