aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Zankel <chris@zankel.net>2008-01-22 03:45:25 -0500
committerChris Zankel <chris@zankel.net>2008-02-13 20:43:54 -0500
commite1088430626b2ec4cd64f2fb7d9fd7c6df5d5824 (patch)
treece563e0400ad22974ae65e25d2534432f5d4e76b
parent9f8fcf38e8928cccf8c7b32668d146e457f2ccf2 (diff)
[XTENSA] Fix register corruption for certain processor configurations
For processor configurations that have optional registers (compiler-used but non-coprocessor), user space registers might get corrupted when there are only 4 registers in the current window-frame, ie. register a4 belongs to the oldest frame in the register file. Signed-off-by: Chris Zankel <chris@zankel.net>
-rw-r--r--arch/xtensa/kernel/entry.S44
1 files changed, 15 insertions, 29 deletions
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index 24770b6a5e4c..dfd35dcc1cb5 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -395,55 +395,49 @@ common_exception_return:
395 /* Jump if we are returning from kernel exceptions. */ 395 /* Jump if we are returning from kernel exceptions. */
396 396
3971: l32i a3, a1, PT_PS 3971: l32i a3, a1, PT_PS
398 _bbsi.l a3, PS_UM_BIT, 2f 398 _bbci.l a3, PS_UM_BIT, 4f
399 j kernel_exception_exit
400 399
401 /* Specific to a user exception exit: 400 /* Specific to a user exception exit:
402 * We need to check some flags for signal handling and rescheduling, 401 * We need to check some flags for signal handling and rescheduling,
403 * and have to restore WB and WS, extra states, and all registers 402 * and have to restore WB and WS, extra states, and all registers
404 * in the register file that were in use in the user task. 403 * in the register file that were in use in the user task.
405 */ 404 * Note that we don't disable interrupts here.
406
4072: wsr a3, PS /* disable interrupts */
408
409 /* Check for signals (keep interrupts disabled while we read TI_FLAGS)
410 * Note: PS.INTLEVEL = 0, PS.EXCM = 1
411 */ 405 */
412 406
413 GET_THREAD_INFO(a2,a1) 407 GET_THREAD_INFO(a2,a1)
414 l32i a4, a2, TI_FLAGS 408 l32i a4, a2, TI_FLAGS
415 409
416 /* Enable interrupts again.
417 * Note: When we get here, we certainly have handled any interrupts.
418 * (Hint: There is only one user exception frame on stack)
419 */
420
421 movi a3, 1 << PS_WOE_BIT
422
423 _bbsi.l a4, TIF_NEED_RESCHED, 3f 410 _bbsi.l a4, TIF_NEED_RESCHED, 3f
424 _bbci.l a4, TIF_SIGPENDING, 4f 411 _bbci.l a4, TIF_SIGPENDING, 4f
425 412
426 l32i a4, a1, PT_DEPC 413 l32i a4, a1, PT_DEPC
427 bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 4f 414 bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 4f
428 /* Reenable interrupts and call do_signal() */
429 415
430 wsr a3, PS 416 /* Call do_signal() */
417
431 movi a4, do_signal # int do_signal(struct pt_regs*, sigset_t*) 418 movi a4, do_signal # int do_signal(struct pt_regs*, sigset_t*)
432 mov a6, a1 419 mov a6, a1
433 movi a7, 0 420 movi a7, 0
434 callx4 a4 421 callx4 a4
435 j 1b 422 j 1b
436 423
4373: /* Reenable interrupts and reschedule */ 4243: /* Reschedule */
438 425
439 wsr a3, PS
440 movi a4, schedule # void schedule (void) 426 movi a4, schedule # void schedule (void)
441 callx4 a4 427 callx4 a4
442 j 1b 428 j 1b
443 429
444 /* Restore the state of the task and return from the exception. */ 4304: /* Restore optional registers. */
431
432 load_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT
445 433
4464: /* a2 holds GET_CURRENT(a2,a1) */ 434 wsr a3, PS /* disable interrupts */
435
436 _bbci.l a3, PS_UM_BIT, kernel_exception_exit
437
438user_exception_exit:
439
440 /* Restore the state of the task and return from the exception. */
447 441
448 /* Switch to the user thread WINDOWBASE. Save SP temporarily in DEPC */ 442 /* Switch to the user thread WINDOWBASE. Save SP temporarily in DEPC */
449 443
@@ -509,10 +503,6 @@ common_exception_return:
509 503
510kernel_exception_exit: 504kernel_exception_exit:
511 505
512 /* Disable interrupts (a3 holds PT_PS) */
513
514 wsr a3, PS
515
516#ifdef PREEMPTIBLE_KERNEL 506#ifdef PREEMPTIBLE_KERNEL
517 507
518#ifdef CONFIG_PREEMPT 508#ifdef CONFIG_PREEMPT
@@ -591,10 +581,6 @@ kernel_exception_exit:
591 581
592common_exception_exit: 582common_exception_exit:
593 583
594 /* Restore optional registers. */
595
596 load_xtregs_opt a1 a3 a4 a5 a6 a7 PT_XTREGS_OPT
597
598 /* Restore address registers. */ 584 /* Restore address registers. */
599 585
600 _bbsi.l a2, 1, 1f 586 _bbsi.l a2, 1, 1f