summaryrefslogtreecommitdiffstats
path: root/arch/tile/kernel/intvec_32.S
diff options
context:
space:
mode:
authorChris Metcalf2015-09-22 20:49:41 +0200
committerChris Metcalf2016-01-18 20:49:09 +0100
commit583b24a210ada7e88fc12aaf50024975ec882816 (patch)
treeb396bc95a44f29d9dd2c8bab86fcd0d0728b24b1 /arch/tile/kernel/intvec_32.S
parenttile/jump_label: add jump label support for TILE-Gx (diff)
downloadkernel-qcow2-linux-583b24a210ada7e88fc12aaf50024975ec882816.tar.gz
kernel-qcow2-linux-583b24a210ada7e88fc12aaf50024975ec882816.tar.xz
kernel-qcow2-linux-583b24a210ada7e88fc12aaf50024975ec882816.zip
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 c5c46f59e4e7 ("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>
Diffstat (limited to 'arch/tile/kernel/intvec_32.S')
-rw-r--r--arch/tile/kernel/intvec_32.S46
1 files changed, 14 insertions, 32 deletions
diff --git a/arch/tile/kernel/intvec_32.S b/arch/tile/kernel/intvec_32.S
index fbbe2ea882ea..33d48812872a 100644
--- a/arch/tile/kernel/intvec_32.S
+++ b/arch/tile/kernel/intvec_32.S
@@ -846,18 +846,6 @@ STD_ENTRY(interrupt_return)
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
* need_resched or sigpending) between sampling and the iret.
@@ -867,33 +855,27 @@ 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. */
+ /*
+ * 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.
+ */
+ GET_THREAD_INFO(r21)
{
- addi r29, r32, THREAD_INFO_FLAGS_OFFSET
- moveli r1, lo16(_TIF_ALLWORK_MASK)
+ addi r22, r21, THREAD_INFO_FLAGS_OFFSET
+ moveli r20, lo16(_TIF_ALLWORK_MASK)
}
{
- lw r29, r29
- auli r1, r1, ha16(_TIF_ALLWORK_MASK)
+ lw r22, r22
+ auli r20, r20, ha16(_TIF_ALLWORK_MASK)
}
- and r1, r29, r1
- bzt r1, .Lrestore_all
-
- /*
- * Make sure we have all the registers saved for signal
- * 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.
- */
+ and r1, r22, r20
{
PTREGS_PTR(r0, PTREGS_OFFSET_BASE)
- bnz r33, 1f
+ bzt r1, .Lrestore_all
}
push_extra_callee_saves r0
- movei r33, 1
-1: jal do_work_pending
- bnz r0, .Lretry_work_pending
+ jal prepare_exit_to_usermode
/*
* In the NMI case we
@@ -1327,7 +1309,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)