diff options
author | Srikar Dronamraju <srikar@linux.vnet.ibm.com> | 2021-04-15 17:39:34 +0530 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2021-04-17 10:40:51 +1000 |
commit | c1e53367dab15e41814cff4e37df8ec4ac8fb9d7 (patch) | |
tree | 490cad3a7a3e381380a82bed254bb9180bc92785 /arch/powerpc/kernel/smp.c | |
parent | 131c82b6a1d261705a6f98368e501d43d994018d (diff) | |
download | linux-c1e53367dab15e41814cff4e37df8ec4ac8fb9d7.tar.gz linux-c1e53367dab15e41814cff4e37df8ec4ac8fb9d7.tar.bz2 linux-c1e53367dab15e41814cff4e37df8ec4ac8fb9d7.zip |
powerpc/smp: Cache CPU to chip lookup
On systems with large CPUs per node, even with the filtered matching of
related CPUs, there can be large number of calls to cpu_to_chip_id for
the same CPU. For example with 4096 vCPU, 1 node QEMU configuration,
with 4 threads per core, system could be see upto 1024 calls to
cpu_to_chip_id() for the same CPU. On a given system, cpu_to_chip_id()
for a given CPU would always return the same. Hence cache the result in
a lookup table for use in subsequent calls.
Since all CPUs sharing the same core will belong to the same chip, the
lookup_table has an entry for one CPU per core. chip_id_lookup_table is
not being freed and would be used on subsequent CPU online post CPU
offline.
Reported-by: Daniel Henrique Barboza <danielhb413@gmail.com>
Suggested-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Tested-by: Daniel Henrique Barboza <danielhb413@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20210415120934.232271-4-srikar@linux.vnet.ibm.com
Diffstat (limited to 'arch/powerpc/kernel/smp.c')
-rw-r--r-- | arch/powerpc/kernel/smp.c | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index f8576a2f34a0..ad3e97472679 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -1073,6 +1073,20 @@ void __init smp_prepare_cpus(unsigned int max_cpus) cpu_smallcore_mask(boot_cpuid)); } + if (cpu_to_chip_id(boot_cpuid) != -1) { + int idx = num_possible_cpus() / threads_per_core; + + /* + * All threads of a core will all belong to the same core, + * chip_id_lookup_table will have one entry per core. + * Assumption: if boot_cpuid doesn't have a chip-id, then no + * other CPUs, will also not have chip-id. + */ + chip_id_lookup_table = kcalloc(idx, sizeof(int), GFP_KERNEL); + if (chip_id_lookup_table) + memset(chip_id_lookup_table, -1, sizeof(int) * idx); + } + if (smp_ops && smp_ops->probe) smp_ops->probe(); } @@ -1468,8 +1482,8 @@ static void add_cpu_to_masks(int cpu) { struct cpumask *(*submask_fn)(int) = cpu_sibling_mask; int first_thread = cpu_first_thread_sibling(cpu); - int chip_id = cpu_to_chip_id(cpu); cpumask_var_t mask; + int chip_id = -1; bool ret; int i; @@ -1492,7 +1506,10 @@ static void add_cpu_to_masks(int cpu) if (has_coregroup_support()) update_coregroup_mask(cpu, &mask); - if (chip_id == -1 || !ret) { + if (chip_id_lookup_table && ret) + chip_id = cpu_to_chip_id(cpu); + + if (chip_id == -1) { cpumask_copy(per_cpu(cpu_core_map, cpu), cpu_cpu_mask(cpu)); goto out; } |