diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 11bc17ce0ebf5e1efcae5ee34fc24159fe837ccd..d5a89f3fdfd3ec33c309f6d5bdeac919499ded03 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1442,6 +1442,7 @@ config MIPS_MT_SMP select MIPS_MT select NR_CPUS_DEFAULT_2 select SMP + select SYS_SUPPORTS_SCHED_SMT if SMP select SYS_SUPPORTS_SMP help This is a kernel model which is also known a VSMP or lately @@ -1468,6 +1469,19 @@ endchoice config MIPS_MT bool +config SCHED_SMT + bool "SMT (multithreading) scheduler support" + depends on SYS_SUPPORTS_SCHED_SMT + default n + help + SMT scheduler support improves the CPU scheduler's decision making + when dealing with MIPS MT enabled cores at a cost of slightly + increased overhead in some places. If unsure say N here. + +config SYS_SUPPORTS_SCHED_SMT + bool + + config SYS_SUPPORTS_MULTITHREADING bool diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c index 6e6e947cce1efe6fac56d54f1a795a6ac9ad7b03..34dd22838fdb57677271053ebfa905b5ffa7b40f 100644 --- a/arch/mips/kernel/proc.c +++ b/arch/mips/kernel/proc.c @@ -62,6 +62,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) ); seq_printf(m, "shadow register sets\t: %d\n", cpu_data[n].srsets); + seq_printf(m, "core\t\t\t: %d\n", cpu_data[n].core); sprintf(fmt, "VCE%%c exceptions\t\t: %s\n", cpu_has_vce ? "%u" : "not available"); diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c index 94e210cc6cb6725675389ba84d190c97d63be789..2ab0b7eeaa7e81060c6067423b94b3586cdc2153 100644 --- a/arch/mips/kernel/smp-mt.c +++ b/arch/mips/kernel/smp-mt.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -30,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -223,6 +223,7 @@ static void __init smp_tc_init(unsigned int tc, unsigned int mvpconf0) void __init plat_smp_setup(void) { unsigned int mvpconf0, ntc, tc, ncpu = 0; + unsigned int nvpe; #ifdef CONFIG_MIPS_MT_FPAFF /* If we have an FPU, enroll ourselves in the FPU-full mask */ @@ -242,6 +243,9 @@ void __init plat_smp_setup(void) mvpconf0 = read_c0_mvpconf0(); ntc = (mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT; + nvpe = ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1; + smp_num_siblings = nvpe; + /* we'll always have more TC's than VPE's, so loop setting everything to a sensible state */ for (tc = 0; tc <= ntc; tc++) { diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 63989e9df4f97099b73889d3610b6111d2447b0c..335be9bcf0dc8b11effd1c78689294ed946af2a9 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -56,6 +56,34 @@ EXPORT_SYMBOL(cpu_online_map); extern void __init calibrate_delay(void); extern void cpu_idle(void); +/* Number of TCs (or siblings in Intel speak) per CPU core */ +int smp_num_siblings = 1; +EXPORT_SYMBOL(smp_num_siblings); + +/* representing the TCs (or siblings in Intel speak) of each logical CPU */ +cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; +EXPORT_SYMBOL(cpu_sibling_map); + +/* representing cpus for which sibling maps can be computed */ +static cpumask_t cpu_sibling_setup_map; + +static inline void set_cpu_sibling_map(int cpu) +{ + int i; + + cpu_set(cpu, cpu_sibling_setup_map); + + if (smp_num_siblings > 1) { + for_each_cpu_mask(i, cpu_sibling_setup_map) { + if (cpu_data[cpu].core == cpu_data[i].core) { + cpu_set(i, cpu_sibling_map[cpu]); + cpu_set(cpu, cpu_sibling_map[i]); + } + } + } else + cpu_set(cpu, cpu_sibling_map[cpu]); +} + /* * First C code run on the secondary CPUs after being started up by * the master. @@ -85,6 +113,7 @@ asmlinkage __cpuinit void start_secondary(void) cpu_data[cpu].udelay_val = loops_per_jiffy; prom_smp_finish(); + set_cpu_sibling_map(cpu); cpu_set(cpu, cpu_callin_map); @@ -258,6 +287,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) init_new_context(current, &init_mm); current_thread_info()->cpu = 0; plat_prepare_cpus(max_cpus); + set_cpu_sibling_map(0); #ifndef CONFIG_HOTPLUG_CPU cpu_present_map = cpu_possible_map; #endif diff --git a/include/asm-mips/cpu-info.h b/include/asm-mips/cpu-info.h index ed5c02c6afbbafa98420565c8f7a88c74bbe2e27..0c5a358863f36067eb8fdbcdbd40166ccfec4954 100644 --- a/include/asm-mips/cpu-info.h +++ b/include/asm-mips/cpu-info.h @@ -55,6 +55,7 @@ struct cpuinfo_mips { struct cache_desc scache; /* Secondary cache */ struct cache_desc tcache; /* Tertiary/split secondary cache */ int srsets; /* Shadow register sets */ + int core; /* physical core number */ #if defined(CONFIG_MIPS_MT_SMTC) /* * In the MIPS MT "SMTC" model, each TC is considered @@ -63,8 +64,10 @@ struct cpuinfo_mips { * to all TCs within the same VPE. */ int vpe_id; /* Virtual Processor number */ - int tc_id; /* Thread Context number */ #endif /* CONFIG_MIPS_MT */ +#ifdef CONFIG_MIPS_MT_SMTC + int tc_id; /* Thread Context number */ +#endif void *data; /* Additional data */ } __attribute__((aligned(SMP_CACHE_BYTES))); diff --git a/include/asm-mips/smp.h b/include/asm-mips/smp.h index dc770025a9b0c98fcbe954f677713c0f85f91b7d..23265879cee90509672897553656ca4476da684a 100644 --- a/include/asm-mips/smp.h +++ b/include/asm-mips/smp.h @@ -20,6 +20,9 @@ #include #include +extern int smp_num_siblings; +extern cpumask_t cpu_sibling_map[]; + #define raw_smp_processor_id() (current_thread_info()->cpu) /* Map from cpu id to sequential logical cpu number. This will only diff --git a/include/asm-mips/topology.h b/include/asm-mips/topology.h index 0440fb9f218044d504cdf18ee13ca8d836fbdd63..259145e07e9724a2e1bcd22e3ed9ee52a8f9580c 100644 --- a/include/asm-mips/topology.h +++ b/include/asm-mips/topology.h @@ -1 +1,17 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2007 by Ralf Baechle + */ +#ifndef __ASM_TOPOLOGY_H +#define __ASM_TOPOLOGY_H + #include + +#ifdef CONFIG_SMP +#define smt_capable() (smp_num_siblings > 1) +#endif + +#endif /* __ASM_TOPOLOGY_H */