9ns: Support SYS_access (XCC)
[akaros.git] / kern / include / acpi.h
index 4e45819..02b4df2 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * 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
@@ -7,9 +7,57 @@
  * in the LICENSE file.
  */
 
+/* -----------------------------------------------------------------------------
+ * ACPI is a table of tables. The tables define a hierarchy.
+ *
+ * From the hardware's perspective:
+ * Each table that we care about has a header, and the header has a
+ * length that includes the the length of all its subtables. So, even
+ * if you can't completely parse a table, you can find the next table.
+ *
+ * The process of parsing is to find the RSDP, and then for each subtable
+ * see what type it is and parse it. The process is recursive except for
+ * a few issues: The RSDP signature and header differs from the header of
+ * its subtables; their headers differ from the signatures of the tables
+ * they contain. As you walk down the tree, you need different parsers.
+ *
+ * The parser is recursive descent. Each parsing function takes a pointer
+ * to the parent of the node it is parsing and will attach itself to the parent
+ * via that pointer. Parsing functions are responsible for building the data
+ * structures that represent their node and recursive invocations of the parser
+ * for subtables.
+ *
+ * So, in this case, it's something like this:
+ *
+ * RSDP is the root. It has a standard header and size. You map that
+ * memory.  You find the first header, get its type and size, and
+ * parse as much of it as you can. Parsing will involve either a
+ * function or case statement for each element type. DMARs are complex
+ * and need functions; APICs are simple and we can get by with case
+ * statements.
+ *
+ * Each node in the tree is represented as a 'struct Atable'. This has a
+ * pointer to the actual node data, a type tag, a name, pointers to this
+ * node's children (if any) and a parent pointer. It also has a QID so that
+ * the entire structure can be exposed as a filesystem. The Atable doesn't
+ * contain any table data per se; it's metadata. The table pointer contains
+ * the table data as well as a pointer back to it's corresponding Atable.
+ *
+ * In the end we present a directory tree for #apic that looks, in this example:
+ * #acpi/DMAR/DRHD/0/{pretty,raw}
+ *
+ * 'cat pretty' will return JSON-encoded data described the element.
+ * 'cat raw' gets you the raw bytes.
+ */
+
+#pragma once
+
+#include <ns.h>
+#include <slice.h>
+
 enum {
 
-       Sdthdrsz = 36,                          /* size of SDT header */
+       Sdthdrsz = 36,                  /* size of SDT header */
 
        /* ACPI regions. Gas ids */
        Rsysmem = 0,
@@ -23,7 +71,7 @@ enum {
        Rfixedhw = 0x7f,
 
        /* ACPI PM1 control */
-       Pm1SciEn = 0x1, /* Generate SCI and not SMI */
+       Pm1SciEn = 0x1,                 /* Generate SCI and not SMI */
 
        /* ACPI tbdf as encoded in acpi region base addresses */
        Rpciregshift = 0,
@@ -36,60 +84,110 @@ enum {
        Rpcibusmask = 0xFFFF,
 
        /* Apic structure types */
-       ASlapic = 0,    /* processor local apic */
-       ASioapic,       /* I/O apic */
-       ASintovr,       /* Interrupt source override */
-       ASnmi,  /* NMI source */
-       ASlnmi, /* local apic nmi */
-       ASladdr,        /* local apic address override */
-       ASiosapic,      /* I/O sapic */
-       ASlsapic,       /* local sapic */
-       ASintsrc,       /* platform interrupt sources */
-       ASlx2apic,      /* local x2 apic */
-       ASlx2nmi,       /* local x2 apic NMI */
+       ASlapic = 0,            /* processor local apic */
+       ASioapic,                       /* I/O apic */
+       ASintovr,                       /* Interrupt source override */
+       ASnmi,                          /* NMI source */
+       ASlnmi,                         /* local apic nmi */
+       ASladdr,                        /* local apic address override */
+       ASiosapic,                      /* I/O sapic */
+       ASlsapic,                       /* local sapic */
+       ASintsrc,                       /* platform interrupt sources */
+       ASlx2apic,                      /* local x2 apic */
+       ASlx2nmi,                       /* local x2 apic NMI */
 
        /* Apic flags */
-       AFbus = 0,      /* polarity/trigger like in ISA */
-       AFhigh = 1,     /* active high */
-       AFlow = 3,      /* active low */
-       AFpmask = 3,    /* polarity bits */
+       AFbus = 0,                      /* polarity/trigger like in ISA */
+       AFhigh = 1,                     /* active high */
+       AFlow = 3,                      /* active low */
+       AFpmask = 3,            /* polarity bits */
        AFedge = 1 << 2,        /* edge triggered */
        AFlevel = 3 << 2,       /* level triggered */
        AFtmask = 3 << 2,       /* trigger bits */
 
+       /* Table types. */
+       RSDP = 0,
+       SDTH,
+       RSDT,
+       FADT,
+       FACS,
+       DSDT,
+       SSDT,
+       MADT,
+       SBST,
+       XSDT,
+       ECDT,
+       SLIT,
+       SRAT,
+       CPEP,
+       MSCT,
+       RASF,
+       MPST,
+       PMTT,
+       BGRT,
+       FPDT,
+       GTDT,
+       HPET,
+       APIC,
+       DMAR,
+       /* DMAR types */
+       DRHD,
+       RMRR,
+       ATSR,
+       RHSA,
+       ANDD,
+       NACPITBLS,                      /* Number of ACPI tables */
+
        /* SRAT types */
-       SRlapic = 0,    /* Local apic/sapic affinity */
-       SRmem,  /* Memory affinity */
-       SRlx2apic,      /* x2 apic affinity */
+       SRlapic = 0,            /* Local apic/sapic affinity */
+       SRmem,                          /* Memory affinity */
+       SRlx2apic,                      /* x2 apic affinity */
+
+       /* Atable constants */
+       SIGSZ           = 4+1,  /* Size of the signature (including NUL) */
+       OEMIDSZ         = 6+1,  /* Size of the OEM ID (including NUL) */
+       OEMTBLIDSZ      = 8+1,  /* Size of the OEM Table ID (including NUL) */
 
        /* Arg for _PIC */
-       Ppic = 0,       /* PIC interrupt model */
-       Papic,  /* APIC interrupt model */
-       Psapic, /* SAPIC interrupt model */
-
-       CMregion = 0,   /* regio name spc base len accsz */
-       CMgpe,  /* gpe name id */
-
-       Qdir = 0,
-       Qctl,
-       Qtbl,
-       Qio,
-       Qpretty,
-       Qioapic,
-       Qapic,
+       Ppic = 0,                       /* PIC interrupt model */
+       Papic,                          /* APIC interrupt model */
+       Psapic,                         /* SAPIC interrupt model */
+
+       CMregion = 0,           /* regio name spc base len accsz */
+       CMgpe,                          /* gpe name id */
 };
 
 /*
  * ACPI table (sw)
+ *
+ * This Atable struct corresponds to an interpretation of the standard header
+ * for all table types we support. It has a pointer to the converted data, i.e.
+ * the structs created by functions like acpimadt and so on. Note: althouh the
+ * various things in this are a superset of many ACPI table names (DRHD, DRHD
+ * scopes, etc). The raw data follows this header.
+ *
+ * Child entries in the table are kept in an array of pointers. Each entry has
+ * a pointer to it's logically "next" sibling, thus forming a linked list. But
+ * these lists are purely for convenience and all point to nodes within the
+ * same array.
  */
 struct Atable {
-       struct Atable *next;            /* next table in list */
-       int is64;                                       /* uses 64bits */
-       char sig[5];                            /* signature */
-       char oemid[7];                          /* oem id str. */
-       char oemtblid[9];                       /* oem tbl. id str. */
-       uint8_t *tbl;                           /* pointer to table in memory */
-       long dlen;                                      /* size of data in table, after Stdhdr */
+       struct qid qid;             /* QID corresponding to this table. */
+       struct qid rqid;                        /* This table's 'raw' QID. */
+       struct qid pqid;                        /* This table's 'pretty' QID. */
+       struct qid tqid;                        /* This table's 'table' QID. */
+       int type;                                       /* This table's type */
+       void *tbl;                                      /* pointer to the converted table, e.g. madt. */
+       char name[16];                          /* name of this table */
+
+       struct Atable *parent;          /* Parent pointer */
+       struct Atable **children;       /* children of this node (an array). */
+       struct dirtab *cdirs;           /* child directory entries of this node. */
+       size_t nchildren;                       /* count of this node's children */
+       struct Atable *next;            /* Pointer to the next sibling. */
+
+       size_t rawsize;                         /* Total size of raw table */
+       uint8_t *raw;                           /* Raw data. */
 };
 
 struct Gpe {
@@ -102,21 +200,16 @@ struct Gpe {
        int id;                                         /* id as supplied by user */
 };
 
-struct Parse {
-       char *sig;
-       struct Atable *(*f) (uint8_t * unused_uint8_p_t, int);  /* return NULL to keep vmap */
-};
-
 struct Regio {
        void *arg;
-        uint8_t(*get8) (uintptr_t, void *);
-       void (*set8) (uintptr_t, uint8_t unused_int, void *);
-        uint16_t(*get16) (uintptr_t, void *);
-       void (*set16) (uintptr_t, uint16_t unused_int, void *);
-        uint32_t(*get32) (uintptr_t, void *);
-       void (*set32) (uintptr_t, uint32_t, void *);
-        uint64_t(*get64) (uintptr_t, void *);
-       void (*set64) (uintptr_t, uint64_t unused_int, void *);
+       uint8_t (*get8)(uintptr_t, void *);
+       void (*set8)(uintptr_t, uint8_t unused_int, void *);
+       uint16_t (*get16)(uintptr_t, void *);
+       void (*set16)(uintptr_t, uint16_t unused_int, void *);
+       uint32_t (*get32)(uintptr_t, void *);
+       void (*set32)(uintptr_t, uint32_t, void *);
+       uint64_t (*get64)(uintptr_t, void *);
+       void (*set64)(uintptr_t, uint64_t unused_int, void *);
 };
 
 struct Reg {
@@ -129,7 +222,7 @@ struct Reg {
        int accsz;                                      /* access size */
 };
 
-/* Generic address structure. 
+/* Generic address structure.
  */
 struct Gas {
        uint8_t spc;                            /* address space id */
@@ -148,7 +241,6 @@ struct Gas {
  *     - SSDTs tables with AML code to add to the acpi namespace.
  *     - pointers to other tables for apics, etc.
  */
-
 struct Rsdp {
        uint8_t signature[8];           /* "RSD PTR " */
        uint8_t rchecksum;
@@ -158,7 +250,7 @@ struct Rsdp {
        uint8_t length[4];
        uint8_t xaddr[8];                       /* XSDT */
        uint8_t xchecksum;                      /* XSDT */
-       uint8_t _33_[3];                        /* reserved */
+       uint8_t _reserved[3];                   /* reserved */
 };
 
 /* Header for ACPI description tables
@@ -178,6 +270,8 @@ struct Sdthdr {
 /* Firmware control structure
  */
 struct Facs {
+       uint8_t sig[4];
+       uint8_t len[4];
        uint32_t hwsig;
        uint32_t wakingv;
        uint32_t glock;
@@ -193,12 +287,11 @@ struct Msct {
        int ndoms;                                      /* number of domains */
        int nclkdoms;                           /* number of clock domains */
        uint64_t maxpa;                         /* max physical address */
-
-       struct Mdom *dom;                       /* domain information list */
+       size_t nmdom;                           /* number of discovered domains */
+       struct Mdom *dom;                       /* array of domains */
 };
 
 struct Mdom {
-       struct Mdom *next;
        int start;                                      /* start dom id */
        int end;                                        /* end dom id */
        int maxproc;                            /* max processor capacity */
@@ -214,12 +307,10 @@ struct Mdom {
 struct Madt {
        uint64_t lapicpa;                       /* local APIC addr */
        int pcat;                                       /* the machine has PC/AT 8259s */
-       struct Apicst *st;                      /* list of Apic related structures */
 };
 
 struct Apicst {
        int type;
-       struct Apicst *next;
        union {
                struct {
                        int pid;                        /* processor id */
@@ -276,7 +367,6 @@ struct Apicst {
  */
 struct Srat {
        int type;
-       struct Srat *next;
        union {
                struct {
                        int dom;                        /* proximity domain */
@@ -375,9 +465,52 @@ struct Fadt {
 /* XSDT/RSDT. 4/8 byte addresses starting at p.
  */
 struct Xsdt {
-       int len;
-       int asize;
+       size_t len;
+       size_t asize;
        uint8_t *p;
 };
 
-extern uintptr_t acpimblocksize(uintptr_t, int *);
+/* DMAR.
+ */
+/*
+ * Device scope.
+ */
+struct DevScope {
+       int enumeration_id;
+       int start_bus_number;
+       int npath;
+       int *paths;
+};
+/*
+ * The device scope is basic tbdf as uint32_t. There is a special value
+ * that means "everything" and if we see that we set "all" in the Drhd.
+ */
+struct Drhd {
+       int flags;
+       int segment;
+       uintptr_t rba;
+       uintptr_t all;  // This drhd scope is for everything.
+       size_t nscope;
+       struct DevScope *scopes;
+};
+
+struct Dmar {
+       int haw;
+       /*
+        * If your firmware disables x2apic mode, you should not be here.
+        * We ignore that bit.
+        */
+       int intr_remap;
+};
+
+int acpiinit(void);
+struct Atable *mkatable(struct Atable *parent,
+                        int type, char *name, uint8_t *raw,
+                        size_t rawsize, size_t addsize);
+struct Atable *finatable(struct Atable *t, struct slice *slice);
+struct Atable *finatable_nochildren(struct Atable *t);
+int get_early_num_cores(void);
+
+extern struct Atable *apics;
+extern struct Atable *dmar;
+extern struct Atable *srat;