akaros/kern/arch/x86/mpacpi.c
<<
>>
Prefs
   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#include <slab.h>
   9#include <kmalloc.h>
  10#include <kref.h>
  11#include <string.h>
  12#include <stdio.h>
  13#include <assert.h>
  14#include <error.h>
  15#include <cpio.h>
  16#include <pmap.h>
  17#include <smp.h>
  18#include <net/ip.h>
  19#include <acpi.h>
  20#include <arch/ioapic.h>
  21#include <arch/topology.h>
  22
  23int mpacpi(int ncleft)
  24{
  25        char *already;
  26        int np, bp;
  27        struct apic *apic;
  28        struct Apicst *st;
  29        struct Madt *mt;
  30
  31        /* If we don't have an mpisabusno yet, it's because the MP tables failed
  32         * to parse.  So we'll just take the last one available.  I think we're
  33         * supposed to parse the ACPI shit with the AML to figure out the buses
  34         * and find a clear one, but fuck that.  Note this busno is just for our
  35         * own RDT/Rbus bookkeeping. */
  36        if (mpisabusno == -1)
  37                mpisabusno = Nbus - 1;
  38
  39        if (apics == NULL)
  40                return ncleft;
  41        mt = apics->tbl;
  42        if (mt == NULL)
  43                return ncleft;
  44
  45        printd("APIC lapic paddr %#.8llux, flags %#.8ux\n",
  46                   mt->lapicpa, mt->pcat);
  47        np = 0;
  48        printd("apics->st %p\n", apics->st);
  49        for (int i = 0; i < apics->nchildren; i++) {
  50                st = apics->children[i]->tbl;
  51                already = "";
  52                switch (st->type) {
  53                case ASlapic:
  54                        printd("ASlapic %d\n", st->lapic.id);
  55                        /* this table is supposed to have all of them if it
  56                         * 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                                apicinit(st->lapic.id, mt->lapicpa, bp);
  66                        } else
  67                                already = "(off)";
  68
  69                        printd("apic proc %d/%d apicid %d %s\n", np - 1,
  70                               apic->machno, st->lapic.id, already);
  71                        break;
  72                case ASioapic:
  73                        printd("ASioapic %d\n", st->ioapic.id);
  74                        if (st->ioapic.id > Napic)
  75                                break;
  76                        apic = xioapic + st->ioapic.id;
  77                        if (apic->useable) {
  78                                apic->ibase = st->ioapic.ibase; /* gnarly */
  79                                already = "(mp)";
  80                                goto pr1;
  81                        }
  82                        ioapicinit(st->ioapic.id, st->ioapic.ibase,
  83                                   st->ioapic.addr);
  84pr1:
  85                        printd("ioapic %d ", st->ioapic.id);
  86                        printd("addr %p base %d %s\n", apic->paddr, apic->ibase,
  87                                   already);
  88                        break;
  89                }
  90        }
  91        return ncleft;
  92}
  93