akaros/kern/include/acpi.h
<<
>>
Prefs
   1/*
   2 * This file is part of the UCB release of Plan 9. It is subject to the license
   3 * terms in the LICENSE file found in the top-level directory of this
   4 * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
   5 * part of the UCB release of Plan 9, including this file, may be copied,
   6 * modified, propagated, or distributed except according to the terms contained
   7 * in the LICENSE file.
   8 */
   9
  10/* -----------------------------------------------------------------------------
  11 * ACPI is a table of tables. The tables define a hierarchy.
  12 *
  13 * From the hardware's perspective:
  14 * Each table that we care about has a header, and the header has a
  15 * length that includes the the length of all its subtables. So, even
  16 * if you can't completely parse a table, you can find the next table.
  17 *
  18 * The process of parsing is to find the RSDP, and then for each subtable
  19 * see what type it is and parse it. The process is recursive except for
  20 * a few issues: The RSDP signature and header differs from the header of
  21 * its subtables; their headers differ from the signatures of the tables
  22 * they contain. As you walk down the tree, you need different parsers.
  23 *
  24 * The parser is recursive descent. Each parsing function takes a pointer
  25 * to the parent of the node it is parsing and will attach itself to the parent
  26 * via that pointer. Parsing functions are responsible for building the data
  27 * structures that represent their node and recursive invocations of the parser
  28 * for subtables.
  29 *
  30 * So, in this case, it's something like this:
  31 *
  32 * RSDP is the root. It has a standard header and size. You map that
  33 * memory.  You find the first header, get its type and size, and
  34 * parse as much of it as you can. Parsing will involve either a
  35 * function or case statement for each element type. DMARs are complex
  36 * and need functions; APICs are simple and we can get by with case
  37 * statements.
  38 *
  39 * Each node in the tree is represented as a 'struct Atable'. This has a
  40 * pointer to the actual node data, a type tag, a name, pointers to this
  41 * node's children (if any) and a parent pointer. It also has a QID so that
  42 * the entire structure can be exposed as a filesystem. The Atable doesn't
  43 * contain any table data per se; it's metadata. The table pointer contains
  44 * the table data as well as a pointer back to it's corresponding Atable.
  45 *
  46 * In the end we present a directory tree for #apic that looks, in this example:
  47 * #acpi/DMAR/DRHD/0/{pretty,raw}
  48 *
  49 * 'cat pretty' will return JSON-encoded data described the element.
  50 * 'cat raw' gets you the raw bytes.
  51 */
  52
  53#pragma once
  54
  55#include <ns.h>
  56#include <slice.h>
  57#include <arch/intel-iommu.h>
  58
  59enum {
  60
  61        Sdthdrsz = 36,          /* size of SDT header */
  62
  63        /* ACPI regions. Gas ids */
  64        Rsysmem = 0,
  65        Rsysio,
  66        Rpcicfg,
  67        Rembed,
  68        Rsmbus,
  69        Rcmos,
  70        Rpcibar,
  71        Ripmi,
  72        Rfixedhw = 0x7f,
  73
  74        /* ACPI PM1 control */
  75        Pm1SciEn = 0x1,         /* Generate SCI and not SMI */
  76
  77        /* ACPI tbdf as encoded in acpi region base addresses */
  78        Rpciregshift = 0,
  79        Rpciregmask = 0xFFFF,
  80        Rpcifunshift = 16,
  81        Rpcifunmask = 0xFFFF,
  82        Rpcidevshift = 32,
  83        Rpcidevmask = 0xFFFF,
  84        Rpcibusshift = 48,
  85        Rpcibusmask = 0xFFFF,
  86
  87        /* Apic structure types */
  88        ASlapic = 0,            /* processor local apic */
  89        ASioapic,               /* I/O apic */
  90        ASintovr,               /* Interrupt source override */
  91        ASnmi,                  /* NMI source */
  92        ASlnmi,                 /* local apic nmi */
  93        ASladdr,                /* local apic address override */
  94        ASiosapic,              /* I/O sapic */
  95        ASlsapic,               /* local sapic */
  96        ASintsrc,               /* platform interrupt sources */
  97        ASlx2apic,              /* local x2 apic */
  98        ASlx2nmi,               /* local x2 apic NMI */
  99
 100        /* Apic flags */
 101        AFbus = 0,              /* polarity/trigger like in ISA */
 102        AFhigh = 1,             /* active high */
 103        AFlow = 3,              /* active low */
 104        AFpmask = 3,            /* polarity bits */
 105        AFedge = 1 << 2,        /* edge triggered */
 106        AFlevel = 3 << 2,       /* level triggered */
 107        AFtmask = 3 << 2,       /* trigger bits */
 108
 109        /* Table types. */
 110        RSDP = 0,
 111        SDTH,
 112        RSDT,
 113        FADT,
 114        FACS,
 115        DSDT,
 116        SSDT,
 117        MADT,
 118        SBST,
 119        XSDT,
 120        ECDT,
 121        SLIT,
 122        SRAT,
 123        CPEP,
 124        MSCT,
 125        RASF,
 126        MPST,
 127        PMTT,
 128        BGRT,
 129        FPDT,
 130        GTDT,
 131        HPET,
 132        APIC,
 133        DMAR,
 134        MCFG,
 135        /* DMAR types */
 136        DRHD,
 137        RMRR,
 138        ATSR,
 139        RHSA,
 140        ANDD,
 141        NACPITBLS,              /* Number of ACPI tables */
 142
 143        /* SRAT types */
 144        SRlapic = 0,            /* Local apic/sapic affinity */
 145        SRmem,                  /* Memory affinity */
 146        SRlx2apic,              /* x2 apic affinity */
 147
 148        /* Atable constants */
 149        SIGSZ           = 4+1,  /* Size of the signature (including NUL) */
 150        OEMIDSZ         = 6+1,  /* Size of the OEM ID (including NUL) */
 151        OEMTBLIDSZ      = 8+1,  /* Size of the OEM Table ID (including NUL) */
 152
 153        /* Arg for _PIC */
 154        Ppic = 0,               /* PIC interrupt model */
 155        Papic,                  /* APIC interrupt model */
 156        Psapic,                 /* SAPIC interrupt model */
 157
 158        CMregion = 0,           /* regio name spc base len accsz */
 159        CMgpe,                  /* gpe name id */
 160};
 161
 162/*
 163 * ACPI table (sw)
 164 *
 165 * This Atable struct corresponds to an interpretation of the standard header
 166 * for all table types we support. It has a pointer to the converted data, i.e.
 167 * the structs created by functions like acpimadt and so on. Note: althouh the
 168 * various things in this are a superset of many ACPI table names (DRHD, DRHD
 169 * scopes, etc). The raw data follows this header.
 170 *
 171 * Child entries in the table are kept in an array of pointers. Each entry has
 172 * a pointer to it's logically "next" sibling, thus forming a linked list. But
 173 * these lists are purely for convenience and all point to nodes within the
 174 * same array.
 175 */
 176struct Atable {
 177        struct qid qid;         /* QID corresponding to this table. */
 178        struct qid rqid;        /* This table's 'raw' QID. */
 179        struct qid pqid;        /* This table's 'pretty' QID. */
 180        struct qid tqid;        /* This table's 'table' QID. */
 181        int type;               /* This table's type */
 182        void *tbl;              /* pointer to the converted table, e.g. madt. */
 183        char name[16];          /* name of this table */
 184
 185        struct Atable *parent;  /* Parent pointer */
 186        struct Atable **children; /* children of this node (an array). */
 187        struct dirtab *cdirs;   /* child directory entries of this node. */
 188        size_t nchildren;       /* count of this node's children */
 189        struct Atable *next;    /* Pointer to the next sibling. */
 190
 191        size_t rawsize;         /* Total size of raw table */
 192        uint8_t *raw;           /* Raw data. */
 193};
 194
 195struct Gpe {
 196        uintptr_t stsio;        /* port used for status */
 197        int stsbit;             /* bit number */
 198        uintptr_t enio;         /* port used for enable */
 199        int enbit;              /* bit number */
 200        int nb;                 /* event number */
 201        char *obj;              /* handler object  */
 202        int id;                 /* id as supplied by user */
 203};
 204
 205struct Regio {
 206        void *arg;
 207        uint8_t (*get8)(uintptr_t, void *);
 208        void (*set8)(uintptr_t, uint8_t unused_int, void *);
 209        uint16_t (*get16)(uintptr_t, void *);
 210        void (*set16)(uintptr_t, uint16_t unused_int, void *);
 211        uint32_t (*get32)(uintptr_t, void *);
 212        void (*set32)(uintptr_t, uint32_t, void *);
 213        uint64_t (*get64)(uintptr_t, void *);
 214        void (*set64)(uintptr_t, uint64_t unused_int, void *);
 215};
 216
 217struct Reg {
 218        char *name;
 219        int spc;                /* io space */
 220        uint64_t base;          /* address, physical */
 221        uint8_t *p;             /* address, kmapped */
 222        uint64_t len;
 223        int tbdf;
 224        int accsz;              /* access size */
 225};
 226
 227/* Generic address structure.
 228 */
 229struct Gas {
 230        uint8_t spc;            /* address space id */
 231        uint8_t len;            /* register size in bits */
 232        uint8_t off;            /* bit offset */
 233        uint8_t accsz;          /* 1: byte; 2: word; 3: dword; 4: qword */
 234        uint64_t addr;          /* address (or acpi encoded tbdf + reg) */
 235};
 236
 237/* Root system description table pointer.
 238 * Used to locate the root system description table RSDT
 239 * (or the extended system description table from version 2) XSDT.
 240 * The XDST contains (after the DST header) a list of pointers to tables:
 241 *      - FADT  fixed acpi description table.
 242 *              It points to the DSDT, AML code making the acpi namespace.
 243 *      - SSDTs tables with AML code to add to the acpi namespace.
 244 *      - pointers to other tables for apics, etc.
 245 */
 246struct Rsdp {
 247        uint8_t signature[8];   /* "RSD PTR " */
 248        uint8_t rchecksum;
 249        uint8_t oemid[6];
 250        uint8_t revision;
 251        uint8_t raddr[4];       /* RSDT */
 252        uint8_t length[4];
 253        uint8_t xaddr[8];       /* XSDT */
 254        uint8_t xchecksum;      /* XSDT */
 255        uint8_t _reserved[3];   /* reserved */
 256};
 257
 258/* Header for ACPI description tables
 259 */
 260struct Sdthdr {
 261        uint8_t sig[4];         /* "FACP" or whatever */
 262        uint8_t length[4];
 263        uint8_t rev;
 264        uint8_t csum;
 265        uint8_t oemid[6];
 266        uint8_t oemtblid[8];
 267        uint8_t oemrev[4];
 268        uint8_t creatorid[4];
 269        uint8_t creatorrev[4];
 270};
 271
 272/* Firmware control structure
 273 */
 274struct Facs {
 275        uint8_t sig[4];
 276        uint8_t len[4];
 277        uint32_t hwsig;
 278        uint32_t wakingv;
 279        uint32_t glock;
 280        uint32_t flags;
 281        uint64_t xwakingv;
 282        uint8_t vers;
 283        uint32_t ospmflags;
 284};
 285
 286/* Maximum System Characteristics table
 287 */
 288struct Msct {
 289        int ndoms;              /* number of domains */
 290        int nclkdoms;           /* number of clock domains */
 291        uint64_t maxpa;         /* max physical address */
 292        size_t nmdom;           /* number of discovered domains */
 293        struct Mdom *dom;       /* array of domains */
 294};
 295
 296struct Mdom {
 297        int start;              /* start dom id */
 298        int end;                /* end dom id */
 299        int maxproc;            /* max processor capacity */
 300        uint64_t maxmem;        /* max memory capacity */
 301};
 302
 303/* Multiple APIC description table
 304 * Interrupts are virtualized by ACPI and each APIC has
 305 * a `virtual interrupt base' where its interrupts start.
 306 * Addresses are processor-relative physical addresses.
 307 * Only enabled devices are linked, others are filtered out.
 308 */
 309struct Madt {
 310        uint64_t lapicpa;       /* local APIC addr */
 311        int pcat;               /* the machine has PC/AT 8259s */
 312};
 313
 314struct Apicst {
 315        int type;
 316        union {
 317                struct {
 318                        int pid;                /* processor id */
 319                        int id;                 /* apic no */
 320                } lapic;
 321                struct {
 322                        int id;                 /* io apic id */
 323                        uint32_t ibase;         /* interrupt base addr. */
 324                        uint64_t addr;          /* base address */
 325                } ioapic, iosapic;
 326                struct {
 327                        int irq;                /* bus intr. source (ISA only) */
 328                        int intr;               /* system interrupt */
 329                        int flags;              /* apic flags */
 330                } intovr;
 331                struct {
 332                        int intr;               /* system interrupt */
 333                        int flags;              /* apic flags */
 334                } nmi;
 335                struct {
 336                        int pid;                /* processor id */
 337                        int flags;              /* lapic flags */
 338                        int lint;               /* lapic LINTn for nmi */
 339                } lnmi;
 340                struct {
 341                        int pid;                /* processor id */
 342                        int id;                 /* apic id */
 343                        int eid;                /* apic eid */
 344                        int puid;               /* processor uid */
 345                        char *puids;            /* same thing */
 346                } lsapic;
 347                struct {
 348                        int pid;                /* processor id */
 349                        int peid;               /* processor eid */
 350                        int iosv;               /* io sapic vector */
 351                        int intr;               /* global sys intr. */
 352                        int type;               /* intr type */
 353                        int flags;              /* apic flags */
 354                        int any;                /* err sts at any proc */
 355                } intsrc;
 356                struct {
 357                        int id;                 /* x2 apic id */
 358                        int puid;               /* processor uid */
 359                } lx2apic;
 360                struct {
 361                        int puid;
 362                        int flags;
 363                        int intr;
 364                } lx2nmi;
 365        };
 366};
 367
 368/* System resource affinity table
 369 */
 370struct Srat {
 371        int type;
 372        union {
 373                struct {
 374                        int dom;                /* proximity domain */
 375                        int apic;               /* apic id */
 376                        int sapic;              /* sapic id */
 377                        int clkdom;             /* clock domain */
 378                } lapic;
 379                struct {
 380                        int dom;                /* proximity domain */
 381                        uint64_t addr;          /* base address */
 382                        uint64_t len;
 383                        int hplug;              /* hot pluggable */
 384                        int nvram;              /* non volatile */
 385                } mem;
 386                struct {
 387                        int dom;                /* proximity domain */
 388                        int apic;               /* x2 apic id */
 389                        int clkdom;             /* clock domain */
 390                } lx2apic;
 391        };
 392};
 393
 394/* System locality information table
 395 */
 396struct Slit {
 397        uint64_t rowlen;
 398        struct SlEntry **e;
 399};
 400
 401struct SlEntry {
 402        int dom;                        /* proximity domain */
 403        unsigned int dist;              /* distance to proximity domain */
 404};
 405
 406/* Fixed ACPI description table.
 407 * Describes implementation and hardware registers.
 408 * PM* blocks are low level functions.
 409 * GPE* blocks refer to general purpose events.
 410 * P_* blocks are for processor features.
 411 * Has address for the DSDT.
 412 */
 413struct Fadt {
 414        uint32_t facs;
 415        uint32_t dsdt;
 416        /* 1 reserved */
 417        uint8_t pmprofile;
 418        uint16_t sciint;
 419        uint32_t smicmd;
 420        uint8_t acpienable;
 421        uint8_t acpidisable;
 422        uint8_t s4biosreq;
 423        uint8_t pstatecnt;
 424        uint32_t pm1aevtblk;
 425        uint32_t pm1bevtblk;
 426        uint32_t pm1acntblk;
 427        uint32_t pm1bcntblk;
 428        uint32_t pm2cntblk;
 429        uint32_t pmtmrblk;
 430        uint32_t gpe0blk;
 431        uint32_t gpe1blk;
 432        uint8_t pm1evtlen;
 433        uint8_t pm1cntlen;
 434        uint8_t pm2cntlen;
 435        uint8_t pmtmrlen;
 436        uint8_t gpe0blklen;
 437        uint8_t gpe1blklen;
 438        uint8_t gp1base;
 439        uint8_t cstcnt;
 440        uint16_t plvl2lat;
 441        uint16_t plvl3lat;
 442        uint16_t flushsz;
 443        uint16_t flushstride;
 444        uint8_t dutyoff;
 445        uint8_t dutywidth;
 446        uint8_t dayalrm;
 447        uint8_t monalrm;
 448        uint8_t century;
 449        uint16_t iapcbootarch;
 450        /* 1 reserved */
 451        uint32_t flags;
 452        struct Gas resetreg;
 453        uint8_t resetval;
 454        /* 3 reserved */
 455        uint64_t xfacs;
 456        uint64_t xdsdt;
 457        struct Gas xpm1aevtblk;
 458        struct Gas xpm1bevtblk;
 459        struct Gas xpm1acntblk;
 460        struct Gas xpm1bcntblk;
 461        struct Gas xpm2cntblk;
 462        struct Gas xpmtmrblk;
 463        struct Gas xgpe0blk;
 464        struct Gas xgpe1blk;
 465};
 466
 467/* XSDT/RSDT. 4/8 byte addresses starting at p.
 468 */
 469struct Xsdt {
 470        size_t len;
 471        size_t asize;
 472        uint8_t *p;
 473};
 474
 475/* DMAR.
 476 */
 477/*
 478 * Device scope.
 479 */
 480struct DevScope {
 481        int enumeration_id;
 482        int start_bus_number;
 483        int npath;
 484        int *paths;
 485};
 486/*
 487 * The device scope is basic tbdf as uint32_t. There is a special value
 488 * that means "everything" and if we see that we set "all" in the Drhd.
 489 */
 490struct Drhd {
 491        int flags;
 492        int segment;
 493        uintptr_t rba;
 494        uintptr_t all;  // This drhd scope is for everything.
 495        size_t nscope;
 496        struct DevScope *scopes;
 497        struct iommu iommu; /* not part of the ACPI table */
 498};
 499
 500struct Dmar {
 501        int haw;
 502        /*
 503         * If your firmware disables x2apic mode, you should not be here.
 504         * We ignore that bit.
 505         */
 506        int intr_remap;
 507};
 508
 509struct acpi_mcfg {
 510        uint8_t sig[4];
 511        uint8_t length[4];
 512        uint8_t rev;
 513        uint8_t csum;
 514        uint8_t oemid[6];
 515        uint8_t oemtblid[8];
 516        uint8_t oemrev[4];
 517        uint8_t creatorid[4];
 518        uint8_t creatorrev[4];
 519        uint8_t _pad[8];
 520        uint8_t entries[0];
 521};
 522
 523struct acpi_mcfg_entry {
 524        physaddr_t addr;
 525        uint16_t segment;
 526        uint8_t start_bus;
 527        uint8_t end_bus;
 528};
 529
 530struct acpi_mcfg_data {
 531        size_t nr_entries;
 532        struct acpi_mcfg_entry entries[];
 533};
 534
 535int acpiinit(void);
 536struct Atable *mkatable(struct Atable *parent,
 537                        int type, char *name, uint8_t *raw,
 538                        size_t rawsize, size_t addsize);
 539struct Atable *finatable(struct Atable *t, struct slice *slice);
 540struct Atable *finatable_nochildren(struct Atable *t);
 541
 542int get_early_num_cores(void);
 543physaddr_t acpi_pci_get_mmio_cfg_addr(int segment, int bus, int dev, int func);
 544
 545extern struct Atable *apics;
 546extern struct Atable *dmar;
 547extern struct Atable *srat;
 548