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 integer, named 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];
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;
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 describes the association of a processor's APIC ID (or SAPIC ID/EID) and the proximity domain (in ACPI jargon) in which it belongs to.
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; // Flags (see below)
uint8_t SAPIC_EID; // The processor's local SAPIC EID.
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));
Currently, only one flag is defined for the flags field:
| 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
Keep in mind, that there can be several Memory Affinity structures corresponding to single proximity domain due to various memory holes (e.g. 384 KiB Reserved ("Upper Memory") hole may be present even on (QEMU) UEFI machines). For example, 1GiB domain may have (0x0, 0x80000) and (0x100000 - 0x40000000) Memory Affinities.
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 (see below)
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 API C 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;
uint32_t _CDM; // The clock domain which the processor belongs to (more jargon)
uint8_t reserved2[4]; // Reserved.
} __attribute__((packed));
Clock Domain
Refer to the documentation (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.