Staticize mp_nbusses
[dragonfly.git] / sys / platform / pc32 / i386 / mp_machdep.c
index f270c5d..1be7955 100644 (file)
@@ -229,9 +229,8 @@ 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
@@ -1019,14 +1018,82 @@ 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,
@@ -1034,7 +1101,7 @@ mptable_hyperthread_fixup(u_int id_mask)
         * 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. */
@@ -2144,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);