Re: How many CPU cores does FreeBSD support?

From: Konstantin Belousov <kostikbel_at_gmail.com>
Date: Thu, 5 Jan 2017 13:48:03 +0200
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
_at__at_ -135,7 +135,7 _at__at_ 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;
 
_at__at_ -216,6 +216,11 _at__at_ 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?
_at__at_ -242,7 +247,7 _at__at_ 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. */
_at__at_ -269,7 +274,7 _at__at_ 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);
 
_at__at_ -365,7 +370,7 _at__at_ 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
_at__at_ -74,8 +74,9 _at__at_
  * 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)
_at__at_ -204,6 +205,7 _at__at_ 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);
_at__at_ -256,6 +258,13 _at__at_ 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
_at__at_ -78,6 +78,7 _at__at_ 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
_at__at_ -298,6 +298,7 _at__at_ 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);
_at__at_ -337,6 +338,7 _at__at_ 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,
_at__at_ -602,6 +604,18 _at__at_ 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
_at__at_ -136,6 +136,8 _at__at_ 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];
_at__at_ -794,12 +796,12 _at__at_ 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;
_at__at_ -809,11 +811,24 _at__at_ 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)
 {
 
Received on Thu Jan 05 2017 - 10:48:15 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:41:09 UTC