svn commit: r284175 - head/sys/x86/acpica

John Baldwin jhb at FreeBSD.org
Tue Jun 9 10:49:41 UTC 2015


Author: jhb
Date: Tue Jun  9 10:49:40 2015
New Revision: 284175
URL: https://svnweb.freebsd.org/changeset/base/284175

Log:
  Handle X2APIC entries in the MADT for APICs with an ID < 255.  At least one
  BIOS has been seen to include such entries even though the relevant specs
  require that X2APIC entries only be used for CPUs with an APIC ID >= 255.
  
  This was tested on a system with "plain" local APIC entries in the MADT
  to ensure no regressions, but it has not yet been tested on a system with
  X2APIC entries in the MADT.  Currently such systems do not boot at all,
  and with this change they might now boot correctly.
  
  Differential Revision:	https://reviews.freebsd.org/D2521
  Reviewed by:	kib
  MFC after:	2 weeks

Modified:
  head/sys/x86/acpica/madt.c

Modified: head/sys/x86/acpica/madt.c
==============================================================================
--- head/sys/x86/acpica/madt.c	Tue Jun  9 00:14:47 2015	(r284174)
+++ head/sys/x86/acpica/madt.c	Tue Jun  9 10:49:40 2015	(r284175)
@@ -56,8 +56,8 @@ static struct {
 } *ioapics;
 
 static struct lapic_info {
-	u_int la_enabled:1;
-	u_int la_acpi_id:8;
+	u_int la_enabled;
+	u_int la_acpi_id;
 } lapics[MAX_APIC_ID + 1];
 
 int madt_found_sci_override;
@@ -255,34 +255,48 @@ madt_walk_table(acpi_subtable_handler *h
 }
 
 static void
+madt_add_cpu(u_int acpi_id, u_int apic_id, u_int flags)
+{
+	struct lapic_info *la;
+
+	/*
+	 * The MADT does not include a BSP flag, so we have to let the
+	 * MP code figure out which CPU is the BSP on its own.
+	 */
+	if (bootverbose)
+		printf("MADT: Found CPU APIC ID %u ACPI ID %u: %s\n",
+		    apic_id, acpi_id, flags & ACPI_MADT_ENABLED ?
+		    "enabled" : "disabled");
+	if (!(flags & ACPI_MADT_ENABLED))
+		return;
+	if (apic_id > MAX_APIC_ID) {
+		printf("MADT: Ignoring local APIC ID %u (too high)\n",
+		    apic_id);
+		return;
+	}
+
+	la = &lapics[apic_id];
+	KASSERT(la->la_enabled == 0, ("Duplicate local APIC ID %u", apic_id));
+	la->la_enabled = 1;
+	la->la_acpi_id = acpi_id;
+	lapic_create(apic_id, 0);
+}
+
+static void
 madt_probe_cpus_handler(ACPI_SUBTABLE_HEADER *entry, void *arg)
 {
 	ACPI_MADT_LOCAL_APIC *proc;
-	struct lapic_info *la;
+	ACPI_MADT_LOCAL_X2APIC *x2apic;
 
 	switch (entry->Type) {
 	case ACPI_MADT_TYPE_LOCAL_APIC:
-		/*
-		 * The MADT does not include a BSP flag, so we have to
-		 * let the MP code figure out which CPU is the BSP on
-		 * its own.
-		 */
 		proc = (ACPI_MADT_LOCAL_APIC *)entry;
-		if (bootverbose)
-			printf("MADT: Found CPU APIC ID %u ACPI ID %u: %s\n",
-			    proc->Id, proc->ProcessorId,
-			    (proc->LapicFlags & ACPI_MADT_ENABLED) ?
-			    "enabled" : "disabled");
-		if (!(proc->LapicFlags & ACPI_MADT_ENABLED))
-			break;
-		if (proc->Id > MAX_APIC_ID)
-			panic("%s: CPU ID %u too high", __func__, proc->Id);
-		la = &lapics[proc->Id];
-		KASSERT(la->la_enabled == 0,
-		    ("Duplicate local APIC ID %u", proc->Id));
-		la->la_enabled = 1;
-		la->la_acpi_id = proc->ProcessorId;
-		lapic_create(proc->Id, 0);
+		madt_add_cpu(proc->ProcessorId, proc->Id, proc->LapicFlags);
+		break;
+	case ACPI_MADT_TYPE_LOCAL_X2APIC:
+		x2apic = (ACPI_MADT_LOCAL_X2APIC *)entry;
+		madt_add_cpu(x2apic->Uid, x2apic->LocalApicId,
+		    x2apic->LapicFlags);
 		break;
 	}
 }
@@ -551,29 +565,44 @@ madt_parse_nmi(ACPI_MADT_NMI_SOURCE *nmi
  * Parse an entry for an NMI routed to a local APIC LVT pin.
  */
 static void
-madt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi)
+madt_handle_local_nmi(u_int acpi_id, UINT8 Lint, UINT16 IntiFlags)
 {
 	u_int apic_id, pin;
 
-	if (nmi->ProcessorId == 0xff)
+	if (acpi_id == 0xffffffff)
 		apic_id = APIC_ID_ALL;
-	else if (madt_find_cpu(nmi->ProcessorId, &apic_id) != 0) {
+	else if (madt_find_cpu(acpi_id, &apic_id) != 0) {
 		if (bootverbose)
 			printf("MADT: Ignoring local NMI routed to "
-			    "ACPI CPU %u\n", nmi->ProcessorId);
+			    "ACPI CPU %u\n", acpi_id);
 		return;
 	}
-	if (nmi->Lint == 0)
+	if (Lint == 0)
 		pin = APIC_LVT_LINT0;
 	else
 		pin = APIC_LVT_LINT1;
 	lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI);
-	if (!(nmi->IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
+	if (!(IntiFlags & ACPI_MADT_TRIGGER_CONFORMS))
 		lapic_set_lvt_triggermode(apic_id, pin,
-		    interrupt_trigger(nmi->IntiFlags, 0));
-	if (!(nmi->IntiFlags & ACPI_MADT_POLARITY_CONFORMS))
+		    interrupt_trigger(IntiFlags, 0));
+	if (!(IntiFlags & ACPI_MADT_POLARITY_CONFORMS))
 		lapic_set_lvt_polarity(apic_id, pin,
-		    interrupt_polarity(nmi->IntiFlags, 0));
+		    interrupt_polarity(IntiFlags, 0));
+}
+
+static void
+madt_parse_local_nmi(ACPI_MADT_LOCAL_APIC_NMI *nmi)
+{
+
+	madt_handle_local_nmi(nmi->ProcessorId == 0xff ? 0xffffffff :
+	    nmi->ProcessorId, nmi->Lint, nmi->IntiFlags);
+}
+
+static void
+madt_parse_local_x2apic_nmi(ACPI_MADT_LOCAL_X2APIC_NMI *nmi)
+{
+
+	madt_handle_local_nmi(nmi->Uid, nmi->Lint, nmi->IntiFlags);
 }
 
 /*
@@ -594,6 +623,10 @@ madt_parse_ints(ACPI_SUBTABLE_HEADER *en
 	case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
 		madt_parse_local_nmi((ACPI_MADT_LOCAL_APIC_NMI *)entry);
 		break;
+	case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
+		madt_parse_local_x2apic_nmi(
+		    (ACPI_MADT_LOCAL_X2APIC_NMI *)entry);
+		break;
 	}
 }
 


More information about the svn-src-head mailing list