Is anyone else interested in having the 64-bit kernel *not* use the CP0
watchpoint registers for storing the kernel stack pointer for the CPU's
current process?
I have a couple problems with this:
- there are read-only bits in watchhi (according to the MIPS64 spec) so
hoping to save and restore all high 32 bits (as currently coded) seems
unjustified.
- somebody might want to actually *use* watchpoints (a JTAG debugger,
in my case)
I put together something that works, based on the 32-bit kernel which
has an array of kernelsp's instead of keeping it in CP0. Some notes
about this solution are:
- processor id isn't as easy to get in the 64-bit kernel since
CP0_CONTEXT has (&pgd_current[cpu] << 23) instead of (cpu << 23) so in
this patch I use ((&pgd_current[cpu] - &pgd_current[0]) + &kernelsp)
which seems expensive.
- smp_bootstrap tries to stash the kernelsp away, but won't work
because CP0_CONTEXT on secondary CPUs isn't set up yet. However, I
don't think this really needs to happen at this time; the first context
switch on the CPU will save the kernelsp without any damage being done
(I think). So in the patch, I axed this use of set_saved_sp.
- set_saved_sp implemented using the pointer math needs two temporaries
instead of one (or am I missing a trick?)
2.4 kernel patch included.
Kip
Index: include/asm-mips64/stackframe.h
===================================================================
RCS file: /home/cvs/linux/include/asm-mips64/stackframe.h,v
retrieving revision 1.7.2.4
diff -u -r1.7.2.4 stackframe.h
--- include/asm-mips64/stackframe.h 28 Jan 2003 14:31:33 -0000 1.7.2.4
+++ include/asm-mips64/stackframe.h 4 Mar 2003 21:49:47 -0000
@@ -11,6 +11,7 @@
#define _ASM_STACKFRAME_H
#include <linux/config.h>
+#include <linux/threads.h>
#include <asm/asm.h>
#include <asm/offset.h>
@@ -76,33 +77,23 @@
.endm
#ifdef CONFIG_SMP
- .macro get_saved_sp /* R10000 variation */
-#ifdef CONFIG_CPU_SB1
- dmfc0 k1, CP0_WATCHLO
-#else
- mfc0 k0, CP0_WATCHLO
- mfc0 k1, CP0_WATCHHI
- dsll32 k0, k0, 0 /* Get rid of sign extension */
- dsrl32 k0, k0, 0 /* Get rid of sign extension */
- dsll32 k1, k1, 0
- or k1, k1, k0
- li k0, K0BASE
- or k1, k1, k0
-#endif
- .endm
-
- .macro set_saved_sp stackp temp
-#ifdef CONFIG_CPU_SB1
- dmtc0 \stackp, CP0_WATCHLO
-#else
- mtc0 \stackp, CP0_WATCHLO
- dsrl32 \temp, \stackp, 0
- mtc0 \temp, CP0_WATCHHI
-#endif
+ .macro get_saved_sp /* SMP variation */
+ dmfc0 k1, CP0_CONTEXT
+ dsra k1, 23
+ lui k0, %hi(pgd_current)
+ daddiu k0, %lo(pgd_current)
+ dsubu k1, k0
+ lui k0, %hi(kernelsp)
+ daddu k1, k0
+ ld k1, %lo(kernelsp)(k1)
.endm
- .macro declare_saved_sp
- # empty, stackpointer stored in a register
+ .macro set_saved_sp stackp temp temp2
+ lw \temp, TASK_PROCESSOR(gp)
+ dsll \temp, 3
+ lui \temp2, %hi(kernelsp)
+ daddu \temp, \temp2
+ sd \stackp, %lo(kernelsp)(\temp)
.endm
#else
.macro get_saved_sp /* Uniprocessor variation */
@@ -110,14 +101,13 @@
ld k1, %lo(kernelsp)(k1)
.endm
- .macro set_saved_sp stackp temp
+ .macro set_saved_sp stackp temp temp2
sd \stackp, kernelsp
.endm
-
+#endif
.macro declare_saved_sp
- .comm kernelsp, 8, 8 # current stackpointer
+ .comm kernelsp, NR_CPUS * 8, 8
.endm
-#endif
.macro SAVE_SOME
.set push
Index: arch/mips64/kernel/head.S
===================================================================
RCS file: /home/cvs/linux/arch/mips64/kernel/head.S,v
retrieving revision 1.34.2.10
diff -u -r1.34.2.10 head.S
--- arch/mips64/kernel/head.S 29 Nov 2002 04:02:31 -0000 1.34.2.10
+++ arch/mips64/kernel/head.S 4 Mar 2003 21:49:47 -0000
@@ -107,7 +107,7 @@
PTR_LA $28, init_task_union # init current pointer
daddiu sp, $28, KERNEL_STACK_SIZE-32
- set_saved_sp sp, t0
+ set_saved_sp sp, t0, t1
/* The firmware/bootloader passes argc/argp/envp
* to us as arguments. But clear bss first because
@@ -156,8 +156,6 @@
mfc0 t0, CP0_STATUS
or t0, ST0_KX
mtc0 t0, CP0_STATUS
-
- set_saved_sp sp, t0
jal start_secondary # XXX: IP27: cboot
Index: arch/mips64/kernel/r4k_switch.S
===================================================================
RCS file: /home/cvs/linux/arch/mips64/kernel/r4k_switch.S,v
retrieving revision 1.5.2.10
diff -u -r1.5.2.10 r4k_switch.S
--- arch/mips64/kernel/r4k_switch.S 4 Nov 2002 19:39:56 -0000 1.5.2.10
+++ arch/mips64/kernel/r4k_switch.S 4 Mar 2003 21:49:47 -0000
@@ -87,7 +87,7 @@
cpu_restore_nonscratch $28
daddiu a1, $28, KERNEL_STACK_SIZE-32
- set_saved_sp a1 t0
+ set_saved_sp a1, t0, t1
mfc0 t1, CP0_STATUS /* Do we really need this? */
li a3, 0xff00