Reserve the running BSP as kernel ID 0 before the MADT walk, so it
survives firmware that lists it later. Ignore duplicate LAPIC entries
and CPUs beyond NCPUS.

This uses the apic_add_cpu() return value and the cpu_lapic_list bound.
---
 i386/i386at/acpi_parse_apic.c | 34 +++++++++++++++++++---------------
 1 file changed, 19 insertions(+), 15 deletions(-)

diff --git a/i386/i386at/acpi_parse_apic.c b/i386/i386at/acpi_parse_apic.c
index 85123015..8304bee5 100644
--- a/i386/i386at/acpi_parse_apic.c
+++ b/i386/i386at/acpi_parse_apic.c
@@ -392,12 +392,23 @@ acpi_get_apic2(struct acpi_xsdt *xsdt, int acpi_xsdt_n)
 static void
 acpi_apic_add_lapic(struct acpi_apic_lapic *lapic_entry)
 {
+    uint16_t apic_id;
+    int i;
+
     /* If cpu flag is correct */
-    if (lapic_entry->flags & (ACPI_LAPIC_FLAG_ENABLED | 
ACPI_LAPIC_FLAG_CAPABLE)) {
-        /* Add cpu to processors' list. */
-        apic_add_cpu(lapic_entry->apic_id & apic_id_mask);
+    if (!(lapic_entry->flags & (ACPI_LAPIC_FLAG_ENABLED | 
ACPI_LAPIC_FLAG_CAPABLE)))
+        return;
+
+    apic_id = lapic_entry->apic_id & apic_id_mask;
+
+    for (i = 0; i < apic_get_numcpus(); i++) {
+        if (apic_get_cpu_apic_id(i) == apic_id)
+            return;
     }
 
+    if (apic_add_cpu(apic_id) != 0)
+        printf("APIC: ignoring LAPIC ID %#x: NCPUS=%d limit reached\n",
+               apic_id, NCPUS);
 }
 
 /*
@@ -462,7 +473,6 @@ acpi_apic_parse_table(struct acpi_apic *apic)
 {
     struct acpi_apic_dhdr *apic_entry = NULL;
     vm_offset_t end = 0;
-    uint8_t numcpus = 1;
 
     /* Get the address of first APIC entry */
     apic_entry = (struct acpi_apic_dhdr*) apic->entry;
@@ -472,9 +482,6 @@ acpi_apic_parse_table(struct acpi_apic *apic)
 
     printf("APIC entry=0x%p end=0x%x\n", apic_entry, end);
 
-    /* Initialize number of cpus */
-    numcpus = apic_get_numcpus();
-
     while ((vm_offset_t)apic_entry + sizeof(struct acpi_apic_dhdr) <= end) {
         struct acpi_apic_lapic *lapic_entry;
         struct acpi_apic_ioapic *ioapic_entry;
@@ -493,11 +500,8 @@ acpi_apic_parse_table(struct acpi_apic *apic)
 
         /* If APIC entry is a CPU's Local APIC. */
         case ACPI_APIC_ENTRY_LAPIC:
-            if(numcpus < NCPUS) {
-                /* Store Local APIC data. */
-                lapic_entry = (struct acpi_apic_lapic*) apic_entry;
-                acpi_apic_add_lapic(lapic_entry);
-            }
+            lapic_entry = (struct acpi_apic_lapic*) apic_entry;
+            acpi_apic_add_lapic(lapic_entry);
             break;
 
         /* If APIC entry is an IOAPIC. */
@@ -534,9 +538,6 @@ acpi_apic_parse_table(struct acpi_apic *apic)
         /* Get next APIC entry. */
         apic_entry = (struct acpi_apic_dhdr*)((vm_offset_t) apic_entry
                                               + apic_entry->length);
-
-        /* Update number of cpus. */
-        numcpus = apic_get_numcpus();
     }
 
     return ACPI_SUCCESS;
@@ -575,6 +576,9 @@ acpi_apic_setup(struct acpi_apic *apic)
 
     fix_apic_id_mask();
 
+    if (apic_add_cpu(apic_get_current_cpu()) != 0)
+        return ACPI_APIC_FAILURE;
+
     acpi_apic_parse_table(apic);
 
     ncpus = apic_get_numcpus();

Reply via email to