[PATCH v6 2/6] drm/xe/guc: Add LFD related abi definitions
John Harrison
john.c.harrison at intel.com
Tue Jul 29 19:08:28 UTC 2025
On 7/21/2025 6:35 PM, Zhanjun Dong wrote:
> Add GuC LFD (Log Format Descriptors) related ABI definitions.
>
> Signed-off-by: Zhanjun Dong <zhanjun.dong at intel.com>
> ---
> drivers/gpu/drm/xe/abi/guc_lfd_abi.h | 282 +++++++++++++++++++++++++++
> 1 file changed, 282 insertions(+)
> create mode 100644 drivers/gpu/drm/xe/abi/guc_lfd_abi.h
>
> diff --git a/drivers/gpu/drm/xe/abi/guc_lfd_abi.h b/drivers/gpu/drm/xe/abi/guc_lfd_abi.h
> new file mode 100644
> index 000000000000..b6888ab47e25
> --- /dev/null
> +++ b/drivers/gpu/drm/xe/abi/guc_lfd_abi.h
> @@ -0,0 +1,282 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2025 Intel Corporation
> + */
> +
> +#ifndef _ABI_GUC_LFD_ABI_H_
> +#define _ABI_GUC_LFD_ABI_H_
> +
> +#include <linux/types.h>
> +
> +#include "guc_lic_abi.h"
> +
> +/* Magic keys define */
> +#define GUC_LFD_DRIVER_KEY_STREAMING 0x8086AAAA474C5346
> +#define GUC_LFD_LOG_BUFFER_MARKER_2 0xDEADFEED
> +#define GUC_LFD_CRASH_DUMP_BUFFER_MARKER_2 0x8086DEAD
> +#define GUC_LFD_STATE_CAPTURE_BUFFER_MARKER_2 0xBEEFFEED
> +#define GUC_LFD_LOG_BUFFER_MARKER_1V2 0xCABBA9E6
> +#define GUC_LFD_STATE_CAPTURE_BUFFER_MARKER_1V2 0xCABBA9F7
> +#define GUC_LFD_DATA_HEADER_MAGIC 0x8086
These are not LFD defines. They are the in-memory buffer header magic words.
> +
> +/* The current major version of GuC-Log-File format. */
> +#define GUC_LFD_FORMAT_VERSION_MAJOR 0x0001
> +/* The current minor version of GuC-Log-File format. */
> +#define GUC_LFD_FORMAT_VERSION_MINOR 0x0000
> +
> +/** enum guc_lfd_type - Log format descriptor type */
> +enum guc_lfd_type {
> + /**
> + * @GUC_LFD_TYPE_FW_REQUIRED_RANGE_START: Start of range for
> + * required LFDs from GuC
> + */
> + GUC_LFD_TYPE_FW_REQUIRED_RANGE_START = 0x1,
> + /**
> + * @GUC_LFD_TYPE_FW_VERSION: GuC Firmware Version structure. LFDs
> + * payload is guc_lfd_data_fw_version
> + */
> + GUC_LFD_TYPE_FW_VERSION = GUC_LIC_TYPE_GUC_SW_VERSION,
This equality is coincidental not a definition. Indeed, the original
spec had different numbering for the two enums. It only change to match
due to an implementation bug! So you should not define them as being
related and should not make any assumptions in the code about them being
related.
> + /**
> + * @GUC_LFD_TYPE_GUC_DEVICE_ID: GuC microcontroller device ID.
> + * LFDs payload is guc_lfd_data_guc_devid
> + */
> + GUC_LFD_TYPE_GUC_DEVICE_ID = GUC_LIC_TYPE_GUC_DEVICE_ID,
> + /**
> + * @GUC_LFD_TYPE_TSC_FREQUENCY: Frequency of GuC timestamps. LFDs
> + * payload is guc_lfd_data_tsc_freq
> + */
> + GUC_LFD_TYPE_TSC_FREQUENCY = GUC_LIC_TYPE_TSC_FREQUENCY,
> + /**
> + * @GUC_LFD_TYPE_GMD_ID: HW GMD ID. LFDs payload is
> + * guc_lfd_data_gmdid
> + */
> + GUC_LFD_TYPE_GMD_ID = GUC_LIC_TYPE_GMD_ID,
> + /**
> + * @GUC_LFD_TYPE_BUILD_PLATFORM_ID: GuC build platform ID. LFDs
> + * payload is guc_lfd_data_build_platformid
> + */
> + GUC_LFD_TYPE_BUILD_PLATFORM_ID = GUC_LIC_TYPE_BUILD_PLATFORM_ID,
> + /** @GUC_LFD_TYPE_FW_REQUIRED_RANGE_END: End of this range */
> + GUC_LFD_TYPE_FW_REQUIRED_RANGE_END = 0x1FFF,
> + /**
> + * @GUC_LFD_TYPE_FW_OPTIONAL_RANGE_START: Start of range for
> + * required LFDs from GuC
> + */
> + GUC_LFD_TYPE_FW_OPTIONAL_RANGE_START = 0x2000,
> + /**
> + * @GUC_LFD_TYPE_LOG_EVENTS_BUFFER: Log-event-entries buffer. LFDs
> + * payload is guc_lfd_data_log_events_buf
> + */
> + GUC_LFD_TYPE_LOG_EVENTS_BUFFER = 0x2000,
> + /**
> + * @GUC_LFD_TYPE_FW_CRASH_DUMP: GuC generated crash-dump blob.
> + * LFDs payload is guc_lfd_data_fw_crashdump
> + */
> + GUC_LFD_TYPE_FW_CRASH_DUMP = 0x2001,
> + /** @GUC_LFD_TYPE_FW_OPTIONAL_RANGE_END: End of this range */
> + GUC_LFD_TYPE_FW_OPTIONAL_RANGE_END = 0x3FFF,
> + /**
> + * @GUC_LFD_TYPE_KMD_REQUIRED_RANGE_START: Start of range for
> + * required KMD LFDs
> + */
> + GUC_LFD_TYPE_KMD_REQUIRED_RANGE_START = 0x4000,
> + /**
> + * @GUC_LFD_TYPE_OS_ID: An identifier for the OS. LFDs payload is
> + * guc_lfd_data_os_id
> + */
> + GUC_LFD_TYPE_OS_ID = 0x4000,
> + /** @GUC_LFD_TYPE_KMD_REQUIRED_RANGE_END: End of this range */
> + GUC_LFD_TYPE_KMD_REQUIRED_RANGE_END = 0x5FFF,
> + /**
> + * @GUC_LFD_TYPE_KMD_OPTIONAL_RANGE_START: Start of range for
> + * optional KMD LFDs
> + */
> + GUC_LFD_TYPE_KMD_OPTIONAL_RANGE_START = 0x6000,
> + /**
> + * @GUC_LFD_TYPE_BINARY_SCHEMA_FORMAT: Binary representation of
> + * GuC log-events schema. LFDs TLV payload is
> + * guc_lfd_data_binary_schema
> + */
> + GUC_LFD_TYPE_BINARY_SCHEMA_FORMAT = 0x6000,
> + /**
> + * @GUC_LFD_TYPE_HOST_COMMENT: ASCII string containing comments
> + * from the host/KMD. LFDs TLV payload is
> + * guc_lfd_data_host_comment
> + */
> + GUC_LFD_TYPE_HOST_COMMENT = 0x6001,
> + /** @GUC_LFD_TYPE_KMD_OPTIONAL_RANGE_END: End of this range */
> + GUC_LFD_TYPE_KMD_OPTIONAL_RANGE_END = 0x7FFF,
> + /** @GUC_LFD_TYPE_RESERVED_RANGE_START: Start of reserved range */
> + GUC_LFD_TYPE_RESERVED_RANGE_START = 0x8000,
> + /** @GUC_LFD_TYPE_RESERVED_RANGE_END: End of this range */
> + GUC_LFD_TYPE_RESERVED_RANGE_END = 0xFFFF,
> +};
Personally, I find the above impossible to read at a glance. The
comments add nothing - GUC_LFD_TYPE_KMD_REQUIRED_RANGE_START is
described as "Start of range for required KMD LFDs". Well, yeah, I can
get that from the name. I think this whole section would be much easier
to read if was just the enums:
+ GUC_LFD_TYPE_KMD_REQUIRED_RANGE_START = 0x4000,
+ GUC_LFD_TYPE_OS_ID = 0x4000,
+ GUC_LFD_TYPE_KMD_REQUIRED_RANGE_END = 0x5FFF,
The structure definitions and such for the individual entries can refer
back to the define they are associated with. But this section would be
more use if it is a simple list of enum values that is quick and easy to
scan through.
> +
> +/** enum guc_lfd_os_type - OS Type LFD-ID */
> +enum guc_lfd_os_type {
> + /** @GUC_LFD_OS_TYPE_OSID_WIN: Windows OS */
> + GUC_LFD_OS_TYPE_OSID_WIN = 0x1,
> + /** @GUC_LFD_OS_TYPE_OSID_LIN: Linux OS */
> + GUC_LFD_OS_TYPE_OSID_LIN = 0x2,
> + /** @GUC_LFD_OS_TYPE_OSID_VMW: VMWare OS */
> + GUC_LFD_OS_TYPE_OSID_VMW = 0x3,
> + /** @GUC_LFD_OS_TYPE_OSID_OTHER: Other */
> + GUC_LFD_OS_TYPE_OSID_OTHER = 0x4,
> +};
> +
> +/**
> + * struct guc_lfd_data - Log format descriptor (LFD).
> + * A type of KLV with custom field-sizes + magic numbers.
This description tells me nothing that I can't immediately see from
looking at the contents. Maybe just say "A generic header structure for
all LFD blocks".
> + */
> +struct guc_lfd_data {
> + /** @dw0: A 32 bits dword, contains multiple bit fields */
> + u32 dw0;
'header' would be better than 'dw0'.
> + /*
> + * Expected value: GUC_LFD_DATA_HEADER_MAGIC.
> + * Helpful in detecting file errors.
Why 'expected value'? Indeed, I don't think this comment is worth having
at all.
> + */
> +#define GUC_LFD_DATA_MAGIC GENMASK(15, 0)
Calling this 'DATA_MAGIC' implies it is related to the 'data' field
below. Assuming that 'dw0' is renamed to 'header' then this shld be
'GUC_LFD_HEADER_MAGIC'.
> + /*
> + * File descriptor type (the 'T' in TLV) is used to identify how
> + * to interpret `data` below. For the range of types, see
> + * guc_lfd_type
Again, this is a redundant comment. Also, the KMD uses KLV not TLV.
> + */
> +#define GUC_LFD_DATA_DESC_TYPE GENMASK(31, 16)
Again, GUC_LFD_HEADER_TYPE would be a better name.
> + /** @dw_size: Number of dwords the `data` field contains. */
> + u32 dw_size;
data_size
> + /** @data: Data defined by File descriptor type. */
Defined by GUC_LFD_HEADER_TYPE.
> + u32 data[] __counted_by(dw_size);
> +} __packed;
> +
> +/**
> + * struct guc_lfd_version - GuC Log File Format Version.
LFD is Log File Descriptor not Log File Format.
> + * Major-Minor is not a fractional number (i.e. Ver 1.3 would be older
> + * than 1.12)
> + */
> +struct guc_lfd_version {
> + /** @dw0: A 32 bits dword, contains multiple bit fields */
> + u32 dw0;
> + /*
> + * Guc-Log-File Format minor version. Must be
> + * GUC_LOG_FILE_FORMAT_VERSION_MINOR
> + */
> +#define GUC_LFD_VERSION_MINOR GENMASK(15, 0)
> + /*
> + * Guc-Log-File Format major version. Must be
> + * GUC_LOG_FILE_FORMAT_VERSION_MAJOR
> + */
> +#define GUC_LFD_VERSION_MAJOR GENMASK(31, 16)
> +} __packed;
Again, no point in having a structure defined for a single u32. Just the
bit field definitions is all we need.
> +
> +/**
> + * struct guc_lfd_data_guc_devid - GuC Device ID.
> + * This is mandatory fw LFD data
"fw" meaning firmware? But this is the LFD as created entirely by the
KMD, the firmware is not involved. Should just say "This is a mandatory
LFD block."
> + */
> +struct guc_lfd_data_guc_devid {
> + /**
> + * @guc_devid: GuC microcontroller device ID defined as described
> + * in GUC_LIC_TYPE_GUC_DEVICE_ID
> + */
> + u32 guc_devid;
> +} __packed;
> +
> +/**
> + * struct guc_lfd_data_tsc_freq - GuC TSC Fequency.
> + * This is mandatory fw LFD data
> + */
> +struct guc_lfd_data_tsc_freq {
> + /**
> + * @tsc_freq: GuC timestamp counter frequency as described in
> + * GUC_LIC_TYPE_TSC_FREQUENCY
> + */
> + u32 tsc_freq;
> +} __packed;
> +
> +/** struct guc_lfd_data_gmdid - GMD ID. */
> +struct guc_lfd_data_gmdid {
> + /** @gmd_id: GMD ID as described in GUC_LIC_TYPE_GMD_ID */
> + u32 gmd_id;
> +} __packed;
> +
> +/** struct guc_lfd_data_build_platformid - GuC build platform ID. */
> +struct guc_lfd_data_build_platformid {
> + /**
> + * @platform_build_id: GuC build platform ID as described in
> + * GUC_LIC_TYPE_BUILD_PLATFORM_ID
> + */
> + u32 platform_build_id;
> +} __packed;
Again, not sure these four are worth having structure definitions for. A
comment that says LFD_DEVID maps to LIC_DEVID, etc. would be sufficient.
> +
> +/**
> + * struct guc_lfd_data_log_events_buf - GuC Log Events Buffer.
> + * This is optional fw LFD data
As above, this is not a firmware generated data stream. Should just say
"This is an optional LFD block.".
> + */
> +struct guc_lfd_data_log_events_buf {
> + /**
> + * @log_events_format_version: version of GuC log format of buffer
> + */
> + u32 log_events_format_version;
> + /**
> + * @log_format_buf: If `log_format_version` == 1, array of
> + * guc_log_format_version_1. If `log_format_version` == 2, array
> + * of guc_log_format_version_2. Dword size determined by
> + * guc_logfile_lfd.`desc_dw_size` - 1
This does not match the name you used in the parent LFD header
structure. Should just say "Size in dwords is LFD block size - 1".
> + */
> + u32 log_format_buf[];
> +} __packed;
> +
> +/**
> + * struct guc_lfd_data_os_info - OS Version Information.
> + * This is mandatory host LFD data
As above, this is all being created by the host so no need to specify.
> + */
> +struct guc_lfd_data_os_info {
> + /**
> + * @os_id: enum values to identify the OS brand (1=Windows,
> + * 2=Linux, etc..). See guc_lfd_os_type for the range of types
Should not repeat a subset of the enum definition values here. Just
reference the enum name.
> + */
> + u32 os_id;
> + /**
> + * @build_version: ASCII string containing OS build version
> + * information based on os_id. String is padded with null
> + * characters to ensure its DWORD aligned. Dword size determined
> + * by guc_logfile_lfd.`desc_dw_size` - 1
As above about naming.
> + */
> + char build_version[];
> +} __packed;
> +
> +/**
> + * struct guc_lfd_data_fw_version - GuC FW Version.
> + * This is mandatory fw LFD data
> + */
> +struct guc_lfd_data_fw_version {
> + /**
> + * @guc_sw_version: The full version of the GuC microkernel that
> + * generated the logs as described in
> + * GUC_LIC_TYPE_GUC_SW_VERSION.
Except that the log data block is optional and so not necessarily
present. Should just say "The full version of the GuC firmware.".
> + */
> + struct guc_sw_version guc_sw_version;
> +} __packed;
Although, again this is a single u32 structure, which seems pointless. A
comment description would be sufficient.
> +
> +/**
> + * struct guc_logfile_header - Header of GuC Log Streaming-LFD-File Format.
> + * This structure encapsulates the layout of the guc-log-file format
> + */
> +struct guc_lfd_file_header {
> + /**
> + * @magic: A magic number set by producer of a GuC log file to
> + * identify that file is a valid guc-log-file containing a stream
> + * of LFDs: Expected value: GUC_LFD_DRIVER_KEY_STREAMING
> + */
> + u64 magic;
> + /**
> + * @version: Version of this file format layout as per
> + * guc_lfd_version
> + */
> + struct guc_lfd_version version;
> + /**
> + * @lfd_stream: A stream of one or more guc_lfd_data LFD data
"LFD blocks" is a better way to describe them than "LFD data". Data can
mean pretty much anything, whereas block implies a discrete unit.
> + */
> + struct guc_lfd_data lfd_stream;
Technically, this is just a single LFD block, not a stream. And you
can't really do 'lfd_stream[]' because blocks are variable in size.
Would be better to just say "u32 lfd_stream[];".
John.
> +} __packed;
> +
> +#endif
More information about the Intel-xe
mailing list