Skip to content

Commit

Permalink
Merge branch 'topic/cpu-smt' into merge-test
Browse files Browse the repository at this point in the history
  • Loading branch information
mpe committed Jul 29, 2023
2 parents 394fa1b + 265bb41 commit 0df4bab
Show file tree
Hide file tree
Showing 15 changed files with 196 additions and 85 deletions.
1 change: 1 addition & 0 deletions Documentation/ABI/testing/sysfs-devices-system-cpu
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,7 @@ Description: Control Symmetric Multi Threading (SMT)
================ =========================================
"on" SMT is enabled
"off" SMT is disabled
"<N>" SMT is enabled with N threads per core.
"forceoff" SMT is force disabled. Cannot be changed.
"notsupported" SMT is not supported by the CPU
"notimplemented" SMT runtime toggling is not
Expand Down
4 changes: 2 additions & 2 deletions Documentation/admin-guide/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3853,10 +3853,10 @@
nosmp [SMP] Tells an SMP kernel to act as a UP kernel,
and disable the IO APIC. legacy for "maxcpus=0".

nosmt [KNL,MIPS,S390] Disable symmetric multithreading (SMT).
nosmt [KNL,MIPS,PPC,S390] Disable symmetric multithreading (SMT).
Equivalent to smt=1.

[KNL,X86] Disable symmetric multithreading (SMT).
[KNL,X86,PPC] Disable symmetric multithreading (SMT).
nosmt=force: Force disable SMT, cannot be undone
via the sysfs control file.

Expand Down
3 changes: 3 additions & 0 deletions arch/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ config ARCH_HAS_SUBPAGE_FAULTS
config HOTPLUG_SMT
bool

config SMT_NUM_THREADS_DYNAMIC
bool

# Selected by HOTPLUG_CORE_SYNC_DEAD or HOTPLUG_CORE_SYNC_FULL
config HOTPLUG_CORE_SYNC
bool
Expand Down
2 changes: 2 additions & 0 deletions arch/powerpc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,8 @@ config PPC
select HAVE_SYSCALL_TRACEPOINTS
select HAVE_VIRT_CPU_ACCOUNTING
select HAVE_VIRT_CPU_ACCOUNTING_GEN
select HOTPLUG_SMT if HOTPLUG_CPU
select SMT_NUM_THREADS_DYNAMIC
select HUGETLB_PAGE_SIZE_VARIABLE if PPC_BOOK3S_64 && HUGETLB_PAGE
select IOMMU_HELPER if PPC64
select IRQ_DOMAIN
Expand Down
15 changes: 15 additions & 0 deletions arch/powerpc/include/asm/topology.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,5 +143,20 @@ static inline int cpu_to_coregroup_id(int cpu)
#endif
#endif

#ifdef CONFIG_HOTPLUG_SMT
#include <linux/cpu_smt.h>
#include <asm/cputhreads.h>

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 */
8 changes: 7 additions & 1 deletion arch/powerpc/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1088,7 +1088,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");

Expand Down Expand Up @@ -1155,6 +1155,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)
Expand Down
30 changes: 21 additions & 9 deletions arch/powerpc/platforms/pseries/hotplug-cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,14 @@ static int dlpar_online_cpu(struct device_node *dn)
for_each_present_cpu(cpu) {
if (get_hard_smp_processor_id(cpu) != thread)
continue;

if (!topology_is_primary_thread(cpu)) {
if (cpu_smt_control != CPU_SMT_ENABLED)
break;
if (!topology_smt_thread_allowed(cpu))
break;
}

cpu_maps_update_done();
find_and_update_cpu_nid(cpu);
rc = device_online(get_cpu_device(cpu));
Expand Down Expand Up @@ -845,15 +853,9 @@ static struct notifier_block pseries_smp_nb = {
.notifier_call = pseries_smp_notifier,
};

static int __init pseries_cpu_hotplug_init(void)
void __init pseries_cpu_hotplug_init(void)
{
int qcss_tok;
unsigned int node;

#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
ppc_md.cpu_probe = dlpar_cpu_probe;
ppc_md.cpu_release = dlpar_cpu_release;
#endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */

rtas_stop_self_token = rtas_function_token(RTAS_FN_STOP_SELF);
qcss_tok = rtas_function_token(RTAS_FN_QUERY_CPU_STOPPED_STATE);
Expand All @@ -862,12 +864,22 @@ static int __init pseries_cpu_hotplug_init(void)
qcss_tok == RTAS_UNKNOWN_SERVICE) {
printk(KERN_INFO "CPU Hotplug not supported by firmware "
"- disabling.\n");
return 0;
return;
}

smp_ops->cpu_offline_self = pseries_cpu_offline_self;
smp_ops->cpu_disable = pseries_cpu_disable;
smp_ops->cpu_die = pseries_cpu_die;
}

static int __init pseries_dlpar_init(void)
{
unsigned int node;

#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
ppc_md.cpu_probe = dlpar_cpu_probe;
ppc_md.cpu_release = dlpar_cpu_release;
#endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */

/* Processors can be added/removed only on LPAR */
if (firmware_has_feature(FW_FEATURE_LPAR)) {
Expand All @@ -886,4 +898,4 @@ static int __init pseries_cpu_hotplug_init(void)

return 0;
}
machine_arch_initcall(pseries, pseries_cpu_hotplug_init);
machine_arch_initcall(pseries, pseries_dlpar_init);
2 changes: 2 additions & 0 deletions arch/powerpc/platforms/pseries/pseries.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,13 @@ static inline int dlpar_hp_pmem(struct pseries_hp_errorlog *hp_elog)

#ifdef CONFIG_HOTPLUG_CPU
int dlpar_cpu(struct pseries_hp_errorlog *hp_elog);
void pseries_cpu_hotplug_init(void);
#else
static inline int dlpar_cpu(struct pseries_hp_errorlog *hp_elog)
{
return -EOPNOTSUPP;
}
static inline void pseries_cpu_hotplug_init(void) { }
#endif

/* PCI root bridge prepare function override for pseries */
Expand Down
2 changes: 2 additions & 0 deletions arch/powerpc/platforms/pseries/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,8 @@ static void __init pSeries_setup_arch(void)
/* Discover PIC type and setup ppc_md accordingly */
smp_init_pseries();

// Setup CPU hotplug callbacks
pseries_cpu_hotplug_init();

if (radix_enabled() && !mmu_has_feature(MMU_FTR_GTSE))
if (!firmware_has_feature(FW_FEATURE_RPT_INVALIDATE))
Expand Down
4 changes: 2 additions & 2 deletions arch/x86/include/asm/topology.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,11 @@ static inline int topology_max_smt_threads(void)
return __max_smt_threads;
}

#include <linux/cpu_smt.h>

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);
bool topology_smt_supported(void);

extern struct cpumask __cpu_primary_thread_mask;
#define cpu_primary_thread_mask ((const struct cpumask *)&__cpu_primary_thread_mask)
Expand All @@ -162,7 +163,6 @@ static inline int topology_phys_to_logical_pkg(unsigned int pkg) { 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 /* !CONFIG_SMP */

static inline void arch_fix_phys_package_id(int num, u32 slot)
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/kernel/cpu/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -2319,7 +2319,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: ");
Expand Down
8 changes: 0 additions & 8 deletions arch/x86/kernel/smpboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -326,14 +326,6 @@ static void notrace start_secondary(void *unused)
cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
}

/**
* topology_smt_supported - Check whether SMT is supported by the CPUs
*/
bool topology_smt_supported(void)
{
return smp_num_siblings > 1;
}

/**
* topology_phys_to_logical_pkg - Map a physical package id to a logical
* @phys_pkg: The physical package id to map
Expand Down
25 changes: 1 addition & 24 deletions include/linux/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <linux/compiler.h>
#include <linux/cpumask.h>
#include <linux/cpuhotplug.h>
#include <linux/cpu_smt.h>

struct device;
struct device_node;
Expand Down Expand Up @@ -204,30 +205,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);

Expand Down
33 changes: 33 additions & 0 deletions include/linux/cpu_smt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* 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 unsigned int cpu_smt_num_threads;
extern void cpu_smt_disable(bool force);
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_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; }
#endif

#endif /* _LINUX_CPU_SMT_H_ */
Loading

0 comments on commit 0df4bab

Please sign in to comment.