Commit 176ae640 authored by John David Anglin's avatar John David Anglin Committed by Ben Hutchings

parisc: Ensure consistent state when switching to kernel stack at syscall entry

commit 6ed51832 upstream.

We have one critical section in the syscall entry path in which we switch from
the userspace stack to kernel stack. In the event of an external interrupt, the
interrupt code distinguishes between those two states by analyzing the value of
sr7. If sr7 is zero, it uses the kernel stack. Therefore it's important, that
the value of sr7 is in sync with the currently enabled stack.

This patch now disables interrupts while executing the critical section.  This
prevents the interrupt handler to possibly see an inconsistent state which in
the worst case can lead to crashes.

Interestingly, in the syscall exit path interrupts were already disabled in the
critical section which switches back to the userspace stack.
Signed-off-by: default avatarJohn David Anglin <dave.anglin@bell.net>
Signed-off-by: default avatarHelge Deller <deller@gmx.de>
Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
parent 9cc90663
...@@ -106,8 +106,6 @@ linux_gateway_entry: ...@@ -106,8 +106,6 @@ linux_gateway_entry:
mtsp %r0,%sr4 /* get kernel space into sr4 */ mtsp %r0,%sr4 /* get kernel space into sr4 */
mtsp %r0,%sr5 /* get kernel space into sr5 */ mtsp %r0,%sr5 /* get kernel space into sr5 */
mtsp %r0,%sr6 /* get kernel space into sr6 */ mtsp %r0,%sr6 /* get kernel space into sr6 */
mfsp %sr7,%r1 /* save user sr7 */
mtsp %r1,%sr3 /* and store it in sr3 */
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
/* for now we can *always* set the W bit on entry to the syscall /* for now we can *always* set the W bit on entry to the syscall
...@@ -133,6 +131,14 @@ linux_gateway_entry: ...@@ -133,6 +131,14 @@ linux_gateway_entry:
depdi 0, 31, 32, %r21 depdi 0, 31, 32, %r21
1: 1:
#endif #endif
/* We use a rsm/ssm pair to prevent sr3 from being clobbered
* by external interrupts.
*/
mfsp %sr7,%r1 /* save user sr7 */
rsm PSW_SM_I, %r0 /* disable interrupts */
mtsp %r1,%sr3 /* and store it in sr3 */
mfctl %cr30,%r1 mfctl %cr30,%r1
xor %r1,%r30,%r30 /* ye olde xor trick */ xor %r1,%r30,%r30 /* ye olde xor trick */
xor %r1,%r30,%r1 xor %r1,%r30,%r1
...@@ -147,6 +153,7 @@ linux_gateway_entry: ...@@ -147,6 +153,7 @@ linux_gateway_entry:
*/ */
mtsp %r0,%sr7 /* get kernel space into sr7 */ mtsp %r0,%sr7 /* get kernel space into sr7 */
ssm PSW_SM_I, %r0 /* enable interrupts */
STREGM %r1,FRAME_SIZE(%r30) /* save r1 (usp) here for now */ STREGM %r1,FRAME_SIZE(%r30) /* save r1 (usp) here for now */
mfctl %cr30,%r1 /* get task ptr in %r1 */ mfctl %cr30,%r1 /* get task ptr in %r1 */
LDREG TI_TASK(%r1),%r1 LDREG TI_TASK(%r1),%r1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment