Skip to content

Commit 1f12e32

Browse files
KAGA-KOKOIngo Molnar
authored andcommitted
x86/topology: Create logical package id
For per package oriented services we must be able to rely on the number of CPU packages to be within bounds. Create a tracking facility, which - calculates the number of possible packages depending on nr_cpu_ids after boot - makes sure that the package id is within the number of possible packages. If the apic id is outside we map it to a logical package id if there is enough space available. Provide interfaces for drivers to query the mapping and do translations from physcial to logical ids. Signed-off-by: Thomas Gleixner <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Cc: Andi Kleen <[email protected]> Cc: Andrew Morton <[email protected]> Cc: Andy Lutomirski <[email protected]> Cc: Arnaldo Carvalho de Melo <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: Brian Gerst <[email protected]> Cc: Denys Vlasenko <[email protected]> Cc: H. Peter Anvin <[email protected]> Cc: Harish Chegondi <[email protected]> Cc: Jacob Pan <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: Kan Liang <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Luis R. Rodriguez <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Stephane Eranian <[email protected]> Cc: Toshi Kani <[email protected]> Cc: Vince Weaver <[email protected]> Cc: [email protected] Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Ingo Molnar <[email protected]>
1 parent 1f2569f commit 1f12e32

File tree

6 files changed

+142
-0
lines changed

6 files changed

+142
-0
lines changed

arch/x86/include/asm/processor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ struct cpuinfo_x86 {
129129
u16 booted_cores;
130130
/* Physical processor id: */
131131
u16 phys_proc_id;
132+
/* Logical processor id: */
133+
u16 logical_proc_id;
132134
/* Core id: */
133135
u16 cpu_core_id;
134136
/* Compute unit id */

arch/x86/include/asm/topology.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,12 +119,23 @@ static inline void setup_node_to_cpumask_map(void) { }
119119

120120
extern const struct cpumask *cpu_coregroup_mask(int cpu);
121121

122+
#define topology_logical_package_id(cpu) (cpu_data(cpu).logical_proc_id)
122123
#define topology_physical_package_id(cpu) (cpu_data(cpu).phys_proc_id)
123124
#define topology_core_id(cpu) (cpu_data(cpu).cpu_core_id)
124125

125126
#ifdef ENABLE_TOPO_DEFINES
126127
#define topology_core_cpumask(cpu) (per_cpu(cpu_core_map, cpu))
127128
#define topology_sibling_cpumask(cpu) (per_cpu(cpu_sibling_map, cpu))
129+
130+
extern unsigned int __max_logical_packages;
131+
#define topology_max_packages() (__max_logical_packages)
132+
int topology_update_package_map(unsigned int apicid, unsigned int cpu);
133+
extern int topology_phys_to_logical_pkg(unsigned int pkg);
134+
#else
135+
#define topology_max_packages() (1)
136+
static inline int
137+
topology_update_package_map(unsigned int apicid, unsigned int cpu) { return 0; }
138+
static inline int topology_phys_to_logical_pkg(unsigned int pkg) { return 0; }
128139
#endif
129140

130141
static inline void arch_fix_phys_package_id(int num, u32 slot)

arch/x86/kernel/apic/apic.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2077,6 +2077,20 @@ int generic_processor_info(int apicid, int version)
20772077
} else
20782078
cpu = cpumask_next_zero(-1, cpu_present_mask);
20792079

2080+
/*
2081+
* This can happen on physical hotplug. The sanity check at boot time
2082+
* is done from native_smp_prepare_cpus() after num_possible_cpus() is
2083+
* established.
2084+
*/
2085+
if (topology_update_package_map(apicid, cpu) < 0) {
2086+
int thiscpu = max + disabled_cpus;
2087+
2088+
pr_warning("ACPI: Package limit reached. Processor %d/0x%x ignored.\n",
2089+
thiscpu, apicid);
2090+
disabled_cpus++;
2091+
return -ENOSPC;
2092+
}
2093+
20802094
/*
20812095
* Validate version
20822096
*/

arch/x86/kernel/cpu/common.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -975,6 +975,8 @@ static void identify_cpu(struct cpuinfo_x86 *c)
975975
#ifdef CONFIG_NUMA
976976
numa_add_cpu(smp_processor_id());
977977
#endif
978+
/* The boot/hotplug time assigment got cleared, restore it */
979+
c->logical_proc_id = topology_phys_to_logical_pkg(c->phys_proc_id);
978980
}
979981

980982
/*

arch/x86/kernel/cpu/intel.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,19 @@ static void early_init_intel(struct cpuinfo_x86 *c)
160160
pr_info("Disabling PGE capability bit\n");
161161
setup_clear_cpu_cap(X86_FEATURE_PGE);
162162
}
163+
164+
if (c->cpuid_level >= 0x00000001) {
165+
u32 eax, ebx, ecx, edx;
166+
167+
cpuid(0x00000001, &eax, &ebx, &ecx, &edx);
168+
/*
169+
* If HTT (EDX[28]) is set EBX[16:23] contain the number of
170+
* apicids which are reserved per package. Store the resulting
171+
* shift value for the package management code.
172+
*/
173+
if (edx & (1U << 28))
174+
c->x86_coreid_bits = get_count_order((ebx >> 16) & 0xff);
175+
}
163176
}
164177

165178
#ifdef CONFIG_X86_32

arch/x86/kernel/smpboot.c

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,14 @@ DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_llc_shared_map);
9797
DEFINE_PER_CPU_READ_MOSTLY(struct cpuinfo_x86, cpu_info);
9898
EXPORT_PER_CPU_SYMBOL(cpu_info);
9999

100+
/* Logical package management. We might want to allocate that dynamically */
101+
static int *physical_to_logical_pkg __read_mostly;
102+
static unsigned long *physical_package_map __read_mostly;;
103+
static unsigned long *logical_package_map __read_mostly;
104+
static unsigned int max_physical_pkg_id __read_mostly;
105+
unsigned int __max_logical_packages __read_mostly;
106+
EXPORT_SYMBOL(__max_logical_packages);
107+
100108
static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip)
101109
{
102110
unsigned long flags;
@@ -251,13 +259,105 @@ static void notrace start_secondary(void *unused)
251259
cpu_startup_entry(CPUHP_ONLINE);
252260
}
253261

262+
int topology_update_package_map(unsigned int apicid, unsigned int cpu)
263+
{
264+
unsigned int new, pkg = apicid >> boot_cpu_data.x86_coreid_bits;
265+
266+
/* Called from early boot ? */
267+
if (!physical_package_map)
268+
return 0;
269+
270+
if (pkg >= max_physical_pkg_id)
271+
return -EINVAL;
272+
273+
/* Set the logical package id */
274+
if (test_and_set_bit(pkg, physical_package_map))
275+
goto found;
276+
277+
if (pkg < __max_logical_packages) {
278+
set_bit(pkg, logical_package_map);
279+
physical_to_logical_pkg[pkg] = pkg;
280+
goto found;
281+
}
282+
new = find_first_zero_bit(logical_package_map, __max_logical_packages);
283+
if (new >= __max_logical_packages) {
284+
physical_to_logical_pkg[pkg] = -1;
285+
pr_warn("APIC(%x) Package %u exceeds logical package map\n",
286+
apicid, pkg);
287+
return -ENOSPC;
288+
}
289+
set_bit(new, logical_package_map);
290+
pr_info("APIC(%x) Converting physical %u to logical package %u\n",
291+
apicid, pkg, new);
292+
physical_to_logical_pkg[pkg] = new;
293+
294+
found:
295+
cpu_data(cpu).logical_proc_id = physical_to_logical_pkg[pkg];
296+
return 0;
297+
}
298+
299+
/**
300+
* topology_phys_to_logical_pkg - Map a physical package id to a logical
301+
*
302+
* Returns logical package id or -1 if not found
303+
*/
304+
int topology_phys_to_logical_pkg(unsigned int phys_pkg)
305+
{
306+
if (phys_pkg >= max_physical_pkg_id)
307+
return -1;
308+
return physical_to_logical_pkg[phys_pkg];
309+
}
310+
EXPORT_SYMBOL(topology_phys_to_logical_pkg);
311+
312+
static void __init smp_init_package_map(void)
313+
{
314+
unsigned int ncpus, cpu;
315+
size_t size;
316+
317+
/*
318+
* Today neither Intel nor AMD support heterogenous systems. That
319+
* might change in the future....
320+
*/
321+
ncpus = boot_cpu_data.x86_max_cores * smp_num_siblings;
322+
__max_logical_packages = DIV_ROUND_UP(nr_cpu_ids, ncpus);
323+
324+
/*
325+
* Possibly larger than what we need as the number of apic ids per
326+
* package can be smaller than the actual used apic ids.
327+
*/
328+
max_physical_pkg_id = DIV_ROUND_UP(MAX_LOCAL_APIC, ncpus);
329+
size = max_physical_pkg_id * sizeof(unsigned int);
330+
physical_to_logical_pkg = kmalloc(size, GFP_KERNEL);
331+
memset(physical_to_logical_pkg, 0xff, size);
332+
size = BITS_TO_LONGS(max_physical_pkg_id) * sizeof(unsigned long);
333+
physical_package_map = kzalloc(size, GFP_KERNEL);
334+
size = BITS_TO_LONGS(__max_logical_packages) * sizeof(unsigned long);
335+
logical_package_map = kzalloc(size, GFP_KERNEL);
336+
337+
pr_info("Max logical packages: %u\n", __max_logical_packages);
338+
339+
for_each_present_cpu(cpu) {
340+
unsigned int apicid = apic->cpu_present_to_apicid(cpu);
341+
342+
if (apicid == BAD_APICID || !apic->apic_id_valid(apicid))
343+
continue;
344+
if (!topology_update_package_map(apicid, cpu))
345+
continue;
346+
pr_warn("CPU %u APICId %x disabled\n", cpu, apicid);
347+
per_cpu(x86_bios_cpu_apicid, cpu) = BAD_APICID;
348+
set_cpu_possible(cpu, false);
349+
set_cpu_present(cpu, false);
350+
}
351+
}
352+
254353
void __init smp_store_boot_cpu_info(void)
255354
{
256355
int id = 0; /* CPU 0 */
257356
struct cpuinfo_x86 *c = &cpu_data(id);
258357

259358
*c = boot_cpu_data;
260359
c->cpu_index = id;
360+
smp_init_package_map();
261361
}
262362

263363
/*

0 commit comments

Comments
 (0)