Skip to content

Commit

Permalink
ACPI: NUMA: Add a node and memblk for each CFMWS not in SRAT
Browse files Browse the repository at this point in the history
During NUMA init, CXL memory defined in the SRAT Memory Affinity
subtable may be assigned to a NUMA node. Since there is no
requirement that the SRAT be comprehensive for CXL memory another
mechanism is needed to assign NUMA nodes to CXL memory not identified
in the SRAT.

Use the CXL Fixed Memory Window Structure (CFMWS) of the ACPI CXL
Early Discovery Table (CEDT) to find all CXL memory ranges.
Create a NUMA node for each CFMWS that is not already assigned to
a NUMA node. Add a memblk attaching its host physical address
range to the node.

Note that these ranges may not actually map any memory at boot time.
They may describe persistent capacity or may be present to enable
hot-plug.

Consumers can use phys_to_target_node() to discover the NUMA node.

Signed-off-by: Alison Schofield <alison.schofield@intel.com>
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Link: https://lore.kernel.org/r/163553711933.2509508.2203471175679990.stgit@dwillia2-desk3.amr.corp.intel.com
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
  • Loading branch information
AlisonSchofield authored and djbw committed Nov 15, 2021
1 parent 814dff9 commit fd49f99
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 2 deletions.
59 changes: 58 additions & 1 deletion drivers/acpi/numa/srat.c
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,47 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
out_err:
return -EINVAL;
}

static int __init acpi_parse_cfmws(union acpi_subtable_headers *header,
void *arg, const unsigned long table_end)
{
struct acpi_cedt_cfmws *cfmws;
int *fake_pxm = arg;
u64 start, end;
int node;

cfmws = (struct acpi_cedt_cfmws *)header;
start = cfmws->base_hpa;
end = cfmws->base_hpa + cfmws->window_size;

/* Skip if the SRAT already described the NUMA details for this HPA */
node = phys_to_target_node(start);
if (node != NUMA_NO_NODE)
return 0;

node = acpi_map_pxm_to_node(*fake_pxm);

if (node == NUMA_NO_NODE) {
pr_err("ACPI NUMA: Too many proximity domains while processing CFMWS.\n");
return -EINVAL;
}

if (numa_add_memblk(node, start, end) < 0) {
/* CXL driver must handle the NUMA_NO_NODE case */
pr_warn("ACPI NUMA: Failed to add memblk for CFMWS node %d [mem %#llx-%#llx]\n",
node, start, end);
}

/* Set the next available fake_pxm value */
(*fake_pxm)++;
return 0;
}
#else
static int __init acpi_parse_cfmws(union acpi_subtable_headers *header,
void *arg, const unsigned long table_end)
{
return 0;
}
#endif /* defined(CONFIG_X86) || defined (CONFIG_ARM64) */

static int __init acpi_parse_slit(struct acpi_table_header *table)
Expand Down Expand Up @@ -442,7 +483,7 @@ acpi_table_parse_srat(enum acpi_srat_type id,

int __init acpi_numa_init(void)
{
int cnt = 0;
int i, fake_pxm, cnt = 0;

if (acpi_disabled)
return -EINVAL;
Expand Down Expand Up @@ -478,6 +519,22 @@ int __init acpi_numa_init(void)
/* SLIT: System Locality Information Table */
acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit);

/*
* CXL Fixed Memory Window Structures (CFMWS) must be parsed
* after the SRAT. Create NUMA Nodes for CXL memory ranges that
* are defined in the CFMWS and not already defined in the SRAT.
* Initialize a fake_pxm as the first available PXM to emulate.
*/

/* fake_pxm is the next unused PXM value after SRAT parsing */
for (i = 0, fake_pxm = -1; i < MAX_NUMNODES - 1; i++) {
if (node_to_pxm_map[i] > fake_pxm)
fake_pxm = node_to_pxm_map[i];
}
fake_pxm++;
acpi_table_parse_cedt(ACPI_CEDT_TYPE_CFMWS, acpi_parse_cfmws,
&fake_pxm);

if (cnt < 0)
return cnt;
else if (!parsed_numa_memblks)
Expand Down
3 changes: 2 additions & 1 deletion drivers/cxl/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ static int cxl_parse_cfmws(union acpi_subtable_headers *header, void *arg,
cfmws->base_hpa + cfmws->window_size - 1);
return 0;
}
dev_dbg(dev, "add: %s range %#llx-%#llx\n", dev_name(&cxld->dev),
dev_dbg(dev, "add: %s node: %d range %#llx-%#llx\n",
dev_name(&cxld->dev), phys_to_target_node(cxld->range.start),
cfmws->base_hpa, cfmws->base_hpa + cfmws->window_size - 1);

return 0;
Expand Down

0 comments on commit fd49f99

Please sign in to comment.