x86: MP table cleanup, multiple IOAPICs
[akaros.git] / kern / arch / x86 / mpacpi.c
1 /* This file is part of the UCB release of Plan 9. It is subject to the license
2  * terms in the LICENSE file found in the top-level directory of this
3  * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
4  * part of the UCB release of Plan 9, including this file, may be copied,
5  * modified, propagated, or distributed except according to the terms contained
6  * in the LICENSE file. */
7
8 #define DEBUG
9 #include <vfs.h>
10 #include <kfs.h>
11 #include <slab.h>
12 #include <kmalloc.h>
13 #include <kref.h>
14 #include <string.h>
15 #include <stdio.h>
16 #include <assert.h>
17 #include <error.h>
18 #include <cpio.h>
19 #include <pmap.h>
20 #include <smp.h>
21 #include <ip.h>
22 #include <acpi.h>
23 #include <arch/ioapic.h>
24 #include <arch/coreid.h>
25
26 extern struct Madt *apics;
27
28 int mpacpi(int ncleft)
29 {
30         char *already;
31         int np, bp;
32         struct apic *apic;
33         struct Apicst *st;
34
35         /* If we don't have an mpisabusno yet, it's because the MP tables failed to
36          * parse.  So we'll just take the last one available.  I think we're
37          * supposed to parse the ACPI shit with the AML to figure out the buses and
38          * find a clear one, but fuck that.  Note this busno is just for our own
39          * RDT/Rbus bookkeeping. */
40         if (mpisabusno == -1)
41                 mpisabusno = Nbus - 1;
42
43         printk("mpacpi ncleft %d\n", ncleft);
44         if (apics == NULL)
45                 return ncleft;
46
47         printd("APIC lapic paddr %#.8llux, flags %#.8ux\n",
48                    apics->lapicpa, apics->pcat);
49         np = 0;
50         printd("apics->st %p\n", apics->st);
51         for (st = apics->st; st != NULL; st = st->next) {
52                 already = "";
53                 switch (st->type) {
54                         case ASlapic:
55                                 printd("ASlapic %d\n", st->lapic.id);
56                                 /* this table is supposed to have all of them if it exists */
57                                 if (st->lapic.id > MaxAPICNO)
58                                         break;
59                                 apic = xlapic + st->lapic.id;
60                                 bp = (np++ == 0);
61                                 if (apic->useable) {
62                                         already = "(mp)";
63                                 } else if (ncleft != 0) {
64                                         ncleft--;
65                                         printk("apicinit(%d, %p, %d);\n", st->lapic.id,
66                                                    apics->lapicpa, bp);
67                                         apicinit(st->lapic.id, apics->lapicpa, bp);
68                                 } else
69                                         already = "(off)";
70
71                                 printd("apic proc %d/%d apicid %d %s\n", np - 1, apic->machno,
72                                            st->lapic.id, already);
73                                 break;
74                         case ASioapic:
75                                 printd("ASioapic %d\n", st->ioapic.id);
76                                 if (st->ioapic.id > Napic)
77                                         break;
78                                 apic = xioapic + st->ioapic.id;
79                                 if (apic->useable) {
80                                         apic->ibase = st->ioapic.ibase; /* gnarly */
81                                         already = "(mp)";
82                                         goto pr1;
83                                 }
84                                 printk("ioapicinit(%d, %p, %p);\n", st->lapic.id,
85                                            apics->lapicpa, st->ioapic.addr);
86                                 ioapicinit(st->ioapic.id, st->ioapic.ibase, st->ioapic.addr);
87 pr1:
88                                 printd("ioapic %d ", st->ioapic.id);
89                                 printd("addr %p base %d %s\n", apic->paddr, apic->ibase,
90                                            already);
91                                 break;
92                 }
93         }
94         return ncleft;
95 }