diff options
author | Max Filippov <jcmvbkbc@gmail.com> | 2013-10-16 18:42:26 -0400 |
---|---|---|
committer | Chris Zankel <chris@zankel.net> | 2014-01-14 13:19:58 -0500 |
commit | f615136c06a791364f5afa8b8ba965315a6440f1 (patch) | |
tree | d9ced4cfdfd13438ce23384fbd64006bb74fd8b6 /arch/xtensa/kernel/traps.c | |
parent | 26a8e96a8b37e8070fa9dcb1b7490cf4d4492d50 (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.c | 33 |
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 | ||
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 | ||
@@ -313,17 +313,31 @@ do_debug(struct pt_regs *regs) | |||
313 | } | 313 | } |
314 | 314 | ||
315 | 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 | |||
316 | /* Set exception C handler - for temporary use when probing exceptions */ | 324 | /* Set exception C handler - for temporary use when probing exceptions */ |
317 | 325 | ||
318 | void * __init trap_set_handler(int cause, void *handler) | 326 | void * __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 | ||
335 | static 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 | |||
342 | void __init trap_init(void) | 354 | void __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)); | 387 | void __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. |