acpi.h 14 KB

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