Skip to content

Commit 763e15d

Browse files
committed
Merge branch 'for-6.15/extended-linear-cache' into cxl-for-next2
Add support for Extended Linear Cache for CXL. Add enumeration support of the cache. Add MCE notification of the aliased memory address.
2 parents d781a45 + 516e5bd commit 763e15d

File tree

18 files changed

+334
-21
lines changed

18 files changed

+334
-21
lines changed

Documentation/ABI/stable/sysfs-devices-node

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,12 @@ Description:
177177
The cache write policy: 0 for write-back, 1 for write-through,
178178
other or unknown.
179179

180+
What: /sys/devices/system/node/nodeX/memory_side_cache/indexY/address_mode
181+
Date: March 2025
182+
Contact: Dave Jiang <dave.jiang@intel.com>
183+
Description:
184+
The address mode: 0 for reserved, 1 for extended-linear.
185+
180186
What: /sys/devices/system/node/nodeX/x86/sgx_total_bytes
181187
Date: November 2021
182188
Contact: Jarkko Sakkinen <jarkko@kernel.org>

arch/x86/mm/pat/set_memory.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2081,6 +2081,7 @@ int set_mce_nospec(unsigned long pfn)
20812081
pr_warn("Could not invalidate pfn=0x%lx from 1:1 map\n", pfn);
20822082
return rc;
20832083
}
2084+
EXPORT_SYMBOL_GPL(set_mce_nospec);
20842085

20852086
/* Restore full speculative operation to the pfn. */
20862087
int clear_mce_nospec(unsigned long pfn)

drivers/acpi/numa/hmat.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,45 @@ static struct memory_target *find_mem_target(unsigned int mem_pxm)
108108
return NULL;
109109
}
110110

111+
/**
112+
* hmat_get_extended_linear_cache_size - Retrieve the extended linear cache size
113+
* @backing_res: resource from the backing media
114+
* @nid: node id for the memory region
115+
* @cache_size: (Output) size of extended linear cache.
116+
*
117+
* Return: 0 on success. Errno on failure.
118+
*
119+
*/
120+
int hmat_get_extended_linear_cache_size(struct resource *backing_res, int nid,
121+
resource_size_t *cache_size)
122+
{
123+
unsigned int pxm = node_to_pxm(nid);
124+
struct memory_target *target;
125+
struct target_cache *tcache;
126+
struct resource *res;
127+
128+
target = find_mem_target(pxm);
129+
if (!target)
130+
return -ENOENT;
131+
132+
list_for_each_entry(tcache, &target->caches, node) {
133+
if (tcache->cache_attrs.address_mode !=
134+
NODE_CACHE_ADDR_MODE_EXTENDED_LINEAR)
135+
continue;
136+
137+
res = &target->memregions;
138+
if (!resource_contains(res, backing_res))
139+
continue;
140+
141+
*cache_size = tcache->cache_attrs.size;
142+
return 0;
143+
}
144+
145+
*cache_size = 0;
146+
return 0;
147+
}
148+
EXPORT_SYMBOL_NS_GPL(hmat_get_extended_linear_cache_size, "CXL");
149+
111150
static struct memory_target *acpi_find_genport_target(u32 uid)
112151
{
113152
struct memory_target *target;
@@ -506,6 +545,11 @@ static __init int hmat_parse_cache(union acpi_subtable_headers *header,
506545
switch ((attrs & ACPI_HMAT_CACHE_ASSOCIATIVITY) >> 8) {
507546
case ACPI_HMAT_CA_DIRECT_MAPPED:
508547
tcache->cache_attrs.indexing = NODE_CACHE_DIRECT_MAP;
548+
/* Extended Linear mode is only valid if cache is direct mapped */
549+
if (cache->address_mode == ACPI_HMAT_CACHE_MODE_EXTENDED_LINEAR) {
550+
tcache->cache_attrs.address_mode =
551+
NODE_CACHE_ADDR_MODE_EXTENDED_LINEAR;
552+
}
509553
break;
510554
case ACPI_HMAT_CA_COMPLEX_CACHE_INDEXING:
511555
tcache->cache_attrs.indexing = NODE_CACHE_INDEXED;

drivers/base/node.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,12 +244,14 @@ CACHE_ATTR(size, "%llu")
244244
CACHE_ATTR(line_size, "%u")
245245
CACHE_ATTR(indexing, "%u")
246246
CACHE_ATTR(write_policy, "%u")
247+
CACHE_ATTR(address_mode, "%#x")
247248

248249
static struct attribute *cache_attrs[] = {
249250
&dev_attr_indexing.attr,
250251
&dev_attr_size.attr,
251252
&dev_attr_line_size.attr,
252253
&dev_attr_write_policy.attr,
254+
&dev_attr_address_mode.attr,
253255
NULL,
254256
};
255257
ATTRIBUTE_GROUPS(cache);

drivers/cxl/Kconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,8 @@ config CXL_REGION_INVALIDATION_TEST
146146
If unsure, or if this kernel is meant for production environments,
147147
say N.
148148

149+
config CXL_MCE
150+
def_bool y
151+
depends on X86_MCE && MEMORY_FAILURE
152+
149153
endif

drivers/cxl/core/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,7 @@ cxl_core-y += hdm.o
1515
cxl_core-y += pmu.o
1616
cxl_core-y += cdat.o
1717
cxl_core-y += ras.o
18+
cxl_core-y += acpi.o
1819
cxl_core-$(CONFIG_TRACING) += trace.o
1920
cxl_core-$(CONFIG_CXL_REGION) += region.o
21+
cxl_core-$(CONFIG_CXL_MCE) += mce.o

drivers/cxl/core/acpi.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/* Copyright(c) 2024 Intel Corporation. All rights reserved. */
3+
#include <linux/acpi.h>
4+
#include "cxl.h"
5+
#include "core.h"
6+
7+
int cxl_acpi_get_extended_linear_cache_size(struct resource *backing_res,
8+
int nid, resource_size_t *size)
9+
{
10+
return hmat_get_extended_linear_cache_size(backing_res, nid, size);
11+
}

drivers/cxl/core/core.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,5 +118,7 @@ int cxl_port_get_switch_dport_bandwidth(struct cxl_port *port,
118118
int cxl_ras_init(void);
119119
void cxl_ras_exit(void);
120120
int cxl_gpf_port_setup(struct device *dport_dev, struct cxl_port *port);
121+
int cxl_acpi_get_extended_linear_cache_size(struct resource *backing_res,
122+
int nid, resource_size_t *size);
121123

122124
#endif /* __CXL_CORE_H__ */

drivers/cxl/core/mbox.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include "core.h"
1313
#include "trace.h"
14+
#include "mce.h"
1415

1516
static bool cxl_raw_allow_all;
1617

@@ -871,7 +872,7 @@ void cxl_event_trace_record(const struct cxl_memdev *cxlmd,
871872
}
872873

873874
if (trace_cxl_general_media_enabled() || trace_cxl_dram_enabled()) {
874-
u64 dpa, hpa = ULLONG_MAX;
875+
u64 dpa, hpa = ULLONG_MAX, hpa_alias = ULLONG_MAX;
875876
struct cxl_region *cxlr;
876877

877878
/*
@@ -884,14 +885,20 @@ void cxl_event_trace_record(const struct cxl_memdev *cxlmd,
884885

885886
dpa = le64_to_cpu(evt->media_hdr.phys_addr) & CXL_DPA_MASK;
886887
cxlr = cxl_dpa_to_region(cxlmd, dpa);
887-
if (cxlr)
888+
if (cxlr) {
889+
u64 cache_size = cxlr->params.cache_size;
890+
888891
hpa = cxl_dpa_to_hpa(cxlr, cxlmd, dpa);
892+
if (cache_size)
893+
hpa_alias = hpa - cache_size;
894+
}
889895

890896
if (event_type == CXL_CPER_EVENT_GEN_MEDIA)
891897
trace_cxl_general_media(cxlmd, type, cxlr, hpa,
892-
&evt->gen_media);
898+
hpa_alias, &evt->gen_media);
893899
else if (event_type == CXL_CPER_EVENT_DRAM)
894-
trace_cxl_dram(cxlmd, type, cxlr, hpa, &evt->dram);
900+
trace_cxl_dram(cxlmd, type, cxlr, hpa, hpa_alias,
901+
&evt->dram);
895902
}
896903
}
897904
EXPORT_SYMBOL_NS_GPL(cxl_event_trace_record, "CXL");
@@ -1451,6 +1458,7 @@ EXPORT_SYMBOL_NS_GPL(cxl_mailbox_init, "CXL");
14511458
struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev)
14521459
{
14531460
struct cxl_memdev_state *mds;
1461+
int rc;
14541462

14551463
mds = devm_kzalloc(dev, sizeof(*mds), GFP_KERNEL);
14561464
if (!mds) {
@@ -1464,6 +1472,10 @@ struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev)
14641472
mds->cxlds.reg_map.resource = CXL_RESOURCE_NONE;
14651473
mds->cxlds.type = CXL_DEVTYPE_CLASSMEM;
14661474

1475+
rc = devm_cxl_register_mce_notifier(dev, &mds->mce_notifier);
1476+
if (rc)
1477+
return ERR_PTR(rc);
1478+
14671479
return mds;
14681480
}
14691481
EXPORT_SYMBOL_NS_GPL(cxl_memdev_state_create, "CXL");

drivers/cxl/core/mce.c

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/* Copyright(c) 2024 Intel Corporation. All rights reserved. */
3+
#include <linux/mm.h>
4+
#include <linux/notifier.h>
5+
#include <linux/set_memory.h>
6+
#include <asm/mce.h>
7+
#include <cxlmem.h>
8+
#include "mce.h"
9+
10+
static int cxl_handle_mce(struct notifier_block *nb, unsigned long val,
11+
void *data)
12+
{
13+
struct cxl_memdev_state *mds = container_of(nb, struct cxl_memdev_state,
14+
mce_notifier);
15+
struct cxl_memdev *cxlmd = mds->cxlds.cxlmd;
16+
struct cxl_port *endpoint = cxlmd->endpoint;
17+
struct mce *mce = data;
18+
u64 spa, spa_alias;
19+
unsigned long pfn;
20+
21+
if (!mce || !mce_usable_address(mce))
22+
return NOTIFY_DONE;
23+
24+
if (!endpoint)
25+
return NOTIFY_DONE;
26+
27+
spa = mce->addr & MCI_ADDR_PHYSADDR;
28+
29+
pfn = spa >> PAGE_SHIFT;
30+
if (!pfn_valid(pfn))
31+
return NOTIFY_DONE;
32+
33+
spa_alias = cxl_port_get_spa_cache_alias(endpoint, spa);
34+
if (spa_alias == ~0ULL)
35+
return NOTIFY_DONE;
36+
37+
pfn = spa_alias >> PAGE_SHIFT;
38+
39+
/*
40+
* Take down the aliased memory page. The original memory page flagged
41+
* by the MCE will be taken cared of by the standard MCE handler.
42+
*/
43+
dev_emerg(mds->cxlds.dev, "Offlining aliased SPA address0: %#llx\n",
44+
spa_alias);
45+
if (!memory_failure(pfn, 0))
46+
set_mce_nospec(pfn);
47+
48+
return NOTIFY_OK;
49+
}
50+
51+
static void cxl_unregister_mce_notifier(void *mce_notifier)
52+
{
53+
mce_unregister_decode_chain(mce_notifier);
54+
}
55+
56+
int devm_cxl_register_mce_notifier(struct device *dev,
57+
struct notifier_block *mce_notifier)
58+
{
59+
mce_notifier->notifier_call = cxl_handle_mce;
60+
mce_notifier->priority = MCE_PRIO_UC;
61+
mce_register_decode_chain(mce_notifier);
62+
63+
return devm_add_action_or_reset(dev, cxl_unregister_mce_notifier,
64+
mce_notifier);
65+
}

0 commit comments

Comments
 (0)