Staticize mp_nbusses
[dragonfly.git] / sys / platform / pc32 / i386 / mp_machdep.c
index 49edcfb..1be7955 100644 (file)
@@ -220,15 +220,17 @@ static int need_hyperthreading_fixup;
 static u_int logical_cpus;
 u_int  logical_cpus_mask;
 
+static int madt_probe_test;
+TUNABLE_INT("hw.madt_probe_test", &madt_probe_test);
+
 /** XXX FIXME: where does this really belong, isa.h/isa.c perhaps? */
 int    current_postcode;
 
 /** XXX FIXME: what system files declare these??? */
 extern struct region_descriptor r_gdt, r_idt;
 
-int    bsp_apic_ready = 0;     /* flags useability of BSP apic */
 int    mp_naps;                /* # of Applications processors */
-int    mp_nbusses;             /* # of busses */
+static int     mp_nbusses;     /* # of busses */
 #ifdef APIC_IO
 int    mp_napics;              /* # of IO APICs */
 #endif
@@ -498,40 +500,68 @@ mp_enable(u_int boot_addr)
        u_int   ux;
 #endif /* APIC_IO */
        vm_paddr_t mpfps_paddr;
-       struct mptable_pos mpt;
 
        POSTCODE(MP_ENABLE_POST);
 
-       mpfps_paddr = mptable_probe();
-       if (mpfps_paddr == 0)
-               panic("mp_enable: mptable_probe failed\n");
+       if (madt_probe_test)
+               mpfps_paddr = 0;
+       else
+               mpfps_paddr = mptable_probe();
 
-       mptable_map(&mpt, mpfps_paddr);
+       if (mpfps_paddr) {
+               struct mptable_pos mpt;
 
-       /*
-        * We can safely map physical memory into SMPpt after
-        * mptable_pass1() completes.
-        */
-       mptable_pass1(&mpt);
+               mptable_map(&mpt, mpfps_paddr);
 
-       if (cpu_apic_address == 0)
-               panic("mp_enable: no local apic!\n");
+               /*
+                * We can safely map physical memory into SMPpt after
+                * mptable_pass1() completes.
+                */
+               mptable_pass1(&mpt);
 
-       /* examine the MP table for needed info, uses physical addresses */
-       x = mptable_pass2(&mpt);
+               if (cpu_apic_address == 0)
+                       panic("mp_enable: no local apic (mptable)!\n");
 
-       mptable_unmap(&mpt);
+               /*
+                * Examine the MP table for needed info
+                */
+               x = mptable_pass2(&mpt);
+
+               mptable_unmap(&mpt);
+
+               /* Local apic is mapped on last page */
+               SMPpt[NPTEPG - 1] = (pt_entry_t)(PG_V | PG_RW | PG_N |
+                   pmap_get_pgeflag() | (cpu_apic_address & PG_FRAME));
 
-       /* local apic is mapped on last page */
-       SMPpt[NPTEPG - 1] = (pt_entry_t)(PG_V | PG_RW | PG_N |
-           pmap_get_pgeflag() | (cpu_apic_address & PG_FRAME));
+               /*
+                * Can't process default configs till the
+                * CPU APIC is pmapped
+                */
+               if (x)
+                       mptable_default(x);
 
-       /* can't process default configs till the CPU APIC is pmapped */
-       if (x)
-               mptable_default(x);
+               /* Post scan cleanup */
+               mptable_fix();
+       } else {
+               vm_paddr_t madt_paddr;
+               int bsp_apic_id;
 
-       /* post scan cleanup */
-       mptable_fix();
+               madt_paddr = madt_probe();
+               if (madt_paddr == 0)
+                       panic("mp_enable: madt_probe failed\n");
+
+               cpu_apic_address = madt_pass1(madt_paddr);
+               if (cpu_apic_address == 0)
+                       panic("mp_enable: no local apic (madt)!\n");
+
+               /* Local apic is mapped on last page */
+               SMPpt[NPTEPG - 1] = (pt_entry_t)(PG_V | PG_RW | PG_N |
+                   pmap_get_pgeflag() | (cpu_apic_address & PG_FRAME));
+
+               bsp_apic_id = (lapic.id & 0xff000000) >> 24;
+               if (madt_pass2(madt_paddr, bsp_apic_id))
+                       panic("mp_enable: madt_pass2 failed\n");
+       }
 
 #if defined(APIC_IO)
 
@@ -988,22 +1018,90 @@ mptable_pass2(struct mptable_pos *mpt)
 static void
 mptable_hyperthread_fixup(u_int id_mask)
 {
-       u_int i, id;
+       int i, id, lcpus_max;
 
-       /* Nothing to do if there is no HTT support. */
        if ((cpu_feature & CPUID_HTT) == 0)
                return;
-       logical_cpus = (cpu_procinfo & CPUID_HTT_CORES) >> 16;
-       if (logical_cpus <= 1)
+
+       lcpus_max = (cpu_procinfo & CPUID_HTT_CORES) >> 16;
+       if (lcpus_max <= 1)
                return;
 
+       if (strcmp(cpu_vendor, "GenuineIntel") == 0) {
+               /*
+                * INSTRUCTION SET REFERENCE, A-M (#253666)
+                * Page 3-181, Table 3-20
+                * "The nearest power-of-2 integer that is not smaller
+                *  than EBX[23:16] is the number of unique initial APIC
+                *  IDs reserved for addressing different logical
+                *  processors in a physical package."
+                */
+               for (i = 0; ; ++i) {
+                       if ((1 << i) >= lcpus_max) {
+                               lcpus_max = 1 << i;
+                               break;
+                       }
+               }
+       }
+
+       if (mp_naps == lcpus_max) {
+               /* We have nothing to fix */
+               return;
+       } else if (mp_naps == 1) {
+               /* XXX this may be incorrect */
+               logical_cpus = lcpus_max;
+       } else {
+               int cur, prev, dist;
+
+               /*
+                * Calculate the distances between two nearest
+                * APIC IDs.  If all such distances are same,
+                * then it is the number of missing cpus that
+                * we are going to fill later.
+                */
+               dist = cur = prev = -1;
+               for (id = 0; id < MAXCPU; ++id) {
+                       if ((id_mask & 1 << id) == 0)
+                               continue;
+
+                       cur = id;
+                       if (prev >= 0) {
+                               int new_dist = cur - prev;
+
+                               if (dist < 0)
+                                       dist = new_dist;
+
+                               /*
+                                * Make sure that all distances
+                                * between two nearest APIC IDs
+                                * are same.
+                                */
+                               if (dist != new_dist)
+                                       return;
+                       }
+                       prev = cur;
+               }
+               if (dist == 1)
+                       return;
+
+               /* Must be power of 2 */
+               if (dist & (dist - 1))
+                       return;
+
+               /* Can't exceed CPU package capacity */
+               if (dist > lcpus_max)
+                       logical_cpus = lcpus_max;
+               else
+                       logical_cpus = dist;
+       }
+
        /*
         * For each APIC ID of a CPU that is set in the mask,
         * scan the other candidate APIC ID's for this
         * physical processor.  If any of those ID's are
         * already in the table, then kill the fixup.
         */
-       for (id = 0; id <= MAXCPU; id++) {
+       for (id = 0; id < MAXCPU; id++) {
                if ((id_mask & 1 << id) == 0)
                        continue;
                /* First, make sure we are on a logical_cpus boundary. */
@@ -1462,6 +1560,13 @@ setup_apic_irq_mapping(void)
 
 #endif
 
+void
+mp_set_cpuids(int cpu_id, int apic_id)
+{
+       CPU_TO_ID(cpu_id) = apic_id;
+       ID_TO_CPU(apic_id) = cpu_id;
+}
+
 static int
 processor_entry(proc_entry_ptr entry, int cpu)
 {
@@ -1475,15 +1580,13 @@ processor_entry(proc_entry_ptr entry, int cpu)
                panic("CPU APIC ID out of range (0..%d)", NAPICID - 1);
        /* check for BSP flag */
        if (entry->cpu_flags & PROCENTRY_FLAG_BP) {
-               CPU_TO_ID(0) = entry->apic_id;
-               ID_TO_CPU(entry->apic_id) = 0;
+               mp_set_cpuids(0, entry->apic_id);
                return 0;       /* its already been counted */
        }
 
        /* add another AP to list, if less than max number of CPUs */
        else if (cpu < MAXCPU) {
-               CPU_TO_ID(cpu) = entry->apic_id;
-               ID_TO_CPU(entry->apic_id) = cpu;
+               mp_set_cpuids(cpu, entry->apic_id);
                return 1;
        }
 
@@ -2108,7 +2211,6 @@ start_all_aps(u_int boot_addr)
 
        /* Initialize BSP's local APIC */
        apic_initialize(TRUE);
-       bsp_apic_ready = 1;
 
        /* install the AP 1st level boot code */
        install_ap_tramp(boot_addr);