summaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/winfixup.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/kernel/winfixup.S')
-rw-r--r--arch/sparc64/kernel/winfixup.S71
1 files changed, 45 insertions, 26 deletions
diff --git a/arch/sparc64/kernel/winfixup.S b/arch/sparc64/kernel/winfixup.S
index 0ebf92767..6e3f6193a 100644
--- a/arch/sparc64/kernel/winfixup.S
+++ b/arch/sparc64/kernel/winfixup.S
@@ -1,4 +1,4 @@
-/* $Id: winfixup.S,v 1.19 1997/08/08 08:33:37 jj Exp $
+/* $Id: winfixup.S,v 1.22 1997/10/24 11:57:48 jj Exp $
*
* winfixup.S: Handle cases where user stack pointer is found to be bogus.
*
@@ -48,6 +48,10 @@ fill_fixup:
* most things are where they need to be, we also have the address
* which triggered the fault handy as well.
*
+ * Also note that we must preserve %l5 and %l6. If the user was
+ * returning from a system call, we must make it look this way
+ * after we process the fill fault on the users stack.
+ *
* First, get into the window where the original restore was executed.
*/
@@ -65,15 +69,23 @@ fill_fixup:
rdpr %pstate, %l1 ! Prepare to change globals.
mov %g6, %o7 ! Get current.
- mov %g5, %l5 ! Fault address
- clr %l4 ! It was a load, not a store
+ andn %l1, PSTATE_MM, %l1 ! We want to be in RMO
+ srlx %g5, PAGE_SHIFT, %o1 ! Fault address
wrpr %g0, 0x0, %tl ! Out of trap levels.
wrpr %l1, (PSTATE_IE | PSTATE_AG | PSTATE_RMO), %pstate
sethi %uhi(PAGE_OFFSET), %g4 ! Prepare page_offset global reg
mov %o7, %g6
- b,pt %xcc, window_scheisse_merge ! And merge.
+ sllx %g4, 32, %g4 ! and finish it...
+ clr %o2
- sllx %g4, 32, %g4 ! and finish it...
+ /* This is the same as below, except we handle this a bit special
+ * since we must preserve %l5 and %l6, see comment above.
+ */
+ sllx %o1, PAGE_SHIFT, %o1
+ call do_sparc64_fault
+ add %sp, STACK_BIAS + REGWIN_SZ, %o0
+ b,pt %xcc, rtrap
+ nop ! yes, nop is correct
/* Be very careful about usage of the alternate globals here.
* You cannot touch %g4/%g5 as that has the fault information
@@ -84,59 +96,59 @@ fill_fixup:
* do not touch %g7 or %g2 so we handle the two cases fine.
*/
spill_fixup:
- ld [%g6 + AOFF_task_tss + AOFF_thread_flags], %g1
+ lduh [%g6 + AOFF_task_tss + AOFF_thread_flags], %g1
andcc %g1, SPARC_FLAG_32BIT, %g0
- ldx [%g6 + AOFF_task_tss + AOFF_thread_w_saved], %g1
+ lduh [%g6 + AOFF_task_tss + AOFF_thread_w_saved], %g1
+
sll %g1, 3, %g3
add %g6, %g3, %g3
stx %sp, [%g3 + AOFF_task_tss + AOFF_thread_rwbuf_stkptrs]
sll %g1, 7, %g3
-
bne,pt %xcc, 1f
add %g6, %g3, %g3
stx %l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00]
stx %l1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08]
+
stx %l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10]
stx %l3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18]
stx %l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x20]
stx %l5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28]
-
stx %l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30]
stx %l7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38]
stx %i0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x40]
stx %i1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x48]
+
stx %i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x50]
stx %i3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x58]
stx %i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x60]
stx %i5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x68]
-
stx %i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x70]
b,pt %xcc, 2f
stx %i7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x78]
1: stw %l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00]
+
stw %l1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x04]
stw %l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08]
stw %l3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x0c]
stw %l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10]
-
stw %l5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x14]
stw %l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18]
stw %l7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x1c]
stw %i0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x20]
+
stw %i1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x24]
stw %i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28]
stw %i3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x2c]
stw %i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30]
-
stw %i5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x34]
stw %i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38]
stw %i7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x3c]
2: add %g1, 1, %g1
- stx %g1, [%g6 + AOFF_task_tss + AOFF_thread_w_saved]
+
+ sth %g1, [%g6 + AOFF_task_tss + AOFF_thread_w_saved]
rdpr %tstate, %g1
andcc %g1, TSTATE_PRIV, %g0
saved
-
and %g1, TSTATE_CWP, %g1
be,a,pn %xcc, window_scheisse_from_user_common
or %g4, 0x4, %g4 ! we know it was a write
@@ -146,7 +158,6 @@ window_scheisse_from_user_common:
sethi %hi(109f), %g7
ba,pt %xcc, etrap
109: or %g7, %lo(109b), %g7
-window_scheisse_merge:
srlx %l5, PAGE_SHIFT, %o1
and %l4, 0x4, %o2
@@ -173,10 +184,15 @@ fill_fixup_mna:
andcc %g1, TSTATE_PRIV, %g0
be,pt %xcc, window_mna_from_user_common
and %g1, TSTATE_CWP, %g1
+
+ /* Please, see fill_fixup commentary about why we must preserve
+ * %l5 and %l6 to preserve absolute correct semantics.
+ */
rdpr %wstate, %g2 ! Grab user mode wstate.
wrpr %g1, %cwp ! Get into the right window.
sll %g2, 3, %g2 ! NORMAL-->OTHER
wrpr %g0, 0x0, %canrestore ! Standard etrap stuff.
+
wrpr %g2, 0x0, %wstate ! This must be consistant.
wrpr %g0, 0x0, %otherwin ! We know this.
mov PRIMARY_CONTEXT, %g1 ! Change contexts...
@@ -185,23 +201,28 @@ fill_fixup_mna:
rdpr %pstate, %l1 ! Prepare to change globals.
mov %g4, %o5 ! Setup args for
mov %g5, %o4 ! final call to do_sparc64_fault.
+ andn %l1, PSTATE_MM, %l1 ! We want to be in RMO
+
mov %g6, %o7 ! Stash away current.
wrpr %g0, 0x0, %tl ! Out of trap levels.
wrpr %l1, (PSTATE_IE | PSTATE_AG | PSTATE_RMO), %pstate
sethi %uhi(PAGE_OFFSET), %g4 ! Set page_offset global reg.
mov %o7, %g6 ! Get current back.
- b,pt %xcc, window_mna_merge ! And merge.
- sllx %g4, 32, %g4 ! Finish it.
+ sllx %g4, 32, %g4 ! Finish it.
+ call mem_address_unaligned
+ add %sp, STACK_BIAS + REGWIN_SZ, %o0
+ b,pt %xcc, rtrap
+ nop ! yes, the nop is correct
spill_fixup_mna:
- ld [%g6 + AOFF_task_tss + AOFF_thread_flags], %g1
+ lduh [%g6 + AOFF_task_tss + AOFF_thread_flags], %g1
andcc %g1, SPARC_FLAG_32BIT, %g0
- ldx [%g6 + AOFF_task_tss + AOFF_thread_w_saved], %g1
+ lduh [%g6 + AOFF_task_tss + AOFF_thread_w_saved], %g1
sll %g1, 3, %g3
add %g6, %g3, %g3
stx %sp, [%g3 + AOFF_task_tss + AOFF_thread_rwbuf_stkptrs]
- sll %g1, 7, %g3
+ sll %g1, 7, %g3
bne,pt %xcc, 1f
add %g6, %g3, %g3
stx %l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00]
@@ -209,8 +230,8 @@ spill_fixup_mna:
stx %l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10]
stx %l3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18]
stx %l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x20]
- stx %l5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28]
+ stx %l5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28]
stx %l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30]
stx %l7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38]
stx %i0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x40]
@@ -218,8 +239,8 @@ spill_fixup_mna:
stx %i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x50]
stx %i3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x58]
stx %i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x60]
- stx %i5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x68]
+ stx %i5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x68]
stx %i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x70]
stx %i7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x78]
b,pt %xcc, 2f
@@ -227,16 +248,15 @@ spill_fixup_mna:
1: std %l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00]
std %l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08]
std %l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10]
- std %l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18]
+ std %l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18]
std %i0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x20]
std %i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28]
std %i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30]
std %i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38]
add %g1, 1, %g1
-2: stx %g1, [%g6 + AOFF_task_tss + AOFF_thread_w_saved]
+2: sth %g1, [%g6 + AOFF_task_tss + AOFF_thread_w_saved]
rdpr %tstate, %g1
- nop
andcc %g1, TSTATE_PRIV, %g0
saved
@@ -248,7 +268,6 @@ window_mna_from_user_common:
sethi %hi(109f), %g7
ba,pt %xcc, etrap
109: or %g7, %lo(109b), %g7
-window_mna_merge:
call mem_address_unaligned
add %sp, STACK_BIAS + REGWIN_SZ, %o0
ba,pt %xcc, rtrap