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:
Chris Metcalf
2011-05-02 14:50:06 -04:00
父節點 93013a0f53
當前提交 313ce674d3
共有 7 個文件被更改,包括 87 次插入100 次删除

查看文件

@@ -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)
/*