From: Badal Nilawar <badal.nilawar@intel.com>
To: intel-xe@lists.freedesktop.org
Cc: anshuman.gupta@intel.com, rodrigo.vivi@intel.com,
daniele.ceraolospurio@intel.com, raag.jadav@intel.com,
riana.tauro@intel.com, mallesh.koujalagi@intel.com,
aravind.iddamsetty@intel.com
Subject: [RFC PATCH 5/7] drm/xe/cper: APIs to prepare and log CPER record
Date: Thu, 2 Jul 2026 16:44:07 +0530 [thread overview]
Message-ID: <20260702111401.3680214-14-badal.nilawar@intel.com> (raw)
In-Reply-To: <20260702111401.3680214-9-badal.nilawar@intel.com>
Add APIs to initialize Intel-specific CPER metadata, build a
non-standard CPER record, and emit it via the xe_error_cper tracepoint.
Signed-off-by: Badal Nilawar <badal.nilawar@intel.com>
Assisted-by: Copilot:claude-sonnet-4.6
---
drivers/gpu/drm/xe/Makefile | 1 +
drivers/gpu/drm/xe/xe_cper.c | 215 +++++++++++++++++++++++++++++++++++
drivers/gpu/drm/xe/xe_cper.h | 30 +++++
3 files changed, 246 insertions(+)
create mode 100644 drivers/gpu/drm/xe/xe_cper.c
create mode 100644 drivers/gpu/drm/xe/xe_cper.h
diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
index 01e6711cce1c..37600de21a35 100644
--- a/drivers/gpu/drm/xe/Makefile
+++ b/drivers/gpu/drm/xe/Makefile
@@ -35,6 +35,7 @@ $(obj)/generated/%_device_wa_oob.c $(obj)/generated/%_device_wa_oob.h: $(obj)/xe
xe-y += xe_bb.o \
xe_bo.o \
xe_bo_evict.o \
+ xe_cper.o \
xe_dep_scheduler.o \
xe_devcoredump.o \
xe_device.o \
diff --git a/drivers/gpu/drm/xe/xe_cper.c b/drivers/gpu/drm/xe/xe_cper.c
new file mode 100644
index 000000000000..b46190601d98
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_cper.c
@@ -0,0 +1,215 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+#include <linux/cper.h>
+#include <linux/ktime.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include <drm/drm_print.h>
+
+#include "xe_cper.h"
+#include "xe_cper_types.h"
+#include "xe_device_types.h"
+#include "xe_ras_types.h"
+#include "xe_trace_cper.h"
+
+static const struct xe_platform_id_entry xe_platform_ids[] = {
+ /* 0x674C platform/8086:674c */
+ { 0x674C, GUID_INIT(0x9046afe5, 0x9041, 0x5124,
+ 0x86, 0x14, 0x92, 0x55, 0x0d, 0x9e, 0x9d, 0xa6) },
+};
+
+/**
+ * fill_pci_bdf - populate pci_bdf in the Intel section header
+ * @xe: xe device instance
+ * @ihdr: Intel section header to update
+ *
+ * Writes the PCI domain:bus:device.function string into @ihdr->pci_bdf and
+ * sets the corresponding valid bit.
+ */
+static void fill_pci_bdf(struct xe_device *xe,
+ struct xe_cper_sec_intel_err_hdr *ihdr)
+{
+ struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
+
+ snprintf(ihdr->pci_bdf, sizeof(ihdr->pci_bdf), "%04x:%02x:%02x.%x",
+ pci_domain_nr(pdev->bus), pdev->bus->number,
+ PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
+ ihdr->valid_bits.pci_bdf = 1;
+}
+
+/**
+ * fill_drv_version - populate drv_version in the Intel section header
+ * @ihdr: Intel section header to update
+ *
+ * Copies the module's srcversion string into @ihdr->drv_version and sets the
+ * corresponding valid bit.
+ */
+static void fill_drv_version(struct xe_cper_sec_intel_err_hdr *ihdr)
+{
+ if (!THIS_MODULE->srcversion)
+ return;
+
+ strscpy(ihdr->drv_version, THIS_MODULE->srcversion,
+ sizeof(ihdr->drv_version));
+ ihdr->valid_bits.drv_version = 1;
+}
+
+/**
+ * lookup_platform_id - find the UUIDv5 platform_id for a PCI device ID
+ * @pdev: PCI device whose device ID is used as the lookup key
+ *
+ * Searches xe_platform_ids[] for an entry matching @pdev->device.
+ *
+ * Returns a pointer to the matching guid_t, or %NULL if not found.
+ */
+static const guid_t *lookup_platform_id(const struct pci_dev *pdev)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(xe_platform_ids); i++)
+ if (xe_platform_ids[i].device_id == pdev->device)
+ return &xe_platform_ids[i].platform_id;
+ return NULL;
+}
+
+static void fill_fw_id(struct xe_device *xe,
+ struct xe_cper_sec_intel_err_hdr *ihdr)
+{
+ /* TODO: populate ihdr->fw_id from firmware version queries */
+}
+
+/**
+ * xe_cper_init_intel_err_hdr - Populate an Intel CPER section header
+ * @xe: xe device instance
+ * @location: 12-byte error classification blob (cast from the source
+ * error class struct); pass %NULL if not applicable
+ * @first_timestamp: timestamp of the first occurrence; pass 0 if not available
+ * @sig_id: signal identifier for the error; pass %U32_MAX if not applicable
+ * @error_count: number of times this error has occurred
+ * @ihdr: Intel section header to populate
+ *
+ * Fills in @ihdr with the provided error metadata and sets the corresponding
+ * valid bits.
+ */
+void xe_cper_init_intel_err_hdr(struct xe_device *xe,
+ const u8 location[12],
+ u64 first_timestamp,
+ u32 sig_id,
+ u64 error_count,
+ struct xe_cper_sec_intel_err_hdr *ihdr)
+{
+ if (location) {
+ memcpy(&ihdr->error_class, location, sizeof(ihdr->error_class));
+ ihdr->valid_bits.location = 1;
+ }
+
+ if (first_timestamp) {
+ ihdr->first_timestamp = first_timestamp;
+ ihdr->valid_bits.first_timestamp = 1;
+ }
+
+ if (sig_id != U32_MAX) {
+ ihdr->sig_id = sig_id;
+ ihdr->valid_bits.sig_id = 1;
+ }
+
+ ihdr->error_count = error_count;
+
+ fill_pci_bdf(xe, ihdr);
+ fill_drv_version(ihdr);
+ fill_fw_id(xe, ihdr);
+}
+
+/**
+ * xe_cper_record_emit - Build and emit a CPER record for an Intel GPU error
+ * @xe: xe device instance
+ * @fru_id: GUID identifying the field-replaceable unit
+ * @severity: CPER error severity (CPER_SEV_*)
+ * @ihdr: Intel-specific section header, fully populated by
+ * xe_cper_init_intel_err_hdr()
+ * @einfo: optional xe_cper_sec_intel_error_info payload; may be %NULL
+ * @einfo_size: byte size of @einfo, including any event_queue data
+ *
+ * The platform_id is resolved automatically from xe_platform_ids[] using
+ * the PCI device ID. If no entry matches, the field is left zeroed and
+ * the record is still emitted.
+ */
+void xe_cper_record_emit(struct xe_device *xe,
+ const guid_t *fru_id,
+ u8 severity,
+ guid_t notification_type,
+ struct xe_cper_sec_intel_err_hdr *ihdr,
+ const void *einfo,
+ u32 einfo_size)
+{
+ struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
+ const guid_t *platform_id = lookup_platform_id(pdev);
+ u32 total_len = sizeof(struct xe_cper_nonstd_record) + einfo_size;
+ struct cper_section_descriptor *sdesc;
+ struct cper_record_header *rhdr;
+ struct xe_cper_nonstd_record *rec;
+
+ rec = kzalloc(total_len, GFP_KERNEL);
+ if (!rec) {
+ drm_err(&xe->drm, "CPER: failed to allocate record buffer\n");
+ return;
+ }
+
+ rhdr = &rec->record_hdr;
+ sdesc = &rec->section_desc;
+
+ /* Assemble the CPER record header (UEFI Appendix N.2.1) */
+ memcpy(rhdr->signature, CPER_SIG_RECORD, CPER_SIG_SIZE);
+ rhdr->revision = CPER_RECORD_REV;
+ rhdr->signature_end = CPER_SIG_END;
+ rhdr->section_count = 1;
+ rhdr->error_severity = severity;
+ rhdr->validation_bits = CPER_VALID_TIMESTAMP;
+ rhdr->record_length = total_len;
+ rhdr->timestamp = ktime_get_real_ns();
+ if (platform_id) {
+ rhdr->platform_id = *platform_id;
+ rhdr->validation_bits |= CPER_VALID_PLATFORM_ID;
+ }
+ rhdr->creator_id = INTEL_CPER_CREATOR_XEKMD;
+ rhdr->notification_type = notification_type;
+ rhdr->record_id = cper_next_record_id();
+ rhdr->flags = 0;
+
+ /* Assemble the section descriptor (UEFI Appendix N.2.2) */
+ sdesc->section_offset = sizeof(struct cper_record_header) +
+ sizeof(struct cper_section_descriptor);
+ sdesc->section_length = sizeof(struct xe_cper_sec_intel_err_hdr) +
+ einfo_size;
+ sdesc->revision = CPER_RECORD_REV;
+ /* Set validation_bits using CPER_SEC_VALID_FRU_ID / CPER_SEC_VALID_FRU_TEXT
+ * when the corresponding fields are populated.
+ */
+ sdesc->validation_bits = 0;
+ sdesc->reserved = 0;
+ sdesc->flags = 0;
+ sdesc->section_type = INTEL_CPER_SECTION_ACCEL_GENERIC;
+ if (fru_id && !guid_is_null(fru_id)) {
+ sdesc->fru_id = *fru_id;
+ sdesc->validation_bits |= CPER_SEC_VALID_FRU_ID;
+ }
+ sdesc->section_severity = severity;
+
+ /* Copy the Intel-specific section header (updated with BDF/version) */
+ rec->intel_hdr = *ihdr;
+
+ /* Append optional variable-length error info */
+ if (einfo && einfo_size)
+ memcpy((u8 *)rec + sizeof(*rec), einfo, einfo_size);
+
+ trace_xe_error_cper(xe, platform_id, fru_id, severity,
+ &rec->intel_hdr, total_len, (u8 *)rec);
+
+ kfree(rec);
+}
diff --git a/drivers/gpu/drm/xe/xe_cper.h b/drivers/gpu/drm/xe/xe_cper.h
new file mode 100644
index 000000000000..7027e3f1be60
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_cper.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+#ifndef _XE_CPER_H_
+#define _XE_CPER_H_
+
+#include <linux/types.h>
+#include <linux/uuid.h>
+
+struct xe_cper_sec_intel_err_hdr;
+struct xe_device;
+
+void xe_cper_record_emit(struct xe_device *xe,
+ const guid_t *fru_id,
+ u8 severity,
+ guid_t notification_type,
+ struct xe_cper_sec_intel_err_hdr *ihdr,
+ const void *einfo,
+ u32 einfo_size);
+
+void xe_cper_init_intel_err_hdr(struct xe_device *xe,
+ const u8 location[12],
+ u64 first_timestamp,
+ u32 sig_id,
+ u64 error_count,
+ struct xe_cper_sec_intel_err_hdr *ihdr);
+
+#endif /* _XE_CPER_H_ */
--
2.54.0
next prev parent reply other threads:[~2026-07-02 11:03 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-02 11:14 [RFC PATCH 0/7] Add CPER logging support for CRI Badal Nilawar
2026-07-02 11:14 ` [RFC PATCH 1/7] drm/xe: Add error Signature IDs for RAS logging Badal Nilawar
2026-07-02 11:14 ` [RFC PATCH 2/7] drm/xe/xe_ras: Add support to retrieve info queue data for CRI Badal Nilawar
2026-07-07 12:29 ` Mallesh, Koujalagi
2026-07-02 11:14 ` [RFC PATCH 3/7] drm/xe/xe_ras: Refactor get_counter() to return response structure Badal Nilawar
2026-07-03 7:41 ` Tauro, Riana
2026-07-07 12:53 ` Mallesh, Koujalagi
2026-07-02 11:14 ` [RFC PATCH 4/7] drm/xe/cper: Add CPER structures and trace event Badal Nilawar
2026-07-02 11:14 ` Badal Nilawar [this message]
2026-07-02 11:14 ` [RFC PATCH 6/7] drm/xe/cper: Prepare Intel CPER error info from info queue Badal Nilawar
2026-07-02 11:14 ` [RFC PATCH 7/7] drm/xe/cper: Log CPER record for correctable errors Badal Nilawar
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=20260702111401.3680214-14-badal.nilawar@intel.com \
--to=badal.nilawar@intel.com \
--cc=anshuman.gupta@intel.com \
--cc=aravind.iddamsetty@intel.com \
--cc=daniele.ceraolospurio@intel.com \
--cc=intel-xe@lists.freedesktop.org \
--cc=mallesh.koujalagi@intel.com \
--cc=raag.jadav@intel.com \
--cc=riana.tauro@intel.com \
--cc=rodrigo.vivi@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