[PATCH v2 4/4] drm/xe/pf: Allow to view and replace VF LMEM and CCS state over debugfs

Laguna, Lukasz lukasz.laguna at intel.com
Tue Nov 5 11:08:40 UTC 2024


On 10/31/2024 17:04, Matthew Brost wrote:
> On Thu, Oct 31, 2024 at 04:17:25PM +0100, Lukasz Laguna wrote:
>> For feature enabling and testing purposes, allow to save VF LMEM and CCS
>> state and to replace it using debugfs blob file, but only under strict
>> debug config.
>>
> This patch resembles a function I'm adding to support BO access to and
> from a void * for EU debug and general kernel use. Here is a link to the
> series [1]. It utilizes the GPU for non-visible VRAM access and large
> transfers, or it uses the CPU when possible. It doesn't have CCS
> support, but to be honest, I don’t fully understand CCS, so it may be an
> omission on my part. Either way, I think we need to synchronize and
> develop a common approach for BO access in TTM/Xe, ensuring it meets all
> requirements (EU debug, general Xe use, SRIOV, CCS, etc.).
>
> Please note that the version of my series on the list is not 100%
> functional, but I can share an updated version that should be fully
> tested for non-CCS access.
>
> Matt
>
> [1] https://patchwork.freedesktop.org/series/140200/

The whole point of this patch is to use 
xe_gt_sriov_pf_migration_save_lmem() and 
xe_gt_sriov_pf_migration_restore_lmem() functions, because they will be 
used in future VM save/restore operations. These functions handle the 
transfer of VRAM and CCS data to and from SMEM using blitter engine (to 
increase the performance). As a result, we are only accessing SMEM objects.

>
>> Signed-off-by: Lukasz Laguna <lukasz.laguna at intel.com>
>> ---
>>   drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.c   |  78 +++++++
>>   drivers/gpu/drm/xe/xe_gt_sriov_pf_migration.c | 205 ++++++++++++++++++
>>   drivers/gpu/drm/xe/xe_gt_sriov_pf_migration.h |   9 +
>>   3 files changed, 292 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.c
>> index 05df4ab3514b..001fc6b585ee 100644
>> --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.c
>> +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.c
>> @@ -422,6 +422,76 @@ static const struct file_operations guc_state_ops = {
>>   	.llseek		= default_llseek,
>>   };
>>   
>> +/*
>> + *      /sys/kernel/debug/dri/0/
>> + *      ├── gt0
>> + *      │   ├── vf1
>> + *      │   │   ├── lmem_state
>> + */
>> +static ssize_t lmem_state_read(struct file *file, char __user *buf,
>> +			       size_t count, loff_t *pos)
>> +{
>> +	struct dentry *dent = file_dentry(file);
>> +	struct dentry *parent = dent->d_parent;
>> +	struct xe_gt *gt = extract_gt(parent);
>> +	unsigned int vfid = extract_vfid(parent);
>> +
>> +	return xe_gt_sriov_pf_migration_read_lmem_state(gt, vfid, buf, count, pos);
>> +}
>> +
>> +static ssize_t lmem_state_write(struct file *file, const char __user *buf,
>> +				size_t count, loff_t *pos)
>> +{
>> +	struct dentry *dent = file_dentry(file);
>> +	struct dentry *parent = dent->d_parent;
>> +	struct xe_gt *gt = extract_gt(parent);
>> +	unsigned int vfid = extract_vfid(parent);
>> +
>> +	return xe_gt_sriov_pf_migration_write_lmem_state(gt, vfid, buf, count, pos);
>> +}
>> +
>> +static const struct file_operations lmem_state_ops = {
>> +	.owner		= THIS_MODULE,
>> +	.read		= lmem_state_read,
>> +	.write		= lmem_state_write,
>> +	.llseek		= default_llseek,
>> +};
>> +
>> +/*
>> + *      /sys/kernel/debug/dri/0/
>> + *      ├── gt0
>> + *      │   ├── vf1
>> + *      │   │   ├── ccs_state
>> + */
>> +static ssize_t ccs_state_read(struct file *file, char __user *buf,
>> +			      size_t count, loff_t *pos)
>> +{
>> +	struct dentry *dent = file_dentry(file);
>> +	struct dentry *parent = dent->d_parent;
>> +	struct xe_gt *gt = extract_gt(parent);
>> +	unsigned int vfid = extract_vfid(parent);
>> +
>> +	return xe_gt_sriov_pf_migration_read_ccs_state(gt, vfid, buf, count, pos);
>> +}
>> +
>> +static ssize_t ccs_state_write(struct file *file, const char __user *buf,
>> +			       size_t count, loff_t *pos)
>> +{
>> +	struct dentry *dent = file_dentry(file);
>> +	struct dentry *parent = dent->d_parent;
>> +	struct xe_gt *gt = extract_gt(parent);
>> +	unsigned int vfid = extract_vfid(parent);
>> +
>> +	return xe_gt_sriov_pf_migration_write_ccs_state(gt, vfid, buf, count, pos);
>> +}
>> +
>> +static const struct file_operations ccs_state_ops = {
>> +	.owner		= THIS_MODULE,
>> +	.read		= ccs_state_read,
>> +	.write		= ccs_state_write,
>> +	.llseek		= default_llseek,
>> +};
>> +
>>   /*
>>    *      /sys/kernel/debug/dri/0/
>>    *      ├── gt0
>> @@ -554,6 +624,14 @@ void xe_gt_sriov_pf_debugfs_register(struct xe_gt *gt, struct dentry *root)
>>   			debugfs_create_file("config_blob",
>>   					    IS_ENABLED(CONFIG_DRM_XE_DEBUG_SRIOV) ? 0600 : 0400,
>>   					    vfdentry, NULL, &config_blob_ops);
>> +			if (IS_DGFX(xe)) {
>> +				debugfs_create_file("lmem_state",
>> +						    IS_ENABLED(CONFIG_DRM_XE_DEBUG_SRIOV) ?
>> +						    0600 : 0400, vfdentry, NULL, &lmem_state_ops);
>> +				debugfs_create_file("ccs_state",
>> +						    IS_ENABLED(CONFIG_DRM_XE_DEBUG_SRIOV) ?
>> +						    0600 : 0400, vfdentry, NULL, &ccs_state_ops);
>> +			}
>>   		}
>>   	}
>>   }
>> diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_migration.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_migration.c
>> index eca01c96a348..8ff6b7eebb33 100644
>> --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_migration.c
>> +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_migration.c
>> @@ -6,7 +6,9 @@
>>   #include <drm/drm_managed.h>
>>   
>>   #include "abi/guc_actions_sriov_abi.h"
>> +#include "instructions/xe_gpu_commands.h"
>>   #include "xe_bo.h"
>> +#include "xe_gt_sriov_pf_config.h"
>>   #include "xe_gt_sriov_pf_helpers.h"
>>   #include "xe_gt_sriov_pf_migration.h"
>>   #include "xe_gt_sriov_printk.h"
>> @@ -381,6 +383,209 @@ ssize_t xe_gt_sriov_pf_migration_write_guc_state(struct xe_gt *gt, unsigned int
>>   
>>   	return ret;
>>   }
>> +
>> +static ssize_t pf_read_lmem_state(struct xe_gt *gt, unsigned int vfid, bool ccs,
>> +				  char __user *buf, size_t count, loff_t *pos)
>> +{
>> +	struct xe_device *xe = gt_to_xe(gt);
>> +	size_t lmem_size, chunk_size;
>> +	struct xe_bo *smem_bo;
>> +	struct dma_fence *fence;
>> +	loff_t smem_bo_pos = 0;
>> +	ssize_t ret;
>> +
>> +	xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt)));
>> +	xe_gt_assert(gt, vfid != PFID);
>> +	xe_gt_assert(gt, vfid <= xe_sriov_pf_get_totalvfs(gt_to_xe(gt)));
>> +
>> +	if (!pf_migration_supported(gt))
>> +		return -ENOPKG;
>> +
>> +	lmem_size = xe_gt_sriov_pf_config_get_lmem(gt, vfid);
>> +	if (!lmem_size)
>> +		return -ENODATA;
>> +
>> +	chunk_size = min(count, (ccs ? xe_device_ccs_bytes(xe, lmem_size) : lmem_size) - *pos);
>> +	if (!chunk_size)
>> +		return 0;
>> +
>> +	smem_bo = xe_bo_create_pin_map(xe, NULL, NULL, PAGE_ALIGN(chunk_size), ttm_bo_type_kernel,
>> +				      XE_BO_FLAG_SYSTEM | XE_BO_FLAG_NEEDS_CPU_ACCESS |
>> +				      XE_BO_FLAG_PINNED);
>> +	if (IS_ERR(smem_bo))
>> +		return PTR_ERR(smem_bo);
>> +
>> +	if (ccs)
>> +		fence = xe_gt_sriov_pf_migration_save_lmem(gt, vfid, NULL, 0, smem_bo, 0,
>> +							   *pos * NUM_BYTES_PER_CCS_BYTE(xe),
>> +							   chunk_size * NUM_BYTES_PER_CCS_BYTE(xe));
>> +	else
>> +		fence = xe_gt_sriov_pf_migration_save_lmem(gt, vfid, smem_bo, 0, NULL, 0, *pos,
>> +							   chunk_size);
>> +
>> +	ret = dma_fence_wait_timeout(fence, false, 5 * HZ);
>> +	dma_fence_put(fence);
>> +	if (!ret) {
>> +		ret = -ETIME;
>> +		goto err_smem_bo_put;
>> +	}
>> +
>> +	ret = simple_read_from_buffer(buf, chunk_size, &smem_bo_pos, smem_bo->vmap.vaddr,
>> +				      chunk_size);
>> +	if (ret > 0) {
>> +		if (ret != chunk_size)
>> +			xe_gt_sriov_dbg(gt, "Failed to copy the entire chunk (copied bytes: %ld, expected: %lu)\n",
>> +				ret, chunk_size);
>> +		*pos +=	ret;
>> +	}
>> +
>> +err_smem_bo_put:
>> +	xe_bo_unpin_map_no_vm(smem_bo);
>> +
>> +	return ret;
>> +}
>> +
>> +static ssize_t pf_write_lmem_state(struct xe_gt *gt, unsigned int vfid, bool ccs,
>> +				   const char __user *buf, size_t count, loff_t *pos)
>> +{
>> +	struct xe_device *xe = gt_to_xe(gt);
>> +	struct xe_bo *smem_bo;
>> +	loff_t smem_bo_pos = 0;
>> +	struct dma_fence *fence;
>> +	ssize_t ret, err;
>> +
>> +	xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt)));
>> +	xe_gt_assert(gt, vfid != PFID);
>> +	xe_gt_assert(gt, vfid <= xe_sriov_pf_get_totalvfs(gt_to_xe(gt)));
>> +
>> +	if (!pf_migration_supported(gt))
>> +		return -ENOPKG;
>> +
>> +	if (!xe_gt_sriov_pf_config_get_lmem(gt, vfid))
>> +		return -ENOPKG;
>> +
>> +	smem_bo = xe_bo_create_pin_map(xe, NULL, NULL, PAGE_ALIGN(count), ttm_bo_type_kernel,
>> +				      XE_BO_FLAG_SYSTEM | XE_BO_FLAG_NEEDS_CPU_ACCESS |
>> +				      XE_BO_FLAG_PINNED);
>> +	if (IS_ERR(smem_bo))
>> +		return PTR_ERR(smem_bo);
>> +
>> +	ret = simple_write_to_buffer(smem_bo->vmap.vaddr, count, &smem_bo_pos, buf, count);
>> +	if (ret < 0)
>> +		goto err_smem_bo_put;
>> +	if (ret != count)
>> +		xe_gt_sriov_dbg(gt, "Failed to copy the entire chunk (copied bytes: %ld, expected: %lu)\n",
>> +				ret, count);
>> +
>> +	if (ccs)
>> +		fence = xe_gt_sriov_pf_migration_restore_lmem(gt, vfid, NULL, 0, smem_bo, 0,
>> +							      *pos * NUM_BYTES_PER_CCS_BYTE(xe),
>> +							      ret * NUM_BYTES_PER_CCS_BYTE(xe));
>> +	else
>> +		fence = xe_gt_sriov_pf_migration_restore_lmem(gt, vfid, smem_bo, 0, NULL, 0, *pos,
>> +							      ret);
>> +
>> +	err = dma_fence_wait_timeout(fence, false, 5 * HZ);
>> +	dma_fence_put(fence);
>> +	if (!err) {
>> +		ret = -ETIME;
>> +		goto err_smem_bo_put;
>> +	}
>> +
>> +	*pos +=	ret;
>> +
>> +err_smem_bo_put:
>> +	xe_bo_unpin_map_no_vm(smem_bo);
>> +
>> +	return ret;
>> +}
>> +
>> +/**
>> + * xe_gt_sriov_pf_migration_read_lmem_state() - Read a VF LMEM state.
>> + * @gt: the &xe_gt
>> + * @vfid: the VF identifier
>> + * @buf: the user space buffer to read to
>> + * @count: the maximum number of bytes to read
>> + * @pos: the current position in the buffer
>> + *
>> + * This function is for PF only.
>> + *
>> + * This function reads up to @count bytes from assigned to VF LMEM buffer
>> + * object at offset @pos into the user space address starting at @buf.
>> + *
>> + * Return: the number of bytes read or a negative error code on failure.
>> + */
>> +ssize_t xe_gt_sriov_pf_migration_read_lmem_state(struct xe_gt *gt, unsigned int vfid,
>> +						 char __user *buf, size_t count, loff_t *pos)
>> +{
>> +	return pf_read_lmem_state(gt, vfid, false, buf, count, pos);
>> +}
>> +
>> +/**
>> + * xe_gt_sriov_pf_migration_write_lmem_state() - Write a VF LMEM state.
>> + * @gt: the &xe_gt
>> + * @vfid: the VF identifier
>> + * @buf: the user space buffer with VF LMEM state
>> + * @count: the maximum number of bytes to write (in bytes)
>> + * @pos: the current position in the buffer
>> + *
>> + * This function is for PF only.
>> + *
>> + * This function reads @count bytes of the VF LMEM state stored at offset @pos
>> + * of the user space buffer @buf and writes it into a assigned to VF LMEM buffer
>> + * object.
>> + *
>> + * Return: the number of bytes used or a negative error code on failure.
>> + */
>> +ssize_t xe_gt_sriov_pf_migration_write_lmem_state(struct xe_gt *gt, unsigned int vfid,
>> +						  const char __user *buf, size_t count,
>> +						  loff_t *pos)
>> +{
>> +	return pf_write_lmem_state(gt, vfid, false, buf, count, pos);
>> +}
>> +
>> +/**
>> + * xe_gt_sriov_pf_migration_read_ccs_state() - Read a VF CCS state.
>> + * @gt: the &xe_gt
>> + * @vfid: the VF identifier
>> + * @buf: the user space buffer to read to
>> + * @count: the maximum number of bytes to read
>> + * @pos: the current position in the buffer
>> + *
>> + * This function is for PF only.
>> + *
>> + * This function reads up to @count bytes of the VF CCS data at offset @pos
>> + * into the user space address starting at @buf.
>> + *
>> + * Return: the number of bytes read or a negative error code on failure.
>> + */
>> +ssize_t xe_gt_sriov_pf_migration_read_ccs_state(struct xe_gt *gt, unsigned int vfid,
>> +						char __user *buf, size_t count, loff_t *pos)
>> +{
>> +	return pf_read_lmem_state(gt, vfid, true, buf, count, pos);
>> +}
>> +
>> +/**
>> + * xe_gt_sriov_pf_migration_write_ccs_state() - Write a VF CCS state.
>> + * @gt: the &xe_gt
>> + * @vfid: the VF identifier
>> + * @buf: the user space buffer with VF CCS state
>> + * @count: the maximum number of bytes to write (in bytes)
>> + * @pos: the current position in the buffer
>> + *
>> + * This function is for PF only.
>> + *
>> + * This function reads @count bytes of the VF CCS state from the user space
>> + * address @buf at offset @pos and writes it into a device memory where VF CCS
>> + * is stored.
>> + *
>> + * Return: the number of bytes used or a negative error code on failure.
>> + */
>> +ssize_t xe_gt_sriov_pf_migration_write_ccs_state(struct xe_gt *gt, unsigned int vfid,
>> +						 const char __user *buf, size_t count, loff_t *pos)
>> +{
>> +	return pf_write_lmem_state(gt, vfid, true, buf, count, pos);
>> +}
>>   #endif /* CONFIG_DEBUG_FS */
>>   
>>   static struct dma_fence *pf_save_restore_lmem(struct xe_gt *gt, unsigned int vfid,
>> diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_migration.h b/drivers/gpu/drm/xe/xe_gt_sriov_pf_migration.h
>> index a4301574d92c..da1b067baf56 100644
>> --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_migration.h
>> +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_migration.h
>> @@ -28,6 +28,15 @@ ssize_t xe_gt_sriov_pf_migration_read_guc_state(struct xe_gt *gt, unsigned int v
>>   						char __user *buf, size_t count, loff_t *pos);
>>   ssize_t xe_gt_sriov_pf_migration_write_guc_state(struct xe_gt *gt, unsigned int vfid,
>>   						 const char __user *buf, size_t count);
>> +ssize_t xe_gt_sriov_pf_migration_read_lmem_state(struct xe_gt *gt, unsigned int vfid,
>> +						 char __user *buf, size_t count, loff_t *pos);
>> +ssize_t xe_gt_sriov_pf_migration_write_lmem_state(struct xe_gt *gt, unsigned int vfid,
>> +						  const char __user *buf, size_t count,
>> +						  loff_t *pos);
>> +ssize_t xe_gt_sriov_pf_migration_read_ccs_state(struct xe_gt *gt, unsigned int vfid,
>> +						char __user *buf, size_t count, loff_t *pos);
>> +ssize_t xe_gt_sriov_pf_migration_write_ccs_state(struct xe_gt *gt, unsigned int vfid,
>> +						 const char __user *buf, size_t count, loff_t *pos);
>>   #endif
>>   
>>   #endif
>> -- 
>> 2.40.0
>>


More information about the Intel-xe mailing list