diff options
author | Max Filippov <jcmvbkbc@gmail.com> | 2013-08-26 07:12:58 -0400 |
---|---|---|
committer | Chris Zankel <chris@zankel.net> | 2013-09-06 12:46:35 -0400 |
commit | aea8e7c80ab50305257838bfb04f91a76cf9fec7 (patch) | |
tree | 9fc08e6ec839f35c3f1c27398e6c67ae108594dc | |
parent | 0bc2ba94a65d2cd2ad01004d2d3f94f31c6064bd (diff) |
xtensa: check thread flags atomically on return from user exception
Check pending signals and rescheduling thread flags with interrupts
disabled, and don't enable them if no flags are set. Call
trace_hardirqs_on after thread flags handling, so that rescheduling is
done and hardirqs tracking flag is updated in the correct task context.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Chris Zankel <chris@zankel.net>
-rw-r--r-- | arch/xtensa/kernel/entry.S | 39 |
1 files changed, 21 insertions, 18 deletions
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index 9298742f0fd0..03709ef2f3ce 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S | |||
@@ -423,29 +423,14 @@ common_exception: | |||
423 | .global common_exception_return | 423 | .global common_exception_return |
424 | common_exception_return: | 424 | common_exception_return: |
425 | 425 | ||
426 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
427 | l32i a4, a1, PT_DEPC | ||
428 | /* Double exception means we came here with an exception | ||
429 | * while PS.EXCM was set, i.e. interrupts disabled. | ||
430 | */ | ||
431 | bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f | ||
432 | l32i a4, a1, PT_EXCCAUSE | ||
433 | bnei a4, EXCCAUSE_LEVEL1_INTERRUPT, 1f | ||
434 | /* We came here with an interrupt means interrupts were enabled | ||
435 | * and we'll reenable them on return. | ||
436 | */ | ||
437 | movi a4, trace_hardirqs_on | ||
438 | callx4 a4 | ||
439 | 1: | 426 | 1: |
440 | #endif | 427 | rsil a2, LOCKLEVEL |
441 | 428 | ||
442 | /* Jump if we are returning from kernel exceptions. */ | 429 | /* Jump if we are returning from kernel exceptions. */ |
443 | 430 | ||
444 | 1: l32i a3, a1, PT_PS | 431 | l32i a3, a1, PT_PS |
445 | _bbci.l a3, PS_UM_BIT, 4f | 432 | _bbci.l a3, PS_UM_BIT, 4f |
446 | 433 | ||
447 | rsil a2, 0 | ||
448 | |||
449 | /* Specific to a user exception exit: | 434 | /* Specific to a user exception exit: |
450 | * We need to check some flags for signal handling and rescheduling, | 435 | * We need to check some flags for signal handling and rescheduling, |
451 | * and have to restore WB and WS, extra states, and all registers | 436 | * and have to restore WB and WS, extra states, and all registers |
@@ -465,6 +450,7 @@ common_exception_return: | |||
465 | 450 | ||
466 | /* Call do_signal() */ | 451 | /* Call do_signal() */ |
467 | 452 | ||
453 | rsil a2, 0 | ||
468 | movi a4, do_notify_resume # int do_notify_resume(struct pt_regs*) | 454 | movi a4, do_notify_resume # int do_notify_resume(struct pt_regs*) |
469 | mov a6, a1 | 455 | mov a6, a1 |
470 | callx4 a4 | 456 | callx4 a4 |
@@ -472,6 +458,7 @@ common_exception_return: | |||
472 | 458 | ||
473 | 3: /* Reschedule */ | 459 | 3: /* Reschedule */ |
474 | 460 | ||
461 | rsil a2, 0 | ||
475 | movi a4, schedule # void schedule (void) | 462 | movi a4, schedule # void schedule (void) |
476 | callx4 a4 | 463 | callx4 a4 |
477 | j 1b | 464 | j 1b |
@@ -483,7 +470,23 @@ common_exception_return: | |||
483 | movi a4, check_tlb_sanity | 470 | movi a4, check_tlb_sanity |
484 | callx4 a4 | 471 | callx4 a4 |
485 | #endif | 472 | #endif |
486 | 4: /* Restore optional registers. */ | 473 | 4: |
474 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
475 | l32i a4, a1, PT_DEPC | ||
476 | /* Double exception means we came here with an exception | ||
477 | * while PS.EXCM was set, i.e. interrupts disabled. | ||
478 | */ | ||
479 | bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f | ||
480 | l32i a4, a1, PT_EXCCAUSE | ||
481 | bnei a4, EXCCAUSE_LEVEL1_INTERRUPT, 1f | ||
482 | /* We came here with an interrupt means interrupts were enabled | ||
483 | * and we'll reenable them on return. | ||
484 | */ | ||
485 | movi a4, trace_hardirqs_on | ||
486 | callx4 a4 | ||
487 | 1: | ||
488 | #endif | ||
489 | /* Restore optional registers. */ | ||
487 | 490 | ||
488 | load_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT | 491 | load_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT |
489 | 492 | ||