Parse the System Resource Affinity Table ('SRAT') used to describe affinity

relationships between CPUs and memory.

Reviewed by:	jkim
Approved by:	re (kib)
MFC after:	1 week
This commit is contained in:
John Baldwin 2009-07-29 19:07:24 +00:00
parent bdfc8cc4cd
commit a0333ad155
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=195947
2 changed files with 148 additions and 8 deletions

View File

@ -36,6 +36,7 @@
#include <fcntl.h>
#include <paths.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@ -59,6 +60,11 @@ static void acpi_print_intr(u_int32_t intr, u_int16_t mps_flags);
static void acpi_print_apic(struct MADT_APIC *mp);
static void acpi_handle_apic(struct ACPIsdt *sdp);
static void acpi_handle_hpet(struct ACPIsdt *sdp);
static void acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain,
uint32_t flags);
static void acpi_print_srat_memory(struct SRAT_memory *mp);
static void acpi_print_srat(struct SRATentry *srat);
static void acpi_handle_srat(struct ACPIsdt *sdp);
static void acpi_print_sdt(struct ACPIsdt *sdp);
static void acpi_print_fadt(struct ACPIsdt *sdp);
static void acpi_print_facs(struct FACSbody *facs);
@ -258,7 +264,10 @@ static void
acpi_print_apic(struct MADT_APIC *mp)
{
printf("\tType=%s\n", apic_types[mp->type]);
if (mp->type < sizeof(apic_types) / sizeof(apic_types[0]))
printf("\tType=%s\n", apic_types[mp->type]);
else
printf("\tType=%d (unknown)\n", mp->type);
switch (mp->type) {
case ACPI_MADT_APIC_TYPE_LOCAL_APIC:
acpi_print_local_apic(mp->body.local_apic.cpu_id,
@ -307,9 +316,6 @@ acpi_print_apic(struct MADT_APIC *mp)
acpi_print_intr(mp->body.int_src.intr,
mp->body.int_src.mps_flags);
break;
default:
printf("\tUnknown type %d\n", (u_int)mp->type);
break;
}
}
@ -393,10 +399,92 @@ acpi_handle_mcfg(struct ACPIsdt *sdp)
sizeof(*mcfg->s);
for (i = 0; i < e; i++, mcfg++) {
printf("\n");
printf("\tBase Address= 0x%016jx\n", mcfg->s[i].baseaddr);
printf("\tSegment Group= 0x%04x\n", mcfg->s[i].seg_grp);
printf("\tStart Bus= %d\n", mcfg->s[i].start);
printf("\tEnd Bus= %d\n", mcfg->s[i].end);
printf("\tBase Address=0x%016jx\n", mcfg->s[i].baseaddr);
printf("\tSegment Group=0x%04x\n", mcfg->s[i].seg_grp);
printf("\tStart Bus=%d\n", mcfg->s[i].start);
printf("\tEnd Bus=%d\n", mcfg->s[i].end);
}
printf(END_COMMENT);
}
static void
acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain,
uint32_t flags)
{
printf("\tFlags={");
if (flags & ACPI_SRAT_CPU_ENABLED)
printf("ENABLED");
else
printf("DISABLED");
printf("}\n");
printf("\tAPIC ID=%d\n", apic_id);
printf("\tProximity Domain=%d\n", proximity_domain);
}
static void
acpi_print_srat_memory(struct SRAT_memory *mp)
{
printf("\tFlags={");
if (mp->flags & ACPI_SRAT_MEM_ENABLED)
printf("ENABLED");
else
printf("DISABLED");
if (mp->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)
printf(",HOT_PLUGGABLE");
if (mp->flags & ACPI_SRAT_MEM_NON_VOLATILE)
printf(",NON_VOLATILE");
printf("}\n");
printf("\tBase Address=0x%016jx\n", (uintmax_t)mp->base_address);
printf("\tLength=0x%016jx\n", (uintmax_t)mp->length);
printf("\tProximity Domain=%d\n", mp->proximity_domain);
}
const char *srat_types[] = { "CPU", "Memory", "X2APIC" };
static void
acpi_print_srat(struct SRATentry *srat)
{
if (srat->type < sizeof(srat_types) / sizeof(srat_types[0]))
printf("\tType=%s\n", srat_types[srat->type]);
else
printf("\tType=%d (unknown)\n", srat->type);
switch (srat->type) {
case ACPI_SRAT_TYPE_CPU_AFFINITY:
acpi_print_srat_cpu(srat->body.cpu.apic_id,
srat->body.cpu.proximity_domain_hi[2] << 24 |
srat->body.cpu.proximity_domain_hi[1] << 16 |
srat->body.cpu.proximity_domain_hi[0] << 0 |
srat->body.cpu.proximity_domain_lo, srat->body.cpu.flags);
break;
case ACPI_SRAT_TYPE_MEMORY_AFFINITY:
acpi_print_srat_memory(&srat->body.mem);
break;
case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY:
acpi_print_srat_cpu(srat->body.x2apic.apic_id,
srat->body.x2apic.proximity_domain,
srat->body.x2apic.flags);
break;
}
}
static void
acpi_handle_srat(struct ACPIsdt *sdp)
{
struct SRATbody *sratp;
struct SRATentry *entry;
printf(BEGIN_COMMENT);
acpi_print_sdt(sdp);
sratp = (struct SRATbody *)sdp->body;
printf("\tTable Revision=%d\n", sratp->table_revision);
entry = sratp->body;
while (((uintptr_t)entry) - ((uintptr_t)sdp) < sdp->len) {
printf("\n");
acpi_print_srat(entry);
entry = (struct SRATentry *)((char *)entry + entry->len);
}
printf(END_COMMENT);
}
@ -710,6 +798,8 @@ acpi_handle_rsdt(struct ACPIsdt *rsdp)
acpi_handle_ecdt(sdp);
else if (!memcmp(sdp->signature, "MCFG", 4))
acpi_handle_mcfg(sdp);
else if (!memcmp(sdp->signature, "SRAT", 4))
acpi_handle_srat(sdp);
else {
printf(BEGIN_COMMENT);
acpi_print_sdt(sdp);

View File

@ -304,6 +304,56 @@ struct MCFGbody {
} s[1] __packed;
} __packed;
/* System Resource Affinity Table */
struct SRAT_cpu {
uint8_t proximity_domain_lo;
uint8_t apic_id;
uint32_t flags;
#define ACPI_SRAT_CPU_ENABLED 0x00000001
uint8_t sapic_eid;
uint8_t proximity_domain_hi[3];
uint32_t reserved;
} __packed;
struct SRAT_memory {
uint32_t proximity_domain;
uint16_t reserved;
uint64_t base_address;
uint64_t length;
uint32_t reserved1;
uint32_t flags;
#define ACPI_SRAT_MEM_ENABLED 0x00000001
#define ACPI_SRAT_MEM_HOT_PLUGGABLE 0x00000002
#define ACPI_SRAT_MEM_NON_VOLATILE 0x00000002
uint64_t reserved2;
} __packed;
struct SRAT_x2apic {
uint16_t reserved;
uint32_t proximity_domain;
uint32_t apic_id;
uint32_t flags;
} __packed;
struct SRATentry {
uint8_t type;
#define ACPI_SRAT_TYPE_CPU_AFFINITY 0
#define ACPI_SRAT_TYPE_MEMORY_AFFINITY 1
#define ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY 2
uint8_t len;
union {
struct SRAT_cpu cpu;
struct SRAT_memory mem;
struct SRAT_x2apic x2apic;
} body;
} __packed;
struct SRATbody {
uint32_t table_revision;
uint64_t reserved;
struct SRATentry body[0];
} __packed;
/*
* Addresses to scan on ia32 for the RSD PTR. According to section 5.2.2
* of the ACPI spec, we only consider two regions for the base address: