arch/tile: adopt prepare_exit_to_usermode() model from x86
This change is a prerequisite change for TASK_ISOLATION but also
stands on its own for readability and maintainability. The existing
tile do_work_pending() was called in a loop from assembly on
the slow path; this change moves the loop into C code as well.
For the x86 version see commit c5c46f59e4
("x86/entry: Add new,
comprehensible entry and exit handlers written in C").
This change exposes a pre-existing bug on the older tilepro platform;
the singlestep processing is done last, but on tilepro (unlike tilegx)
we enable interrupts while doing that processing, so we could in
theory miss a signal or other asynchronous event. A future change
could fix this by breaking the singlestep work into a "prepare"
step done in the main loop, and a "trigger" step done after exiting
the loop. Since this change is intended as purely a restructuring
change, we call out the bug explicitly now, but don't yet fix it.
Signed-off-by: Chris Metcalf <cmetcalf@ezchip.com>
This commit is contained in:
@@ -878,20 +878,6 @@ 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.
|
||||
*/
|
||||
{
|
||||
movei r33, 0
|
||||
move r32, sp
|
||||
}
|
||||
|
||||
/* Get base of stack in r32. */
|
||||
EXTRACT_THREAD_INFO(r32)
|
||||
|
||||
.Lretry_work_pending:
|
||||
/*
|
||||
* Disable interrupts so as to make sure we don't
|
||||
* miss an interrupt that sets any of the thread flags (like
|
||||
@@ -902,33 +888,28 @@ STD_ENTRY(interrupt_return)
|
||||
IRQ_DISABLE(r20, r21)
|
||||
TRACE_IRQS_OFF /* Note: clobbers registers r0-r29 */
|
||||
|
||||
|
||||
/* Check to see if there is any work to do before returning to user. */
|
||||
{
|
||||
addi r29, r32, THREAD_INFO_FLAGS_OFFSET
|
||||
moveli r1, hw1_last(_TIF_ALLWORK_MASK)
|
||||
}
|
||||
{
|
||||
ld r29, r29
|
||||
shl16insli r1, r1, hw0(_TIF_ALLWORK_MASK)
|
||||
}
|
||||
and r1, r29, r1
|
||||
beqzt r1, .Lrestore_all
|
||||
|
||||
/*
|
||||
* Make sure we have all the registers saved for signal
|
||||
* handling or notify-resume. 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.
|
||||
* See if there are any work items (including single-shot items)
|
||||
* to do. If so, save the callee-save registers to pt_regs
|
||||
* and then dispatch to C code.
|
||||
*/
|
||||
move r21, sp
|
||||
EXTRACT_THREAD_INFO(r21)
|
||||
{
|
||||
addi r22, r21, THREAD_INFO_FLAGS_OFFSET
|
||||
moveli r20, hw1_last(_TIF_ALLWORK_MASK)
|
||||
}
|
||||
{
|
||||
ld r22, r22
|
||||
shl16insli r20, r20, hw0(_TIF_ALLWORK_MASK)
|
||||
}
|
||||
and r1, r22, r20
|
||||
{
|
||||
PTREGS_PTR(r0, PTREGS_OFFSET_BASE)
|
||||
bnez r33, 1f
|
||||
beqzt r1, .Lrestore_all
|
||||
}
|
||||
push_extra_callee_saves r0
|
||||
movei r33, 1
|
||||
1: jal do_work_pending
|
||||
bnez r0, .Lretry_work_pending
|
||||
jal prepare_exit_to_usermode
|
||||
|
||||
/*
|
||||
* In the NMI case we
|
||||
@@ -1411,7 +1392,7 @@ STD_ENTRY(ret_from_kernel_thread)
|
||||
FEEDBACK_REENTER(ret_from_kernel_thread)
|
||||
{
|
||||
movei r30, 0 /* not an NMI */
|
||||
j .Lresume_userspace /* jump into middle of interrupt_return */
|
||||
j interrupt_return
|
||||
}
|
||||
STD_ENDPROC(ret_from_kernel_thread)
|
||||
|
||||
|
Reference in New Issue
Block a user