* [PATCH v6 0/4] hw/cxl: Poison get, inject, clear
@ 2023-05-19 14:17 Jonathan Cameron via
2023-05-19 14:18 ` [PATCH v6 1/4] bswap: Add the ability to store to an unaligned 24 bit field Jonathan Cameron via
` (3 more replies)
0 siblings, 4 replies; 17+ messages in thread
From: Jonathan Cameron via @ 2023-05-19 14:17 UTC (permalink / raw)
To: qemu-devel, Michael Tsirkin, Fan Ni
Cc: linux-cxl, linuxarm, Ira Weiny, Michael Roth,
Philippe Mathieu-Daudé, Dave Jiang, Markus Armbruster,
Daniel P . Berrangé, Eric Blake, Mike Maslenkin,
Marc-André Lureau, Thomas Huth
Note that Michael Tsirkin replied to v5 to say he has first
3 queued - the bswap one is buggy so should be dropped and
replaced with this v6. Note changes in that patch were large
enough that I've dropped Fan Ni's tag.
Tested the problematic cross compiles using docker.
v6:
- Fix 24 bit bswap on big endian platforms.
I think this was broken in a bad rebase some time ago.
Fix is to not use the general macros for this case as they
rely on a builtin 24 bit byte swap which doesn't exist.
- Wrong use of int128_to_64() on a variable that was uint64_t in
the first place.
Many of the precursors listed for v4 have now been applied, but
a few minor fixes have come up in the meantime so there are still
a few precursors including the volatile support left from v4
precursors.
Michael has the above series + initial patches of v5 of this series
queued up.
Depends on
[PATCH 0/2] hw/cxl: CDAT file handling fixes.
[PATCH v2 0/3] hw/cxl: Fix decoder commit and uncommit handling
[PATCH 0/3] docs/cxl: Gathering of fixes for 8.0 CXL docs.
[PATCH v5 0/3] hw/mem: CXL Type-3 Volatile Memory Support
Based on: Message-ID: 20230421132020.7408-1-Jonathan.Cameron@huawei.com
Based on: Message-ID: 20230421135906.3515-1-Jonathan.Cameron@huawei.com
Based on: Message-ID: 20230421134507.26842-1-Jonathan.Cameron@huawei.com
Based on: Message-ID: 20230421160827.2227-1-Jonathan.Cameron@huawei.com
The kernel support for Poison handling is currently in the cxl/pending
branch and hopefully should be in the CXL pull request next week.
https://git.kernel.org/pub/scm/linux/kernel/git/cxl/cxl.git/log/?h=pending
This code has been very useful for testing and helped identify various
corner cases.
Updated cover letter.
The series supports:
1) Injection of variable length poison regions via QMP (to fake real
memory corruption and ensure we deal with odd overflow corner cases
such as clearing the middle of a large region making the list overflow
as we go from one long entry to two smaller entries.
2) Read of poison list via the CXL mailbox.
3) Injection via the poison injection mailbox command (limited to 64 byte
entries - spec constraint)
4) Clearing of poison injected via either method.
The implementation is meant to be a valid combination of impdef choices
based on what the spec allowed. There are a number of places where it could
be made more sophisticated that we might consider in future:
* Fusing adjacent poison entries if the types match.
* Separate injection list and main poison list, to test out limits on
injected poison list being smaller than the main list.
* Poison list overflow event (needs event log support in general)
* Connecting up to the poison list error record generation (rather complex
and not needed for currently kernel handling testing).
* Triggering the synchronous and asynchronous errors that occur on reads
and writes of the memory when the host receives poison.
As the kernel code is currently fairly simple, it is likely that the above
does not yet matter but who knows what will turn up in future!
Ira Weiny (1):
bswap: Add the ability to store to an unaligned 24 bit field
Jonathan Cameron (3):
hw/cxl: QMP based poison injection support
hw/cxl: Add poison injection via the mailbox.
hw/cxl: Add clear poison mailbox command support.
docs/devel/loads-stores.rst | 1 +
hw/cxl/cxl-mailbox-utils.c | 214 ++++++++++++++++++++++++++++++++++++
hw/mem/cxl_type3.c | 93 ++++++++++++++++
hw/mem/cxl_type3_stubs.c | 6 +
include/hw/cxl/cxl.h | 1 +
include/hw/cxl/cxl_device.h | 21 ++++
include/qemu/bswap.h | 27 +++++
qapi/cxl.json | 18 +++
8 files changed, 381 insertions(+)
--
2.39.2
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v6 1/4] bswap: Add the ability to store to an unaligned 24 bit field
2023-05-19 14:17 [PATCH v6 0/4] hw/cxl: Poison get, inject, clear Jonathan Cameron via
@ 2023-05-19 14:18 ` Jonathan Cameron via
2023-05-19 16:08 ` Philippe Mathieu-Daudé
2023-05-20 12:37 ` Peter Maydell
2023-05-19 14:18 ` [PATCH v6 2/4] hw/cxl: QMP based poison injection support Jonathan Cameron via
` (2 subsequent siblings)
3 siblings, 2 replies; 17+ messages in thread
From: Jonathan Cameron via @ 2023-05-19 14:18 UTC (permalink / raw)
To: qemu-devel, Michael Tsirkin, Fan Ni
Cc: linux-cxl, linuxarm, Ira Weiny, Michael Roth,
Philippe Mathieu-Daudé, Dave Jiang, Markus Armbruster,
Daniel P . Berrangé, Eric Blake, Mike Maslenkin,
Marc-André Lureau, Thomas Huth
From: Ira Weiny <ira.weiny@intel.com>
CXL has 24 bit unaligned fields which need to be stored to. CXL is
specified as little endian.
Define st24_le_p() and the supporting functions to store such a field
from a 32 bit host native value.
The use of b, w, l, q as the size specifier is limiting. So "24" was
used for the size part of the function name.
Signed-off-by: Ira Weiny <ira.weiny@intel.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
docs/devel/loads-stores.rst | 1 +
include/qemu/bswap.h | 27 +++++++++++++++++++++++++++
2 files changed, 28 insertions(+)
diff --git a/docs/devel/loads-stores.rst b/docs/devel/loads-stores.rst
index d2cefc77a2..82a79e91d9 100644
--- a/docs/devel/loads-stores.rst
+++ b/docs/devel/loads-stores.rst
@@ -36,6 +36,7 @@ store: ``st{size}_{endian}_p(ptr, val)``
``size``
- ``b`` : 8 bits
- ``w`` : 16 bits
+ - ``24`` : 24 bits
- ``l`` : 32 bits
- ``q`` : 64 bits
diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h
index 15a78c0db5..f546b1fc06 100644
--- a/include/qemu/bswap.h
+++ b/include/qemu/bswap.h
@@ -8,11 +8,25 @@
#undef bswap64
#define bswap64(_x) __builtin_bswap64(_x)
+static inline uint32_t bswap24(uint32_t x)
+{
+ assert((x & 0xff000000U) == 0);
+
+ return (((x & 0x000000ffU) << 16) |
+ ((x & 0x0000ff00U) << 0) |
+ ((x & 0x00ff0000U) >> 16));
+}
+
static inline void bswap16s(uint16_t *s)
{
*s = __builtin_bswap16(*s);
}
+static inline void bswap24s(uint32_t *s)
+{
+ *s = bswap24(*s & 0x00ffffffU);
+}
+
static inline void bswap32s(uint32_t *s)
{
*s = __builtin_bswap32(*s);
@@ -26,11 +40,13 @@ static inline void bswap64s(uint64_t *s)
#if HOST_BIG_ENDIAN
#define be_bswap(v, size) (v)
#define le_bswap(v, size) glue(__builtin_bswap, size)(v)
+#define le_bswap24(v) bswap24(v)
#define be_bswaps(v, size)
#define le_bswaps(p, size) \
do { *p = glue(__builtin_bswap, size)(*p); } while (0)
#else
#define le_bswap(v, size) (v)
+#define le_bswap24(v) (v)
#define be_bswap(v, size) glue(__builtin_bswap, size)(v)
#define le_bswaps(v, size)
#define be_bswaps(p, size) \
@@ -176,6 +192,7 @@ CPU_CONVERT(le, 64, uint64_t)
* size is:
* b: 8 bits
* w: 16 bits
+ * 24: 24 bits
* l: 32 bits
* q: 64 bits
*
@@ -248,6 +265,11 @@ static inline void stw_he_p(void *ptr, uint16_t v)
__builtin_memcpy(ptr, &v, sizeof(v));
}
+static inline void st24_he_p(void *ptr, uint32_t v)
+{
+ __builtin_memcpy(ptr, &v, 3);
+}
+
static inline int ldl_he_p(const void *ptr)
{
int32_t r;
@@ -297,6 +319,11 @@ static inline void stw_le_p(void *ptr, uint16_t v)
stw_he_p(ptr, le_bswap(v, 16));
}
+static inline void st24_le_p(void *ptr, uint32_t v)
+{
+ st24_he_p(ptr, le_bswap24(v));
+}
+
static inline void stl_le_p(void *ptr, uint32_t v)
{
stl_he_p(ptr, le_bswap(v, 32));
--
2.39.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v6 2/4] hw/cxl: QMP based poison injection support
2023-05-19 14:17 [PATCH v6 0/4] hw/cxl: Poison get, inject, clear Jonathan Cameron via
2023-05-19 14:18 ` [PATCH v6 1/4] bswap: Add the ability to store to an unaligned 24 bit field Jonathan Cameron via
@ 2023-05-19 14:18 ` Jonathan Cameron via
2023-05-22 11:20 ` Jonathan Cameron via
2023-05-19 14:18 ` [PATCH v6 3/4] hw/cxl: Add poison injection via the mailbox Jonathan Cameron via
2023-05-19 14:18 ` [PATCH v6 4/4] hw/cxl: Add clear poison mailbox command support Jonathan Cameron via
3 siblings, 1 reply; 17+ messages in thread
From: Jonathan Cameron via @ 2023-05-19 14:18 UTC (permalink / raw)
To: qemu-devel, Michael Tsirkin, Fan Ni
Cc: linux-cxl, linuxarm, Ira Weiny, Michael Roth,
Philippe Mathieu-Daudé, Dave Jiang, Markus Armbruster,
Daniel P . Berrangé, Eric Blake, Mike Maslenkin,
Marc-André Lureau, Thomas Huth
Inject poison using qmp command cxl-inject-poison to add an entry to the
poison list.
For now, the poison is not returned CXL.mem reads, but only via the
mailbox command Get Poison List. So a normal memory read to an address
that is on the poison list will not yet result in a synchronous exception
(and similar for partial cacheline writes).
That is left for a future patch.
See CXL rev 3.0, sec 8.2.9.8.4.1 Get Poison list (Opcode 4300h)
Kernel patches to use this interface here:
https://lore.kernel.org/linux-cxl/cover.1665606782.git.alison.schofield@intel.com/
To inject poison using qmp (telnet to the qmp port)
{ "execute": "qmp_capabilities" }
{ "execute": "cxl-inject-poison",
"arguments": {
"path": "/machine/peripheral/cxl-pmem0",
"start": 2048,
"length": 256
}
}
Adjusted to select a device on your machine.
Note that the poison list supported is kept short enough to avoid the
complexity of state machine that is needed to handle the MORE flag.
Reviewed-by: Fan Ni <fan.ni@samsung.com>
Reviewed-by: Ira Weiny <ira.weiny@intel.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
hw/cxl/cxl-mailbox-utils.c | 90 +++++++++++++++++++++++++++++++++++++
hw/mem/cxl_type3.c | 56 +++++++++++++++++++++++
hw/mem/cxl_type3_stubs.c | 6 +++
include/hw/cxl/cxl.h | 1 +
include/hw/cxl/cxl_device.h | 20 +++++++++
qapi/cxl.json | 18 ++++++++
6 files changed, 191 insertions(+)
diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
index 702e16ca20..1f74b26ea2 100644
--- a/hw/cxl/cxl-mailbox-utils.c
+++ b/hw/cxl/cxl-mailbox-utils.c
@@ -62,6 +62,8 @@ enum {
#define GET_PARTITION_INFO 0x0
#define GET_LSA 0x2
#define SET_LSA 0x3
+ MEDIA_AND_POISON = 0x43,
+ #define GET_POISON_LIST 0x0
};
/* 8.2.8.4.5.1 Command Return Codes */
@@ -295,6 +297,10 @@ static CXLRetCode cmd_identify_memory_device(struct cxl_cmd *cmd,
stq_le_p(&id->persistent_capacity, cxl_dstate->pmem_size / CXL_CAPACITY_MULTIPLIER);
stq_le_p(&id->volatile_capacity, cxl_dstate->vmem_size / CXL_CAPACITY_MULTIPLIER);
stl_le_p(&id->lsa_size, cvc->get_lsa_size(ct3d));
+ /* 256 poison records */
+ st24_le_p(id->poison_list_max_mer, 256);
+ /* No limit - so limited by main poison record limit */
+ stw_le_p(&id->inject_poison_limit, 0);
*len = sizeof(*id);
return CXL_MBOX_SUCCESS;
@@ -384,6 +390,88 @@ static CXLRetCode cmd_ccls_set_lsa(struct cxl_cmd *cmd,
return CXL_MBOX_SUCCESS;
}
+/*
+ * This is very inefficient, but good enough for now!
+ * Also the payload will always fit, so no need to handle the MORE flag and
+ * make this stateful. We may want to allow longer poison lists to aid
+ * testing that kernel functionality.
+ */
+static CXLRetCode cmd_media_get_poison_list(struct cxl_cmd *cmd,
+ CXLDeviceState *cxl_dstate,
+ uint16_t *len)
+{
+ struct get_poison_list_pl {
+ uint64_t pa;
+ uint64_t length;
+ } QEMU_PACKED;
+
+ struct get_poison_list_out_pl {
+ uint8_t flags;
+ uint8_t rsvd1;
+ uint64_t overflow_timestamp;
+ uint16_t count;
+ uint8_t rsvd2[0x14];
+ struct {
+ uint64_t addr;
+ uint32_t length;
+ uint32_t resv;
+ } QEMU_PACKED records[];
+ } QEMU_PACKED;
+
+ struct get_poison_list_pl *in = (void *)cmd->payload;
+ struct get_poison_list_out_pl *out = (void *)cmd->payload;
+ CXLType3Dev *ct3d = container_of(cxl_dstate, CXLType3Dev, cxl_dstate);
+ uint16_t record_count = 0, i = 0;
+ uint64_t query_start, query_length;
+ CXLPoisonList *poison_list = &ct3d->poison_list;
+ CXLPoison *ent;
+ uint16_t out_pl_len;
+
+ query_start = ldq_le_p(&in->pa);
+ /* 64 byte alignemnt required */
+ if (query_start & 0x3f) {
+ return CXL_MBOX_INVALID_INPUT;
+ }
+ query_length = ldq_le_p(&in->length) * CXL_CACHE_LINE_SIZE;
+
+ QLIST_FOREACH(ent, poison_list, node) {
+ /* Check for no overlap */
+ if (ent->start >= query_start + query_length ||
+ ent->start + ent->length <= query_start) {
+ continue;
+ }
+ record_count++;
+ }
+ out_pl_len = sizeof(*out) + record_count * sizeof(out->records[0]);
+ assert(out_pl_len <= CXL_MAILBOX_MAX_PAYLOAD_SIZE);
+
+ memset(out, 0, out_pl_len);
+ QLIST_FOREACH(ent, poison_list, node) {
+ uint64_t start, stop;
+
+ /* Check for no overlap */
+ if (ent->start >= query_start + query_length ||
+ ent->start + ent->length <= query_start) {
+ continue;
+ }
+
+ /* Deal with overlap */
+ start = MAX(ROUND_DOWN(ent->start, 64ull), query_start);
+ stop = MIN(ROUND_DOWN(ent->start, 64ull) + ent->length,
+ query_start + query_length);
+ stq_le_p(&out->records[i].addr, start | (ent->type & 0x7));
+ stl_le_p(&out->records[i].length, (stop - start) / CXL_CACHE_LINE_SIZE);
+ i++;
+ }
+ if (ct3d->poison_list_overflowed) {
+ out->flags = (1 << 1);
+ stq_le_p(&out->overflow_timestamp, ct3d->poison_list_overflow_ts);
+ }
+ stw_le_p(&out->count, record_count);
+ *len = out_pl_len;
+ return CXL_MBOX_SUCCESS;
+}
+
#define IMMEDIATE_CONFIG_CHANGE (1 << 1)
#define IMMEDIATE_DATA_CHANGE (1 << 2)
#define IMMEDIATE_POLICY_CHANGE (1 << 3)
@@ -411,6 +499,8 @@ static struct cxl_cmd cxl_cmd_set[256][256] = {
[CCLS][GET_LSA] = { "CCLS_GET_LSA", cmd_ccls_get_lsa, 8, 0 },
[CCLS][SET_LSA] = { "CCLS_SET_LSA", cmd_ccls_set_lsa,
~0, IMMEDIATE_CONFIG_CHANGE | IMMEDIATE_DATA_CHANGE },
+ [MEDIA_AND_POISON][GET_POISON_LIST] = { "MEDIA_AND_POISON_GET_POISON_LIST",
+ cmd_media_get_poison_list, 16, 0 },
};
void cxl_process_mailbox(CXLDeviceState *cxl_dstate)
diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
index 2adacbd01b..ab600735eb 100644
--- a/hw/mem/cxl_type3.c
+++ b/hw/mem/cxl_type3.c
@@ -947,6 +947,62 @@ static void set_lsa(CXLType3Dev *ct3d, const void *buf, uint64_t size,
*/
}
+void cxl_set_poison_list_overflowed(CXLType3Dev *ct3d)
+{
+ ct3d->poison_list_overflowed = true;
+ ct3d->poison_list_overflow_ts =
+ cxl_device_get_timestamp(&ct3d->cxl_dstate);
+}
+
+void qmp_cxl_inject_poison(const char *path, uint64_t start, uint64_t length,
+ Error **errp)
+{
+ Object *obj = object_resolve_path(path, NULL);
+ CXLType3Dev *ct3d;
+ CXLPoison *p;
+
+ if (length % 64) {
+ error_setg(errp, "Poison injection must be in multiples of 64 bytes");
+ return;
+ }
+ if (start % 64) {
+ error_setg(errp, "Poison start address must be 64 byte aligned");
+ return;
+ }
+ if (!obj) {
+ error_setg(errp, "Unable to resolve path");
+ return;
+ }
+ if (!object_dynamic_cast(obj, TYPE_CXL_TYPE3)) {
+ error_setg(errp, "Path does not point to a CXL type 3 device");
+ return;
+ }
+
+ ct3d = CXL_TYPE3(obj);
+
+ QLIST_FOREACH(p, &ct3d->poison_list, node) {
+ if (((start >= p->start) && (start < p->start + p->length)) ||
+ ((start + length > p->start) &&
+ (start + length <= p->start + p->length))) {
+ error_setg(errp, "Overlap with existing poisoned region not supported");
+ return;
+ }
+ }
+
+ if (ct3d->poison_list_cnt == CXL_POISON_LIST_LIMIT) {
+ cxl_set_poison_list_overflowed(ct3d);
+ return;
+ }
+
+ p = g_new0(CXLPoison, 1);
+ p->length = length;
+ p->start = start;
+ p->type = CXL_POISON_TYPE_INTERNAL; /* Different from injected via the mbox */
+
+ QLIST_INSERT_HEAD(&ct3d->poison_list, p, node);
+ ct3d->poison_list_cnt++;
+}
+
/* For uncorrectable errors include support for multiple header recording */
void qmp_cxl_inject_uncorrectable_errors(const char *path,
CXLUncorErrorRecordList *errors,
diff --git a/hw/mem/cxl_type3_stubs.c b/hw/mem/cxl_type3_stubs.c
index d574c58f9a..fd1166a610 100644
--- a/hw/mem/cxl_type3_stubs.c
+++ b/hw/mem/cxl_type3_stubs.c
@@ -3,6 +3,12 @@
#include "qapi/error.h"
#include "qapi/qapi-commands-cxl.h"
+void qmp_cxl_inject_poison(const char *path, uint64_t start, uint64_t length,
+ Error **errp)
+{
+ error_setg(errp, "CXL Type 3 support is not compiled in");
+}
+
void qmp_cxl_inject_uncorrectable_errors(const char *path,
CXLUncorErrorRecordList *errors,
Error **errp)
diff --git a/include/hw/cxl/cxl.h b/include/hw/cxl/cxl.h
index c453983e83..56c9e7676e 100644
--- a/include/hw/cxl/cxl.h
+++ b/include/hw/cxl/cxl.h
@@ -18,6 +18,7 @@
#include "cxl_component.h"
#include "cxl_device.h"
+#define CXL_CACHE_LINE_SIZE 64
#define CXL_COMPONENT_REG_BAR_IDX 0
#define CXL_DEVICE_REG_BAR_IDX 2
diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h
index 02befda0f6..32c234ea91 100644
--- a/include/hw/cxl/cxl_device.h
+++ b/include/hw/cxl/cxl_device.h
@@ -242,6 +242,18 @@ typedef struct CXLError {
typedef QTAILQ_HEAD(, CXLError) CXLErrorList;
+typedef struct CXLPoison {
+ uint64_t start, length;
+ uint8_t type;
+#define CXL_POISON_TYPE_EXTERNAL 0x1
+#define CXL_POISON_TYPE_INTERNAL 0x2
+#define CXL_POISON_TYPE_INJECTED 0x3
+ QLIST_ENTRY(CXLPoison) node;
+} CXLPoison;
+
+typedef QLIST_HEAD(, CXLPoison) CXLPoisonList;
+#define CXL_POISON_LIST_LIMIT 256
+
struct CXLType3Dev {
/* Private */
PCIDevice parent_obj;
@@ -264,6 +276,12 @@ struct CXLType3Dev {
/* Error injection */
CXLErrorList error_list;
+
+ /* Poison Injection - cache */
+ CXLPoisonList poison_list;
+ unsigned int poison_list_cnt;
+ bool poison_list_overflowed;
+ uint64_t poison_list_overflow_ts;
};
#define TYPE_CXL_TYPE3 "cxl-type3"
@@ -289,4 +307,6 @@ MemTxResult cxl_type3_write(PCIDevice *d, hwaddr host_addr, uint64_t data,
uint64_t cxl_device_get_timestamp(CXLDeviceState *cxlds);
+void cxl_set_poison_list_overflowed(CXLType3Dev *ct3d);
+
#endif
diff --git a/qapi/cxl.json b/qapi/cxl.json
index b21c9b4c1c..dcf9e7b715 100644
--- a/qapi/cxl.json
+++ b/qapi/cxl.json
@@ -5,6 +5,24 @@
# = CXL devices
##
+##
+# @cxl-inject-poison:
+#
+# Poison records indicate that a CXL memory device knows that a particular
+# memory region may be corrupted. This may be because of locally detected
+# errors (e.g. ECC failure) or poisoned writes received from other components
+# in the system. This injection mechanism enables testing of the OS handling
+# of poison records which may be queried via the CXL mailbox.
+#
+# @path: CXL type 3 device canonical QOM path
+# @start: Start address - must be 64 byte aligned.
+# @length: Length of poison to inject - must be a multiple of 64 bytes.
+#
+# Since: 8.1
+##
+{ 'command': 'cxl-inject-poison',
+ 'data': { 'path': 'str', 'start': 'uint64', 'length': 'uint64' }}
+
##
# @CxlUncorErrorType:
#
--
2.39.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v6 3/4] hw/cxl: Add poison injection via the mailbox.
2023-05-19 14:17 [PATCH v6 0/4] hw/cxl: Poison get, inject, clear Jonathan Cameron via
2023-05-19 14:18 ` [PATCH v6 1/4] bswap: Add the ability to store to an unaligned 24 bit field Jonathan Cameron via
2023-05-19 14:18 ` [PATCH v6 2/4] hw/cxl: QMP based poison injection support Jonathan Cameron via
@ 2023-05-19 14:18 ` Jonathan Cameron via
2023-05-19 14:18 ` [PATCH v6 4/4] hw/cxl: Add clear poison mailbox command support Jonathan Cameron via
3 siblings, 0 replies; 17+ messages in thread
From: Jonathan Cameron via @ 2023-05-19 14:18 UTC (permalink / raw)
To: qemu-devel, Michael Tsirkin, Fan Ni
Cc: linux-cxl, linuxarm, Ira Weiny, Michael Roth,
Philippe Mathieu-Daudé, Dave Jiang, Markus Armbruster,
Daniel P . Berrangé, Eric Blake, Mike Maslenkin,
Marc-André Lureau, Thomas Huth
Very simple implementation to allow testing of corresponding
kernel code. Note that for now we track each 64 byte section
independently. Whilst a valid implementation choice, it may
make sense to fuse entries so as to prove out more complex
corners of the kernel code.
Reviewed-by: Ira Weiny <ira.weiny@intel.com>
Reviewed-by: Fan Ni <fan.ni@samsung.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
hw/cxl/cxl-mailbox-utils.c | 42 ++++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
index 1f74b26ea2..6c476ad7f4 100644
--- a/hw/cxl/cxl-mailbox-utils.c
+++ b/hw/cxl/cxl-mailbox-utils.c
@@ -64,6 +64,7 @@ enum {
#define SET_LSA 0x3
MEDIA_AND_POISON = 0x43,
#define GET_POISON_LIST 0x0
+ #define INJECT_POISON 0x1
};
/* 8.2.8.4.5.1 Command Return Codes */
@@ -472,6 +473,45 @@ static CXLRetCode cmd_media_get_poison_list(struct cxl_cmd *cmd,
return CXL_MBOX_SUCCESS;
}
+static CXLRetCode cmd_media_inject_poison(struct cxl_cmd *cmd,
+ CXLDeviceState *cxl_dstate,
+ uint16_t *len_unused)
+{
+ CXLType3Dev *ct3d = container_of(cxl_dstate, CXLType3Dev, cxl_dstate);
+ CXLPoisonList *poison_list = &ct3d->poison_list;
+ CXLPoison *ent;
+ struct inject_poison_pl {
+ uint64_t dpa;
+ };
+ struct inject_poison_pl *in = (void *)cmd->payload;
+ uint64_t dpa = ldq_le_p(&in->dpa);
+ CXLPoison *p;
+
+ QLIST_FOREACH(ent, poison_list, node) {
+ if (dpa >= ent->start &&
+ dpa + CXL_CACHE_LINE_SIZE <= ent->start + ent->length) {
+ return CXL_MBOX_SUCCESS;
+ }
+ }
+
+ if (ct3d->poison_list_cnt == CXL_POISON_LIST_LIMIT) {
+ return CXL_MBOX_INJECT_POISON_LIMIT;
+ }
+ p = g_new0(CXLPoison, 1);
+
+ p->length = CXL_CACHE_LINE_SIZE;
+ p->start = dpa;
+ p->type = CXL_POISON_TYPE_INJECTED;
+
+ /*
+ * Possible todo: Merge with existing entry if next to it and if same type
+ */
+ QLIST_INSERT_HEAD(poison_list, p, node);
+ ct3d->poison_list_cnt++;
+
+ return CXL_MBOX_SUCCESS;
+}
+
#define IMMEDIATE_CONFIG_CHANGE (1 << 1)
#define IMMEDIATE_DATA_CHANGE (1 << 2)
#define IMMEDIATE_POLICY_CHANGE (1 << 3)
@@ -501,6 +541,8 @@ static struct cxl_cmd cxl_cmd_set[256][256] = {
~0, IMMEDIATE_CONFIG_CHANGE | IMMEDIATE_DATA_CHANGE },
[MEDIA_AND_POISON][GET_POISON_LIST] = { "MEDIA_AND_POISON_GET_POISON_LIST",
cmd_media_get_poison_list, 16, 0 },
+ [MEDIA_AND_POISON][INJECT_POISON] = { "MEDIA_AND_POISON_INJECT_POISON",
+ cmd_media_inject_poison, 8, 0 },
};
void cxl_process_mailbox(CXLDeviceState *cxl_dstate)
--
2.39.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v6 4/4] hw/cxl: Add clear poison mailbox command support.
2023-05-19 14:17 [PATCH v6 0/4] hw/cxl: Poison get, inject, clear Jonathan Cameron via
` (2 preceding siblings ...)
2023-05-19 14:18 ` [PATCH v6 3/4] hw/cxl: Add poison injection via the mailbox Jonathan Cameron via
@ 2023-05-19 14:18 ` Jonathan Cameron via
2023-05-19 17:48 ` Ira Weiny
3 siblings, 1 reply; 17+ messages in thread
From: Jonathan Cameron via @ 2023-05-19 14:18 UTC (permalink / raw)
To: qemu-devel, Michael Tsirkin, Fan Ni
Cc: linux-cxl, linuxarm, Ira Weiny, Michael Roth,
Philippe Mathieu-Daudé, Dave Jiang, Markus Armbruster,
Daniel P . Berrangé, Eric Blake, Mike Maslenkin,
Marc-André Lureau, Thomas Huth
Current implementation is very simple so many of the corner
cases do not exist (e.g. fragmenting larger poison list entries)
Reviewed-by: Fan Ni <fan.ni@samsung.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
hw/cxl/cxl-mailbox-utils.c | 82 +++++++++++++++++++++++++++++++++++++
hw/mem/cxl_type3.c | 37 +++++++++++++++++
include/hw/cxl/cxl_device.h | 1 +
3 files changed, 120 insertions(+)
diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
index 6c476ad7f4..e3401b6be8 100644
--- a/hw/cxl/cxl-mailbox-utils.c
+++ b/hw/cxl/cxl-mailbox-utils.c
@@ -65,6 +65,7 @@ enum {
MEDIA_AND_POISON = 0x43,
#define GET_POISON_LIST 0x0
#define INJECT_POISON 0x1
+ #define CLEAR_POISON 0x2
};
/* 8.2.8.4.5.1 Command Return Codes */
@@ -512,6 +513,85 @@ static CXLRetCode cmd_media_inject_poison(struct cxl_cmd *cmd,
return CXL_MBOX_SUCCESS;
}
+static CXLRetCode cmd_media_clear_poison(struct cxl_cmd *cmd,
+ CXLDeviceState *cxl_dstate,
+ uint16_t *len_unused)
+{
+ CXLType3Dev *ct3d = container_of(cxl_dstate, CXLType3Dev, cxl_dstate);
+ CXLPoisonList *poison_list = &ct3d->poison_list;
+ CXLType3Class *cvc = CXL_TYPE3_GET_CLASS(ct3d);
+ struct clear_poison_pl {
+ uint64_t dpa;
+ uint8_t data[64];
+ };
+ CXLPoison *ent;
+ uint64_t dpa;
+
+ struct clear_poison_pl *in = (void *)cmd->payload;
+
+ dpa = ldq_le_p(&in->dpa);
+ if (dpa + CXL_CACHE_LINE_SIZE > cxl_dstate->mem_size) {
+ return CXL_MBOX_INVALID_PA;
+ }
+
+ /* Clearing a region with no poison is not an error so always do so */
+ if (cvc->set_cacheline) {
+ if (!cvc->set_cacheline(ct3d, dpa, in->data)) {
+ return CXL_MBOX_INTERNAL_ERROR;
+ }
+ }
+
+ QLIST_FOREACH(ent, poison_list, node) {
+ /*
+ * Test for contained in entry. Simpler than general case
+ * as clearing 64 bytes and entries 64 byte aligned
+ */
+ if ((dpa >= ent->start) && (dpa < ent->start + ent->length)) {
+ break;
+ }
+ }
+ if (!ent) {
+ return CXL_MBOX_SUCCESS;
+ }
+
+ QLIST_REMOVE(ent, node);
+ ct3d->poison_list_cnt--;
+
+ if (dpa > ent->start) {
+ CXLPoison *frag;
+ /* Cannot overflow as replacing existing entry */
+
+ frag = g_new0(CXLPoison, 1);
+
+ frag->start = ent->start;
+ frag->length = dpa - ent->start;
+ frag->type = ent->type;
+
+ QLIST_INSERT_HEAD(poison_list, frag, node);
+ ct3d->poison_list_cnt++;
+ }
+
+ if (dpa + CXL_CACHE_LINE_SIZE < ent->start + ent->length) {
+ CXLPoison *frag;
+
+ if (ct3d->poison_list_cnt == CXL_POISON_LIST_LIMIT) {
+ cxl_set_poison_list_overflowed(ct3d);
+ } else {
+ frag = g_new0(CXLPoison, 1);
+
+ frag->start = dpa + CXL_CACHE_LINE_SIZE;
+ frag->length = ent->start + ent->length - frag->start;
+ frag->type = ent->type;
+ QLIST_INSERT_HEAD(poison_list, frag, node);
+ ct3d->poison_list_cnt++;
+ }
+ }
+ /* Any fragments have been added, free original entry */
+ g_free(ent);
+
+ return CXL_MBOX_SUCCESS;
+}
+
#define IMMEDIATE_CONFIG_CHANGE (1 << 1)
#define IMMEDIATE_DATA_CHANGE (1 << 2)
#define IMMEDIATE_POLICY_CHANGE (1 << 3)
@@ -543,6 +623,8 @@ static struct cxl_cmd cxl_cmd_set[256][256] = {
cmd_media_get_poison_list, 16, 0 },
[MEDIA_AND_POISON][INJECT_POISON] = { "MEDIA_AND_POISON_INJECT_POISON",
cmd_media_inject_poison, 8, 0 },
+ [MEDIA_AND_POISON][CLEAR_POISON] = { "MEDIA_AND_POISON_CLEAR_POISON",
+ cmd_media_clear_poison, 72, 0 },
};
void cxl_process_mailbox(CXLDeviceState *cxl_dstate)
diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
index ab600735eb..84022d7ae3 100644
--- a/hw/mem/cxl_type3.c
+++ b/hw/mem/cxl_type3.c
@@ -947,6 +947,42 @@ static void set_lsa(CXLType3Dev *ct3d, const void *buf, uint64_t size,
*/
}
+static bool set_cacheline(CXLType3Dev *ct3d, uint64_t dpa_offset, uint8_t *data)
+{
+ MemoryRegion *vmr = NULL, *pmr = NULL;
+ AddressSpace *as;
+
+ if (ct3d->hostvmem) {
+ vmr = host_memory_backend_get_memory(ct3d->hostvmem);
+ }
+ if (ct3d->hostpmem) {
+ pmr = host_memory_backend_get_memory(ct3d->hostpmem);
+ }
+
+ if (!vmr && !pmr) {
+ return false;
+ }
+
+ if (dpa_offset + 64 > ct3d->cxl_dstate.mem_size) {
+ return false;
+ }
+
+ if (vmr) {
+ if (dpa_offset < memory_region_size(vmr)) {
+ as = &ct3d->hostvmem_as;
+ } else {
+ as = &ct3d->hostpmem_as;
+ dpa_offset -= memory_region_size(vmr);
+ }
+ } else {
+ as = &ct3d->hostpmem_as;
+ }
+
+ address_space_write(as, dpa_offset, MEMTXATTRS_UNSPECIFIED, &data,
+ CXL_CACHE_LINE_SIZE);
+ return true;
+}
+
void cxl_set_poison_list_overflowed(CXLType3Dev *ct3d)
{
ct3d->poison_list_overflowed = true;
@@ -1168,6 +1204,7 @@ static void ct3_class_init(ObjectClass *oc, void *data)
cvc->get_lsa_size = get_lsa_size;
cvc->get_lsa = get_lsa;
cvc->set_lsa = set_lsa;
+ cvc->set_cacheline = set_cacheline;
}
static const TypeInfo ct3d_info = {
diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h
index 32c234ea91..73328a52cf 100644
--- a/include/hw/cxl/cxl_device.h
+++ b/include/hw/cxl/cxl_device.h
@@ -298,6 +298,7 @@ struct CXLType3Class {
uint64_t offset);
void (*set_lsa)(CXLType3Dev *ct3d, const void *buf, uint64_t size,
uint64_t offset);
+ bool (*set_cacheline)(CXLType3Dev *ct3d, uint64_t dpa_offset, uint8_t *data);
};
MemTxResult cxl_type3_read(PCIDevice *d, hwaddr host_addr, uint64_t *data,
--
2.39.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH v6 1/4] bswap: Add the ability to store to an unaligned 24 bit field
2023-05-19 14:18 ` [PATCH v6 1/4] bswap: Add the ability to store to an unaligned 24 bit field Jonathan Cameron via
@ 2023-05-19 16:08 ` Philippe Mathieu-Daudé
2023-05-19 16:24 ` Jonathan Cameron via
2023-05-20 12:37 ` Peter Maydell
1 sibling, 1 reply; 17+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-05-19 16:08 UTC (permalink / raw)
To: Jonathan Cameron, qemu-devel, Michael Tsirkin, Fan Ni
Cc: linux-cxl, linuxarm, Ira Weiny, Michael Roth, Dave Jiang,
Markus Armbruster, Daniel P . Berrangé, Eric Blake,
Mike Maslenkin, Marc-André Lureau, Thomas Huth
On 19/5/23 16:18, Jonathan Cameron wrote:
> From: Ira Weiny <ira.weiny@intel.com>
>
> CXL has 24 bit unaligned fields which need to be stored to. CXL is
> specified as little endian.
>
> Define st24_le_p() and the supporting functions to store such a field
> from a 32 bit host native value.
>
> The use of b, w, l, q as the size specifier is limiting. So "24" was
> used for the size part of the function name.
>
> Signed-off-by: Ira Weiny <ira.weiny@intel.com>
> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> ---
> docs/devel/loads-stores.rst | 1 +
> include/qemu/bswap.h | 27 +++++++++++++++++++++++++++
> 2 files changed, 28 insertions(+)
>
> diff --git a/docs/devel/loads-stores.rst b/docs/devel/loads-stores.rst
> index d2cefc77a2..82a79e91d9 100644
> --- a/docs/devel/loads-stores.rst
> +++ b/docs/devel/loads-stores.rst
> @@ -36,6 +36,7 @@ store: ``st{size}_{endian}_p(ptr, val)``
> ``size``
> - ``b`` : 8 bits
> - ``w`` : 16 bits
> + - ``24`` : 24 bits
> - ``l`` : 32 bits
> - ``q`` : 64 bits
>
> diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h
> index 15a78c0db5..f546b1fc06 100644
> --- a/include/qemu/bswap.h
> +++ b/include/qemu/bswap.h
> @@ -8,11 +8,25 @@
> #undef bswap64
> #define bswap64(_x) __builtin_bswap64(_x)
>
> +static inline uint32_t bswap24(uint32_t x)
> +{
> + assert((x & 0xff000000U) == 0);
Asserting here is a bit violent. In particular because there is no
contract description that x should be less than N bits for bswapN()
in "qemu/bswap.h" API.
But if you rather to assert ...
> +
> + return (((x & 0x000000ffU) << 16) |
> + ((x & 0x0000ff00U) << 0) |
> + ((x & 0x00ff0000U) >> 16));
> +}
> +
> static inline void bswap16s(uint16_t *s)
> {
> *s = __builtin_bswap16(*s);
> }
>
> +static inline void bswap24s(uint32_t *s)
> +{
> + *s = bswap24(*s & 0x00ffffffU);
... and sanitize the value here ...
> +}
> +
> static inline void bswap32s(uint32_t *s)
> {
> *s = __builtin_bswap32(*s);
> @@ -26,11 +40,13 @@ static inline void bswap64s(uint64_t *s)
> #if HOST_BIG_ENDIAN
> #define be_bswap(v, size) (v)
> #define le_bswap(v, size) glue(__builtin_bswap, size)(v)
> +#define le_bswap24(v) bswap24(v)
... then shouldn't you sanitize also here?
Personally I'd just drop the assertion.
> #define be_bswaps(v, size)
> #define le_bswaps(p, size) \
> do { *p = glue(__builtin_bswap, size)(*p); } while (0)
> #else
> #define le_bswap(v, size) (v)
> +#define le_bswap24(v) (v)
> #define be_bswap(v, size) glue(__builtin_bswap, size)(v)
> #define le_bswaps(v, size)
> #define be_bswaps(p, size) \
> @@ -176,6 +192,7 @@ CPU_CONVERT(le, 64, uint64_t)
> * size is:
> * b: 8 bits
> * w: 16 bits
> + * 24: 24 bits
> * l: 32 bits
> * q: 64 bits
> *
> @@ -248,6 +265,11 @@ static inline void stw_he_p(void *ptr, uint16_t v)
> __builtin_memcpy(ptr, &v, sizeof(v));
> }
>
> +static inline void st24_he_p(void *ptr, uint32_t v)
> +{
> + __builtin_memcpy(ptr, &v, 3);
> +}
> +
> static inline int ldl_he_p(const void *ptr)
> {
> int32_t r;
> @@ -297,6 +319,11 @@ static inline void stw_le_p(void *ptr, uint16_t v)
> stw_he_p(ptr, le_bswap(v, 16));
> }
>
> +static inline void st24_le_p(void *ptr, uint32_t v)
> +{
> + st24_he_p(ptr, le_bswap24(v));
> +}
> +
> static inline void stl_le_p(void *ptr, uint32_t v)
> {
> stl_he_p(ptr, le_bswap(v, 32));
Conditional to removing the assertion in bswap24():
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v6 1/4] bswap: Add the ability to store to an unaligned 24 bit field
2023-05-19 16:08 ` Philippe Mathieu-Daudé
@ 2023-05-19 16:24 ` Jonathan Cameron via
2023-05-19 16:43 ` Philippe Mathieu-Daudé
0 siblings, 1 reply; 17+ messages in thread
From: Jonathan Cameron via @ 2023-05-19 16:24 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: qemu-devel, Michael Tsirkin, Fan Ni, linux-cxl, linuxarm,
Ira Weiny, Michael Roth, Dave Jiang, Markus Armbruster,
Daniel P . Berrangé, Eric Blake, Mike Maslenkin,
Marc-André Lureau, Thomas Huth
On Fri, 19 May 2023 18:08:30 +0200
Philippe Mathieu-Daudé <philmd@linaro.org> wrote:
> On 19/5/23 16:18, Jonathan Cameron wrote:
> > From: Ira Weiny <ira.weiny@intel.com>
> >
> > CXL has 24 bit unaligned fields which need to be stored to. CXL is
> > specified as little endian.
> >
> > Define st24_le_p() and the supporting functions to store such a field
> > from a 32 bit host native value.
> >
> > The use of b, w, l, q as the size specifier is limiting. So "24" was
> > used for the size part of the function name.
> >
> > Signed-off-by: Ira Weiny <ira.weiny@intel.com>
> > Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> > ---
> > docs/devel/loads-stores.rst | 1 +
> > include/qemu/bswap.h | 27 +++++++++++++++++++++++++++
> > 2 files changed, 28 insertions(+)
> >
> > diff --git a/docs/devel/loads-stores.rst b/docs/devel/loads-stores.rst
> > index d2cefc77a2..82a79e91d9 100644
> > --- a/docs/devel/loads-stores.rst
> > +++ b/docs/devel/loads-stores.rst
> > @@ -36,6 +36,7 @@ store: ``st{size}_{endian}_p(ptr, val)``
> > ``size``
> > - ``b`` : 8 bits
> > - ``w`` : 16 bits
> > + - ``24`` : 24 bits
> > - ``l`` : 32 bits
> > - ``q`` : 64 bits
> >
> > diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h
> > index 15a78c0db5..f546b1fc06 100644
> > --- a/include/qemu/bswap.h
> > +++ b/include/qemu/bswap.h
> > @@ -8,11 +8,25 @@
> > #undef bswap64
> > #define bswap64(_x) __builtin_bswap64(_x)
> >
> > +static inline uint32_t bswap24(uint32_t x)
> > +{
> > + assert((x & 0xff000000U) == 0);
>
> Asserting here is a bit violent. In particular because there is no
> contract description that x should be less than N bits for bswapN()
> in "qemu/bswap.h" API.
>
> But if you rather to assert ...
I'm fine either way. You asked for it when reviewing v4...
https://lore.kernel.org/all/28a9d97a-b252-a33f-1ac0-cd36264b29ab@linaro.org/
>
> > +
> > + return (((x & 0x000000ffU) << 16) |
> > + ((x & 0x0000ff00U) << 0) |
> > + ((x & 0x00ff0000U) >> 16));
> > +}
> > +
> > static inline void bswap16s(uint16_t *s)
> > {
> > *s = __builtin_bswap16(*s);
> > }
> >
> > +static inline void bswap24s(uint32_t *s)
> > +{
> > + *s = bswap24(*s & 0x00ffffffU);
>
> ... and sanitize the value here ...
>
> > +}
> > +
> > static inline void bswap32s(uint32_t *s)
> > {
> > *s = __builtin_bswap32(*s);
> > @@ -26,11 +40,13 @@ static inline void bswap64s(uint64_t *s)
> > #if HOST_BIG_ENDIAN
> > #define be_bswap(v, size) (v)
> > #define le_bswap(v, size) glue(__builtin_bswap, size)(v)
> > +#define le_bswap24(v) bswap24(v)
>
> ... then shouldn't you sanitize also here?
>
Good point. I forgot that detail whilst fighting with s390
cross builds earlier ;)
> Personally I'd just drop the assertion.
I'm fine with doing that.
Jonathan
>
> > #define be_bswaps(v, size)
> > #define le_bswaps(p, size) \
> > do { *p = glue(__builtin_bswap, size)(*p); } while (0)
> > #else
> > #define le_bswap(v, size) (v)
> > +#define le_bswap24(v) (v)
> > #define be_bswap(v, size) glue(__builtin_bswap, size)(v)
> > #define le_bswaps(v, size)
> > #define be_bswaps(p, size) \
> > @@ -176,6 +192,7 @@ CPU_CONVERT(le, 64, uint64_t)
> > * size is:
> > * b: 8 bits
> > * w: 16 bits
> > + * 24: 24 bits
> > * l: 32 bits
> > * q: 64 bits
> > *
> > @@ -248,6 +265,11 @@ static inline void stw_he_p(void *ptr, uint16_t v)
> > __builtin_memcpy(ptr, &v, sizeof(v));
> > }
> >
> > +static inline void st24_he_p(void *ptr, uint32_t v)
> > +{
> > + __builtin_memcpy(ptr, &v, 3);
> > +}
> > +
> > static inline int ldl_he_p(const void *ptr)
> > {
> > int32_t r;
> > @@ -297,6 +319,11 @@ static inline void stw_le_p(void *ptr, uint16_t v)
> > stw_he_p(ptr, le_bswap(v, 16));
> > }
> >
> > +static inline void st24_le_p(void *ptr, uint32_t v)
> > +{
> > + st24_he_p(ptr, le_bswap24(v));
> > +}
> > +
> > static inline void stl_le_p(void *ptr, uint32_t v)
> > {
> > stl_he_p(ptr, le_bswap(v, 32));
>
> Conditional to removing the assertion in bswap24():
> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v6 1/4] bswap: Add the ability to store to an unaligned 24 bit field
2023-05-19 16:24 ` Jonathan Cameron via
@ 2023-05-19 16:43 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 17+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-05-19 16:43 UTC (permalink / raw)
To: Jonathan Cameron
Cc: qemu-devel, Michael Tsirkin, Fan Ni, linux-cxl, linuxarm,
Ira Weiny, Michael Roth, Dave Jiang, Markus Armbruster,
Daniel P . Berrangé, Eric Blake, Mike Maslenkin,
Marc-André Lureau, Thomas Huth
On 19/5/23 18:24, Jonathan Cameron wrote:
> On Fri, 19 May 2023 18:08:30 +0200
> Philippe Mathieu-Daudé <philmd@linaro.org> wrote:
>
>> On 19/5/23 16:18, Jonathan Cameron wrote:
>>> From: Ira Weiny <ira.weiny@intel.com>
>>>
>>> CXL has 24 bit unaligned fields which need to be stored to. CXL is
>>> specified as little endian.
>>>
>>> Define st24_le_p() and the supporting functions to store such a field
>>> from a 32 bit host native value.
>>>
>>> The use of b, w, l, q as the size specifier is limiting. So "24" was
>>> used for the size part of the function name.
>>>
>>> Signed-off-by: Ira Weiny <ira.weiny@intel.com>
>>> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
>>> ---
>>> docs/devel/loads-stores.rst | 1 +
>>> include/qemu/bswap.h | 27 +++++++++++++++++++++++++++
>>> 2 files changed, 28 insertions(+)
>>>
>>> diff --git a/docs/devel/loads-stores.rst b/docs/devel/loads-stores.rst
>>> index d2cefc77a2..82a79e91d9 100644
>>> --- a/docs/devel/loads-stores.rst
>>> +++ b/docs/devel/loads-stores.rst
>>> @@ -36,6 +36,7 @@ store: ``st{size}_{endian}_p(ptr, val)``
>>> ``size``
>>> - ``b`` : 8 bits
>>> - ``w`` : 16 bits
>>> + - ``24`` : 24 bits
>>> - ``l`` : 32 bits
>>> - ``q`` : 64 bits
>>>
>>> diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h
>>> index 15a78c0db5..f546b1fc06 100644
>>> --- a/include/qemu/bswap.h
>>> +++ b/include/qemu/bswap.h
>>> @@ -8,11 +8,25 @@
>>> #undef bswap64
>>> #define bswap64(_x) __builtin_bswap64(_x)
>>>
>>> +static inline uint32_t bswap24(uint32_t x)
>>> +{
>>> + assert((x & 0xff000000U) == 0);
>>
>> Asserting here is a bit violent. In particular because there is no
>> contract description that x should be less than N bits for bswapN()
>> in "qemu/bswap.h" API.
>>
>> But if you rather to assert ...
>
>
> I'm fine either way. You asked for it when reviewing v4...
> https://lore.kernel.org/all/28a9d97a-b252-a33f-1ac0-cd36264b29ab@linaro.org/
Never too late to improve oneself ;)
One month later I'm afraid the assertion would fire too often,
resulting in unnecessary pain to developers (in particular the
non-QEMU ones).
>>
>>> +
>>> + return (((x & 0x000000ffU) << 16) |
>>> + ((x & 0x0000ff00U) << 0) |
>>> + ((x & 0x00ff0000U) >> 16));
>>> +}
>>> +
>>> static inline void bswap16s(uint16_t *s)
>>> {
>>> *s = __builtin_bswap16(*s);
>>> }
>>>
>>> +static inline void bswap24s(uint32_t *s)
>>> +{
>>> + *s = bswap24(*s & 0x00ffffffU);
>>
>> ... and sanitize the value here ...
>>
>>> +}
>>> +
>>> static inline void bswap32s(uint32_t *s)
>>> {
>>> *s = __builtin_bswap32(*s);
>>> @@ -26,11 +40,13 @@ static inline void bswap64s(uint64_t *s)
>>> #if HOST_BIG_ENDIAN
>>> #define be_bswap(v, size) (v)
>>> #define le_bswap(v, size) glue(__builtin_bswap, size)(v)
>>> +#define le_bswap24(v) bswap24(v)
>>
>> ... then shouldn't you sanitize also here?
>>
>
> Good point. I forgot that detail whilst fighting with s390
> cross builds earlier ;)
>
>> Personally I'd just drop the assertion.
>
> I'm fine with doing that.
>
> Jonathan
>
>>
>>> #define be_bswaps(v, size)
>>> #define le_bswaps(p, size) \
>>> do { *p = glue(__builtin_bswap, size)(*p); } while (0)
>>> #else
>>> #define le_bswap(v, size) (v)
>>> +#define le_bswap24(v) (v)
>>> #define be_bswap(v, size) glue(__builtin_bswap, size)(v)
>>> #define le_bswaps(v, size)
>>> #define be_bswaps(p, size) \
>>> @@ -176,6 +192,7 @@ CPU_CONVERT(le, 64, uint64_t)
>>> * size is:
>>> * b: 8 bits
>>> * w: 16 bits
>>> + * 24: 24 bits
>>> * l: 32 bits
>>> * q: 64 bits
>>> *
>>> @@ -248,6 +265,11 @@ static inline void stw_he_p(void *ptr, uint16_t v)
>>> __builtin_memcpy(ptr, &v, sizeof(v));
>>> }
>>>
>>> +static inline void st24_he_p(void *ptr, uint32_t v)
>>> +{
>>> + __builtin_memcpy(ptr, &v, 3);
>>> +}
>>> +
>>> static inline int ldl_he_p(const void *ptr)
>>> {
>>> int32_t r;
>>> @@ -297,6 +319,11 @@ static inline void stw_le_p(void *ptr, uint16_t v)
>>> stw_he_p(ptr, le_bswap(v, 16));
>>> }
>>>
>>> +static inline void st24_le_p(void *ptr, uint32_t v)
>>> +{
>>> + st24_he_p(ptr, le_bswap24(v));
>>> +}
>>> +
>>> static inline void stl_le_p(void *ptr, uint32_t v)
>>> {
>>> stl_he_p(ptr, le_bswap(v, 32));
>>
>> Conditional to removing the assertion in bswap24():
>> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
>>
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v6 4/4] hw/cxl: Add clear poison mailbox command support.
2023-05-19 14:18 ` [PATCH v6 4/4] hw/cxl: Add clear poison mailbox command support Jonathan Cameron via
@ 2023-05-19 17:48 ` Ira Weiny
0 siblings, 0 replies; 17+ messages in thread
From: Ira Weiny @ 2023-05-19 17:48 UTC (permalink / raw)
To: Jonathan Cameron, qemu-devel, Michael Tsirkin, Fan Ni
Cc: linux-cxl, linuxarm, Ira Weiny, Michael Roth,
Philippe Mathieu-Daudé, Dave Jiang, Markus Armbruster,
Daniel P . Berrangé, Eric Blake, Mike Maslenkin,
Marc-André Lureau, Thomas Huth
Jonathan Cameron wrote:
> Current implementation is very simple so many of the corner
> cases do not exist (e.g. fragmenting larger poison list entries)
>
> Reviewed-by: Fan Ni <fan.ni@samsung.com>
Minor nit below. Otherwise looks good.
Reviewed-by: Ira Weiny <ira.weiny@intel.com>
> diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
> index ab600735eb..84022d7ae3 100644
> --- a/hw/mem/cxl_type3.c
> +++ b/hw/mem/cxl_type3.c
> @@ -947,6 +947,42 @@ static void set_lsa(CXLType3Dev *ct3d, const void *buf, uint64_t size,
> */
> }
>
> +static bool set_cacheline(CXLType3Dev *ct3d, uint64_t dpa_offset, uint8_t *data)
> +{
> + MemoryRegion *vmr = NULL, *pmr = NULL;
> + AddressSpace *as;
> +
> + if (ct3d->hostvmem) {
> + vmr = host_memory_backend_get_memory(ct3d->hostvmem);
> + }
> + if (ct3d->hostpmem) {
> + pmr = host_memory_backend_get_memory(ct3d->hostpmem);
> + }
> +
> + if (!vmr && !pmr) {
> + return false;
> + }
> +
> + if (dpa_offset + 64 > ct3d->cxl_dstate.mem_size) {
NIT: s/64/CXL_CACHE_LINE_SIZE/
Ira
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v6 1/4] bswap: Add the ability to store to an unaligned 24 bit field
2023-05-19 14:18 ` [PATCH v6 1/4] bswap: Add the ability to store to an unaligned 24 bit field Jonathan Cameron via
2023-05-19 16:08 ` Philippe Mathieu-Daudé
@ 2023-05-20 12:37 ` Peter Maydell
2023-05-20 13:15 ` BALATON Zoltan
2023-05-22 11:59 ` Jonathan Cameron via
1 sibling, 2 replies; 17+ messages in thread
From: Peter Maydell @ 2023-05-20 12:37 UTC (permalink / raw)
To: Jonathan Cameron
Cc: qemu-devel, Michael Tsirkin, Fan Ni, linux-cxl, linuxarm,
Ira Weiny, Michael Roth, Philippe Mathieu-Daudé, Dave Jiang,
Markus Armbruster, Daniel P . Berrangé, Eric Blake,
Mike Maslenkin, Marc-André Lureau, Thomas Huth
On Fri, 19 May 2023 at 15:19, Jonathan Cameron via
<qemu-devel@nongnu.org> wrote:
>
> From: Ira Weiny <ira.weiny@intel.com>
>
> CXL has 24 bit unaligned fields which need to be stored to. CXL is
> specified as little endian.
>
> Define st24_le_p() and the supporting functions to store such a field
> from a 32 bit host native value.
>
> The use of b, w, l, q as the size specifier is limiting. So "24" was
> used for the size part of the function name.
>
> Signed-off-by: Ira Weiny <ira.weiny@intel.com>
> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> ---
> docs/devel/loads-stores.rst | 1 +
> include/qemu/bswap.h | 27 +++++++++++++++++++++++++++
> 2 files changed, 28 insertions(+)
>
> diff --git a/docs/devel/loads-stores.rst b/docs/devel/loads-stores.rst
> index d2cefc77a2..82a79e91d9 100644
> --- a/docs/devel/loads-stores.rst
> +++ b/docs/devel/loads-stores.rst
> @@ -36,6 +36,7 @@ store: ``st{size}_{endian}_p(ptr, val)``
> ``size``
> - ``b`` : 8 bits
> - ``w`` : 16 bits
> + - ``24`` : 24 bits
> - ``l`` : 32 bits
> - ``q`` : 64 bits
Can you also update the "Regexes for git grep" section
below to account for the new size value, please?
thanks
-- PMM
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v6 1/4] bswap: Add the ability to store to an unaligned 24 bit field
2023-05-20 12:37 ` Peter Maydell
@ 2023-05-20 13:15 ` BALATON Zoltan
2023-05-20 15:15 ` Richard Henderson
2023-05-22 11:59 ` Jonathan Cameron via
1 sibling, 1 reply; 17+ messages in thread
From: BALATON Zoltan @ 2023-05-20 13:15 UTC (permalink / raw)
To: Peter Maydell
Cc: Jonathan Cameron, qemu-devel, Michael Tsirkin, Fan Ni, linux-cxl,
linuxarm, Ira Weiny, Michael Roth, Philippe Mathieu-Daudé,
Dave Jiang, Markus Armbruster, Daniel P . Berrangé,
Eric Blake, Mike Maslenkin, Marc-André Lureau, Thomas Huth
On Sat, 20 May 2023, Peter Maydell wrote:
> On Fri, 19 May 2023 at 15:19, Jonathan Cameron via
> <qemu-devel@nongnu.org> wrote:
>>
>> From: Ira Weiny <ira.weiny@intel.com>
>>
>> CXL has 24 bit unaligned fields which need to be stored to. CXL is
>> specified as little endian.
>>
>> Define st24_le_p() and the supporting functions to store such a field
>> from a 32 bit host native value.
>>
>> The use of b, w, l, q as the size specifier is limiting. So "24" was
>> used for the size part of the function name.
Maybe it's clearer to use 24 but if we want to keep these somewhat
consistent how about using t for Triplet, Three-bytes or Twenty-four?
Regards,
BALATON Zoltan
>> Signed-off-by: Ira Weiny <ira.weiny@intel.com>
>> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
>> ---
>> docs/devel/loads-stores.rst | 1 +
>> include/qemu/bswap.h | 27 +++++++++++++++++++++++++++
>> 2 files changed, 28 insertions(+)
>>
>> diff --git a/docs/devel/loads-stores.rst b/docs/devel/loads-stores.rst
>> index d2cefc77a2..82a79e91d9 100644
>> --- a/docs/devel/loads-stores.rst
>> +++ b/docs/devel/loads-stores.rst
>> @@ -36,6 +36,7 @@ store: ``st{size}_{endian}_p(ptr, val)``
>> ``size``
>> - ``b`` : 8 bits
>> - ``w`` : 16 bits
>> + - ``24`` : 24 bits
>> - ``l`` : 32 bits
>> - ``q`` : 64 bits
>
> Can you also update the "Regexes for git grep" section
> below to account for the new size value, please?
>
> thanks
> -- PMM
>
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v6 1/4] bswap: Add the ability to store to an unaligned 24 bit field
2023-05-20 13:15 ` BALATON Zoltan
@ 2023-05-20 15:15 ` Richard Henderson
2023-05-20 17:08 ` Philippe Mathieu-Daudé
0 siblings, 1 reply; 17+ messages in thread
From: Richard Henderson @ 2023-05-20 15:15 UTC (permalink / raw)
To: BALATON Zoltan, Peter Maydell
Cc: Jonathan Cameron, qemu-devel, Michael Tsirkin, Fan Ni, linux-cxl,
linuxarm, Ira Weiny, Michael Roth, Philippe Mathieu-Daudé,
Dave Jiang, Markus Armbruster, Daniel P . Berrangé,
Eric Blake, Mike Maslenkin, Marc-André Lureau, Thomas Huth
On 5/20/23 06:15, BALATON Zoltan wrote:
> On Sat, 20 May 2023, Peter Maydell wrote:
>> On Fri, 19 May 2023 at 15:19, Jonathan Cameron via
>> <qemu-devel@nongnu.org> wrote:
>>>
>>> From: Ira Weiny <ira.weiny@intel.com>
>>>
>>> CXL has 24 bit unaligned fields which need to be stored to. CXL is
>>> specified as little endian.
>>>
>>> Define st24_le_p() and the supporting functions to store such a field
>>> from a 32 bit host native value.
>>>
>>> The use of b, w, l, q as the size specifier is limiting. So "24" was
>>> used for the size part of the function name.
>
> Maybe it's clearer to use 24 but if we want to keep these somewhat consistent how about
> using t for Triplet, Three-bytes or Twenty-four?
I think it's clearer to use '3'.
When I added 128-bit support I used cpu_ld16_mmu.
I think it would be clearer to not use letters anywhere, and to use units of bytes instead
of units of bits (no one can store just a bit), but changing everything is a big job.
r~
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v6 1/4] bswap: Add the ability to store to an unaligned 24 bit field
2023-05-20 15:15 ` Richard Henderson
@ 2023-05-20 17:08 ` Philippe Mathieu-Daudé
2023-05-21 9:05 ` Michael S. Tsirkin
2023-05-22 12:09 ` Jonathan Cameron via
0 siblings, 2 replies; 17+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-05-20 17:08 UTC (permalink / raw)
To: Richard Henderson, BALATON Zoltan, Peter Maydell
Cc: Jonathan Cameron, qemu-devel, Michael Tsirkin, Fan Ni, linux-cxl,
linuxarm, Ira Weiny, Michael Roth, Dave Jiang, Markus Armbruster,
Daniel P . Berrangé, Eric Blake, Mike Maslenkin,
Marc-André Lureau, Thomas Huth
On 20/5/23 17:15, Richard Henderson wrote:
> On 5/20/23 06:15, BALATON Zoltan wrote:
>> On Sat, 20 May 2023, Peter Maydell wrote:
>>> On Fri, 19 May 2023 at 15:19, Jonathan Cameron via
>>> <qemu-devel@nongnu.org> wrote:
>>>>
>>>> From: Ira Weiny <ira.weiny@intel.com>
>>>>
>>>> CXL has 24 bit unaligned fields which need to be stored to. CXL is
>>>> specified as little endian.
>>>>
>>>> Define st24_le_p() and the supporting functions to store such a field
>>>> from a 32 bit host native value.
>>>>
>>>> The use of b, w, l, q as the size specifier is limiting. So "24" was
>>>> used for the size part of the function name.
>>
>> Maybe it's clearer to use 24 but if we want to keep these somewhat
>> consistent how about using t for Triplet, Three-bytes or Twenty-four?
>
> I think it's clearer to use '3'.
> When I added 128-bit support I used cpu_ld16_mmu.
There is also ld8u / ld8s / st8.
> I think it would be clearer to not use letters anywhere, and to use
> units of bytes instead of units of bits (no one can store just a bit),
> but changing everything is a big job.
So:
ldub -> ld1u,
lduw_le -> ld2u_le,
virtio_stl -> virtio_st4,
stq_be -> st8_be.
Right?
Also we have:
cpu_ld/st_*
virtio_ld/st_*
ld/st_*_phys
ld/st_*_pci_dma
address_space_ld/st
While mass-changing, we could use FOO_ld/st_BAR with FOO
for API and BAR for API variant (endian, mmuidx, ra, ...):
So:
ld/st_*_pci_dma -> pci_dma_ld/st_*
for ld/st_*_phys I'm not sure.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v6 1/4] bswap: Add the ability to store to an unaligned 24 bit field
2023-05-20 17:08 ` Philippe Mathieu-Daudé
@ 2023-05-21 9:05 ` Michael S. Tsirkin
2023-05-22 12:09 ` Jonathan Cameron via
1 sibling, 0 replies; 17+ messages in thread
From: Michael S. Tsirkin @ 2023-05-21 9:05 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: Richard Henderson, BALATON Zoltan, Peter Maydell,
Jonathan Cameron, qemu-devel, Fan Ni, linux-cxl, linuxarm,
Ira Weiny, Michael Roth, Dave Jiang, Markus Armbruster,
Daniel P . Berrangé, Eric Blake, Mike Maslenkin,
Marc-André Lureau, Thomas Huth
On Sat, May 20, 2023 at 07:08:22PM +0200, Philippe Mathieu-Daudé wrote:
> On 20/5/23 17:15, Richard Henderson wrote:
> > On 5/20/23 06:15, BALATON Zoltan wrote:
> > > On Sat, 20 May 2023, Peter Maydell wrote:
> > > > On Fri, 19 May 2023 at 15:19, Jonathan Cameron via
> > > > <qemu-devel@nongnu.org> wrote:
> > > > >
> > > > > From: Ira Weiny <ira.weiny@intel.com>
> > > > >
> > > > > CXL has 24 bit unaligned fields which need to be stored to. CXL is
> > > > > specified as little endian.
> > > > >
> > > > > Define st24_le_p() and the supporting functions to store such a field
> > > > > from a 32 bit host native value.
> > > > >
> > > > > The use of b, w, l, q as the size specifier is limiting. So "24" was
> > > > > used for the size part of the function name.
> > >
> > > Maybe it's clearer to use 24 but if we want to keep these somewhat
> > > consistent how about using t for Triplet, Three-bytes or
> > > Twenty-four?
> >
> > I think it's clearer to use '3'.
> > When I added 128-bit support I used cpu_ld16_mmu.
>
> There is also ld8u / ld8s / st8.
>
> > I think it would be clearer to not use letters anywhere, and to use
> > units of bytes instead of units of bits (no one can store just a bit),
> > but changing everything is a big job.
>
> So:
>
> ldub -> ld1u,
>
> lduw_le -> ld2u_le,
>
> virtio_stl -> virtio_st4,
>
> stq_be -> st8_be.
>
> Right?
No, using bits is so ingrained by now, that people will think
st8 is a single byte.
And yes, you can store a bit - you have to read modify write but
hey.
> Also we have:
>
> cpu_ld/st_*
> virtio_ld/st_*
> ld/st_*_phys
> ld/st_*_pci_dma
> address_space_ld/st
>
> While mass-changing, we could use FOO_ld/st_BAR with FOO
> for API and BAR for API variant (endian, mmuidx, ra, ...):
>
> So:
>
> ld/st_*_pci_dma -> pci_dma_ld/st_*
>
> for ld/st_*_phys I'm not sure.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v6 2/4] hw/cxl: QMP based poison injection support
2023-05-19 14:18 ` [PATCH v6 2/4] hw/cxl: QMP based poison injection support Jonathan Cameron via
@ 2023-05-22 11:20 ` Jonathan Cameron via
0 siblings, 0 replies; 17+ messages in thread
From: Jonathan Cameron via @ 2023-05-22 11:20 UTC (permalink / raw)
To: qemu-devel, Michael Tsirkin, Fan Ni
Cc: linux-cxl, Ira Weiny, Michael Roth, Philippe Mathieu-Daudé,
Dave Jiang, Markus Armbruster, Daniel P . Berrangé,
Eric Blake, Mike Maslenkin, Marc-André Lureau, Thomas Huth
On Fri, 19 May 2023 15:18:01 +0100
Jonathan Cameron <Jonathan.Cameron@huawei.com> wrote:
> Inject poison using qmp command cxl-inject-poison to add an entry to the
> poison list.
>
> For now, the poison is not returned CXL.mem reads, but only via the
> mailbox command Get Poison List. So a normal memory read to an address
> that is on the poison list will not yet result in a synchronous exception
> (and similar for partial cacheline writes).
> That is left for a future patch.
>
> See CXL rev 3.0, sec 8.2.9.8.4.1 Get Poison list (Opcode 4300h)
>
> Kernel patches to use this interface here:
> https://lore.kernel.org/linux-cxl/cover.1665606782.git.alison.schofield@intel.com/
>
> To inject poison using qmp (telnet to the qmp port)
> { "execute": "qmp_capabilities" }
>
> { "execute": "cxl-inject-poison",
> "arguments": {
> "path": "/machine/peripheral/cxl-pmem0",
> "start": 2048,
> "length": 256
> }
> }
>
> Adjusted to select a device on your machine.
>
> Note that the poison list supported is kept short enough to avoid the
> complexity of state machine that is needed to handle the MORE flag.
>
> Reviewed-by: Fan Ni <fan.ni@samsung.com>
> Reviewed-by: Ira Weiny <ira.weiny@intel.com>
> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
For reference. Markus Armbruster gave some feedback on v5 that crossed this this.
I'll incorporate into v7.
Thanks,
Jonathan
> ---
> hw/cxl/cxl-mailbox-utils.c | 90 +++++++++++++++++++++++++++++++++++++
> hw/mem/cxl_type3.c | 56 +++++++++++++++++++++++
> hw/mem/cxl_type3_stubs.c | 6 +++
> include/hw/cxl/cxl.h | 1 +
> include/hw/cxl/cxl_device.h | 20 +++++++++
> qapi/cxl.json | 18 ++++++++
> 6 files changed, 191 insertions(+)
>
> diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
> index 702e16ca20..1f74b26ea2 100644
> --- a/hw/cxl/cxl-mailbox-utils.c
> +++ b/hw/cxl/cxl-mailbox-utils.c
> @@ -62,6 +62,8 @@ enum {
> #define GET_PARTITION_INFO 0x0
> #define GET_LSA 0x2
> #define SET_LSA 0x3
> + MEDIA_AND_POISON = 0x43,
> + #define GET_POISON_LIST 0x0
> };
>
> /* 8.2.8.4.5.1 Command Return Codes */
> @@ -295,6 +297,10 @@ static CXLRetCode cmd_identify_memory_device(struct cxl_cmd *cmd,
> stq_le_p(&id->persistent_capacity, cxl_dstate->pmem_size / CXL_CAPACITY_MULTIPLIER);
> stq_le_p(&id->volatile_capacity, cxl_dstate->vmem_size / CXL_CAPACITY_MULTIPLIER);
> stl_le_p(&id->lsa_size, cvc->get_lsa_size(ct3d));
> + /* 256 poison records */
> + st24_le_p(id->poison_list_max_mer, 256);
> + /* No limit - so limited by main poison record limit */
> + stw_le_p(&id->inject_poison_limit, 0);
>
> *len = sizeof(*id);
> return CXL_MBOX_SUCCESS;
> @@ -384,6 +390,88 @@ static CXLRetCode cmd_ccls_set_lsa(struct cxl_cmd *cmd,
> return CXL_MBOX_SUCCESS;
> }
>
> +/*
> + * This is very inefficient, but good enough for now!
> + * Also the payload will always fit, so no need to handle the MORE flag and
> + * make this stateful. We may want to allow longer poison lists to aid
> + * testing that kernel functionality.
> + */
> +static CXLRetCode cmd_media_get_poison_list(struct cxl_cmd *cmd,
> + CXLDeviceState *cxl_dstate,
> + uint16_t *len)
> +{
> + struct get_poison_list_pl {
> + uint64_t pa;
> + uint64_t length;
> + } QEMU_PACKED;
> +
> + struct get_poison_list_out_pl {
> + uint8_t flags;
> + uint8_t rsvd1;
> + uint64_t overflow_timestamp;
> + uint16_t count;
> + uint8_t rsvd2[0x14];
> + struct {
> + uint64_t addr;
> + uint32_t length;
> + uint32_t resv;
> + } QEMU_PACKED records[];
> + } QEMU_PACKED;
> +
> + struct get_poison_list_pl *in = (void *)cmd->payload;
> + struct get_poison_list_out_pl *out = (void *)cmd->payload;
> + CXLType3Dev *ct3d = container_of(cxl_dstate, CXLType3Dev, cxl_dstate);
> + uint16_t record_count = 0, i = 0;
> + uint64_t query_start, query_length;
> + CXLPoisonList *poison_list = &ct3d->poison_list;
> + CXLPoison *ent;
> + uint16_t out_pl_len;
> +
> + query_start = ldq_le_p(&in->pa);
> + /* 64 byte alignemnt required */
> + if (query_start & 0x3f) {
> + return CXL_MBOX_INVALID_INPUT;
> + }
> + query_length = ldq_le_p(&in->length) * CXL_CACHE_LINE_SIZE;
> +
> + QLIST_FOREACH(ent, poison_list, node) {
> + /* Check for no overlap */
> + if (ent->start >= query_start + query_length ||
> + ent->start + ent->length <= query_start) {
> + continue;
> + }
> + record_count++;
> + }
> + out_pl_len = sizeof(*out) + record_count * sizeof(out->records[0]);
> + assert(out_pl_len <= CXL_MAILBOX_MAX_PAYLOAD_SIZE);
> +
> + memset(out, 0, out_pl_len);
> + QLIST_FOREACH(ent, poison_list, node) {
> + uint64_t start, stop;
> +
> + /* Check for no overlap */
> + if (ent->start >= query_start + query_length ||
> + ent->start + ent->length <= query_start) {
> + continue;
> + }
> +
> + /* Deal with overlap */
> + start = MAX(ROUND_DOWN(ent->start, 64ull), query_start);
> + stop = MIN(ROUND_DOWN(ent->start, 64ull) + ent->length,
> + query_start + query_length);
> + stq_le_p(&out->records[i].addr, start | (ent->type & 0x7));
> + stl_le_p(&out->records[i].length, (stop - start) / CXL_CACHE_LINE_SIZE);
> + i++;
> + }
> + if (ct3d->poison_list_overflowed) {
> + out->flags = (1 << 1);
> + stq_le_p(&out->overflow_timestamp, ct3d->poison_list_overflow_ts);
> + }
> + stw_le_p(&out->count, record_count);
> + *len = out_pl_len;
> + return CXL_MBOX_SUCCESS;
> +}
> +
> #define IMMEDIATE_CONFIG_CHANGE (1 << 1)
> #define IMMEDIATE_DATA_CHANGE (1 << 2)
> #define IMMEDIATE_POLICY_CHANGE (1 << 3)
> @@ -411,6 +499,8 @@ static struct cxl_cmd cxl_cmd_set[256][256] = {
> [CCLS][GET_LSA] = { "CCLS_GET_LSA", cmd_ccls_get_lsa, 8, 0 },
> [CCLS][SET_LSA] = { "CCLS_SET_LSA", cmd_ccls_set_lsa,
> ~0, IMMEDIATE_CONFIG_CHANGE | IMMEDIATE_DATA_CHANGE },
> + [MEDIA_AND_POISON][GET_POISON_LIST] = { "MEDIA_AND_POISON_GET_POISON_LIST",
> + cmd_media_get_poison_list, 16, 0 },
> };
>
> void cxl_process_mailbox(CXLDeviceState *cxl_dstate)
> diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
> index 2adacbd01b..ab600735eb 100644
> --- a/hw/mem/cxl_type3.c
> +++ b/hw/mem/cxl_type3.c
> @@ -947,6 +947,62 @@ static void set_lsa(CXLType3Dev *ct3d, const void *buf, uint64_t size,
> */
> }
>
> +void cxl_set_poison_list_overflowed(CXLType3Dev *ct3d)
> +{
> + ct3d->poison_list_overflowed = true;
> + ct3d->poison_list_overflow_ts =
> + cxl_device_get_timestamp(&ct3d->cxl_dstate);
> +}
> +
> +void qmp_cxl_inject_poison(const char *path, uint64_t start, uint64_t length,
> + Error **errp)
> +{
> + Object *obj = object_resolve_path(path, NULL);
> + CXLType3Dev *ct3d;
> + CXLPoison *p;
> +
> + if (length % 64) {
> + error_setg(errp, "Poison injection must be in multiples of 64 bytes");
> + return;
> + }
> + if (start % 64) {
> + error_setg(errp, "Poison start address must be 64 byte aligned");
> + return;
> + }
> + if (!obj) {
> + error_setg(errp, "Unable to resolve path");
> + return;
> + }
> + if (!object_dynamic_cast(obj, TYPE_CXL_TYPE3)) {
> + error_setg(errp, "Path does not point to a CXL type 3 device");
> + return;
> + }
> +
> + ct3d = CXL_TYPE3(obj);
> +
> + QLIST_FOREACH(p, &ct3d->poison_list, node) {
> + if (((start >= p->start) && (start < p->start + p->length)) ||
> + ((start + length > p->start) &&
> + (start + length <= p->start + p->length))) {
> + error_setg(errp, "Overlap with existing poisoned region not supported");
> + return;
> + }
> + }
> +
> + if (ct3d->poison_list_cnt == CXL_POISON_LIST_LIMIT) {
> + cxl_set_poison_list_overflowed(ct3d);
> + return;
> + }
> +
> + p = g_new0(CXLPoison, 1);
> + p->length = length;
> + p->start = start;
> + p->type = CXL_POISON_TYPE_INTERNAL; /* Different from injected via the mbox */
> +
> + QLIST_INSERT_HEAD(&ct3d->poison_list, p, node);
> + ct3d->poison_list_cnt++;
> +}
> +
> /* For uncorrectable errors include support for multiple header recording */
> void qmp_cxl_inject_uncorrectable_errors(const char *path,
> CXLUncorErrorRecordList *errors,
> diff --git a/hw/mem/cxl_type3_stubs.c b/hw/mem/cxl_type3_stubs.c
> index d574c58f9a..fd1166a610 100644
> --- a/hw/mem/cxl_type3_stubs.c
> +++ b/hw/mem/cxl_type3_stubs.c
> @@ -3,6 +3,12 @@
> #include "qapi/error.h"
> #include "qapi/qapi-commands-cxl.h"
>
> +void qmp_cxl_inject_poison(const char *path, uint64_t start, uint64_t length,
> + Error **errp)
> +{
> + error_setg(errp, "CXL Type 3 support is not compiled in");
> +}
> +
> void qmp_cxl_inject_uncorrectable_errors(const char *path,
> CXLUncorErrorRecordList *errors,
> Error **errp)
> diff --git a/include/hw/cxl/cxl.h b/include/hw/cxl/cxl.h
> index c453983e83..56c9e7676e 100644
> --- a/include/hw/cxl/cxl.h
> +++ b/include/hw/cxl/cxl.h
> @@ -18,6 +18,7 @@
> #include "cxl_component.h"
> #include "cxl_device.h"
>
> +#define CXL_CACHE_LINE_SIZE 64
> #define CXL_COMPONENT_REG_BAR_IDX 0
> #define CXL_DEVICE_REG_BAR_IDX 2
>
> diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h
> index 02befda0f6..32c234ea91 100644
> --- a/include/hw/cxl/cxl_device.h
> +++ b/include/hw/cxl/cxl_device.h
> @@ -242,6 +242,18 @@ typedef struct CXLError {
>
> typedef QTAILQ_HEAD(, CXLError) CXLErrorList;
>
> +typedef struct CXLPoison {
> + uint64_t start, length;
> + uint8_t type;
> +#define CXL_POISON_TYPE_EXTERNAL 0x1
> +#define CXL_POISON_TYPE_INTERNAL 0x2
> +#define CXL_POISON_TYPE_INJECTED 0x3
> + QLIST_ENTRY(CXLPoison) node;
> +} CXLPoison;
> +
> +typedef QLIST_HEAD(, CXLPoison) CXLPoisonList;
> +#define CXL_POISON_LIST_LIMIT 256
> +
> struct CXLType3Dev {
> /* Private */
> PCIDevice parent_obj;
> @@ -264,6 +276,12 @@ struct CXLType3Dev {
>
> /* Error injection */
> CXLErrorList error_list;
> +
> + /* Poison Injection - cache */
> + CXLPoisonList poison_list;
> + unsigned int poison_list_cnt;
> + bool poison_list_overflowed;
> + uint64_t poison_list_overflow_ts;
> };
>
> #define TYPE_CXL_TYPE3 "cxl-type3"
> @@ -289,4 +307,6 @@ MemTxResult cxl_type3_write(PCIDevice *d, hwaddr host_addr, uint64_t data,
>
> uint64_t cxl_device_get_timestamp(CXLDeviceState *cxlds);
>
> +void cxl_set_poison_list_overflowed(CXLType3Dev *ct3d);
> +
> #endif
> diff --git a/qapi/cxl.json b/qapi/cxl.json
> index b21c9b4c1c..dcf9e7b715 100644
> --- a/qapi/cxl.json
> +++ b/qapi/cxl.json
> @@ -5,6 +5,24 @@
> # = CXL devices
> ##
>
> +##
> +# @cxl-inject-poison:
> +#
> +# Poison records indicate that a CXL memory device knows that a particular
> +# memory region may be corrupted. This may be because of locally detected
> +# errors (e.g. ECC failure) or poisoned writes received from other components
> +# in the system. This injection mechanism enables testing of the OS handling
> +# of poison records which may be queried via the CXL mailbox.
> +#
> +# @path: CXL type 3 device canonical QOM path
> +# @start: Start address - must be 64 byte aligned.
> +# @length: Length of poison to inject - must be a multiple of 64 bytes.
> +#
> +# Since: 8.1
> +##
> +{ 'command': 'cxl-inject-poison',
> + 'data': { 'path': 'str', 'start': 'uint64', 'length': 'uint64' }}
> +
> ##
> # @CxlUncorErrorType:
> #
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v6 1/4] bswap: Add the ability to store to an unaligned 24 bit field
2023-05-20 12:37 ` Peter Maydell
2023-05-20 13:15 ` BALATON Zoltan
@ 2023-05-22 11:59 ` Jonathan Cameron via
1 sibling, 0 replies; 17+ messages in thread
From: Jonathan Cameron via @ 2023-05-22 11:59 UTC (permalink / raw)
To: Peter Maydell
Cc: qemu-devel, Michael Tsirkin, Fan Ni, linux-cxl, linuxarm,
Ira Weiny, Michael Roth, Philippe Mathieu-Daudé, Dave Jiang,
Markus Armbruster, Daniel P . Berrangé, Eric Blake,
Mike Maslenkin, Marc-André Lureau, Thomas Huth
On Sat, 20 May 2023 13:37:42 +0100
Peter Maydell <peter.maydell@linaro.org> wrote:
> On Fri, 19 May 2023 at 15:19, Jonathan Cameron via
> <qemu-devel@nongnu.org> wrote:
> >
> > From: Ira Weiny <ira.weiny@intel.com>
> >
> > CXL has 24 bit unaligned fields which need to be stored to. CXL is
> > specified as little endian.
> >
> > Define st24_le_p() and the supporting functions to store such a field
> > from a 32 bit host native value.
> >
> > The use of b, w, l, q as the size specifier is limiting. So "24" was
> > used for the size part of the function name.
> >
> > Signed-off-by: Ira Weiny <ira.weiny@intel.com>
> > Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> > ---
> > docs/devel/loads-stores.rst | 1 +
> > include/qemu/bswap.h | 27 +++++++++++++++++++++++++++
> > 2 files changed, 28 insertions(+)
> >
> > diff --git a/docs/devel/loads-stores.rst b/docs/devel/loads-stores.rst
> > index d2cefc77a2..82a79e91d9 100644
> > --- a/docs/devel/loads-stores.rst
> > +++ b/docs/devel/loads-stores.rst
> > @@ -36,6 +36,7 @@ store: ``st{size}_{endian}_p(ptr, val)``
> > ``size``
> > - ``b`` : 8 bits
> > - ``w`` : 16 bits
> > + - ``24`` : 24 bits
> > - ``l`` : 32 bits
> > - ``q`` : 64 bits
>
> Can you also update the "Regexes for git grep" section
> below to account for the new size value, please?
Ok. My regex isn't great, but I think this would require either some
separate entries or a switch to git grep -E to allow for the multiple
character matching.
So I've added
- ``\st24\(_[hbl]e\)\?_p\>``
>
> thanks
> -- PMM
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v6 1/4] bswap: Add the ability to store to an unaligned 24 bit field
2023-05-20 17:08 ` Philippe Mathieu-Daudé
2023-05-21 9:05 ` Michael S. Tsirkin
@ 2023-05-22 12:09 ` Jonathan Cameron via
1 sibling, 0 replies; 17+ messages in thread
From: Jonathan Cameron via @ 2023-05-22 12:09 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: Richard Henderson, BALATON Zoltan, Peter Maydell, qemu-devel,
Michael Tsirkin, Fan Ni, linux-cxl, linuxarm, Ira Weiny,
Michael Roth, Dave Jiang, Markus Armbruster,
Daniel P . Berrangé, Eric Blake, Mike Maslenkin,
Marc-André Lureau, Thomas Huth
On Sat, 20 May 2023 19:08:22 +0200
Philippe Mathieu-Daudé <philmd@linaro.org> wrote:
> On 20/5/23 17:15, Richard Henderson wrote:
> > On 5/20/23 06:15, BALATON Zoltan wrote:
> >> On Sat, 20 May 2023, Peter Maydell wrote:
> >>> On Fri, 19 May 2023 at 15:19, Jonathan Cameron via
> >>> <qemu-devel@nongnu.org> wrote:
> >>>>
> >>>> From: Ira Weiny <ira.weiny@intel.com>
> >>>>
> >>>> CXL has 24 bit unaligned fields which need to be stored to. CXL is
> >>>> specified as little endian.
> >>>>
> >>>> Define st24_le_p() and the supporting functions to store such a field
> >>>> from a 32 bit host native value.
> >>>>
> >>>> The use of b, w, l, q as the size specifier is limiting. So "24" was
> >>>> used for the size part of the function name.
> >>
> >> Maybe it's clearer to use 24 but if we want to keep these somewhat
> >> consistent how about using t for Triplet, Three-bytes or Twenty-four?
> >
> > I think it's clearer to use '3'.
> > When I added 128-bit support I used cpu_ld16_mmu.
As an aside on that - you didn't update the docs when you added that
(I was looking for it to copy your regex ;)
>
> There is also ld8u / ld8s / st8.
>
> > I think it would be clearer to not use letters anywhere, and to use
> > units of bytes instead of units of bits (no one can store just a bit),
> > but changing everything is a big job.
>
> So:
>
> ldub -> ld1u,
>
> lduw_le -> ld2u_le,
>
> virtio_stl -> virtio_st4,
>
> stq_be -> st8_be.
>
> Right?
>
> Also we have:
>
> cpu_ld/st_*
> virtio_ld/st_*
> ld/st_*_phys
> ld/st_*_pci_dma
> address_space_ld/st
>
> While mass-changing, we could use FOO_ld/st_BAR with FOO
> for API and BAR for API variant (endian, mmuidx, ra, ...):
>
> So:
>
> ld/st_*_pci_dma -> pci_dma_ld/st_*
>
> for ld/st_*_phys I'm not sure.
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2023-05-22 12:10 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-05-19 14:17 [PATCH v6 0/4] hw/cxl: Poison get, inject, clear Jonathan Cameron via
2023-05-19 14:18 ` [PATCH v6 1/4] bswap: Add the ability to store to an unaligned 24 bit field Jonathan Cameron via
2023-05-19 16:08 ` Philippe Mathieu-Daudé
2023-05-19 16:24 ` Jonathan Cameron via
2023-05-19 16:43 ` Philippe Mathieu-Daudé
2023-05-20 12:37 ` Peter Maydell
2023-05-20 13:15 ` BALATON Zoltan
2023-05-20 15:15 ` Richard Henderson
2023-05-20 17:08 ` Philippe Mathieu-Daudé
2023-05-21 9:05 ` Michael S. Tsirkin
2023-05-22 12:09 ` Jonathan Cameron via
2023-05-22 11:59 ` Jonathan Cameron via
2023-05-19 14:18 ` [PATCH v6 2/4] hw/cxl: QMP based poison injection support Jonathan Cameron via
2023-05-22 11:20 ` Jonathan Cameron via
2023-05-19 14:18 ` [PATCH v6 3/4] hw/cxl: Add poison injection via the mailbox Jonathan Cameron via
2023-05-19 14:18 ` [PATCH v6 4/4] hw/cxl: Add clear poison mailbox command support Jonathan Cameron via
2023-05-19 17:48 ` Ira Weiny
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).