Skip to content

Commit 660c0a8

Browse files
committed
Merge remote-tracking branch 'cxl/for-6.10/dpa-to-hpa' into cxl-for-next
Support for HPA to DPA translation for CXL events cxl_dram and cxl_general_media.
2 parents c26a55e + 6aec001 commit 660c0a8

File tree

7 files changed

+226
-154
lines changed

7 files changed

+226
-154
lines changed

drivers/cxl/core/core.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,21 @@ void cxl_decoder_kill_region(struct cxl_endpoint_decoder *cxled);
2727
int cxl_region_init(void);
2828
void cxl_region_exit(void);
2929
int cxl_get_poison_by_endpoint(struct cxl_port *port);
30+
struct cxl_region *cxl_dpa_to_region(const struct cxl_memdev *cxlmd, u64 dpa);
31+
u64 cxl_trace_hpa(struct cxl_region *cxlr, const struct cxl_memdev *cxlmd,
32+
u64 dpa);
33+
3034
#else
35+
static inline u64
36+
cxl_trace_hpa(struct cxl_region *cxlr, const struct cxl_memdev *cxlmd, u64 dpa)
37+
{
38+
return ULLONG_MAX;
39+
}
40+
static inline
41+
struct cxl_region *cxl_dpa_to_region(const struct cxl_memdev *cxlmd, u64 dpa)
42+
{
43+
return NULL;
44+
}
3145
static inline int cxl_get_poison_by_endpoint(struct cxl_port *port)
3246
{
3347
return 0;

drivers/cxl/core/mbox.c

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -854,14 +854,38 @@ void cxl_event_trace_record(const struct cxl_memdev *cxlmd,
854854
enum cxl_event_type event_type,
855855
const uuid_t *uuid, union cxl_event *evt)
856856
{
857-
if (event_type == CXL_CPER_EVENT_GEN_MEDIA)
858-
trace_cxl_general_media(cxlmd, type, &evt->gen_media);
859-
else if (event_type == CXL_CPER_EVENT_DRAM)
860-
trace_cxl_dram(cxlmd, type, &evt->dram);
861-
else if (event_type == CXL_CPER_EVENT_MEM_MODULE)
857+
if (event_type == CXL_CPER_EVENT_MEM_MODULE) {
862858
trace_cxl_memory_module(cxlmd, type, &evt->mem_module);
863-
else
859+
return;
860+
}
861+
if (event_type == CXL_CPER_EVENT_GENERIC) {
864862
trace_cxl_generic_event(cxlmd, type, uuid, &evt->generic);
863+
return;
864+
}
865+
866+
if (trace_cxl_general_media_enabled() || trace_cxl_dram_enabled()) {
867+
u64 dpa, hpa = ULLONG_MAX;
868+
struct cxl_region *cxlr;
869+
870+
/*
871+
* These trace points are annotated with HPA and region
872+
* translations. Take topology mutation locks and lookup
873+
* { HPA, REGION } from { DPA, MEMDEV } in the event record.
874+
*/
875+
guard(rwsem_read)(&cxl_region_rwsem);
876+
guard(rwsem_read)(&cxl_dpa_rwsem);
877+
878+
dpa = le64_to_cpu(evt->common.phys_addr) & CXL_DPA_MASK;
879+
cxlr = cxl_dpa_to_region(cxlmd, dpa);
880+
if (cxlr)
881+
hpa = cxl_trace_hpa(cxlr, cxlmd, dpa);
882+
883+
if (event_type == CXL_CPER_EVENT_GEN_MEDIA)
884+
trace_cxl_general_media(cxlmd, type, cxlr, hpa,
885+
&evt->gen_media);
886+
else if (event_type == CXL_CPER_EVENT_DRAM)
887+
trace_cxl_dram(cxlmd, type, cxlr, hpa, &evt->dram);
888+
}
865889
}
866890
EXPORT_SYMBOL_NS_GPL(cxl_event_trace_record, CXL);
867891

drivers/cxl/core/memdev.c

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -251,50 +251,6 @@ int cxl_trigger_poison_list(struct cxl_memdev *cxlmd)
251251
}
252252
EXPORT_SYMBOL_NS_GPL(cxl_trigger_poison_list, CXL);
253253

254-
struct cxl_dpa_to_region_context {
255-
struct cxl_region *cxlr;
256-
u64 dpa;
257-
};
258-
259-
static int __cxl_dpa_to_region(struct device *dev, void *arg)
260-
{
261-
struct cxl_dpa_to_region_context *ctx = arg;
262-
struct cxl_endpoint_decoder *cxled;
263-
u64 dpa = ctx->dpa;
264-
265-
if (!is_endpoint_decoder(dev))
266-
return 0;
267-
268-
cxled = to_cxl_endpoint_decoder(dev);
269-
if (!cxled->dpa_res || !resource_size(cxled->dpa_res))
270-
return 0;
271-
272-
if (dpa > cxled->dpa_res->end || dpa < cxled->dpa_res->start)
273-
return 0;
274-
275-
dev_dbg(dev, "dpa:0x%llx mapped in region:%s\n", dpa,
276-
dev_name(&cxled->cxld.region->dev));
277-
278-
ctx->cxlr = cxled->cxld.region;
279-
280-
return 1;
281-
}
282-
283-
static struct cxl_region *cxl_dpa_to_region(struct cxl_memdev *cxlmd, u64 dpa)
284-
{
285-
struct cxl_dpa_to_region_context ctx;
286-
struct cxl_port *port;
287-
288-
ctx = (struct cxl_dpa_to_region_context) {
289-
.dpa = dpa,
290-
};
291-
port = cxlmd->endpoint;
292-
if (port && is_cxl_endpoint(port) && cxl_num_decoders_committed(port))
293-
device_for_each_child(&port->dev, &ctx, __cxl_dpa_to_region);
294-
295-
return ctx.cxlr;
296-
}
297-
298254
static int cxl_validate_poison_dpa(struct cxl_memdev *cxlmd, u64 dpa)
299255
{
300256
struct cxl_dev_state *cxlds = cxlmd->cxlds;

drivers/cxl/core/region.c

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2679,6 +2679,141 @@ int cxl_get_poison_by_endpoint(struct cxl_port *port)
26792679
return rc;
26802680
}
26812681

2682+
struct cxl_dpa_to_region_context {
2683+
struct cxl_region *cxlr;
2684+
u64 dpa;
2685+
};
2686+
2687+
static int __cxl_dpa_to_region(struct device *dev, void *arg)
2688+
{
2689+
struct cxl_dpa_to_region_context *ctx = arg;
2690+
struct cxl_endpoint_decoder *cxled;
2691+
u64 dpa = ctx->dpa;
2692+
2693+
if (!is_endpoint_decoder(dev))
2694+
return 0;
2695+
2696+
cxled = to_cxl_endpoint_decoder(dev);
2697+
if (!cxled->dpa_res || !resource_size(cxled->dpa_res))
2698+
return 0;
2699+
2700+
if (dpa > cxled->dpa_res->end || dpa < cxled->dpa_res->start)
2701+
return 0;
2702+
2703+
dev_dbg(dev, "dpa:0x%llx mapped in region:%s\n", dpa,
2704+
dev_name(&cxled->cxld.region->dev));
2705+
2706+
ctx->cxlr = cxled->cxld.region;
2707+
2708+
return 1;
2709+
}
2710+
2711+
struct cxl_region *cxl_dpa_to_region(const struct cxl_memdev *cxlmd, u64 dpa)
2712+
{
2713+
struct cxl_dpa_to_region_context ctx;
2714+
struct cxl_port *port;
2715+
2716+
ctx = (struct cxl_dpa_to_region_context) {
2717+
.dpa = dpa,
2718+
};
2719+
port = cxlmd->endpoint;
2720+
if (port && is_cxl_endpoint(port) && cxl_num_decoders_committed(port))
2721+
device_for_each_child(&port->dev, &ctx, __cxl_dpa_to_region);
2722+
2723+
return ctx.cxlr;
2724+
}
2725+
2726+
static bool cxl_is_hpa_in_range(u64 hpa, struct cxl_region *cxlr, int pos)
2727+
{
2728+
struct cxl_region_params *p = &cxlr->params;
2729+
int gran = p->interleave_granularity;
2730+
int ways = p->interleave_ways;
2731+
u64 offset;
2732+
2733+
/* Is the hpa within this region at all */
2734+
if (hpa < p->res->start || hpa > p->res->end) {
2735+
dev_dbg(&cxlr->dev,
2736+
"Addr trans fail: hpa 0x%llx not in region\n", hpa);
2737+
return false;
2738+
}
2739+
2740+
/* Is the hpa in an expected chunk for its pos(-ition) */
2741+
offset = hpa - p->res->start;
2742+
offset = do_div(offset, gran * ways);
2743+
if ((offset >= pos * gran) && (offset < (pos + 1) * gran))
2744+
return true;
2745+
2746+
dev_dbg(&cxlr->dev,
2747+
"Addr trans fail: hpa 0x%llx not in expected chunk\n", hpa);
2748+
2749+
return false;
2750+
}
2751+
2752+
static u64 cxl_dpa_to_hpa(u64 dpa, struct cxl_region *cxlr,
2753+
struct cxl_endpoint_decoder *cxled)
2754+
{
2755+
u64 dpa_offset, hpa_offset, bits_upper, mask_upper, hpa;
2756+
struct cxl_region_params *p = &cxlr->params;
2757+
int pos = cxled->pos;
2758+
u16 eig = 0;
2759+
u8 eiw = 0;
2760+
2761+
ways_to_eiw(p->interleave_ways, &eiw);
2762+
granularity_to_eig(p->interleave_granularity, &eig);
2763+
2764+
/*
2765+
* The device position in the region interleave set was removed
2766+
* from the offset at HPA->DPA translation. To reconstruct the
2767+
* HPA, place the 'pos' in the offset.
2768+
*
2769+
* The placement of 'pos' in the HPA is determined by interleave
2770+
* ways and granularity and is defined in the CXL Spec 3.0 Section
2771+
* 8.2.4.19.13 Implementation Note: Device Decode Logic
2772+
*/
2773+
2774+
/* Remove the dpa base */
2775+
dpa_offset = dpa - cxl_dpa_resource_start(cxled);
2776+
2777+
mask_upper = GENMASK_ULL(51, eig + 8);
2778+
2779+
if (eiw < 8) {
2780+
hpa_offset = (dpa_offset & mask_upper) << eiw;
2781+
hpa_offset |= pos << (eig + 8);
2782+
} else {
2783+
bits_upper = (dpa_offset & mask_upper) >> (eig + 8);
2784+
bits_upper = bits_upper * 3;
2785+
hpa_offset = ((bits_upper << (eiw - 8)) + pos) << (eig + 8);
2786+
}
2787+
2788+
/* The lower bits remain unchanged */
2789+
hpa_offset |= dpa_offset & GENMASK_ULL(eig + 7, 0);
2790+
2791+
/* Apply the hpa_offset to the region base address */
2792+
hpa = hpa_offset + p->res->start;
2793+
2794+
if (!cxl_is_hpa_in_range(hpa, cxlr, cxled->pos))
2795+
return ULLONG_MAX;
2796+
2797+
return hpa;
2798+
}
2799+
2800+
u64 cxl_trace_hpa(struct cxl_region *cxlr, const struct cxl_memdev *cxlmd,
2801+
u64 dpa)
2802+
{
2803+
struct cxl_region_params *p = &cxlr->params;
2804+
struct cxl_endpoint_decoder *cxled = NULL;
2805+
2806+
for (int i = 0; i < p->nr_targets; i++) {
2807+
cxled = p->targets[i];
2808+
if (cxlmd == cxled_to_memdev(cxled))
2809+
break;
2810+
}
2811+
if (!cxled || cxlmd != cxled_to_memdev(cxled))
2812+
return ULLONG_MAX;
2813+
2814+
return cxl_dpa_to_hpa(dpa, cxlr, cxled);
2815+
}
2816+
26822817
static struct lock_class_key cxl_pmem_region_key;
26832818

26842819
static struct cxl_pmem_region *cxl_pmem_region_alloc(struct cxl_region *cxlr)

drivers/cxl/core/trace.c

Lines changed: 0 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -6,94 +6,3 @@
66

77
#define CREATE_TRACE_POINTS
88
#include "trace.h"
9-
10-
static bool cxl_is_hpa_in_range(u64 hpa, struct cxl_region *cxlr, int pos)
11-
{
12-
struct cxl_region_params *p = &cxlr->params;
13-
int gran = p->interleave_granularity;
14-
int ways = p->interleave_ways;
15-
u64 offset;
16-
17-
/* Is the hpa within this region at all */
18-
if (hpa < p->res->start || hpa > p->res->end) {
19-
dev_dbg(&cxlr->dev,
20-
"Addr trans fail: hpa 0x%llx not in region\n", hpa);
21-
return false;
22-
}
23-
24-
/* Is the hpa in an expected chunk for its pos(-ition) */
25-
offset = hpa - p->res->start;
26-
offset = do_div(offset, gran * ways);
27-
if ((offset >= pos * gran) && (offset < (pos + 1) * gran))
28-
return true;
29-
30-
dev_dbg(&cxlr->dev,
31-
"Addr trans fail: hpa 0x%llx not in expected chunk\n", hpa);
32-
33-
return false;
34-
}
35-
36-
static u64 cxl_dpa_to_hpa(u64 dpa, struct cxl_region *cxlr,
37-
struct cxl_endpoint_decoder *cxled)
38-
{
39-
u64 dpa_offset, hpa_offset, bits_upper, mask_upper, hpa;
40-
struct cxl_region_params *p = &cxlr->params;
41-
int pos = cxled->pos;
42-
u16 eig = 0;
43-
u8 eiw = 0;
44-
45-
ways_to_eiw(p->interleave_ways, &eiw);
46-
granularity_to_eig(p->interleave_granularity, &eig);
47-
48-
/*
49-
* The device position in the region interleave set was removed
50-
* from the offset at HPA->DPA translation. To reconstruct the
51-
* HPA, place the 'pos' in the offset.
52-
*
53-
* The placement of 'pos' in the HPA is determined by interleave
54-
* ways and granularity and is defined in the CXL Spec 3.0 Section
55-
* 8.2.4.19.13 Implementation Note: Device Decode Logic
56-
*/
57-
58-
/* Remove the dpa base */
59-
dpa_offset = dpa - cxl_dpa_resource_start(cxled);
60-
61-
mask_upper = GENMASK_ULL(51, eig + 8);
62-
63-
if (eiw < 8) {
64-
hpa_offset = (dpa_offset & mask_upper) << eiw;
65-
hpa_offset |= pos << (eig + 8);
66-
} else {
67-
bits_upper = (dpa_offset & mask_upper) >> (eig + 8);
68-
bits_upper = bits_upper * 3;
69-
hpa_offset = ((bits_upper << (eiw - 8)) + pos) << (eig + 8);
70-
}
71-
72-
/* The lower bits remain unchanged */
73-
hpa_offset |= dpa_offset & GENMASK_ULL(eig + 7, 0);
74-
75-
/* Apply the hpa_offset to the region base address */
76-
hpa = hpa_offset + p->res->start;
77-
78-
if (!cxl_is_hpa_in_range(hpa, cxlr, cxled->pos))
79-
return ULLONG_MAX;
80-
81-
return hpa;
82-
}
83-
84-
u64 cxl_trace_hpa(struct cxl_region *cxlr, struct cxl_memdev *cxlmd,
85-
u64 dpa)
86-
{
87-
struct cxl_region_params *p = &cxlr->params;
88-
struct cxl_endpoint_decoder *cxled = NULL;
89-
90-
for (int i = 0; i < p->nr_targets; i++) {
91-
cxled = p->targets[i];
92-
if (cxlmd == cxled_to_memdev(cxled))
93-
break;
94-
}
95-
if (!cxled || cxlmd != cxled_to_memdev(cxled))
96-
return ULLONG_MAX;
97-
98-
return cxl_dpa_to_hpa(dpa, cxlr, cxled);
99-
}

0 commit comments

Comments
 (0)