patch-2.3.9 linux/arch/mips/kernel/r2300_switch.S
Next file: linux/arch/mips/kernel/r4k_fpu.S
Previous file: linux/arch/mips/kernel/r2300_misc.S
Back to the patch index
Back to the overall index
- Lines: 224
- Date:
Fri Jun 25 17:40:12 1999
- Orig file:
v2.3.8/linux/arch/mips/kernel/r2300_switch.S
- Orig date:
Tue Oct 20 13:52:54 1998
diff -u --recursive --new-file v2.3.8/linux/arch/mips/kernel/r2300_switch.S linux/arch/mips/kernel/r2300_switch.S
@@ -1,12 +1,15 @@
-/*
- * r2300_switch.S: R3000/R2000 specific task switching code.
+/* $Id: r2300_switch.S,v 1.6 1999/06/13 16:30:32 ralf Exp $
+ *
+ * r2300_switch.S: R2300 specific task switching code.
*
- * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse
+ * Copyright (C) 1994, 1995, 1996, 1999 by Ralf Baechle
+ * Copyright (C) 1994, 1995, 1996 by Andreas Busse
*
* Multi-cpu abstraction and macros for easier reading:
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
*
- * $Id: r2300_switch.S,v 1.4 1998/04/04 13:59:38 ralf Exp $
+ * Further modifications to make this work:
+ * Copyright (c) 1998 Harald Koerfgen
*/
#include <asm/asm.h>
#include <asm/bootinfo.h>
@@ -15,6 +18,7 @@
#include <asm/fpregdef.h>
#include <asm/mipsconfig.h>
#include <asm/mipsregs.h>
+#include <asm/offset.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/processor.h>
@@ -23,68 +27,137 @@
#include <asm/asmmacro.h>
-/* XXX The following is fucking losing... find a better way dave. */
-MODE_ALIAS = 0x00e0 # uncachable, dirty, valid
-
- .text
.set mips1
- .set noreorder
+ .align 5
+
/*
- * Code necessary to switch tasks on an Linux/MIPS machine.
- * FIXME: We don't need to disable interrupts anymore.
+ * task_struct *r4xx0_resume(task_struct *prev,
+ * task_struct *next)
*/
- .align 5
- LEAF(r2300_resume)
- mfc0 t1,CP0_STATUS # Save status register
- sw t1,THREAD_STATUS($28)
- ori t2,t1,0x1f # Disable interrupts
- xori t2,0x1e
- mtc0 t2,CP0_STATUS
- CPU_SAVE_NONSCRATCH($28)
- sll t2,t1,2 # Save floating point state
- bgez t2,1f
- sw ra,THREAD_REG31($28)
- FPU_SAVE($28, t0)
-1:
- move $28, a0
- lw t0,THREAD_PGDIR($28) # Switch the root pointer
- li t1,TLB_ROOT # get PFN
- mtc0 t1,CP0_ENTRYHI
- mtc0 zero,CP0_INDEX
- srl t0,12 # PFN is 12 bits west
- ori t0,MODE_ALIAS # want uncachable, dirty, valid
- mtc0 t0,CP0_ENTRYLO0
- lw a2,THREAD_STATUS($28)
- tlbwi
-
- /* Flush TLB. */
- mfc0 t3,CP0_STATUS # disable interrupts...
- ori t4,t3,1
- xori t4,1
- mtc0 t4,CP0_STATUS
- lw t0,mips_tlb_entries
- mtc0 zero,CP0_ENTRYLO0
-1:
- subu t0,1
- mtc0 t0,CP0_INDEX
- lui t1,0x0008
- or t1,t0,t1
- sll t1,12
- mtc0 t1,CP0_ENTRYHI
- bne t2,t0,1b
- tlbwi
-
- ori t1,a2,1 # Restore FPU, pipeline magic
- xori t1,1
- mtc0 t1,CP0_STATUS
- sll t0,a2,2
- bgez t0,1f
- lw ra,THREAD_REG31($28)
- FPU_RESTORE($28, t0)
-1:
+LEAF(r2300_resume)
+ .set reorder
+ mfc0 t1, CP0_STATUS
+ .set noreorder
+ sw t1, THREAD_STATUS(a0)
+ CPU_SAVE_NONSCRATCH(a0)
+ sw ra, THREAD_REG31(a0)
+
+ /*
+ * The order of restoring the registers takes care of the race
+ * updating $28, $29 and kernelsp without disabling ints.
+ */
+ move $28, a1
CPU_RESTORE_NONSCRATCH($28)
addiu t0, $28, KERNEL_STACK_SIZE-32
- sw t0,kernelsp
+ sw t0, kernelsp
+ mfc0 t1, CP0_STATUS /* Do we really need this? */
+ li a3, 0xff00
+ and t1, a3
+ lw a2, THREAD_STATUS($28)
+ nor a3, $0, a3
+ and a2, a3
+ lw a3, TASK_MM($28)
+ or a2, t1
+ lw a3, MM_CONTEXT(a3)
+ mtc0 a2, CP0_STATUS
+ andi a3, 0xfc0
+ mtc0 a3, CP0_ENTRYHI
jr ra
- mtc0 a2,CP0_STATUS # Restore status register
+ move v0, a0
END(r2300_resume)
+
+/*
+ * Do lazy fpu context switch. Saves FPU context to the process in a0
+ * and loads the new context of the current process.
+ */
+
+#define ST_OFF (KERNEL_STACK_SIZE - 32 - PT_SIZE + PT_STATUS)
+
+LEAF(r2300_lazy_fpu_switch)
+ mfc0 t0, CP0_STATUS # enable cp1
+ li t3, 0x20000000
+ or t0, t3
+ mtc0 t0, CP0_STATUS
+
+ beqz a0, 2f # Save floating point state
+ nor t3, zero, t3
+ .set reorder
+ lw t1, ST_OFF(a0) # last thread looses fpu
+ .set noreorder
+ and t1, t3
+ sw t1, ST_OFF(a0)
+ swc1 $f0, (THREAD_FPU + 0x00)(a0)
+ FPU_SAVE(a0, t1) # clobbers t1
+
+2:
+ lwc1 $f0, (THREAD_FPU + 0x00)($28)
+ .set reorder
+ FPU_RESTORE($28, t0) # clobbers t0
+ jr ra
+ END(r2300_lazy_fpu_switch)
+
+/*
+ * Save a thread's fp context.
+ */
+ .set noreorder
+LEAF(r2300_save_fp)
+ FPU_SAVE(a0, t1) # clobbers t1
+ jr ra
+ swc1 $f0, (THREAD_FPU + 0x00)(a0)
+ END(r2300_save_fp)
+
+/*
+ * Load the FPU with signalling NANS. This bit pattern we're using has
+ * the property that no matter wether considered as single or as double
+ * precission represents signaling NANS.
+ *
+ * We initialize fcr31 to rounding to nearest, no exceptions.
+ */
+
+#define FPU_DEFAULT 0x00000000
+
+LEAF(r2300_init_fpu)
+ mfc0 t0, CP0_STATUS
+ li t1, 0x20000000
+ or t0, t1
+ mtc0 t0, CP0_STATUS
+
+ li t1, FPU_DEFAULT
+ ctc1 t1, fcr31
+
+ li t0, -1
+
+ mtc1 t0, $f0
+ mtc1 t0, $f1
+ mtc1 t0, $f2
+ mtc1 t0, $f3
+ mtc1 t0, $f4
+ mtc1 t0, $f5
+ mtc1 t0, $f6
+ mtc1 t0, $f7
+ mtc1 t0, $f8
+ mtc1 t0, $f9
+ mtc1 t0, $f10
+ mtc1 t0, $f11
+ mtc1 t0, $f12
+ mtc1 t0, $f13
+ mtc1 t0, $f14
+ mtc1 t0, $f15
+ mtc1 t0, $f16
+ mtc1 t0, $f17
+ mtc1 t0, $f18
+ mtc1 t0, $f19
+ mtc1 t0, $f20
+ mtc1 t0, $f21
+ mtc1 t0, $f22
+ mtc1 t0, $f23
+ mtc1 t0, $f24
+ mtc1 t0, $f25
+ mtc1 t0, $f26
+ mtc1 t0, $f27
+ mtc1 t0, $f28
+ mtc1 t0, $f29
+ mtc1 t0, $f30
+ jr ra
+ mtc1 t0, $f31
+ END(r2300_init_fpu)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)