From: alison.schofield@intel.com
To: Dan Williams <dan.j.williams@intel.com>,
Ira Weiny <ira.weiny@intel.com>,
Vishal Verma <vishal.l.verma@intel.com>,
Dave Jiang <dave.jiang@intel.com>,
Ben Widawsky <bwidawsk@kernel.org>,
Steven Rostedt <rostedt@goodmis.org>
Cc: Alison Schofield <alison.schofield@intel.com>,
linux-cxl@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH v6 4/6] cxl/region: Provide region info to the cxl_poison trace event
Date: Thu, 9 Feb 2023 15:32:57 -0800 [thread overview]
Message-ID: <7862ef793a3b4fce49b0c8074b014b53b389ce12.1675983077.git.alison.schofield@intel.com> (raw)
In-Reply-To: <cover.1675983077.git.alison.schofield@intel.com>
From: Alison Schofield <alison.schofield@intel.com>
User space may need to know which region, if any, maps the poison
address(es) logged in a cxl_poison trace event. Since the mapping
of DPAs (device physical addresses) to a region can change, the
kernel must provide this information at the time the poison list
is read. The event informs user space that at event <timestamp>
this <region> mapped to this <DPA>, which is poisoned.
The cxl_poison trace event is already wired up to log the region
name and uuid if it receives param 'struct cxl_region'.
In order to provide that cxl_region, add another method for gathering
poison - by committed endpoint decoder mappings. This method is only
available with CONFIG_CXL_REGION and is only used if a region actually
maps the memdev where poison is being read. The default method remains:
read the poison by memdev resource.
Signed-off-by: Alison Schofield <alison.schofield@intel.com>
---
drivers/cxl/core/core.h | 5 +++
drivers/cxl/core/memdev.c | 14 ++++++-
drivers/cxl/core/region.c | 82 +++++++++++++++++++++++++++++++++++++++
3 files changed, 100 insertions(+), 1 deletion(-)
diff --git a/drivers/cxl/core/core.h b/drivers/cxl/core/core.h
index 8c04672dca56..2f9bd8651eb1 100644
--- a/drivers/cxl/core/core.h
+++ b/drivers/cxl/core/core.h
@@ -22,7 +22,12 @@ void cxl_decoder_kill_region(struct cxl_endpoint_decoder *cxled);
#define CXL_PMEM_REGION_TYPE(x) (&cxl_pmem_region_type)
int cxl_region_init(void);
void cxl_region_exit(void);
+int cxl_get_poison_by_endpoint(struct device *dev, void *data);
#else
+static inline int cxl_get_poison_by_endpoint(struct device *dev, void *data)
+{
+ return 0;
+}
static inline void cxl_decoder_kill_region(struct cxl_endpoint_decoder *cxled)
{
}
diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
index 19b833c9cf35..8696d7b508b6 100644
--- a/drivers/cxl/core/memdev.c
+++ b/drivers/cxl/core/memdev.c
@@ -139,14 +139,26 @@ static ssize_t trigger_poison_list_store(struct device *dev,
const char *buf, size_t len)
{
struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
+ struct cxl_port *port;
bool trigger;
int rc;
if (kstrtobool(buf, &trigger) || !trigger)
return -EINVAL;
+ port = dev_get_drvdata(&cxlmd->dev);
+ if (!port || !is_cxl_endpoint(port))
+ return -EINVAL;
+
down_read(&cxl_dpa_rwsem);
- rc = cxl_get_poison_by_memdev(cxlmd);
+ if (port->commit_end == -1)
+ /* No regions mapped to this memdev */
+ rc = cxl_get_poison_by_memdev(cxlmd);
+ else
+ /* Regions mapped, collect poison by endpoint */
+ rc = device_for_each_child(&port->dev, port,
+ cxl_get_poison_by_endpoint);
+
up_read(&cxl_dpa_rwsem);
return rc ? rc : len;
diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
index 67e83d961670..0ac08e9106af 100644
--- a/drivers/cxl/core/region.c
+++ b/drivers/cxl/core/region.c
@@ -1826,6 +1826,88 @@ struct cxl_pmem_region *to_cxl_pmem_region(struct device *dev)
}
EXPORT_SYMBOL_NS_GPL(to_cxl_pmem_region, CXL);
+int cxl_get_poison_by_endpoint(struct device *dev, void *data)
+{
+ struct cxl_endpoint_decoder *cxled;
+ struct cxl_port *port = data;
+ struct cxl_dev_state *cxlds;
+ struct cxl_memdev *cxlmd;
+ u64 offset, length;
+ int rc = 0;
+
+ down_read(&cxl_dpa_rwsem);
+
+ if (!is_endpoint_decoder(dev))
+ goto out;
+
+ cxled = to_cxl_endpoint_decoder(dev);
+ if (!cxled->dpa_res || !resource_size(cxled->dpa_res))
+ goto out;
+
+ /*
+ * Get the poison by decoder for mapped resources. This
+ * separates pmem and ram poison list reads, as the spec
+ * requires, and provides the region for the trace event.
+ */
+ cxlmd = cxled_to_memdev(cxled);
+ length = cxled->dpa_res->end - cxled->dpa_res->start + 1;
+ rc = cxl_mem_get_poison(cxlmd, cxled->dpa_res->start, length,
+ cxled->cxld.region);
+ if (rc == -EFAULT && cxled->mode == CXL_DECODER_RAM)
+ rc = 0;
+ if (rc)
+ goto out;
+
+ /* Get poison in a skip range */
+ if (cxled->skip) {
+ rc = cxl_mem_get_poison(cxlmd, 0, cxled->skip, NULL);
+ if (rc == -EFAULT && cxled->mode == CXL_DECODER_RAM)
+ rc = 0;
+ if (rc)
+ goto out;
+ }
+
+ /* Iterate until commit_end is reached */
+ if (cxled->cxld.id < port->commit_end)
+ goto out;
+
+ /*
+ * Reach here with the last committed decoder only.
+ * Knowing that PMEM must always follow RAM, get poison
+ * for unmapped ranges based on the last decoder's mode:
+ * ram: scan remains of ram range, then scan for pmem
+ * pmem: scan remains of pmem range
+ */
+ cxlds = cxlmd->cxlds;
+
+ if (cxled->mode == CXL_DECODER_RAM) {
+ offset = cxled->dpa_res->end + 1;
+ length = resource_size(&cxlds->ram_res) - offset;
+ rc = cxl_mem_get_poison(cxlmd, offset, length, NULL);
+ if (rc == -EFAULT)
+ rc = 0;
+ if (rc)
+ goto out;
+ }
+ if (cxled->mode == CXL_DECODER_PMEM) {
+ offset = cxled->dpa_res->end + 1;
+ length = resource_size(&cxlds->pmem_res) - offset;
+ } else if (resource_size(&cxlds->pmem_res)) {
+ offset = cxlds->pmem_res.start;
+ length = resource_size(&cxlds->pmem_res);
+ } else {
+ rc = 1;
+ goto out;
+ }
+ /* Final get poison call. Return rc or 1 to stop iteration. */
+ rc = cxl_mem_get_poison(cxlmd, offset, length, NULL);
+ if (!rc)
+ rc = 1;
+out:
+ up_read(&cxl_dpa_rwsem);
+ return rc;
+}
+
static struct lock_class_key cxl_pmem_region_key;
static struct cxl_pmem_region *cxl_pmem_region_alloc(struct cxl_region *cxlr)
--
2.37.3
next prev parent reply other threads:[~2023-02-09 23:35 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-02-09 23:32 [PATCH v6 0/6] CXL Poison List Retrieval & Tracing alison.schofield
2023-02-09 23:32 ` [PATCH v6 1/6] cxl/mbox: Add GET_POISON_LIST mailbox command alison.schofield
2023-02-09 23:32 ` [PATCH v6 2/6] cxl/trace: Add TRACE support for CXL media-error records alison.schofield
2023-02-09 23:32 ` [PATCH v6 3/6] cxl/memdev: Add trigger_poison_list sysfs attribute alison.schofield
2023-02-09 23:32 ` alison.schofield [this message]
2023-02-10 12:56 ` [PATCH v6 4/6] cxl/region: Provide region info to the cxl_poison trace event Jonathan Cameron
2023-02-16 2:04 ` Alison Schofield
2023-02-09 23:32 ` [PATCH v6 5/6] cxl/trace: Add an HPA to cxl_poison trace events alison.schofield
2023-02-09 23:32 ` [PATCH v6 6/6] tools/testing/cxl: Mock support for Get Poison List alison.schofield
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=7862ef793a3b4fce49b0c8074b014b53b389ce12.1675983077.git.alison.schofield@intel.com \
--to=alison.schofield@intel.com \
--cc=bwidawsk@kernel.org \
--cc=dan.j.williams@intel.com \
--cc=dave.jiang@intel.com \
--cc=ira.weiny@intel.com \
--cc=linux-cxl@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=rostedt@goodmis.org \
--cc=vishal.l.verma@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®