From a8d0d9c7d855a1acbac16eecb60d7d48f6f28239 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 5 Jul 2023 16:51:35 +0200 Subject: [PATCH 1/7] cpu/SMT: Move SMT prototypes into cpu_smt.h kunpeng inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB1WB9 CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3f9169196be55590a794b52f49637561ddd1ba4f ---------------------------------------------------------------------- In order to export the cpuhp_smt_control enum as part of the interface between generic and architecture code, the architecture code needs to include asm/topology.h. But that leads to circular header dependencies. So split the enum and related declarations into a separate header. [ ldufour: Reworded the commit's description ] Signed-off-by: Michael Ellerman Signed-off-by: Laurent Dufour Signed-off-by: Thomas Gleixner Tested-by: Zhang Rui Link: https://lore.kernel.org/r/20230705145143.40545-3-ldufour@linux.ibm.com Signed-off-by: caodongxia --- arch/x86/include/asm/topology.h | 2 ++ include/linux/cpu.h | 25 +------------------------ include/linux/cpu_smt.h | 29 +++++++++++++++++++++++++++++ kernel/cpu.c | 1 + 4 files changed, 33 insertions(+), 24 deletions(-) create mode 100644 include/linux/cpu_smt.h diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h index 833575f92eac..0965b303cef9 100644 --- a/arch/x86/include/asm/topology.h +++ b/arch/x86/include/asm/topology.h @@ -135,6 +135,8 @@ static inline int topology_max_smt_threads(void) return __max_smt_threads; } +#include + int topology_update_package_map(unsigned int apicid, unsigned int cpu); int topology_update_die_map(unsigned int dieid, unsigned int cpu); int topology_phys_to_logical_pkg(unsigned int pkg); diff --git a/include/linux/cpu.h b/include/linux/cpu.h index 623e764cab13..62f9a3b3dba5 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -18,6 +18,7 @@ #include #include #include +#include #ifndef __GENKSYMS__ #include #endif @@ -221,30 +222,6 @@ void cpuhp_report_idle_dead(void); static inline void cpuhp_report_idle_dead(void) { } #endif /* #ifdef CONFIG_HOTPLUG_CPU */ -enum cpuhp_smt_control { - CPU_SMT_ENABLED, - CPU_SMT_DISABLED, - CPU_SMT_FORCE_DISABLED, - CPU_SMT_NOT_SUPPORTED, - CPU_SMT_NOT_IMPLEMENTED, -}; - -#if defined(CONFIG_SMP) && defined(CONFIG_HOTPLUG_SMT) -extern enum cpuhp_smt_control cpu_smt_control; -extern void cpu_smt_disable(bool force); -extern void cpu_smt_check_topology(void); -extern bool cpu_smt_possible(void); -extern int cpuhp_smt_enable(void); -extern int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval); -#else -# define cpu_smt_control (CPU_SMT_NOT_IMPLEMENTED) -static inline void cpu_smt_disable(bool force) { } -static inline void cpu_smt_check_topology(void) { } -static inline bool cpu_smt_possible(void) { return false; } -static inline int cpuhp_smt_enable(void) { return 0; } -static inline int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval) { return 0; } -#endif - extern bool cpu_mitigations_off(void); extern bool cpu_mitigations_auto_nosmt(void); diff --git a/include/linux/cpu_smt.h b/include/linux/cpu_smt.h new file mode 100644 index 000000000000..722c2e306fef --- /dev/null +++ b/include/linux/cpu_smt.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_CPU_SMT_H_ +#define _LINUX_CPU_SMT_H_ + +enum cpuhp_smt_control { + CPU_SMT_ENABLED, + CPU_SMT_DISABLED, + CPU_SMT_FORCE_DISABLED, + CPU_SMT_NOT_SUPPORTED, + CPU_SMT_NOT_IMPLEMENTED, +}; + +#if defined(CONFIG_SMP) && defined(CONFIG_HOTPLUG_SMT) +extern enum cpuhp_smt_control cpu_smt_control; +extern void cpu_smt_disable(bool force); +extern void cpu_smt_check_topology(void); +extern bool cpu_smt_possible(void); +extern int cpuhp_smt_enable(void); +extern int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval); +#else +# define cpu_smt_control (CPU_SMT_NOT_IMPLEMENTED) +static inline void cpu_smt_disable(bool force) { } +static inline void cpu_smt_check_topology(void) { } +static inline bool cpu_smt_possible(void) { return false; } +static inline int cpuhp_smt_enable(void) { return 0; } +static inline int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval) { return 0; } +#endif + +#endif /* _LINUX_CPU_SMT_H_ */ diff --git a/kernel/cpu.c b/kernel/cpu.c index 8dcfc18df9ca..8c7cb77bfbfe 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -394,6 +394,7 @@ static void lockdep_release_cpus_lock(void) void __weak arch_smt_update(void) { } #ifdef CONFIG_HOTPLUG_SMT + enum cpuhp_smt_control cpu_smt_control __read_mostly = CPU_SMT_ENABLED; void __init cpu_smt_disable(bool force) -- Gitee From e423bb0218cabb9b2d881552a9fee56b610819cc Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 5 Jul 2023 16:51:37 +0200 Subject: [PATCH 2/7] cpu/SMT: Store the current/max number of threads kunpeng inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB1WB9 CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=447ae4ac41130a7f127c2581a5e816bb0800b560 ---------------------------------------------------------------------- Some architectures allow partial SMT states at boot time, ie. when not all SMT threads are brought online. To support that the SMT code needs to know the maximum number of SMT threads, and also the currently configured number. The architecture code knows the max number of threads, so have the architecture code pass that value to cpu_smt_set_num_threads(). Note that although topology_max_smt_threads() exists, it is not configured early enough to be used here. As architecture, like PowerPC, allows the threads number to be set through the kernel command line, also pass that value. [ ldufour: Slightly reword the commit message ] [ ldufour: Rename cpu_smt_check_topology and add a num_threads argument ] Signed-off-by: Michael Ellerman Signed-off-by: Laurent Dufour Signed-off-by: Thomas Gleixner Tested-by: Zhang Rui Link: https://lore.kernel.org/r/20230705145143.40545-5-ldufour@linux.ibm.com Signed-off-by: caodongxia --- arch/x86/kernel/cpu/common.c | 2 +- include/linux/cpu_smt.h | 8 ++++++-- kernel/cpu.c | 23 +++++++++++++++++++++-- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 9828af1f594d..f4b3f8426b26 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -2262,7 +2262,7 @@ void __init arch_cpu_finalize_init(void) * identify_boot_cpu() initialized SMT support information, let the * core code know. */ - cpu_smt_check_topology(); + cpu_smt_set_num_threads(smp_num_siblings, smp_num_siblings); if (!IS_ENABLED(CONFIG_SMP)) { pr_info("CPU: "); diff --git a/include/linux/cpu_smt.h b/include/linux/cpu_smt.h index 722c2e306fef..0c1664294b57 100644 --- a/include/linux/cpu_smt.h +++ b/include/linux/cpu_smt.h @@ -12,15 +12,19 @@ enum cpuhp_smt_control { #if defined(CONFIG_SMP) && defined(CONFIG_HOTPLUG_SMT) extern enum cpuhp_smt_control cpu_smt_control; +extern unsigned int cpu_smt_num_threads; extern void cpu_smt_disable(bool force); -extern void cpu_smt_check_topology(void); +extern void cpu_smt_set_num_threads(unsigned int num_threads, + unsigned int max_threads); extern bool cpu_smt_possible(void); extern int cpuhp_smt_enable(void); extern int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval); #else # define cpu_smt_control (CPU_SMT_NOT_IMPLEMENTED) +# define cpu_smt_num_threads 1 static inline void cpu_smt_disable(bool force) { } -static inline void cpu_smt_check_topology(void) { } +static inline void cpu_smt_set_num_threads(unsigned int num_threads, + unsigned int max_threads) { } static inline bool cpu_smt_possible(void) { return false; } static inline int cpuhp_smt_enable(void) { return 0; } static inline int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval) { return 0; } diff --git a/kernel/cpu.c b/kernel/cpu.c index 8c7cb77bfbfe..137baebdeced 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -396,6 +396,8 @@ void __weak arch_smt_update(void) { } #ifdef CONFIG_HOTPLUG_SMT enum cpuhp_smt_control cpu_smt_control __read_mostly = CPU_SMT_ENABLED; +static unsigned int cpu_smt_max_threads __ro_after_init; +unsigned int cpu_smt_num_threads __read_mostly = UINT_MAX; void __init cpu_smt_disable(bool force) { @@ -409,16 +411,33 @@ void __init cpu_smt_disable(bool force) pr_info("SMT: disabled\n"); cpu_smt_control = CPU_SMT_DISABLED; } + cpu_smt_num_threads = 1; } /* * The decision whether SMT is supported can only be done after the full * CPU identification. Called from architecture code. */ -void __init cpu_smt_check_topology(void) +void __init cpu_smt_set_num_threads(unsigned int num_threads, + unsigned int max_threads) { - if (!topology_smt_supported()) + WARN_ON(!num_threads || (num_threads > max_threads)); + + if (max_threads == 1) cpu_smt_control = CPU_SMT_NOT_SUPPORTED; + + cpu_smt_max_threads = max_threads; + + /* + * If SMT has been disabled via the kernel command line or SMT is + * not supported, set cpu_smt_num_threads to 1 for consistency. + * If enabled, take the architecture requested number of threads + * to bring up into account. + */ + if (cpu_smt_control != CPU_SMT_ENABLED) + cpu_smt_num_threads = 1; + else if (num_threads < cpu_smt_num_threads) + cpu_smt_num_threads = num_threads; } static int __init smt_cmdline_disable(char *str) -- Gitee From 6ba6f0f3a490a714411aa48e8502dd43107e2ca2 Mon Sep 17 00:00:00 2001 From: Yicong Yang Date: Tue, 21 Nov 2023 17:25:59 +0800 Subject: [PATCH 3/7] arch_topology: Support basic SMT control for the driver kunpeng inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8TAPW CVE: NA Reference: https://lore.kernel.org/all/20231121092602.47792-1-yangyicong@huawei.com/ ---------------------------------------------------------------------- The core CPU control framework supports runtime SMT control which is not yet supported by arch_topology driver and thus arch_topology based architectures. This patch implements it in the following aspects: - implement topology_is_primary_thread() to indicate the primary thread, required by the framework - architecture code can get/set the SMT thread number by topology_smt_{get, set}_num_threads() - update the SMT thread number for the framework after the topology enumerated on arm64, which is also required by the framework For disabling SMT we'll offline all the secondary threads and only leave the primary thread. Since we don't have restriction for primary thread selection, the first thread is chosen as the primary thread in this implementation. This patch only implements the basic support for SMT control, which needs to collabrate with ACPI/OF based topology building to fully enable the feature. The SMT control will be enabled unless the correct SMT thread number is set and HOTPLUG_SMT kconfig is selected. Signed-off-by: Yicong Yang Signed-off-by: Jie Liu Signed-off-by: caodongxia --- drivers/base/arch_topology.c | 39 +++++++++++++++++++++++++++++++++++ include/linux/arch_topology.h | 14 +++++++++++++ 2 files changed, 53 insertions(+) diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index cb0d6a99855e..5ca0e87b1e9e 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -563,6 +563,36 @@ const struct cpumask *cpu_clustergroup_mask(int cpu) return &cpu_topology[cpu].cluster_sibling; } +#ifdef CONFIG_HOTPLUG_SMT + +/* Maximum threads number per-Core */ +static unsigned int topology_smt_num_threads = 1; + +void __init topology_smt_set_num_threads(unsigned int num_threads) +{ + topology_smt_num_threads = num_threads; +} + +unsigned int __init topology_smt_get_num_threads(void) +{ + return topology_smt_num_threads; +} + +/* + * On SMT Hotplug the primary thread of the SMT won't be disabled. For x86 they + * seem to have a primary thread for special purpose. For other arthitectures + * like arm64 there's no such restriction for a primary thread, so make the + * first thread in the SMT as the primary thread. + */ +bool topology_is_primary_thread(unsigned int cpu) +{ + if (cpu == cpumask_first(topology_sibling_cpumask(cpu))) + return true; + + return false; +} +#endif + void update_siblings_masks(unsigned int cpuid) { struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid]; @@ -664,5 +694,14 @@ void __init init_cpu_topology(void) reset_cpu_topology(); else if (of_have_populated_dt() && parse_dt_topology()) reset_cpu_topology(); + + /* + * By this stage we get to know whether we support SMT or not, update + * the information for the core. We don't support + * CONFIG_SMT_NUM_THREADS_DYNAMIC so make the max_threads == num_threads. + */ + cpu_smt_set_num_threads(topology_smt_get_num_threads(), + topology_smt_get_num_threads()); + } #endif diff --git a/include/linux/arch_topology.h b/include/linux/arch_topology.h index 94775f3cfcaf..64a05d38a45f 100644 --- a/include/linux/arch_topology.h +++ b/include/linux/arch_topology.h @@ -80,6 +80,20 @@ void update_siblings_masks(unsigned int cpu); void remove_cpu_topology(unsigned int cpuid); void reset_cpu_topology(void); int parse_acpi_topology(void); + +#ifdef CONFIG_HOTPLUG_SMT +bool topology_is_primary_thread(unsigned int cpu); +void topology_smt_set_num_threads(unsigned int num_threads); +unsigned int topology_smt_get_num_threads(void); +#else +static inline bool topology_is_primary_thread(unsigned int cpu) { return false; } +static inline void topology_smt_set_num_threads(unsigned int num_threads) { } +static inline unsigned int topology_smt_get_num_threads(void) +{ + return 1; +} +#endif + #endif #endif /* _LINUX_ARCH_TOPOLOGY_H_ */ -- Gitee From 1e4cc203e3036c57be87c583b1b2131e6afd3b10 Mon Sep 17 00:00:00 2001 From: Yicong Yang Date: Tue, 21 Nov 2023 17:26:00 +0800 Subject: [PATCH 4/7] arch_topology: Support SMT control for OF based system kunpeng inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8TAPW CVE: NA Reference: https://lore.kernel.org/all/20231121092602.47792-1-yangyicong@huawei.com/ ---------------------------------------------------------------------- On building the topology from the devicetree, we've already gotten the SMT thread number of each core. Update the largest SMT thread number to enable the SMT control. Signed-off-by: Yicong Yang Signed-off-by: Jie Liu Signed-off-by: caodongxia --- drivers/base/arch_topology.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index 5ca0e87b1e9e..ba1c8e1ff0b6 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -399,6 +399,13 @@ static int __init parse_core(struct device_node *core, int package_id, i++; } while (t); + /* + * We've already gotten threads number in this core, update the SMT + * threads number when necessary. + */ + if (i > topology_smt_get_num_threads()) + topology_smt_set_num_threads(i); + cpu = get_cpu_for_node(core); if (cpu >= 0) { if (!leaf) { -- Gitee From e129309b2d5feaebc3ee71fd86412ee0373754eb Mon Sep 17 00:00:00 2001 From: Yicong Yang Date: Tue, 21 Nov 2023 17:26:01 +0800 Subject: [PATCH 5/7] arm64: topology: Support SMT control on ACPI based system kunpeng inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8TAPW CVE: NA Reference: https://lore.kernel.org/all/20231121092602.47792-1-yangyicong@huawei.com/ ---------------------------------------------------------------------- For ACPI we'll build the topology from PPTT and we cannot directly get the SMT number of each core. Instead using a temporary xarray to record the SMT number of each core when building the topology and we can know the largest SMT number in the system. Then we can notify the arch_topology for supporting SMT control. Signed-off-by: Yicong Yang Signed-off-by: Jie Liu Signed-off-by: caodongxia --- arch/arm64/kernel/topology.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c index 0c9f986e3c6b..785de5b9696d 100644 --- a/arch/arm64/kernel/topology.c +++ b/arch/arm64/kernel/topology.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -90,11 +91,16 @@ static bool __init acpi_cpu_is_threaded(int cpu) */ int __init parse_acpi_topology(void) { + int thread_num, max_smt_thread_num = 1; + struct xarray core_threads; int cpu, topology_id, ret; + void *entry; if (acpi_disabled) return 0; + xa_init(&core_threads); + ret = acpi_pptt_init(); if (ret) return ret; @@ -110,6 +116,20 @@ int __init parse_acpi_topology(void) cpu_topology[cpu].thread_id = topology_id; topology_id = find_acpi_cpu_topology(cpu, 1); cpu_topology[cpu].core_id = topology_id; + + entry = xa_load(&core_threads, topology_id); + if (!entry) { + xa_store(&core_threads, topology_id, + xa_mk_value(1), GFP_KERNEL); + } else { + thread_num = xa_to_value(entry); + thread_num++; + xa_store(&core_threads, topology_id, + xa_mk_value(thread_num), GFP_KERNEL); + + if (thread_num > max_smt_thread_num) + max_smt_thread_num = thread_num; + } } else { cpu_topology[cpu].thread_id = -1; cpu_topology[cpu].core_id = topology_id; @@ -132,6 +152,9 @@ int __init parse_acpi_topology(void) } } + topology_smt_set_num_threads(max_smt_thread_num); + + xa_destroy(&core_threads); return 0; } #endif -- Gitee From 79841f47c49e9dc4c1ae5676515cd2b66b0a9a3d Mon Sep 17 00:00:00 2001 From: Yicong Yang Date: Tue, 21 Nov 2023 17:26:02 +0800 Subject: [PATCH 6/7] arm64: Kconfig: Enable HOTPLUG_SMT kunpeng inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8TAPW CVE: NA Reference: https://lore.kernel.org/all/20231121092602.47792-1-yangyicong@huawei.com/ ---------------------------------------------------------------------- Enable HOTPLUG_SMT for SMT control. Signed-off-by: Yicong Yang Signed-off-by: Jie Liu Signed-off-by: caodongxia --- arch/arm64/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 8b8f48b2a51e..c57dfa47937f 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -198,6 +198,7 @@ config ARM64 select HAVE_GENERIC_VDSO select HOLES_IN_ZONE select IOMMU_DMA if IOMMU_SUPPORT + select HOTPLUG_SMT if (SMP && HOTPLUG_CPU) select IRQ_DOMAIN select IRQ_FORCED_THREADING select KASAN_VMALLOC if KASAN_GENERIC -- Gitee From 9a8a34f651b9dbd813cc33e83158e37f99c139f2 Mon Sep 17 00:00:00 2001 From: Jie Liu Date: Tue, 30 Jan 2024 09:03:55 +0800 Subject: [PATCH 7/7] config: enable CONFIG_HOTPLUG_SMT for arm64 kunpeng inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8TAPW CVE: NA ---------------------------------------------------------------------- Set CONFIG_HOTPLUG_SMT=y in arm64 openeuler_defconfig. Signed-off-by: Jie Liu Signed-off-by: caodongxia --- arch/arm64/configs/openeuler_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig index 83bb2e111a10..4c117f2f55f1 100644 --- a/arch/arm64/configs/openeuler_defconfig +++ b/arch/arm64/configs/openeuler_defconfig @@ -826,6 +826,7 @@ CONFIG_QUICK_KEXEC=y CONFIG_HAVE_IMA_KEXEC=y CONFIG_ARCH_WANT_RESERVE_CRASH_KERNEL=y CONFIG_OPROFILE_NMI_TIMER=y +CONFIG_HOTPLUG_SMT=y CONFIG_KPROBES=y CONFIG_JUMP_LABEL=y # CONFIG_STATIC_KEYS_SELFTEST is not set -- Gitee