Skip to content

Commit 5647847

Browse files
committed
Merge branch 'for-6.11/xor_fixes' into cxl-for-next
Series to fix XOR math for DPA to SPA translation - Refactor and fold cxl_trace_hpa() into cxl_dpa_to_hpa() - Complete DPA->HPA->SPA translation and correct XOR translation issue - Add new method to verify a CXL target position - Remove old method of CXL target position verifiation
2 parents 3a8617c + 8f55ada commit 5647847

File tree

7 files changed

+76
-112
lines changed

7 files changed

+76
-112
lines changed

drivers/cxl/acpi.c

Lines changed: 34 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -22,56 +22,42 @@ static const guid_t acpi_cxl_qtg_id_guid =
2222
GUID_INIT(0xF365F9A6, 0xA7DE, 0x4071,
2323
0xA6, 0x6A, 0xB4, 0x0C, 0x0B, 0x4F, 0x8E, 0x52);
2424

25-
/*
26-
* Find a targets entry (n) in the host bridge interleave list.
27-
* CXL Specification 3.0 Table 9-22
28-
*/
29-
static int cxl_xor_calc_n(u64 hpa, struct cxl_cxims_data *cximsd, int iw,
30-
int ig)
31-
{
32-
int i = 0, n = 0;
33-
u8 eiw;
34-
35-
/* IW: 2,4,6,8,12,16 begin building 'n' using xormaps */
36-
if (iw != 3) {
37-
for (i = 0; i < cximsd->nr_maps; i++)
38-
n |= (hweight64(hpa & cximsd->xormaps[i]) & 1) << i;
39-
}
40-
/* IW: 3,6,12 add a modulo calculation to 'n' */
41-
if (!is_power_of_2(iw)) {
42-
if (ways_to_eiw(iw, &eiw))
43-
return -1;
44-
hpa &= GENMASK_ULL(51, eiw + ig);
45-
n |= do_div(hpa, 3) << i;
46-
}
47-
return n;
48-
}
4925

50-
static struct cxl_dport *cxl_hb_xor(struct cxl_root_decoder *cxlrd, int pos)
26+
static u64 cxl_xor_hpa_to_spa(struct cxl_root_decoder *cxlrd, u64 hpa)
5127
{
5228
struct cxl_cxims_data *cximsd = cxlrd->platform_data;
53-
struct cxl_switch_decoder *cxlsd = &cxlrd->cxlsd;
54-
struct cxl_decoder *cxld = &cxlsd->cxld;
55-
int ig = cxld->interleave_granularity;
56-
int iw = cxld->interleave_ways;
57-
int n = 0;
58-
u64 hpa;
59-
60-
if (dev_WARN_ONCE(&cxld->dev,
61-
cxld->interleave_ways != cxlsd->nr_targets,
62-
"misconfigured root decoder\n"))
63-
return NULL;
29+
int hbiw = cxlrd->cxlsd.nr_targets;
30+
u64 val;
31+
int pos;
6432

65-
hpa = cxlrd->res->start + pos * ig;
33+
/* No xormaps for host bridge interleave ways of 1 or 3 */
34+
if (hbiw == 1 || hbiw == 3)
35+
return hpa;
6636

67-
/* Entry (n) is 0 for no interleave (iw == 1) */
68-
if (iw != 1)
69-
n = cxl_xor_calc_n(hpa, cximsd, iw, ig);
37+
/*
38+
* For root decoders using xormaps (hbiw: 2,4,6,8,12,16) restore
39+
* the position bit to its value before the xormap was applied at
40+
* HPA->DPA translation.
41+
*
42+
* pos is the lowest set bit in an XORMAP
43+
* val is the XORALLBITS(HPA & XORMAP)
44+
*
45+
* XORALLBITS: The CXL spec (3.1 Table 9-22) defines XORALLBITS
46+
* as an operation that outputs a single bit by XORing all the
47+
* bits in the input (hpa & xormap). Implement XORALLBITS using
48+
* hweight64(). If the hamming weight is even the XOR of those
49+
* bits results in val==0, if odd the XOR result is val==1.
50+
*/
7051

71-
if (n < 0)
72-
return NULL;
52+
for (int i = 0; i < cximsd->nr_maps; i++) {
53+
if (!cximsd->xormaps[i])
54+
continue;
55+
pos = __ffs(cximsd->xormaps[i]);
56+
val = (hweight64(hpa & cximsd->xormaps[i]) & 1);
57+
hpa = (hpa & ~(1ULL << pos)) | (val << pos);
58+
}
7359

74-
return cxlrd->cxlsd.target[n];
60+
return hpa;
7561
}
7662

7763
struct cxl_cxims_context {
@@ -361,7 +347,6 @@ static int __cxl_parse_cfmws(struct acpi_cedt_cfmws *cfmws,
361347
struct cxl_port *root_port = ctx->root_port;
362348
struct cxl_cxims_context cxims_ctx;
363349
struct device *dev = ctx->dev;
364-
cxl_calc_hb_fn cxl_calc_hb;
365350
struct cxl_decoder *cxld;
366351
unsigned int ways, i, ig;
367352
int rc;
@@ -389,13 +374,9 @@ static int __cxl_parse_cfmws(struct acpi_cedt_cfmws *cfmws,
389374
if (rc)
390375
return rc;
391376

392-
if (cfmws->interleave_arithmetic == ACPI_CEDT_CFMWS_ARITHMETIC_MODULO)
393-
cxl_calc_hb = cxl_hb_modulo;
394-
else
395-
cxl_calc_hb = cxl_hb_xor;
396-
397377
struct cxl_root_decoder *cxlrd __free(put_cxlrd) =
398-
cxl_root_decoder_alloc(root_port, ways, cxl_calc_hb);
378+
cxl_root_decoder_alloc(root_port, ways);
379+
399380
if (IS_ERR(cxlrd))
400381
return PTR_ERR(cxlrd);
401382

@@ -434,6 +415,9 @@ static int __cxl_parse_cfmws(struct acpi_cedt_cfmws *cfmws,
434415

435416
cxlrd->qos_class = cfmws->qtg_id;
436417

418+
if (cfmws->interleave_arithmetic == ACPI_CEDT_CFMWS_ARITHMETIC_XOR)
419+
cxlrd->hpa_to_spa = cxl_xor_hpa_to_spa;
420+
437421
rc = cxl_decoder_add(cxld, target_map);
438422
if (rc)
439423
return rc;

drivers/cxl/core/core.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,12 @@ int cxl_region_init(void);
2828
void cxl_region_exit(void);
2929
int cxl_get_poison_by_endpoint(struct cxl_port *port);
3030
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);
31+
u64 cxl_dpa_to_hpa(struct cxl_region *cxlr, const struct cxl_memdev *cxlmd,
32+
u64 dpa);
3333

3434
#else
35-
static inline u64
36-
cxl_trace_hpa(struct cxl_region *cxlr, const struct cxl_memdev *cxlmd, u64 dpa)
35+
static inline u64 cxl_dpa_to_hpa(struct cxl_region *cxlr,
36+
const struct cxl_memdev *cxlmd, u64 dpa)
3737
{
3838
return ULLONG_MAX;
3939
}

drivers/cxl/core/mbox.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -878,7 +878,7 @@ void cxl_event_trace_record(const struct cxl_memdev *cxlmd,
878878
dpa = le64_to_cpu(evt->media_hdr.phys_addr) & CXL_DPA_MASK;
879879
cxlr = cxl_dpa_to_region(cxlmd, dpa);
880880
if (cxlr)
881-
hpa = cxl_trace_hpa(cxlr, cxlmd, dpa);
881+
hpa = cxl_dpa_to_hpa(cxlr, cxlmd, dpa);
882882

883883
if (event_type == CXL_CPER_EVENT_GEN_MEDIA)
884884
trace_cxl_general_media(cxlmd, type, cxlr, hpa,

drivers/cxl/core/port.c

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1733,21 +1733,6 @@ static int decoder_populate_targets(struct cxl_switch_decoder *cxlsd,
17331733
return 0;
17341734
}
17351735

1736-
struct cxl_dport *cxl_hb_modulo(struct cxl_root_decoder *cxlrd, int pos)
1737-
{
1738-
struct cxl_switch_decoder *cxlsd = &cxlrd->cxlsd;
1739-
struct cxl_decoder *cxld = &cxlsd->cxld;
1740-
int iw;
1741-
1742-
iw = cxld->interleave_ways;
1743-
if (dev_WARN_ONCE(&cxld->dev, iw != cxlsd->nr_targets,
1744-
"misconfigured root decoder\n"))
1745-
return NULL;
1746-
1747-
return cxlrd->cxlsd.target[pos % iw];
1748-
}
1749-
EXPORT_SYMBOL_NS_GPL(cxl_hb_modulo, CXL);
1750-
17511736
static struct lock_class_key cxl_decoder_key;
17521737

17531738
/**
@@ -1807,16 +1792,14 @@ static int cxl_switch_decoder_init(struct cxl_port *port,
18071792
* cxl_root_decoder_alloc - Allocate a root level decoder
18081793
* @port: owning CXL root of this decoder
18091794
* @nr_targets: static number of downstream targets
1810-
* @calc_hb: which host bridge covers the n'th position by granularity
18111795
*
18121796
* Return: A new cxl decoder to be registered by cxl_decoder_add(). A
18131797
* 'CXL root' decoder is one that decodes from a top-level / static platform
18141798
* firmware description of CXL resources into a CXL standard decode
18151799
* topology.
18161800
*/
18171801
struct cxl_root_decoder *cxl_root_decoder_alloc(struct cxl_port *port,
1818-
unsigned int nr_targets,
1819-
cxl_calc_hb_fn calc_hb)
1802+
unsigned int nr_targets)
18201803
{
18211804
struct cxl_root_decoder *cxlrd;
18221805
struct cxl_switch_decoder *cxlsd;
@@ -1838,7 +1821,6 @@ struct cxl_root_decoder *cxl_root_decoder_alloc(struct cxl_port *port,
18381821
return ERR_PTR(rc);
18391822
}
18401823

1841-
cxlrd->calc_hb = calc_hb;
18421824
mutex_init(&cxlrd->range_lock);
18431825

18441826
cxld = &cxlsd->cxld;

drivers/cxl/core/region.c

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1560,10 +1560,13 @@ static int cxl_region_attach_position(struct cxl_region *cxlr,
15601560
const struct cxl_dport *dport, int pos)
15611561
{
15621562
struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
1563+
struct cxl_switch_decoder *cxlsd = &cxlrd->cxlsd;
1564+
struct cxl_decoder *cxld = &cxlsd->cxld;
1565+
int iw = cxld->interleave_ways;
15631566
struct cxl_port *iter;
15641567
int rc;
15651568

1566-
if (cxlrd->calc_hb(cxlrd, pos) != dport) {
1569+
if (dport != cxlrd->cxlsd.target[pos % iw]) {
15671570
dev_dbg(&cxlr->dev, "%s:%s invalid target position for %s\n",
15681571
dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev),
15691572
dev_name(&cxlrd->cxlsd.cxld.dev));
@@ -2759,20 +2762,13 @@ struct cxl_region *cxl_dpa_to_region(const struct cxl_memdev *cxlmd, u64 dpa)
27592762
return ctx.cxlr;
27602763
}
27612764

2762-
static bool cxl_is_hpa_in_range(u64 hpa, struct cxl_region *cxlr, int pos)
2765+
static bool cxl_is_hpa_in_chunk(u64 hpa, struct cxl_region *cxlr, int pos)
27632766
{
27642767
struct cxl_region_params *p = &cxlr->params;
27652768
int gran = p->interleave_granularity;
27662769
int ways = p->interleave_ways;
27672770
u64 offset;
27682771

2769-
/* Is the hpa within this region at all */
2770-
if (hpa < p->res->start || hpa > p->res->end) {
2771-
dev_dbg(&cxlr->dev,
2772-
"Addr trans fail: hpa 0x%llx not in region\n", hpa);
2773-
return false;
2774-
}
2775-
27762772
/* Is the hpa in an expected chunk for its pos(-ition) */
27772773
offset = hpa - p->res->start;
27782774
offset = do_div(offset, gran * ways);
@@ -2785,15 +2781,26 @@ static bool cxl_is_hpa_in_range(u64 hpa, struct cxl_region *cxlr, int pos)
27852781
return false;
27862782
}
27872783

2788-
static u64 cxl_dpa_to_hpa(u64 dpa, struct cxl_region *cxlr,
2789-
struct cxl_endpoint_decoder *cxled)
2784+
u64 cxl_dpa_to_hpa(struct cxl_region *cxlr, const struct cxl_memdev *cxlmd,
2785+
u64 dpa)
27902786
{
2787+
struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(cxlr->dev.parent);
27912788
u64 dpa_offset, hpa_offset, bits_upper, mask_upper, hpa;
27922789
struct cxl_region_params *p = &cxlr->params;
2793-
int pos = cxled->pos;
2790+
struct cxl_endpoint_decoder *cxled = NULL;
27942791
u16 eig = 0;
27952792
u8 eiw = 0;
2793+
int pos;
27962794

2795+
for (int i = 0; i < p->nr_targets; i++) {
2796+
cxled = p->targets[i];
2797+
if (cxlmd == cxled_to_memdev(cxled))
2798+
break;
2799+
}
2800+
if (!cxled || cxlmd != cxled_to_memdev(cxled))
2801+
return ULLONG_MAX;
2802+
2803+
pos = cxled->pos;
27972804
ways_to_eiw(p->interleave_ways, &eiw);
27982805
granularity_to_eig(p->interleave_granularity, &eig);
27992806

@@ -2827,27 +2834,21 @@ static u64 cxl_dpa_to_hpa(u64 dpa, struct cxl_region *cxlr,
28272834
/* Apply the hpa_offset to the region base address */
28282835
hpa = hpa_offset + p->res->start;
28292836

2830-
if (!cxl_is_hpa_in_range(hpa, cxlr, cxled->pos))
2831-
return ULLONG_MAX;
2837+
/* Root decoder translation overrides typical modulo decode */
2838+
if (cxlrd->hpa_to_spa)
2839+
hpa = cxlrd->hpa_to_spa(cxlrd, hpa);
28322840

2833-
return hpa;
2834-
}
2835-
2836-
u64 cxl_trace_hpa(struct cxl_region *cxlr, const struct cxl_memdev *cxlmd,
2837-
u64 dpa)
2838-
{
2839-
struct cxl_region_params *p = &cxlr->params;
2840-
struct cxl_endpoint_decoder *cxled = NULL;
2841-
2842-
for (int i = 0; i < p->nr_targets; i++) {
2843-
cxled = p->targets[i];
2844-
if (cxlmd == cxled_to_memdev(cxled))
2845-
break;
2841+
if (hpa < p->res->start || hpa > p->res->end) {
2842+
dev_dbg(&cxlr->dev,
2843+
"Addr trans fail: hpa 0x%llx not in region\n", hpa);
2844+
return ULLONG_MAX;
28462845
}
2847-
if (!cxled || cxlmd != cxled_to_memdev(cxled))
2846+
2847+
/* Simple chunk check, by pos & gran, only applies to modulo decodes */
2848+
if (!cxlrd->hpa_to_spa && (!cxl_is_hpa_in_chunk(hpa, cxlr, pos)))
28482849
return ULLONG_MAX;
28492850

2850-
return cxl_dpa_to_hpa(dpa, cxlr, cxled);
2851+
return hpa;
28512852
}
28522853

28532854
static struct lock_class_key cxl_pmem_region_key;

drivers/cxl/core/trace.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -704,8 +704,8 @@ TRACE_EVENT(cxl_poison,
704704
if (cxlr) {
705705
__assign_str(region);
706706
memcpy(__entry->uuid, &cxlr->params.uuid, 16);
707-
__entry->hpa = cxl_trace_hpa(cxlr, cxlmd,
708-
__entry->dpa);
707+
__entry->hpa = cxl_dpa_to_hpa(cxlr, cxlmd,
708+
__entry->dpa);
709709
} else {
710710
__assign_str(region);
711711
memset(__entry->uuid, 0, 16);

drivers/cxl/cxl.h

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -432,14 +432,13 @@ struct cxl_switch_decoder {
432432
};
433433

434434
struct cxl_root_decoder;
435-
typedef struct cxl_dport *(*cxl_calc_hb_fn)(struct cxl_root_decoder *cxlrd,
436-
int pos);
435+
typedef u64 (*cxl_hpa_to_spa_fn)(struct cxl_root_decoder *cxlrd, u64 hpa);
437436

438437
/**
439438
* struct cxl_root_decoder - Static platform CXL address decoder
440439
* @res: host / parent resource for region allocations
441440
* @region_id: region id for next region provisioning event
442-
* @calc_hb: which host bridge covers the n'th position by granularity
441+
* @hpa_to_spa: translate CXL host-physical-address to Platform system-physical-address
443442
* @platform_data: platform specific configuration data
444443
* @range_lock: sync region autodiscovery by address range
445444
* @qos_class: QoS performance class cookie
@@ -448,7 +447,7 @@ typedef struct cxl_dport *(*cxl_calc_hb_fn)(struct cxl_root_decoder *cxlrd,
448447
struct cxl_root_decoder {
449448
struct resource *res;
450449
atomic_t region_id;
451-
cxl_calc_hb_fn calc_hb;
450+
cxl_hpa_to_spa_fn hpa_to_spa;
452451
void *platform_data;
453452
struct mutex range_lock;
454453
int qos_class;
@@ -774,9 +773,7 @@ bool is_root_decoder(struct device *dev);
774773
bool is_switch_decoder(struct device *dev);
775774
bool is_endpoint_decoder(struct device *dev);
776775
struct cxl_root_decoder *cxl_root_decoder_alloc(struct cxl_port *port,
777-
unsigned int nr_targets,
778-
cxl_calc_hb_fn calc_hb);
779-
struct cxl_dport *cxl_hb_modulo(struct cxl_root_decoder *cxlrd, int pos);
776+
unsigned int nr_targets);
780777
struct cxl_switch_decoder *cxl_switch_decoder_alloc(struct cxl_port *port,
781778
unsigned int nr_targets);
782779
int cxl_decoder_add(struct cxl_decoder *cxld, int *target_map);

0 commit comments

Comments
 (0)