madt: Prepare to extract I/O APIC information from MADT
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Sat, 12 Feb 2011 06:22:09 +0000 (14:22 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Sat, 12 Feb 2011 06:54:56 +0000 (14:54 +0800)
- Run madt_probe() at BOOT2_PRESMP/ORDER_FIRST.
- Save MADT's physical address in global variable.
- Move preliminary LAPIC checks from MADT probing to MADT LAPIC
  enumerator's probing function.

sys/platform/pc32/i386/mp_madt.c
sys/platform/pc64/x86_64/mp_madt.c

index 757aebc..f7b0c26 100644 (file)
@@ -167,11 +167,6 @@ struct acpi_madt_lapic_addr {
        uint64_t                mla_lapic_addr;
 } __packed;
 
-struct madt_lapic_enumerator {
-       struct lapic_enumerator enumerator;
-       vm_paddr_t              madt_paddr;
-};
-
 typedef        vm_paddr_t              (*madt_search_t)(vm_paddr_t);
 typedef int                    (*madt_iter_t)(void *,
                                    const struct acpi_madt_ent *);
@@ -185,16 +180,17 @@ static int                        madt_check(vm_paddr_t);
 static int                     madt_iterate_entries(struct acpi_madt *,
                                    madt_iter_t, void *);
 
-static vm_paddr_t              madt_probe(void);
-static vm_offset_t             madt_pass1(vm_paddr_t);
-static int                     madt_pass2(vm_paddr_t, int);
+static vm_offset_t             madt_pass1(void);
+static int                     madt_pass2(int);
 
 static void                    madt_lapic_enumerate(struct lapic_enumerator *);
 static int                     madt_lapic_probe(struct lapic_enumerator *);
 
 extern u_long  ebda_addr;
 
-static vm_paddr_t
+static vm_paddr_t              madt_phyaddr;
+
+static void
 madt_probe(void)
 {
        const struct acpi_rsdp *rsdp;
@@ -203,6 +199,8 @@ madt_probe(void)
        vm_size_t mapsz;
        uint8_t *ptr;
 
+       KKASSERT(madt_phyaddr == 0);
+
        if (ebda_addr != 0) {
                mapsz = ACPI_RSDP_EBDA_MAPSZ;
                ptr = pmap_mapdev(ebda_addr, mapsz);
@@ -227,7 +225,7 @@ madt_probe(void)
        if (rsdp == NULL) {
                kprintf("madt_probe: no RSDP\n");
                pmap_unmapdev((vm_offset_t)ptr, mapsz);
-               return 0;
+               return;
        } else {
                MADT_VPRINTF("RSDP in BIOS mem\n");
        }
@@ -245,14 +243,18 @@ found_rsdp:
        madt_paddr = search(search_paddr);
        if (madt_paddr == 0) {
                kprintf("madt_probe: can't locate MADT\n");
-               return 0;
+               return;
        }
 
        /* Preliminary checks */
-       if (madt_check(madt_paddr))
-               return 0;
-       return madt_paddr;
+       if (madt_check(madt_paddr)) {
+               kprintf("madt_probe: madt_check failed\n");
+               return;
+       }
+
+       madt_phyaddr = madt_paddr;
 }
+SYSINIT(madt_probe, SI_BOOT2_PRESMP, SI_ORDER_FIRST, madt_probe, 0);
 
 static const struct acpi_rsdp *
 madt_rsdp_search(const uint8_t *target, int size)
@@ -428,16 +430,16 @@ madt_pass1_callback(void *xarg, const struct acpi_madt_ent *ent)
 }
 
 static vm_offset_t
-madt_pass1(vm_paddr_t madt_paddr)
+madt_pass1(void)
 {
        struct acpi_madt *madt;
        vm_offset_t lapic_addr;
        uint64_t lapic_addr64;
        int error;
 
-       KKASSERT(madt_paddr != 0);
+       KKASSERT(madt_phyaddr != 0);
 
-       madt = madt_sdth_map(madt_paddr);
+       madt = madt_sdth_map(madt_phyaddr);
        KKASSERT(madt != NULL);
 
        MADT_VPRINTF("LAPIC address 0x%08x, flags %#x\n",
@@ -491,7 +493,7 @@ madt_pass2_callback(void *xarg, const struct acpi_madt_ent *ent)
 }
 
 static int
-madt_pass2(vm_paddr_t madt_paddr, int bsp_apic_id)
+madt_pass2(int bsp_apic_id)
 {
        struct acpi_madt *madt;
        struct madt_pass2_cbarg arg;
@@ -499,9 +501,9 @@ madt_pass2(vm_paddr_t madt_paddr, int bsp_apic_id)
 
        MADT_VPRINTF("BSP apic id %d\n", bsp_apic_id);
 
-       KKASSERT(madt_paddr != 0);
+       KKASSERT(madt_phyaddr != 0);
 
-       madt = madt_sdth_map(madt_paddr);
+       madt = madt_sdth_map(madt_phyaddr);
        KKASSERT(madt != NULL);
 
        bzero(&arg, sizeof(arg));
@@ -521,29 +523,9 @@ madt_pass2(vm_paddr_t madt_paddr, int bsp_apic_id)
        return 0;
 }
 
-struct madt_check_cbarg {
-       int     cpu_count;
-};
-
-static int
-madt_check_callback(void *xarg, const struct acpi_madt_ent *ent)
-{
-       struct madt_check_cbarg *arg = xarg;
-       const struct acpi_madt_lapic *lapic_ent;
-
-       if (ent->me_type != MADT_ENT_LAPIC)
-               return 0;
-       lapic_ent = (const struct acpi_madt_lapic *)ent;
-
-       if (lapic_ent->ml_flags & MADT_LAPIC_ENABLED)
-               arg->cpu_count++;
-       return 0;
-}
-
 static int
 madt_check(vm_paddr_t madt_paddr)
 {
-       struct madt_check_cbarg arg;
        struct acpi_madt *madt;
        int error = 0;
 
@@ -566,16 +548,6 @@ madt_check(vm_paddr_t madt_paddr)
                error = EINVAL;
                goto back;
        }
-
-       bzero(&arg, sizeof(arg));
-
-       error = madt_iterate_entries(madt, madt_check_callback, &arg);
-       if (!error) {
-               if (arg.cpu_count <= 1) {
-                       kprintf("madt_check: less than 2 CPUs is found\n");
-                       error = EOPNOTSUPP;
-               }
-       }
 back:
        madt_sdth_unmap(&madt->madt_hdr);
        return error;
@@ -650,46 +622,94 @@ madt_iterate_entries(struct acpi_madt *madt, madt_iter_t func, void *arg)
        return error;
 }
 
+struct madt_lapic_probe_cbarg {
+       int             cpu_count;
+       vm_offset_t     lapic_addr;
+};
+
+static int
+madt_lapic_probe_callback(void *xarg, const struct acpi_madt_ent *ent)
+{
+       struct madt_lapic_probe_cbarg *arg = xarg;
+
+       if (ent->me_type == MADT_ENT_LAPIC) {
+               const struct acpi_madt_lapic *lapic_ent;
+
+               lapic_ent = (const struct acpi_madt_lapic *)ent;
+               if (lapic_ent->ml_flags & MADT_LAPIC_ENABLED)
+                       arg->cpu_count++;
+       } else if (ent->me_type == MADT_ENT_LAPIC_ADDR) {
+               const struct acpi_madt_lapic_addr *lapic_addr_ent;
+
+               if (ent->me_len < sizeof(*lapic_addr_ent)) {
+                       kprintf("madt_lapic_probe: "
+                               "invalid LAPIC address override length\n");
+                       return 0;
+               }
+               lapic_addr_ent = (const struct acpi_madt_lapic_addr *)ent;
+
+               if (lapic_addr_ent->mla_lapic_addr != 0)
+                       arg->lapic_addr = lapic_addr_ent->mla_lapic_addr;
+       }
+       return 0;
+}
+
 static int
 madt_lapic_probe(struct lapic_enumerator *e)
 {
-       vm_paddr_t madt_paddr;
+       struct madt_lapic_probe_cbarg arg;
+       struct acpi_madt *madt;
+       int error;
 
-       madt_paddr = madt_probe();
-       if (madt_paddr == 0)
+       if (madt_phyaddr == 0)
                return ENXIO;
 
-       ((struct madt_lapic_enumerator *)e)->madt_paddr = madt_paddr;
-       return 0;
+       madt = madt_sdth_map(madt_phyaddr);
+       KKASSERT(madt != NULL);
+
+       bzero(&arg, sizeof(arg));
+       arg.lapic_addr = madt->madt_lapic_addr;
+
+       error = madt_iterate_entries(madt, madt_lapic_probe_callback, &arg);
+       if (!error) {
+               if (arg.cpu_count <= 1) {
+                       kprintf("madt_lapic_probe: "
+                               "less than 2 CPUs is found\n");
+                       error = EOPNOTSUPP;
+               }
+               if (arg.lapic_addr == 0) {
+                       kprintf("madt_lapic_probe: zero LAPIC address\n");
+                       error = EOPNOTSUPP;
+               }
+       }
+
+       madt_sdth_unmap(&madt->madt_hdr);
+       return error;
 }
 
 static void
 madt_lapic_enumerate(struct lapic_enumerator *e)
 {
-       vm_paddr_t madt_paddr;
        vm_offset_t lapic_addr;
        int bsp_apic_id;
 
-       madt_paddr = ((struct madt_lapic_enumerator *)e)->madt_paddr;
-       KKASSERT(madt_paddr != 0);
+       KKASSERT(madt_phyaddr != 0);
 
-       lapic_addr = madt_pass1(madt_paddr);
+       lapic_addr = madt_pass1();
        if (lapic_addr == 0)
-               panic("madt_lapic_enumerate no local apic\n");
+               panic("madt_lapic_enumerate: no local apic\n");
 
        lapic_map(lapic_addr);
 
        bsp_apic_id = APIC_ID(lapic.id);
-       if (madt_pass2(madt_paddr, bsp_apic_id))
-               panic("mp_enable: madt_pass2 failed\n");
+       if (madt_pass2(bsp_apic_id))
+               panic("madt_lapic_enumerate: madt_pass2 failed\n");
 }
 
-static struct madt_lapic_enumerator    madt_lapic_enumerator = {
-       .enumerator = {
-               .lapic_prio = LAPIC_ENUM_PRIO_MADT,
-               .lapic_probe = madt_lapic_probe,
-               .lapic_enumerate = madt_lapic_enumerate
-       }
+static struct lapic_enumerator madt_lapic_enumerator = {
+       .lapic_prio = LAPIC_ENUM_PRIO_MADT,
+       .lapic_probe = madt_lapic_probe,
+       .lapic_enumerate = madt_lapic_enumerate
 };
 
 static void
@@ -699,8 +719,8 @@ madt_lapic_register(void)
 
        prio = LAPIC_ENUM_PRIO_MADT;
        kgetenv_int("hw.madt_lapic_prio", &prio);
-       madt_lapic_enumerator.enumerator.lapic_prio = prio;
+       madt_lapic_enumerator.lapic_prio = prio;
 
-       lapic_enumerator_register(&madt_lapic_enumerator.enumerator);
+       lapic_enumerator_register(&madt_lapic_enumerator);
 }
-SYSINIT(madt, SI_BOOT2_PRESMP, SI_ORDER_ANY, madt_lapic_register, 0);
+SYSINIT(madt_lapic, SI_BOOT2_PRESMP, SI_ORDER_ANY, madt_lapic_register, 0);
index c3130a1..5b07b06 100644 (file)
@@ -167,11 +167,6 @@ struct acpi_madt_lapic_addr {
        uint64_t                mla_lapic_addr;
 } __packed;
 
-struct madt_lapic_enumerator {
-       struct lapic_enumerator enumerator;
-       vm_paddr_t              madt_paddr;
-};
-
 typedef        vm_paddr_t              (*madt_search_t)(vm_paddr_t);
 typedef int                    (*madt_iter_t)(void *,
                                    const struct acpi_madt_ent *);
@@ -185,16 +180,17 @@ static int                        madt_check(vm_paddr_t);
 static int                     madt_iterate_entries(struct acpi_madt *,
                                    madt_iter_t, void *);
 
-static vm_paddr_t              madt_probe(void);
-static vm_offset_t             madt_pass1(vm_paddr_t);
-static int                     madt_pass2(vm_paddr_t, int);
+static vm_offset_t             madt_pass1(void);
+static int                     madt_pass2(int);
 
 static void                    madt_lapic_enumerate(struct lapic_enumerator *);
 static int                     madt_lapic_probe(struct lapic_enumerator *);
 
 extern u_long  ebda_addr;
 
-static vm_paddr_t
+static vm_paddr_t              madt_phyaddr;
+
+static void
 madt_probe(void)
 {
        const struct acpi_rsdp *rsdp;
@@ -203,6 +199,8 @@ madt_probe(void)
        vm_size_t mapsz;
        uint8_t *ptr;
 
+       KKASSERT(madt_phyaddr == 0);
+
        if (ebda_addr != 0) {
                mapsz = ACPI_RSDP_EBDA_MAPSZ;
                ptr = pmap_mapdev(ebda_addr, mapsz);
@@ -227,7 +225,7 @@ madt_probe(void)
        if (rsdp == NULL) {
                kprintf("madt_probe: no RSDP\n");
                pmap_unmapdev((vm_offset_t)ptr, mapsz);
-               return 0;
+               return;
        } else {
                MADT_VPRINTF("RSDP in BIOS mem\n");
        }
@@ -245,14 +243,18 @@ found_rsdp:
        madt_paddr = search(search_paddr);
        if (madt_paddr == 0) {
                kprintf("madt_probe: can't locate MADT\n");
-               return 0;
+               return;
        }
 
        /* Preliminary checks */
-       if (madt_check(madt_paddr))
-               return 0;
-       return madt_paddr;
+       if (madt_check(madt_paddr)) {
+               kprintf("madt_probe: madt_check failed\n");
+               return;
+       }
+
+       madt_phyaddr = madt_paddr;
 }
+SYSINIT(madt_probe, SI_BOOT2_PRESMP, SI_ORDER_FIRST, madt_probe, 0);
 
 static const struct acpi_rsdp *
 madt_rsdp_search(const uint8_t *target, int size)
@@ -428,16 +430,16 @@ madt_pass1_callback(void *xarg, const struct acpi_madt_ent *ent)
 }
 
 static vm_offset_t
-madt_pass1(vm_paddr_t madt_paddr)
+madt_pass1(void)
 {
        struct acpi_madt *madt;
        vm_offset_t lapic_addr;
        uint64_t lapic_addr64;
        int error;
 
-       KKASSERT(madt_paddr != 0);
+       KKASSERT(madt_phyaddr != 0);
 
-       madt = madt_sdth_map(madt_paddr);
+       madt = madt_sdth_map(madt_phyaddr);
        KKASSERT(madt != NULL);
 
        MADT_VPRINTF("LAPIC address 0x%08x, flags %#x\n",
@@ -491,7 +493,7 @@ madt_pass2_callback(void *xarg, const struct acpi_madt_ent *ent)
 }
 
 static int
-madt_pass2(vm_paddr_t madt_paddr, int bsp_apic_id)
+madt_pass2(int bsp_apic_id)
 {
        struct acpi_madt *madt;
        struct madt_pass2_cbarg arg;
@@ -499,9 +501,9 @@ madt_pass2(vm_paddr_t madt_paddr, int bsp_apic_id)
 
        MADT_VPRINTF("BSP apic id %d\n", bsp_apic_id);
 
-       KKASSERT(madt_paddr != 0);
+       KKASSERT(madt_phyaddr != 0);
 
-       madt = madt_sdth_map(madt_paddr);
+       madt = madt_sdth_map(madt_phyaddr);
        KKASSERT(madt != NULL);
 
        bzero(&arg, sizeof(arg));
@@ -521,29 +523,9 @@ madt_pass2(vm_paddr_t madt_paddr, int bsp_apic_id)
        return 0;
 }
 
-struct madt_check_cbarg {
-       int     cpu_count;
-};
-
-static int
-madt_check_callback(void *xarg, const struct acpi_madt_ent *ent)
-{
-       struct madt_check_cbarg *arg = xarg;
-       const struct acpi_madt_lapic *lapic_ent;
-
-       if (ent->me_type != MADT_ENT_LAPIC)
-               return 0;
-       lapic_ent = (const struct acpi_madt_lapic *)ent;
-
-       if (lapic_ent->ml_flags & MADT_LAPIC_ENABLED)
-               arg->cpu_count++;
-       return 0;
-}
-
 static int
 madt_check(vm_paddr_t madt_paddr)
 {
-       struct madt_check_cbarg arg;
        struct acpi_madt *madt;
        int error = 0;
 
@@ -566,16 +548,6 @@ madt_check(vm_paddr_t madt_paddr)
                error = EINVAL;
                goto back;
        }
-
-       bzero(&arg, sizeof(arg));
-
-       error = madt_iterate_entries(madt, madt_check_callback, &arg);
-       if (!error) {
-               if (arg.cpu_count <= 1) {
-                       kprintf("madt_check: less than 2 CPUs is found\n");
-                       error = EOPNOTSUPP;
-               }
-       }
 back:
        madt_sdth_unmap(&madt->madt_hdr);
        return error;
@@ -650,46 +622,94 @@ madt_iterate_entries(struct acpi_madt *madt, madt_iter_t func, void *arg)
        return error;
 }
 
+struct madt_lapic_probe_cbarg {
+       int             cpu_count;
+       vm_offset_t     lapic_addr;
+};
+
+static int
+madt_lapic_probe_callback(void *xarg, const struct acpi_madt_ent *ent)
+{
+       struct madt_lapic_probe_cbarg *arg = xarg;
+
+       if (ent->me_type == MADT_ENT_LAPIC) {
+               const struct acpi_madt_lapic *lapic_ent;
+
+               lapic_ent = (const struct acpi_madt_lapic *)ent;
+               if (lapic_ent->ml_flags & MADT_LAPIC_ENABLED)
+                       arg->cpu_count++;
+       } else if (ent->me_type == MADT_ENT_LAPIC_ADDR) {
+               const struct acpi_madt_lapic_addr *lapic_addr_ent;
+
+               if (ent->me_len < sizeof(*lapic_addr_ent)) {
+                       kprintf("madt_lapic_probe: "
+                               "invalid LAPIC address override length\n");
+                       return 0;
+               }
+               lapic_addr_ent = (const struct acpi_madt_lapic_addr *)ent;
+
+               if (lapic_addr_ent->mla_lapic_addr != 0)
+                       arg->lapic_addr = lapic_addr_ent->mla_lapic_addr;
+       }
+       return 0;
+}
+
 static int
 madt_lapic_probe(struct lapic_enumerator *e)
 {
-       vm_paddr_t madt_paddr;
+       struct madt_lapic_probe_cbarg arg;
+       struct acpi_madt *madt;
+       int error;
 
-       madt_paddr = madt_probe();
-       if (madt_paddr == 0)
+       if (madt_phyaddr == 0)
                return ENXIO;
 
-       ((struct madt_lapic_enumerator *)e)->madt_paddr = madt_paddr;
-       return 0;
+       madt = madt_sdth_map(madt_phyaddr);
+       KKASSERT(madt != NULL);
+
+       bzero(&arg, sizeof(arg));
+       arg.lapic_addr = madt->madt_lapic_addr;
+
+       error = madt_iterate_entries(madt, madt_lapic_probe_callback, &arg);
+       if (!error) {
+               if (arg.cpu_count <= 1) {
+                       kprintf("madt_lapic_probe: "
+                               "less than 2 CPUs is found\n");
+                       error = EOPNOTSUPP;
+               }
+               if (arg.lapic_addr == 0) {
+                       kprintf("madt_lapic_probe: zero LAPIC address\n");
+                       error = EOPNOTSUPP;
+               }
+       }
+
+       madt_sdth_unmap(&madt->madt_hdr);
+       return error;
 }
 
 static void
 madt_lapic_enumerate(struct lapic_enumerator *e)
 {
-       vm_paddr_t madt_paddr;
        vm_offset_t lapic_addr;
        int bsp_apic_id;
 
-       madt_paddr = ((struct madt_lapic_enumerator *)e)->madt_paddr;
-       KKASSERT(madt_paddr != 0);
+       KKASSERT(madt_phyaddr != 0);
 
-       lapic_addr = madt_pass1(madt_paddr);
+       lapic_addr = madt_pass1();
        if (lapic_addr == 0)
-               panic("madt_lapic_enumerate no local apic\n");
+               panic("madt_lapic_enumerate: no local apic\n");
 
        lapic_init(lapic_addr);
 
        bsp_apic_id = APIC_ID(lapic->id);
-       if (madt_pass2(madt_paddr, bsp_apic_id))
-               panic("mp_enable: madt_pass2 failed\n");
+       if (madt_pass2(bsp_apic_id))
+               panic("madt_lapic_enumerate: madt_pass2 failed\n");
 }
 
-static struct madt_lapic_enumerator    madt_lapic_enumerator = {
-       .enumerator = {
-               .lapic_prio = LAPIC_ENUM_PRIO_MADT,
-               .lapic_probe = madt_lapic_probe,
-               .lapic_enumerate = madt_lapic_enumerate
-       }
+static struct lapic_enumerator madt_lapic_enumerator = {
+       .lapic_prio = LAPIC_ENUM_PRIO_MADT,
+       .lapic_probe = madt_lapic_probe,
+       .lapic_enumerate = madt_lapic_enumerate
 };
 
 static void
@@ -699,8 +719,8 @@ madt_lapic_register(void)
 
        prio = LAPIC_ENUM_PRIO_MADT;
        kgetenv_int("hw.madt_lapic_prio", &prio);
-       madt_lapic_enumerator.enumerator.lapic_prio = prio;
+       madt_lapic_enumerator.lapic_prio = prio;
 
-       lapic_enumerator_register(&madt_lapic_enumerator.enumerator);
+       lapic_enumerator_register(&madt_lapic_enumerator);
 }
-SYSINIT(madt, SI_BOOT2_PRESMP, SI_ORDER_ANY, madt_lapic_register, 0);
+SYSINIT(madt_lapic, SI_BOOT2_PRESMP, SI_ORDER_ANY, madt_lapic_register, 0);