SRAT
ACPI |
---|
Fixed Tables |
Differentiated Tables |
Tools/Libs |
This page is about the ACPI SRAT (System/Static Resource Affinity Table) It describes how the APIC works.
Introduction
The SRAT table is described by the ACPI Specification 5.0a [1] in section 5.2.16 as a table providing information that allows an OSPM (Operating System Power Management [System]) "to associate processors and memory ranges, including ranges of memory provided by hot-added memory devices, with system localities proximity domains and clock domains." Basically, the SRAT provides information on relationships of resources in the system - namely the processor(s) and memory. The SRAT table associates each processor and blocks of memory to a plain ol' integer, called proximity domains in ACPI jargon.
Header Structure
The SRAT table follows this structure:
struct SRAT
{
char signature[4]; // Contains "SRAT"
uint32_t length; // Length of entire SRAT including entries
uint8_t rev; // 3
uint8_t checksum; // Entire table must sum to zero
uint8_t OEMID[6]; // What do you think it is?
uint64_t OEMTableID; // For the SRAT it's the manufacturer model ID
uint32_t OEMRev; // OEM revision for OEM Table ID
uint32_t creatorID; // Vendor ID of the utility used to create the table
uint32_t creatorRev; // Blah blah
uint8_t reserved[12];
} __attribute__((packed));
This header structure (48 bytes) is then followed by a list of Static Resource Allocation Structures. There are 3 types of SRAS:
Type | Name |
---|---|
0x0 | Processor Local APIC/SAPIC Affinity Structure |
0x1 | Memory Affinity Structure |
0x2 | Processor Local x2APIC Affinity Structure |
Processor Local APIC Affinity Structure
This structure (whose name is too long to repeat) gives us the association of a processor's APIC ID (or SAPIC ID/EID) and the proximity domain (in ACPI jargon) in which it belongs to. Here goes nothing:
struct SRAT_proc_lapic_struct
{
uint8_t type; // 0x0 for this type of structure
uint8_t length; // 16
uint8_t lo_DM; // Bits [0:7] of the proximity domain
uint8_t APIC_ID; // Processor's APIC ID
uint32_t flags; // Haha the most useless thing ever
uint8_t SAPIC_EID; // The processor's local SAPIC EID. Don't even bother.
uint8_t hi_DM[3]; // Bits [8:31] of the proximity domain
uint32_t _CDM; // The clock domain which the processor belongs to (more jargon)
} __attribute__((packed));
And here's for (drumroll please) the utterly mind-blowing flags:
Field name | Field bit width | Bit offset | Description |
---|---|---|---|
Enabled | 1 | 0 | If clear, the OS should ignore the contents of the structure. This is to allow system firmware to populate the SRAT with a static number of entries and enable as needed. |
Reserved | 31 | 1 | Must be zero. |
Memory Affinity Structure
The Memory Affinity structure contains:
- A range of memory and the unexciting integer (proximity domain) to which it belongs
- Information about whether the range of memory is hot-pluggable
struct SRAT_mem_struct
{
uint8_t type; // 0x1 for this type of structure
uint8_t length; // 40
uint32_t domain; // The domain to which this memory region belongs to
uint8_t reserved1[2]; // Reserved
uint32_t lo_base; // Low 32 bits of the base address of the memory range
uint32_t hi_base; // High 32 bits of the base address of the memory range
uint32_t lo_length; // Low 32 bits of the length of the range
uint32_t hi_length; // High 32 bits of the length
uint8_t reserved2[4]; // Reserved
uint32_t flags; // Flags
uint8_t reserved3[8]; // Reserved
} __attribute__ ((packed));
Flags:
Field name | Field bit width | Bit offset | Description |
---|---|---|---|
Enabled | 1 | 0 | If clear, the OS should ignore the contents of the structure. This is to allow system firmware to populate the SRAT with a static number of entries and enable as needed. |
Hot-pluggable* | 1 | 1 | If both Enabled and Hot-pluggable flags are set, then the system supports hot-adding and hot-removing of this memory region. |
Non-Volatile | 1 | 2 | If set, this memory region is non-volatile memory |
Reserved | 29 | 3 | Must be zero. |
* The asterisk says nothing
Processor Local x2APIC Affinity Structure
The x2APIC structure is basically the APIC structure but for x2APIC.
struct SRAT_proc_lapic2_struct
{
uint8_t type; // 0x2 for this type of structure
uint8_t length; // 24
uint8_t reserved1[2]; // Must be zero
uint32_t domain; // The proximity domain which the logical processor belongs to
uint32_t x2APIC_ID; // Processor's x2APIC ID
uint32_t flags; // Haha the most useless thing ever
uint32_t _CDM; // The clock domain which the processor belongs to (more jargon)
uint8_t reserved2[4]; // Reserved.
} __attribute__((packed));
Clock Domain
Go read the docs (section 6.2.1). The clock domain represents the clock connected to a processor of that domain. When a processor attempts to access a clock source that is not in the same clock domain as itself, inaccuracies may occur when compared to other processors. This is the same concept as a proximity domain, where processors accessing memory or I/O resources outside its domain will need to ask a processor inside the domain to perform the memory or I/O action.