Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
f23462b
powerpc/smp: Enable Asym packing for cores on shared processor
srikard Dec 14, 2023
fe72193
powerpc/smp: Disable MC domain for shared processor
srikard Dec 14, 2023
11da578
powerpc/smp: Add __ro_after_init attribute
srikard Dec 14, 2023
c8c506a
powerpc/smp: Avoid asym packing within thread_group of a core
srikard Dec 14, 2023
60475f1
powerpc/smp: Dynamically build Powerpc topology
srikard Dec 14, 2023
7c945a9
bitmap: Define a cleanup function for bitmaps
Dec 16, 2025
2a66e4d
sched: Create architecture specific sched domain distances
pdxChen Dec 16, 2025
d2a4bf3
sched/topology: Fix sched domain build error for GNR, CWF in SNC-3 mode
pdxChen Dec 16, 2025
cf577f5
sched/topology,x86: Fix build warning
Sep 17, 2026
bff1680
x86/mm: Don't print out SRAT table information
lrq-max Aug 6, 2024
c2782ea
x86/topology: Remove x86_smt_flags and use cpu_smt_flags directly
kudureranganath Dec 23, 2024
a532442
sched: Move sched domain name out of CONFIG_SCHED_DEBUG
SSapkal Sep 17, 2026
936c603
smpboot: introduce SDTL_INIT() helper to tidy sched topology setup
FirstLoveLife Sep 17, 2026
ebcdc58
x86/smpboot: remove redundant CONFIG_SCHED_SMT
FirstLoveLife Jul 10, 2025
aaad9c0
x86/smpboot: moves x86_topology to static initialize and truncate
FirstLoveLife Jul 10, 2025
5836eaa
x86/smpboot: avoid SMT domain attach/destroy if SMT is not enabled
FirstLoveLife Apr 14, 2026
286917f
x86/numa: Store extra copy of numa_nodes_parsed
Apr 14, 2026
ac0e964
x86/topo: Add topology_num_nodes_per_package()
Apr 14, 2026
e87fecb
x86/topo: Replace x86_has_numa_in_package
Apr 14, 2026
09884a3
x86/topo: Fix SNC topology mess
Mar 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 63 additions & 52 deletions arch/powerpc/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,10 @@ static DEFINE_PER_CPU(int, cpu_state) = { 0 };
#endif

struct task_struct *secondary_current;
bool has_big_cores;
bool coregroup_enabled;
bool thread_group_shares_l2;
bool thread_group_shares_l3;
bool has_big_cores __ro_after_init;
bool coregroup_enabled __ro_after_init;
bool thread_group_shares_l2 __ro_after_init;
bool thread_group_shares_l3 __ro_after_init;

DEFINE_PER_CPU(cpumask_var_t, cpu_sibling_map);
DEFINE_PER_CPU(cpumask_var_t, cpu_smallcore_map);
Expand All @@ -93,15 +93,6 @@ EXPORT_PER_CPU_SYMBOL(cpu_l2_cache_map);
EXPORT_PER_CPU_SYMBOL(cpu_core_map);
EXPORT_SYMBOL_GPL(has_big_cores);

enum {
#ifdef CONFIG_SCHED_SMT
smt_idx,
#endif
cache_idx,
mc_idx,
die_idx,
};

#define MAX_THREAD_LIST_SIZE 8
#define THREAD_GROUP_SHARE_L1 1
#define THREAD_GROUP_SHARE_L2_L3 2
Expand Down Expand Up @@ -989,7 +980,7 @@ static int __init init_thread_group_cache_map(int cpu, int cache_property)
return 0;
}

static bool shared_caches;
static bool shared_caches __ro_after_init;

#ifdef CONFIG_SCHED_SMT
/* cpumask of CPUs with asymmetric SMT dependency */
Expand All @@ -1005,6 +996,13 @@ static int powerpc_smt_flags(void)
}
#endif

/*
* On shared processor LPARs scheduled on a big core (which has two or more
* independent thread groups per core), prefer lower numbered CPUs, so
* that workload consolidates to lesser number of cores.
*/
static __ro_after_init DEFINE_STATIC_KEY_FALSE(splpar_asym_pack);

/*
* P9 has a slightly odd architecture where pairs of cores share an L2 cache.
* This topology makes it *much* cheaper to migrate tasks between adjacent cores
Expand All @@ -1013,9 +1011,20 @@ static int powerpc_smt_flags(void)
*/
static int powerpc_shared_cache_flags(void)
{
if (static_branch_unlikely(&splpar_asym_pack))
return SD_SHARE_PKG_RESOURCES | SD_ASYM_PACKING;

return SD_SHARE_PKG_RESOURCES;
}

static int powerpc_shared_proc_flags(void)
{
if (static_branch_unlikely(&splpar_asym_pack))
return SD_ASYM_PACKING;

return 0;
}

/*
* We can't just pass cpu_l2_cache_mask() directly because
* returns a non-const pointer and the compiler barfs on that.
Expand All @@ -1039,6 +1048,10 @@ static struct cpumask *cpu_coregroup_mask(int cpu)

static bool has_coregroup_support(void)
{
/* Coregroup identification not available on shared systems */
if (is_shared_processor())
return 0;

return coregroup_enabled;
}

Expand All @@ -1047,16 +1060,6 @@ static const struct cpumask *cpu_mc_mask(int cpu)
return cpu_coregroup_mask(cpu);
}

static struct sched_domain_topology_level powerpc_topology[] = {
#ifdef CONFIG_SCHED_SMT
{ cpu_smt_mask, powerpc_smt_flags, SD_INIT_NAME(SMT) },
#endif
{ shared_cache_mask, powerpc_shared_cache_flags, SD_INIT_NAME(CACHE) },
{ cpu_mc_mask, SD_INIT_NAME(MC) },
{ cpu_cpu_mask, SD_INIT_NAME(PKG) },
{ NULL, },
};

static int __init init_big_cores(void)
{
int cpu;
Expand Down Expand Up @@ -1684,43 +1687,40 @@ void start_secondary(void *unused)
BUG();
}

static void __init fixup_topology(void)
static struct sched_domain_topology_level powerpc_topology[6];

static void __init build_sched_topology(void)
{
int i;
int i = 0;

if (is_shared_processor() && has_big_cores)
static_branch_enable(&splpar_asym_pack);

#ifdef CONFIG_SCHED_SMT
if (has_big_cores) {
pr_info("Big cores detected but using small core scheduling\n");
powerpc_topology[smt_idx].mask = smallcore_smt_mask;
powerpc_topology[i++] =
SDTL_INIT(smallcore_smt_mask, powerpc_smt_flags, SMT);
} else {
powerpc_topology[i++] = SDTL_INIT(cpu_smt_mask, powerpc_smt_flags, SMT);
}
#endif
if (shared_caches) {
powerpc_topology[i++] =
SDTL_INIT(shared_cache_mask, powerpc_shared_cache_flags, CACHE);
}

if (!has_coregroup_support())
powerpc_topology[mc_idx].mask = powerpc_topology[cache_idx].mask;

/*
* Try to consolidate topology levels here instead of
* allowing scheduler to degenerate.
* - Dont consolidate if masks are different.
* - Dont consolidate if sd_flags exists and are different.
*/
for (i = 1; i <= die_idx; i++) {
if (powerpc_topology[i].mask != powerpc_topology[i - 1].mask)
continue;
if (has_coregroup_support()) {
powerpc_topology[i++] =
SDTL_INIT(cpu_mc_mask, powerpc_shared_proc_flags, MC);
}

if (powerpc_topology[i].sd_flags && powerpc_topology[i - 1].sd_flags &&
powerpc_topology[i].sd_flags != powerpc_topology[i - 1].sd_flags)
continue;
powerpc_topology[i++] = SDTL_INIT(cpu_cpu_mask, powerpc_shared_proc_flags, PKG);

if (!powerpc_topology[i - 1].sd_flags)
powerpc_topology[i - 1].sd_flags = powerpc_topology[i].sd_flags;
/* There must be one trailing NULL entry left. */
BUG_ON(i >= ARRAY_SIZE(powerpc_topology) - 1);

powerpc_topology[i].mask = powerpc_topology[i + 1].mask;
powerpc_topology[i].sd_flags = powerpc_topology[i + 1].sd_flags;
#ifdef CONFIG_SCHED_DEBUG
powerpc_topology[i].name = powerpc_topology[i + 1].name;
#endif
}
set_sched_topology(powerpc_topology);
}

void __init smp_cpus_done(unsigned int max_cpus)
Expand All @@ -1735,9 +1735,20 @@ void __init smp_cpus_done(unsigned int max_cpus)
smp_ops->bringup_done();

dump_numa_cpu_topology();
build_sched_topology();
}

fixup_topology();
set_sched_topology(powerpc_topology);
/*
* For asym packing, by default lower numbered CPU has higher priority.
* On shared processors, pack to lower numbered core. However avoid moving
* between thread_groups within the same core.
*/
int arch_asym_cpu_priority(int cpu)
{
if (static_branch_unlikely(&splpar_asym_pack))
return -cpu / threads_per_core;

return -cpu;
}

#ifdef CONFIG_HOTPLUG_CPU
Expand Down
10 changes: 5 additions & 5 deletions arch/s390/kernel/topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -518,11 +518,11 @@ static const struct cpumask *cpu_drawer_mask(int cpu)
}

static struct sched_domain_topology_level s390_topology[] = {
{ cpu_thread_mask, cpu_smt_flags, SD_INIT_NAME(SMT) },
{ cpu_coregroup_mask, cpu_core_flags, SD_INIT_NAME(MC) },
{ cpu_book_mask, SD_INIT_NAME(BOOK) },
{ cpu_drawer_mask, SD_INIT_NAME(DRAWER) },
{ cpu_cpu_mask, SD_INIT_NAME(PKG) },
SDTL_INIT(cpu_thread_mask, cpu_smt_flags, SMT),
SDTL_INIT(cpu_coregroup_mask, cpu_core_flags, MC),
SDTL_INIT(cpu_book_mask, NULL, BOOK),
SDTL_INIT(cpu_drawer_mask, NULL, DRAWER),
SDTL_INIT(cpu_cpu_mask, NULL, PKG),
{ NULL, },
};

Expand Down
6 changes: 6 additions & 0 deletions arch/x86/include/asm/numa.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ extern int numa_off;
*/
extern s16 __apicid_to_node[MAX_LOCAL_APIC];
extern nodemask_t numa_nodes_parsed __initdata;
extern nodemask_t numa_phys_nodes_parsed __initdata;

extern int __init numa_add_memblk(int nodeid, u64 start, u64 end);
extern void __init numa_set_distance(int from, int to, int distance);
Expand Down Expand Up @@ -57,13 +58,18 @@ extern void __init init_cpu_to_node(void);
extern void numa_add_cpu(int cpu);
extern void numa_remove_cpu(int cpu);
extern void init_gi_nodes(void);
extern int num_phys_nodes(void);
#else /* CONFIG_NUMA */
static inline void numa_set_node(int cpu, int node) { }
static inline void numa_clear_node(int cpu) { }
static inline void init_cpu_to_node(void) { }
static inline void numa_add_cpu(int cpu) { }
static inline void numa_remove_cpu(int cpu) { }
static inline void init_gi_nodes(void) { }
static inline int num_phys_nodes(void)
{
return 1;
}
#endif /* CONFIG_NUMA */

#ifdef CONFIG_DEBUG_PER_CPU_MAPS
Expand Down
8 changes: 8 additions & 0 deletions arch/x86/include/asm/topology.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ extern unsigned int __max_logical_packages;
extern unsigned int __max_threads_per_core;
extern unsigned int __num_threads_per_package;
extern unsigned int __num_cores_per_package;
extern unsigned int __num_nodes_per_package;

static inline unsigned int topology_max_packages(void)
{
Expand All @@ -169,6 +170,11 @@ static inline unsigned int topology_num_threads_per_package(void)
return __num_threads_per_package;
}

static inline unsigned int topology_num_nodes_per_package(void)
{
return __num_nodes_per_package;
}

#ifdef CONFIG_X86_LOCAL_APIC
int topology_get_logical_id(u32 apicid, enum x86_topology_domains at_level);
#else
Expand Down Expand Up @@ -305,4 +311,6 @@ static inline void freq_invariance_set_perf_ratio(u64 ratio, bool turbo_disabled
extern void arch_scale_freq_tick(void);
#define arch_scale_freq_tick arch_scale_freq_tick

extern int arch_sched_node_distance(int from, int to);

#endif /* _ASM_X86_TOPOLOGY_H */
3 changes: 3 additions & 0 deletions arch/x86/kernel/cpu/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ EXPORT_SYMBOL(__max_dies_per_package);
unsigned int __max_logical_packages __ro_after_init = 1;
EXPORT_SYMBOL(__max_logical_packages);

unsigned int __num_nodes_per_package __ro_after_init = 1;
EXPORT_SYMBOL(__num_nodes_per_package);

unsigned int __num_cores_per_package __ro_after_init = 1;
EXPORT_SYMBOL(__num_cores_per_package);

Expand Down
13 changes: 11 additions & 2 deletions arch/x86/kernel/cpu/topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <asm/io_apic.h>
#include <asm/mpspec.h>
#include <asm/smp.h>
#include <asm/numa.h>

#include "cpu.h"

Expand Down Expand Up @@ -482,11 +483,19 @@ void __init topology_init_possible_cpus(void)
set_nr_cpu_ids(allowed);

cnta = domain_weight(TOPO_PKG_DOMAIN);
cntb = domain_weight(TOPO_DIE_DOMAIN);
__max_logical_packages = cnta;

pr_info("Max. logical packages: %3u\n", __max_logical_packages);

cntb = num_phys_nodes();
__num_nodes_per_package = DIV_ROUND_UP(cntb, cnta);

pr_info("Max. logical nodes: %3u\n", cntb);
pr_info("Num. nodes per package:%3u\n", __num_nodes_per_package);

cntb = domain_weight(TOPO_DIE_DOMAIN);
__max_dies_per_package = 1U << (get_count_order(cntb) - get_count_order(cnta));

pr_info("Max. logical packages: %3u\n", cnta);
pr_info("Max. logical dies: %3u\n", cntb);
pr_info("Max. dies per package: %3u\n", __max_dies_per_package);

Expand Down
Loading