[RFC PATCH 12/16] MIPS: Keep a copy of each CPU's current_thread

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



In preparation for CONFIG_THREAD_INFO_IN_TASK, where the thread_info is
no longer located at the bottom of the kernel's stack, keep a copy of
each CPU's current thread. Initialise it to the init thread on each CPU,
switch it on context switch, and restore it on entry to kernel space.

Signed-off-by: Matt Redfearn <matt.redfearn@xxxxxxxx>
---

 arch/mips/include/asm/stackframe.h  | 50 ++++++++++++++++++++++++++++++++++---
 arch/mips/include/asm/thread_info.h |  3 +++
 arch/mips/kernel/genex.S            |  8 +++---
 arch/mips/kernel/head.S             |  2 ++
 arch/mips/kernel/octeon_switch.S    |  3 ++-
 arch/mips/kernel/r2300_switch.S     |  3 ++-
 arch/mips/kernel/r4k_switch.S       |  3 ++-
 arch/mips/kernel/setup.c            |  1 +
 arch/mips/kernel/smp.c              |  1 +
 9 files changed, 63 insertions(+), 11 deletions(-)

diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h
index bdcd4088d764..d83d148fec28 100644
--- a/arch/mips/include/asm/stackframe.h
+++ b/arch/mips/include/asm/stackframe.h
@@ -95,8 +95,7 @@
 #endif
 
 		/* Set thread_info if we're coming from user mode */
-		ori	$28, sp, _THREAD_MASK
-		xori	$28, _THREAD_MASK
+		get_saved_ti $28, v1
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
 		.set	push
 		.set	mips64
@@ -165,13 +164,58 @@
 		.endm
 
 /*
+ * get_saved_ti returns the thread_info for the current CPU by looking in the
+ * thread_info_ptr array for it. It clobbers k0 and returns the value in k1.
+ */
+#ifdef CONFIG_SMP
+		/* SMP variation */
+		.macro	get_saved_ti out temp
+		ASM_CPUID_MFC0	\temp, ASM_SMP_CPUID_REG
+#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
+		lui		\out, %hi(thread_info_ptr)
+#else
+		lui		\out, %highest(thread_info_ptr)
+		daddiu		\out, %higher(thread_info_ptr)
+		dsll		\out, 16
+		daddiu		\out, %hi(thread_info_ptr)
+		dsll		\out, 16
+#endif
+		LONG_SRL	\temp, SMP_CPUID_PTRSHIFT
+		LONG_ADDU	\out, \temp
+		LONG_L		\out, %lo(thread_info_ptr)(\out)
+		.endm
+
+		.macro	set_saved_ti ti temp
+		ASM_CPUID_MFC0	\temp, ASM_SMP_CPUID_REG
+		LONG_SRL	\temp, SMP_CPUID_PTRSHIFT
+		LONG_S		\ti, thread_info_ptr(\temp)
+		.endm
+#else /* !CONFIG_SMP */
+		.macro	get_saved_ti out temp	/* Uniprocessor variation */
+#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
+		lui		\out, %hi(thread_info_ptr)
+#else
+		lui		\out, %highest(thread_info_ptr)
+		daddiu		\out, %higher(thread_info_ptr)
+		dsll		\out, \out, 16
+		daddiu		\out, %hi(thread_info_ptr)
+		dsll		\out, \out, 16
+#endif
+		LONG_L		\out, %lo(thread_info_ptr)(\out)
+		.endm
+
+		.macro		set_saved_ti ti temp
+		LONG_S		\ti, thread_info_ptr
+		.endm
+#endif
+
+/*
  * get_saved_sp returns the SP for the current CPU by looking in the
  * kernelsp array for it.  If tosp is set, it stores the current sp in
  * k0 and loads the new value in sp.  If not, it clobbers k0 and
  * stores the new value in k1, leaving sp unaffected.
  */
 #ifdef CONFIG_SMP
-
 		/* SMP variation */
 		.macro	get_saved_sp docfi=0 tosp=0
 		ASM_CPUID_MFC0	k0, ASM_SMP_CPUID_REG
diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h
index 5e8927f99a76..b8cc81055d57 100644
--- a/arch/mips/include/asm/thread_info.h
+++ b/arch/mips/include/asm/thread_info.h
@@ -55,6 +55,9 @@ struct thread_info {
 /* How to get the thread information struct from C.  */
 register struct thread_info *__current_thread_info __asm__("$28");
 
+/* thread_info pointer for each CPU */
+extern unsigned long thread_info_ptr[NR_CPUS];
+
 static inline struct thread_info *current_thread_info(void)
 {
 	return __current_thread_info;
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index 37b9383eacd3..9f7347211ab4 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -581,12 +581,10 @@ docheck:
 
 isrdhwr:
 	/* The insn is rdhwr.  No need to check CAUSE.BD here. */
-	get_saved_sp	/* k1 := current_thread_info */
+	get_saved_ti	k1, k0
 	.set	noreorder
 	MFC0	k0, CP0_EPC
 #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
-	ori	k1, _THREAD_MASK
-	xori	k1, _THREAD_MASK
 	LONG_L	v1, TI_TP_VALUE(k1)
 	LONG_ADDIU	k0, 4
 	jr	k0
@@ -601,8 +599,8 @@ isrdhwr:
 #endif
 	MTC0	k0, CP0_EPC
 	/* I hope three instructions between MTC0 and ERET are enough... */
-	ori	k1, _THREAD_MASK
-	xori	k1, _THREAD_MASK
+	nop
+	nop
 	LONG_L	v1, TI_TP_VALUE(k1)
 	.set	arch=r4000
 	eret
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index 0fcb3e048ece..c74f2e1f4b08 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -135,6 +135,7 @@ dtb_found:
 	PTR_LI		sp, _THREAD_SIZE - 32 - PT_SIZE
 	PTR_ADDU	sp, $28
 	back_to_back_c0_hazard
+	set_saved_ti	$28, t0
 	set_saved_sp	sp, t0, t1
 	PTR_SUBU	sp, 4 * SZREG		# init stack pointer
 
@@ -146,6 +147,7 @@ dtb_found:
 	PTR_ADDU	$28, v0
 	PTR_ADDU	sp, v0
 
+	set_saved_ti	$28, t0
 	set_saved_sp	sp, t0, t1
 
 	/*
diff --git a/arch/mips/kernel/octeon_switch.S b/arch/mips/kernel/octeon_switch.S
index e42113fe2762..b0ef486ad6c1 100644
--- a/arch/mips/kernel/octeon_switch.S
+++ b/arch/mips/kernel/octeon_switch.S
@@ -69,10 +69,11 @@
 
 	/*
 	 * The order of restoring the registers takes care of the race
-	 * updating $28, $29 and kernelsp without disabling ints.
+	 * updating $28, $29 and saved_ti without disabling ints.
 	 */
 	move	$28, a2
 	cpu_restore_nonscratch a1
+	set_saved_ti	$28, t0
 
 	PTR_ADDU	t0, $28, _THREAD_SIZE - 32
 	set_saved_sp	t0, t1, t2
diff --git a/arch/mips/kernel/r2300_switch.S b/arch/mips/kernel/r2300_switch.S
index 665897139f30..6e6c012dfc5e 100644
--- a/arch/mips/kernel/r2300_switch.S
+++ b/arch/mips/kernel/r2300_switch.S
@@ -44,10 +44,11 @@ LEAF(resume)
 
 	/*
 	 * The order of restoring the registers takes care of the race
-	 * updating $28, $29 and kernelsp without disabling ints.
+	 * updating $28, $29 and saved_ti without disabling ints.
 	 */
 	move	$28, a2
 	cpu_restore_nonscratch a1
+	set_saved_ti	$28, t0
 
 	addiu	t1, $28, _THREAD_SIZE - 32
 	sw	t1, kernelsp
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index 17cf9341c1cf..5afbbc1b4bd3 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -39,10 +39,11 @@
 
 	/*
 	 * The order of restoring the registers takes care of the race
-	 * updating $28, $29 and kernelsp without disabling ints.
+	 * updating $28, $29 and saved_ti without disabling ints.
 	 */
 	move	$28, a2
 	cpu_restore_nonscratch a1
+	set_saved_ti	$28, t0
 
 	PTR_ADDU	t0, $28, _THREAD_SIZE - 32
 	set_saved_sp	t0, t1, t2
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 702c678de116..d7078589a077 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -1025,6 +1025,7 @@ void __init setup_arch(char **cmdline_p)
 }
 
 unsigned long kernelsp[NR_CPUS];
+unsigned long thread_info_ptr[NR_CPUS];
 unsigned long fw_arg0, fw_arg1, fw_arg2, fw_arg3;
 
 #ifdef CONFIG_USE_OF
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index defec7499ccd..b93e6748f38d 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -458,6 +458,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle)
 {
 	int err;
 
+	thread_info_ptr[cpu] = (unsigned long)task_thread_info(tidle);
 	err = mp_ops->boot_secondary(cpu, tidle);
 	if (err)
 		return err;
-- 
2.7.4



[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux