arch/tile: support TIF_NOTIFY_RESUME
This support is required for CONFIG_KEYS, NFSv4 kernel DNS, etc. The change is slightly more complex than the minimal thing, since I took advantage of having to go into the assembly code to just move a bunch of stuff into C code: specifically, the schedule(), do_async_page_fault(), do_signal(), and single_step_once() support, in addition to the TIF_NOTIFY_RESUME support. Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
This commit is contained in:
@@ -851,14 +851,27 @@ STD_ENTRY(interrupt_return)
|
||||
/* Check to see if there is any work to do before returning to user. */
|
||||
{
|
||||
addi r29, r32, THREAD_INFO_FLAGS_OFFSET
|
||||
moveli r28, lo16(_TIF_ALLWORK_MASK)
|
||||
moveli r1, lo16(_TIF_ALLWORK_MASK)
|
||||
}
|
||||
{
|
||||
lw r29, r29
|
||||
auli r28, r28, ha16(_TIF_ALLWORK_MASK)
|
||||
auli r1, r1, ha16(_TIF_ALLWORK_MASK)
|
||||
}
|
||||
and r28, r29, r28
|
||||
bnz r28, .Lwork_pending
|
||||
and r1, r29, r1
|
||||
bzt r1, .Lrestore_all
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
push_extra_callee_saves r0
|
||||
{
|
||||
PTREGS_PTR(r0, PTREGS_OFFSET_BASE)
|
||||
jal do_work_pending
|
||||
}
|
||||
bnz r0, .Lresume_userspace
|
||||
|
||||
/*
|
||||
* In the NMI case we
|
||||
@@ -1099,99 +1112,6 @@ STD_ENTRY(interrupt_return)
|
||||
pop_reg r50
|
||||
pop_reg r51, sp, PTREGS_OFFSET_REG(29) - PTREGS_OFFSET_REG(51)
|
||||
j .Lcontinue_restore_regs
|
||||
|
||||
.Lwork_pending:
|
||||
/* Mask the reschedule flag */
|
||||
andi r28, r29, _TIF_NEED_RESCHED
|
||||
|
||||
{
|
||||
/*
|
||||
* If the NEED_RESCHED flag is called, we call schedule(), which
|
||||
* may drop this context right here and go do something else.
|
||||
* On return, jump back to .Lresume_userspace and recheck.
|
||||
*/
|
||||
bz r28, .Lasync_tlb
|
||||
|
||||
/* Mask the async-tlb flag */
|
||||
andi r28, r29, _TIF_ASYNC_TLB
|
||||
}
|
||||
|
||||
jal schedule
|
||||
FEEDBACK_REENTER(interrupt_return)
|
||||
|
||||
/* Reload the flags and check again */
|
||||
j .Lresume_userspace
|
||||
|
||||
.Lasync_tlb:
|
||||
{
|
||||
bz r28, .Lneed_sigpending
|
||||
|
||||
/* Mask the sigpending flag */
|
||||
andi r28, r29, _TIF_SIGPENDING
|
||||
}
|
||||
|
||||
PTREGS_PTR(r0, PTREGS_OFFSET_BASE)
|
||||
jal do_async_page_fault
|
||||
FEEDBACK_REENTER(interrupt_return)
|
||||
|
||||
/*
|
||||
* Go restart the "resume userspace" process. We may have
|
||||
* fired a signal, and we need to disable interrupts again.
|
||||
*/
|
||||
j .Lresume_userspace
|
||||
|
||||
.Lneed_sigpending:
|
||||
/*
|
||||
* At this point we are either doing signal handling or single-step,
|
||||
* so either way make sure we have all the registers saved.
|
||||
*/
|
||||
push_extra_callee_saves r0
|
||||
|
||||
{
|
||||
/* If no signal pending, skip to singlestep check */
|
||||
bz r28, .Lneed_singlestep
|
||||
|
||||
/* Mask the singlestep flag */
|
||||
andi r28, r29, _TIF_SINGLESTEP
|
||||
}
|
||||
|
||||
jal do_signal
|
||||
FEEDBACK_REENTER(interrupt_return)
|
||||
|
||||
/* Reload the flags and check again */
|
||||
j .Lresume_userspace
|
||||
|
||||
.Lneed_singlestep:
|
||||
{
|
||||
/* Get a pointer to the EX1 field */
|
||||
PTREGS_PTR(r29, PTREGS_OFFSET_EX1)
|
||||
|
||||
/* If we get here, our bit must be set. */
|
||||
bz r28, .Lwork_confusion
|
||||
}
|
||||
/* If we are in priv mode, don't single step */
|
||||
lw r28, r29
|
||||
andi r28, r28, SPR_EX_CONTEXT_1_1__PL_MASK /* mask off ICS */
|
||||
bnz r28, .Lrestore_all
|
||||
|
||||
/* Allow interrupts within the single step code */
|
||||
TRACE_IRQS_ON /* Note: clobbers registers r0-r29 */
|
||||
IRQ_ENABLE(r20, r21)
|
||||
|
||||
/* try to single-step the current instruction */
|
||||
PTREGS_PTR(r0, PTREGS_OFFSET_BASE)
|
||||
jal single_step_once
|
||||
FEEDBACK_REENTER(interrupt_return)
|
||||
|
||||
/* Re-disable interrupts. TRACE_IRQS_OFF in .Lrestore_all. */
|
||||
IRQ_DISABLE(r20,r21)
|
||||
|
||||
j .Lrestore_all
|
||||
|
||||
.Lwork_confusion:
|
||||
move r0, r28
|
||||
panic "thread_info allwork flags unhandled on userspace resume: %#x"
|
||||
|
||||
STD_ENDPROC(interrupt_return)
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user