x86 added a control for turning SMT on and off in commit 05736e4ac13c ("cpu/hotplug: Provide knobs to control SMT").
Implement this for powerpc as an alternative to the currently method of iterating through /sys/devices/system/cpu/cpuN/online for every CPU. # ppc64_cpu --info Core 0: 0* 1* 2* 3* 4* 5* 6* 7* Core 1: 8* 9* 10* 11* 12* 13* 14* 15* # grep . /sys/devices/system/cpu/smt/* /sys/devices/system/cpu/smt/active:1 /sys/devices/system/cpu/smt/control:on # echo off > /sys/devices/system/cpu/smt/control # ppc64_cpu --info Core 0: 0* 1 2 3 4 5 6 7 Core 1: 8* 9 10 11 12 13 14 15 # grep . /sys/devices/system/cpu/smt/* /sys/devices/system/cpu/smt/active:0 /sys/devices/system/cpu/smt/control:off Signed-off-by: Joel Stanley <j...@jms.id.au> --- This is a RFC as there are bugs: - Booting with nosmt results in a WARN for every sibling thread smp: Bringing up secondary CPUs ... CPU UP failed (-125) CPU 1 state (null) (151) ------------[ cut here ]------------ WARNING: CPU: 0 PID: 1 at kernel/cpu.c:711 _cpu_up+0x304/0x310 Modules linked in: CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.17.0-rc4-00055-g2db720040f59-dirty #8 ... NIP [c000000000136ac4] _cpu_up+0x304/0x310 LR [c000000000136ac4] _cpu_up+0x304/0x310 Call Trace: [c000000008503ab0] [c000000000136ac4] _cpu_up+0x304/0x310 (unreliable) [c000000008503b60] [c000000000136be4] cpu_up+0x114/0x1b0 [c000000008503c00] [c000000000137538] bringup_nonboot_cpus+0xb8/0x110 [c000000008503c60] [c000000002031838] smp_init+0x48/0xd4 [c000000008503cc0] [c0000000020048f4] kernel_init_freeable+0x20c/0x3dc [c000000008503da0] [c0000000000127a4] kernel_init+0x34/0x1a0 [c000000008503e10] [c00000000000cd64] ret_from_kernel_thread+0x5c/0x64 Instruction dump: 1d270028 7cca482a 48089689 60000000 7ec4b378 7f03c378 4bffd45d 7ec6b378 7f05c378 7f84e378 38600000 4bffe919 <0b030000> eac10060 4bfffe64 3c4c0271 ---[ end trace 0000000000000000 ]--- and then you can get a BUG at runtime if you fiddle with the online state: # ppc64_cpu --smt=on # ppc64_cpu --info Core 0: 0* 1* 2* 3* 4* 5* 6* 7* Core 1: 8* 9* 10* 11* 12* 13* 14* 15* # ppc64_cpu --smt=off [ 95.643467][ T203] ------------[ cut here ]------------ [ 95.643556][ T203] kernel BUG at kernel/irq_work.c:235! [ 95.643633][ T203] Oops: Exception in kernel mode, sig: 5 [#1] - Using the smt control to turn off SMT means you cannot online those CPUs with /sys/devices/system/cpu/cpuN/online (returns EPERM) # ppc64_cpu --info Core 0: 0* 1* 2* 3* 4* 5* 6* 7* Core 1: 8* 9* 10* 11* 12* 13* 14* 15* # echo off > /sys/devices/system/cpu/smt/control # ppc64_cpu --info Core 0: 0* 1 2 3 4 5 6 7 Core 1: 8* 9 10 11 12 13 14 15 # grep . /sys/devices/system/cpu/smt/* /sys/devices/system/cpu/smt/active:0 /sys/devices/system/cpu/smt/control:off # ppc64_cpu --smt=on One or more cpus could not be on/offlined # strace ppc64_cpu --smt=on openat(AT_FDCWD, "/sys/devices/system/cpu/cpu0/online", O_RDONLY) = 3 newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=65536, ...}, AT_EMPTY_PATH) = 0 read(3, "1\n", 8192) = 2 close(3) = 0 openat(AT_FDCWD, "/sys/devices/system/cpu/cpu0/online", O_WRONLY) = 3 write(3, "1", 1) = 1 close(3) = 0 openat(AT_FDCWD, "/sys/devices/system/cpu/cpu1/online", O_WRONLY) = 3 write(3, "1", 1) = -1 EPERM (Operation not permitted) close(3) = 0 access("/sys/devices/system/cpu/cpu8/online", F_OK) = 0 openat(AT_FDCWD, "/sys/devices/system/cpu/cpu8/online", O_RDONLY) = 3 newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=65536, ...}, AT_EMPTY_PATH) = 0 read(3, "1\n", 8192) = 2 close(3) = 0 openat(AT_FDCWD, "/sys/devices/system/cpu/cpu8/online", O_WRONLY) = 3 write(3, "1", 1) = 1 close(3) = 0 openat(AT_FDCWD, "/sys/devices/system/cpu/cpu9/online", O_WRONLY) = 3 write(3, "1", 1) = -1 EPERM (Operation not permitted) close(3) = 0 write(2, "One or more cpus could not be on"..., 42One or more cpus could not be on/offlined - Setting smt off with the online interface doesn't update the status of the smt control sysfs file (but does update the active file): # ppc64_cpu --smt=off # grep . /sys/devices/system/cpu/smt/* /sys/devices/system/cpu/smt/active:0 /sys/devices/system/cpu/smt/control:on Signed-off-by: Joel Stanley <j...@jms.id.au> --- arch/powerpc/include/asm/topology.h | 8 ++++++++ arch/powerpc/kernel/smp.c | 10 ++++++++++ arch/powerpc/Kconfig | 1 + 3 files changed, 19 insertions(+) diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h index 36fcafb1fd6d..58280ca4321c 100644 --- a/arch/powerpc/include/asm/topology.h +++ b/arch/powerpc/include/asm/topology.h @@ -147,5 +147,13 @@ static inline int cpu_to_coregroup_id(int cpu) #endif #endif +#ifdef CONFIG_HOTPLUG_CPU +bool topology_is_primary_thread(unsigned int cpu); +bool topology_smt_supported(void); +#else +static inline bool topology_is_primary_thread(unsigned int cpu) { return true; } +static inline bool topology_smt_supported(void) { return false; } +#endif + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_TOPOLOGY_H */ diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index b7fd6a72aa76..24bd98401c91 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -1781,4 +1781,14 @@ void arch_cpu_idle_dead(void) start_secondary_resume(); } +bool topology_smt_supported(void) +{ + return cpu_has_feature(CPU_FTR_SMT); +} + +bool topology_is_primary_thread(unsigned int cpu) +{ + return cpu_thread_in_core(cpu) == 0; +} + #endif diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index b779603978e1..a3e3d5de4d39 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -239,6 +239,7 @@ config PPC select HAVE_STATIC_CALL if PPC32 select HAVE_SYSCALL_TRACEPOINTS select HAVE_VIRT_CPU_ACCOUNTING + select HOTPLUG_SMT if SMP select HUGETLB_PAGE_SIZE_VARIABLE if PPC_BOOK3S_64 && HUGETLB_PAGE select IOMMU_HELPER if PPC64 select IRQ_DOMAIN -- 2.34.1