diff options
-rw-r--r-- | src/soc/intel/xeon_sp/include/soc/numa.h | 65 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/uncore.c | 55 |
2 files changed, 117 insertions, 3 deletions
diff --git a/src/soc/intel/xeon_sp/include/soc/numa.h b/src/soc/intel/xeon_sp/include/soc/numa.h new file mode 100644 index 0000000000..48141c73f7 --- /dev/null +++ b/src/soc/intel/xeon_sp/include/soc/numa.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* + * This header file defines data structures and operations related + * to NUMA proximity domains. + */ +#ifndef NUMA_H +#define NUMA_H + +#include <types.h> + +enum proximity_domain_type { + PD_TYPE_PROCESSOR, + /* + * The Generic Initiator concept is used in ACPI spec. A typical + * Generic Initiator domain is a CXL memory device. + */ + PD_TYPE_GENERIC_INITIATOR, +}; + +/* + * This proximity domain structure records all data related to + * a proximity doamin needed for following purpose: + * a. Device resource allocation. IIO stack involving CXL device + * needs to have different resource allocation method. + * b. e820 table setup. For example, CXL memory region may need to + * be set as soft reserved, since it is specific purpose memory. + * c. ACPI NUMA tables (SRAT, SLIT, HMAT). + */ +struct proximity_domain { + enum proximity_domain_type pd_type; + /* + * For processor domain, this holds the socket #. + * For generic initiator domain, this indicates to which socket the + * device is attached to. CXL 2.0 allows interleaving within and between + * sockets, so we need a bitmap. + */ + uint8_t socket_bitmap; + /* Relative distances (memory latency) from all domains */ + uint8_t *distances; + /* + * Below fields are set to 0 for processor domains. + */ + uint32_t device_handle; /* This holds PCIe device segment, BDF info */ + uint32_t base; /* Memory region base address in the unit of 64MB */ + uint32_t size; /* Memory region size in the unit of 64MB */ +}; + +struct proximity_domains { + uint8_t num_pds; + struct proximity_domain *pds; +}; + +extern struct proximity_domains pds; + +void dump_pds(void); +enum cb_err fill_pds(void); + +/* + * Return the total size of memory regions in generic initiator affinity + * domains. The size is in unit of 64MB. + */ +uint32_t get_generic_initiator_mem_size(void); + +#endif /* NUMA_H */ diff --git a/src/soc/intel/xeon_sp/uncore.c b/src/soc/intel/xeon_sp/uncore.c index 418736ed2e..5249a94474 100644 --- a/src/soc/intel/xeon_sp/uncore.c +++ b/src/soc/intel/xeon_sp/uncore.c @@ -5,6 +5,7 @@ #include <cpu/x86/lapic_def.h> #include <device/pci.h> #include <device/pci_ids.h> +#include <drivers/ocp/include/vpd.h> #include <soc/acpi.h> #include <soc/iomap.h> #include <soc/pci_devs.h> @@ -13,8 +14,15 @@ #include <fsp/util.h> #include <security/intel/txt/txt_platform.h> #include <security/intel/txt/txt.h> +#include <soc/numa.h> +#include <soc/soc_util.h> #include <stdint.h> +struct proximity_domains pds = { + .num_pds = 0, + .pds = NULL, +}; + struct map_entry { uint32_t reg; int is_64_bit; @@ -238,9 +246,42 @@ static void mc_add_dram_resources(struct device *dev, int *res_count) mc_values[TOLM_REG]); LOG_RESOURCE("mmio_tolm", dev, res); - /* 4GiB -> TOHM */ - res = upper_ram_end(dev, index++, mc_values[TOHM_REG] + 1); - LOG_RESOURCE("high_ram", dev, res); + if (CONFIG(SOC_INTEL_HAS_CXL)) { + /* 4GiB -> CXL Memory */ + uint32_t gi_mem_size; + gi_mem_size = get_generic_initiator_mem_size(); + + res = reserved_ram_from_to(dev, index++, 0x100000000, + mc_values[TOHM_REG] - (uint64_t)gi_mem_size + 1); + LOG_RESOURCE("high_ram", dev, res); + + /* CXL Memory */ + uint8_t i; + for (i = 0; i < pds.num_pds; i++) { + if (pds.pds[i].pd_type == PD_TYPE_PROCESSOR) + continue; + + if (CONFIG(OCP_VPD)) { + unsigned long flags = IORESOURCE_CACHEABLE; + int cxl_mode = get_cxl_mode_from_vpd(); + if (cxl_mode == CXL_SPM) + flags |= IORESOURCE_SOFT_RESERVE; + else + flags |= IORESOURCE_STORED; + + res = fixed_mem_range_flags(dev, index++, (uint64_t)pds.pds[i].base, + (uint64_t)pds.pds[i].size, flags); + if (cxl_mode == CXL_SPM) + LOG_RESOURCE("specific_purpose_memory", dev, res); + else + LOG_RESOURCE("CXL_memory", dev, res); + } + } + } else { + /* 4GiB -> TOHM */ + res = upper_ram_end(dev, index++, mc_values[TOHM_REG] + 1); + LOG_RESOURCE("high_ram", dev, res); + } /* add MMIO CFG resource */ res = mmio_from_to(dev, index++, mc_values[MMCFG_BASE_REG], @@ -271,6 +312,14 @@ static void mmapvtd_read_resources(struct device *dev) { int index = 0; + if (CONFIG(SOC_INTEL_HAS_CXL)) { + /* Construct NUMA data structure. This is needed for CXL. */ + if (fill_pds() != CB_SUCCESS) + pds.num_pds = 0; + + dump_pds(); + } + /* Read standard PCI resources. */ pci_dev_read_resources(dev); |