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