Skip to content

Commit d1257d0

Browse files
committed
cxl/region: Move cache invalidation before region teardown, and before setup
Vikram raised a concern with the theoretical case of a CPU sending MemClnEvict to a device that is not prepared to receive. MemClnEvict is a message that is sent after a CPU has taken ownership of a cacheline from accelerator memory (HDM-DB). In the case of hotplug or HDM decoder reconfiguration it is possible that the CPU is holding old contents for a new device that has taken over the physical address range being cached by the CPU. To avoid this scenario, invalidate caches prior to tearing down an HDM decoder configuration. Now, this poses another problem that it is possible for something to speculate into that space while the decode configuration is still up, so to close that gap also invalidate prior to establish new contents behind a given physical address range. With this change the cache invalidation is now explicit and need not be checked in cxl_region_probe(), and that obviates the need for CXL_REGION_F_INCOHERENT. Cc: Jonathan Cameron <Jonathan.Cameron@Huawei.com> Fixes: d18bc74 ("cxl/region: Manage CPU caches relative to DPA invalidation events") Reported-by: Vikram Sethi <vsethi@nvidia.com> Closes: http://lore.kernel.org/r/BYAPR12MB33364B5EB908BF7239BB996BBD53A@BYAPR12MB3336.namprd12.prod.outlook.com Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Reviewed-by: Dave Jiang <dave.jiang@intel.com> Link: https://lore.kernel.org/r/168696506886.3590522.4597053660991916591.stgit@dwillia2-xfh.jf.intel.com Signed-off-by: Dan Williams <dan.j.williams@intel.com>
1 parent 858fd16 commit d1257d0

2 files changed

Lines changed: 38 additions & 36 deletions

File tree

drivers/cxl/core/region.c

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -125,18 +125,45 @@ static struct cxl_region_ref *cxl_rr_load(struct cxl_port *port,
125125
return xa_load(&port->regions, (unsigned long)cxlr);
126126
}
127127

128+
static int cxl_region_invalidate_memregion(struct cxl_region *cxlr)
129+
{
130+
if (!cpu_cache_has_invalidate_memregion()) {
131+
if (IS_ENABLED(CONFIG_CXL_REGION_INVALIDATION_TEST)) {
132+
dev_warn_once(
133+
&cxlr->dev,
134+
"Bypassing cpu_cache_invalidate_memregion() for testing!\n");
135+
return 0;
136+
} else {
137+
dev_err(&cxlr->dev,
138+
"Failed to synchronize CPU cache state\n");
139+
return -ENXIO;
140+
}
141+
}
142+
143+
cpu_cache_invalidate_memregion(IORES_DESC_CXL);
144+
return 0;
145+
}
146+
128147
static int cxl_region_decode_reset(struct cxl_region *cxlr, int count)
129148
{
130149
struct cxl_region_params *p = &cxlr->params;
131-
int i;
150+
int i, rc = 0;
151+
152+
/*
153+
* Before region teardown attempt to flush, and if the flush
154+
* fails cancel the region teardown for data consistency
155+
* concerns
156+
*/
157+
rc = cxl_region_invalidate_memregion(cxlr);
158+
if (rc)
159+
return rc;
132160

133161
for (i = count - 1; i >= 0; i--) {
134162
struct cxl_endpoint_decoder *cxled = p->targets[i];
135163
struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
136164
struct cxl_port *iter = cxled_to_port(cxled);
137165
struct cxl_dev_state *cxlds = cxlmd->cxlds;
138166
struct cxl_ep *ep;
139-
int rc = 0;
140167

141168
if (cxlds->rcd)
142169
goto endpoint_reset;
@@ -256,6 +283,14 @@ static ssize_t commit_store(struct device *dev, struct device_attribute *attr,
256283
goto out;
257284
}
258285

286+
/*
287+
* Invalidate caches before region setup to drop any speculative
288+
* consumption of this address space
289+
*/
290+
rc = cxl_region_invalidate_memregion(cxlr);
291+
if (rc)
292+
return rc;
293+
259294
if (commit)
260295
rc = cxl_region_decode_commit(cxlr);
261296
else {
@@ -1674,7 +1709,6 @@ static int cxl_region_attach(struct cxl_region *cxlr,
16741709
if (rc)
16751710
goto err_decrement;
16761711
p->state = CXL_CONFIG_ACTIVE;
1677-
set_bit(CXL_REGION_F_INCOHERENT, &cxlr->flags);
16781712
}
16791713

16801714
cxled->cxld.interleave_ways = p->interleave_ways;
@@ -2803,30 +2837,6 @@ int cxl_add_to_region(struct cxl_port *root, struct cxl_endpoint_decoder *cxled)
28032837
}
28042838
EXPORT_SYMBOL_NS_GPL(cxl_add_to_region, CXL);
28052839

2806-
static int cxl_region_invalidate_memregion(struct cxl_region *cxlr)
2807-
{
2808-
if (!test_bit(CXL_REGION_F_INCOHERENT, &cxlr->flags))
2809-
return 0;
2810-
2811-
if (!cpu_cache_has_invalidate_memregion()) {
2812-
if (IS_ENABLED(CONFIG_CXL_REGION_INVALIDATION_TEST)) {
2813-
dev_warn_once(
2814-
&cxlr->dev,
2815-
"Bypassing cpu_cache_invalidate_memregion() for testing!\n");
2816-
clear_bit(CXL_REGION_F_INCOHERENT, &cxlr->flags);
2817-
return 0;
2818-
} else {
2819-
dev_err(&cxlr->dev,
2820-
"Failed to synchronize CPU cache state\n");
2821-
return -ENXIO;
2822-
}
2823-
}
2824-
2825-
cpu_cache_invalidate_memregion(IORES_DESC_CXL);
2826-
clear_bit(CXL_REGION_F_INCOHERENT, &cxlr->flags);
2827-
return 0;
2828-
}
2829-
28302840
static int is_system_ram(struct resource *res, void *arg)
28312841
{
28322842
struct cxl_region *cxlr = arg;
@@ -2854,8 +2864,6 @@ static int cxl_region_probe(struct device *dev)
28542864
goto out;
28552865
}
28562866

2857-
rc = cxl_region_invalidate_memregion(cxlr);
2858-
28592867
/*
28602868
* From this point on any path that changes the region's state away from
28612869
* CXL_CONFIG_COMMIT is also responsible for releasing the driver.

drivers/cxl/cxl.h

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -462,18 +462,12 @@ struct cxl_region_params {
462462
int nr_targets;
463463
};
464464

465-
/*
466-
* Flag whether this region needs to have its HPA span synchronized with
467-
* CPU cache state at region activation time.
468-
*/
469-
#define CXL_REGION_F_INCOHERENT 0
470-
471465
/*
472466
* Indicate whether this region has been assembled by autodetection or
473467
* userspace assembly. Prevent endpoint decoders outside of automatic
474468
* detection from being added to the region.
475469
*/
476-
#define CXL_REGION_F_AUTO 1
470+
#define CXL_REGION_F_AUTO 0
477471

478472
/**
479473
* struct cxl_region - CXL region

0 commit comments

Comments
 (0)