| /* This file is part of the UCB release of Plan 9. It is subject to the license |
| * terms in the LICENSE file found in the top-level directory of this |
| * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No |
| * part of the UCB release of Plan 9, including this file, may be copied, |
| * modified, propagated, or distributed except according to the terms contained |
| * in the LICENSE file. */ |
| |
| #include <slab.h> |
| #include <kmalloc.h> |
| #include <kref.h> |
| #include <string.h> |
| #include <stdio.h> |
| #include <assert.h> |
| #include <error.h> |
| #include <cpio.h> |
| #include <pmap.h> |
| #include <smp.h> |
| #include <net/ip.h> |
| #include <acpi.h> |
| #include <arch/ioapic.h> |
| #include <arch/topology.h> |
| |
| int mpacpi(int ncleft) |
| { |
| char *already; |
| int np, bp; |
| struct apic *apic; |
| struct Apicst *st; |
| struct Madt *mt; |
| |
| /* If we don't have an mpisabusno yet, it's because the MP tables failed |
| * to parse. So we'll just take the last one available. I think we're |
| * supposed to parse the ACPI shit with the AML to figure out the buses |
| * and find a clear one, but fuck that. Note this busno is just for our |
| * own RDT/Rbus bookkeeping. */ |
| if (mpisabusno == -1) |
| mpisabusno = Nbus - 1; |
| |
| if (apics == NULL) |
| return ncleft; |
| mt = apics->tbl; |
| if (mt == NULL) |
| return ncleft; |
| |
| printd("APIC lapic paddr %#.8llux, flags %#.8ux\n", |
| mt->lapicpa, mt->pcat); |
| np = 0; |
| printd("apics->st %p\n", apics->st); |
| for (int i = 0; i < apics->nchildren; i++) { |
| st = apics->children[i]->tbl; |
| already = ""; |
| switch (st->type) { |
| case ASlapic: |
| printd("ASlapic %d\n", st->lapic.id); |
| /* this table is supposed to have all of them if it |
| * exists */ |
| if (st->lapic.id > MaxAPICNO) |
| break; |
| apic = xlapic + st->lapic.id; |
| bp = (np++ == 0); |
| if (apic->useable) { |
| already = "(mp)"; |
| } else if (ncleft != 0) { |
| ncleft--; |
| apicinit(st->lapic.id, mt->lapicpa, bp); |
| } else |
| already = "(off)"; |
| |
| printd("apic proc %d/%d apicid %d %s\n", np - 1, |
| apic->machno, st->lapic.id, already); |
| break; |
| case ASioapic: |
| printd("ASioapic %d\n", st->ioapic.id); |
| if (st->ioapic.id > Napic) |
| break; |
| apic = xioapic + st->ioapic.id; |
| if (apic->useable) { |
| apic->ibase = st->ioapic.ibase; /* gnarly */ |
| already = "(mp)"; |
| goto pr1; |
| } |
| ioapicinit(st->ioapic.id, st->ioapic.ibase, |
| st->ioapic.addr); |
| pr1: |
| printd("ioapic %d ", st->ioapic.id); |
| printd("addr %p base %d %s\n", apic->paddr, apic->ibase, |
| already); |
| break; |
| } |
| } |
| return ncleft; |
| } |