From: Jonathan Cameron <jic23@kernel.org>
To: Shaikh Kamaluddin <shaikhkamal2012@gmail.com>
Cc: Davidlohr Bueso <dave@stgolabs.net>,
Dave Jiang <dave.jiang@intel.com>,
Alison Schofield <alison.schofield@intel.com>,
Vishal Verma <vishal.l.verma@intel.com>,
Dan Williams <djbw@kernel.org>, Miaohe Lin <linmiaohe@huawei.com>,
Andrew Morton <akpm@linux-foundation.org>,
Vlastimil Babka <vbabka@kernel.org>,
Breno Leitao <leitao@debian.org>, Ira Weiny <iweiny@kernel.org>,
Li Ming <ming.li@zohomail.com>, Richard Cheng <icheng@nvidia.com>,
Naoya Horiguchi <nao.horiguchi@gmail.com>,
Suren Baghdasaryan <surenb@google.com>,
Michal Hocko <mhocko@suse.com>,
Brendan Jackman <brendan.jackman@linux.dev>,
Johannes Weiner <hannes@cmpxchg.org>, Zi Yan <ziy@nvidia.com>,
linux-cxl@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-mm@kvack.org, David Hildenbrand <david@kernel.org>,
Oscar Salvador <osalvador@suse.de>,
Kiryl Shutsemau <kas@kernel.org>, Harry Yoo <harry@kernel.org>
Subject: Re: [RFC PATCH 1/5] cxl/mbox: Add Get Poison List snapshot support
Date: Fri, 16 Oct 2026 23:18:27 +0100 [thread overview]
Message-ID: <20261016231827.074e0326@jic23-hlaptop> (raw)
In-Reply-To: <20261010162017.62506-2-shaikhkamal2012@gmail.com>
On Sat, 10 Oct 2026 21:50:09 +0530
Shaikh Kamaluddin <shaikhkamal2012@gmail.com> wrote:
> cxl_mem_get_poison() uses a device-owned output buffer for each Get
> Poison List response. It traces the records before issuing the next
> command, which overwrites that buffer when the device sets the More
> Media Error Records flag. A caller therefore cannot inspect the complete
> set of collected records after the function returns.
>
> Add a caller-owned snapshot and copy each validated mailbox response
> into it. Preserve device overflow and scan-in-progress status, and
> indicate when the host stops collection before retrieving all available
> records.
>
> Keep cxl_mem_get_poison() as the existing trace-only wrapper so its
> current callers, including trigger_poison_list, retain their behavior.
>
> Signed-off-by: Shaikh Kamaluddin <shaikhkamal2012@gmail.com>
> ---
> drivers/cxl/core/mbox.c | 137 ++++++++++++++++++++++++++++++++++++++--
> drivers/cxl/cxlmem.h | 25 ++++++++
> 2 files changed, 156 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c
> index 55828a836c01..2752b46ffee2 100644
> --- a/drivers/cxl/core/mbox.c
> +++ b/drivers/cxl/core/mbox.c
> @@ -1376,14 +1376,91 @@ int cxl_set_timestamp(struct cxl_memdev_state *mds)
> }
> EXPORT_SYMBOL_NS_GPL(cxl_set_timestamp, "CXL");
>
> -int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,
> - struct cxl_region *cxlr)
> +int cxl_poison_snapshot_init(struct cxl_memdev *cxlmd,
> + struct cxl_poison_snapshot *snapshot)
> +{
> + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
> + u32 capacity = mds->poison.max_errors;
> +
> + if (!snapshot)
That seems like a buggy use of the interface, so not sure we need
that defence.
> + return -EINVAL;
> + memset(snapshot, 0, sizeof(*snapshot));
> +
> + if (!test_bit(CXL_POISON_ENABLED_LIST, mds->poison.enabled_cmds))
> + return -EOPNOTSUPP;
> +
> + if (!capacity)
> + return -EPROTO;
> +
> + snapshot->records = kvmalloc_array(mds->poison.max_errors,
> + sizeof(*snapshot->records),
> + GFP_KERNEL);
kvmalloc_objs()?
> + if (!snapshot->records)
> + return -ENOMEM;
> +
> + snapshot->capacity = capacity;
> +
> + return 0;
> +}
> +
> +void cxl_poison_snapshot_destroy(struct cxl_poison_snapshot *snapshot)
> +{
> + if (!snapshot)
> + return;
> +
> + kvfree(snapshot->records);
> + memset(snapshot, 0, sizeof(*snapshot));
> +}
> +
> +static int cxl_poison_snapshot_append(struct cxl_poison_snapshot *snapshot,
> + struct cxl_poison_record *records,
> + u32 count)
> +{
> + u32 available;
> +
> + /*
> + * Existing cxl_mem_get_poison() callers request tracing only and
> + * pass no snapshot.
> + */
> +
> + if (!snapshot)
> + return 0;
> +
> + if (!snapshot->records)
> + return -EINVAL;
> +
> + if (snapshot->nr_records > snapshot->capacity)
> + return -EOVERFLOW;
> +
> + if (!count)
> + return 0;
> +
> + if (!records)
> + return -EINVAL;
> +
> + available = snapshot->capacity - snapshot->nr_records;
> + if (count > available) {
> + snapshot->truncated = true;
> + return -ENOSPC;
> + }
> +
> + memcpy(&snapshot->records[snapshot->nr_records], records,
> + count * sizeof(*records));
> + snapshot->nr_records += count;
> +
> + return 0;
> +}
> +
> +static int cxl_mem_get_poison_common(struct cxl_memdev *cxlmd, u64 offset,
> + u64 len, struct cxl_region *cxlr,
> + struct cxl_poison_snapshot *snapshot)
> {
> struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
> struct cxl_mailbox *cxl_mbox = &cxlmd->cxlds->cxl_mbox;
> struct cxl_mbox_poison_out *po;
> struct cxl_mbox_poison_in pi;
> - int nr_records = 0;
> + u32 nr_records = 0;
> + u32 count;
> int rc;
>
> ACQUIRE(mutex_intr, lock)(&mds->poison.mutex);
> @@ -1408,29 +1485,77 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,
> if (rc)
> break;
>
> - if (!le16_to_cpu(po->count)) {
> + count = le16_to_cpu(po->count);
> + if (!count) {
> dev_dbg(&cxlmd->dev, "Poison empty payload!\n");
> +
> + if (po->flags & CXL_POISON_FLAG_MORE) {
> + if (snapshot)
> + snapshot->truncated = true;
Count of zero and yet more? How would that happen? This smells like
a hardware bug. Maybe we defend against it, but that's a separate
question from the rest of this patch.
> + rc = -EPROTO;
> + }
> +
> + break;
> + }
> +
> + if (struct_size(po, record, count) > mbox_cmd.size_out) {
> + dev_err(&cxlmd->dev,
> + "invalid poison record count: %u\n", count);
Also looks like broken hardware. I don't necessarily mind that sort
of defense, but not in a patch doing anything else.
> + rc = -EPROTO;
> break;
> }
>
> - for (int i = 0; i < le16_to_cpu(po->count); i++)
> + for (u32 i = 0; i < count; i++)
> trace_cxl_poison(cxlmd, cxlr, &po->record[i],
> po->flags, po->overflow_ts,
> CXL_POISON_TRACE_LIST);
>
> + if (snapshot && (po->flags & CXL_POISON_FLAG_OVERFLOW)) {
> + snapshot->device_flags |= CXL_POISON_FLAG_OVERFLOW;
> + snapshot->overflow_ts = le64_to_cpu(po->overflow_ts);
> + }
I'm curious. What use is the overflow_ts in your scheme? Lets keep things
minimal unless there is a reason to add data to the snapshot.
> +
> + if (snapshot && (po->flags & CXL_POISON_FLAG_SCANNING))
> + snapshot->device_flags |= CXL_POISON_FLAG_SCANNING;
> +
> + rc = cxl_poison_snapshot_append(snapshot, po->record, count);
> + if (rc)
> + break;
> +
> /* Protect against an uncleared _FLAG_MORE */
> - nr_records = nr_records + le16_to_cpu(po->count);
> + nr_records += count;
> if (nr_records >= mds->poison.max_errors) {
> dev_dbg(&cxlmd->dev, "Max Error Records reached: %d\n",
> nr_records);
> + if (snapshot && (po->flags & CXL_POISON_FLAG_MORE))
> + snapshot->truncated = true;
> +
> break;
> }
> } while (po->flags & CXL_POISON_FLAG_MORE);
>
> return rc;
> }
> +
> +int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,
> + struct cxl_region *cxlr)
> +{
> + return cxl_mem_get_poison_common(cxlmd, offset, len, cxlr, NULL);
> +}
> EXPORT_SYMBOL_NS_GPL(cxl_mem_get_poison, "CXL");
>
> +int cxl_mem_get_poison_snapshot(struct cxl_memdev *cxlmd, u64 offset, u64 len,
> + struct cxl_region *cxlr,
> + struct cxl_poison_snapshot *snapshot)
> +{
> + if (!snapshot || !snapshot->records || !snapshot->capacity)
> + return -EINVAL;
> +
> + if (snapshot->nr_records > snapshot->capacity)
> + return -EOVERFLOW;
> +
> + return cxl_mem_get_poison_common(cxlmd, offset, len, cxlr, snapshot);
> +}
Blank line here
> static void free_poison_buf(void *buf)
> {
> kvfree(buf);
> diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
> index c401e3a1af06..1d6f8d958bd2 100644
> --- a/drivers/cxl/cxlmem.h
> +++ b/drivers/cxl/cxlmem.h
> @@ -812,6 +812,31 @@ int cxl_set_timestamp(struct cxl_memdev_state *mds);
> int cxl_poison_state_init(struct cxl_memdev_state *mds);
> int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,
> struct cxl_region *cxlr);
> +
> +/**
> + * struct cxl_poison_snapshot - Aggregate Get Poison List result
> + * @records: Copied Media Error Records from all mailbox responses
> + * @nr_records: Number of valid records stored in @records
> + * @capacity: Maximum number of records that @records can hold
> + * @overflow_ts: Timestamp associated with a reported device overflow
> + * @device_flags: Persistent device status observed during collection
> + * @truncated: Host stopped before collecting all available records
> + */
> +struct cxl_poison_snapshot {
> + struct cxl_poison_record *records;
__counted_by_ptr() seems likely to apply here.
> + u32 nr_records;
> + u32 capacity;
> + u64 overflow_ts;
As above. I'd like to ensure this only stashes what we actually need.
> + u8 device_flags;
> + bool truncated;
> +};
> +
> +int cxl_poison_snapshot_init(struct cxl_memdev *cxlmd,
> + struct cxl_poison_snapshot *snapshot);
> +void cxl_poison_snapshot_destroy(struct cxl_poison_snapshot *snapshot);
> +int cxl_mem_get_poison_snapshot(struct cxl_memdev *cxlmd, u64 offset, u64 len,
> + struct cxl_region *cxlr,
> + struct cxl_poison_snapshot *snapshot);
> 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);
next prev parent reply other threads:[~2026-10-17 18:51 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-10 16:20 [RFC PATCH 0/5] cxl, mm: Keep device-reported poison out of the page allocator Shaikh Kamaluddin
2026-10-10 16:20 ` [RFC PATCH 1/5] cxl/mbox: Add Get Poison List snapshot support Shaikh Kamaluddin
2026-10-16 22:18 ` Jonathan Cameron [this message]
2026-10-10 16:20 ` [RFC PATCH 2/5] cxl/region: Factor decoder poison-list retrieval Shaikh Kamaluddin
2026-10-16 22:21 ` Jonathan Cameron
2026-10-10 16:20 ` [RFC PATCH 3/5] mm/memory-failure: Add a pre-online poison registry Shaikh Kamaluddin
2026-10-10 16:20 ` [RFC PATCH 4/5] mm/page_alloc: Keep pre-online poison out of the buddy allocator Shaikh Kamaluddin
2026-10-15 7:27 ` Richard Cheng
2026-10-10 16:20 ` [RFC PATCH 5/5] cxl/region: Register device poison before exposing RAM Shaikh Kamaluddin
2026-10-15 7:59 ` Richard Cheng
2026-10-16 22:35 ` Jonathan Cameron
2026-10-16 20:42 ` [RFC PATCH 0/5] cxl, mm: Keep device-reported poison out of the page allocator Jonathan Cameron
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=20261016231827.074e0326@jic23-hlaptop \
--to=jic23@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=alison.schofield@intel.com \
--cc=brendan.jackman@linux.dev \
--cc=dave.jiang@intel.com \
--cc=dave@stgolabs.net \
--cc=david@kernel.org \
--cc=djbw@kernel.org \
--cc=hannes@cmpxchg.org \
--cc=harry@kernel.org \
--cc=icheng@nvidia.com \
--cc=iweiny@kernel.org \
--cc=kas@kernel.org \
--cc=leitao@debian.org \
--cc=linmiaohe@huawei.com \
--cc=linux-cxl@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=mhocko@suse.com \
--cc=ming.li@zohomail.com \
--cc=nao.horiguchi@gmail.com \
--cc=osalvador@suse.de \
--cc=shaikhkamal2012@gmail.com \
--cc=surenb@google.com \
--cc=vbabka@kernel.org \
--cc=vishal.l.verma@intel.com \
--cc=ziy@nvidia.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®