ACPI Table Fixes for vmrunkernel
authorMichael Taufen <mtaufen@gmail.com>
Tue, 29 Mar 2016 20:25:54 +0000 (13:25 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 6 Apr 2016 20:37:47 +0000 (16:37 -0400)
Please note: Our ACPI tables are still quite hacky, and should probably
revised at some point in the future.

Upgraded table revision numbers as per the ACPI 5.0a spec

Used macros from actbl.h for ACPI table signatures
  One issue was that we had used "FADT" as the signature
  for the FADT table, when the ACPI spec says to use
  "FACP." Using the macros from the header should help
  avoid this in the future.

Provided a pre-compiled (from asl to c) DSDT in a new header file.
ACPI requires the DSDT table be present, and Linux makes the
reasonable assumption that you will provide it.

Puts the FADT address in the first entry of the XSDT, as Linux expects.

Background:

Linux used to place tables at fixed indices in an internal array
when reading in ACPI. It would look for the DSDT in a specific place
in that array later on, even when it hadn't managed to install it,
and would bail out and continue booting when it found bogus data.

We noticed the issue when we upgraded our Linux fork to v4.5, in which
they use a default value of 0xffffffff for the FADT and DSDT indices,
and set these indices as the tables are installed rather than using
fixed positions.

It would look for the address of the DSDT at this index, and the use of the
retrieved, bogus address would cause a page fault in the kernel during boot.

Linux commit 8ec3f459073e67e5c6d78507dec693064b3040a2 contains the relevant
change to ACPI code.

Signed-off-by: Michael Taufen <mtaufen@gmail.com>
[fixed checkpatch complaints, rm extraneous //comment]
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
tests/vmm/vmrunkernel.c
user/vmm/include/vmm/acpi/vmm_simple_dsdt.h [new file with mode: 0644]

index 1d06723..2439433 100644 (file)
@@ -15,6 +15,7 @@
 #include <vmm/coreboot_tables.h>
 #include <vmm/vmm.h>
 #include <vmm/acpi/acpi.h>
+#include <vmm/acpi/vmm_simple_dsdt.h>
 #include <ros/arch/mmu.h>
 #include <ros/vmm.h>
 #include <parlib/uthread.h>
@@ -196,7 +197,7 @@ static void run_vmthread(struct vmctl *vmctl)
  */
 
 struct acpi_table_rsdp rsdp = {
-       .signature = "RSD PTR ",
+       .signature = ACPI_SIG_RSDP,
        .oem_id = "AKAROS",
        .revision = 2,
        .length = 36,
@@ -204,9 +205,8 @@ struct acpi_table_rsdp rsdp = {
 
 struct acpi_table_xsdt xsdt = {
        .header = {
-               .signature= "XSDT",
-               // This is so stupid. Incredibly stupid.
-               .revision = 0,
+               .signature = ACPI_SIG_DSDT,
+               .revision = 2,
                .oem_id = "AKAROS",
                .oem_table_id = "ALPHABET",
                .oem_revision = 0,
@@ -216,9 +216,8 @@ struct acpi_table_xsdt xsdt = {
 };
 struct acpi_table_fadt fadt = {
        .header = {
-               .signature= "FADT",
-               // This is so stupid. Incredibly stupid.
-               .revision = 0,
+               .signature = ACPI_SIG_FADT,
+               .revision = 2,
                .oem_id = "AKAROS",
                .oem_table_id = "ALPHABET",
                .oem_revision = 0,
@@ -227,12 +226,13 @@ struct acpi_table_fadt fadt = {
        },
 };
 
+
 /* This has to be dropped into memory, then the other crap just follows it.
  */
 struct acpi_table_madt madt = {
        .header = {
-               .signature = "APIC",
-               .revision = 0,
+               .signature = ACPI_SIG_MADT,
+               .revision = 2,
                .oem_id = "AKAROS",
                .oem_table_id = "ALPHABET",
                .oem_revision = 0,
@@ -704,7 +704,7 @@ int main(int argc, char **argv)
        fprintf(stderr, "install rsdp to %p\n", r);
        *r = rsdp;
        a += sizeof(*r);
-       memmove(&r->xsdt_physical_address, &a, sizeof(a));
+       r->xsdt_physical_address = (uint64_t)a;
        gencsum(&r->checksum, r, ACPI_RSDP_CHECKSUM_LENGTH);
        if ((csum = acpi_tb_checksum((uint8_t *) r, ACPI_RSDP_CHECKSUM_LENGTH)) != 0) {
                fprintf(stderr, "RSDP has bad checksum; summed to %x\n", csum);
@@ -733,12 +733,18 @@ int main(int argc, char **argv)
        f = a;
        fprintf(stderr, "install fadt to %p\n", f);
        *f = fadt;
-       x->table_offset_entry[2] = (uint64_t) f;
+       x->table_offset_entry[0] = (uint64_t)f; // fadt MUST be first in xsdt!
        a += sizeof(*f);
        f->header.length = a - (void *)f;
+
+       f->Xdsdt = (uint64_t) a;
+       fprintf(stderr, "install dsdt to %p\n", a);
+       memcpy(a, &DSDT_DSDTTBL_Header, 36);
+       a += 36;
+
        gencsum(&f->header.checksum, f, f->header.length);
        if (acpi_tb_checksum((uint8_t *)f, f->header.length) != 0) {
-               fprintf(stderr, "ffadt has bad checksum v2\n");
+               fprintf(stderr, "fadt has bad checksum v2\n");
                exit(1);
        }
 
@@ -756,12 +762,12 @@ int main(int argc, char **argv)
        memmove(a, &isor, sizeof(isor));
        a += sizeof(isor);
        m->header.length = a - (void *)m;
+
        gencsum(&m->header.checksum, m, m->header.length);
        if (acpi_tb_checksum((uint8_t *) m, m->header.length) != 0) {
                fprintf(stderr, "madt has bad checksum v2\n");
                exit(1);
        }
-       fprintf(stderr, "allchecksums ok\n");
 
        gencsum(&x->header.checksum, x, x->header.length);
        if ((csum = acpi_tb_checksum((uint8_t *) x, x->header.length)) != 0) {
@@ -769,6 +775,10 @@ int main(int argc, char **argv)
                exit(1);
        }
 
+
+
+       fprintf(stderr, "allchecksums ok\n");
+
        hexdump(stdout, r, a-(void *)r);
 
        a = (void *)(((unsigned long)a + 0xfff) & ~0xfff);
diff --git a/user/vmm/include/vmm/acpi/vmm_simple_dsdt.h b/user/vmm/include/vmm/acpi/vmm_simple_dsdt.h
new file mode 100644 (file)
index 0000000..748592d
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ *
+ * Intel ACPI Component Architecture
+ * ASL Optimizing Compiler version 20140214-64 [Mar 29 2014]
+ * Copyright (c) 2000 - 2014 Intel Corporation
+ *
+ * Compilation of "vmm_acpi_dsdt.dsl" - Fri Apr  1 13:34:26 2016
+ *
+ */
+
+    /*
+     *
+     * Based on the example at osdev wiki wiki.osdev.org/AML,
+     * and the other example in http://www.acpi.info/DOWNLOADS/ACPI_5_Errata%20A.pdf
+     * on page 194
+     *
+     * Compiled with `iasl -sc input_file.dsl`
+    */
+
+    /*
+     *       9:  DefinitionBlock (
+     *      10:      "vmm_acpi_dsdt.aml", // Output AML Filename : String
+     *      11:      "DSDT",              // Signature : String
+     *      12:      0x2,                 // DSDT Compliance Revision : ByteConst
+     *      13:      "MIKE",              // OEMID : String
+     *      14:      "DSDTTBL",           // TABLE ID : String
+     *      15:      0x0                  // OEM Revision : DWordConst
+     *      16:  ){}
+     */
+    unsigned char    DSDT_DSDTTBL_Header [] =
+    {
+        0x44,0x53,0x44,0x54,0x24,0x00,0x00,0x00,    /* 00000000    "DSDT$..." */
+        0x02,0xF3,0x4D,0x49,0x4B,0x45,0x00,0x00,    /* 00000008    "..MIKE.." */
+        0x44,0x53,0x44,0x54,0x54,0x42,0x4C,0x00,    /* 00000010    "DSDTTBL." */
+        0x00,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C,    /* 00000018    "....INTL" */
+        0x14,0x02,0x14,0x20,                        /* 00000020    "... " */
+    /*
+
+     */
+    };