All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v6 0/10] cxl: CXL Inject & Clear Poison
@ 2023-04-19  3:26 alison.schofield
  2023-04-19  3:26 ` [PATCH v6 01/10] cxl/memdev: Add support for the Inject Poison mailbox command alison.schofield
                   ` (10 more replies)
  0 siblings, 11 replies; 16+ messages in thread
From: alison.schofield @ 2023-04-19  3:26 UTC (permalink / raw)
  To: Dan Williams, Ira Weiny, Vishal Verma, Ben Widawsky, Dave Jiang
  Cc: Alison Schofield, linux-cxl

From: Alison Schofield <alison.schofield@intel.com>

Built on cxl/next plus [PATCH v13 0/9] CXL Poison List Retrieval & Tracing
https://lore.kernel.org/linux-cxl/cover.1681838291.git.alison.schofield@intel.com/

Changes in v6:
- Drop patches: The deprecate, and the removal of raw access, introduced
  for all poison commands in v13 of CXL Poison List Retrieval & Tracing,
  made these 2 patches obsolete:
	cxl/memdev: Make inject and clear poison cmds kernel exclusive
	cxl/mbox: Block inject and clear poison opcodes in raw mode

- The device always writes the write data on Clear, regardless of whether or
  not the address is actually poisoned. Stop stating otherwise. (Jonathan)
- Update Patch 1 commit message to refer to CXL.mem driver (DaveJ)
- __cxl_dpa_to_region() Stop the walk on a match (Jonathan)
- Set & use cxlds->poison.enabled_cmds for inject & clear
- Simplify inject payload address assignment (DaveJ)
- Use down_read_interruptible in inject/clear 
- Tidy up the memdev core api for inject/clear by using cxl_memdev
- Use the available cxl_memdev rather than dev in debugfs_create_file()

Link to v5:
https://lore.kernel.org/linux-cxl/cover.1679892337.git.alison.schofield@intel.com/


Introducing Inject and Clear Poison support for CXL Devices.

These are optional commands, meaning not all CXL devices must support
them. The debugfs attributes, inject_poison and clear_poison, are only
visible for devices reporting support of the capability.

Example:
# echo 0x40000000 > /sys/kernel/debug/cxl/mem1/inject_poison

cxl_poison: memdev=mem1 pcidev=cxl_mem.1 trace_type=Inject region= region_uuid=00000000-0000-0000-0000-000000000000 hpa=0xffffffffffffffff dpa=0x40000000 dpa_length=0x40 source=Unknown flags= overflow_time=0

Example in which the injected poison landed in region5:
# echo 0x40000000 > /sys/kernel/debug/cxl/mem0/inject_poison

cxl_poison: memdev=mem0 host=cxl_mem.0 serial=0 trace_type=Inject region=region5 region_uuid=cfcfc13a-5290-4983-aa74-4c8465c25f26 hpa=0xf110000000 dpa=0x40000000 dpa_length=0x40 source=Unknown flags= overflow_time=0


Alison Schofield (10):
  cxl/memdev: Add support for the Inject Poison mailbox command
  cxl/memdev: Add support for the Clear Poison mailbox command
  cxl/memdev: Warn of poison inject or clear to a mapped region
  cxl/memdev: Trace inject and clear poison as cxl_poison events
  cxl/mem: Add debugfs attributes for poison inject and clear
  tools/testing/cxl: Mock the Inject Poison mailbox command
  tools/testing/cxl: Mock the Clear Poison mailbox command
  tools/testing/cxl: Use injected poison for get poison list
  tools/testing/cxl: Add a sysfs attr to test poison inject limits
  tools/testing/cxl: Require CONFIG_DEBUG_FS

 Documentation/ABI/testing/debugfs-cxl |  35 +++++
 drivers/cxl/core/core.h               |   2 +
 drivers/cxl/core/memdev.c             | 172 ++++++++++++++++++++
 drivers/cxl/core/trace.h              |   8 +-
 drivers/cxl/cxlmem.h                  |  13 ++
 drivers/cxl/mem.c                     |  28 ++++
 tools/testing/cxl/config_check.c      |   1 +
 tools/testing/cxl/test/mem.c          | 216 +++++++++++++++++++++++---
 8 files changed, 453 insertions(+), 22 deletions(-)
 create mode 100644 Documentation/ABI/testing/debugfs-cxl

-- 
2.37.3


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v6 01/10] cxl/memdev: Add support for the Inject Poison mailbox command
  2023-04-19  3:26 [PATCH v6 0/10] cxl: CXL Inject & Clear Poison alison.schofield
@ 2023-04-19  3:26 ` alison.schofield
  2023-04-22 21:49   ` Dan Williams
  2023-04-19  3:26 ` [PATCH v6 02/10] cxl/memdev: Add support for the Clear " alison.schofield
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 16+ messages in thread
From: alison.schofield @ 2023-04-19  3:26 UTC (permalink / raw)
  To: Dan Williams, Ira Weiny, Vishal Verma, Ben Widawsky, Dave Jiang
  Cc: Alison Schofield, linux-cxl, Jonathan Cameron

From: Alison Schofield <alison.schofield@intel.com>

CXL devices optionally support the INJECT POISON mailbox command. Add
memdev driver support for the mailbox command.

Per the CXL Specification (3.0 8.2.9.8.4.2), after receiving a valid
inject poison request, the device will return poison when the address
is accessed through the CXL.mem driver. Injecting poison adds the address
to the device's Poison List and the error source is set to Injected.
In addition, the device adds a poison creation event to its internal
Informational Event log, updates the Event Status register, and if
configured, interrupts the host.

Also, per the CXL Specification, it is not an error to inject poison
into an address that already has poison present and no error is
returned from the device.

If the address is not contained in the device's dpa resource, or is
not 64 byte aligned, return -EINVAL without issuing the mbox command.

Poison injection is intended for debug only and will be exposed to
userspace through debugfs. Restrict compilation to CONFIG_DEBUG_FS.

Signed-off-by: Alison Schofield <alison.schofield@intel.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
---
 drivers/cxl/core/memdev.c | 56 +++++++++++++++++++++++++++++++++++++++
 drivers/cxl/cxlmem.h      |  6 +++++
 2 files changed, 62 insertions(+)

diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
index 8db7f220f182..474f7c2f4f6e 100644
--- a/drivers/cxl/core/memdev.c
+++ b/drivers/cxl/core/memdev.c
@@ -160,6 +160,62 @@ int cxl_trigger_poison_list(struct cxl_memdev *cxlmd)
 }
 EXPORT_SYMBOL_NS_GPL(cxl_trigger_poison_list, CXL);
 
+static int cxl_validate_poison_dpa(struct cxl_memdev *cxlmd, u64 dpa)
+{
+	struct cxl_dev_state *cxlds = cxlmd->cxlds;
+
+	if (!IS_ENABLED(CONFIG_DEBUG_FS))
+		return 0;
+
+	if (!resource_size(&cxlds->dpa_res)) {
+		dev_dbg(cxlds->dev, "device has no dpa resource\n");
+		return -EINVAL;
+	}
+	if (dpa < cxlds->dpa_res.start || dpa > cxlds->dpa_res.end) {
+		dev_dbg(cxlds->dev, "dpa:0x%llx not in resource:%pR\n",
+			dpa, &cxlds->dpa_res);
+		return -EINVAL;
+	}
+	if (!IS_ALIGNED(dpa, 64)) {
+		dev_dbg(cxlds->dev, "dpa:0x%llx is not 64-byte aligned\n", dpa);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa)
+{
+	struct cxl_dev_state *cxlds = cxlmd->cxlds;
+	struct cxl_mbox_inject_poison inject;
+	struct cxl_mbox_cmd mbox_cmd;
+	int rc;
+
+	if (!IS_ENABLED(CONFIG_DEBUG_FS))
+		return 0;
+
+	rc = down_read_interruptible(&cxl_dpa_rwsem);
+	if (rc)
+		return rc;
+
+	rc = cxl_validate_poison_dpa(cxlmd, dpa);
+	if (rc)
+		goto out;
+
+	inject.address = cpu_to_le64(dpa);
+	mbox_cmd = (struct cxl_mbox_cmd) {
+		.opcode = CXL_MBOX_OP_INJECT_POISON,
+		.size_in = sizeof(inject),
+		.payload_in = &inject,
+	};
+	rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+out:
+	up_read(&cxl_dpa_rwsem);
+
+	return rc;
+}
+EXPORT_SYMBOL_NS_GPL(cxl_inject_poison, CXL);
+
 static struct attribute *cxl_memdev_attributes[] = {
 	&dev_attr_serial.attr,
 	&dev_attr_firmware_version.attr,
diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
index 68b9db545aae..8a3ea9cabf1f 100644
--- a/drivers/cxl/cxlmem.h
+++ b/drivers/cxl/cxlmem.h
@@ -615,6 +615,11 @@ struct cxl_mbox_poison_out {
 #define CXL_POISON_SOURCE_INJECTED	3
 #define CXL_POISON_SOURCE_VENDOR	7
 
+/* Inject & Clear Poison  CXL 3.0 Spec 8.2.9.8.4.2/3 */
+struct cxl_mbox_inject_poison {
+	__le64 address;
+};
+
 /**
  * struct cxl_mem_command - Driver representation of a memory device command
  * @info: Command information as it exists for the UAPI
@@ -689,6 +694,7 @@ int cxl_poison_state_init(struct cxl_dev_state *cxlds);
 int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,
 		       struct cxl_region *cxlr);
 int cxl_trigger_poison_list(struct cxl_memdev *cxlmd);
+int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa);
 
 #ifdef CONFIG_CXL_SUSPEND
 void cxl_mem_active_inc(void);
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v6 02/10] cxl/memdev: Add support for the Clear Poison mailbox command
  2023-04-19  3:26 [PATCH v6 0/10] cxl: CXL Inject & Clear Poison alison.schofield
  2023-04-19  3:26 ` [PATCH v6 01/10] cxl/memdev: Add support for the Inject Poison mailbox command alison.schofield
@ 2023-04-19  3:26 ` alison.schofield
  2023-04-19  3:26 ` [PATCH v6 03/10] cxl/memdev: Warn of poison inject or clear to a mapped region alison.schofield
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 16+ messages in thread
From: alison.schofield @ 2023-04-19  3:26 UTC (permalink / raw)
  To: Dan Williams, Ira Weiny, Vishal Verma, Ben Widawsky, Dave Jiang
  Cc: Alison Schofield, linux-cxl, Jonathan Cameron

From: Alison Schofield <alison.schofield@intel.com>

CXL devices optionally support the CLEAR POISON mailbox command. Add
memdev driver support for clearing poison.

Per the CXL Specification (3.0 8.2.9.8.4.3), after receiving a valid
clear poison request, the device removes the address from the device's
Poison List and writes 0 (zero) for 64 bytes starting at address. If
the device cannot clear poison from the address, it returns a permanent
media error and -ENXIO is returned to the user.

Additionally, and per the spec also, it is not an error to clear poison
of an address that is not poisoned.

If the address is not contained in the device's dpa resource, or is
not 64 byte aligned, the driver returns -EINVAL without sending the
command to the device.

Poison clearing is intended for debug only and will be exposed to
userspace through debugfs. Restrict compilation to CONFIG_DEBUG_FS.

Implementation note: Although the CXL specification defines the clear
command to accept 64 bytes of 'write-data', this implementation always
uses zeroes as write-data.

Signed-off-by: Alison Schofield <alison.schofield@intel.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
 drivers/cxl/core/memdev.c | 43 +++++++++++++++++++++++++++++++++++++++
 drivers/cxl/cxlmem.h      |  7 +++++++
 2 files changed, 50 insertions(+)

diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
index 474f7c2f4f6e..3b48b6eec007 100644
--- a/drivers/cxl/core/memdev.c
+++ b/drivers/cxl/core/memdev.c
@@ -216,6 +216,49 @@ int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa)
 }
 EXPORT_SYMBOL_NS_GPL(cxl_inject_poison, CXL);
 
+int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa)
+{
+	struct cxl_dev_state *cxlds = cxlmd->cxlds;
+	struct cxl_mbox_clear_poison clear;
+	struct cxl_mbox_cmd mbox_cmd;
+	int rc;
+
+	if (!IS_ENABLED(CONFIG_DEBUG_FS))
+		return 0;
+
+	rc = down_read_interruptible(&cxl_dpa_rwsem);
+	if (rc)
+		return rc;
+
+	rc = cxl_validate_poison_dpa(cxlmd, dpa);
+	if (rc)
+		goto out;
+
+	/*
+	 * In CXL 3.0 Spec 8.2.9.8.4.3, the Clear Poison mailbox command
+	 * is defined to accept 64 bytes of write-data, along with the
+	 * address to clear. This driver uses zeroes as write-data.
+	 */
+	clear = (struct cxl_mbox_clear_poison) {
+		.address = cpu_to_le64(dpa)
+	};
+
+	mbox_cmd = (struct cxl_mbox_cmd) {
+		.opcode = CXL_MBOX_OP_CLEAR_POISON,
+		.size_in = sizeof(clear),
+		.payload_in = &clear,
+	};
+
+	rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+	if (rc)
+		goto out;
+out:
+	up_read(&cxl_dpa_rwsem);
+
+	return rc;
+}
+EXPORT_SYMBOL_NS_GPL(cxl_clear_poison, CXL);
+
 static struct attribute *cxl_memdev_attributes[] = {
 	&dev_attr_serial.attr,
 	&dev_attr_firmware_version.attr,
diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
index 8a3ea9cabf1f..fa73bbdc5327 100644
--- a/drivers/cxl/cxlmem.h
+++ b/drivers/cxl/cxlmem.h
@@ -620,6 +620,12 @@ struct cxl_mbox_inject_poison {
 	__le64 address;
 };
 
+/* Clear Poison  CXL 3.0 Spec 8.2.9.8.4.3 */
+struct cxl_mbox_clear_poison {
+	__le64 address;
+	u8 write_data[CXL_POISON_LEN_MULT];
+} __packed;
+
 /**
  * struct cxl_mem_command - Driver representation of a memory device command
  * @info: Command information as it exists for the UAPI
@@ -695,6 +701,7 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,
 		       struct cxl_region *cxlr);
 int cxl_trigger_poison_list(struct cxl_memdev *cxlmd);
 int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa);
+int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa);
 
 #ifdef CONFIG_CXL_SUSPEND
 void cxl_mem_active_inc(void);
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v6 03/10] cxl/memdev: Warn of poison inject or clear to a mapped region
  2023-04-19  3:26 [PATCH v6 0/10] cxl: CXL Inject & Clear Poison alison.schofield
  2023-04-19  3:26 ` [PATCH v6 01/10] cxl/memdev: Add support for the Inject Poison mailbox command alison.schofield
  2023-04-19  3:26 ` [PATCH v6 02/10] cxl/memdev: Add support for the Clear " alison.schofield
@ 2023-04-19  3:26 ` alison.schofield
  2023-04-23 15:35   ` Jonathan Cameron
  2023-04-19  3:26 ` [PATCH v6 04/10] cxl/memdev: Trace inject and clear poison as cxl_poison events alison.schofield
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 16+ messages in thread
From: alison.schofield @ 2023-04-19  3:26 UTC (permalink / raw)
  To: Dan Williams, Ira Weiny, Vishal Verma, Ben Widawsky, Dave Jiang
  Cc: Alison Schofield, linux-cxl

From: Alison Schofield <alison.schofield@intel.com>

Inject and clear poison capabilities and intended for debug usage only.
In order to be useful in debug environments, the driver needs to allow
inject and clear operations on DPAs mapped in regions.

dev_warn_once() when either operation occurs.

Signed-off-by: Alison Schofield <alison.schofield@intel.com>
---
 drivers/cxl/core/memdev.c | 58 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)

diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
index 3b48b6eec007..23ac8d322b37 100644
--- a/drivers/cxl/core/memdev.c
+++ b/drivers/cxl/core/memdev.c
@@ -160,6 +160,50 @@ int cxl_trigger_poison_list(struct cxl_memdev *cxlmd)
 }
 EXPORT_SYMBOL_NS_GPL(cxl_trigger_poison_list, CXL);
 
+struct cxl_dpa_to_region_context {
+	struct cxl_region *cxlr;
+	u64 dpa;
+};
+
+static int __cxl_dpa_to_region(struct device *dev, void *arg)
+{
+	struct cxl_dpa_to_region_context *ctx = arg;
+	struct cxl_endpoint_decoder *cxled;
+	u64 dpa = ctx->dpa;
+
+	if (!is_endpoint_decoder(dev))
+		return 0;
+
+	cxled = to_cxl_endpoint_decoder(dev);
+	if (!cxled->dpa_res || !resource_size(cxled->dpa_res))
+		return 0;
+
+	if (dpa > cxled->dpa_res->end || dpa < cxled->dpa_res->start)
+		return 0;
+
+	dev_dbg(dev, "dpa:0x%llx mapped in region:%s\n", dpa,
+		dev_name(&cxled->cxld.region->dev));
+
+	ctx->cxlr = cxled->cxld.region;
+
+	return 1;
+}
+
+static struct cxl_region *cxl_dpa_to_region(struct cxl_memdev *cxlmd, u64 dpa)
+{
+	struct cxl_dpa_to_region_context ctx;
+	struct cxl_port *port;
+
+	ctx = (struct cxl_dpa_to_region_context) {
+		.dpa = dpa,
+	};
+	port = dev_get_drvdata(&cxlmd->dev);
+	if (port && is_cxl_endpoint(port) && port->commit_end != -1)
+		device_for_each_child(&port->dev, &ctx, __cxl_dpa_to_region);
+
+	return ctx.cxlr;
+}
+
 static int cxl_validate_poison_dpa(struct cxl_memdev *cxlmd, u64 dpa)
 {
 	struct cxl_dev_state *cxlds = cxlmd->cxlds;
@@ -189,6 +233,7 @@ int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa)
 	struct cxl_dev_state *cxlds = cxlmd->cxlds;
 	struct cxl_mbox_inject_poison inject;
 	struct cxl_mbox_cmd mbox_cmd;
+	struct cxl_region *cxlr;
 	int rc;
 
 	if (!IS_ENABLED(CONFIG_DEBUG_FS))
@@ -209,6 +254,13 @@ int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa)
 		.payload_in = &inject,
 	};
 	rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+	if (rc)
+		goto out;
+
+	cxlr = cxl_dpa_to_region(cxlmd, dpa);
+	if (cxlr)
+		dev_warn_once(cxlds->dev, "poison inject dpa:0x%llx region: %s\n",
+			      dpa, dev_name(&cxlr->dev));
 out:
 	up_read(&cxl_dpa_rwsem);
 
@@ -221,6 +273,7 @@ int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa)
 	struct cxl_dev_state *cxlds = cxlmd->cxlds;
 	struct cxl_mbox_clear_poison clear;
 	struct cxl_mbox_cmd mbox_cmd;
+	struct cxl_region *cxlr;
 	int rc;
 
 	if (!IS_ENABLED(CONFIG_DEBUG_FS))
@@ -252,6 +305,11 @@ int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa)
 	rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
 	if (rc)
 		goto out;
+
+	cxlr = cxl_dpa_to_region(cxlmd, dpa);
+	if (cxlr)
+		dev_warn_once(cxlds->dev, "poison inject dpa:0x%llx region: %s\n",
+			      dpa, dev_name(&cxlr->dev));
 out:
 	up_read(&cxl_dpa_rwsem);
 
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v6 04/10] cxl/memdev: Trace inject and clear poison as cxl_poison events
  2023-04-19  3:26 [PATCH v6 0/10] cxl: CXL Inject & Clear Poison alison.schofield
                   ` (2 preceding siblings ...)
  2023-04-19  3:26 ` [PATCH v6 03/10] cxl/memdev: Warn of poison inject or clear to a mapped region alison.schofield
@ 2023-04-19  3:26 ` alison.schofield
  2023-04-19  3:26 ` [PATCH v6 05/10] cxl/mem: Add debugfs attributes for poison inject and clear alison.schofield
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 16+ messages in thread
From: alison.schofield @ 2023-04-19  3:26 UTC (permalink / raw)
  To: Dan Williams, Ira Weiny, Vishal Verma, Ben Widawsky, Dave Jiang
  Cc: Alison Schofield, linux-cxl, Jonathan Cameron

From: Alison Schofield <alison.schofield@intel.com>

The cxl_poison trace event allows users to view the history of poison
list reads. With the addition of inject and clear poison capabilities,
users will expect similar tracing.

Add trace types 'Inject' and 'Clear' to the cxl_poison trace_event and
trace successful operations only.

If the driver finds that the DPA being injected or cleared of poison
is mapped in a region, that region info is included in the cxl_poison
trace event. Region reconfigurations can make this extra info useless
if the debug operations are not carefully managed.

Signed-off-by: Alison Schofield <alison.schofield@intel.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
---
 drivers/cxl/core/core.h   |  2 ++
 drivers/cxl/core/memdev.c | 15 +++++++++++++++
 drivers/cxl/core/trace.h  |  8 +++++---
 3 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/drivers/cxl/core/core.h b/drivers/cxl/core/core.h
index deb5f87d6d0a..27f0968449de 100644
--- a/drivers/cxl/core/core.h
+++ b/drivers/cxl/core/core.h
@@ -71,6 +71,8 @@ void cxl_mbox_init(void);
 
 enum cxl_poison_trace_type {
 	CXL_POISON_TRACE_LIST,
+	CXL_POISON_TRACE_INJECT,
+	CXL_POISON_TRACE_CLEAR,
 };
 
 #endif /* __CXL_CORE_H__ */
diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
index 23ac8d322b37..274c741ea219 100644
--- a/drivers/cxl/core/memdev.c
+++ b/drivers/cxl/core/memdev.c
@@ -6,6 +6,7 @@
 #include <linux/idr.h>
 #include <linux/pci.h>
 #include <cxlmem.h>
+#include "trace.h"
 #include "core.h"
 
 static DECLARE_RWSEM(cxl_memdev_rwsem);
@@ -232,6 +233,7 @@ int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa)
 {
 	struct cxl_dev_state *cxlds = cxlmd->cxlds;
 	struct cxl_mbox_inject_poison inject;
+	struct cxl_poison_record record;
 	struct cxl_mbox_cmd mbox_cmd;
 	struct cxl_region *cxlr;
 	int rc;
@@ -261,6 +263,12 @@ int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa)
 	if (cxlr)
 		dev_warn_once(cxlds->dev, "poison inject dpa:0x%llx region: %s\n",
 			      dpa, dev_name(&cxlr->dev));
+
+	record = (struct cxl_poison_record) {
+		.address = cpu_to_le64(dpa),
+		.length = cpu_to_le32(1),
+	};
+	trace_cxl_poison(cxlmd, cxlr, &record, 0, 0, CXL_POISON_TRACE_INJECT);
 out:
 	up_read(&cxl_dpa_rwsem);
 
@@ -272,6 +280,7 @@ int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa)
 {
 	struct cxl_dev_state *cxlds = cxlmd->cxlds;
 	struct cxl_mbox_clear_poison clear;
+	struct cxl_poison_record record;
 	struct cxl_mbox_cmd mbox_cmd;
 	struct cxl_region *cxlr;
 	int rc;
@@ -310,6 +319,12 @@ int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa)
 	if (cxlr)
 		dev_warn_once(cxlds->dev, "poison inject dpa:0x%llx region: %s\n",
 			      dpa, dev_name(&cxlr->dev));
+
+	record = (struct cxl_poison_record) {
+		.address = cpu_to_le64(dpa),
+		.length = cpu_to_le32(1),
+	};
+	trace_cxl_poison(cxlmd, cxlr, &record, 0, 0, CXL_POISON_TRACE_CLEAR);
 out:
 	up_read(&cxl_dpa_rwsem);
 
diff --git a/drivers/cxl/core/trace.h b/drivers/cxl/core/trace.h
index 220cc7e721b8..a0b5819bc70b 100644
--- a/drivers/cxl/core/trace.h
+++ b/drivers/cxl/core/trace.h
@@ -602,9 +602,11 @@ TRACE_EVENT(cxl_memory_module,
 	)
 );
 
-#define show_poison_trace_type(type)		   \
-	__print_symbolic(type,			   \
-	{ CXL_POISON_TRACE_LIST,	"List"	})
+#define show_poison_trace_type(type)			\
+	__print_symbolic(type,				\
+	{ CXL_POISON_TRACE_LIST,	"List"   },	\
+	{ CXL_POISON_TRACE_INJECT,	"Inject" },	\
+	{ CXL_POISON_TRACE_CLEAR,	"Clear"  })
 
 #define __show_poison_source(source)                          \
 	__print_symbolic(source,                              \
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v6 05/10] cxl/mem: Add debugfs attributes for poison inject and clear
  2023-04-19  3:26 [PATCH v6 0/10] cxl: CXL Inject & Clear Poison alison.schofield
                   ` (3 preceding siblings ...)
  2023-04-19  3:26 ` [PATCH v6 04/10] cxl/memdev: Trace inject and clear poison as cxl_poison events alison.schofield
@ 2023-04-19  3:26 ` alison.schofield
  2023-04-19  3:26 ` [PATCH v6 06/10] tools/testing/cxl: Mock the Inject Poison mailbox command alison.schofield
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 16+ messages in thread
From: alison.schofield @ 2023-04-19  3:26 UTC (permalink / raw)
  To: Dan Williams, Ira Weiny, Vishal Verma, Ben Widawsky, Dave Jiang
  Cc: Alison Schofield, linux-cxl, Jonathan Cameron

From: Alison Schofield <alison.schofield@intel.com>

Inject and Clear Poison commands are optionally supported by CXL
memdev devices and are intended for use in debug environments only.
Add debugfs attributes for user access.

Documentation/ABI/testing/debugfs-cxl describes the usage.

Signed-off-by: Alison Schofield <alison.schofield@intel.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
 Documentation/ABI/testing/debugfs-cxl | 35 +++++++++++++++++++++++++++
 drivers/cxl/mem.c                     | 28 +++++++++++++++++++++
 2 files changed, 63 insertions(+)
 create mode 100644 Documentation/ABI/testing/debugfs-cxl

diff --git a/Documentation/ABI/testing/debugfs-cxl b/Documentation/ABI/testing/debugfs-cxl
new file mode 100644
index 000000000000..fe61d372e3fa
--- /dev/null
+++ b/Documentation/ABI/testing/debugfs-cxl
@@ -0,0 +1,35 @@
+What:		/sys/kernel/debug/cxl/memX/inject_poison
+Date:		April, 2023
+KernelVersion:	v6.4
+Contact:	linux-cxl@vger.kernel.org
+Description:
+		(WO) When a Device Physical Address (DPA) is written to this
+		attribute, the memdev driver sends an inject poison command to
+		the device for the specified address. The DPA must be 64-byte
+		aligned and the length of the injected poison is 64-bytes. If
+		successful, the device returns poison when the address is
+		accessed through the CXL.mem bus. Injecting poison adds the
+		address to the device's Poison List and the error source is set
+		to Injected. In addition, the device adds a poison creation
+		event to its internal Informational Event log, updates the
+		Event Status register, and if configured, interrupts the host.
+		It is not an error to inject poison into an address that
+		already has poison present and no error is returned. The
+		inject_poison attribute is only visible for devices supporting
+		the capability.
+
+
+What:		/sys/kernel/debug/memX/clear_poison
+Date:		April, 2023
+KernelVersion:	v6.4
+Contact:	linux-cxl@vger.kernel.org
+Description:
+		(WO) When a Device Physical Address (DPA) is written to this
+		attribute, the memdev driver sends a clear poison command to
+		the device for the specified address. Clearing poison removes
+		the address from the device's Poison List and writes 0 (zero)
+		for 64 bytes starting at address. It is not an error to clear
+		poison from an address that does not have poison set. If the
+		device cannot clear poison from the address, -ENXIO is returned.
+		The clear_poison attribute is only visible for devices
+		supporting the capability.
diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
index b6a413facbd7..10caf180b3fa 100644
--- a/drivers/cxl/mem.c
+++ b/drivers/cxl/mem.c
@@ -94,6 +94,26 @@ static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd,
 	return 0;
 }
 
+static int cxl_debugfs_poison_inject(void *data, u64 dpa)
+{
+	struct cxl_memdev *cxlmd = data;
+
+	return cxl_inject_poison(cxlmd, dpa);
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(cxl_poison_inject_fops, NULL,
+			 cxl_debugfs_poison_inject, "%llx\n");
+
+static int cxl_debugfs_poison_clear(void *data, u64 dpa)
+{
+	struct cxl_memdev *cxlmd = data;
+
+	return cxl_clear_poison(cxlmd, dpa);
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(cxl_poison_clear_fops, NULL,
+			 cxl_debugfs_poison_clear, "%llx\n");
+
 static int cxl_mem_probe(struct device *dev)
 {
 	struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
@@ -117,6 +137,14 @@ static int cxl_mem_probe(struct device *dev)
 
 	dentry = cxl_debugfs_create_dir(dev_name(dev));
 	debugfs_create_devm_seqfile(dev, "dpamem", dentry, cxl_mem_dpa_show);
+
+	if (test_bit(CXL_POISON_ENABLED_INJECT, cxlds->poison.enabled_cmds))
+		debugfs_create_file("inject_poison", 0200, dentry, cxlmd,
+				    &cxl_poison_inject_fops);
+	if (test_bit(CXL_POISON_ENABLED_CLEAR, cxlds->poison.enabled_cmds))
+		debugfs_create_file("clear_poison", 0200, dentry, cxlmd,
+				    &cxl_poison_clear_fops);
+
 	rc = devm_add_action_or_reset(dev, remove_debugfs, dentry);
 	if (rc)
 		return rc;
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v6 06/10] tools/testing/cxl: Mock the Inject Poison mailbox command
  2023-04-19  3:26 [PATCH v6 0/10] cxl: CXL Inject & Clear Poison alison.schofield
                   ` (4 preceding siblings ...)
  2023-04-19  3:26 ` [PATCH v6 05/10] cxl/mem: Add debugfs attributes for poison inject and clear alison.schofield
@ 2023-04-19  3:26 ` alison.schofield
  2023-04-19  3:26 ` [PATCH v6 07/10] tools/testing/cxl: Mock the Clear " alison.schofield
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 16+ messages in thread
From: alison.schofield @ 2023-04-19  3:26 UTC (permalink / raw)
  To: Dan Williams, Ira Weiny, Vishal Verma, Ben Widawsky, Dave Jiang
  Cc: Alison Schofield, linux-cxl

From: Alison Schofield <alison.schofield@intel.com>

Mock the injection of poison by storing the device:address entries in
mock_poison_list[]. Enforce a limit of 8 poison injections per memdev
device and 128 total entries for the cxl_test mock driver.

Introducing the mock_poison[] list here, makes it available for use in
the mock of Clear Poison, and the mock of Get Poison List.

Signed-off-by: Alison Schofield <alison.schofield@intel.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
---
 tools/testing/cxl/test/mem.c | 77 ++++++++++++++++++++++++++++++++++++
 1 file changed, 77 insertions(+)

diff --git a/tools/testing/cxl/test/mem.c b/tools/testing/cxl/test/mem.c
index cf7975db05ed..2731ebbd175b 100644
--- a/tools/testing/cxl/test/mem.c
+++ b/tools/testing/cxl/test/mem.c
@@ -16,6 +16,9 @@
 #define DEV_SIZE SZ_2G
 #define EFFECT(x) (1U << x)
 
+#define MOCK_INJECT_DEV_MAX 8
+#define MOCK_INJECT_TEST_MAX 128
+
 static struct cxl_cel_entry mock_cel[] = {
 	{
 		.opcode = cpu_to_le16(CXL_MBOX_OP_GET_SUPPORTED_LOGS),
@@ -45,6 +48,10 @@ static struct cxl_cel_entry mock_cel[] = {
 		.opcode = cpu_to_le16(CXL_MBOX_OP_GET_POISON),
 		.effect = cpu_to_le16(0),
 	},
+	{
+		.opcode = cpu_to_le16(CXL_MBOX_OP_INJECT_POISON),
+		.effect = cpu_to_le16(0),
+	},
 };
 
 /* See CXL 2.0 Table 181 Get Health Info Output Payload */
@@ -474,6 +481,7 @@ static int mock_id(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd)
 			cpu_to_le64(SZ_256M / CXL_CAPACITY_MULTIPLIER),
 		.total_capacity =
 			cpu_to_le64(DEV_SIZE / CXL_CAPACITY_MULTIPLIER),
+		.inject_poison_limit = cpu_to_le16(MOCK_INJECT_DEV_MAX),
 	};
 
 	put_unaligned_le24(CXL_POISON_LIST_MAX, id.poison_list_max_mer);
@@ -895,6 +903,11 @@ static int mock_health_info(struct cxl_dev_state *cxlds,
 	return 0;
 }
 
+static struct mock_poison {
+	struct cxl_dev_state *cxlds;
+	u64 dpa;
+} mock_poison_list[MOCK_INJECT_TEST_MAX];
+
 static int mock_get_poison(struct cxl_dev_state *cxlds,
 			   struct cxl_mbox_cmd *cmd)
 {
@@ -923,6 +936,67 @@ static int mock_get_poison(struct cxl_dev_state *cxlds,
 	return 0;
 }
 
+static bool mock_poison_dev_max_injected(struct cxl_dev_state *cxlds)
+{
+	int count = 0;
+
+	for (int i = 0; i < MOCK_INJECT_TEST_MAX; i++) {
+		if (mock_poison_list[i].cxlds == cxlds)
+			count++;
+	}
+	return (count >= MOCK_INJECT_DEV_MAX);
+}
+
+static bool mock_poison_add(struct cxl_dev_state *cxlds, u64 dpa)
+{
+	if (mock_poison_dev_max_injected(cxlds)) {
+		dev_dbg(cxlds->dev,
+			"Device poison injection limit has been reached: %d\n",
+			MOCK_INJECT_DEV_MAX);
+		return false;
+	}
+
+	for (int i = 0; i < MOCK_INJECT_TEST_MAX; i++) {
+		if (!mock_poison_list[i].cxlds) {
+			mock_poison_list[i].cxlds = cxlds;
+			mock_poison_list[i].dpa = dpa;
+			return true;
+		}
+	}
+	dev_dbg(cxlds->dev,
+		"Mock test poison injection limit has been reached: %d\n",
+		MOCK_INJECT_TEST_MAX);
+
+	return false;
+}
+
+static bool mock_poison_found(struct cxl_dev_state *cxlds, u64 dpa)
+{
+	for (int i = 0; i < MOCK_INJECT_TEST_MAX; i++) {
+		if (mock_poison_list[i].cxlds == cxlds &&
+		    mock_poison_list[i].dpa == dpa)
+			return true;
+	}
+	return false;
+}
+
+static int mock_inject_poison(struct cxl_dev_state *cxlds,
+			      struct cxl_mbox_cmd *cmd)
+{
+	struct cxl_mbox_inject_poison *pi = cmd->payload_in;
+	u64 dpa = le64_to_cpu(pi->address);
+
+	if (mock_poison_found(cxlds, dpa)) {
+		/* Not an error to inject poison if already poisoned */
+		dev_dbg(cxlds->dev, "DPA: 0x%llx already poisoned\n", dpa);
+		return 0;
+	}
+	if (!mock_poison_add(cxlds, dpa))
+		return -ENXIO;
+
+	return 0;
+}
+
 static int cxl_mock_mbox_send(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd)
 {
 	struct device *dev = cxlds->dev;
@@ -980,6 +1054,9 @@ static int cxl_mock_mbox_send(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *
 	case CXL_MBOX_OP_GET_POISON:
 		rc = mock_get_poison(cxlds, cmd);
 		break;
+	case CXL_MBOX_OP_INJECT_POISON:
+		rc = mock_inject_poison(cxlds, cmd);
+		break;
 	default:
 		break;
 	}
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v6 07/10] tools/testing/cxl: Mock the Clear Poison mailbox command
  2023-04-19  3:26 [PATCH v6 0/10] cxl: CXL Inject & Clear Poison alison.schofield
                   ` (5 preceding siblings ...)
  2023-04-19  3:26 ` [PATCH v6 06/10] tools/testing/cxl: Mock the Inject Poison mailbox command alison.schofield
@ 2023-04-19  3:26 ` alison.schofield
  2023-04-19  3:26 ` [PATCH v6 08/10] tools/testing/cxl: Use injected poison for get poison list alison.schofield
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 16+ messages in thread
From: alison.schofield @ 2023-04-19  3:26 UTC (permalink / raw)
  To: Dan Williams, Ira Weiny, Vishal Verma, Ben Widawsky, Dave Jiang
  Cc: Alison Schofield, linux-cxl, Jonathan Cameron

From: Alison Schofield <alison.schofield@intel.com>

Mock the clear of poison by deleting the device:address entry from
the mock_poison_list[]. Behave like a real CXL device and do not fail
if the address is not in the poison list, but offer a dev_dbg()
message.

Signed-off-by: Alison Schofield <alison.schofield@intel.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
---
 tools/testing/cxl/test/mem.c | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/tools/testing/cxl/test/mem.c b/tools/testing/cxl/test/mem.c
index 2731ebbd175b..3c3909d30d03 100644
--- a/tools/testing/cxl/test/mem.c
+++ b/tools/testing/cxl/test/mem.c
@@ -52,6 +52,10 @@ static struct cxl_cel_entry mock_cel[] = {
 		.opcode = cpu_to_le16(CXL_MBOX_OP_INJECT_POISON),
 		.effect = cpu_to_le16(0),
 	},
+	{
+		.opcode = cpu_to_le16(CXL_MBOX_OP_CLEAR_POISON),
+		.effect = cpu_to_le16(0),
+	},
 };
 
 /* See CXL 2.0 Table 181 Get Health Info Output Payload */
@@ -997,6 +1001,35 @@ static int mock_inject_poison(struct cxl_dev_state *cxlds,
 	return 0;
 }
 
+static bool mock_poison_del(struct cxl_dev_state *cxlds, u64 dpa)
+{
+	for (int i = 0; i < MOCK_INJECT_TEST_MAX; i++) {
+		if (mock_poison_list[i].cxlds == cxlds &&
+		    mock_poison_list[i].dpa == dpa) {
+			mock_poison_list[i].cxlds = NULL;
+			return true;
+		}
+	}
+	return false;
+}
+
+static int mock_clear_poison(struct cxl_dev_state *cxlds,
+			     struct cxl_mbox_cmd *cmd)
+{
+	struct cxl_mbox_clear_poison *pi = cmd->payload_in;
+	u64 dpa = le64_to_cpu(pi->address);
+
+	/*
+	 * A real CXL device will write pi->write_data to the address
+	 * being cleared. In this mock, just delete this address from
+	 * the mock poison list.
+	 */
+	if (!mock_poison_del(cxlds, dpa))
+		dev_dbg(cxlds->dev, "DPA: 0x%llx not in poison list\n", dpa);
+
+	return 0;
+}
+
 static int cxl_mock_mbox_send(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd)
 {
 	struct device *dev = cxlds->dev;
@@ -1057,6 +1090,9 @@ static int cxl_mock_mbox_send(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *
 	case CXL_MBOX_OP_INJECT_POISON:
 		rc = mock_inject_poison(cxlds, cmd);
 		break;
+	case CXL_MBOX_OP_CLEAR_POISON:
+		rc = mock_clear_poison(cxlds, cmd);
+		break;
 	default:
 		break;
 	}
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v6 08/10] tools/testing/cxl: Use injected poison for get poison list
  2023-04-19  3:26 [PATCH v6 0/10] cxl: CXL Inject & Clear Poison alison.schofield
                   ` (6 preceding siblings ...)
  2023-04-19  3:26 ` [PATCH v6 07/10] tools/testing/cxl: Mock the Clear " alison.schofield
@ 2023-04-19  3:26 ` alison.schofield
  2023-04-22 22:03   ` Dan Williams
  2023-04-19  3:26 ` [PATCH v6 09/10] tools/testing/cxl: Add a sysfs attr to test poison inject limits alison.schofield
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 16+ messages in thread
From: alison.schofield @ 2023-04-19  3:26 UTC (permalink / raw)
  To: Dan Williams, Ira Weiny, Vishal Verma, Ben Widawsky, Dave Jiang
  Cc: Alison Schofield, linux-cxl

From: Alison Schofield <alison.schofield@intel.com>

Prior to poison inject support, the mock of 'Get Poison List'
returned a poison list containing a single mocked error record.

Following the addition of poison inject and clear support to the
mock driver, use the mock_poison_list[], rather than faking an
error record. Mock_poison_list[] list tracks the actual poison
inject and clear requests issued by userspace.

Signed-off-by: Alison Schofield <alison.schofield@intel.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
---
 tools/testing/cxl/test/mem.c | 59 ++++++++++++++++++++++++------------
 1 file changed, 40 insertions(+), 19 deletions(-)

diff --git a/tools/testing/cxl/test/mem.c b/tools/testing/cxl/test/mem.c
index 3c3909d30d03..cce7ec8f0efb 100644
--- a/tools/testing/cxl/test/mem.c
+++ b/tools/testing/cxl/test/mem.c
@@ -912,31 +912,52 @@ static struct mock_poison {
 	u64 dpa;
 } mock_poison_list[MOCK_INJECT_TEST_MAX];
 
+static struct cxl_mbox_poison_out
+*cxl_get_injected_po(struct cxl_dev_state *cxlds, u64 offset, u64 length)
+{
+	struct cxl_mbox_poison_out *po;
+	int nr_records = 0;
+	u64 dpa;
+
+	po = kzalloc(struct_size(po, record, MOCK_INJECT_DEV_MAX), GFP_KERNEL);
+	if (!po)
+		return NULL;
+
+	for (int i = 0; i < MOCK_INJECT_TEST_MAX; i++) {
+		if (mock_poison_list[i].cxlds != cxlds)
+			continue;
+		if (mock_poison_list[i].dpa < offset ||
+		    mock_poison_list[i].dpa > offset + length - 1)
+			continue;
+
+		dpa = mock_poison_list[i].dpa + CXL_POISON_SOURCE_INJECTED;
+		po->record[nr_records].address = cpu_to_le64(dpa);
+		po->record[nr_records].length = cpu_to_le32(1);
+		nr_records++;
+		if (nr_records == MOCK_INJECT_DEV_MAX)
+			break;
+	}
+
+	/* Always return count, even when zero */
+	po->count = cpu_to_le16(nr_records);
+
+	return po;
+}
+
 static int mock_get_poison(struct cxl_dev_state *cxlds,
 			   struct cxl_mbox_cmd *cmd)
 {
 	struct cxl_mbox_poison_in *pi = cmd->payload_in;
+	struct cxl_mbox_poison_out *po;
+	u64 offset = le64_to_cpu(pi->offset);
+	u64 length = le64_to_cpu(pi->length);
+	int nr_records;
 
-	/* Mock one poison record at pi.offset for 64 bytes */
-	struct {
-		struct cxl_mbox_poison_out po;
-		struct cxl_poison_record record;
-	} __packed mock_plist = {
-		.po = {
-			.count = cpu_to_le16(1),
-		},
-		.record = {
-			.length = cpu_to_le32(1),
-			.address = cpu_to_le64(le64_to_cpu(pi->offset) +
-					       CXL_POISON_SOURCE_INJECTED),
-		},
-	};
+	po = cxl_get_injected_po(cxlds, offset, length);
+	nr_records = le16_to_cpu(po->count);
+	memcpy(cmd->payload_out, po, struct_size(po, record, nr_records));
+	cmd->size_out = struct_size(po, record, nr_records);
 
-	if (cmd->size_out < sizeof(mock_plist))
-		return -EINVAL;
-
-	memcpy(cmd->payload_out, &mock_plist, sizeof(mock_plist));
-	cmd->size_out = sizeof(mock_plist);
 	return 0;
 }
 
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v6 09/10] tools/testing/cxl: Add a sysfs attr to test poison inject limits
  2023-04-19  3:26 [PATCH v6 0/10] cxl: CXL Inject & Clear Poison alison.schofield
                   ` (7 preceding siblings ...)
  2023-04-19  3:26 ` [PATCH v6 08/10] tools/testing/cxl: Use injected poison for get poison list alison.schofield
@ 2023-04-19  3:26 ` alison.schofield
  2023-04-19  3:26 ` [PATCH v6 10/10] tools/testing/cxl: Require CONFIG_DEBUG_FS alison.schofield
  2023-04-23 15:42 ` [PATCH v6 0/10] cxl: CXL Inject & Clear Poison Jonathan Cameron
  10 siblings, 0 replies; 16+ messages in thread
From: alison.schofield @ 2023-04-19  3:26 UTC (permalink / raw)
  To: Dan Williams, Ira Weiny, Vishal Verma, Ben Widawsky, Dave Jiang
  Cc: Alison Schofield, linux-cxl

From: Alison Schofield <alison.schofield@intel.com>

CXL devices may report a maximum number of addresses that a device
allows to be poisoned using poison injection. When cxl_test creates
mock CXL memory devices, it defaults to MOCK_INJECT_DEV_MAX==88 for
all mocked memdevs.

Add a sysfs attribute, poison_inject_max to module cxl_mock_mem so
that users can set a custom device injection limit. Fail, and return
-EBUSY, if the mock poison list is not empty.

/sys/bus/platform/drivers/cxl_mock_mem/poison_inject_max

A simple usage model is to set the attribute before running a test in
order to emulate a device's poison handling.

Signed-off-by: Alison Schofield <alison.schofield@intel.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
---
 tools/testing/cxl/test/mem.c | 52 +++++++++++++++++++++++++++++++++---
 1 file changed, 48 insertions(+), 4 deletions(-)

diff --git a/tools/testing/cxl/test/mem.c b/tools/testing/cxl/test/mem.c
index cce7ec8f0efb..da27658f7dd6 100644
--- a/tools/testing/cxl/test/mem.c
+++ b/tools/testing/cxl/test/mem.c
@@ -19,6 +19,8 @@
 #define MOCK_INJECT_DEV_MAX 8
 #define MOCK_INJECT_TEST_MAX 128
 
+static unsigned int poison_inject_dev_max = MOCK_INJECT_DEV_MAX;
+
 static struct cxl_cel_entry mock_cel[] = {
 	{
 		.opcode = cpu_to_le16(CXL_MBOX_OP_GET_SUPPORTED_LOGS),
@@ -485,7 +487,7 @@ static int mock_id(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd)
 			cpu_to_le64(SZ_256M / CXL_CAPACITY_MULTIPLIER),
 		.total_capacity =
 			cpu_to_le64(DEV_SIZE / CXL_CAPACITY_MULTIPLIER),
-		.inject_poison_limit = cpu_to_le16(MOCK_INJECT_DEV_MAX),
+		.inject_poison_limit = cpu_to_le16(MOCK_INJECT_TEST_MAX),
 	};
 
 	put_unaligned_le24(CXL_POISON_LIST_MAX, id.poison_list_max_mer);
@@ -919,7 +921,7 @@ static struct cxl_mbox_poison_out
 	int nr_records = 0;
 	u64 dpa;
 
-	po = kzalloc(struct_size(po, record, MOCK_INJECT_DEV_MAX), GFP_KERNEL);
+	po = kzalloc(struct_size(po, record, poison_inject_dev_max), GFP_KERNEL);
 	if (!po)
 		return NULL;
 
@@ -934,7 +936,7 @@ static struct cxl_mbox_poison_out
 		po->record[nr_records].address = cpu_to_le64(dpa);
 		po->record[nr_records].length = cpu_to_le32(1);
 		nr_records++;
-		if (nr_records == MOCK_INJECT_DEV_MAX)
+		if (nr_records == poison_inject_dev_max)
 			break;
 	}
 
@@ -969,7 +971,7 @@ static bool mock_poison_dev_max_injected(struct cxl_dev_state *cxlds)
 		if (mock_poison_list[i].cxlds == cxlds)
 			count++;
 	}
-	return (count >= MOCK_INJECT_DEV_MAX);
+	return (count >= poison_inject_dev_max);
 }
 
 static bool mock_poison_add(struct cxl_dev_state *cxlds, u64 dpa)
@@ -1051,6 +1053,47 @@ static int mock_clear_poison(struct cxl_dev_state *cxlds,
 	return 0;
 }
 
+static bool mock_poison_list_empty(void)
+{
+	for (int i = 0; i < MOCK_INJECT_TEST_MAX; i++) {
+		if (mock_poison_list[i].cxlds)
+			return false;
+	}
+	return true;
+}
+
+static ssize_t poison_inject_max_show(struct device_driver *drv, char *buf)
+{
+	return sysfs_emit(buf, "%u\n", poison_inject_dev_max);
+}
+
+static ssize_t poison_inject_max_store(struct device_driver *drv,
+				       const char *buf, size_t len)
+{
+	int val;
+
+	if (kstrtoint(buf, 0, &val) < 0)
+		return -EINVAL;
+
+	if (!mock_poison_list_empty())
+		return -EBUSY;
+
+	if (val <= MOCK_INJECT_TEST_MAX)
+		poison_inject_dev_max = val;
+	else
+		return -EINVAL;
+
+	return len;
+}
+
+static DRIVER_ATTR_RW(poison_inject_max);
+
+static struct attribute *cxl_mock_mem_core_attrs[] = {
+	&driver_attr_poison_inject_max.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(cxl_mock_mem_core);
+
 static int cxl_mock_mbox_send(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd)
 {
 	struct device *dev = cxlds->dev;
@@ -1259,6 +1302,7 @@ static struct platform_driver cxl_mock_mem_driver = {
 	.driver = {
 		.name = KBUILD_MODNAME,
 		.dev_groups = cxl_mock_mem_groups,
+		.groups = cxl_mock_mem_core_groups,
 	},
 };
 
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v6 10/10] tools/testing/cxl: Require CONFIG_DEBUG_FS
  2023-04-19  3:26 [PATCH v6 0/10] cxl: CXL Inject & Clear Poison alison.schofield
                   ` (8 preceding siblings ...)
  2023-04-19  3:26 ` [PATCH v6 09/10] tools/testing/cxl: Add a sysfs attr to test poison inject limits alison.schofield
@ 2023-04-19  3:26 ` alison.schofield
  2023-04-23 15:42 ` [PATCH v6 0/10] cxl: CXL Inject & Clear Poison Jonathan Cameron
  10 siblings, 0 replies; 16+ messages in thread
From: alison.schofield @ 2023-04-19  3:26 UTC (permalink / raw)
  To: Dan Williams, Ira Weiny, Vishal Verma, Ben Widawsky, Dave Jiang
  Cc: Alison Schofield, linux-cxl

From: Alison Schofield <alison.schofield@intel.com>

The cxl_mem driver uses debugfs to support poison inject and clear.
Add debugfs to the list of required symbols so that cxl_test can
emulate those poison operations.

Signed-off-by: Alison Schofield <alison.schofield@intel.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
---
 tools/testing/cxl/config_check.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tools/testing/cxl/config_check.c b/tools/testing/cxl/config_check.c
index 99b56b5f6edf..0902c5d6e410 100644
--- a/tools/testing/cxl/config_check.c
+++ b/tools/testing/cxl/config_check.c
@@ -13,4 +13,5 @@ void check(void)
 	BUILD_BUG_ON(!IS_MODULE(CONFIG_CXL_PMEM));
 	BUILD_BUG_ON(!IS_ENABLED(CONFIG_CXL_REGION_INVALIDATION_TEST));
 	BUILD_BUG_ON(!IS_ENABLED(CONFIG_NVDIMM_SECURITY_TEST));
+	BUILD_BUG_ON(!IS_ENABLED(CONFIG_DEBUG_FS));
 }
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* RE: [PATCH v6 01/10] cxl/memdev: Add support for the Inject Poison mailbox command
  2023-04-19  3:26 ` [PATCH v6 01/10] cxl/memdev: Add support for the Inject Poison mailbox command alison.schofield
@ 2023-04-22 21:49   ` Dan Williams
  0 siblings, 0 replies; 16+ messages in thread
From: Dan Williams @ 2023-04-22 21:49 UTC (permalink / raw)
  To: alison.schofield, Dan Williams, Ira Weiny, Vishal Verma,
	Ben Widawsky, Dave Jiang
  Cc: Alison Schofield, linux-cxl, Jonathan Cameron

alison.schofield@ wrote:
> From: Alison Schofield <alison.schofield@intel.com>
> 
> CXL devices optionally support the INJECT POISON mailbox command. Add
> memdev driver support for the mailbox command.
> 
> Per the CXL Specification (3.0 8.2.9.8.4.2), after receiving a valid
> inject poison request, the device will return poison when the address
> is accessed through the CXL.mem driver. Injecting poison adds the address
> to the device's Poison List and the error source is set to Injected.
> In addition, the device adds a poison creation event to its internal
> Informational Event log, updates the Event Status register, and if
> configured, interrupts the host.
> 
> Also, per the CXL Specification, it is not an error to inject poison
> into an address that already has poison present and no error is
> returned from the device.
> 
> If the address is not contained in the device's dpa resource, or is
> not 64 byte aligned, return -EINVAL without issuing the mbox command.
> 
> Poison injection is intended for debug only and will be exposed to
> userspace through debugfs. Restrict compilation to CONFIG_DEBUG_FS.
> 
> Signed-off-by: Alison Schofield <alison.schofield@intel.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> ---
>  drivers/cxl/core/memdev.c | 56 +++++++++++++++++++++++++++++++++++++++
>  drivers/cxl/cxlmem.h      |  6 +++++
>  2 files changed, 62 insertions(+)
> 
> diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
> index 8db7f220f182..474f7c2f4f6e 100644
> --- a/drivers/cxl/core/memdev.c
> +++ b/drivers/cxl/core/memdev.c
> @@ -160,6 +160,62 @@ int cxl_trigger_poison_list(struct cxl_memdev *cxlmd)
>  }
>  EXPORT_SYMBOL_NS_GPL(cxl_trigger_poison_list, CXL);
>  
> +static int cxl_validate_poison_dpa(struct cxl_memdev *cxlmd, u64 dpa)
> +{
> +	struct cxl_dev_state *cxlds = cxlmd->cxlds;
> +
> +	if (!IS_ENABLED(CONFIG_DEBUG_FS))
> +		return 0;

This does no harm, but it looks unnecessary given that it is only called
by debugfs entry points which already compile away in the
CONFIG_DEBUG_FS=n case. It also takes no action, so why block it if
someone besides a debugfs entry point wants to use it?

I'll leave it for now.

> +
> +	if (!resource_size(&cxlds->dpa_res)) {
> +		dev_dbg(cxlds->dev, "device has no dpa resource\n");
> +		return -EINVAL;
> +	}
> +	if (dpa < cxlds->dpa_res.start || dpa > cxlds->dpa_res.end) {
> +		dev_dbg(cxlds->dev, "dpa:0x%llx not in resource:%pR\n",
> +			dpa, &cxlds->dpa_res);
> +		return -EINVAL;
> +	}
> +	if (!IS_ALIGNED(dpa, 64)) {
> +		dev_dbg(cxlds->dev, "dpa:0x%llx is not 64-byte aligned\n", dpa);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa)
> +{
> +	struct cxl_dev_state *cxlds = cxlmd->cxlds;
> +	struct cxl_mbox_inject_poison inject;
> +	struct cxl_mbox_cmd mbox_cmd;
> +	int rc;
> +
> +	if (!IS_ENABLED(CONFIG_DEBUG_FS))
> +		return 0;
> +
> +	rc = down_read_interruptible(&cxl_dpa_rwsem);
> +	if (rc)
> +		return rc;
> +
> +	rc = cxl_validate_poison_dpa(cxlmd, dpa);
> +	if (rc)
> +		goto out;
> +
> +	inject.address = cpu_to_le64(dpa);
> +	mbox_cmd = (struct cxl_mbox_cmd) {
> +		.opcode = CXL_MBOX_OP_INJECT_POISON,
> +		.size_in = sizeof(inject),
> +		.payload_in = &inject,
> +	};
> +	rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
> +out:
> +	up_read(&cxl_dpa_rwsem);
> +
> +	return rc;
> +}
> +EXPORT_SYMBOL_NS_GPL(cxl_inject_poison, CXL);
> +
>  static struct attribute *cxl_memdev_attributes[] = {
>  	&dev_attr_serial.attr,
>  	&dev_attr_firmware_version.attr,
> diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
> index 68b9db545aae..8a3ea9cabf1f 100644
> --- a/drivers/cxl/cxlmem.h
> +++ b/drivers/cxl/cxlmem.h
> @@ -615,6 +615,11 @@ struct cxl_mbox_poison_out {
>  #define CXL_POISON_SOURCE_INJECTED	3
>  #define CXL_POISON_SOURCE_VENDOR	7
>  
> +/* Inject & Clear Poison  CXL 3.0 Spec 8.2.9.8.4.2/3 */
> +struct cxl_mbox_inject_poison {
> +	__le64 address;
> +};
> +
>  /**
>   * struct cxl_mem_command - Driver representation of a memory device command
>   * @info: Command information as it exists for the UAPI
> @@ -689,6 +694,7 @@ int cxl_poison_state_init(struct cxl_dev_state *cxlds);
>  int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,
>  		       struct cxl_region *cxlr);
>  int cxl_trigger_poison_list(struct cxl_memdev *cxlmd);
> +int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa);
>  
>  #ifdef CONFIG_CXL_SUSPEND
>  void cxl_mem_active_inc(void);
> -- 
> 2.37.3
> 



^ permalink raw reply	[flat|nested] 16+ messages in thread

* RE: [PATCH v6 08/10] tools/testing/cxl: Use injected poison for get poison list
  2023-04-19  3:26 ` [PATCH v6 08/10] tools/testing/cxl: Use injected poison for get poison list alison.schofield
@ 2023-04-22 22:03   ` Dan Williams
  0 siblings, 0 replies; 16+ messages in thread
From: Dan Williams @ 2023-04-22 22:03 UTC (permalink / raw)
  To: alison.schofield, Dan Williams, Ira Weiny, Vishal Verma,
	Ben Widawsky, Dave Jiang
  Cc: Alison Schofield, linux-cxl

alison.schofield@ wrote:
> From: Alison Schofield <alison.schofield@intel.com>
> 
> Prior to poison inject support, the mock of 'Get Poison List'
> returned a poison list containing a single mocked error record.
> 
> Following the addition of poison inject and clear support to the
> mock driver, use the mock_poison_list[], rather than faking an
> error record. Mock_poison_list[] list tracks the actual poison
> inject and clear requests issued by userspace.
> 
> Signed-off-by: Alison Schofield <alison.schofield@intel.com>
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> ---
>  tools/testing/cxl/test/mem.c | 59 ++++++++++++++++++++++++------------
>  1 file changed, 40 insertions(+), 19 deletions(-)
> 
> diff --git a/tools/testing/cxl/test/mem.c b/tools/testing/cxl/test/mem.c
> index 3c3909d30d03..cce7ec8f0efb 100644
> --- a/tools/testing/cxl/test/mem.c
> +++ b/tools/testing/cxl/test/mem.c
> @@ -912,31 +912,52 @@ static struct mock_poison {
>  	u64 dpa;
>  } mock_poison_list[MOCK_INJECT_TEST_MAX];
>  
> +static struct cxl_mbox_poison_out
> +*cxl_get_injected_po(struct cxl_dev_state *cxlds, u64 offset, u64 length)
> +{
> +	struct cxl_mbox_poison_out *po;
> +	int nr_records = 0;
> +	u64 dpa;
> +
> +	po = kzalloc(struct_size(po, record, MOCK_INJECT_DEV_MAX), GFP_KERNEL);
> +	if (!po)
> +		return NULL;

I do not see where this is freed.

> +
> +	for (int i = 0; i < MOCK_INJECT_TEST_MAX; i++) {
> +		if (mock_poison_list[i].cxlds != cxlds)
> +			continue;
> +		if (mock_poison_list[i].dpa < offset ||
> +		    mock_poison_list[i].dpa > offset + length - 1)
> +			continue;
> +
> +		dpa = mock_poison_list[i].dpa + CXL_POISON_SOURCE_INJECTED;
> +		po->record[nr_records].address = cpu_to_le64(dpa);
> +		po->record[nr_records].length = cpu_to_le32(1);
> +		nr_records++;
> +		if (nr_records == MOCK_INJECT_DEV_MAX)
> +			break;
> +	}
> +
> +	/* Always return count, even when zero */
> +	po->count = cpu_to_le16(nr_records);
> +
> +	return po;
> +}
> +
>  static int mock_get_poison(struct cxl_dev_state *cxlds,
>  			   struct cxl_mbox_cmd *cmd)
>  {
>  	struct cxl_mbox_poison_in *pi = cmd->payload_in;
> +	struct cxl_mbox_poison_out *po;
> +	u64 offset = le64_to_cpu(pi->offset);
> +	u64 length = le64_to_cpu(pi->length);
> +	int nr_records;
>  
> -	/* Mock one poison record at pi.offset for 64 bytes */
> -	struct {
> -		struct cxl_mbox_poison_out po;
> -		struct cxl_poison_record record;
> -	} __packed mock_plist = {
> -		.po = {
> -			.count = cpu_to_le16(1),
> -		},
> -		.record = {
> -			.length = cpu_to_le32(1),
> -			.address = cpu_to_le64(le64_to_cpu(pi->offset) +
> -					       CXL_POISON_SOURCE_INJECTED),
> -		},
> -	};
> +	po = cxl_get_injected_po(cxlds, offset, length);
> +	nr_records = le16_to_cpu(po->count);

This needs to check for NULL @po before use.

> +	memcpy(cmd->payload_out, po, struct_size(po, record, nr_records));
> +	cmd->size_out = struct_size(po, record, nr_records);

Looks like the kfree wants to be here. I was going to say just make @po
a static allocation, but I see that you make this dynamically sized in a
later patch. I can fix this up on applying.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v6 03/10] cxl/memdev: Warn of poison inject or clear to a mapped region
  2023-04-19  3:26 ` [PATCH v6 03/10] cxl/memdev: Warn of poison inject or clear to a mapped region alison.schofield
@ 2023-04-23 15:35   ` Jonathan Cameron
  2023-04-23 18:36     ` Dan Williams
  0 siblings, 1 reply; 16+ messages in thread
From: Jonathan Cameron @ 2023-04-23 15:35 UTC (permalink / raw)
  To: alison.schofield
  Cc: Dan Williams, Ira Weiny, Vishal Verma, Ben Widawsky, Dave Jiang,
	linux-cxl

On Tue, 18 Apr 2023 20:26:27 -0700
alison.schofield@intel.com wrote:

> From: Alison Schofield <alison.schofield@intel.com>
> 
> Inject and clear poison capabilities and intended for debug usage only.
> In order to be useful in debug environments, the driver needs to allow
> inject and clear operations on DPAs mapped in regions.
> 
> dev_warn_once() when either operation occurs.
> 
> Signed-off-by: Alison Schofield <alison.schofield@intel.com>

The warn for the clear says it's injecting poison.  Other than that.
(I wondered why I got two copies of a dev_warn_once() message in my
test kernel log).

Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

> ---
>  drivers/cxl/core/memdev.c | 58 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 58 insertions(+)
> 
> diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
> index 3b48b6eec007..23ac8d322b37 100644
> --- a/drivers/cxl/core/memdev.c
> +++ b/drivers/cxl/core/memdev.c
> @@ -160,6 +160,50 @@ int cxl_trigger_poison_list(struct cxl_memdev *cxlmd)
>  }
>  EXPORT_SYMBOL_NS_GPL(cxl_trigger_poison_list, CXL);
>  
> +struct cxl_dpa_to_region_context {
> +	struct cxl_region *cxlr;
> +	u64 dpa;
> +};
> +
> +static int __cxl_dpa_to_region(struct device *dev, void *arg)
> +{
> +	struct cxl_dpa_to_region_context *ctx = arg;
> +	struct cxl_endpoint_decoder *cxled;
> +	u64 dpa = ctx->dpa;
> +
> +	if (!is_endpoint_decoder(dev))
> +		return 0;
> +
> +	cxled = to_cxl_endpoint_decoder(dev);
> +	if (!cxled->dpa_res || !resource_size(cxled->dpa_res))
> +		return 0;
> +
> +	if (dpa > cxled->dpa_res->end || dpa < cxled->dpa_res->start)
> +		return 0;
> +
> +	dev_dbg(dev, "dpa:0x%llx mapped in region:%s\n", dpa,
> +		dev_name(&cxled->cxld.region->dev));
> +
> +	ctx->cxlr = cxled->cxld.region;
> +
> +	return 1;
> +}
> +
> +static struct cxl_region *cxl_dpa_to_region(struct cxl_memdev *cxlmd, u64 dpa)
> +{
> +	struct cxl_dpa_to_region_context ctx;
> +	struct cxl_port *port;
> +
> +	ctx = (struct cxl_dpa_to_region_context) {
> +		.dpa = dpa,
> +	};
> +	port = dev_get_drvdata(&cxlmd->dev);
> +	if (port && is_cxl_endpoint(port) && port->commit_end != -1)
> +		device_for_each_child(&port->dev, &ctx, __cxl_dpa_to_region);
> +
> +	return ctx.cxlr;
> +}
> +
>  static int cxl_validate_poison_dpa(struct cxl_memdev *cxlmd, u64 dpa)
>  {
>  	struct cxl_dev_state *cxlds = cxlmd->cxlds;
> @@ -189,6 +233,7 @@ int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa)
>  	struct cxl_dev_state *cxlds = cxlmd->cxlds;
>  	struct cxl_mbox_inject_poison inject;
>  	struct cxl_mbox_cmd mbox_cmd;
> +	struct cxl_region *cxlr;
>  	int rc;
>  
>  	if (!IS_ENABLED(CONFIG_DEBUG_FS))
> @@ -209,6 +254,13 @@ int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa)
>  		.payload_in = &inject,
>  	};
>  	rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
> +	if (rc)
> +		goto out;
> +
> +	cxlr = cxl_dpa_to_region(cxlmd, dpa);
> +	if (cxlr)
> +		dev_warn_once(cxlds->dev, "poison inject dpa:0x%llx region: %s\n",
> +			      dpa, dev_name(&cxlr->dev));
>  out:
>  	up_read(&cxl_dpa_rwsem);
>  
> @@ -221,6 +273,7 @@ int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa)
>  	struct cxl_dev_state *cxlds = cxlmd->cxlds;
>  	struct cxl_mbox_clear_poison clear;
>  	struct cxl_mbox_cmd mbox_cmd;
> +	struct cxl_region *cxlr;
>  	int rc;
>  
>  	if (!IS_ENABLED(CONFIG_DEBUG_FS))
> @@ -252,6 +305,11 @@ int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa)
>  	rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
>  	if (rc)
>  		goto out;
> +
> +	cxlr = cxl_dpa_to_region(cxlmd, dpa);
> +	if (cxlr)
> +		dev_warn_once(cxlds->dev, "poison inject dpa:0x%llx region: %s\n",

Ah. This had me confused. I got two warnings from a dev_warn_once.

Should be mentioning clearing for this one not injecting ;)

> +			      dpa, dev_name(&cxlr->dev));
>  out:
>  	up_read(&cxl_dpa_rwsem);
>  


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v6 0/10] cxl: CXL Inject & Clear Poison
  2023-04-19  3:26 [PATCH v6 0/10] cxl: CXL Inject & Clear Poison alison.schofield
                   ` (9 preceding siblings ...)
  2023-04-19  3:26 ` [PATCH v6 10/10] tools/testing/cxl: Require CONFIG_DEBUG_FS alison.schofield
@ 2023-04-23 15:42 ` Jonathan Cameron
  10 siblings, 0 replies; 16+ messages in thread
From: Jonathan Cameron @ 2023-04-23 15:42 UTC (permalink / raw)
  To: alison.schofield
  Cc: Dan Williams, Ira Weiny, Vishal Verma, Ben Widawsky, Dave Jiang,
	linux-cxl

On Tue, 18 Apr 2023 20:26:24 -0700
alison.schofield@intel.com wrote:

> From: Alison Schofield <alison.schofield@intel.com>
> 
> Built on cxl/next plus [PATCH v13 0/9] CXL Poison List Retrieval & Tracing
> https://lore.kernel.org/linux-cxl/cover.1681838291.git.alison.schofield@intel.com/

For 1-5 given I've poking them from QEMU whilst testing the emulation and
it all worked well.

Tested-by: Jonathan Cameron <Jonathan.Cameron@huawei.com.
> 
> Changes in v6:
> - Drop patches: The deprecate, and the removal of raw access, introduced
>   for all poison commands in v13 of CXL Poison List Retrieval & Tracing,
>   made these 2 patches obsolete:
> 	cxl/memdev: Make inject and clear poison cmds kernel exclusive
> 	cxl/mbox: Block inject and clear poison opcodes in raw mode
> 
> - The device always writes the write data on Clear, regardless of whether or
>   not the address is actually poisoned. Stop stating otherwise. (Jonathan)
> - Update Patch 1 commit message to refer to CXL.mem driver (DaveJ)
> - __cxl_dpa_to_region() Stop the walk on a match (Jonathan)
> - Set & use cxlds->poison.enabled_cmds for inject & clear
> - Simplify inject payload address assignment (DaveJ)
> - Use down_read_interruptible in inject/clear 
> - Tidy up the memdev core api for inject/clear by using cxl_memdev
> - Use the available cxl_memdev rather than dev in debugfs_create_file()
> 
> Link to v5:
> https://lore.kernel.org/linux-cxl/cover.1679892337.git.alison.schofield@intel.com/
> 
> 
> Introducing Inject and Clear Poison support for CXL Devices.
> 
> These are optional commands, meaning not all CXL devices must support
> them. The debugfs attributes, inject_poison and clear_poison, are only
> visible for devices reporting support of the capability.
> 
> Example:
> # echo 0x40000000 > /sys/kernel/debug/cxl/mem1/inject_poison
> 
> cxl_poison: memdev=mem1 pcidev=cxl_mem.1 trace_type=Inject region= region_uuid=00000000-0000-0000-0000-000000000000 hpa=0xffffffffffffffff dpa=0x40000000 dpa_length=0x40 source=Unknown flags= overflow_time=0
> 
> Example in which the injected poison landed in region5:
> # echo 0x40000000 > /sys/kernel/debug/cxl/mem0/inject_poison
> 
> cxl_poison: memdev=mem0 host=cxl_mem.0 serial=0 trace_type=Inject region=region5 region_uuid=cfcfc13a-5290-4983-aa74-4c8465c25f26 hpa=0xf110000000 dpa=0x40000000 dpa_length=0x40 source=Unknown flags= overflow_time=0
> 
> 
> Alison Schofield (10):
>   cxl/memdev: Add support for the Inject Poison mailbox command
>   cxl/memdev: Add support for the Clear Poison mailbox command
>   cxl/memdev: Warn of poison inject or clear to a mapped region
>   cxl/memdev: Trace inject and clear poison as cxl_poison events
>   cxl/mem: Add debugfs attributes for poison inject and clear
>   tools/testing/cxl: Mock the Inject Poison mailbox command
>   tools/testing/cxl: Mock the Clear Poison mailbox command
>   tools/testing/cxl: Use injected poison for get poison list
>   tools/testing/cxl: Add a sysfs attr to test poison inject limits
>   tools/testing/cxl: Require CONFIG_DEBUG_FS
> 
>  Documentation/ABI/testing/debugfs-cxl |  35 +++++
>  drivers/cxl/core/core.h               |   2 +
>  drivers/cxl/core/memdev.c             | 172 ++++++++++++++++++++
>  drivers/cxl/core/trace.h              |   8 +-
>  drivers/cxl/cxlmem.h                  |  13 ++
>  drivers/cxl/mem.c                     |  28 ++++
>  tools/testing/cxl/config_check.c      |   1 +
>  tools/testing/cxl/test/mem.c          | 216 +++++++++++++++++++++++---
>  8 files changed, 453 insertions(+), 22 deletions(-)
>  create mode 100644 Documentation/ABI/testing/debugfs-cxl
> 


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v6 03/10] cxl/memdev: Warn of poison inject or clear to a mapped region
  2023-04-23 15:35   ` Jonathan Cameron
@ 2023-04-23 18:36     ` Dan Williams
  0 siblings, 0 replies; 16+ messages in thread
From: Dan Williams @ 2023-04-23 18:36 UTC (permalink / raw)
  To: Jonathan Cameron, alison.schofield
  Cc: Dan Williams, Ira Weiny, Vishal Verma, Ben Widawsky, Dave Jiang,
	linux-cxl

Jonathan Cameron wrote:
> On Tue, 18 Apr 2023 20:26:27 -0700
> alison.schofield@intel.com wrote:
> 
> > From: Alison Schofield <alison.schofield@intel.com>
> > 
> > Inject and clear poison capabilities and intended for debug usage only.
> > In order to be useful in debug environments, the driver needs to allow
> > inject and clear operations on DPAs mapped in regions.
> > 
> > dev_warn_once() when either operation occurs.
> > 
> > Signed-off-by: Alison Schofield <alison.schofield@intel.com>
> 
> The warn for the clear says it's injecting poison.  Other than that.
> (I wondered why I got two copies of a dev_warn_once() message in my
> test kernel log).
> 
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> 
[..]
> > @@ -252,6 +305,11 @@ int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa)
> >  	rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
> >  	if (rc)
> >  		goto out;
> > +
> > +	cxlr = cxl_dpa_to_region(cxlmd, dpa);
> > +	if (cxlr)
> > +		dev_warn_once(cxlds->dev, "poison inject dpa:0x%llx region: %s\n",
> 
> Ah. This had me confused. I got two warnings from a dev_warn_once.
> 
> Should be mentioning clearing for this one not injecting ;)

Will fix that up on applying. I also notice that it is spelling out "0x"
when "%#" will do for the number format.

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2023-04-23 18:37 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-04-19  3:26 [PATCH v6 0/10] cxl: CXL Inject & Clear Poison alison.schofield
2023-04-19  3:26 ` [PATCH v6 01/10] cxl/memdev: Add support for the Inject Poison mailbox command alison.schofield
2023-04-22 21:49   ` Dan Williams
2023-04-19  3:26 ` [PATCH v6 02/10] cxl/memdev: Add support for the Clear " alison.schofield
2023-04-19  3:26 ` [PATCH v6 03/10] cxl/memdev: Warn of poison inject or clear to a mapped region alison.schofield
2023-04-23 15:35   ` Jonathan Cameron
2023-04-23 18:36     ` Dan Williams
2023-04-19  3:26 ` [PATCH v6 04/10] cxl/memdev: Trace inject and clear poison as cxl_poison events alison.schofield
2023-04-19  3:26 ` [PATCH v6 05/10] cxl/mem: Add debugfs attributes for poison inject and clear alison.schofield
2023-04-19  3:26 ` [PATCH v6 06/10] tools/testing/cxl: Mock the Inject Poison mailbox command alison.schofield
2023-04-19  3:26 ` [PATCH v6 07/10] tools/testing/cxl: Mock the Clear " alison.schofield
2023-04-19  3:26 ` [PATCH v6 08/10] tools/testing/cxl: Use injected poison for get poison list alison.schofield
2023-04-22 22:03   ` Dan Williams
2023-04-19  3:26 ` [PATCH v6 09/10] tools/testing/cxl: Add a sysfs attr to test poison inject limits alison.schofield
2023-04-19  3:26 ` [PATCH v6 10/10] tools/testing/cxl: Require CONFIG_DEBUG_FS alison.schofield
2023-04-23 15:42 ` [PATCH v6 0/10] cxl: CXL Inject & Clear Poison Jonathan Cameron

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.