From: Michal Wajdeczko <michal.wajdeczko@intel.com>
To: "Tejas Upadhyay" <tejas.upadhyay@intel.com>,
intel-xe@lists.freedesktop.org,
"Rodrigo Vivi" <rodrigo.vivi@intel.com>,
"Thomas Hellström" <thomas.hellstrom@linux.intel.com>
Cc: <himal.prasad.ghimiray@intel.com>
Subject: Re: [PATCH V16 10/12] drm/xe: Add sysfs interface for bad gpu vram pages
Date: Mon, 17 Aug 2026 13:27:11 +0200 [thread overview]
Message-ID: <a670328d-b5dc-48b4-bb02-ed7dfa2d48f1@intel.com> (raw)
In-Reply-To: <20260817065055.3734576-24-tejas.upadhyay@intel.com>
On 8/17/2026 8:51 AM, Tejas Upadhyay wrote:
> Include a sysfs interface designed to expose information about bad
> VRAM pages — those identified as having hardware faults (e.g., ECC
> errors). This interface allows userspace tools and administrators to
> monitor the health of the GPU's local memory and track the status of
> page retirement. Details on bad gpu vram pages can be found under
> /sys/bus/pci/devices/<bdf>/vram_bad_pages.
since those new files are xe driver specific, shouldn't we refer to
them using
/sys/bus/pci/drivers/xe/<bdf>/vram...
>
> The format is: pfn : gpu_page_size : flags
kernel documentation [1] says
"Mixing types, expressing multiple lines of data, and doing
fancy formatting of data is heavily frowned upon"
[1] https://docs.kernel.org/filesystems/sysfs.html#attributes
so to follow the guidelines maybe we expose the separate files:
/sys/bus/pci/drivers/xe/<bdf>/vram_page_size u64
/sys/bus/pci/drivers/xe/<bdf>/vram_bad_pages_count u64
/sys/bus/pci/drivers/xe/<bdf>/vram_bad_pages_reserved u64[]
/sys/bus/pci/drivers/xe/<bdf>/vram_bad_pages_pending u64[]
/sys/bus/pci/drivers/xe/<bdf>/vram_bad_pages_failed u64[]
or
/sys/bus/pci/drivers/xe/<bdf>
|
+-- vram/
+-- page_size u64
+-- bad_pages/
+-- count u64
+-- reserved u64[]
+-- pending u64[]
+-- failed u64[]
then
/sys/bus/pci/drivers/xe/<bdf>/vram_page_size:0x1000
/sys/bus/pci/drivers/xe/<bdf>/vram_bad_pages_count:5
/sys/bus/pci/drivers/xe/<bdf>/vram_bad_pages_reserved:0x0000000000000000
/sys/bus/pci/drivers/xe/<bdf>/vram_bad_pages_pending:0x0000000001234000
/sys/bus/pci/drivers/xe/<bdf>/vram_bad_pages_pending:0x0000000001235000
/sys/bus/pci/drivers/xe/<bdf>/vram_bad_pages_pending:0x0000000001236000
/sys/bus/pci/drivers/xe/<bdf>/vram_bad_pages_pending:0x0000000001237000
>
> flags:
> R: reserved, this gpu page is reserved.
> P: pending for reserve, this gpu page is marked as bad, will be
> reserved in next window of page_reserve.
> F: unable to reserve, this gpu page can't be reserved due to some
> reasons.
>
> For example, cat /sys/bus/pci/devices/<bdf>/vram_bad_pages:
> max_pages : 10000
> 0x0000000000000000 : 0x0000000000001000 : R
> 0x0000000000001234 : 0x0000000000001000 : P
>
> The sysfs binary attribute is created under the PCI device kobject
> when the platform supports it and the configfs bad_page_reservation
> policy is enabled. Uses RCU-protected list traversal so reads never
> block normal VRAM allocation operations.
>
> Signed-off-by: Tejas Upadhyay <tejas.upadhyay@intel.com>
> ---
> drivers/gpu/drm/xe/xe_device_sysfs.c | 7 +
> drivers/gpu/drm/xe/xe_ttm_vram_mgr.c | 141 +++++++++++++++++++++
> drivers/gpu/drm/xe/xe_ttm_vram_mgr.h | 1 +
> drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h | 2 +
> 4 files changed, 151 insertions(+)
>
> diff --git a/drivers/gpu/drm/xe/xe_device_sysfs.c b/drivers/gpu/drm/xe/xe_device_sysfs.c
> index a73e0e957cb0..47c5be4180fe 100644
> --- a/drivers/gpu/drm/xe/xe_device_sysfs.c
> +++ b/drivers/gpu/drm/xe/xe_device_sysfs.c
> @@ -8,12 +8,14 @@
> #include <linux/pci.h>
> #include <linux/sysfs.h>
>
> +#include "xe_configfs.h"
> #include "xe_device.h"
> #include "xe_device_sysfs.h"
> #include "xe_mmio.h"
> #include "xe_pcode_api.h"
> #include "xe_pcode.h"
> #include "xe_pm.h"
> +#include "xe_ttm_vram_mgr.h"
>
> /**
> * DOC: Xe device sysfs
> @@ -267,6 +269,7 @@ static const struct attribute_group auto_link_downgrade_attr_group = {
> int xe_device_sysfs_init(struct xe_device *xe)
> {
> struct device *dev = xe->drm.dev;
> + bool policy;
> int ret;
>
> if (xe->d3cold.capable) {
> @@ -285,5 +288,9 @@ int xe_device_sysfs_init(struct xe_device *xe)
> return ret;
> }
>
> + policy = xe_configfs_get_bad_page_reservation(to_pci_dev(dev));
> + if (xe->info.platform == XE_CRESCENTISLAND && policy)
> + xe_ttm_vram_sysfs_init(xe);
> +
> return 0;
> }
> diff --git a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c
> index a48196ce303f..73cd06c22d37 100644
> --- a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c
> +++ b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c
> @@ -820,3 +820,144 @@ int xe_ttm_vram_handle_addr_fault(struct xe_device *xe, u64 addr)
> return xe_ttm_vram_reserve_page_at_addr(xe, addr - vr->dpa_base, vram_mgr, mm);
> }
> EXPORT_SYMBOL(xe_ttm_vram_handle_addr_fault);
> +
> +static size_t serialize_bad_pages(struct xe_ttm_vram_mgr *mgr, char *buf, size_t max_len)
> +{
> + struct xe_ttm_vram_offline_resource *pos;
> + struct gpu_buddy_block *block;
> + size_t s = 0;
> + int printed;
> + int count = 0;
> +
> + rcu_read_lock();
> +
> + printed = scnprintf(buf + s, max_len - s, "max_pages: %d\n", mgr->max_pages);
> + s += printed;
> +
> + list_for_each_entry_rcu(pos, &mgr->offlined_pages, offlined_link) {
> + if (count >= 10000 || s >= max_len)
> + break;
> +
> + block = list_first_entry_or_null(&pos->blocks, struct gpu_buddy_block, link);
> + if (!block)
> + continue;
> +
> + printed = scnprintf(buf + s, max_len - s, "0x%016llx : 0x%016llx : %c\n",
> + gpu_buddy_block_offset(block) >> PAGE_SHIFT,
> + gpu_buddy_block_size(&mgr->mm, block), 'R');
> + s += printed;
> + count++;
> + }
> + list_for_each_entry_rcu(pos, &mgr->queued_pages, queued_link) {
> + u64 pfn, blk_size;
> +
> + if (count >= 10000 || s >= max_len)
> + break;
> +
> + block = list_first_entry_or_null(&pos->blocks, struct gpu_buddy_block, link);
> + if (block) {
> + pfn = gpu_buddy_block_offset(block) >> PAGE_SHIFT;
> + blk_size = gpu_buddy_block_size(&mgr->mm, block);
> + } else {
> + pfn = pos->addr >> PAGE_SHIFT;
> + blk_size = PAGE_SIZE;
> + }
> +
> + printed = scnprintf(buf + s, max_len - s, "0x%016llx : 0x%016llx : %c\n",
> + pfn, blk_size, pos->status ? 'F' : 'P');
> + s += printed;
> + count++;
> + }
> +
> + rcu_read_unlock();
> + return s;
> +}
> +
> +static ssize_t vram_bad_pages_bin_read(struct file *filp, struct kobject *kobj,
> + const struct bin_attribute *attr, char *buf,
> + loff_t off, size_t count)
> +{
> + struct device *dev = kobj_to_dev(kobj);
> + struct pci_dev *pdev = to_pci_dev(dev);
> + struct ttm_resource_manager *man;
> + struct xe_ttm_vram_mgr *mgr;
> + size_t allocation_size;
> + struct xe_device *xe;
> + size_t full_data_len;
> + int active_entries;
> + char *temp_buf;
> +
> + xe = pdev_to_xe_device(pdev);
> + man = ttm_manager_type(&xe->ttm, XE_PL_VRAM0);
> + if (!man)
> + return -ENODEV;
> + mgr = to_xe_ttm_vram_mgr(man);
> +
> + active_entries = READ_ONCE(mgr->n_offlined_pages) + READ_ONCE(mgr->n_queued_pages);
> +
> + if (active_entries > 10000)
> + active_entries = 10000;
> +
> + allocation_size = 64 + (active_entries * 48);
> +
> + temp_buf = kvmalloc(allocation_size, GFP_KERNEL);
> + if (!temp_buf)
> + return -ENOMEM;
> +
> + /* serialize_bad_pages uses rcu_read_lock internally */
> + full_data_len = serialize_bad_pages(mgr, temp_buf, allocation_size);
> +
> + if (off >= full_data_len) {
> + kvfree(temp_buf);
> + return 0;
> + }
> +
> + if (off + count > full_data_len)
> + count = full_data_len - off;
> +
> + memcpy(buf, temp_buf + off, count);
> +
> + kvfree(temp_buf);
> + return count;
> +}
> +
> +static const struct bin_attribute bin_attr_vram_bad_pages = {
> + .attr = { .name = "vram_bad_pages", .mode = 0444 },
> + .read = vram_bad_pages_bin_read,
> + .size = 0,
> +};
> +
> +static void xe_ttm_vram_sysfs_fini(void *arg)
> +{
> + struct xe_device *xe = arg;
> + struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
> +
> + sysfs_remove_bin_file(&pdev->dev.kobj, &bin_attr_vram_bad_pages);
> +}
> +
> +/**
> + * xe_ttm_vram_sysfs_init - Initialize vram bad pages sysfs binary file
> + * @xe: Xe Device object
> + *
> + * Creates a binary sysfs file under the PCI device for reading
> + * offlined and queued VRAM pages. Supports large entry counts
> + * via offset/count pagination.
> + *
> + * Returns: 0 on success, negative error code on error.
> + */
> +int xe_ttm_vram_sysfs_init(struct xe_device *xe)
> +{
> + struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
> + int err;
> +
> + err = sysfs_create_bin_file(&pdev->dev.kobj, &bin_attr_vram_bad_pages);
> + if (err) {
> + dev_err(&pdev->dev,
> + "Failed to create vram_bad_pages sysfs: %d\n",
> + err);
> + return err;
> + }
> +
> + return devm_add_action_or_reset(&pdev->dev, xe_ttm_vram_sysfs_fini, xe);
> +}
> +EXPORT_SYMBOL(xe_ttm_vram_sysfs_init);
> diff --git a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.h b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.h
> index d5392beff30c..eb55b0f74ef3 100644
> --- a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.h
> +++ b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.h
> @@ -32,6 +32,7 @@ void xe_ttm_vram_get_used(struct ttm_resource_manager *man,
> u64 *used, u64 *used_visible);
>
> int xe_ttm_vram_handle_addr_fault(struct xe_device *xe, u64 addr);
> +int xe_ttm_vram_sysfs_init(struct xe_device *xe);
> static inline struct xe_ttm_vram_mgr_resource *
> to_xe_ttm_vram_mgr_resource(struct ttm_resource *res)
> {
> diff --git a/drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h b/drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h
> index dc97b0ad0e51..efcf3e1d4e80 100644
> --- a/drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h
> +++ b/drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h
> @@ -37,6 +37,8 @@ struct xe_ttm_vram_mgr {
> struct mutex lock;
> /** @mem_type: The TTM memory type */
> u32 mem_type;
> + /** @max_pages: max pages that can be in offline queue retrieved from FW */
> + u16 max_pages;
> };
>
> /**
next prev parent reply other threads:[~2026-08-17 11:27 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-17 6:50 [PATCH V16 00/12] Add memory page offlining support Tejas Upadhyay
2026-08-17 6:50 ` [PATCH V16 01/12] drm/xe: Link VRAM object with gpu buddy Tejas Upadhyay
2026-08-17 6:50 ` [PATCH V16 02/12] drm/xe: Link LRC BO and its execution Queue Tejas Upadhyay
2026-08-17 6:50 ` [PATCH V16 03/12] drm/xe: Extend BO purge to handle vram pages as well Tejas Upadhyay
2026-08-17 6:50 ` [PATCH V16 04/12] drm/xe/bo: Make xe_bo_is_user() public Tejas Upadhyay
2026-08-17 6:51 ` [PATCH V16 05/12] drm/xe: Guard teardown paths against purged BOs Tejas Upadhyay
2026-08-17 6:51 ` [PATCH V16 06/12] drm/xe/vram: Extract buddy alloc and free helpers Tejas Upadhyay
2026-08-17 6:51 ` [PATCH V16 07/12] drm/xe/vram: Add page offline data structures and lifecycle Tejas Upadhyay
2026-08-17 6:51 ` [PATCH V16 08/12] drm/xe/vram: Add VRAM page offline fault handler Tejas Upadhyay
2026-08-17 6:51 ` [PATCH V16 09/12] drm/xe/configfs: Add vram bad page reservation policy Tejas Upadhyay
2026-08-17 6:51 ` [PATCH V16 10/12] drm/xe: Add sysfs interface for bad gpu vram pages Tejas Upadhyay
2026-08-17 11:27 ` Michal Wajdeczko [this message]
2026-08-17 14:58 ` Upadhyay, Tejas
2026-08-17 16:06 ` Rodrigo Vivi
2026-08-17 17:09 ` Michal Wajdeczko
2026-08-17 19:30 ` Rodrigo Vivi
2026-08-17 6:51 ` [PATCH V16 11/12] drm/xe/uapi: Expose ban reason in EXEC_QUEUE_GET_PROPERTY_BAN Tejas Upadhyay
2026-08-17 6:51 ` [PATCH V16 12/12] drm/xe: Add fault-inject based VRAM page offline injection Tejas Upadhyay
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=a670328d-b5dc-48b4-bb02-ed7dfa2d48f1@intel.com \
--to=michal.wajdeczko@intel.com \
--cc=himal.prasad.ghimiray@intel.com \
--cc=intel-xe@lists.freedesktop.org \
--cc=rodrigo.vivi@intel.com \
--cc=tejas.upadhyay@intel.com \
--cc=thomas.hellstrom@linux.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