From: Wang ShaoBo bobo.shaobowang@huawei.com
hulk inclusion category: performance bugzilla: https://gitee.com/openeuler/kernel/issues/I5QK5M CVE: NA
--------------------------------
For some architectures, masking the underlying processor topology differences can make software unable to identify the cpu distance, which results in performance fluctuations.
So we provide additional interface for getting preferred sibling's cpumask supported by platform, this siblings' cpumask indicates those CPUs which are clustered with relatively short distances, but this hardly depends on the specific implementation of the specific platform.
Signed-off-by: Wang ShaoBo bobo.shaobowang@huawei.com Signed-off-by: Yu Kuai yukuai3@huawei.com Reviewed-by: Xiongfeng Wang wangxiongfeng2@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Yongqiang Liu liuyongqiang13@huawei.com --- arch/arm64/Kconfig | 15 +++++++++ arch/arm64/include/asm/smp_plat.h | 14 +++++++++ arch/arm64/kernel/smp.c | 9 ++++++ arch/arm64/kernel/topology.c | 52 +++++++++++++++++++++++++++++++ include/linux/arch_topology.h | 12 +++++++ 5 files changed, 102 insertions(+)
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 80ab9c9dd43c..0ad6ce436355 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1389,6 +1389,21 @@ 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 n + help + For some architectures, masking the underlying processor topology + differences can make software unable to identify the cpu distance, + which results in performance fluctuations. + + So we provide additional interface for getting preferred sibling's + cpumask supported by platform, this siblings' cpumask indicates those + CPUs which are clustered with relatively short distances, NOTE 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..bf937d334b81 100644 --- a/arch/arm64/kernel/topology.c +++ b/arch/arm64/kernel/topology.c @@ -348,6 +348,58 @@ 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_cpumask(unsigned int sibling, + cpumask_var_t dstp) +{ + if (!dstp) + return; + + if (sibling >= MAX_MPIDR_SIBLINGS) { + cpumask_clear(dstp); + return; + } + + cpumask_copy(dstp, &mpidr_siblings_cpumask_map[sibling]); +} +EXPORT_SYMBOL(arch_get_preferred_sibling_cpumask); +#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..80c28bfce557 100644 --- a/include/linux/arch_topology.h +++ b/include/linux/arch_topology.h @@ -32,4 +32,16 @@ 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_cpumask(unsigned int sibling, + cpumask_var_t dstp); +#else +static inline void +arch_get_preferred_sibling_cpumask(unsigned int sibling, cpumask_var_t dstp) +{ + if (dstp) + cpumask_clear(dstp); +} +#endif + #endif /* _LINUX_ARCH_TOPOLOGY_H_ */