On Thu, Jan 05, 2017 at 01:23:55AM +0000, Eric Joyner wrote:
> I started off with a snapshot of 12-CURRENT, but I got a kernel panic on
> boot that complained about a duplicate local APIC ID. For now, disabling
> Hyper Threading gets rid of that panic. I think there's a KASSERT that
> wasn't getting hit on my 11.0-RELEASE install.
This is because 11.0 has INVARIANTS disabled in the GENERIC kernel config.
Do you mean this one
        KASSERT(la->la_enabled == 0, ("Duplicate local APIC ID %u", apic_id));
?  This is most likely to out of bounds accesses to the array.

Please revert the modification I suggested in previous mail, i.e. return
to the stock HEAD, and use this one instead.  You would also need to
bump MAXCPU in your kernel config.

If this works out, the patch still requires more work to get rid of that 
dozen of statically sized arrays.  But more likely, the patch requires
some debugging.

diff --git a/sys/x86/acpica/madt.c b/sys/x86/acpica/madt.c
index 959530c0d89..4509bc4a2f2 100644
--- a/sys/x86/acpica/madt.c
+++ b/sys/x86/acpica/madt.c
@@ -135,7 +135,7 @@ madt_setup_local(void)
        vm_paddr_t dmartbl_physaddr;
        const char *reason;
        char *hw_vendor;
-       u_int p[4];
+       u_int p[4], i;
        int user_x2apic;
        bool bios_x2apic;
 
@@ -216,6 +216,11 @@ madt_setup_local(void)
            (int)sizeof(madt->Header.OemId), madt->Header.OemId,
            (int)sizeof(madt->Header.OemTableId), madt->Header.OemTableId);
 
+       if (!x2apic_mode) {
+               for (i = xAPIC_MAX_APIC_ID; i < MAX_APIC_ID; i++)
+                       lapic_ignore(i);
+       }
+
        /*
         * We ignore 64-bit local APIC override entries.  Should we
         * perhaps emit a warning here if we find one?
@@ -242,7 +247,7 @@ madt_setup_io(void)
                panic("Using MADT but ACPI doesn't work");
        }
 
-       ioapics = malloc(sizeof(*ioapics) * (MAX_APIC_ID + 1), M_MADT,
+       ioapics = malloc(sizeof(*ioapics) * (xAPIC_MAX_APIC_ID + 1), M_MADT,
            M_WAITOK | M_ZERO);
 
        /* First, we run through adding I/O APIC's. */
@@ -269,7 +274,7 @@ madt_setup_io(void)
        }
 
        /* Third, we register all the I/O APIC's. */
-       for (i = 0; i <= MAX_APIC_ID; i++)
+       for (i = 0; i <= xAPIC_MAX_APIC_ID; i++)
                if (ioapics[i].io_apic != NULL)
                        ioapic_register(ioapics[i].io_apic);
 
@@ -365,7 +370,7 @@ madt_parse_apics(ACPI_SUBTABLE_HEADER *entry, void *arg 
__unused)
                            "MADT: Found IO APIC ID %u, Interrupt %u at %p\n",
                            apic->Id, apic->GlobalIrqBase,
                            (void *)(uintptr_t)apic->Address);
-               if (apic->Id > MAX_APIC_ID)
+               if (apic->Id > xAPIC_MAX_APIC_ID)
                        panic("%s: I/O APIC ID %u too high", __func__,
                            apic->Id);
                if (ioapics[apic->Id].io_apic != NULL)
diff --git a/sys/x86/include/apicvar.h b/sys/x86/include/apicvar.h
index 09c3a638df8..b65c4a8c913 100644
--- a/sys/x86/include/apicvar.h
+++ b/sys/x86/include/apicvar.h
@@ -74,8 +74,9 @@
  * I/O device!
  */
 
-#define        MAX_APIC_ID     0xfe
-#define        APIC_ID_ALL     0xff
+#define        xAPIC_MAX_APIC_ID       0xfe
+#define        MAX_APIC_ID             0x200
+#define        APIC_ID_ALL             0xffffffff
 
 /* I/O Interrupts are used for external devices such as ISA, PCI, etc. */
 #define        APIC_IO_INTS    (IDT_IO_INTS + 16)
@@ -204,6 +205,7 @@ int ioapic_set_smi(void *cookie, u_int pin);
  */
 struct apic_ops {
        void    (*create)(u_int, int);
+       void    (*ignore)(u_int);
        void    (*init)(vm_paddr_t);
        void    (*xapic_mode)(void);
        bool    (*is_x2apic)(void);
@@ -256,6 +258,13 @@ lapic_create(u_int apic_id, int boot_cpu)
 }
 
 static inline void
+lapic_ignore(u_int apic_id)
+{
+
+       apic_ops.ignore(apic_id);
+}
+
+static inline void
 lapic_init(vm_paddr_t addr)
 {
 
diff --git a/sys/x86/include/x86_smp.h b/sys/x86/include/x86_smp.h
index 84a0eba25bc..0cf4ef234e4 100644
--- a/sys/x86/include/x86_smp.h
+++ b/sys/x86/include/x86_smp.h
@@ -78,6 +78,7 @@ inthand_t
 /* functions in x86_mp.c */
 void   assign_cpu_ids(void);
 void   cpu_add(u_int apic_id, char boot_cpu);
+void   cpu_ignore(u_int apic_id);
 void   cpustop_handler(void);
 void   cpususpend_handler(void);
 void   init_secondary_tail(void);
diff --git a/sys/x86/x86/local_apic.c b/sys/x86/x86/local_apic.c
index 1b1547de780..163f5e4b66f 100644
--- a/sys/x86/x86/local_apic.c
+++ b/sys/x86/x86/local_apic.c
@@ -298,6 +298,7 @@ struct pic lapic_pic = { .pic_resume = lapic_resume };
 
 /* Forward declarations for apic_ops */
 static void    native_lapic_create(u_int apic_id, int boot_cpu);
+static void    native_lapic_ignore(u_int apic_id);
 static void    native_lapic_init(vm_paddr_t addr);
 static void    native_lapic_xapic_mode(void);
 static void    native_lapic_setup(int boot);
@@ -337,6 +338,7 @@ static void native_lapic_ipi_free(int vector);
 
 struct apic_ops apic_ops = {
        .create                 = native_lapic_create,
+       .ignore                 = native_lapic_ignore,
        .init                   = native_lapic_init,
        .xapic_mode             = native_lapic_xapic_mode,
        .is_x2apic              = native_lapic_is_x2apic,
@@ -602,6 +604,18 @@ native_lapic_create(u_int apic_id, int boot_cpu)
 #endif
 }
 
+static void
+native_lapic_ignore(u_int apic_id)
+{
+
+       if (!lapics[apic_id].la_present)
+               return;
+       lapics[apic_id].la_present = 0;
+#ifdef SMP
+       cpu_ignore(apic_id);
+#endif
+}
+
 /*
  * Dump contents of local APIC registers
  */
diff --git a/sys/x86/x86/mp_x86.c b/sys/x86/x86/mp_x86.c
index 56653ee7470..d3a4a09ceaa 100644
--- a/sys/x86/x86/mp_x86.c
+++ b/sys/x86/x86/mp_x86.c
@@ -136,6 +136,8 @@ volatile int aps_ready = 0;
 struct cpu_info cpu_info[MAX_APIC_ID + 1];
 int apic_cpuids[MAX_APIC_ID + 1];
 int cpu_apic_ids[MAXCPU];
+_Static_assert(MAXCPU <= MAX_APIC_ID,
+    "MAXCPU cannot be larger that MAX_APIC_ID");
 
 /* Holds pending bitmap based IPIs per CPU */
 volatile u_int cpu_ipi_pending[MAXCPU];
@@ -794,12 +796,12 @@ cpu_add(u_int apic_id, char boot_cpu)
                panic("SMP: APIC ID %d too high", apic_id);
                return;
        }
-       KASSERT(cpu_info[apic_id].cpu_present == 0, ("CPU %d added twice",
+       KASSERT(cpu_info[apic_id].cpu_present == 0, ("CPU %u added twice",
            apic_id));
        cpu_info[apic_id].cpu_present = 1;
        if (boot_cpu) {
                KASSERT(boot_cpu_id == -1,
-                   ("CPU %d claims to be BSP, but CPU %d already is", apic_id,
+                   ("CPU %d claims to be BSP, but CPU %u already is", apic_id,
                    boot_cpu_id));
                boot_cpu_id = apic_id;
                cpu_info[apic_id].cpu_bsp = 1;
@@ -809,11 +811,24 @@ cpu_add(u_int apic_id, char boot_cpu)
                mp_maxid = mp_ncpus - 1;
        }
        if (bootverbose)
-               printf("SMP: Added CPU %d (%s)\n", apic_id, boot_cpu ? "BSP" :
+               printf("SMP: Added CPU %u (%s)\n", apic_id, boot_cpu ? "BSP" :
                    "AP");
 }
 
 void
+cpu_ignore(u_int apic_id)
+{
+
+       KASSERT(cpu_info[apic_id].cpu_present == 1, ("CPU %u not added",
+           apic_id));
+       KASSERT(cpu_info[apic_id].cpu_bsp == 0, ("Cannot ignore BSP %u",
+           apic_id));
+       cpu_info[apic_id].cpu_present = 0;
+       if (bootverbose)
+               printf("SMP: Ignoring CPU %u\n", apic_id);
+}
+
+void
 cpu_mp_setmaxid(void)
 {
 
_______________________________________________
freebsd-current@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to "freebsd-current-unsubscr...@freebsd.org"

Reply via email to