summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Metcalf <cmetcalf@tilera.com>2012-03-30 16:29:06 -0400
committerChris Metcalf <cmetcalf@tilera.com>2012-04-02 12:14:03 -0400
commite1d5c0195075abaa45cd04ca397dbeaa0d18c490 (patch)
tree6ed1ccb2ab7cfda0dae569f3adbc667e7642dbe3
parentb1760c847ff9d04fba7cdbef005a0ad805311c6d (diff)
arch/tile: avoid accidentally unmasking NMI-type interrupt accidentally
The return path as we reload registers and core state requires that r30 hold a boolean indicating whether we are returning from an NMI, but in a couple of cases we weren't setting this properly, with the result that we could accidentally unmask the NMI interrupt(s), which could cause confusion. Now we set r30 in every place where we jump into the interrupt return path. Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
-rw-r--r--arch/tile/kernel/intvec_32.S24
-rw-r--r--arch/tile/kernel/intvec_64.S19
2 files changed, 36 insertions, 7 deletions
diff --git a/arch/tile/kernel/intvec_32.S b/arch/tile/kernel/intvec_32.S
index aecc8ed5f39..5d56a1ef5ba 100644
--- a/arch/tile/kernel/intvec_32.S
+++ b/arch/tile/kernel/intvec_32.S
@@ -799,6 +799,10 @@ handle_interrupt:
* This routine takes a boolean in r30 indicating if this is an NMI.
* If so, we also expect a boolean in r31 indicating whether to
* re-enable the oprofile interrupts.
+ *
+ * Note that .Lresume_userspace is jumped to directly in several
+ * places, and we need to make sure r30 is set correctly in those
+ * callers as well.
*/
STD_ENTRY(interrupt_return)
/* If we're resuming to kernel space, don't check thread flags. */
@@ -1237,7 +1241,10 @@ handle_syscall:
bzt r30, 1f
jal do_syscall_trace
FEEDBACK_REENTER(handle_syscall)
-1: j .Lresume_userspace /* jump into middle of interrupt_return */
+1: {
+ movei r30, 0 /* not an NMI */
+ j .Lresume_userspace /* jump into middle of interrupt_return */
+ }
.Linvalid_syscall:
/* Report an invalid syscall back to the user program */
@@ -1246,7 +1253,10 @@ handle_syscall:
movei r28, -ENOSYS
}
sw r29, r28
- j .Lresume_userspace /* jump into middle of interrupt_return */
+ {
+ movei r30, 0 /* not an NMI */
+ j .Lresume_userspace /* jump into middle of interrupt_return */
+ }
STD_ENDPROC(handle_syscall)
/* Return the address for oprofile to suppress in backtraces. */
@@ -1262,7 +1272,10 @@ STD_ENTRY(ret_from_fork)
jal sim_notify_fork
jal schedule_tail
FEEDBACK_REENTER(ret_from_fork)
- j .Lresume_userspace /* jump into middle of interrupt_return */
+ {
+ movei r30, 0 /* not an NMI */
+ j .Lresume_userspace /* jump into middle of interrupt_return */
+ }
STD_ENDPROC(ret_from_fork)
/*
@@ -1376,7 +1389,10 @@ handle_ill:
jal send_sigtrap /* issue a SIGTRAP */
FEEDBACK_REENTER(handle_ill)
- j .Lresume_userspace /* jump into middle of interrupt_return */
+ {
+ movei r30, 0 /* not an NMI */
+ j .Lresume_userspace /* jump into middle of interrupt_return */
+ }
.Ldispatch_normal_ill:
{
diff --git a/arch/tile/kernel/intvec_64.S b/arch/tile/kernel/intvec_64.S
index fdff17c70cc..49d9d662168 100644
--- a/arch/tile/kernel/intvec_64.S
+++ b/arch/tile/kernel/intvec_64.S
@@ -606,6 +606,10 @@ handle_interrupt:
* This routine takes a boolean in r30 indicating if this is an NMI.
* If so, we also expect a boolean in r31 indicating whether to
* re-enable the oprofile interrupts.
+ *
+ * Note that .Lresume_userspace is jumped to directly in several
+ * places, and we need to make sure r30 is set correctly in those
+ * callers as well.
*/
STD_ENTRY(interrupt_return)
/* If we're resuming to kernel space, don't check thread flags. */
@@ -1058,7 +1062,10 @@ handle_syscall:
}
FEEDBACK_REENTER(handle_syscall)
-2: j .Lresume_userspace /* jump into middle of interrupt_return */
+2: {
+ movei r30, 0 /* not an NMI */
+ j .Lresume_userspace /* jump into middle of interrupt_return */
+ }
.Lcompat_syscall:
/*
@@ -1092,7 +1099,10 @@ handle_syscall:
movei r28, -ENOSYS
}
st r29, r28
- j .Lresume_userspace /* jump into middle of interrupt_return */
+ {
+ movei r30, 0 /* not an NMI */
+ j .Lresume_userspace /* jump into middle of interrupt_return */
+ }
STD_ENDPROC(handle_syscall)
/* Return the address for oprofile to suppress in backtraces. */
@@ -1108,7 +1118,10 @@ STD_ENTRY(ret_from_fork)
jal sim_notify_fork
jal schedule_tail
FEEDBACK_REENTER(ret_from_fork)
- j .Lresume_userspace
+ {
+ movei r30, 0 /* not an NMI */
+ j .Lresume_userspace /* jump into middle of interrupt_return */
+ }
STD_ENDPROC(ret_from_fork)
/* Various stub interrupt handlers and syscall handlers */