summaryrefslogtreecommitdiff
path: root/src/soc
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc')
-rw-r--r--src/soc/intel/xeon_sp/include/soc/numa.h65
-rw-r--r--src/soc/intel/xeon_sp/uncore.c55
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);