| /* 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 <vfs.h> | 
 | #include <kfs.h> | 
 | #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 <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; | 
 | } |