* Validate that ACPI/mptables have the same information about the
  * effective APIC id and update the package map.
  */
-static void validate_apic_and_package_id(struct cpuinfo_x86 *c)
+static void validate_apic_id(struct cpuinfo_x86 *c)
 {
 #ifdef CONFIG_SMP
        unsigned int apicid, cpu = smp_processor_id();
                pr_err(FW_BUG "CPU%u: APIC id mismatch. Firmware: %x APIC: %x\n",
                       cpu, apicid, c->initial_apicid);
        }
-       BUG_ON(topology_update_package_map(c->phys_proc_id, cpu));
-       BUG_ON(topology_update_die_map(c->cpu_die_id, cpu));
 #else
        c->logical_proc_id = 0;
 #endif
 #ifdef CONFIG_X86_32
        enable_sep_cpu();
 #endif
-       validate_apic_and_package_id(c);
+       validate_apic_id(c);
        x86_spec_ctrl_setup_ap();
        update_srbds_msr();
 
 
        apic_ap_setup();
 
        /*
-        * Save our processor parameters. Note: this information
-        * is needed for clock calibration.
-        */
-       smp_store_cpu_info(cpuid);
-
-       /*
+        * Save our processor parameters and update topology.
+        * Note: this information is needed for clock calibration.
         * The topology information must be up to date before
         * calibrate_delay() and notify_cpu_starting().
         */
-       set_cpu_sibling_map(raw_smp_processor_id());
+       smp_store_cpu_info(cpuid, false);
 
        ap_init_aperfmperf();
 
         * smp_callout_mask to release them.
         */
        cpu_init_secondary();
+
+       /*
+        * Even though notify_cpu_starting() will do this, it does so too late
+        * as the AP may already have triggered lockdep splats by then. See
+        * commit 29368e093 ("x86/smpboot:  Move rcu_cpu_starting() earlier").
+        */
        rcu_cpu_starting(raw_smp_processor_id());
        x86_cpuinit.early_percpu_clock_init();
 
  * @pkg:       The physical package id as retrieved via CPUID
  * @cpu:       The cpu for which this is updated
  */
-int topology_update_package_map(unsigned int pkg, unsigned int cpu)
+static int topology_update_package_map(unsigned int pkg, unsigned int cpu)
 {
        int new;
 
  * @die:       The die id as retrieved via CPUID
  * @cpu:       The cpu for which this is updated
  */
-int topology_update_die_map(unsigned int die, unsigned int cpu)
+static int topology_update_die_map(unsigned int die, unsigned int cpu)
 {
        int new;
 
        c->initialized = true;
 }
 
-/*
- * The bootstrap kernel entry code has set these up. Save them for
- * a given CPU
- */
-void smp_store_cpu_info(int id)
-{
-       struct cpuinfo_x86 *c = &cpu_data(id);
-
-       /* Copy boot_cpu_data only on the first bringup */
-       if (!c->initialized)
-               *c = boot_cpu_data;
-       c->cpu_index = id;
-       /*
-        * During boot time, CPU0 has this setup already. Save the info when
-        * bringing up AP or offlined CPU0.
-        */
-       identify_secondary_cpu(c);
-       c->initialized = true;
-}
+static arch_spinlock_t topology_lock = __ARCH_SPIN_LOCK_UNLOCKED;
 
 static bool
 topology_same_node(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
  */
 static bool x86_has_numa_in_package;
 
-void set_cpu_sibling_map(int cpu)
+static void set_cpu_sibling_map(int cpu)
 {
        bool has_smt = smp_num_siblings > 1;
        bool has_mp = has_smt || boot_cpu_data.x86_max_cores > 1;
        }
 }
 
+/*
+ * The bootstrap kernel entry code has set these up. Save them for
+ * a given CPU
+ */
+void smp_store_cpu_info(int id, bool force_single_core)
+{
+       struct cpuinfo_x86 *c = &cpu_data(id);
+
+       /* Copy boot_cpu_data only on the first bringup */
+       if (!c->initialized)
+               *c = boot_cpu_data;
+       c->cpu_index = id;
+       /*
+        * During boot time, CPU0 has this setup already. Save the info when
+        * bringing up AP or offlined CPU0.
+        */
+       identify_secondary_cpu(c);
+
+       arch_spin_lock(&topology_lock);
+       BUG_ON(topology_update_package_map(c->phys_proc_id, id));
+       BUG_ON(topology_update_die_map(c->cpu_die_id, id));
+       c->initialized = true;
+
+       /* For Xen PV */
+       if (force_single_core)
+               c->x86_max_cores = 1;
+
+       set_cpu_sibling_map(id);
+       arch_spin_unlock(&topology_lock);
+}
+
 /* maps the cpu to the sched domain representing multi-core */
 const struct cpumask *cpu_coregroup_mask(int cpu)
 {