Skip to content

Commit 30bb981

Browse files
Andi KleenKAGA-KOKO
authored andcommitted
x86/topology: Avoid wasting 128k for package id array
Analyzing large early boot allocations unveiled the logical package id storage as a prominent memory waste. Since commit 1f12e32 ("x86/topology: Create logical package id") every 64-bit system allocates a 128k array to convert logical package ids. This happens because the array is sized for MAX_LOCAL_APIC which is always 32k on 64bit systems, and it needs 4 bytes for each entry. This is fairly wasteful, especially for the common case of having only one socket, which uses exactly 4 byte out of 128K. There is no user of the package id map which is performance critical, so the lookup is not required to be O(1). Store the logical processor id in cpu_data and use a loop based lookup. To keep the mapping stable accross cpu hotplug operations, add a flag to cpu_data which is set when the CPU is brought up the first time. When the flag is set, then cpu_data is not reinitialized by copying boot_cpu_data on subsequent bringups. [ tglx: Rename the flag to 'initialized', use proper pointers instead of repeated cpu_data(x) evaluation and massage changelog. ] Signed-off-by: Andi Kleen <[email protected]> Signed-off-by: Prarit Bhargava <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Cc: Tom Lendacky <[email protected]> Cc: Christian Borntraeger <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Kan Liang <[email protected]> Cc: He Chen <[email protected]> Cc: Stephane Eranian <[email protected]> Cc: Dave Hansen <[email protected]> Cc: Piotr Luc <[email protected]> Cc: Andy Lutomirski <[email protected]> Cc: Arvind Yadav <[email protected]> Cc: Vitaly Kuznetsov <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: Tim Chen <[email protected]> Cc: Mathias Krause <[email protected]> Cc: "Kirill A. Shutemov" <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent d46b4c1 commit 30bb981

File tree

2 files changed

+30
-44
lines changed

2 files changed

+30
-44
lines changed

arch/x86/include/asm/processor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ struct cpuinfo_x86 {
132132
/* Index into per_cpu list: */
133133
u16 cpu_index;
134134
u32 microcode;
135+
unsigned initialized : 1;
135136
} __randomize_layout;
136137

137138
struct cpuid_regs {

arch/x86/kernel/smpboot.c

Lines changed: 29 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,6 @@ DEFINE_PER_CPU_READ_MOSTLY(struct cpuinfo_x86, cpu_info);
101101
EXPORT_PER_CPU_SYMBOL(cpu_info);
102102

103103
/* Logical package management. We might want to allocate that dynamically */
104-
static int *physical_to_logical_pkg __read_mostly;
105-
static unsigned long *physical_package_map __read_mostly;;
106-
static unsigned int max_physical_pkg_id __read_mostly;
107104
unsigned int __max_logical_packages __read_mostly;
108105
EXPORT_SYMBOL(__max_logical_packages);
109106
static unsigned int logical_packages __read_mostly;
@@ -280,24 +277,37 @@ static void notrace start_secondary(void *unused)
280277
cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
281278
}
282279

280+
/**
281+
* topology_phys_to_logical_pkg - Map a physical package id to a logical
282+
*
283+
* Returns logical package id or -1 if not found
284+
*/
285+
int topology_phys_to_logical_pkg(unsigned int phys_pkg)
286+
{
287+
int cpu;
288+
289+
for_each_possible_cpu(cpu) {
290+
struct cpuinfo_x86 *c = &cpu_data(cpu);
291+
292+
if (c->initialized && c->phys_proc_id == phys_pkg)
293+
return c->logical_proc_id;
294+
}
295+
return -1;
296+
}
297+
EXPORT_SYMBOL(topology_phys_to_logical_pkg);
298+
283299
/**
284300
* topology_update_package_map - Update the physical to logical package map
285301
* @pkg: The physical package id as retrieved via CPUID
286302
* @cpu: The cpu for which this is updated
287303
*/
288304
int topology_update_package_map(unsigned int pkg, unsigned int cpu)
289305
{
290-
unsigned int new;
291-
292-
/* Called from early boot ? */
293-
if (!physical_package_map)
294-
return 0;
295-
296-
if (pkg >= max_physical_pkg_id)
297-
return -EINVAL;
306+
int new;
298307

299-
/* Set the logical package id */
300-
if (test_and_set_bit(pkg, physical_package_map))
308+
/* Already available somewhere? */
309+
new = topology_phys_to_logical_pkg(pkg);
310+
if (new >= 0)
301311
goto found;
302312

303313
if (logical_packages >= __max_logical_packages) {
@@ -311,30 +321,14 @@ int topology_update_package_map(unsigned int pkg, unsigned int cpu)
311321
pr_info("CPU %u Converting physical %u to logical package %u\n",
312322
cpu, pkg, new);
313323
}
314-
physical_to_logical_pkg[pkg] = new;
315-
316324
found:
317-
cpu_data(cpu).logical_proc_id = physical_to_logical_pkg[pkg];
325+
cpu_data(cpu).logical_proc_id = new;
318326
return 0;
319327
}
320328

321-
/**
322-
* topology_phys_to_logical_pkg - Map a physical package id to a logical
323-
*
324-
* Returns logical package id or -1 if not found
325-
*/
326-
int topology_phys_to_logical_pkg(unsigned int phys_pkg)
327-
{
328-
if (phys_pkg >= max_physical_pkg_id)
329-
return -1;
330-
return physical_to_logical_pkg[phys_pkg];
331-
}
332-
EXPORT_SYMBOL(topology_phys_to_logical_pkg);
333-
334329
static void __init smp_init_package_map(struct cpuinfo_x86 *c, unsigned int cpu)
335330
{
336331
unsigned int ncpus;
337-
size_t size;
338332

339333
/*
340334
* Today neither Intel nor AMD support heterogenous systems. That
@@ -365,19 +359,6 @@ static void __init smp_init_package_map(struct cpuinfo_x86 *c, unsigned int cpu)
365359
}
366360

367361
__max_logical_packages = DIV_ROUND_UP(total_cpus, ncpus);
368-
logical_packages = 0;
369-
370-
/*
371-
* Possibly larger than what we need as the number of apic ids per
372-
* package can be smaller than the actual used apic ids.
373-
*/
374-
max_physical_pkg_id = DIV_ROUND_UP(MAX_LOCAL_APIC, ncpus);
375-
size = max_physical_pkg_id * sizeof(unsigned int);
376-
physical_to_logical_pkg = kmalloc(size, GFP_KERNEL);
377-
memset(physical_to_logical_pkg, 0xff, size);
378-
size = BITS_TO_LONGS(max_physical_pkg_id) * sizeof(unsigned long);
379-
physical_package_map = kzalloc(size, GFP_KERNEL);
380-
381362
pr_info("Max logical packages: %u\n", __max_logical_packages);
382363

383364
topology_update_package_map(c->phys_proc_id, cpu);
@@ -391,6 +372,7 @@ void __init smp_store_boot_cpu_info(void)
391372
*c = boot_cpu_data;
392373
c->cpu_index = id;
393374
smp_init_package_map(c, id);
375+
c->initialized = true;
394376
}
395377

396378
/*
@@ -401,13 +383,16 @@ void smp_store_cpu_info(int id)
401383
{
402384
struct cpuinfo_x86 *c = &cpu_data(id);
403385

404-
*c = boot_cpu_data;
386+
/* Copy boot_cpu_data only on the first bringup */
387+
if (!c->initialized)
388+
*c = boot_cpu_data;
405389
c->cpu_index = id;
406390
/*
407391
* During boot time, CPU0 has this setup already. Save the info when
408392
* bringing up AP or offlined CPU0.
409393
*/
410394
identify_secondary_cpu(c);
395+
c->initialized = true;
411396
}
412397

413398
static bool

0 commit comments

Comments
 (0)