[RFC PATCH] powerpc: Implement hotplug smt control

Joel Stanley joel at jms.id.au
Thu Feb 17 18:04:19 AEDT 2022


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 <joel at 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 <joel at 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



More information about the Linuxppc-dev mailing list