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@xxxxxxxx> --- 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