[PATCH 2/2] drm/xe/guc: Add support for NPK as a GuC log target
John.C.Harrison at Intel.com
John.C.Harrison at Intel.com
Wed Jul 23 21:20:20 UTC 2025
From: John Harrison <John.C.Harrison at Intel.com>
The GuC has an option to write log data via NPK. This is basically a
magic IO address that GuC writes arbitrary data to and which can be
logged by a suitable hardware logger. This can allow retrieval of the
GuC log in hardware debug environments even when the system as a whole
dies horribly.
Signed-off-by: John Harrison <John.C.Harrison at Intel.com>
---
drivers/gpu/drm/xe/xe_configfs.c | 61 ++++++++++++++++++++++++++++++++
drivers/gpu/drm/xe/xe_configfs.h | 3 ++
drivers/gpu/drm/xe/xe_guc.c | 5 +++
3 files changed, 69 insertions(+)
diff --git a/drivers/gpu/drm/xe/xe_configfs.c b/drivers/gpu/drm/xe/xe_configfs.c
index 8ec1ff1e4e80..9fbd7e2ab152 100644
--- a/drivers/gpu/drm/xe/xe_configfs.c
+++ b/drivers/gpu/drm/xe/xe_configfs.c
@@ -77,6 +77,17 @@
* available for migrations, but it's disabled. This is intended for debugging
* purposes only.
*
+ * GuC log target:
+ * ---------------
+ *
+ * Specify the target for GuC firmware logging:
+ * 0 = memory
+ * 1 = NPK
+ * 2 = memory + NPK
+ *
+ * Note that logging via NPK (North Peak) is only useful if some kind of hardware
+ * debugger is attached that can save out the NPK stream externally.
+ *
* Remove devices
* ==============
*
@@ -90,6 +101,7 @@ struct xe_config_device {
bool survivability_mode;
u64 engines_allowed;
+ u32 guc_log_target;
/* protects attributes */
struct mutex lock;
@@ -226,12 +238,38 @@ static ssize_t engines_allowed_store(struct config_item *item, const char *page,
return len;
}
+static ssize_t guc_log_target_show(struct config_item *item, char *page)
+{
+ struct xe_config_device *dev = to_xe_config_device(item);
+
+ return sprintf(page, "%d\n", dev->guc_log_target);
+}
+
+static ssize_t guc_log_target_store(struct config_item *item, const char *page, size_t len)
+{
+ struct xe_config_device *dev = to_xe_config_device(item);
+ u32 guc_log_target;
+ int ret;
+
+ ret = kstrtou32(page, 0, &guc_log_target);
+ if (ret)
+ return ret;
+
+ mutex_lock(&dev->lock);
+ dev->guc_log_target = guc_log_target;
+ mutex_unlock(&dev->lock);
+
+ return len;
+}
+
CONFIGFS_ATTR(, survivability_mode);
CONFIGFS_ATTR(, engines_allowed);
+CONFIGFS_ATTR(, guc_log_target);
static struct configfs_attribute *xe_config_device_attrs[] = {
&attr_survivability_mode,
&attr_engines_allowed,
+ &attr_guc_log_target,
NULL,
};
@@ -386,6 +424,29 @@ u64 xe_configfs_get_engines_allowed(struct pci_dev *pdev)
return engines_allowed;
}
+/**
+ * xe_configfs_get_guc_log_target - get configfs GuC log target attribute
+ * @pdev: pci device
+ *
+ * find the configfs group that belongs to the pci device and return
+ * the GuC log target attribute
+ *
+ * Return: GuC log target if config group is found, false otherwise
+ */
+u32 xe_configfs_get_guc_log_target(struct pci_dev *pdev)
+{
+ struct xe_config_device *dev = configfs_find_group(pdev);
+ u32 guc_log_target;
+
+ if (!dev)
+ return false;
+
+ guc_log_target = dev->guc_log_target;
+ config_item_put(&dev->group.cg_item);
+
+ return guc_log_target;
+}
+
int __init xe_configfs_init(void)
{
struct config_group *root = &xe_configfs.su_group;
diff --git a/drivers/gpu/drm/xe/xe_configfs.h b/drivers/gpu/drm/xe/xe_configfs.h
index fb8764008089..97f9ad0f9495 100644
--- a/drivers/gpu/drm/xe/xe_configfs.h
+++ b/drivers/gpu/drm/xe/xe_configfs.h
@@ -16,12 +16,15 @@ void xe_configfs_exit(void);
bool xe_configfs_get_survivability_mode(struct pci_dev *pdev);
void xe_configfs_clear_survivability_mode(struct pci_dev *pdev);
u64 xe_configfs_get_engines_allowed(struct pci_dev *pdev);
+u32 xe_configfs_get_guc_log_target(struct pci_dev *pdev);
#else
static inline int xe_configfs_init(void) { return 0; }
static inline void xe_configfs_exit(void) { }
static inline bool xe_configfs_get_survivability_mode(struct pci_dev *pdev) { return false; }
static inline void xe_configfs_clear_survivability_mode(struct pci_dev *pdev) { }
static inline u64 xe_configfs_get_engines_allowed(struct pci_dev *pdev) { return U64_MAX; }
+static inline u32 xe_configfs_get_guc_log_target(struct pci_dev *pdev) { return 0; }
+
#endif
#endif
diff --git a/drivers/gpu/drm/xe/xe_guc.c b/drivers/gpu/drm/xe/xe_guc.c
index 8fac3c518975..53ef93e162d2 100644
--- a/drivers/gpu/drm/xe/xe_guc.c
+++ b/drivers/gpu/drm/xe/xe_guc.c
@@ -16,6 +16,7 @@
#include "regs/xe_guc_regs.h"
#include "regs/xe_irq_regs.h"
#include "xe_bo.h"
+#include "xe_configfs.h"
#include "xe_device.h"
#include "xe_force_wake.h"
#include "xe_gt.h"
@@ -67,6 +68,7 @@ static u32 guc_bo_ggtt_addr(struct xe_guc *guc,
static u32 guc_ctl_debug_flags(struct xe_guc *guc)
{
+ u32 target = xe_configfs_get_guc_log_target(to_pci_dev(guc_to_xe(guc)->drm.dev));
u32 level = xe_guc_log_get_level(&guc->log);
u32 flags = 0;
@@ -75,6 +77,9 @@ static u32 guc_ctl_debug_flags(struct xe_guc *guc)
else
flags |= FIELD_PREP(GUC_LOG_VERBOSITY, GUC_LOG_LEVEL_TO_VERBOSITY(level));
+ if (target)
+ flags |= FIELD_PREP(GUC_LOG_DESTINATION, target);
+
return flags;
}
--
2.49.0
More information about the Intel-xe
mailing list