end_local_APIC_setup();
 }
 
+static __init void cpu_set_boot_apic(void);
+
 static __init void apic_read_boot_cpu_id(bool x2apic)
 {
        /*
                boot_cpu_physical_apicid = read_apic_id();
                boot_cpu_apic_version = GET_APIC_VERSION(apic_read(APIC_LVR));
        }
+       cpu_set_boot_apic();
 }
 
-
 #ifdef CONFIG_X86_X2APIC
 int x2apic_mode;
 EXPORT_SYMBOL_GPL(x2apic_mode);
        return nr_logical_cpuids++;
 }
 
-int generic_processor_info(int apicid, int version)
+static void cpu_update_apic(int cpu, int apicid, int version)
 {
-       int cpu, max = nr_cpu_ids;
-       bool boot_cpu_detected = physid_isset(boot_cpu_physical_apicid,
-                               phys_cpu_present_map);
-
-       /*
-        * boot_cpu_physical_apicid is guaranteed to contain the boot CPU
-        * APIC ID read from the local APIC when this function is invoked.
-        */
-       if (disabled_cpu_apicid != boot_cpu_physical_apicid &&
-           disabled_cpu_apicid == apicid) {
-               int thiscpu = num_processors + disabled_cpus;
-
-               pr_warn("APIC: Disabling requested cpu. Processor %d/0x%x ignored.\n",
-                       thiscpu, apicid);
-
-               disabled_cpus++;
-               return -ENODEV;
-       }
-
-       /*
-        * If boot cpu has not been detected yet, then only allow upto
-        * nr_cpu_ids - 1 processors and keep one slot free for boot cpu
-        */
-       if (!boot_cpu_detected && num_processors >= nr_cpu_ids - 1 &&
-           apicid != boot_cpu_physical_apicid) {
-               int thiscpu = max + disabled_cpus - 1;
-
-               pr_warn("APIC: NR_CPUS/possible_cpus limit of %i almost"
-                       " reached. Keeping one slot for boot cpu."
-                       "  Processor %d/0x%x ignored.\n", max, thiscpu, apicid);
-
-               disabled_cpus++;
-               return -ENODEV;
-       }
-
-       if (num_processors >= nr_cpu_ids) {
-               int thiscpu = max + disabled_cpus;
-
-               pr_warn("APIC: NR_CPUS/possible_cpus limit of %i reached. "
-                       "Processor %d/0x%x ignored.\n", max, thiscpu, apicid);
-
-               disabled_cpus++;
-               return -EINVAL;
-       }
-
-       if (apicid == boot_cpu_physical_apicid) {
-               /*
-                * x86_cpu_to_apicid is required to have processors listed
-                * in same order as logical cpu numbers. Hence the first
-                * entry is BSP, and so on.
-                * boot_cpu_init() already hold bit 0 in cpu_present_mask
-                * for BSP.
-                */
-               cpu = 0;
-
-               /* Logical cpuid 0 is reserved for BSP. */
-               cpuid_to_apicid[0] = apicid;
-       } else {
-               cpu = allocate_logical_cpuid(apicid);
-               if (cpu < 0) {
-                       disabled_cpus++;
-                       return -EINVAL;
-               }
-       }
-
-       /*
-        * Validate version
-        */
        if (version == 0x0) {
                pr_warn("BIOS bug: APIC version is 0 for CPU %d/0x%x, fixing up to 0x10\n",
                        cpu, apicid);
 
        if (system_state != SYSTEM_BOOTING)
                cpu_mark_primary_thread(cpu, apicid);
+}
+
+static __init void cpu_set_boot_apic(void)
+{
+       cpuid_to_apicid[0] = boot_cpu_physical_apicid;
+       cpu_update_apic(0, boot_cpu_physical_apicid, boot_cpu_apic_version);
+}
+
+int generic_processor_info(int apicid, int version)
+{
+       int cpu, max = nr_cpu_ids;
+
+       /* The boot CPU must be set before MADT/MPTABLE parsing happens */
+       if (cpuid_to_apicid[0] == BAD_APICID)
+               panic("Boot CPU APIC not registered yet\n");
+
+       if (apicid == boot_cpu_physical_apicid)
+               return 0;
+
+       if (disabled_cpu_apicid == apicid) {
+               int thiscpu = num_processors + disabled_cpus;
+
+               pr_warn("APIC: Disabling requested cpu. Processor %d/0x%x ignored.\n",
+                       thiscpu, apicid);
 
+               disabled_cpus++;
+               return -ENODEV;
+       }
+
+       if (num_processors >= nr_cpu_ids) {
+               int thiscpu = max + disabled_cpus;
+
+               pr_warn("APIC: NR_CPUS/possible_cpus limit of %i reached. "
+                       "Processor %d/0x%x ignored.\n", max, thiscpu, apicid);
+
+               disabled_cpus++;
+               return -EINVAL;
+       }
+
+       cpu = allocate_logical_cpuid(apicid);
+       if (cpu < 0) {
+               disabled_cpus++;
+               return -EINVAL;
+       }
+
+       cpu_update_apic(cpu, apicid, version);
        return cpu;
 }
 
+
 void __irq_msi_compose_msg(struct irq_cfg *cfg, struct msi_msg *msg,
                           bool dmar)
 {