From: Wang ShaoBo bobo.shaobowang@huawei.com
hulk inclusion category: performance bugzilla: https://gitee.com/openeuler/kernel/issues/I5QK5M CVE: NA
--------------------------------
Getting preferred sibling's cpumask supported by platform.
Signed-off-by: Wang ShaoBo bobo.shaobowang@huawei.com Signed-off-by: Yu Kuai yukuai3@huawei.com --- arch/arm64/Kconfig | 8 +++++ arch/arm64/include/asm/smp_plat.h | 14 +++++++++ arch/arm64/kernel/smp.c | 9 ++++++ arch/arm64/kernel/topology.c | 51 +++++++++++++++++++++++++++++++ include/linux/arch_topology.h | 7 +++++ 5 files changed, 89 insertions(+)
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 80ab9c9dd43c..c68dd7d7f054 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1389,6 +1389,14 @@ config RANDOMIZE_MODULE_REGION_FULL a limited range that contains the [_stext, _etext] interval of the core kernel, so branch relocations are always in range.
+config ARCH_GET_PREFERRED_SIBLING_CPUMASK + bool "Get preferred sibling cpumask from mpidr" + depends on ARM64 + default y + help + Get preferred sibling cpumask given by mpidr, this hardly depends on + the specific implementation of the specific platform. + menuconfig ASCEND_FEATURES bool "Support Ascend Features" depends on ARM64 diff --git a/arch/arm64/include/asm/smp_plat.h b/arch/arm64/include/asm/smp_plat.h index af58dcdefb21..63e29335f426 100644 --- a/arch/arm64/include/asm/smp_plat.h +++ b/arch/arm64/include/asm/smp_plat.h @@ -56,4 +56,18 @@ static inline int get_logical_index(u64 mpidr) return -EINVAL; }
+#ifdef CONFIG_ARCH_GET_PREFERRED_SIBLING_CPUMASK +void update_mpidr_siblings_masks(unsigned int cpu, bool remove); + +static inline void mpidr_siblings_add_cpu(unsigned int cpu) +{ + update_mpidr_siblings_masks(cpu, false); +} + +static inline void mpidr_siblings_remove_cpu(unsigned int cpu) +{ + update_mpidr_siblings_masks(cpu, true); +} +#endif + #endif /* __ASM_SMP_PLAT_H */ diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index cdb81a36be85..6b8bc313a87b 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -426,6 +426,9 @@ asmlinkage notrace void secondary_start_kernel(void)
store_cpu_topology(cpu); numa_add_cpu(cpu); +#ifdef CONFIG_ARCH_GET_PREFERRED_SIBLING_CPUMASK + mpidr_siblings_add_cpu(cpu); +#endif
/* * OK, now it's safe to let the boot CPU continue. Wait for @@ -481,6 +484,9 @@ int __cpu_disable(void)
remove_cpu_topology(cpu); numa_remove_cpu(cpu); +#ifdef CONFIG_ARCH_GET_PREFERRED_SIBLING_CPUMASK + mpidr_siblings_remove_cpu(cpu); +#endif
/* * Take this CPU offline. Once we clear this, we can't return, @@ -945,6 +951,9 @@ void __init smp_prepare_cpus(unsigned int max_cpus) store_cpu_topology(this_cpu); numa_store_cpu_info(this_cpu); numa_add_cpu(this_cpu); +#ifdef CONFIG_ARCH_GET_PREFERRED_SIBLING_CPUMASK + mpidr_siblings_add_cpu(this_cpu); +#endif
/* * If UP is mandated by "nosmp" (which implies "maxcpus=0"), don't set diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c index 2646695e2f2a..b8446aad72ea 100644 --- a/arch/arm64/kernel/topology.c +++ b/arch/arm64/kernel/topology.c @@ -348,6 +348,57 @@ void remove_cpu_topology(unsigned int cpu) clear_cpu_topology(cpu); }
+#ifdef CONFIG_ARCH_GET_PREFERRED_SIBLING_CPUMASK +#define MAX_MPIDR_SIBLINGS 100 +static struct cpumask mpidr_siblings_cpumask_map[MAX_MPIDR_SIBLINGS]; + +static void +__update_mpidr_siblings_masks(unsigned int cpu, int sibling, bool remove) +{ + if (WARN_ON_ONCE(sibling < 0 || sibling >= MAX_MPIDR_SIBLINGS)) + return; + + if (remove) + cpumask_clear_cpu(cpu, &mpidr_siblings_cpumask_map[sibling]); + else + cpumask_set_cpu(cpu, &mpidr_siblings_cpumask_map[sibling]); +} + +void update_mpidr_siblings_masks(unsigned int cpu, bool remove) +{ + int sibling, affinity; + u32 midr_impl = MIDR_IMPLEMENTOR(read_cpuid_id()); + u64 mpidr = read_cpuid_mpidr(); + bool mt = mpidr & MPIDR_MT_BITMASK; + + switch (midr_impl) { + case ARM_CPU_IMP_HISI: + if (mt && read_cpuid_part_number() == HISI_CPU_PART_TSV110) { + affinity = MPIDR_AFFINITY_LEVEL(mpidr, 2); + sibling = ((affinity >> 3) - 1) / 2; + __update_mpidr_siblings_masks(cpu, sibling, remove); + } + break; + default: + break; + } +} + +void arch_get_preferred_sibling_mask(unsigned int sibling, cpumask_var_t dstp) +{ + if (dstp == NULL) + return; + + if (sibling >= MAX_MPIDR_SIBLINGS) { + cpumask_clear(dstp); + return; + } + + cpumask_copy(dstp, &mpidr_siblings_cpumask_map[sibling]); +} +EXPORT_SYMBOL(arch_get_preferred_sibling_mask); +#endif + #ifdef CONFIG_ACPI static bool __init acpi_cpu_is_threaded(int cpu) { diff --git a/include/linux/arch_topology.h b/include/linux/arch_topology.h index 2b709416de05..80ce8172b8b5 100644 --- a/include/linux/arch_topology.h +++ b/include/linux/arch_topology.h @@ -32,4 +32,11 @@ unsigned long topology_get_freq_scale(int cpu) return per_cpu(freq_scale, cpu); }
+#ifdef CONFIG_ARCH_GET_PREFERRED_SIBLING_CPUMASK +void arch_get_preferred_sibling_mask(unsigned int sibling, cpumask_var_t dstp); +#else +static inline void +arch_get_preferred_sibling_mask(unsigned int sibling, cpumask_var_t dstp) {} +#endif + #endif /* _LINUX_ARCH_TOPOLOGY_H_ */