|
@@ -838,6 +838,18 @@ STD_ENTRY(interrupt_return)
|
|
|
.Lresume_userspace:
|
|
|
FEEDBACK_REENTER(interrupt_return)
|
|
|
|
|
|
+ /*
|
|
|
+ * Use r33 to hold whether we have already loaded the callee-saves
|
|
|
+ * into ptregs. We don't want to do it twice in this loop, since
|
|
|
+ * then we'd clobber whatever changes are made by ptrace, etc.
|
|
|
+ * Get base of stack in r32.
|
|
|
+ */
|
|
|
+ {
|
|
|
+ GET_THREAD_INFO(r32)
|
|
|
+ movei r33, 0
|
|
|
+ }
|
|
|
+
|
|
|
+.Lretry_work_pending:
|
|
|
/*
|
|
|
* Disable interrupts so as to make sure we don't
|
|
|
* miss an interrupt that sets any of the thread flags (like
|
|
@@ -848,9 +860,6 @@ STD_ENTRY(interrupt_return)
|
|
|
IRQ_DISABLE(r20, r21)
|
|
|
TRACE_IRQS_OFF /* Note: clobbers registers r0-r29 */
|
|
|
|
|
|
- /* Get base of stack in r32; note r30/31 are used as arguments here. */
|
|
|
- GET_THREAD_INFO(r32)
|
|
|
-
|
|
|
|
|
|
/* Check to see if there is any work to do before returning to user. */
|
|
|
{
|
|
@@ -866,16 +875,18 @@ STD_ENTRY(interrupt_return)
|
|
|
|
|
|
/*
|
|
|
* Make sure we have all the registers saved for signal
|
|
|
- * handling or single-step. Call out to C code to figure out
|
|
|
- * exactly what we need to do for each flag bit, then if
|
|
|
- * necessary, reload the flags and recheck.
|
|
|
+ * handling, notify-resume, or single-step. Call out to C
|
|
|
+ * code to figure out exactly what we need to do for each flag bit,
|
|
|
+ * then if necessary, reload the flags and recheck.
|
|
|
*/
|
|
|
- push_extra_callee_saves r0
|
|
|
{
|
|
|
PTREGS_PTR(r0, PTREGS_OFFSET_BASE)
|
|
|
- jal do_work_pending
|
|
|
+ bnz r33, 1f
|
|
|
}
|
|
|
- bnz r0, .Lresume_userspace
|
|
|
+ push_extra_callee_saves r0
|
|
|
+ movei r33, 1
|
|
|
+1: jal do_work_pending
|
|
|
+ bnz r0, .Lretry_work_pending
|
|
|
|
|
|
/*
|
|
|
* In the NMI case we
|
|
@@ -1180,10 +1191,12 @@ handle_syscall:
|
|
|
add r20, r20, tp
|
|
|
lw r21, r20
|
|
|
addi r21, r21, 1
|
|
|
- sw r20, r21
|
|
|
+ {
|
|
|
+ sw r20, r21
|
|
|
+ GET_THREAD_INFO(r31)
|
|
|
+ }
|
|
|
|
|
|
/* Trace syscalls, if requested. */
|
|
|
- GET_THREAD_INFO(r31)
|
|
|
addi r31, r31, THREAD_INFO_FLAGS_OFFSET
|
|
|
lw r30, r31
|
|
|
andi r30, r30, _TIF_SYSCALL_TRACE
|
|
@@ -1362,7 +1375,10 @@ handle_ill:
|
|
|
3:
|
|
|
/* set PC and continue */
|
|
|
lw r26, r24
|
|
|
- sw r28, r26
|
|
|
+ {
|
|
|
+ sw r28, r26
|
|
|
+ GET_THREAD_INFO(r0)
|
|
|
+ }
|
|
|
|
|
|
/*
|
|
|
* Clear TIF_SINGLESTEP to prevent recursion if we execute an ill.
|
|
@@ -1370,7 +1386,6 @@ handle_ill:
|
|
|
* need to clear it here and can't really impose on all other arches.
|
|
|
* So what's another write between friends?
|
|
|
*/
|
|
|
- GET_THREAD_INFO(r0)
|
|
|
|
|
|
addi r1, r0, THREAD_INFO_FLAGS_OFFSET
|
|
|
{
|