diff options
author | Jonathan Zhang <jonzhang@fb.com> | 2020-05-28 17:53:48 -0700 |
---|---|---|
committer | Patrick Georgi <pgeorgi@google.com> | 2020-06-14 16:44:58 +0000 |
commit | 3172f987fa632189ad3bb44d61614b58be0b142a (patch) | |
tree | 93a586c8335b1cbafec9f9e5d823b7325476c8f1 /src/soc/intel/xeon_sp | |
parent | 2c4866228e83e3dc4ae547356fe4be4ce4fda77b (diff) |
soc/intel/xeon_sp/cpx: add NUMA ACPI tables
Add NUMA ACPI tables: SRAT, SLIT.
TESTED=Boot CPX-SP based server, check /sys/firmware/acpi/tables
for SRAT/SLIT tables.
Signed-off-by: Jonathan Zhang <jonzhang@fb.com>
Signed-off-by: Reddy Chagam <anjaneya.chagam@intel.com>
Change-Id: I3374b802afd2d001e841afd85e7ae07bc27c01ff
Reviewed-on: https://review.coreboot.org/c/coreboot/+/41902
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Philipp Deppenwiese <zaolin.daisuki@gmail.com>
Diffstat (limited to 'src/soc/intel/xeon_sp')
-rw-r--r-- | src/soc/intel/xeon_sp/cpx/acpi.c | 156 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/cpx/chip.c | 2 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/cpx/include/soc/acpi.h | 17 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/cpx/include/soc/pci_devs.h | 36 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/cpx/include/soc/soc_util.h | 4 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/cpx/soc_util.c | 24 |
6 files changed, 239 insertions, 0 deletions
diff --git a/src/soc/intel/xeon_sp/cpx/acpi.c b/src/soc/intel/xeon_sp/cpx/acpi.c index b090d12668..b648262347 100644 --- a/src/soc/intel/xeon_sp/cpx/acpi.c +++ b/src/soc/intel/xeon_sp/cpx/acpi.c @@ -3,15 +3,19 @@ #include <acpi/acpigen.h> #include <arch/ioapic.h> #include <arch/smp/mpspec.h> +#include <assert.h> #include <cbmem.h> #include <cf9_reset.h> #include <console/console.h> #include <cpu/x86/smm.h> #include <device/pci.h> #include <intelblocks/acpi.h> +#include <soc/acpi.h> #include <soc/iomap.h> #include <soc/nvs.h> +#include <soc/pci_devs.h> #include <soc/pm.h> +#include <soc/soc_util.h> #include "chip.h" @@ -169,3 +173,155 @@ void acpi_fill_fadt(acpi_fadt_t *fadt) fadt->x_gpe1_blk.addrl = 0; fadt->x_gpe1_blk.addrh = 0; } + +unsigned long acpi_create_srat_lapics(unsigned long current) +{ + struct device *cpu; + unsigned int cpu_index = 0; + + for (cpu = all_devices; cpu; cpu = cpu->next) { + if ((cpu->path.type != DEVICE_PATH_APIC) || + (cpu->bus->dev->path.type != DEVICE_PATH_CPU_CLUSTER)) { + continue; + } + if (!cpu->enabled) + continue; + printk(BIOS_DEBUG, "SRAT: lapic cpu_index=%02x, node_id=%02x, apic_id=%02x\n", + cpu_index, cpu->path.apic.node_id, cpu->path.apic.apic_id); + current += acpi_create_srat_lapic((acpi_srat_lapic_t *)current, + cpu->path.apic.node_id, cpu->path.apic.apic_id); + cpu_index++; + } + return current; +} + +static unsigned int get_srat_memory_entries(acpi_srat_mem_t *srat_mem) +{ + const struct SystemMemoryMapHob *memory_map; + unsigned int mmap_index; + + memory_map = get_system_memory_map(); + assert(memory_map != NULL); + printk(BIOS_DEBUG, "memory_map: %p\n", memory_map); + + mmap_index = 0; + for (int e = 0; e < memory_map->numberEntries; ++e) { + const struct SystemMemoryMapElement *mem_element = &memory_map->Element[e]; + uint64_t addr = + (uint64_t) ((uint64_t)mem_element->BaseAddress << + MEM_ADDR_64MB_SHIFT_BITS); + uint64_t size = + (uint64_t) ((uint64_t)mem_element->ElementSize << + MEM_ADDR_64MB_SHIFT_BITS); + + printk(BIOS_DEBUG, "memory_map %d addr: 0x%llx, BaseAddress: 0x%x, size: 0x%llx, " + "ElementSize: 0x%x, reserved: %d\n", + e, addr, mem_element->BaseAddress, size, + mem_element->ElementSize, (mem_element->Type & MEM_TYPE_RESERVED)); + + assert(mmap_index < MAX_ACPI_MEMORY_AFFINITY_COUNT); + + /* skip reserved memory region */ + if (mem_element->Type & MEM_TYPE_RESERVED) + continue; + + /* skip if this address is already added */ + bool skip = false; + for (int idx = 0; idx < mmap_index; ++idx) { + uint64_t base_addr = ((uint64_t)srat_mem[idx].base_address_high << 32) + + srat_mem[idx].base_address_low; + if (addr == base_addr) { + skip = true; + break; + } + } + if (skip) + continue; + + srat_mem[mmap_index].type = 1; /* Memory affinity structure */ + srat_mem[mmap_index].length = sizeof(acpi_srat_mem_t); + srat_mem[mmap_index].base_address_low = (uint32_t) (addr & 0xffffffff); + srat_mem[mmap_index].base_address_high = (uint32_t) (addr >> 32); + srat_mem[mmap_index].length_low = (uint32_t) (size & 0xffffffff); + srat_mem[mmap_index].length_high = (uint32_t) (size >> 32); + srat_mem[mmap_index].proximity_domain = mem_element->SocketId; + srat_mem[mmap_index].flags = SRAT_ACPI_MEMORY_ENABLED; + if ((mem_element->Type & MEMTYPE_VOLATILE_MASK) == 0) + srat_mem[mmap_index].flags |= SRAT_ACPI_MEMORY_NONVOLATILE; + ++mmap_index; + } + + return mmap_index; +} + +static unsigned long acpi_fill_srat(unsigned long current) +{ + acpi_srat_mem_t srat_mem[MAX_ACPI_MEMORY_AFFINITY_COUNT]; + unsigned int mem_count; + + /* create all subtables for processors */ + current = acpi_create_srat_lapics(current); + + mem_count = get_srat_memory_entries(srat_mem); + for (int i = 0; i < mem_count; ++i) { + printk(BIOS_DEBUG, "adding srat memory %d entry length: %d, addr: 0x%x%x, " + "length: 0x%x%x, proximity_domain: %d, flags: %x\n", + i, srat_mem[i].length, + srat_mem[i].base_address_high, srat_mem[i].base_address_low, + srat_mem[i].length_high, srat_mem[i].length_low, + srat_mem[i].proximity_domain, srat_mem[i].flags); + memcpy((acpi_srat_mem_t *)current, &srat_mem[i], sizeof(srat_mem[i])); + current += srat_mem[i].length; + } + + return current; +} + +static unsigned long acpi_fill_slit(unsigned long current) +{ + unsigned int nodes = xeon_sp_get_cpu_count(); + + uint8_t *p = (uint8_t *)current; + memset(p, 0, 8 + nodes * nodes); + *p = (uint8_t)nodes; + p += 8; + + /* this assumes fully connected socket topology */ + for (int i = 0; i < nodes; i++) { + for (int j = 0; j < nodes; j++) { + if (i == j) + p[i*nodes+j] = 10; + else + p[i*nodes+j] = 16; + } + } + + current += 8 + nodes * nodes; + return current; +} + +unsigned long northbridge_write_acpi_tables(const struct device *device, + unsigned long current, + struct acpi_rsdp *rsdp) +{ + acpi_srat_t *srat; + acpi_slit_t *slit; + + /* SRAT */ + current = ALIGN(current, 8); + printk(BIOS_DEBUG, "ACPI: * SRAT at %lx\n", current); + srat = (acpi_srat_t *) current; + acpi_create_srat(srat, acpi_fill_srat); + current += srat->header.length; + acpi_add_table(rsdp, srat); + + /* SLIT */ + current = ALIGN(current, 8); + printk(BIOS_DEBUG, "ACPI: * SLIT at %lx\n", current); + slit = (acpi_slit_t *) current; + acpi_create_slit(slit, acpi_fill_slit); + current += slit->header.length; + acpi_add_table(rsdp, slit); + + return current; +} diff --git a/src/soc/intel/xeon_sp/cpx/chip.c b/src/soc/intel/xeon_sp/cpx/chip.c index 19ebe4786d..cded072ccd 100644 --- a/src/soc/intel/xeon_sp/cpx/chip.c +++ b/src/soc/intel/xeon_sp/cpx/chip.c @@ -8,6 +8,7 @@ #include <fsp/api.h> #include <intelblocks/p2sb.h> #include <post.h> +#include <soc/acpi.h> #include <soc/cpu.h> #include <soc/ramstage.h> #include <soc/pm.h> @@ -496,6 +497,7 @@ static struct device_operations pci_domain_ops = { .read_resources = &pci_domain_read_resources, .set_resources = &xeonsp_cpx_pci_domain_set_resources, .scan_bus = &xeonsp_cpx_pci_domain_scan_bus, + .write_acpi_tables = &northbridge_write_acpi_tables, }; static struct device_operations cpu_bus_ops = { diff --git a/src/soc/intel/xeon_sp/cpx/include/soc/acpi.h b/src/soc/intel/xeon_sp/cpx/include/soc/acpi.h new file mode 100644 index 0000000000..0f010ec85f --- /dev/null +++ b/src/soc/intel/xeon_sp/cpx/include/soc/acpi.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _SOC_ACPI_H_ +#define _SOC_ACPI_H_ + +#include <acpi/acpi.h> +#include <soc/nvs.h> + +#define MEM_BLK_COUNT 0x140 +typedef struct { + uint8_t buf[32]; +} MEM_BLK; + +unsigned long northbridge_write_acpi_tables(const struct device *device, + unsigned long current, struct acpi_rsdp *rsdp); + +#endif /* _SOC_ACPI_H_ */ diff --git a/src/soc/intel/xeon_sp/cpx/include/soc/pci_devs.h b/src/soc/intel/xeon_sp/cpx/include/soc/pci_devs.h index 0e6f42ca63..4953f930f5 100644 --- a/src/soc/intel/xeon_sp/cpx/include/soc/pci_devs.h +++ b/src/soc/intel/xeon_sp/cpx/include/soc/pci_devs.h @@ -48,7 +48,43 @@ #define VTD_DEV 5 #define VTD_FUNC 0 +#define VMD_DEV_NUM 0x05 +#define VMD_FUNC_NUM 0x05 +#define APIC_DEV_NUM 0x05 +#define APIC_FUNC_NUM 0x04 + +#define CBDMA_DEV_NUM 0x04 +#define IIO_CBDMA_MMIO_SIZE 0x10000 //64kB for one CBDMA function + +#define PCH_IOAPIC_BUS_NUMBER 0x00 +#define PCH_IOAPIC_DEV_NUM 0x1F +#define PCH_IOAPIC_FUNC_NUM 0x00 + +/* PCH Device info */ + +#define XHCI_BUS_NUMBER 0x0 +#define PCH_DEV_SLOT_XHCI 0x14 +#define XHCI_FUNC_NUM 0x0 + +#define HPET_BUS_NUM 0x0 +#define HPET_DEV_NUM PCH_DEV_SLOT_LPC +#define HPET0_FUNC_NUM 0x00 + +// ==================== IOAPIC Definitions for DMAR/ACPI ==================== +#define PCH_IOAPIC_ID 0x08 +#define PC00_IOAPIC_ID 0x09 +#define PC01_IOAPIC_ID 0x0A +#define PC02_IOAPIC_ID 0x0B +#define PC03_IOAPIC_ID 0x0C +#define PC04_IOAPIC_ID 0x0D +#define PC05_IOAPIC_ID 0x0E +#define PC06_IOAPIC_ID 0x0F +#define PC07_IOAPIC_ID 0x10 +#define PC08_IOAPIC_ID 0x11 +#define PC09_IOAPIC_ID 0x12 +#define PC10_IOAPIC_ID 0x13 +#define PC11_IOAPIC_ID 0x14 #define PCH_DEV_SLOT_LPC 0x1f #define PCH_DEVFN_LPC _PCH_DEVFN(LPC, 0) diff --git a/src/soc/intel/xeon_sp/cpx/include/soc/soc_util.h b/src/soc/intel/xeon_sp/cpx/include/soc/soc_util.h index 679ad4a3c0..1c3ca66c52 100644 --- a/src/soc/intel/xeon_sp/cpx/include/soc/soc_util.h +++ b/src/soc/intel/xeon_sp/cpx/include/soc/soc_util.h @@ -36,4 +36,8 @@ void get_cpu_info_from_apicid(uint32_t apicid, uint32_t core_bits, uint32_t thre uint8_t *package, uint8_t *core, uint8_t *thread); unsigned int xeon_sp_get_cpu_count(void); +int get_platform_thread_count(void); +int get_threads_per_package(void); +const struct SystemMemoryMapHob *get_system_memory_map(void); + #endif /* _SOC_UTIL_H_ */ diff --git a/src/soc/intel/xeon_sp/cpx/soc_util.c b/src/soc/intel/xeon_sp/cpx/soc_util.c index 2d106575c3..2e183ef062 100644 --- a/src/soc/intel/xeon_sp/cpx/soc_util.c +++ b/src/soc/intel/xeon_sp/cpx/soc_util.c @@ -9,6 +9,30 @@ #include <stdlib.h> #include <string.h> +int get_threads_per_package(void) +{ + unsigned int core_count, thread_count; + cpu_read_topology(&core_count, &thread_count); + return thread_count; +} + +int get_platform_thread_count(void) +{ + return xeon_sp_get_cpu_count() * get_threads_per_package(); +} + +const struct SystemMemoryMapHob *get_system_memory_map(void) +{ + size_t hob_size; + const uint8_t mem_hob_guid[16] = FSP_SYSTEM_MEMORYMAP_HOB_GUID; + + const void *memmap_addr = fsp_find_extension_hob_by_guid(mem_hob_guid, &hob_size); + assert(memmap_addr != NULL && hob_size != 0); + printk(BIOS_DEBUG, "FSP_SYSTEM_MEMORYMAP_HOB_GUID hob_size: %ld\n", hob_size); + + return (const struct SystemMemoryMapHob *) memmap_addr; +} + void get_cpu_info_from_apicid(uint32_t apicid, uint32_t core_bits, uint32_t thread_bits, uint8_t *package, uint8_t *core, uint8_t *thread) { |