Re: [PATCH v3 02/23] drm/xe/log: Add structured SIGID error logging infrastructure

Rodrigo Vivi <[email protected]> Tue, 4 Aug 2026 21:39:22 -0400
Newsgroups org.freedesktop.lists.intel-xe
Message-ID <[email protected]>
On Tue, Aug 04, 2026 at 05:22:29PM -0400, Summers, Stuart wrote:
> On Tue, 2026-08-04 at 21:21 +0000, Summers, Stuart wrote:
> > On Thu, 2026-07-30 at 17:20 +0200, Michal Wajdeczko wrote:
> > > From: Mallesh Koujalagi <[email protected]>
> > > 
> > > Today the driver reports faults with ad-hoc drm_err()/xe_gt_err()
> > > strings that have no stable shape. That is readable for a human,
> > > but
> > > it
> > > gives fleet tooling nothing durable to match on: the wording
> > > changes
> > > between releases, lines can be rate-limited or dropped under an
> > > error
> > > storm, and there is no consistent way to ask "which recognised
> > > fault
> > > just happened?".
> > > 
> > > Introduce a signature identifier (SIGID): a small, stable integer
> > > that
> > > names one recognised Xe fault situation and serves as the primary
> > > handle
> > > for triage. A SIGID maps, through published end-user documentation,
> > > to a
> > > description and a recommended action; the driver only has to emit
> > > the
> > > right SIGID next to the usual human-readable text.
> > 
> > I'm a little worried we're introducing some ABI with this that isn't
> > really maintainable in the long term: we might decide to change the
> > flow or change the way an error is reported or the situation that
> > triggers this error from firmware or hardware might change for some
> > reason. Does this lock us into a solution for all of this? I still
> > need
> > to go through the full patch series...
> > 
> > The dmesg entries are generally for human debuggability. I get the
> > desire to make these easier to parse for an AI tool or generated
> > script, but we also don't want to prevent debug related changes for
> > error handling and reporting.
> 
> Also, should we be implementing something like this more generically
> across DRM or even outside of DRM and then having device-specific error
> conditions within a particular range?

I doubt that this will be useful outside of our Intel GPU.
Also, other subsystem and drivers have different needs for this
problem and no good broad idea.

Take a look to the cases Jani pointed out:
https://lore.kernel.org/intel-xe/[email protected]/

> 
> Thanks,
> Stuart
> 
> > 
> > Thanks,
> > Stuart
> > 
> > > 
> > > Signed-off-by: Mallesh Koujalagi <[email protected]>
> > > Assisted-by: Copilot:Opus-4.8
> > > Signed-off-by: Rodrigo Vivi <[email protected]>
> > > Co-developed-by: Michal Wajdeczko <[email protected]>
> > > Signed-off-by: Michal Wajdeczko <[email protected]>
> > > ---
> > > Cc: Yoni Levitt <[email protected]>
> > > Cc: Aravind Iddamsetty <[email protected]>
> > > Cc: Raag Jadav <[email protected]>
> > > Cc: Riana Tauro <[email protected]>
> > > ---
> > > v2: CORRECTED is still an error (Michal)
> > >     prepare to decorate dmesg with comp/loc (Michal)
> > > ---
> > >  Documentation/gpu/xe/index.rst        |   1 +
> > >  Documentation/gpu/xe/xe_sigid.rst     |  14 ++
> > >  drivers/gpu/drm/xe/Makefile           |   1 +
> > >  drivers/gpu/drm/xe/abi/xe_sigid_abi.h | 183
> > > ++++++++++++++++++++++++++
> > >  drivers/gpu/drm/xe/xe_log.c           | 135 +++++++++++++++++++
> > >  drivers/gpu/drm/xe/xe_log.h           |  20 +++
> > >  6 files changed, 354 insertions(+)
> > >  create mode 100644 Documentation/gpu/xe/xe_sigid.rst
> > >  create mode 100644 drivers/gpu/drm/xe/abi/xe_sigid_abi.h
> > >  create mode 100644 drivers/gpu/drm/xe/xe_log.c
> > >  create mode 100644 drivers/gpu/drm/xe/xe_log.h
> > > 
> > > diff --git a/Documentation/gpu/xe/index.rst
> > > b/Documentation/gpu/xe/index.rst
> > > index 665c0e93601c..0247a255f7e6 100644
> > > --- a/Documentation/gpu/xe/index.rst
> > > +++ b/Documentation/gpu/xe/index.rst
> > > @@ -35,3 +35,4 @@ The display, or :ref:`drm-kms`, support for
> > > drm/xe
> > > is provided by
> > >     xe-drm-usage-stats.rst
> > >     xe_configfs
> > >     xe_gt_stats
> > > +   xe_sigid
> > > diff --git a/Documentation/gpu/xe/xe_sigid.rst
> > > b/Documentation/gpu/xe/xe_sigid.rst
> > > new file mode 100644
> > > index 000000000000..45d84a62f185
> > > --- /dev/null
> > > +++ b/Documentation/gpu/xe/xe_sigid.rst
> > > @@ -0,0 +1,14 @@
> > > +.. SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> > > +
> > > +========
> > > +Xe SIGID
> > > +========
> > > +
> > > +.. kernel-doc:: drivers/gpu/drm/xe/abi/xe_sigid_abi.h
> > > +   :doc: Xe Error Signatures (SIGID)
> > > +
> > > +Signature Identifiers
> > > +=====================
> > > +
> > > +.. kernel-doc:: drivers/gpu/drm/xe/abi/xe_sigid_abi.h
> > > +   :internal:
> > > diff --git a/drivers/gpu/drm/xe/Makefile
> > > b/drivers/gpu/drm/xe/Makefile
> > > index 67ada1d6c2fb..7ac3954737f9 100644
> > > --- a/drivers/gpu/drm/xe/Makefile
> > > +++ b/drivers/gpu/drm/xe/Makefile
> > > @@ -87,6 +87,7 @@ xe-y += xe_bb.o \
> > >         xe_hw_fence.o \
> > >         xe_irq.o \
> > >         xe_late_bind_fw.o \
> > > +       xe_log.o \
> > >         xe_lrc.o \
> > >         xe_mem_pool.o \
> > >         xe_migrate.o \
> > > diff --git a/drivers/gpu/drm/xe/abi/xe_sigid_abi.h
> > > b/drivers/gpu/drm/xe/abi/xe_sigid_abi.h
> > > new file mode 100644
> > > index 000000000000..99717fdf74a6
> > > --- /dev/null
> > > +++ b/drivers/gpu/drm/xe/abi/xe_sigid_abi.h
> > > @@ -0,0 +1,183 @@
> > > +/* SPDX-License-Identifier: MIT */
> > > +/*
> > > + * Copyright © 2026 Intel Corporation
> > > + */
> > > +
> > > +#ifndef _ABI_XE_SIGID_ABI_H_
> > > +#define _ABI_XE_SIGID_ABI_H_
> > > +
> > > +/**
> > > + * DOC: Xe Error Signatures (SIGID)
> > > + *
> > > + * What SIGID stands for
> > > + * ---------------------
> > > + *
> > > + * SIGID is short for *Signature Identifier*. A SIGID is a small,
> > > stable integer
> > > + * that names one *recognised Xe fault situation* -- nothing more.
> > > It is the
> > > + * primary handle used for triage: a SIGID maps to a human
> > > description and a
> > > + * recommended first action. A coarse first-order action is
> > > documented in-tree
> > > + * per SIGID (see "First-order action" below) so the id is
> > > actionable on its
> > > + * own; published end-user documentation refines it with finer,
> > > cross-product
> > > + * detail. The driver's only job is to emit the right SIGID next
> > > to
> > > the usual
> > > + * human-readable text.
> > > + *
> > > + * Why this exists
> > > + * ---------------
> > > + *
> > > + * Today the driver reports faults with ad-hoc ``drm_err()`` /
> > > ``xe_gt_err()``
> > > + * strings that have no stable shape. That is fine for a human
> > > reading dmesg,
> > > + * but it gives fleet tooling nothing durable to match on: the
> > > wording changes
> > > + * between releases, lines can be rate-limited or dropped under an
> > > error storm,
> > > + * and there is no consistent way to ask "which recognised fault
> > > just happened?"
> > > + * A SIGID answers exactly that one question, identically across
> > > driver and
> > > + * firmware versions, and (eventually) across other Intel devices
> > > in
> > > a node.
> > > + *
> > > + * What a SIGID is (and is not)
> > > + * ----------------------------
> > > + *
> > > + * A SIGID names *which situation* is being reported. It
> > > deliberately does not
> > > + * encode the detailed reason or the outcome. Those are carried
> > > alongside it::
> > > + *
> > > + *   SIGID    -> which recognised situation is being reported
> > > + *   severity -> how serious this instance is (see below -- not
> > > fixed per SIGID)
> > > + *   errno    -> the failing operation's error, shown with %pe
> > > + *   message  -> free-form human-readable context
> > > + *
> > > + * Severity is independent of the SIGID. The same situation can be
> > > reported at
> > > + * different severities depending on the instance and the recovery
> > > taken, so a
> > > + * SIGID is never tied to one severity; the reporting site chooses
> > > it by calling
> > > + * the matching xe_log_*() helper (see xe_log.h).
> > > + *
> > > + * How to pick a SIGID (the uniqueness rule)
> > > + * -----------------------------------------
> > > + *
> > > + * Pick per *report site*, not per incident. Each site emits the
> > > single most
> > > + * specific recognised situation *for that site* -- so the
> > > question
> > > is never
> > > + * "classify this whole failure", it is "what does this site
> > > detect?", which has
> > > + * one answer. A single underlying failure therefore legitimately
> > > produces a
> > > + * *chain* of reports from different layers, each with its own
> > > SIGID
> > > -- e.g. a
> > > + * GuC communication failure is reported as %XE_SIGID_RUNTIME_FW
> > > by
> > > the firmware
> > > + * path, the failed recovery as %XE_SIGID_GT_TDR by the reset
> > > path,
> > > and an
> > > + * aborted bind as %XE_SIGID_PROBE by the probe path. That chain
> > > lets triage
> > > + * follow a fault from origin to final effect; it is not a
> > > duplicate.
> > > + *
> > > + * If a site does not match any defined situation, keep using the
> > > ordinary
> > > + * ``xe_err()`` / ``xe_gt_err()`` logging rather than forcing a
> > > SIGID: a wrong
> > > + * or over-broad classification is harder to retire than a missing
> > > one. When a
> > > + * new situation is genuinely worth triaging, add it to the list
> > > below.
> > > + *
> > > + * Scope: software-emitted signatures only
> > > + * ---------------------------------------
> > > + *
> > > + * This header enumerates only the situations that the *driver
> > > itself* detects
> > > + * and reports from software: probe abort, wedged, survivability,
> > > driver-
> > > + * detected firmware failures, engine TDR, memory faults and
> > > IO/bus
> > > faults.
> > > + * These are the only values the driver assigns.
> > > + *
> > > + * Signatures that *originate* in firmware or hardware are a
> > > different thing:
> > > + * they are produced and identified by the firmware or the
> > > hardware
> > > itself
> > > + * (e.g. via their own records or error counters), and the driver
> > > merely logs
> > > + * them as they are given to us. They are deliberately *not*
> > > enumerated here --
> > > + * minting a driver-side id for a firmware/hardware-reported error
> > > would only
> > > + * duplicate an identifier the reporting layer already owns. The
> > > two
> > > + * driver-detected firmware situations below
> > > (%XE_SIGID_RUNTIME_FW,
> > > + * %XE_SIGID_DEVICE_FW) are software signatures: they mark that
> > > *the
> > > driver*
> > > + * observed a firmware problem, not a signature reported by the
> > > firmware.
> > > + *
> > > + * Numbering
> > > + * ---------
> > > + *
> > > + * SIGIDs are a single flat list numbered sequentially within the
> > > assigned range,
> > > + * in the order the situations were introduced. Values are stable:
> > > once assigned
> > > + * they are only ever appended, never renumbered or reused.
> > > + *
> > > + * A retired situation is deprecated in place, never re-purposed.
> > > + *
> > > + * First-order action (resolution buckets)
> > > + * ---------------------------------------
> > > + *
> > > + * So that a SIGID is actionable on its own, each one is tagged
> > > with
> > > a coarse
> > > + * *resolution bucket*: the first thing an operator should do on
> > > seeing it. The
> > > + * bucket is a stable, driver-owned hint; external documentation
> > > may
> > > refine it,
> > > + * but the in-tree value always stands on its own. Every new SIGID
> > > must pick a
> > > + * bucket, which forces the question "what should someone do about
> > > this?" to be
> > > + * answered up front. The buckets are::
> > > + *
> > > + *   COLLECT  -- capture logs and open a bug report
> > > + *   RETRY    -- transient or already recovered; watch for
> > > recurrence
> > > + *   UPDATE   -- a firmware update / flash is required
> > > + *   RECOVER  -- an explicit recovery step is needed (rebind, bus
> > > reset)
> > > + *   IGNORE   -- ignore if the SIGID severity is INFORMATIONAL
> > > + *
> > > + * The bucket is documentation only -- it is recorded per SIGID in
> > > the enum
> > > + * kernel-doc below and is not printed on the (deliberately lean)
> > > dmesg line.
> > > + *
> > > + * When to use SIGID logging
> > > + * -------------------------
> > > + *
> > > + * The xe_log_*() helpers are for these recognised fault
> > > situations
> > > only --
> > > + * important, operator-relevant faults and events. They are not a
> > > replacement
> > > + * for ``xe_info()`` / ``xe_dbg()`` / tracing, nor for one-off
> > > diagnostics;
> > > + * using them for ordinary logging would dilute the fault stream.
> > > Not every
> > > + * ``xe_err()`` needs to become a SIGID report -- only those that
> > > correspond to
> > > + * a published situation.
> > > + *
> > > + * dmesg vs. the machine record
> > > + * ----------------------------
> > > + *
> > > + * The dmesg line stays close to a normal xe error message so it
> > > remains
> > > + * readable for admins; the only stable, machine-matchable token
> > > on
> > > it is
> > > + * ``SIGID=<n>`` (``dmesg | grep SIGID=``). dmesg is not an ABI:
> > > the
> > > surrounding
> > > + * text may change freely, and lines may be dropped. The durable
> > > record for
> > > + * tooling is the CPER record carrying the same SIGID (generation
> > > is
> > > a planned
> > > + * follow-up).
> > > + */
> > > +
> > > +/*
> > > + * Top level Intel Error Signature Identifiers.
> > > + */
> > > +#define INTEL_SIGID_INVALID                    0
> > > +#define INTEL_SIGID_GPU_START                  100
> > > +#define INTEL_SIGID_GPU_END                    999
> > > +
> > > +#define INTEL_SIGID_GPU_XE_START               100
> > > +#define INTEL_SIGID_GPU_XE_END                 299
> > > +
> > > +#define INTEL_SIGID_GPU_XE_SOFTWARE_START      100
> > > +#define INTEL_SIGID_GPU_XE_SOFTWARE_END                199
> > > +#define INTEL_SIGID_GPU_XE_HARDWARE_START      200
> > > +#define INTEL_SIGID_GPU_XE_HARDWARE_END                299
> > > +
> > > +/**
> > > + * enum xe_sigid - Stable Xe Error Signature Identifiers (SIGID).
> > > + * @XE_SIGID_SW: Software component failure. [COLLECT]
> > > + * @XE_SIGID_PROBE: Device probe/bind was aborted. [COLLECT]
> > > + * @XE_SIGID_WEDGED: Device was declared wedged and is no longer
> > > usable. [RECOVER]
> > > + * @XE_SIGID_SURVIVABILITY: Device entered survivability mode.
> > > [UPDATE]
> > > + * @XE_SIGID_RUNTIME_FW: Driver-detected runtime firmware failure,
> > > GuC/HuC/GSC. [RETRY]
> > > + * @XE_SIGID_DEVICE_FW: Driver-detected device firmware failure,
> > > PCODE/sysctrl. [RETRY]
> > > + * @XE_SIGID_GT_TDR: Engine hang / timeout detection and recovery
> > > (reset). [RETRY]
> > > + * @XE_SIGID_MEM_FAULT: VM bind, page fault or GTT fault.
> > > [COLLECT]
> > > + * @XE_SIGID_IO_BUS: Runtime PCIe / IOMMU / MMIO access fault.
> > > [RECOVER]
> > > + *
> > > + * The situations the driver detects and reports in software.
> > > Values
> > > are
> > > + * numbered sequentially, are only ever appended, and are never
> > > renumbered or
> > > + * reused. The tag in brackets is the default resolution bucket
> > > (see
> > > the `Xe
> > > + * Error Signatures (SIGID)`_ section).
> > > + *
> > > + * Firmware- and hardware-originated signatures are not listed
> > > here;
> > > they are
> > > + * logged as reported by those layers.
> > > + */
> > > +enum xe_sigid {
> > > +       XE_SIGID_SW                     =
> > > INTEL_SIGID_GPU_XE_SOFTWARE_START,
> > > +       XE_SIGID_PROBE                  =
> > > INTEL_SIGID_GPU_XE_SOFTWARE_START + 1,
> > > +       XE_SIGID_WEDGED                 =
> > > INTEL_SIGID_GPU_XE_SOFTWARE_START + 2,
> > > +       XE_SIGID_SURVIVABILITY          =
> > > INTEL_SIGID_GPU_XE_SOFTWARE_START + 3,
> > > +       XE_SIGID_RUNTIME_FW             =
> > > INTEL_SIGID_GPU_XE_SOFTWARE_START + 4,
> > > +       XE_SIGID_DEVICE_FW              =
> > > INTEL_SIGID_GPU_XE_SOFTWARE_START + 5,
> > > +       XE_SIGID_GT_TDR                 =
> > > INTEL_SIGID_GPU_XE_SOFTWARE_START + 6,
> > > +       XE_SIGID_MEM_FAULT              =
> > > INTEL_SIGID_GPU_XE_SOFTWARE_START + 7,
> > > +       XE_SIGID_IO_BUS                 =
> > > INTEL_SIGID_GPU_XE_SOFTWARE_START + 8,
> > > +};
> > > +
> > > +#endif
> > > diff --git a/drivers/gpu/drm/xe/xe_log.c
> > > b/drivers/gpu/drm/xe/xe_log.c
> > > new file mode 100644
> > > index 000000000000..70a41bdf1a01
> > > --- /dev/null
> > > +++ b/drivers/gpu/drm/xe/xe_log.c
> > > @@ -0,0 +1,135 @@
> > > +// SPDX-License-Identifier: MIT
> > > +/*
> > > + * Copyright © 2026 Intel Corporation
> > > + */
> > > +
> > > +#include "xe_log.h"
> > > +#include "xe_printk.h"
> > > +
> > > +static void log_emit_cper(struct pci_dev *pdev, int cper_sev, enum
> > > xe_sigid sigid,
> > > +                         u32 component, u32 location, const void
> > > *data, size_t len,
> > > +                         struct va_format *vaf)
> > > +{
> > > +       /* TODO */
> > > +}
> > > +
> > > +static bool is_hw_sigid(enum xe_sigid sigid)
> > > +{
> > > +       return (int)sigid >= INTEL_SIGID_GPU_XE_HARDWARE_START;
> > > +}
> > > +
> > > +static bool is_sev_error(int cper_sev)
> > > +{
> > > +       return cper_sev != CPER_SEV_INFORMATIONAL;
> > > +}
> > > +
> > > +static const char *log_hwe_prefix(int cper_sev, enum xe_sigid
> > > sigid)
> > > +{
> > > +       return is_sev_error(cper_sev) && is_hw_sigid(sigid) ?
> > > HW_ERR
> > > : "";
> > > +}
> > > +
> > > +static const char *log_sev_prefix(int cper_sev)
> > > +{
> > > +       switch (cper_sev) {
> > > +       case CPER_SEV_FATAL:
> > > +               return "FATAL ";
> > > +       case CPER_SEV_RECOVERABLE:
> > > +               return "";
> > > +       case CPER_SEV_CORRECTED:
> > > +               return "CORRECTED ";
> > > +       default:
> > > +               return "";
> > > +       }
> > > +}
> > > +
> > > +#define __LOG_DRM_PRINTK_FMT(fmt, args...)     "[drm] " fmt,
> > > ##args
> > > +#define __LOG_DRM_PRINTK_ERR_FMT(fmt,
> > > args...) __LOG_DRM_PRINTK_FMT("*ERROR* " fmt, args)
> > > +
> > > +static void log_dmesg_vprintk(struct pci_dev *pdev, int cper_sev,
> > > struct va_format *vaf)
> > > +{
> > > +       if (cper_sev == CPER_SEV_INFORMATIONAL)
> > > +               pci_info(pdev, __LOG_DRM_PRINTK_FMT("%pV", vaf));
> > > +       else
> > > +               pci_err(pdev, __LOG_DRM_PRINTK_ERR_FMT("%pV",
> > > vaf));
> > > +}
> > > +
> > > +static void log_dmesg_printf(struct pci_dev *pdev, int cper_sev,
> > > const char *fmt, ...)
> > > +{
> > > +       struct va_format vaf;
> > > +       va_list args;
> > > +
> > > +       va_start(args, fmt);
> > > +       vaf.fmt = fmt;
> > > +       vaf.va = &args;
> > > +
> > > +       log_dmesg_vprintk(pdev, cper_sev, &vaf);
> > > +
> > > +       va_end(args);
> > > +}
> > > +
> > > +static void log_emit_dmesg(struct pci_dev *pdev, int cper_sev,
> > > enum
> > > xe_sigid sigid,
> > > +                          u32 component, u32 location, const void
> > > *data, size_t len,
> > > +                          struct va_format *vaf)
> > > +{
> > > +       const char *hwe_prefix = log_hwe_prefix(cper_sev, sigid);
> > > +       const char *sev_prefix = log_sev_prefix(cper_sev);
> > > +
> > > +       /* TODO: add component/location details */
> > > +
> > > +       if (IS_ERR(data))
> > > +               log_dmesg_printf(pdev, cper_sev, "SIGID=%u %s(%pe)
> > > %s%pV",
> > > +                                sigid, sev_prefix, data,
> > > hwe_prefix,
> > > vaf);
> > > +       else if (data && len)
> > > +               log_dmesg_printf(pdev, cper_sev, "SIGID=%u
> > > %s(%*phN)
> > > %s%pV",
> > > +                                sigid, sev_prefix, (int)len, data,
> > > hwe_prefix, vaf);
> > > +       else
> > > +               log_dmesg_printf(pdev, cper_sev, "SIGID=%u
> > > %s%s%pV",
> > > +                                sigid, sev_prefix, hwe_prefix,
> > > vaf);
> > > +}
> > > +
> > > +/**
> > > + * xe_log_emit() - Emit a structured SIGID log entry
> > > + * @pdev: the &pci_dev device
> > > + * @cper_sev: CPER severity (CPER_SEV_FATAL, CPER_SEV_RECOVERABLE,
> > > ...)
> > > + * @sigid: signature identifier, see &enum xe_sigid
> > > + * @component: component identifer
> > > + * @location: location details of the @component
> > > + * @data: pointer to the additional details, or ERR_PTR, or NULL
> > > if
> > > not applicable
> > > + * @len: length of the @data in bytes, or 0 if not applicable
> > > + * @fmt: printf-style format string
> > > + * @...: format arguments
> > > + *
> > > + * Emits a dmesg line that includes a single stable, machine-
> > > matchable token
> > > + * ``SIGID=<n>`` followed by the optional severity token (like
> > > ``FATAL``) and,
> > > + * when @data pointer is set, either the error printed with %pe or
> > > a
> > > packed hex
> > > + * dump of the @data binary blob. The dmesg line will also include
> > > printf-style
> > > + * text message.
> > > + *
> > > + * Note that the full dmesg line, with the free text message, is
> > > only a debugging
> > > + * aid, not an interface! Only the ``SIGID=<n>`` token is stable
> > > there.
> > > + * The durable machine record is the CPER carrying the same SIGID.
> > > + *
> > > + * Note: generation of the CPER record is a planned follow-up.
> > > + *
> > > + * Examples::
> > > + *
> > > + *   <3> xe 0000:03:00.0: [drm] *ERROR* SIGID=104 FATAL (-EPROTO)
> > > Invalid GuC reply
> > > + *   <3> xe 0000:03:00.0: [drm] *ERROR* SIGID=106 (-ETIMEDOUT)
> > > Engine 'rcs0' hung
> > > + *   <6> xe 0000:03:00.0: [drm] *ERROR* SIGID=103 In survivability
> > > mode
> > > + */
> > > +void xe_log_emit(struct pci_dev *pdev, int cper_sev, enum xe_sigid
> > > sigid,
> > > +                u32 component, u32 location, const void *data,
> > > size_t len,
> > > +                const char *fmt, ...)
> > > +{
> > > +       struct va_format vaf;
> > > +       va_list args;
> > > +
> > > +       va_start(args, fmt);
> > > +       vaf.fmt = fmt;
> > > +       vaf.va = &args;
> > > +
> > > +       log_emit_dmesg(pdev, cper_sev, sigid, component, location,
> > > data, len, &vaf);
> > > +       log_emit_cper(pdev, cper_sev, sigid, component, location,
> > > data, len, &vaf);
> > > +
> > > +       va_end(args);
> > > +}
> > > diff --git a/drivers/gpu/drm/xe/xe_log.h
> > > b/drivers/gpu/drm/xe/xe_log.h
> > > new file mode 100644
> > > index 000000000000..d475e816ee0b
> > > --- /dev/null
> > > +++ b/drivers/gpu/drm/xe/xe_log.h
> > > @@ -0,0 +1,20 @@
> > > +/* SPDX-License-Identifier: MIT */
> > > +/*
> > > + * Copyright © 2026 Intel Corporation
> > > + */
> > > +
> > > +#ifndef _XE_LOG_H_
> > > +#define _XE_LOG_H_
> > > +
> > > +#include <linux/cper.h>
> > > +
> > > +#include "abi/xe_sigid_abi.h"
> > > +
> > > +struct pci_dev;
> > > +
> > > +__printf(8, 9)
> > > +void xe_log_emit(struct pci_dev *pdev, int cper_sev, enum xe_sigid
> > > sigid,
> > > +                u32 component, u32 location, const void *data,
> > > size_t len,
> > > +                const char *fmt, ...);
> > > +
> > > +#endif
> > 
>