We already keep a copy of the CPU's ID stashed in CP0.Context or
CP0.XContext (defined by SMP_CPUID_REG) for use in exceptions handlers
to restore the correct CPUs state.
Currently, smp_processor_id() uses the thread_info->cpu
field, which will vanish when CONFIG_THREAD_INFO_IN_TASK is activated.
Switch smp_processor_id() to use the CP0 register.
Since this is quite an invasive change, here is quantification of it's
impact. All tests are from start of series to this patch with a 64r6
defconfig on Boston platform.
Size of 64r6 generic kernel according to bloatometer:
Total: Before=10010245, After=10016193, chg +0.06%
Average latency of syscall (10 x lat_syscall -W 2 -N 10 null)
Before: 6.13729, After: 6.13794, chg +0.00%
Average latency of syscall (10 x lat_syscall -W 2 -N 10 stat /dev/null)
Before: 102.21804, After: 104.14817, chg +1.89%
Average latency of syscall (10 x lat_syscall -W 2 -N 10 exec)
Before: 16051.1, After: 16066.2, chg +0.09%
Signed-off-by: Matt Redfearn <matt.redfearn@mips.com>
---
arch/mips/include/asm/smp.h | 5 ++++-
arch/mips/kernel/cps-vec.S | 5 +++--
arch/mips/kernel/smp.c | 9 ++++++++-
arch/mips/kvm/entry.c | 4 ++--
4 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h
index 056a6bf13491..38352af394d6 100644
--- a/arch/mips/include/asm/smp.h
+++ b/arch/mips/include/asm/smp.h
@@ -19,6 +19,7 @@
#include <linux/atomic.h>
#include <asm/smp-ops.h>
+#include <asm/thread_info.h>
extern int smp_num_siblings;
extern cpumask_t cpu_sibling_map[];
@@ -31,8 +32,10 @@ static inline int raw_smp_processor_id(void)
extern int vdso_smp_processor_id(void)
__compiletime_error("VDSO should not call smp_processor_id()");
return vdso_smp_processor_id();
+#elif defined(CONFIG_MIPS_PGD_C0_CONTEXT)
+ return read_const_c0_xcontext() >> SMP_CPUID_REGSHIFT;
#else
- return current_thread_info()->cpu;
+ return read_const_c0_context() >> SMP_CPUID_REGSHIFT;
#endif
}
#define raw_smp_processor_id raw_smp_processor_id
diff --git a/arch/mips/kernel/cps-vec.S b/arch/mips/kernel/cps-vec.S
index c7ed26029cbb..8c8822b2cf16 100644
--- a/arch/mips/kernel/cps-vec.S
+++ b/arch/mips/kernel/cps-vec.S
@@ -17,6 +17,7 @@
#include <asm/mipsregs.h>
#include <asm/mipsmtregs.h>
#include <asm/pm.h>
+#include <asm/thread_info.h>
#define GCR_CPC_BASE_OFS 0x0088
#define GCR_CL_COHERENCE_OFS 0x2008
@@ -596,8 +597,8 @@ dcache_done:
.macro psstate dest
.set push
.set noat
- lw $1, TI_CPU(gp)
- sll $1, $1, LONGLOG
+ ASM_CPUID_MFC0 $1, ASM_SMP_CPUID_REG
+ LONG_SRL $1, SMP_CPUID_PTRSHIFT
PTR_LA \dest, __per_cpu_offset
addu $1, $1, \dest
lw $1, 0($1)
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index d84b9066b465..defec7499ccd 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -353,7 +353,14 @@ early_initcall(mips_smp_ipi_init);
*/
asmlinkage void start_secondary(void)
{
- unsigned int cpu;
+ unsigned int cpu = current_thread_info()->cpu;
+
+ /* Stash this CPUs ID in CP0 for smp_processor_id() */
+#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
+ write_c0_xcontext((unsigned long)cpu << SMP_CPUID_REGSHIFT);
+#else
+ write_c0_context(cpu << SMP_CPUID_REGSHIFT);
+#endif
cpu_probe();
per_cpu_trap_init(false);
diff --git a/arch/mips/kvm/entry.c b/arch/mips/kvm/entry.c
index 16e1c93b484f..ef411117d435 100644
--- a/arch/mips/kvm/entry.c
+++ b/arch/mips/kvm/entry.c
@@ -382,9 +382,9 @@ static void *kvm_mips_build_enter_guest(void *addr)
/* t1: contains the base of the ASID array, need to get the cpu id */
/* smp_processor_id */
- uasm_i_lw(&p, T2, offsetof(struct thread_info, cpu), GP);
+ UASM_i_MFC0(&p, T2, SMP_CPUID_REG);
+ UASM_i_SRL(&p, T2, T2, SMP_CPUID_PTRSHIFT);
/* index the ASID array */
- uasm_i_sll(&p, T2, T2, ilog2(sizeof(long)));
UASM_i_ADDU(&p, T3, T1, T2);
UASM_i_LW(&p, K0, 0, T3);
#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE
--
2.7.4
|