From a68b8dc38168cea48f98ac2615b50be08e7c1611 Mon Sep 17 00:00:00 2001 From: huwentao Date: Mon, 27 Oct 2025 10:06:34 +0800 Subject: [PATCH 01/10] Revert "arm64: Kconfig: Enable HOTPLUG_SMT" driver inclusion category: cleanup bugzilla: https://gitee.com/openeuler/kernel/issues/IBZQQR ---------------------------------------------------------------------- This reverts commit 9a8a34f651b9dbd813cc33e83158e37f99c139f2. This reverts commit 79841f47c49e9dc4c1ae5676515cd2b66b0a9a3d. This reverts commit e129309b2d5feaebc3ee71fd86412ee0373754eb. This reverts commit 1e4cc203e3036c57be87c583b1b2131e6afd3b10. This reverts commit 6ba6f0f3a490a714411aa48e8502dd43107e2ca2. Signed-off-by: huwentao --- arch/arm64/Kconfig | 1 - arch/arm64/configs/openeuler_defconfig | 1 - arch/arm64/kernel/topology.c | 23 ------------- drivers/base/arch_topology.c | 46 -------------------------- include/linux/arch_topology.h | 14 -------- 5 files changed, 85 deletions(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 0f1accb7355f..9c120f3e518d 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -201,7 +201,6 @@ 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 diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig index 9d58c2d8eb5e..7b8a939cf436 100644 --- a/arch/arm64/configs/openeuler_defconfig +++ b/arch/arm64/configs/openeuler_defconfig @@ -831,7 +831,6 @@ 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 diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c index 4c7f3687356d..923c760e71d4 100644 --- a/arch/arm64/kernel/topology.c +++ b/arch/arm64/kernel/topology.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include @@ -91,16 +90,11 @@ 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; @@ -116,20 +110,6 @@ 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; @@ -152,9 +132,6 @@ int __init parse_acpi_topology(void) } } - topology_smt_set_num_threads(max_smt_thread_num); - - xa_destroy(&core_threads); return 0; } #endif diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index ba1c8e1ff0b6..cb0d6a99855e 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -399,13 +399,6 @@ 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) { @@ -570,36 +563,6 @@ 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]; @@ -701,14 +664,5 @@ 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 64a05d38a45f..94775f3cfcaf 100644 --- a/include/linux/arch_topology.h +++ b/include/linux/arch_topology.h @@ -80,20 +80,6 @@ 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 2dda1f07a72169fa22350559421f61565473f25a Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 5 Jul 2023 16:51:42 +0200 Subject: [PATCH 02/10] powerpc: Add HOTPLUG_SMT support mainline inclusion from mainline-v6.6-rc1 commit 73c58e7e14126466701705820c4eb47daddc357d category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBZQQR CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma.git/commit/?id=73c58e7e14126466701705820c4eb47daddc357d ---------------------------------------------------------------------- Add support for HOTPLUG_SMT, which enables the generic sysfs SMT support files in /sys/devices/system/cpu/smt, as well as the "nosmt" boot parameter. Implement the recently added hooks to allow partial SMT states, allow any number of threads per core. Tie the config symbol to HOTPLUG_CPU, which enables it on the major platforms that support SMT. If there are other platforms that want the SMT support that can be tweaked in future. Signed-off-by: Michael Ellerman [ldufour: remove topology_smt_supported] [ldufour: remove topology_smt_threads_supported] [ldufour: select CONFIG_SMT_NUM_THREADS_DYNAMIC] [ldufour: update kernel-parameters.txt] Signed-off-by: Laurent Dufour Link: https://msgid.link/20230705145143.40545-10-ldufour@linux.ibm.com Signed-off-by: huwentao --- arch/powerpc/Kconfig | 2 ++ arch/powerpc/include/asm/topology.h | 15 +++++++++++++++ arch/powerpc/kernel/smp.c | 8 +++++++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index ed06e0c32727..aff26268a242 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -242,6 +242,8 @@ config PPC select HAVE_VIRT_CPU_ACCOUNTING select HAVE_IRQ_TIME_ACCOUNTING select HAVE_RSEQ + select HOTPLUG_SMT if HOTPLUG_CPU + select SMT_NUM_THREADS_DYNAMIC select IOMMU_HELPER if PPC64 select IRQ_DOMAIN select IRQ_FORCED_THREADING diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h index 64268d4163df..a78bcd38fd72 100644 --- a/arch/powerpc/include/asm/topology.h +++ b/arch/powerpc/include/asm/topology.h @@ -147,5 +147,20 @@ static inline int cpu_to_coregroup_id(int cpu) #endif #endif +#ifdef CONFIG_HOTPLUG_SMT +#include +#include + +static inline bool topology_is_primary_thread(unsigned int cpu) +{ + return cpu == cpu_first_thread_sibling(cpu); +} + +static inline bool topology_smt_thread_allowed(unsigned int cpu) +{ + return cpu_thread_in_core(cpu) < cpu_smt_num_threads; +} +#endif + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_TOPOLOGY_H */ diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index b12e4437bf0a..95db31f9c1b5 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -991,7 +991,7 @@ static int __init init_big_cores(void) void __init smp_prepare_cpus(unsigned int max_cpus) { - unsigned int cpu; + unsigned int cpu, num_threads; DBG("smp_prepare_cpus\n"); @@ -1044,6 +1044,12 @@ void __init smp_prepare_cpus(unsigned int max_cpus) if (smp_ops && smp_ops->probe) smp_ops->probe(); + + // Initalise the generic SMT topology support + num_threads = 1; + if (smt_enabled_at_boot) + num_threads = smt_enabled_at_boot; + cpu_smt_set_num_threads(num_threads, threads_per_core); } void smp_prepare_boot_cpu(void) -- Gitee From 275ae827ef837cad504b11e890af91cfe7aeb049 Mon Sep 17 00:00:00 2001 From: Yicong Yang Date: Fri, 11 Apr 2025 11:32:03 +0800 Subject: [PATCH 03/10] cpu/SMT: Provide a default topology_is_primary_thread() driver inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBZQQR ---------------------------------------------------------------------- Currently if architectures want to support HOTPLUG_SMT they need to provide a topology_is_primary_thread() telling the framework which thread in the SMT cannot offline. However arm64 doesn't have a restriction on which thread in the SMT cannot offline, a simplest choice is that just make 1st thread as the "primary" thread. So just make this as the default implementation in the framework and let architectures like x86 that have special primary thread to override this function (which they've already done). There's no need to provide a stub function if !CONFIG_SMP or !CONFIG_HOTPLUG_SMT. In such case the testing CPU is already the 1st CPU in the SMT so it's always the primary thread. Reviewed-by: Jonathan Cameron Reviewed-by: Pierre Gondois Reviewed-by: Dietmar Eggemann Reviewed-by: Yicong Yang Signed-off-by: Yicong Yang Signed-off-by: Hongye Lin Signed-off-by: huwentao --- arch/powerpc/include/asm/topology.h | 1 + arch/x86/include/asm/topology.h | 4 +++- include/linux/topology.h | 24 ++++++++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h index a78bcd38fd72..f16d2881ee9a 100644 --- a/arch/powerpc/include/asm/topology.h +++ b/arch/powerpc/include/asm/topology.h @@ -155,6 +155,7 @@ static inline bool topology_is_primary_thread(unsigned int cpu) { return cpu == cpu_first_thread_sibling(cpu); } +#define topology_is_primary_thread topology_is_primary_thread static inline bool topology_smt_thread_allowed(unsigned int cpu) { diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h index 0965b303cef9..76c15a6cd5c8 100644 --- a/arch/x86/include/asm/topology.h +++ b/arch/x86/include/asm/topology.h @@ -143,6 +143,9 @@ int topology_phys_to_logical_pkg(unsigned int pkg); int topology_phys_to_logical_die(unsigned int die, unsigned int cpu); bool topology_is_primary_thread(unsigned int cpu); bool topology_smt_supported(void); + +#define topology_is_primary_thread topology_is_primary_thread + #else #define topology_max_packages() (1) static inline int @@ -154,7 +157,6 @@ static inline int topology_phys_to_logical_die(unsigned int die, unsigned int cpu) { return 0; } static inline int topology_max_die_per_package(void) { return 1; } static inline int topology_max_smt_threads(void) { return 1; } -static inline bool topology_is_primary_thread(unsigned int cpu) { return true; } static inline bool topology_smt_supported(void) { return false; } #endif diff --git a/include/linux/topology.h b/include/linux/topology.h index 4a6b52fa471c..034bda288225 100644 --- a/include/linux/topology.h +++ b/include/linux/topology.h @@ -213,6 +213,30 @@ static inline const struct cpumask *cpu_smt_mask(int cpu) } #endif +#ifndef topology_is_primary_thread + +#define topology_is_primary_thread topology_is_primary_thread + +static inline bool topology_is_primary_thread(unsigned int cpu) +{ + /* + * When disabling SMT the primary thread of the SMT will remain + * enabled/active. Architectures do have a special primary thread + * (e.g. x86) needs to override this function. Otherwise can make + * the first thread in the SMT as the primary thread. + * + * The sibling cpumask of an offline CPU contains always the CPU + * itself for architectures using the implementation of + * CONFIG_GENERIC_ARCH_TOPOLOGY for building their topology. + * Other architectures not using CONFIG_GENERIC_ARCH_TOPOLOGY for + * building their topology have to check whether to use this default + * implementation or to override it. + */ + return cpu == cpumask_first(topology_sibling_cpumask(cpu)); +} + +#endif + static inline const struct cpumask *cpu_cpu_mask(int cpu) { return cpumask_of_node(cpu_to_node(cpu)); -- Gitee From 42dd069a27dd40852fa3e3c1c7d74e47f2bdeaf9 Mon Sep 17 00:00:00 2001 From: Yicong Yang Date: Fri, 11 Apr 2025 11:32:04 +0800 Subject: [PATCH 04/10] arch_topology: Support SMT control for OF based system driver inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBZQQR ---------------------------------------------------------------------- On building the topology from the devicetree, we've already gotten the SMT thread number of each core. Update the largest SMT thread number and enable the SMT control by the end of topology parsing. The framework's SMT control provides two interface to the users [1] through /sys/devices/system/cpu/smt/control: 1) enable SMT by writing "on" and disable by "off" 2) enable SMT by writing max_thread_number or disable by writing 1 Both method support to completely disable/enable the SMT cores so both work correctly for symmetric SMT platform and asymmetric platform with non-SMT and one type SMT cores like: core A: 1 thread core B: X (X!=1) threads Note that for a theoretically possible multiple SMT-X (X>1) core platform the SMT control is also supported as expected but only by writing the "on/off" method. [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/ABI/testing/sysfs-devices-system-cpu#n542 Reviewed-by: Pierre Gondois Reviewed-by: Dietmar Eggemann Reviewed-by: Yicong Yang Signed-off-by: Yicong Yang Signed-off-by: Hongye Lin Signed-off-by: huwentao --- drivers/base/arch_topology.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index cb0d6a99855e..13976e771ff4 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -340,6 +341,10 @@ core_initcall(free_raw_capacity); #endif #if defined(CONFIG_ARM64) || defined(CONFIG_RISCV) + +/* Used to enable the SMT control */ +static unsigned int max_smt_thread_num = 1; + /* * This function returns the logic cpu number of the node. * There are basically three kinds of return values: @@ -399,6 +404,8 @@ static int __init parse_core(struct device_node *core, int package_id, i++; } while (t); + max_smt_thread_num = max_t(unsigned int, max_smt_thread_num, i); + cpu = get_cpu_for_node(core); if (cpu >= 0) { if (!leaf) { @@ -482,6 +489,17 @@ static int __init parse_cluster(struct device_node *cluster, int depth) if (leaf) package_id++; + /* + * Reset the max_smt_thread_num to 1 on failure. Since on failure + * we need to notify the framework the SMT is not supported, but + * max_smt_thread_num can be initialized to the SMT thread number + * of the cores which are successfully parsed. + */ + if (ret) + max_smt_thread_num = 1; + + cpu_smt_set_num_threads(max_smt_thread_num, max_smt_thread_num); + return 0; } -- Gitee From 6cb2b2efbeebcee609da4628e978c343a94e94c2 Mon Sep 17 00:00:00 2001 From: Yicong Yang Date: Fri, 11 Apr 2025 11:32:05 +0800 Subject: [PATCH 05/10] arm64: topology: Support SMT control on ACPI based system driver inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBZQQR ---------------------------------------------------------------------- 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 heterogeneous information (from ACPI_PPTT_ACPI_IDENTICAL) and SMT information of the first core in its heterogeneous CPU cluster when building the topology. Then we can know the largest SMT number in the system. If a homogeneous system's using ACPI 6.2 or later, all the CPUs should be under the root node of PPTT. There'll be only one entry in the xarray and all the CPUs in the system will be assumed identical. The framework's SMT control provides two interface to the users [1] through /sys/devices/system/cpu/smt/control: 1) enable SMT by writing "on" and disable by "off" 2) enable SMT by writing max_thread_number or disable by writing 1 Both method support to completely disable/enable the SMT cores so both work correctly for symmetric SMT platform and asymmetric platform with non-SMT and one type SMT cores like: core A: 1 thread core B: X (X!=1) threads Note that for a theoretically possible multiple SMT-X (X>1) core platform the SMT control is also supported as expected but only by writing the "on/off" method. [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/ABI/testing/sysfs-devices-system-cpu#n542 Reviewed-by: Jonathan Cameron Reviewed-by: Hanjun Guo Reviewed-by: Pierre Gondois Reviewed-by: Dietmar Eggemann Reviewed-by: Yicong Yang Signed-off-by: Yicong Yang Signed-off-by: Hongye Lin Signed-off-by: huwentao --- arch/arm64/kernel/topology.c | 54 ++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c index 923c760e71d4..4a202346242d 100644 --- a/arch/arm64/kernel/topology.c +++ b/arch/arm64/kernel/topology.c @@ -15,8 +15,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -84,12 +86,21 @@ static bool __init acpi_cpu_is_threaded(int cpu) return !!is_threaded; } +struct cpu_smt_info { + unsigned int thread_num; + int core_id; +}; + /* * Propagate the topology information of the processor_topology_node tree to the * cpu_topology array. */ int __init parse_acpi_topology(void) { + unsigned int max_smt_thread_num = 1; + struct cpu_smt_info *entry; + struct xarray hetero_cpu; + unsigned long hetero_id; int cpu, topology_id, ret; if (acpi_disabled) @@ -99,6 +110,8 @@ int __init parse_acpi_topology(void) if (ret) return ret; + xa_init(&hetero_cpu); + for_each_possible_cpu(cpu) { int i, cache_id; @@ -110,6 +123,34 @@ 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; + + /* + * In the PPTT, CPUs below a node with the 'identical + * implementation' flag have the same number of threads. + * Count the number of threads for only one CPU (i.e. + * one core_id) among those with the same hetero_id. + * See the comment of find_acpi_cpu_topology_hetero_id() + * for more details. + * + * One entry is created for each node having: + * - the 'identical implementation' flag + * - its parent not having the flag + */ + hetero_id = find_acpi_cpu_topology_hetero_id(cpu); + entry = xa_load(&hetero_cpu, hetero_id); + if (!entry) { + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + WARN_ON_ONCE(!entry); + + if (entry) { + entry->core_id = topology_id; + entry->thread_num = 1; + xa_store(&hetero_cpu, hetero_id, + entry, GFP_KERNEL); + } + } else if (entry->core_id == topology_id) { + entry->thread_num++; + } } else { cpu_topology[cpu].thread_id = -1; cpu_topology[cpu].core_id = topology_id; @@ -132,6 +173,19 @@ int __init parse_acpi_topology(void) } } + /* + * This is a short loop since the number of XArray elements is the + * number of heterogeneous CPU clusters. On a homogeneous system + * there's only one entry in the XArray. + */ + xa_for_each(&hetero_cpu, hetero_id, entry) { + max_smt_thread_num = max(max_smt_thread_num, entry->thread_num); + xa_erase(&hetero_cpu, hetero_id); + kfree(entry); + } + + cpu_smt_set_num_threads(max_smt_thread_num, max_smt_thread_num); + xa_destroy(&hetero_cpu); return 0; } #endif -- Gitee From 1c22006fd8f9f2af6061cf9120ed10677782ccb8 Mon Sep 17 00:00:00 2001 From: Yicong Yang Date: Fri, 11 Apr 2025 11:32:06 +0800 Subject: [PATCH 06/10] arm64: Kconfig: Enable HOTPLUG_SMT driver inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBZQQR ---------------------------------------------------------------------- Enable HOTPLUG_SMT for SMT control. Reviewed-by: Jonathan Cameron Reviewed-by: Pierre Gondois Reviewed-by: Dietmar Eggemann Reviewed-by: Yicong Yang Signed-off-by: Yicong Yang Signed-off-by: Hongye Lin Signed-off-by: huwentao --- arch/arm64/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 9c120f3e518d..80311e5eb083 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -201,6 +201,7 @@ config ARM64 select HAVE_GENERIC_VDSO select HOLES_IN_ZONE select IOMMU_DMA if IOMMU_SUPPORT + select HOTPLUG_SMT if HOTPLUG_CPU select IRQ_DOMAIN select IRQ_FORCED_THREADING select KASAN_VMALLOC if KASAN_GENERIC -- Gitee From f03aee44d7bdc412ddd8d0103c04370a7cc008c7 Mon Sep 17 00:00:00 2001 From: Hongye Lin Date: Fri, 18 Apr 2025 15:48:04 +0800 Subject: [PATCH 07/10] config: enable CONFIG_HOTPLUG_SMT for arm64 driver inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBZQQR ---------------------------------------------------------------------- Set CONFIG_HOTPLUG_SMT=y in arm64 openeuler_defconfig. Reviewed-by: Yicong Yang Signed-off-by: Yicong Yang Signed-off-by: Hongye Lin Signed-off-by: huwentao --- 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 7b8a939cf436..9d58c2d8eb5e 100644 --- a/arch/arm64/configs/openeuler_defconfig +++ b/arch/arm64/configs/openeuler_defconfig @@ -831,6 +831,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 From 6ff1fc2f6345d7e40a532d1b1f81d066d6b7b3c7 Mon Sep 17 00:00:00 2001 From: "Nysal Jan K.A" Date: Wed, 31 Jul 2024 08:31:13 +0530 Subject: [PATCH 08/10] powerpc/topology: Check if a core is online mainline inclusion from mainline-v6.11-rc4 commit 227bbaabe64b6f9cd98aa051454c1d4a194a8c6a category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IBZQQR CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma.git/commit/?id=227bbaabe64b6f9cd98aa051454c1d4a194a8c6a ---------------------------------------------------------------------- topology_is_core_online() checks if the core a CPU belongs to is online. The core is online if at least one of the sibling CPUs is online. The first CPU of an online core is also online in the common case, so this should be fairly quick. Fixes: 73c58e7e1412 ("powerpc: Add HOTPLUG_SMT support") Signed-off-by: Nysal Jan K.A Reviewed-by: Shrikanth Hegde Signed-off-by: Michael Ellerman Link: https://msgid.link/20240731030126.956210-3-nysal@linux.ibm.com Signed-off-by: huwentao --- arch/powerpc/include/asm/topology.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h index f16d2881ee9a..4ec2bc68c64e 100644 --- a/arch/powerpc/include/asm/topology.h +++ b/arch/powerpc/include/asm/topology.h @@ -149,6 +149,7 @@ static inline int cpu_to_coregroup_id(int cpu) #ifdef CONFIG_HOTPLUG_SMT #include +#include #include static inline bool topology_is_primary_thread(unsigned int cpu) @@ -161,6 +162,18 @@ static inline bool topology_smt_thread_allowed(unsigned int cpu) { return cpu_thread_in_core(cpu) < cpu_smt_num_threads; } + +#define topology_is_core_online topology_is_core_online +static inline bool topology_is_core_online(unsigned int cpu) +{ + int i, first_cpu = cpu_first_thread_sibling(cpu); + + for (i = first_cpu; i < first_cpu + threads_per_core; ++i) { + if (cpu_online(i)) + return true; + } + return false; +} #endif #endif /* __KERNEL__ */ -- Gitee From 257ad5ad557ebd1da622516ecd0322183fef2865 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 5 Jul 2023 16:51:39 +0200 Subject: [PATCH 09/10] cpu/SMT: Create topology_smt_thread_allowed() mainline inclusion from mainline-v6.6-rc1 commit 38253464bc821d6de6bba81bb1412ebb36f6cbd1 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IBZQQR CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma.git/commit/?id=38253464bc821d6de6bba81bb1412ebb36f6cbd1 ---------------------------------------------------------------------- Some architectures allows partial SMT states, i.e. when not all SMT threads are brought online. To support that, add an architecture helper which checks whether a given CPU is allowed to be brought online depending on how many SMT threads are currently enabled. Since this is only applicable to architecture supporting partial SMT, only these architectures should select the new configuration variable CONFIG_SMT_NUM_THREADS_DYNAMIC. For the other architectures, not supporting the partial SMT states, there is no need to define topology_cpu_smt_allowed(), the generic code assumed that all the threads are allowed or only the primary ones. Call the helper from cpu_smt_enable(), and cpu_smt_allowed() when SMT is enabled, to check if the particular thread should be onlined. Notably, also call it from cpu_smt_disable() if CPU_SMT_ENABLED, to allow offlining some threads to move from a higher to lower number of threads online. [ ldufour: Slightly reword the commit's description ] [ ldufour: Introduce CONFIG_SMT_NUM_THREADS_DYNAMIC ] Suggested-by: Thomas Gleixner 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-7-ldufour@linux.ibm.com Signed-off-by: huwentao --- arch/Kconfig | 3 +++ kernel/cpu.c | 24 +++++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/arch/Kconfig b/arch/Kconfig index d27eb1800cd9..54731054096e 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -43,6 +43,9 @@ config SET_FS config HOTPLUG_SMT bool +config SMT_NUM_THREADS_DYNAMIC + bool + config GENERIC_ENTRY bool diff --git a/kernel/cpu.c b/kernel/cpu.c index 83e1bc2fafb1..1b658c0ea922 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -447,9 +447,23 @@ static int __init smt_cmdline_disable(char *str) } early_param("nosmt", smt_cmdline_disable); +/* + * For Archicture supporting partial SMT states check if the thread is allowed. + * Otherwise this has already been checked through cpu_smt_max_threads when + * setting the SMT level. + */ +static inline bool cpu_smt_thread_allowed(unsigned int cpu) +{ +#ifdef CONFIG_SMT_NUM_THREADS_DYNAMIC + return topology_smt_thread_allowed(cpu); +#else + return true; +#endif +} + static inline bool cpu_smt_allowed(unsigned int cpu) { - if (cpu_smt_control == CPU_SMT_ENABLED) + if (cpu_smt_control == CPU_SMT_ENABLED && cpu_smt_thread_allowed(cpu)) return true; /* All CPUs are bootable if controls are not configured */ @@ -2208,6 +2222,12 @@ int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval) for_each_online_cpu(cpu) { if (topology_is_primary_thread(cpu)) continue; + /* + * Disable can be called with CPU_SMT_ENABLED when changing + * from a higher to lower number of SMT threads per core. + */ + if (ctrlval == CPU_SMT_ENABLED && cpu_smt_thread_allowed(cpu)) + continue; ret = cpu_down_maps_locked(cpu, CPUHP_OFFLINE); if (ret) break; @@ -2242,6 +2262,8 @@ int cpuhp_smt_enable(void) /* Skip online CPUs and CPUs on offline nodes */ if (cpu_online(cpu) || !node_online(cpu_to_node(cpu))) continue; + if (!cpu_smt_thread_allowed(cpu)) + continue; ret = _cpu_up(cpu, 0, CPUHP_ONLINE); if (ret) break; -- Gitee From 65a05e281f6c5b53823c15cc45abb6c168536479 Mon Sep 17 00:00:00 2001 From: "Nysal Jan K.A" Date: Wed, 31 Jul 2024 08:31:12 +0530 Subject: [PATCH 10/10] cpu/SMT: Enable SMT only if a core is online mainline inclusion from mainline-v6.11-rc4 commit 6c17ea1f3eaa330d445ac14a9428402ce4e3055e category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IBZQQR CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma.git/commit/?id=6c17ea1f3eaa330d445ac14a9428402ce4e3055e ---------------------------------------------------------------------- If a core is offline then enabling SMT should not online CPUs of this core. By enabling SMT, what is intended is either changing the SMT value from "off" to "on" or setting the SMT level (threads per core) from a lower to higher value. On PowerPC the ppc64_cpu utility can be used, among other things, to perform the following functions: ppc64_cpu --cores-on # Get the number of online cores ppc64_cpu --cores-on=X # Put exactly X cores online ppc64_cpu --offline-cores=X[,Y,...] # Put specified cores offline ppc64_cpu --smt={on|off|value} # Enable, disable or change SMT level If the user has decided to offline certain cores, enabling SMT should not online CPUs in those cores. This patch fixes the issue and changes the behaviour as described, by introducing an arch specific function topology_is_core_online(). It is currently implemented only for PowerPC. Fixes: 73c58e7e1412 ("powerpc: Add HOTPLUG_SMT support") Reported-by: Tyrel Datwyler Closes: https://groups.google.com/g/powerpc-utils-devel/c/wrwVzAAnRlI/m/5KJSoqP4BAAJ Signed-off-by: Nysal Jan K.A Reviewed-by: Shrikanth Hegde Reviewed-by: Thomas Gleixner Signed-off-by: Michael Ellerman Link: https://msgid.link/20240731030126.956210-2-nysal@linux.ibm.com Signed-off-by: huwentao --- Documentation/ABI/testing/sysfs-devices-system-cpu | 3 ++- kernel/cpu.c | 12 +++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu index bc59db0a75d2..63bec681488e 100644 --- a/Documentation/ABI/testing/sysfs-devices-system-cpu +++ b/Documentation/ABI/testing/sysfs-devices-system-cpu @@ -589,7 +589,8 @@ Description: Control Symetric Multi Threading (SMT) ================ ========================================= If control status is "forceoff" or "notsupported" writes - are rejected. + are rejected. Note that enabling SMT on PowerPC skips + offline cores. What: /sys/devices/system/cpu/cpu#/power/energy_perf_bias Date: March 2019 diff --git a/kernel/cpu.c b/kernel/cpu.c index 1b658c0ea922..319eb24dc34a 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -2252,6 +2252,16 @@ int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval) return ret; } +/** + * Check if the core a CPU belongs to is online + */ +#if !defined(topology_is_core_online) +static inline bool topology_is_core_online(unsigned int cpu) +{ + return true; +} +#endif + int cpuhp_smt_enable(void) { int cpu, ret = 0; @@ -2262,7 +2272,7 @@ int cpuhp_smt_enable(void) /* Skip online CPUs and CPUs on offline nodes */ if (cpu_online(cpu) || !node_online(cpu_to_node(cpu))) continue; - if (!cpu_smt_thread_allowed(cpu)) + if (!cpu_smt_thread_allowed(cpu) || !topology_is_core_online(cpu)) continue; ret = _cpu_up(cpu, 0, CPUHP_ONLINE); if (ret) -- Gitee