* [PATCH 0/2] hw/cxl: Support emulating 4 HDM decoders throughout topology
@ 2023-09-04 16:47 Jonathan Cameron via
2023-09-04 16:47 ` [PATCH 1/2] hw/cxl: Add utility functions decoder interleave ways and target count Jonathan Cameron via
2023-09-04 16:47 ` [PATCH 2/2] hw/cxl: Support 4 HDM decoders at all levels of topology Jonathan Cameron via
0 siblings, 2 replies; 10+ messages in thread
From: Jonathan Cameron via @ 2023-09-04 16:47 UTC (permalink / raw)
To: qemu-devel, Michael Tsirkin, Fan Ni, linux-cxl
Cc: Dave Jiang, Philippe Mathieu-Daudé, linuxarm
For initial CXL emulation / kernel driver bring up a single Host-managed
Device Memory (HDM) decoder instance was sufficient as it let us test the
basic region creation code etc. More complex testing appropriate today
requires a more realistic configuration with multiple decoders.
The Linux kernel will use separate decoders for each memory type (and
shortly per DCD region) and for each interleave set within a memory type
or DCD region. 4 decoders are sufficient for most test cases today but
we may need to grow these further in future.
This patch set already allowed us to identify one kernel bug which is
now fixed.
https://lore.kernel.org/linux-cxl/168696507968.3590522.14484000711718573626.stgit@dwillia2-xfh.jf.intel.com/
Note that, whilst I'm proposing this series for upstream (based on
priorities of what we have out of tree) it hasn't previously been posted
so needs review. (I failed to send it out previously)
Based on: [PATCH 0/4] hw/cxl: Minor CXL emulation fixes and cleanup
Based on: [PATCH v2 0/3] hw/cxl: Add dummy ACPI QTG DSM
Based on: Message ID: 20230904132806.6094-1-Jonathan.Cameron@huawei.com
Based on: Message ID: 20230904161847.18468-1-Jonathan.Cameron@huawei.com
Jonathan Cameron (2):
hw/cxl: Add utility functions decoder interleave ways and target
count.
hw/cxl: Support 4 HDM decoders at all levels of topology
include/hw/cxl/cxl_component.h | 21 ++++++++
hw/cxl/cxl-component-utils.c | 43 +++++++++++----
hw/cxl/cxl-host.c | 65 +++++++++++++++--------
hw/mem/cxl_type3.c | 97 +++++++++++++++++++++++-----------
4 files changed, 164 insertions(+), 62 deletions(-)
--
2.39.2
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/2] hw/cxl: Add utility functions decoder interleave ways and target count.
2023-09-04 16:47 [PATCH 0/2] hw/cxl: Support emulating 4 HDM decoders throughout topology Jonathan Cameron via
@ 2023-09-04 16:47 ` Jonathan Cameron via
2023-09-04 18:26 ` Philippe Mathieu-Daudé
2023-09-04 16:47 ` [PATCH 2/2] hw/cxl: Support 4 HDM decoders at all levels of topology Jonathan Cameron via
1 sibling, 1 reply; 10+ messages in thread
From: Jonathan Cameron via @ 2023-09-04 16:47 UTC (permalink / raw)
To: qemu-devel, Michael Tsirkin, Fan Ni, linux-cxl
Cc: Dave Jiang, Philippe Mathieu-Daudé, linuxarm
As an encoded version of these key configuration parameters is
a register, provide functions to extract it again so as to avoid
the need for duplicating the storage.
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
include/hw/cxl/cxl_component.h | 14 ++++++++++++++
hw/cxl/cxl-component-utils.c | 17 +++++++++++++++++
2 files changed, 31 insertions(+)
diff --git a/include/hw/cxl/cxl_component.h b/include/hw/cxl/cxl_component.h
index 42c7e581a7..f0ad9cf7de 100644
--- a/include/hw/cxl/cxl_component.h
+++ b/include/hw/cxl/cxl_component.h
@@ -238,7 +238,21 @@ static inline int cxl_decoder_count_enc(int count)
return 0;
}
+static inline int cxl_decoder_count_dec(int enc_cnt)
+{
+ switch (enc_cnt) {
+ case 0: return 1;
+ case 1: return 2;
+ case 2: return 4;
+ case 3: return 6;
+ case 4: return 8;
+ case 5: return 10;
+ }
+ return 0;
+}
+
uint8_t cxl_interleave_ways_enc(int iw, Error **errp);
+int cxl_interleave_ways_dec(uint8_t iw_enc, Error **errp);
uint8_t cxl_interleave_granularity_enc(uint64_t gran, Error **errp);
static inline hwaddr cxl_decode_ig(int ig)
diff --git a/hw/cxl/cxl-component-utils.c b/hw/cxl/cxl-component-utils.c
index 378f1082ce..e96398e8af 100644
--- a/hw/cxl/cxl-component-utils.c
+++ b/hw/cxl/cxl-component-utils.c
@@ -392,6 +392,23 @@ uint8_t cxl_interleave_ways_enc(int iw, Error **errp)
}
}
+int cxl_interleave_ways_dec(uint8_t iw_enc, Error **errp)
+{
+ switch (iw_enc) {
+ case 0x0: return 1;
+ case 0x1: return 2;
+ case 0x2: return 4;
+ case 0x3: return 8;
+ case 0x4: return 16;
+ case 0x8: return 3;
+ case 0x9: return 6;
+ case 0xa: return 12;
+ default:
+ error_setg(errp, "Encoded interleave ways: %d not supported", iw_enc);
+ return 0;
+ }
+}
+
uint8_t cxl_interleave_granularity_enc(uint64_t gran, Error **errp)
{
switch (gran) {
--
2.39.2
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/2] hw/cxl: Support 4 HDM decoders at all levels of topology
2023-09-04 16:47 [PATCH 0/2] hw/cxl: Support emulating 4 HDM decoders throughout topology Jonathan Cameron via
2023-09-04 16:47 ` [PATCH 1/2] hw/cxl: Add utility functions decoder interleave ways and target count Jonathan Cameron via
@ 2023-09-04 16:47 ` Jonathan Cameron via
2023-09-04 18:36 ` Philippe Mathieu-Daudé
1 sibling, 1 reply; 10+ messages in thread
From: Jonathan Cameron via @ 2023-09-04 16:47 UTC (permalink / raw)
To: qemu-devel, Michael Tsirkin, Fan Ni, linux-cxl
Cc: Dave Jiang, Philippe Mathieu-Daudé, linuxarm
Support these decoders in CXL host bridges (pxb-cxl), CXL Switch USP
and CXL Type 3 end points.
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
Note there is a fix in here for a wrong increment that had
no impact when there was only one HDM decoder.
include/hw/cxl/cxl_component.h | 7 +++
hw/cxl/cxl-component-utils.c | 26 +++++----
hw/cxl/cxl-host.c | 65 +++++++++++++++--------
hw/mem/cxl_type3.c | 97 +++++++++++++++++++++++-----------
4 files changed, 133 insertions(+), 62 deletions(-)
diff --git a/include/hw/cxl/cxl_component.h b/include/hw/cxl/cxl_component.h
index f0ad9cf7de..c5a93b2cec 100644
--- a/include/hw/cxl/cxl_component.h
+++ b/include/hw/cxl/cxl_component.h
@@ -135,6 +135,10 @@ REG32(CXL_RAS_ERR_HEADER0, CXL_RAS_REGISTERS_OFFSET + 0x18)
REG32(CXL_HDM_DECODER##n##_TARGET_LIST_LO, \
CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x24) \
REG32(CXL_HDM_DECODER##n##_TARGET_LIST_HI, \
+ CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x28) \
+ REG32(CXL_HDM_DECODER##n##_DPA_SKIP_LO, \
+ CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x24) \
+ REG32(CXL_HDM_DECODER##n##_DPA_SKIP_HI, \
CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x28)
REG32(CXL_HDM_DECODER_CAPABILITY, CXL_HDM_REGISTERS_OFFSET)
@@ -148,6 +152,9 @@ REG32(CXL_HDM_DECODER_GLOBAL_CONTROL, CXL_HDM_REGISTERS_OFFSET + 4)
FIELD(CXL_HDM_DECODER_GLOBAL_CONTROL, HDM_DECODER_ENABLE, 1, 1)
HDM_DECODER_INIT(0);
+HDM_DECODER_INIT(1);
+HDM_DECODER_INIT(2);
+HDM_DECODER_INIT(3);
/* 8.2.5.13 - CXL Extended Security Capability Structure (Root complex only) */
#define EXTSEC_ENTRY_MAX 256
diff --git a/hw/cxl/cxl-component-utils.c b/hw/cxl/cxl-component-utils.c
index e96398e8af..79b9369756 100644
--- a/hw/cxl/cxl-component-utils.c
+++ b/hw/cxl/cxl-component-utils.c
@@ -42,6 +42,9 @@ static void dumb_hdm_handler(CXLComponentState *cxl_cstate, hwaddr offset,
switch (offset) {
case A_CXL_HDM_DECODER0_CTRL:
+ case A_CXL_HDM_DECODER1_CTRL:
+ case A_CXL_HDM_DECODER2_CTRL:
+ case A_CXL_HDM_DECODER3_CTRL:
should_commit = FIELD_EX32(value, CXL_HDM_DECODER0_CTRL, COMMIT);
should_uncommit = !should_commit;
break;
@@ -81,7 +84,7 @@ static void cxl_cache_mem_write_reg(void *opaque, hwaddr offset, uint64_t value,
}
if (offset >= A_CXL_HDM_DECODER_CAPABILITY &&
- offset <= A_CXL_HDM_DECODER0_TARGET_LIST_HI) {
+ offset <= A_CXL_HDM_DECODER3_TARGET_LIST_HI) {
dumb_hdm_handler(cxl_cstate, offset, value);
} else {
cregs->cache_mem_registers[offset / sizeof(*cregs->cache_mem_registers)] = value;
@@ -161,7 +164,7 @@ static void ras_init_common(uint32_t *reg_state, uint32_t *write_msk)
static void hdm_init_common(uint32_t *reg_state, uint32_t *write_msk,
enum reg_type type)
{
- int decoder_count = 1;
+ int decoder_count = 4;
int i;
ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, DECODER_COUNT,
@@ -174,19 +177,22 @@ static void hdm_init_common(uint32_t *reg_state, uint32_t *write_msk,
HDM_DECODER_ENABLE, 0);
write_msk[R_CXL_HDM_DECODER_GLOBAL_CONTROL] = 0x3;
for (i = 0; i < decoder_count; i++) {
- write_msk[R_CXL_HDM_DECODER0_BASE_LO + i * 0x20] = 0xf0000000;
- write_msk[R_CXL_HDM_DECODER0_BASE_HI + i * 0x20] = 0xffffffff;
- write_msk[R_CXL_HDM_DECODER0_SIZE_LO + i * 0x20] = 0xf0000000;
- write_msk[R_CXL_HDM_DECODER0_SIZE_HI + i * 0x20] = 0xffffffff;
- write_msk[R_CXL_HDM_DECODER0_CTRL + i * 0x20] = 0x13ff;
+ write_msk[R_CXL_HDM_DECODER0_BASE_LO + i * 0x20 / 4] = 0xf0000000;
+ write_msk[R_CXL_HDM_DECODER0_BASE_HI + i * 0x20 / 4] = 0xffffffff;
+ write_msk[R_CXL_HDM_DECODER0_SIZE_LO + i * 0x20 / 4] = 0xf0000000;
+ write_msk[R_CXL_HDM_DECODER0_SIZE_HI + i * 0x20 / 4] = 0xffffffff;
+ write_msk[R_CXL_HDM_DECODER0_CTRL + i * 0x20 / 4] = 0x13ff;
if (type == CXL2_DEVICE ||
type == CXL2_TYPE3_DEVICE ||
type == CXL2_LOGICAL_DEVICE) {
- write_msk[R_CXL_HDM_DECODER0_TARGET_LIST_LO + i * 0x20] = 0xf0000000;
+ write_msk[R_CXL_HDM_DECODER0_TARGET_LIST_LO + i * 0x20 / 4] =
+ 0xf0000000;
} else {
- write_msk[R_CXL_HDM_DECODER0_TARGET_LIST_LO + i * 0x20] = 0xffffffff;
+ write_msk[R_CXL_HDM_DECODER0_TARGET_LIST_LO + i * 0x20 / 4] =
+ 0xffffffff;
}
- write_msk[R_CXL_HDM_DECODER0_TARGET_LIST_HI + i * 0x20] = 0xffffffff;
+ write_msk[R_CXL_HDM_DECODER0_TARGET_LIST_HI + i * 0x20 / 4] =
+ 0xffffffff;
}
}
diff --git a/hw/cxl/cxl-host.c b/hw/cxl/cxl-host.c
index f0920da956..e71b70d5b0 100644
--- a/hw/cxl/cxl-host.c
+++ b/hw/cxl/cxl-host.c
@@ -97,33 +97,56 @@ void cxl_fmws_link_targets(CXLState *cxl_state, Error **errp)
}
}
-/* TODO: support, multiple hdm decoders */
static bool cxl_hdm_find_target(uint32_t *cache_mem, hwaddr addr,
uint8_t *target)
{
- uint32_t ctrl;
- uint32_t ig_enc;
- uint32_t iw_enc;
- uint32_t target_idx;
-
- ctrl = cache_mem[R_CXL_HDM_DECODER0_CTRL];
- if (!FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, COMMITTED)) {
- return false;
- }
-
- ig_enc = FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, IG);
- iw_enc = FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, IW);
- target_idx = (addr / cxl_decode_ig(ig_enc)) % (1 << iw_enc);
+ bool found = false;
+ int i;
+ uint32_t cap;
+
+ cap = ldl_le_p(cache_mem + R_CXL_HDM_DECODER_CAPABILITY);
+ for (i = 0;
+ i < cxl_decoder_count_dec(FIELD_EX32(cap, CXL_HDM_DECODER_CAPABILITY,
+ DECODER_COUNT));
+ i++) {
+ uint32_t ctrl, ig_enc, iw_enc, target_idx;
+ uint32_t low, high;
+ uint64_t base, size;
+
+ low = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_BASE_LO + i * 0x20 / 4);
+ high = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_BASE_HI + i * 0x20 / 4);
+ base = (low & 0xf0000000) | ((uint64_t)high << 32);
+ low = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_SIZE_LO + i * 0x20 / 4);
+ high = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_SIZE_HI + i * 0x20 / 4);
+ size = (low & 0xf0000000) | ((uint64_t)high << 32);
+ if (addr < base || addr >= base + size) {
+ continue;
+ }
- if (target_idx < 4) {
- *target = extract32(cache_mem[R_CXL_HDM_DECODER0_TARGET_LIST_LO],
- target_idx * 8, 8);
- } else {
- *target = extract32(cache_mem[R_CXL_HDM_DECODER0_TARGET_LIST_HI],
- (target_idx - 4) * 8, 8);
+ ctrl = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL + i * 0x20 / 4);
+ if (!FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, COMMITTED)) {
+ return false;
+ }
+ found = true;
+ ig_enc = FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, IG);
+ iw_enc = FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, IW);
+ target_idx = (addr / cxl_decode_ig(ig_enc)) % (1 << iw_enc);
+
+ if (target_idx < 4) {
+ uint32_t val = ldl_le_p(cache_mem +
+ R_CXL_HDM_DECODER0_TARGET_LIST_LO +
+ i * 0x20 / 4);
+ *target = extract32(val, target_idx * 8, 8);
+ } else {
+ uint32_t val = ldl_le_p(cache_mem +
+ R_CXL_HDM_DECODER0_TARGET_LIST_HI +
+ i * 0x20 / 4);
+ *target = extract32(val, (target_idx - 4) * 8, 8);
+ }
+ break;
}
- return true;
+ return found;
}
static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, hwaddr addr)
diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
index 4e314748d3..fdfdb84813 100644
--- a/hw/mem/cxl_type3.c
+++ b/hw/mem/cxl_type3.c
@@ -381,14 +381,12 @@ static void hdm_decoder_commit(CXLType3Dev *ct3d, int which)
uint32_t *cache_mem = cregs->cache_mem_registers;
uint32_t ctrl;
- assert(which == 0);
-
- ctrl = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL);
+ ctrl = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL + which * 0x20 / 4);
/* TODO: Sanity checks that the decoder is possible */
ctrl = FIELD_DP32(ctrl, CXL_HDM_DECODER0_CTRL, ERR, 0);
ctrl = FIELD_DP32(ctrl, CXL_HDM_DECODER0_CTRL, COMMITTED, 1);
- stl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL, ctrl);
+ stl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL + which * 0x20 / 4, ctrl);
}
static void hdm_decoder_uncommit(CXLType3Dev *ct3d, int which)
@@ -397,14 +395,12 @@ static void hdm_decoder_uncommit(CXLType3Dev *ct3d, int which)
uint32_t *cache_mem = cregs->cache_mem_registers;
uint32_t ctrl;
- assert(which == 0);
-
- ctrl = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL);
+ ctrl = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL + which * 0x20 / 4);
ctrl = FIELD_DP32(ctrl, CXL_HDM_DECODER0_CTRL, ERR, 0);
ctrl = FIELD_DP32(ctrl, CXL_HDM_DECODER0_CTRL, COMMITTED, 0);
- stl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL, ctrl);
+ stl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL + which * 0x20 / 4, ctrl);
}
static int ct3d_qmp_uncor_err_to_cxl(CxlUncorErrorType qmp_err)
@@ -487,6 +483,21 @@ static void ct3d_reg_write(void *opaque, hwaddr offset, uint64_t value,
should_uncommit = !should_commit;
which_hdm = 0;
break;
+ case A_CXL_HDM_DECODER1_CTRL:
+ should_commit = FIELD_EX32(value, CXL_HDM_DECODER0_CTRL, COMMIT);
+ should_uncommit = !should_commit;
+ which_hdm = 1;
+ break;
+ case A_CXL_HDM_DECODER2_CTRL:
+ should_commit = FIELD_EX32(value, CXL_HDM_DECODER0_CTRL, COMMIT);
+ should_uncommit = !should_commit;
+ which_hdm = 2;
+ break;
+ case A_CXL_HDM_DECODER3_CTRL:
+ should_commit = FIELD_EX32(value, CXL_HDM_DECODER0_CTRL, COMMIT);
+ should_uncommit = !should_commit;
+ which_hdm = 3;
+ break;
case A_CXL_RAS_UNC_ERR_STATUS:
{
uint32_t capctrl = ldl_le_p(cache_mem + R_CXL_RAS_ERR_CAP_CTRL);
@@ -758,36 +769,60 @@ static void ct3_exit(PCIDevice *pci_dev)
}
}
-/* TODO: Support multiple HDM decoders and DPA skip */
static bool cxl_type3_dpa(CXLType3Dev *ct3d, hwaddr host_addr, uint64_t *dpa)
{
uint32_t *cache_mem = ct3d->cxl_cstate.crb.cache_mem_registers;
- uint64_t decoder_base, decoder_size, hpa_offset;
- uint32_t hdm0_ctrl;
- int ig, iw;
+ uint32_t cap;
+ uint64_t dpa_base = 0;
+ int i;
- decoder_base = (((uint64_t)cache_mem[R_CXL_HDM_DECODER0_BASE_HI] << 32) |
- cache_mem[R_CXL_HDM_DECODER0_BASE_LO]);
- if ((uint64_t)host_addr < decoder_base) {
- return false;
- }
+ cap = ldl_le_p(cache_mem + R_CXL_HDM_DECODER_CAPABILITY);
+ for (i = 0; i < cxl_decoder_count_dec(FIELD_EX32(cap,
+ CXL_HDM_DECODER_CAPABILITY,
+ DECODER_COUNT));
+ i++) {
+ uint64_t decoder_base, decoder_size, hpa_offset, skip;
+ uint32_t hdm_ctrl, low, high;
+ int ig, iw;
+
+ low = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_BASE_LO + i * 0x20 / 4);
+ high = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_BASE_HI + i * 0x20 / 4);
+ decoder_base = ((uint64_t)high << 32) | (low & 0xf0000000);
+
+ low = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_SIZE_LO + i * 0x20 / 4);
+ high = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_SIZE_HI + i * 0x20 / 4);
+ decoder_size = ((uint64_t)high << 32) | (low & 0xf0000000);
+
+ low = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_DPA_SKIP_LO +
+ i * 0x20 / 4);
+ high = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_DPA_SKIP_HI +
+ i * 0x20 / 4);
+ skip = ((uint64_t)high << 32) | (low & 0xf0000000);
+ dpa_base += skip;
+
+ hpa_offset = (uint64_t)host_addr - decoder_base;
+
+ hdm_ctrl = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL + i * 0x20 / 4);
+ iw = FIELD_EX32(hdm_ctrl, CXL_HDM_DECODER0_CTRL, IW);
+ ig = FIELD_EX32(hdm_ctrl, CXL_HDM_DECODER0_CTRL, IG);
+ if (!FIELD_EX32(hdm_ctrl, CXL_HDM_DECODER0_CTRL, COMMITTED)) {
+ return false;
+ }
+ if (((uint64_t)host_addr < decoder_base) ||
+ (hpa_offset >= decoder_size)) {
+ dpa_base += decoder_size /
+ cxl_interleave_ways_dec(iw, &error_fatal);
+ continue;
+ }
- hpa_offset = (uint64_t)host_addr - decoder_base;
+ *dpa = dpa_base +
+ ((MAKE_64BIT_MASK(0, 8 + ig) & hpa_offset) |
+ ((MAKE_64BIT_MASK(8 + ig + iw, 64 - 8 - ig - iw) & hpa_offset)
+ >> iw));
- decoder_size = ((uint64_t)cache_mem[R_CXL_HDM_DECODER0_SIZE_HI] << 32) |
- cache_mem[R_CXL_HDM_DECODER0_SIZE_LO];
- if (hpa_offset >= decoder_size) {
- return false;
+ return true;
}
-
- hdm0_ctrl = cache_mem[R_CXL_HDM_DECODER0_CTRL];
- iw = FIELD_EX32(hdm0_ctrl, CXL_HDM_DECODER0_CTRL, IW);
- ig = FIELD_EX32(hdm0_ctrl, CXL_HDM_DECODER0_CTRL, IG);
-
- *dpa = (MAKE_64BIT_MASK(0, 8 + ig) & hpa_offset) |
- ((MAKE_64BIT_MASK(8 + ig + iw, 64 - 8 - ig - iw) & hpa_offset) >> iw);
-
- return true;
+ return false;
}
static int cxl_type3_hpa_to_as_and_dpa(CXLType3Dev *ct3d,
--
2.39.2
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] hw/cxl: Add utility functions decoder interleave ways and target count.
2023-09-04 16:47 ` [PATCH 1/2] hw/cxl: Add utility functions decoder interleave ways and target count Jonathan Cameron via
@ 2023-09-04 18:26 ` Philippe Mathieu-Daudé
2023-09-05 14:56 ` Jonathan Cameron via
0 siblings, 1 reply; 10+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-09-04 18:26 UTC (permalink / raw)
To: Jonathan Cameron, qemu-devel, Michael Tsirkin, Fan Ni, linux-cxl
Cc: Dave Jiang, linuxarm
On 4/9/23 18:47, Jonathan Cameron wrote:
> As an encoded version of these key configuration parameters is
> a register, provide functions to extract it again so as to avoid
> the need for duplicating the storage.
>
> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> ---
> include/hw/cxl/cxl_component.h | 14 ++++++++++++++
> hw/cxl/cxl-component-utils.c | 17 +++++++++++++++++
> 2 files changed, 31 insertions(+)
>
> diff --git a/include/hw/cxl/cxl_component.h b/include/hw/cxl/cxl_component.h
> index 42c7e581a7..f0ad9cf7de 100644
> --- a/include/hw/cxl/cxl_component.h
> +++ b/include/hw/cxl/cxl_component.h
> @@ -238,7 +238,21 @@ static inline int cxl_decoder_count_enc(int count)
> return 0;
> }
>
> +static inline int cxl_decoder_count_dec(int enc_cnt)
> +{
> + switch (enc_cnt) {
> + case 0: return 1;
> + case 1: return 2;
> + case 2: return 4;
> + case 3: return 6;
> + case 4: return 8;
> + case 5: return 10;
> + }
> + return 0;
> +}
Why inline?
Alternatively:
unsigned cxl_decoder_count_dec(unsigned enc_cnt)
{
return enc_cnt <= 5 ? 2 * enc_cnt : 0;
}
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] hw/cxl: Support 4 HDM decoders at all levels of topology
2023-09-04 16:47 ` [PATCH 2/2] hw/cxl: Support 4 HDM decoders at all levels of topology Jonathan Cameron via
@ 2023-09-04 18:36 ` Philippe Mathieu-Daudé
2023-09-05 15:44 ` Jonathan Cameron via
0 siblings, 1 reply; 10+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-09-04 18:36 UTC (permalink / raw)
To: Jonathan Cameron, qemu-devel, Michael Tsirkin, Fan Ni, linux-cxl
Cc: Dave Jiang, linuxarm
Hi Jonathan,
Few style comments inlined.
On 4/9/23 18:47, Jonathan Cameron wrote:
> Support these decoders in CXL host bridges (pxb-cxl), CXL Switch USP
> and CXL Type 3 end points.
>
> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> ---
> Note there is a fix in here for a wrong increment that had
> no impact when there was only one HDM decoder.
>
> include/hw/cxl/cxl_component.h | 7 +++
> hw/cxl/cxl-component-utils.c | 26 +++++----
> hw/cxl/cxl-host.c | 65 +++++++++++++++--------
> hw/mem/cxl_type3.c | 97 +++++++++++++++++++++++-----------
> 4 files changed, 133 insertions(+), 62 deletions(-)
>
> diff --git a/include/hw/cxl/cxl_component.h b/include/hw/cxl/cxl_component.h
> index f0ad9cf7de..c5a93b2cec 100644
> --- a/include/hw/cxl/cxl_component.h
> +++ b/include/hw/cxl/cxl_component.h
> @@ -135,6 +135,10 @@ REG32(CXL_RAS_ERR_HEADER0, CXL_RAS_REGISTERS_OFFSET + 0x18)
> REG32(CXL_HDM_DECODER##n##_TARGET_LIST_LO, \
> CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x24) \
> REG32(CXL_HDM_DECODER##n##_TARGET_LIST_HI, \
> + CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x28) \
> + REG32(CXL_HDM_DECODER##n##_DPA_SKIP_LO, \
> + CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x24) \
> + REG32(CXL_HDM_DECODER##n##_DPA_SKIP_HI, \
> CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x28)
>
> REG32(CXL_HDM_DECODER_CAPABILITY, CXL_HDM_REGISTERS_OFFSET)
> @@ -148,6 +152,9 @@ REG32(CXL_HDM_DECODER_GLOBAL_CONTROL, CXL_HDM_REGISTERS_OFFSET + 4)
> FIELD(CXL_HDM_DECODER_GLOBAL_CONTROL, HDM_DECODER_ENABLE, 1, 1)
>
> HDM_DECODER_INIT(0);
> +HDM_DECODER_INIT(1);
> +HDM_DECODER_INIT(2);
> +HDM_DECODER_INIT(3);
#define HDM_DECODER_COUNT 4
> /* 8.2.5.13 - CXL Extended Security Capability Structure (Root complex only) */
> #define EXTSEC_ENTRY_MAX 256
> diff --git a/hw/cxl/cxl-component-utils.c b/hw/cxl/cxl-component-utils.c
> index e96398e8af..79b9369756 100644
> --- a/hw/cxl/cxl-component-utils.c
> +++ b/hw/cxl/cxl-component-utils.c
> @@ -42,6 +42,9 @@ static void dumb_hdm_handler(CXLComponentState *cxl_cstate, hwaddr offset,
>
> switch (offset) {
> case A_CXL_HDM_DECODER0_CTRL:
> + case A_CXL_HDM_DECODER1_CTRL:
> + case A_CXL_HDM_DECODER2_CTRL:
> + case A_CXL_HDM_DECODER3_CTRL:
> should_commit = FIELD_EX32(value, CXL_HDM_DECODER0_CTRL, COMMIT);
> should_uncommit = !should_commit;
> break;
> @@ -81,7 +84,7 @@ static void cxl_cache_mem_write_reg(void *opaque, hwaddr offset, uint64_t value,
> }
>
> if (offset >= A_CXL_HDM_DECODER_CAPABILITY &&
> - offset <= A_CXL_HDM_DECODER0_TARGET_LIST_HI) {
> + offset <= A_CXL_HDM_DECODER3_TARGET_LIST_HI) {
> dumb_hdm_handler(cxl_cstate, offset, value);
> } else {
> cregs->cache_mem_registers[offset / sizeof(*cregs->cache_mem_registers)] = value;
> @@ -161,7 +164,7 @@ static void ras_init_common(uint32_t *reg_state, uint32_t *write_msk)
> static void hdm_init_common(uint32_t *reg_state, uint32_t *write_msk,
> enum reg_type type)
> {
> - int decoder_count = 1;
> + int decoder_count = 4;
unsigned decoder_count = HDM_DECODER_COUNT;
> int i;
>
> ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, DECODER_COUNT,
> @@ -174,19 +177,22 @@ static void hdm_init_common(uint32_t *reg_state, uint32_t *write_msk,
> HDM_DECODER_ENABLE, 0);
> write_msk[R_CXL_HDM_DECODER_GLOBAL_CONTROL] = 0x3;
> for (i = 0; i < decoder_count; i++) {
Alternatively:
for (i = 0; i < decoder_count; i++, write_msk += 8) {
write_msk[R_CXL_HDM_DECODER0_BASE_LO] = 0xf0000000;
> - write_msk[R_CXL_HDM_DECODER0_BASE_LO + i * 0x20] = 0xf0000000;
> - write_msk[R_CXL_HDM_DECODER0_BASE_HI + i * 0x20] = 0xffffffff;
> - write_msk[R_CXL_HDM_DECODER0_SIZE_LO + i * 0x20] = 0xf0000000;
> - write_msk[R_CXL_HDM_DECODER0_SIZE_HI + i * 0x20] = 0xffffffff;
> - write_msk[R_CXL_HDM_DECODER0_CTRL + i * 0x20] = 0x13ff;
> + write_msk[R_CXL_HDM_DECODER0_BASE_LO + i * 0x20 / 4] = 0xf0000000;
(this 0x20 / 4 bugs me a bit).
> + write_msk[R_CXL_HDM_DECODER0_BASE_HI + i * 0x20 / 4] = 0xffffffff;
> + write_msk[R_CXL_HDM_DECODER0_SIZE_LO + i * 0x20 / 4] = 0xf0000000;
> + write_msk[R_CXL_HDM_DECODER0_SIZE_HI + i * 0x20 / 4] = 0xffffffff;
> + write_msk[R_CXL_HDM_DECODER0_CTRL + i * 0x20 / 4] = 0x13ff;
> if (type == CXL2_DEVICE ||
> type == CXL2_TYPE3_DEVICE ||
> type == CXL2_LOGICAL_DEVICE) {
> - write_msk[R_CXL_HDM_DECODER0_TARGET_LIST_LO + i * 0x20] = 0xf0000000;
> + write_msk[R_CXL_HDM_DECODER0_TARGET_LIST_LO + i * 0x20 / 4] =
> + 0xf0000000;
> } else {
> - write_msk[R_CXL_HDM_DECODER0_TARGET_LIST_LO + i * 0x20] = 0xffffffff;
> + write_msk[R_CXL_HDM_DECODER0_TARGET_LIST_LO + i * 0x20 / 4] =
> + 0xffffffff;
> }
> - write_msk[R_CXL_HDM_DECODER0_TARGET_LIST_HI + i * 0x20] = 0xffffffff;
> + write_msk[R_CXL_HDM_DECODER0_TARGET_LIST_HI + i * 0x20 / 4] =
> + 0xffffffff;
> }
> }
>
> diff --git a/hw/cxl/cxl-host.c b/hw/cxl/cxl-host.c
> index f0920da956..e71b70d5b0 100644
> --- a/hw/cxl/cxl-host.c
> +++ b/hw/cxl/cxl-host.c
> @@ -97,33 +97,56 @@ void cxl_fmws_link_targets(CXLState *cxl_state, Error **errp)
> }
> }
>
> -/* TODO: support, multiple hdm decoders */
> static bool cxl_hdm_find_target(uint32_t *cache_mem, hwaddr addr,
> uint8_t *target)
> {
> - uint32_t ctrl;
> - uint32_t ig_enc;
> - uint32_t iw_enc;
> - uint32_t target_idx;
> -
> - ctrl = cache_mem[R_CXL_HDM_DECODER0_CTRL];
> - if (!FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, COMMITTED)) {
> - return false;
> - }
> -
> - ig_enc = FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, IG);
> - iw_enc = FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, IW);
> - target_idx = (addr / cxl_decode_ig(ig_enc)) % (1 << iw_enc);
> + bool found = false;
> + int i;
> + uint32_t cap;
> +
> + cap = ldl_le_p(cache_mem + R_CXL_HDM_DECODER_CAPABILITY);
unsigned count = cxl_decoder_count_dec(FIELD_EX32(cap,
CXL_HDM_DECODER_CAPABILITY,
DECODER_COUNT));
for (i = 0; i < count; ...)
> + for (i = 0;
> + i < cxl_decoder_count_dec(FIELD_EX32(cap, CXL_HDM_DECODER_CAPABILITY,
> + DECODER_COUNT));
> + i++) {
> + uint32_t ctrl, ig_enc, iw_enc, target_idx;
> + uint32_t low, high;
> + uint64_t base, size;
> +
> + low = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_BASE_LO + i * 0x20 / 4);
> + high = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_BASE_HI + i * 0x20 / 4);
> + base = (low & 0xf0000000) | ((uint64_t)high << 32);
> + low = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_SIZE_LO + i * 0x20 / 4);
> + high = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_SIZE_HI + i * 0x20 / 4);
> + size = (low & 0xf0000000) | ((uint64_t)high << 32);
> + if (addr < base || addr >= base + size) {
> + continue;
> + }
>
> - if (target_idx < 4) {
> - *target = extract32(cache_mem[R_CXL_HDM_DECODER0_TARGET_LIST_LO],
> - target_idx * 8, 8);
> - } else {
> - *target = extract32(cache_mem[R_CXL_HDM_DECODER0_TARGET_LIST_HI],
> - (target_idx - 4) * 8, 8);
> + ctrl = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL + i * 0x20 / 4);
> + if (!FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, COMMITTED)) {
> + return false;
> + }
> + found = true;
> + ig_enc = FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, IG);
> + iw_enc = FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, IW);
> + target_idx = (addr / cxl_decode_ig(ig_enc)) % (1 << iw_enc);
> +
> + if (target_idx < 4) {
> + uint32_t val = ldl_le_p(cache_mem +
> + R_CXL_HDM_DECODER0_TARGET_LIST_LO +
> + i * 0x20 / 4);
> + *target = extract32(val, target_idx * 8, 8);
> + } else {
> + uint32_t val = ldl_le_p(cache_mem +
> + R_CXL_HDM_DECODER0_TARGET_LIST_HI +
> + i * 0x20 / 4);
> + *target = extract32(val, (target_idx - 4) * 8, 8);
> + }
> + break;
> }
>
> - return true;
> + return found;
> }
>
> static PCIDevice *cxl_cfmws_find_device(CXLFixedWindow *fw, hwaddr addr)
> diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
> index 4e314748d3..fdfdb84813 100644
> --- a/hw/mem/cxl_type3.c
> +++ b/hw/mem/cxl_type3.c
> @@ -381,14 +381,12 @@ static void hdm_decoder_commit(CXLType3Dev *ct3d, int which)
> uint32_t *cache_mem = cregs->cache_mem_registers;
> uint32_t ctrl;
>
> - assert(which == 0);
> -
> - ctrl = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL);
> + ctrl = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL + which * 0x20 / 4);
> /* TODO: Sanity checks that the decoder is possible */
> ctrl = FIELD_DP32(ctrl, CXL_HDM_DECODER0_CTRL, ERR, 0);
> ctrl = FIELD_DP32(ctrl, CXL_HDM_DECODER0_CTRL, COMMITTED, 1);
>
> - stl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL, ctrl);
> + stl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL + which * 0x20 / 4, ctrl);
> }
>
> static void hdm_decoder_uncommit(CXLType3Dev *ct3d, int which)
> @@ -397,14 +395,12 @@ static void hdm_decoder_uncommit(CXLType3Dev *ct3d, int which)
> uint32_t *cache_mem = cregs->cache_mem_registers;
> uint32_t ctrl;
>
> - assert(which == 0);
> -
> - ctrl = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL);
> + ctrl = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL + which * 0x20 / 4);
>
> ctrl = FIELD_DP32(ctrl, CXL_HDM_DECODER0_CTRL, ERR, 0);
> ctrl = FIELD_DP32(ctrl, CXL_HDM_DECODER0_CTRL, COMMITTED, 0);
>
> - stl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL, ctrl);
> + stl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL + which * 0x20 / 4, ctrl);
> }
>
> static int ct3d_qmp_uncor_err_to_cxl(CxlUncorErrorType qmp_err)
> @@ -487,6 +483,21 @@ static void ct3d_reg_write(void *opaque, hwaddr offset, uint64_t value,
> should_uncommit = !should_commit;
> which_hdm = 0;
> break;
> + case A_CXL_HDM_DECODER1_CTRL:
> + should_commit = FIELD_EX32(value, CXL_HDM_DECODER0_CTRL, COMMIT);
> + should_uncommit = !should_commit;
> + which_hdm = 1;
> + break;
> + case A_CXL_HDM_DECODER2_CTRL:
> + should_commit = FIELD_EX32(value, CXL_HDM_DECODER0_CTRL, COMMIT);
> + should_uncommit = !should_commit;
> + which_hdm = 2;
> + break;
> + case A_CXL_HDM_DECODER3_CTRL:
> + should_commit = FIELD_EX32(value, CXL_HDM_DECODER0_CTRL, COMMIT);
> + should_uncommit = !should_commit;
> + which_hdm = 3;
> + break;
> case A_CXL_RAS_UNC_ERR_STATUS:
> {
> uint32_t capctrl = ldl_le_p(cache_mem + R_CXL_RAS_ERR_CAP_CTRL);
> @@ -758,36 +769,60 @@ static void ct3_exit(PCIDevice *pci_dev)
> }
> }
>
> -/* TODO: Support multiple HDM decoders and DPA skip */
> static bool cxl_type3_dpa(CXLType3Dev *ct3d, hwaddr host_addr, uint64_t *dpa)
> {
> uint32_t *cache_mem = ct3d->cxl_cstate.crb.cache_mem_registers;
> - uint64_t decoder_base, decoder_size, hpa_offset;
> - uint32_t hdm0_ctrl;
> - int ig, iw;
> + uint32_t cap;
> + uint64_t dpa_base = 0;
> + int i;
>
> - decoder_base = (((uint64_t)cache_mem[R_CXL_HDM_DECODER0_BASE_HI] << 32) |
> - cache_mem[R_CXL_HDM_DECODER0_BASE_LO]);
> - if ((uint64_t)host_addr < decoder_base) {
> - return false;
> - }
> + cap = ldl_le_p(cache_mem + R_CXL_HDM_DECODER_CAPABILITY);
> + for (i = 0; i < cxl_decoder_count_dec(FIELD_EX32(cap,
> + CXL_HDM_DECODER_CAPABILITY,
> + DECODER_COUNT));
> + i++) {
> + uint64_t decoder_base, decoder_size, hpa_offset, skip;
> + uint32_t hdm_ctrl, low, high;
> + int ig, iw;
> +
> + low = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_BASE_LO + i * 0x20 / 4);
> + high = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_BASE_HI + i * 0x20 / 4);
> + decoder_base = ((uint64_t)high << 32) | (low & 0xf0000000);
> +
> + low = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_SIZE_LO + i * 0x20 / 4);
> + high = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_SIZE_HI + i * 0x20 / 4);
> + decoder_size = ((uint64_t)high << 32) | (low & 0xf0000000);
> +
> + low = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_DPA_SKIP_LO +
> + i * 0x20 / 4);
> + high = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_DPA_SKIP_HI +
> + i * 0x20 / 4);
> + skip = ((uint64_t)high << 32) | (low & 0xf0000000);
> + dpa_base += skip;
> +
> + hpa_offset = (uint64_t)host_addr - decoder_base;
> +
> + hdm_ctrl = ldl_le_p(cache_mem + R_CXL_HDM_DECODER0_CTRL + i * 0x20 / 4);
> + iw = FIELD_EX32(hdm_ctrl, CXL_HDM_DECODER0_CTRL, IW);
> + ig = FIELD_EX32(hdm_ctrl, CXL_HDM_DECODER0_CTRL, IG);
> + if (!FIELD_EX32(hdm_ctrl, CXL_HDM_DECODER0_CTRL, COMMITTED)) {
> + return false;
> + }
> + if (((uint64_t)host_addr < decoder_base) ||
> + (hpa_offset >= decoder_size)) {
> + dpa_base += decoder_size /
> + cxl_interleave_ways_dec(iw, &error_fatal);
> + continue;
> + }
>
> - hpa_offset = (uint64_t)host_addr - decoder_base;
> + *dpa = dpa_base +
> + ((MAKE_64BIT_MASK(0, 8 + ig) & hpa_offset) |
> + ((MAKE_64BIT_MASK(8 + ig + iw, 64 - 8 - ig - iw) & hpa_offset)
> + >> iw));
>
> - decoder_size = ((uint64_t)cache_mem[R_CXL_HDM_DECODER0_SIZE_HI] << 32) |
> - cache_mem[R_CXL_HDM_DECODER0_SIZE_LO];
> - if (hpa_offset >= decoder_size) {
> - return false;
> + return true;
> }
> -
> - hdm0_ctrl = cache_mem[R_CXL_HDM_DECODER0_CTRL];
> - iw = FIELD_EX32(hdm0_ctrl, CXL_HDM_DECODER0_CTRL, IW);
> - ig = FIELD_EX32(hdm0_ctrl, CXL_HDM_DECODER0_CTRL, IG);
> -
> - *dpa = (MAKE_64BIT_MASK(0, 8 + ig) & hpa_offset) |
> - ((MAKE_64BIT_MASK(8 + ig + iw, 64 - 8 - ig - iw) & hpa_offset) >> iw);
> -
> - return true;
> + return false;
> }
>
> static int cxl_type3_hpa_to_as_and_dpa(CXLType3Dev *ct3d,
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] hw/cxl: Add utility functions decoder interleave ways and target count.
2023-09-04 18:26 ` Philippe Mathieu-Daudé
@ 2023-09-05 14:56 ` Jonathan Cameron via
2023-09-05 15:06 ` Jonathan Cameron via
0 siblings, 1 reply; 10+ messages in thread
From: Jonathan Cameron via @ 2023-09-05 14:56 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: qemu-devel, Michael Tsirkin, Fan Ni, linux-cxl, Dave Jiang,
linuxarm
On Mon, 4 Sep 2023 20:26:59 +0200
Philippe Mathieu-Daudé <philmd@linaro.org> wrote:
> On 4/9/23 18:47, Jonathan Cameron wrote:
> > As an encoded version of these key configuration parameters is
> > a register, provide functions to extract it again so as to avoid
> > the need for duplicating the storage.
> >
> > Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> > ---
> > include/hw/cxl/cxl_component.h | 14 ++++++++++++++
> > hw/cxl/cxl-component-utils.c | 17 +++++++++++++++++
> > 2 files changed, 31 insertions(+)
> >
> > diff --git a/include/hw/cxl/cxl_component.h b/include/hw/cxl/cxl_component.h
> > index 42c7e581a7..f0ad9cf7de 100644
> > --- a/include/hw/cxl/cxl_component.h
> > +++ b/include/hw/cxl/cxl_component.h
> > @@ -238,7 +238,21 @@ static inline int cxl_decoder_count_enc(int count)
> > return 0;
> > }
> >
> > +static inline int cxl_decoder_count_dec(int enc_cnt)
> > +{
> > + switch (enc_cnt) {
> > + case 0: return 1;
> > + case 1: return 2;
> > + case 2: return 4;
> > + case 3: return 6;
> > + case 4: return 8;
> > + case 5: return 10;
> > + }
> > + return 0;
> > +}
>
> Why inline?
>
Bad habit.
> Alternatively:
>
> unsigned cxl_decoder_count_dec(unsigned enc_cnt)
> {
> return enc_cnt <= 5 ? 2 * enc_cnt : 0;
It gets a little more fiddly than the code I'm proposing implies.
For Switches and Host Bridges larger values are defined
(we just don't emulate them yet and may never do so) and those
don't have a sensible mapping.
I guess there is no harm in adding the full decode however
which will make it more obvious why it was a switch statement.
> }
>
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] hw/cxl: Add utility functions decoder interleave ways and target count.
2023-09-05 14:56 ` Jonathan Cameron via
@ 2023-09-05 15:06 ` Jonathan Cameron via
2023-09-05 16:55 ` Philippe Mathieu-Daudé
0 siblings, 1 reply; 10+ messages in thread
From: Jonathan Cameron via @ 2023-09-05 15:06 UTC (permalink / raw)
To: Jonathan Cameron via
Cc: Jonathan Cameron, Philippe Mathieu-Daudé, Michael Tsirkin,
Fan Ni, linux-cxl, Dave Jiang, linuxarm
On Tue, 5 Sep 2023 15:56:39 +0100
Jonathan Cameron via <qemu-devel@nongnu.org> wrote:
> On Mon, 4 Sep 2023 20:26:59 +0200
> Philippe Mathieu-Daudé <philmd@linaro.org> wrote:
>
> > On 4/9/23 18:47, Jonathan Cameron wrote:
> > > As an encoded version of these key configuration parameters is
> > > a register, provide functions to extract it again so as to avoid
> > > the need for duplicating the storage.
> > >
> > > Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> > > ---
> > > include/hw/cxl/cxl_component.h | 14 ++++++++++++++
> > > hw/cxl/cxl-component-utils.c | 17 +++++++++++++++++
> > > 2 files changed, 31 insertions(+)
> > >
> > > diff --git a/include/hw/cxl/cxl_component.h b/include/hw/cxl/cxl_component.h
> > > index 42c7e581a7..f0ad9cf7de 100644
> > > --- a/include/hw/cxl/cxl_component.h
> > > +++ b/include/hw/cxl/cxl_component.h
> > > @@ -238,7 +238,21 @@ static inline int cxl_decoder_count_enc(int count)
> > > return 0;
> > > }
> > >
> > > +static inline int cxl_decoder_count_dec(int enc_cnt)
> > > +{
> > > + switch (enc_cnt) {
> > > + case 0: return 1;
> > > + case 1: return 2;
> > > + case 2: return 4;
> > > + case 3: return 6;
> > > + case 4: return 8;
> > > + case 5: return 10;
> > > + }
> > > + return 0;
> > > +}
> >
> > Why inline?
> >
>
> Bad habit.
Nope. I'm being slow. This is in a header so if I don't
mark it inline I get a bunch of defined but not used warnings.
Obviously I could move the implementation of this and the matching
encoding routines out of the header. I haven't done so for now.
>
>
> > Alternatively:
> >
> > unsigned cxl_decoder_count_dec(unsigned enc_cnt)
> > {
> > return enc_cnt <= 5 ? 2 * enc_cnt : 0;
>
> It gets a little more fiddly than the code I'm proposing implies.
> For Switches and Host Bridges larger values are defined
> (we just don't emulate them yet and may never do so) and those
> don't have a sensible mapping.
>
> I guess there is no harm in adding the full decode however
> which will make it more obvious why it was a switch statement.
>
> > }
> >
> >
>
>
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] hw/cxl: Support 4 HDM decoders at all levels of topology
2023-09-04 18:36 ` Philippe Mathieu-Daudé
@ 2023-09-05 15:44 ` Jonathan Cameron via
0 siblings, 0 replies; 10+ messages in thread
From: Jonathan Cameron via @ 2023-09-05 15:44 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: qemu-devel, Michael Tsirkin, Fan Ni, linux-cxl, Dave Jiang,
linuxarm
On Mon, 4 Sep 2023 20:36:02 +0200
Philippe Mathieu-Daudé <philmd@linaro.org> wrote:
> Hi Jonathan,
>
> Few style comments inlined.
>
> On 4/9/23 18:47, Jonathan Cameron wrote:
> > Support these decoders in CXL host bridges (pxb-cxl), CXL Switch USP
> > and CXL Type 3 end points.
> >
> > Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> > ---
Hi Philippe,
Thanks for the particularly quick reviews!
...
> > diff --git a/hw/cxl/cxl-component-utils.c b/hw/cxl/cxl-component-utils.c
> > index e96398e8af..79b9369756 100644
> > --- a/hw/cxl/cxl-component-utils.c
> > +++ b/hw/cxl/cxl-component-utils.c
> > @@ -42,6 +42,9 @@ static void dumb_hdm_handler(CXLComponentState *cxl_cstate, hwaddr offset,
> >
> > switch (offset) {
> > case A_CXL_HDM_DECODER0_CTRL:
> > + case A_CXL_HDM_DECODER1_CTRL:
> > + case A_CXL_HDM_DECODER2_CTRL:
> > + case A_CXL_HDM_DECODER3_CTRL:
> > should_commit = FIELD_EX32(value, CXL_HDM_DECODER0_CTRL, COMMIT);
> > should_uncommit = !should_commit;
> > break;
> > @@ -81,7 +84,7 @@ static void cxl_cache_mem_write_reg(void *opaque, hwaddr offset, uint64_t value,
> > }
> >
> > if (offset >= A_CXL_HDM_DECODER_CAPABILITY &&
> > - offset <= A_CXL_HDM_DECODER0_TARGET_LIST_HI) {
> > + offset <= A_CXL_HDM_DECODER3_TARGET_LIST_HI) {
> > dumb_hdm_handler(cxl_cstate, offset, value);
> > } else {
> > cregs->cache_mem_registers[offset / sizeof(*cregs->cache_mem_registers)] = value;
> > @@ -161,7 +164,7 @@ static void ras_init_common(uint32_t *reg_state, uint32_t *write_msk)
> > static void hdm_init_common(uint32_t *reg_state, uint32_t *write_msk,
> > enum reg_type type)
> > {
> > - int decoder_count = 1;
> > + int decoder_count = 4;
>
> unsigned decoder_count = HDM_DECODER_COUNT;
>
> > int i;
> >
> > ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, DECODER_COUNT,
> > @@ -174,19 +177,22 @@ static void hdm_init_common(uint32_t *reg_state, uint32_t *write_msk,
> > HDM_DECODER_ENABLE, 0);
> > write_msk[R_CXL_HDM_DECODER_GLOBAL_CONTROL] = 0x3;
> > for (i = 0; i < decoder_count; i++) {
>
> Alternatively:
>
> for (i = 0; i < decoder_count; i++, write_msk += 8) {
> write_msk[R_CXL_HDM_DECODER0_BASE_LO] = 0xf0000000;
That's a bit nasty and fragile given we are offsetting the base register than
indexing into it (so applying a later offset).
>
> > - write_msk[R_CXL_HDM_DECODER0_BASE_LO + i * 0x20] = 0xf0000000;
> > - write_msk[R_CXL_HDM_DECODER0_BASE_HI + i * 0x20] = 0xffffffff;
> > - write_msk[R_CXL_HDM_DECODER0_SIZE_LO + i * 0x20] = 0xf0000000;
> > - write_msk[R_CXL_HDM_DECODER0_SIZE_HI + i * 0x20] = 0xffffffff;
> > - write_msk[R_CXL_HDM_DECODER0_CTRL + i * 0x20] = 0x13ff;
> > + write_msk[R_CXL_HDM_DECODER0_BASE_LO + i * 0x20 / 4] = 0xf0000000;
>
> (this 0x20 / 4 bugs me a bit).
Instead, I've gone with a local variable which leaves me room for deriving
this based on the step between the registers for decoders 0 and 1.
hdm_inc = R_CXL_HDM_DECODER1_BASE_LO - R_CXL_HDM_DECODER0_BASE_LO;
I haven't added a define for this because it would probably have to be
long enough that it will cause line length problems :(
So it is replicated in a few different places which isn't ideal
but definitely better than the 0x20 / 4
>
> > + write_msk[R_CXL_HDM_DECODER0_BASE_HI + i * 0x20 / 4] = 0xffffffff;
> > + write_msk[R_CXL_HDM_DECODER0_SIZE_LO + i * 0x20 / 4] = 0xf0000000;
> > + write_msk[R_CXL_HDM_DECODER0_SIZE_HI + i * 0x20 / 4] = 0xffffffff;
> > + write_msk[R_CXL_HDM_DECODER0_CTRL + i * 0x20 / 4] = 0x13ff;
> > if (type == CXL2_DEVICE ||
> > type == CXL2_TYPE3_DEVICE ||
> > type == CXL2_LOGICAL_DEVICE) {
> > - write_msk[R_CXL_HDM_DECODER0_TARGET_LIST_LO + i * 0x20] = 0xf0000000;
> > + write_msk[R_CXL_HDM_DECODER0_TARGET_LIST_LO + i * 0x20 / 4] =
> > + 0xf0000000;
> > } else {
> > - write_msk[R_CXL_HDM_DECODER0_TARGET_LIST_LO + i * 0x20] = 0xffffffff;
> > + write_msk[R_CXL_HDM_DECODER0_TARGET_LIST_LO + i * 0x20 / 4] =
> > + 0xffffffff;
> > }
> > - write_msk[R_CXL_HDM_DECODER0_TARGET_LIST_HI + i * 0x20] = 0xffffffff;
> > + write_msk[R_CXL_HDM_DECODER0_TARGET_LIST_HI + i * 0x20 / 4] =
> > + 0xffffffff;
> > }
> > }
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] hw/cxl: Add utility functions decoder interleave ways and target count.
2023-09-05 15:06 ` Jonathan Cameron via
@ 2023-09-05 16:55 ` Philippe Mathieu-Daudé
2023-09-07 11:27 ` Jonathan Cameron via
0 siblings, 1 reply; 10+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-09-05 16:55 UTC (permalink / raw)
To: Jonathan Cameron, Jonathan Cameron via
Cc: Michael Tsirkin, Fan Ni, linux-cxl, Dave Jiang, linuxarm
On 5/9/23 17:06, Jonathan Cameron wrote:
> On Tue, 5 Sep 2023 15:56:39 +0100
> Jonathan Cameron via <qemu-devel@nongnu.org> wrote:
>
>> On Mon, 4 Sep 2023 20:26:59 +0200
>> Philippe Mathieu-Daudé <philmd@linaro.org> wrote:
>>
>>> On 4/9/23 18:47, Jonathan Cameron wrote:
>>>> As an encoded version of these key configuration parameters is
>>>> a register, provide functions to extract it again so as to avoid
>>>> the need for duplicating the storage.
>>>>
>>>> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
>>>> ---
>>>> include/hw/cxl/cxl_component.h | 14 ++++++++++++++
>>>> hw/cxl/cxl-component-utils.c | 17 +++++++++++++++++
>>>> 2 files changed, 31 insertions(+)
>>>>
>>>> diff --git a/include/hw/cxl/cxl_component.h b/include/hw/cxl/cxl_component.h
>>>> index 42c7e581a7..f0ad9cf7de 100644
>>>> --- a/include/hw/cxl/cxl_component.h
>>>> +++ b/include/hw/cxl/cxl_component.h
>>>> @@ -238,7 +238,21 @@ static inline int cxl_decoder_count_enc(int count)
>>>> return 0;
>>>> }
>>>>
>>>> +static inline int cxl_decoder_count_dec(int enc_cnt)
>>>> +{
>>>> + switch (enc_cnt) {
>>>> + case 0: return 1;
>>>> + case 1: return 2;
>>>> + case 2: return 4;
>>>> + case 3: return 6;
>>>> + case 4: return 8;
>>>> + case 5: return 10;
>>>> + }
>>>> + return 0;
>>>> +}
>>>
>>> Why inline?
>>>
>>
>> Bad habit.
> Nope. I'm being slow. This is in a header so if I don't
> mark it inline I get a bunch of defined but not used warnings.
>
> Obviously I could move the implementation of this and the matching
> encoding routines out of the header. I haven't done so for now.
Inlined function in hw/ are hardly justifiable. They make the headers
and debugging sessions harder to read in my experience. Compilers are
becoming clever and clever, and we have LTO, so I rather privilege
code maintainability. My 2 cents :)
>>> Alternatively:
>>>
>>> unsigned cxl_decoder_count_dec(unsigned enc_cnt)
>>> {
>>> return enc_cnt <= 5 ? 2 * enc_cnt : 0;
>>
>> It gets a little more fiddly than the code I'm proposing implies.
>> For Switches and Host Bridges larger values are defined
>> (we just don't emulate them yet and may never do so) and those
>> don't have a sensible mapping.
>>
>> I guess there is no harm in adding the full decode however
>> which will make it more obvious why it was a switch statement.
Right, no problem.
Preferably having this tiny function not inlined:
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] hw/cxl: Add utility functions decoder interleave ways and target count.
2023-09-05 16:55 ` Philippe Mathieu-Daudé
@ 2023-09-07 11:27 ` Jonathan Cameron via
0 siblings, 0 replies; 10+ messages in thread
From: Jonathan Cameron via @ 2023-09-07 11:27 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: Jonathan Cameron via, Michael Tsirkin, Fan Ni, linux-cxl,
Dave Jiang, linuxarm
On Tue, 5 Sep 2023 18:55:23 +0200
Philippe Mathieu-Daudé <philmd@linaro.org> wrote:
> On 5/9/23 17:06, Jonathan Cameron wrote:
> > On Tue, 5 Sep 2023 15:56:39 +0100
> > Jonathan Cameron via <qemu-devel@nongnu.org> wrote:
> >
> >> On Mon, 4 Sep 2023 20:26:59 +0200
> >> Philippe Mathieu-Daudé <philmd@linaro.org> wrote:
> >>
> >>> On 4/9/23 18:47, Jonathan Cameron wrote:
> >>>> As an encoded version of these key configuration parameters is
> >>>> a register, provide functions to extract it again so as to avoid
> >>>> the need for duplicating the storage.
> >>>>
> >>>> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> >>>> ---
> >>>> include/hw/cxl/cxl_component.h | 14 ++++++++++++++
> >>>> hw/cxl/cxl-component-utils.c | 17 +++++++++++++++++
> >>>> 2 files changed, 31 insertions(+)
> >>>>
> >>>> diff --git a/include/hw/cxl/cxl_component.h b/include/hw/cxl/cxl_component.h
> >>>> index 42c7e581a7..f0ad9cf7de 100644
> >>>> --- a/include/hw/cxl/cxl_component.h
> >>>> +++ b/include/hw/cxl/cxl_component.h
> >>>> @@ -238,7 +238,21 @@ static inline int cxl_decoder_count_enc(int count)
> >>>> return 0;
> >>>> }
> >>>>
> >>>> +static inline int cxl_decoder_count_dec(int enc_cnt)
> >>>> +{
> >>>> + switch (enc_cnt) {
> >>>> + case 0: return 1;
> >>>> + case 1: return 2;
> >>>> + case 2: return 4;
> >>>> + case 3: return 6;
> >>>> + case 4: return 8;
> >>>> + case 5: return 10;
> >>>> + }
> >>>> + return 0;
> >>>> +}
> >>>
> >>> Why inline?
> >>>
> >>
> >> Bad habit.
> > Nope. I'm being slow. This is in a header so if I don't
> > mark it inline I get a bunch of defined but not used warnings.
> >
> > Obviously I could move the implementation of this and the matching
> > encoding routines out of the header. I haven't done so for now.
>
> Inlined function in hw/ are hardly justifiable. They make the headers
> and debugging sessions harder to read in my experience. Compilers are
> becoming clever and clever, and we have LTO, so I rather privilege
> code maintainability. My 2 cents :)
>
> >>> Alternatively:
> >>>
> >>> unsigned cxl_decoder_count_dec(unsigned enc_cnt)
> >>> {
> >>> return enc_cnt <= 5 ? 2 * enc_cnt : 0;
> >>
> >> It gets a little more fiddly than the code I'm proposing implies.
> >> For Switches and Host Bridges larger values are defined
> >> (we just don't emulate them yet and may never do so) and those
> >> don't have a sensible mapping.
> >>
> >> I guess there is no harm in adding the full decode however
> >> which will make it more obvious why it was a switch statement.
>
> Right, no problem.
>
> Preferably having this tiny function not inlined
I'll push this and the enc() version down into the cxl-component-utils.c
as a precursor patch.
>
> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
>
>
Thanks, but the changes to do make these non inline, and include
the larger decode and encode values are big enough I won't pick up
the RB - too much changing (that I might mess up ;)
Jonathan
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2023-09-07 11:28 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-09-04 16:47 [PATCH 0/2] hw/cxl: Support emulating 4 HDM decoders throughout topology Jonathan Cameron via
2023-09-04 16:47 ` [PATCH 1/2] hw/cxl: Add utility functions decoder interleave ways and target count Jonathan Cameron via
2023-09-04 18:26 ` Philippe Mathieu-Daudé
2023-09-05 14:56 ` Jonathan Cameron via
2023-09-05 15:06 ` Jonathan Cameron via
2023-09-05 16:55 ` Philippe Mathieu-Daudé
2023-09-07 11:27 ` Jonathan Cameron via
2023-09-04 16:47 ` [PATCH 2/2] hw/cxl: Support 4 HDM decoders at all levels of topology Jonathan Cameron via
2023-09-04 18:36 ` Philippe Mathieu-Daudé
2023-09-05 15:44 ` Jonathan Cameron via
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).