Start putting together ACPI for guests.
[akaros.git] / kern / drivers / dev / acpi.c
index 69876ec..d5aa3a3 100644 (file)
 #include <smp.h>
 #include <ip.h>
 #include <acpi.h>
+
+#include "../timers/hpet.h"
+
 #ifdef CONFIG_X86
 #include <arch/pci.h>
 #endif
 
+struct dev acpidevtab;
+
+static char *devname(void)
+{
+       return acpidevtab.name;
+}
+
 /*
  * ACPI 4.0 Support.
  * Still WIP.
@@ -54,6 +64,7 @@ static struct dirtab acpidir[] = {
        {"acpipretty", {Qpretty}, 0, 0444},
        {"ioapic", {Qioapic}, 0, 0444},
        {"apic", {Qapic}, 0, 0444},
+       {"raw", {Qraw}, 0, 0444},
 };
 
 /*
@@ -63,7 +74,10 @@ static struct dirtab acpidir[] = {
  * required to do early initialization before we have user processes.
  * Other tables are given to the user level interpreter for
  * execution.
- */
+ *
+ * These historically returned a value to tell acpi whether or not it was okay
+ * to unmap the table.  (return 0 means there was no table, meaning it was okay
+ * to unmap).  We just use the kernbase mapping, so it's irrelevant. */
 static struct Parse ptables[] = {
        {"FACP", acpifadt},
        {"APIC", acpimadt,},
@@ -71,6 +85,7 @@ static struct Parse ptables[] = {
        {"SLIT", acpislit,},
        {"MSCT", acpimsct,},
        {"SSDT", acpitable,},
+       {"HPET", acpihpet,},
 };
 
 static struct Facs *facs;              /* Firmware ACPI control structure */
@@ -79,7 +94,7 @@ static struct Xsdt *xsdt;             /* XSDT table */
 static struct Atable *tfirst;  /* loaded DSDT/SSDT/... tables */
 static struct Atable *tlast;   /* pointer to last table */
 struct Madt *apics;                            /* APIC info */
-static struct Srat *srat;              /* System resource affinity, used by physalloc */
+struct Srat *srat;                             /* System resource affinity, used by physalloc */
 static struct Slit *slit;              /* System locality information table used by the scheduler */
 static struct Msct *msct;              /* Maximum system characteristics table */
 static struct Reg *reg;                        /* region used for I/O */
@@ -308,11 +323,6 @@ regcpy(struct Regio *dio, uintptr_t da, struct Regio *sio,
        return n * align;
 }
 
-// until we know.  TODO: spatch/find_replace this shit, same with mp.c
-//#define vmap(x,y) (void *)vmap_pmem((x),(y))
-//#define vunmap(x,y) vunmap_vmem((uintptr_t)(x),(y))
-#define vmap(x,y) ((void*)(x + KERNBASE))
-#define vunmap(x,y)
 /*
  * Perform I/O within region in access units of accsz bytes.
  * All units in bytes.
@@ -336,9 +346,9 @@ static long regio(struct Reg *r, void *p, uint32_t len, uintptr_t off, int iswr)
        switch (r->spc) {
                case Rsysmem:
                        if (r->p == NULL)
-                               r->p = vmap(r->base, len);
+                               r->p = KADDR_NOCHECK(r->base);
                        if (r->p == NULL)
-                               error("regio: vmap failed");
+                               error(EFAIL, "regio: vmap/KADDR failed");
                        rp = (uintptr_t) r->p + off;
                        rio = memio;
                        break;
@@ -358,7 +368,7 @@ static long regio(struct Reg *r, void *p, uint32_t len, uintptr_t off, int iswr)
                case Ripmi:
                case Rfixedhw:
                        printd("regio: reg %s not supported\n", acpiregstr(r->spc));
-                       error("region not supported");
+                       error(EFAIL, "region not supported");
        }
        if (iswr)
                regcpy(&rio, rp, &memio, (uintptr_t) p, len, r->accsz);
@@ -367,7 +377,7 @@ static long regio(struct Reg *r, void *p, uint32_t len, uintptr_t off, int iswr)
        return len;
 }
 
-static struct Atable *newtable(uint8_t * p)
+struct Atable *new_acpi_table(uint8_t * p)
 {
        struct Atable *t;
        struct Sdthdr *h;
@@ -417,24 +427,22 @@ static void *sdtmap(uintptr_t pa, int *n, int cksum)
                printk("sdtmap: NULL pa\n");
                return NULL;
        }
-       sdt = vmap(pa, sizeof(*sdt));
+       sdt = KADDR_NOCHECK(pa);
        if (sdt == NULL) {
                printk("acpi: vmap1: NULL\n");
                return NULL;
        }
        *n = l32get(sdt->length);
-       vunmap(sdt, sizeof(*sdt));
        if (!*n) {
                printk("sdt has zero length!\n");
                return NULL;
        }
-       if ((sdt = vmap(pa, *n)) == NULL) {
+       if ((sdt = KADDR_NOCHECK(pa)) == NULL) {
                printk("acpi: NULL vmap\n");
                return NULL;
        }
        if (cksum != 0 && sdtchecksum(sdt, *n) == NULL) {
                printk("acpi: SDT: bad checksum\n");
-               vunmap(sdt, sizeof(*sdt));
                return NULL;
        }
        return sdt;
@@ -449,7 +457,6 @@ static int loadfacs(uintptr_t pa)
                return -1;
        }
        if (memcmp(facs, "FACS", 4) != 0) {
-               //vunmap(facs, n);
                facs = NULL;
                return -1;
        }
@@ -474,7 +481,6 @@ static void loaddsdt(uintptr_t pa)
        if (dsdtp == NULL) {
                return;
        }
-       if (acpitable(dsdtp, n) == NULL) ;      //vunmap(dsdtp, n);
 }
 
 static void gasget(struct Gas *gas, uint8_t * p)
@@ -492,6 +498,7 @@ static char *dumpfadt(char *start, char *end, struct Fadt *fp)
                return NULL;
        }
 
+       start = seprintf(start, end, "acpi: FADT@%p\n", fp);
        start = seprintf(start, end, "acpi: fadt: facs: $%p\n", fp->facs);
        start = seprintf(start, end, "acpi: fadt: dsdt: $%p\n", fp->dsdt);
        start = seprintf(start, end, "acpi: fadt: pmprofile: $%p\n", fp->pmprofile);
@@ -678,7 +685,7 @@ static struct Atable *acpimsct(uint8_t * p, int len)
 
 static char *dumpsrat(char *start, char *end, struct Srat *st)
 {
-       start = seprintf(start, end, "acpi: srat:\n");
+       start = seprintf(start, end, "acpi: START@%p:\n", st);
        for (; st != NULL; st = st->next)
                switch (st->type) {
                        case SRlapic:
@@ -848,7 +855,7 @@ int pickcore(int mycolor, int index)
        if (slit == NULL) {
                return 0;
        }
-       ncorepercol = num_cpus / slit->rowlen;
+       ncorepercol = num_cores / slit->rowlen;
        color = slit->e[mycolor][index / ncorepercol].dom;
        return color * ncorepercol + index % ncorepercol;
 }
@@ -879,8 +886,8 @@ static char *dumpmadt(char *start, char *end, struct Madt *apics)
        struct Apicst *st;
 
        start =
-               seprintf(start, end, "acpi: madt lapic paddr %llux pcat %d:\n",
-                                apics->lapicpa, apics->pcat);
+               seprintf(start, end, "acpi: MADT@%p: lapic paddr %p pcat %d:\n",
+                               apics, apics->lapicpa, apics->pcat);
        for (st = apics->st; st != NULL; st = st->next)
 
                switch (st->type) {
@@ -893,7 +900,7 @@ static char *dumpmadt(char *start, char *end, struct Madt *apics)
                        case ASiosapic:
                                start =
                                        seprintf(start, end,
-                                                        "\tioapic id %d addr %#llux ibase %d\n",
+                                                        "\tioapic id %d addr %p ibase %d\n",
                                                         st->ioapic.id, st->ioapic.addr, st->ioapic.ibase);
                                break;
                        case ASintovr:
@@ -1073,7 +1080,7 @@ static struct Atable *acpitable(uint8_t * p, int len)
        if (len < Sdthdrsz) {
                return NULL;
        }
-       return newtable(p);
+       return new_acpi_table(p);
 }
 
 static char *dumptable(char *start, char *end, char *sig, uint8_t * p, int l)
@@ -1123,7 +1130,7 @@ static char *seprinttable(char *s, char *e, struct Atable *t)
  */
 static int acpixsdtload(char *sig)
 {
-       int i, l, t, unmap, found;
+       int i, l, t, found;
        uintptr_t dhpa;
        uint8_t *sdt;
        char tsig[5];
@@ -1137,7 +1144,6 @@ static int acpixsdtload(char *sig)
                        dhpa = l32get(xsdt->p + i);
                if ((sdt = sdtmap(dhpa, &l, 1)) == NULL)
                        continue;
-               unmap = 1;
                memmove(tsig, sdt, 4);
                tsig[4] = 0;
                if (sig == NULL || strcmp(sig, tsig) == 0) {
@@ -1145,13 +1151,11 @@ static int acpixsdtload(char *sig)
                        for (t = 0; t < ARRAY_SIZE(ptables); t++)
                                if (strcmp(tsig, ptables[t].sig) == 0) {
                                        //dumptable(table, &table[127], tsig, sdt, l);
-                                       unmap = ptables[t].f(sdt, l) == NULL;
+                                       ptables[t].f(sdt, l);
                                        found = 1;
                                        break;
                                }
                }
-//      if(unmap)
-//          vunmap(sdt, l);
        }
        return found;
 }
@@ -1176,10 +1180,16 @@ static void acpirsdptr(void)
        uintptr_t sdtpa;
 
        if ((rsd = rsdsearch("RSD PTR ")) == NULL) {
+               printk("NO RSDP\n");
                return;
        }
 
+
        assert(sizeof(struct Sdthdr) == 36);
+       printd("/* RSDP */ struct Rsdp = {%08c, %x, %06c, %x, %p, %d, %p, %x}\n",
+              rsd->signature, rsd->rchecksum, rsd->oemid, rsd->revision,
+              *(uint32_t *)rsd->raddr, *(uint32_t *)rsd->length,
+              *(uint32_t *)rsd->xaddr, rsd->xchecksum);
 
        printd("acpi: RSD PTR@ %#p, physaddr $%p length %ud %#llux rev %d\n",
                   rsd, l32get(rsd->raddr), l32get(rsd->length),
@@ -1219,7 +1229,6 @@ static void acpirsdptr(void)
                           xsdt->p[3]);
                kfree(xsdt);
                xsdt = NULL;
-               //vunmap(xsdt, xsdt->len);
                return;
        }
        xsdt->p += sizeof(struct Sdthdr);
@@ -1239,7 +1248,7 @@ acpigen(struct chan *c, char *unused_char_p_t, struct dirtab *tab, int ntab,
 
        if (i == DEVDOTDOT) {
                mkqid(&qid, Qdir, 0, QTDIR);
-               devdir(c, qid, ".", 0, eve, 0555, dp);
+               devdir(c, qid, devname(), 0, eve, 0555, dp);
                return 1;
        }
        i++;    /* skip first element for . itself */
@@ -1404,7 +1413,6 @@ static unsigned int getgpests(int n)
        return inb(gpes[n].stsio) & 1 << gpes[n].stsbit;
 }
 
-#warning "no acpi interrupts yet"
 #if 0
 static void acpiintr(Ureg *, void *)
 {
@@ -1494,9 +1502,8 @@ static struct chan *acpiattach(char *spec)
         * This was written for the stock kernel.
         * This code must use 64 registers to be acpi ready in nix.
         */
-       if (acpiinit() < 0) {
-               error("no acpi");
-       }
+       if (acpiinit() < 0)
+               error(ENOSYS, "no acpi");
 
        /*
         * should use fadt->xpm* and fadt->xgpe* registers for 64 bits.
@@ -1523,10 +1530,10 @@ static struct chan *acpiattach(char *spec)
                if (getpm1ctl() & Pm1SciEn)
                        break;
        if (i == 10)
-               error("acpi: failed to enable\n");
+               error(EFAIL, "acpi: failed to enable\n");
 //  if(fadt.sciint != 0)
 //      intrenable(fadt.sciint, acpiintr, 0, BUSUNKNOWN, "acpi");
-       return devattach('a', spec);
+       return devattach(devname(), spec);
 }
 
 static struct walkqid *acpiwalk(struct chan *c, struct chan *nc, char **name,
@@ -1562,17 +1569,19 @@ static long acpiread(struct chan *c, void *a, long n, int64_t off)
                tlen = 32768;
                ttext = kzmalloc(tlen, 0);
        }
-       if (ttext == NULL) {
-               error("acpiread: no memory");
-       }
+       if (ttext == NULL)
+               error(ENOMEM, "acpiread: no memory");
        q = c->qid.path;
        switch (q) {
                case Qdir:
                        return devdirread(c, a, n, acpidir, ARRAY_SIZE(acpidir), acpigen);
+               case Qraw:
+                       return readmem(off, a, n, ttext, tlen);
+                       break;
                case Qtbl:
                        s = ttext;
                        e = ttext + tlen;
-                       strncpy(s, "no tables\n", sizeof(s));
+                       strlcpy(s, "no tables\n", tlen);
                        for (t = tfirst; t != NULL; t = t->next) {
                                ns = seprinttable(s, e, t);
                                while (ns == e - 1) {
@@ -1605,10 +1614,10 @@ static long acpiread(struct chan *c, void *a, long n, int64_t off)
                        return readstr(off, a, n, ttext);
                case Qio:
                        if (reg == NULL)
-                               error("region not configured");
+                               error(EFAIL, "region not configured");
                        return regio(reg, a, n, off, 0);
        }
-       error(Eperm);
+       error(EPERM, NULL);
        return -1;
 }
 
@@ -1622,11 +1631,11 @@ static long acpiwrite(struct chan *c, void *a, long n, int64_t off)
 
        if (c->qid.path == Qio) {
                if (reg == NULL)
-                       error("region not configured");
+                       error(EFAIL, "region not configured");
                return regio(reg, a, n, off, 1);
        }
        if (c->qid.path != Qctl)
-               error(Eperm);
+               error(EPERM, NULL);
 
        cb = parsecmd(a, n);
        if (waserror()) {
@@ -1647,7 +1656,7 @@ static long acpiwrite(struct chan *c, void *a, long n, int64_t off)
                        if (r->spc < 0) {
                                kfree(r);
                                reg = NULL;
-                               error("bad region type");
+                               error(EFAIL, "bad region type");
                        }
                        if (r->spc == Rpcicfg || r->spc == Rpcibar) {
                                rno = r->base >> Rpciregshift & Rpciregmask;
@@ -1667,7 +1676,7 @@ static long acpiwrite(struct chan *c, void *a, long n, int64_t off)
                        if (r->accsz < 1 || r->accsz > 4) {
                                kfree(r);
                                reg = NULL;
-                               error("bad region access size");
+                               error(EFAIL, "bad region access size");
                        }
                        reg = r;
                        printd("region %s %s %p %p sz%d",
@@ -1676,7 +1685,7 @@ static long acpiwrite(struct chan *c, void *a, long n, int64_t off)
                case CMgpe:
                        i = strtoul(cb->f[1], NULL, 0);
                        if (i >= ngpes)
-                               error("gpe out of range");
+                               error(ERANGE, "gpe out of range");
                        kstrdup(&gpes[i].obj, cb->f[2]);
                        setgpeen(i, 1);
                        break;
@@ -1689,7 +1698,6 @@ static long acpiwrite(struct chan *c, void *a, long n, int64_t off)
 }
 
 struct dev acpidevtab __devtab = {
-       'a',
        "acpi",
 
        devreset,