#include <sys/param.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <vm/vm_page.h>
#include "acpi.h"
#include "acpi_sdt_var.h"
typedef union srat_entry {
ACPI_SUBTABLE_HEADER head;
ACPI_SRAT_CPU_AFFINITY cpu;
ACPI_SRAT_MEM_AFFINITY mem;
ACPI_SRAT_X2APIC_CPU_AFFINITY x2apic;
ACPI_SRAT_GICC_AFFINITY gicc;
} srat_entry_t;
static void
srat_probe(void)
{
vm_paddr_t srat_paddr;
ACPI_TABLE_SRAT *srat;
srat_entry_t *mem;
srat_entry_t *cpu;
int error = 0;
int enabled = 1;
int disabled = 0;
kgetenv_int("kern.numa_disable", &disabled);
kgetenv_int("hw.acpi.srat.enabled", &enabled);
if (disabled || enabled == 0)
return;
srat_paddr = sdt_search(ACPI_SIG_SRAT);
if (srat_paddr == 0) {
kprintf("srat_probe: can't locate SRAT\n");
return;
}
srat = sdt_sdth_map(srat_paddr);
KKASSERT(srat != NULL);
if (srat->Header.Length < sizeof(*srat)) {
kprintf("acpi: invalid SRAT length %u\n",
srat->Header.Length);
error = EINVAL;
goto done;
}
cpu = NULL;
for (mem = (srat_entry_t *)(srat + 1);
(char *)mem < (char *)srat + srat->Header.Length;
mem = (srat_entry_t *)((char *)mem + mem->head.Length)) {
if (mem->head.Type != ACPI_SRAT_TYPE_MEMORY_AFFINITY)
continue;
if ((mem->mem.Flags & ACPI_SRAT_MEM_ENABLED) == 0)
continue;
kprintf("MemAffinity %016jx,%ldMB Prox=%u ",
mem->mem.BaseAddress,
mem->mem.Length / (1024 * 1024),
mem->mem.ProximityDomain);
if (cpu == NULL ||
mem->mem.ProximityDomain != cpu->cpu.ProximityDomainLo) {
for (cpu = (srat_entry_t *)(srat + 1);
(char *)cpu < (char *)srat + srat->Header.Length;
cpu = (srat_entry_t *)((char *)cpu +
cpu->head.Length)) {
if (cpu->head.Type !=
ACPI_SRAT_TYPE_CPU_AFFINITY)
continue;
if ((cpu->cpu.Flags &
ACPI_SRAT_CPU_USE_AFFINITY) == 0)
continue;
if (mem->mem.ProximityDomain ==
cpu->cpu.ProximityDomainLo) {
break;
}
}
if ((char *)cpu >= (char *)srat + srat->Header.Length)
cpu = NULL;
}
if (cpu) {
kprintf("CpuApicId %02x Socket %d\n",
cpu->cpu.ApicId,
get_chip_ID_from_APICID(cpu->cpu.ApicId));
vm_numa_organize(mem->mem.BaseAddress,
mem->mem.Length,
get_chip_ID_from_APICID(cpu->cpu.ApicId));
} else {
kprintf("(not found)\n");
}
}
vm_numa_organize_finalize();
done:
sdt_sdth_unmap(&srat->Header);
}
SYSINIT(srat_probe, SI_BOOT2_NUMA, SI_ORDER_FIRST, srat_probe, 0);