@@ -97,6 +97,14 @@ DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_llc_shared_map);
9797DEFINE_PER_CPU_READ_MOSTLY (struct cpuinfo_x86 , cpu_info );
9898EXPORT_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+
100108static 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+
254353void __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