#define MAX_IRQ_SOURCES                256
 
-extern unsigned int def_to_bigsmp;
-
 #else /* CONFIG_X86_64: */
 
 #define MAX_MP_BUSSES          256
 
 #include <asm/irq_regs.h>
 #include <asm/cpu.h>
 
+#include "local.h"
+
 unsigned int num_processors;
 
 unsigned disabled_cpus;
 {
        cpuid_to_apicid[0] = boot_cpu_physical_apicid;
        cpu_update_apic(0, boot_cpu_physical_apicid);
+       x86_32_probe_bigsmp_early();
 }
 
 int generic_processor_info(int apicid)
 
 
 static int probe_bigsmp(void)
 {
-       if (def_to_bigsmp)
-               dmi_bigsmp = 1;
-       else
-               dmi_check_system(bigsmp_dmi_table);
-
-       return dmi_bigsmp;
+       return dmi_check_system(bigsmp_dmi_table);
 }
 
 static struct apic apic_bigsmp __ro_after_init = {
        .safe_wait_icr_idle             = native_safe_apic_wait_icr_idle,
 };
 
-void __init generic_bigsmp_probe(void)
+bool __init apic_bigsmp_possible(bool cmdline_override)
 {
-       if (!probe_bigsmp())
-               return;
-
-       apic = &apic_bigsmp;
+       return apic == &apic_bigsmp || !cmdline_override;
+}
 
-       pr_info("Overriding APIC driver with %s\n", apic_bigsmp.name);
+void __init apic_bigsmp_force(void)
+{
+       if (apic != &apic_bigsmp) {
+               apic = &apic_bigsmp;
+               pr_info("Overriding APIC driver with bigsmp\n");
+       }
 }
 
 apic_driver(apic_bigsmp);
 
 void default_send_IPI_mask_sequence_logical(const struct cpumask *mask, int vector);
 void default_send_IPI_mask_allbutself_logical(const struct cpumask *mask, int vector);
 void default_send_IPI_mask_logical(const struct cpumask *mask, int vector);
+void x86_32_probe_bigsmp_early(void);
+#else
+static inline void x86_32_probe_bigsmp_early(void) { }
+#endif
+
+#ifdef CONFIG_X86_BIGSMP
+bool apic_bigsmp_possible(bool cmdline_selected);
+void apic_bigsmp_force(void);
+#else
+static inline bool apic_bigsmp_possible(bool cmdline_selected) { return false; };
+static inline void apic_bigsmp_force(void) { }
 #endif
 
 #include <linux/errno.h>
 #include <linux/smp.h>
 
+#include <xen/xen.h>
+
 #include <asm/io_apic.h>
 #include <asm/apic.h>
 #include <asm/acpi.h>
 }
 early_param("apic", parse_apic);
 
-void __init default_setup_apic_routing(void)
+void __init x86_32_probe_bigsmp_early(void)
 {
-       int version = boot_cpu_apic_version;
+       if (nr_cpu_ids <= 8 || xen_pv_domain())
+               return;
 
-       if (num_possible_cpus() > 8) {
+       if (IS_ENABLED(CONFIG_X86_BIGSMP)) {
                switch (boot_cpu_data.x86_vendor) {
                case X86_VENDOR_INTEL:
-                       if (!APIC_XAPIC(version)) {
-                               def_to_bigsmp = 0;
+                       if (!APIC_XAPIC(boot_cpu_apic_version))
                                break;
-                       }
                        /* P4 and above */
                        fallthrough;
                case X86_VENDOR_HYGON:
                case X86_VENDOR_AMD:
-                       def_to_bigsmp = 1;
+                       if (apic_bigsmp_possible(cmdline_apic))
+                               return;
+                       break;
                }
        }
+       pr_info("Limiting to 8 possible CPUs\n");
+       set_nr_cpu_ids(8);
+}
 
-#ifdef CONFIG_X86_BIGSMP
-       /*
-        * This is used to switch to bigsmp mode when
-        * - There is no apic= option specified by the user
-        * - generic_apic_probe() has chosen apic_default as the sub_arch
-        * - we find more than 8 CPUs in acpi LAPIC listing with xAPIC support
-        */
-
-       if (!cmdline_apic && apic == &apic_default)
-               generic_bigsmp_probe();
-#endif
+void __init default_setup_apic_routing(void)
+{
+       if (nr_cpu_ids > 8 && !xen_pv_domain())
+               apic_bigsmp_force();
 
        if (apic->setup_apic_routing)
                apic->setup_apic_routing();
 
 #ifdef CONFIG_X86_32
 /* CPU data as detected by the assembly code in head_32.S */
 struct cpuinfo_x86 new_cpu_data;
-unsigned int def_to_bigsmp;
 
 struct apm_info apm_info;
 EXPORT_SYMBOL(apm_info);
 
        cpumask_set_cpu(0, topology_die_cpumask(0));
 }
 
-/*
- * Various sanity checks.
- */
-static void __init smp_sanity_check(void)
-{
-       preempt_disable();
-
-#if !defined(CONFIG_X86_BIGSMP) && defined(CONFIG_X86_32)
-       if (def_to_bigsmp && nr_cpu_ids > 8) {
-               unsigned int cpu;
-               unsigned nr;
-
-               pr_warn("More than 8 CPUs detected - skipping them\n"
-                       "Use CONFIG_X86_BIGSMP\n");
-
-               nr = 0;
-               for_each_present_cpu(cpu) {
-                       if (nr >= 8)
-                               set_cpu_present(cpu, false);
-                       nr++;
-               }
-
-               nr = 0;
-               for_each_possible_cpu(cpu) {
-                       if (nr >= 8)
-                               set_cpu_possible(cpu, false);
-                       nr++;
-               }
-
-               set_nr_cpu_ids(8);
-       }
-#endif
-       preempt_enable();
-}
-
 static void __init smp_cpu_index_default(void)
 {
        int i;
 {
        smp_prepare_cpus_common();
 
-       smp_sanity_check();
-
        switch (apic_intr_mode) {
        case APIC_PIC:
        case APIC_VIRTUAL_WIRE_NO_CONFIG: