diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/2694-drm-amdkfd-Add-wavefront-context-save-state-retrieva.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/2694-drm-amdkfd-Add-wavefront-context-save-state-retrieva.patch | 350 |
1 files changed, 350 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/2694-drm-amdkfd-Add-wavefront-context-save-state-retrieva.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/2694-drm-amdkfd-Add-wavefront-context-save-state-retrieva.patch new file mode 100644 index 00000000..7f450b83 --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/2694-drm-amdkfd-Add-wavefront-context-save-state-retrieva.patch @@ -0,0 +1,350 @@ +From bdad2d0bb4a8a4f995d6ace4331f082e54458c12 Mon Sep 17 00:00:00 2001 +From: Jay Cornwall <Jay.Cornwall@amd.com> +Date: Tue, 2 May 2017 17:39:37 -0500 +Subject: [PATCH 2694/2940] drm/amdkfd: Add wavefront context save state + retrieval ioctl + +Wavefront context save data is of interest to userspace clients for +debugging static wavefront state. The MQD contains two parameters +required to parse the control stack and the control stack itself +is kept in the MQD from gfx9 onwards. + +Add an ioctl to fetch the context save area and control stack offsets +and to copy the control stack to a userspace address if it is kept in +the MQD. + +Signed-off-by: Jay Cornwall <Jay.Cornwall@amd.com> +Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> +Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com> +Acked-by: Alex Deucher <alexander.deucher@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +--- + drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 21 +++++++++++ + .../drm/amd/amdkfd/kfd_device_queue_manager.c | 37 +++++++++++++++++++ + .../drm/amd/amdkfd/kfd_device_queue_manager.h | 8 ++++ + drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h | 8 ++++ + .../gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c | 23 ++++++++++++ + .../gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c | 23 ++++++++++++ + drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 5 +++ + .../amd/amdkfd/kfd_process_queue_manager.c | 22 +++++++++++ + include/uapi/linux/kfd_ioctl.h | 13 ++++++- + 9 files changed, 159 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +index 758398bdb39b..14d5b5fa822d 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +@@ -447,6 +447,24 @@ static int kfd_ioctl_set_cu_mask(struct file *filp, struct kfd_process *p, + return retval; + } + ++static int kfd_ioctl_get_queue_wave_state(struct file *filep, ++ struct kfd_process *p, void *data) ++{ ++ struct kfd_ioctl_get_queue_wave_state_args *args = data; ++ int r; ++ ++ mutex_lock(&p->mutex); ++ ++ r = pqm_get_wave_state(&p->pqm, args->queue_id, ++ (void __user *)args->ctl_stack_address, ++ &args->ctl_stack_used_size, ++ &args->save_area_used_size); ++ ++ mutex_unlock(&p->mutex); ++ ++ return r; ++} ++ + static int kfd_ioctl_set_memory_policy(struct file *filep, + struct kfd_process *p, void *data) + { +@@ -1615,6 +1633,9 @@ static const struct amdkfd_ioctl_desc amdkfd_ioctls[] = { + AMDKFD_IOCTL_DEF(AMDKFD_IOC_SET_CU_MASK, + kfd_ioctl_set_cu_mask, 0), + ++ AMDKFD_IOCTL_DEF(AMDKFD_IOC_GET_QUEUE_WAVE_STATE, ++ kfd_ioctl_get_queue_wave_state, 0) ++ + }; + + #define AMDKFD_CORE_IOCTL_COUNT ARRAY_SIZE(amdkfd_ioctls) +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +index 4f22e745df51..1542c98112ac 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +@@ -1549,6 +1549,41 @@ static int process_termination_nocpsch(struct device_queue_manager *dqm, + return retval; + } + ++static int get_wave_state(struct device_queue_manager *dqm, ++ struct queue *q, ++ void __user *ctl_stack, ++ u32 *ctl_stack_used_size, ++ u32 *save_area_used_size) ++{ ++ struct mqd_manager *mqd; ++ int r; ++ ++ dqm_lock(dqm); ++ ++ if (q->properties.type != KFD_QUEUE_TYPE_COMPUTE || ++ q->properties.is_active || !q->device->cwsr_enabled) { ++ r = -EINVAL; ++ goto dqm_unlock; ++ } ++ ++ mqd = dqm->ops.get_mqd_manager(dqm, KFD_MQD_TYPE_COMPUTE); ++ if (!mqd) { ++ r = -ENOMEM; ++ goto dqm_unlock; ++ } ++ ++ if (!mqd->get_wave_state) { ++ r = -EINVAL; ++ goto dqm_unlock; ++ } ++ ++ r = mqd->get_wave_state(mqd, q->mqd, ctl_stack, ctl_stack_used_size, ++ save_area_used_size); ++ ++dqm_unlock: ++ dqm_unlock(dqm); ++ return r; ++} + + static int process_termination_cpsch(struct device_queue_manager *dqm, + struct qcm_process_device *qpd) +@@ -1670,6 +1705,7 @@ struct device_queue_manager *device_queue_manager_init(struct kfd_dev *dev) + dqm->ops.process_termination = process_termination_cpsch; + dqm->ops.evict_process_queues = evict_process_queues_cpsch; + dqm->ops.restore_process_queues = restore_process_queues_cpsch; ++ dqm->ops.get_wave_state = get_wave_state; + break; + case KFD_SCHED_POLICY_NO_HWS: + /* initialize dqm for no cp scheduling */ +@@ -1689,6 +1725,7 @@ struct device_queue_manager *device_queue_manager_init(struct kfd_dev *dev) + dqm->ops.evict_process_queues = evict_process_queues_nocpsch; + dqm->ops.restore_process_queues = + restore_process_queues_nocpsch; ++ dqm->ops.get_wave_state = get_wave_state; + break; + default: + pr_err("Invalid scheduling policy %d\n", dqm->sched_policy); +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h +index 00da3169a004..e7bd19d09845 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h +@@ -82,6 +82,8 @@ struct device_process_node { + * + * @restore_process_queues: Restore all evicted queues queues of a process + * ++ * @get_wave_state: Retrieves context save state and optionally copies the ++ * control stack, if kept in the MQD, to the given userspace address. + */ + + struct device_queue_manager_ops { +@@ -137,6 +139,12 @@ struct device_queue_manager_ops { + struct qcm_process_device *qpd); + int (*restore_process_queues)(struct device_queue_manager *dqm, + struct qcm_process_device *qpd); ++ ++ int (*get_wave_state)(struct device_queue_manager *dqm, ++ struct queue *q, ++ void __user *ctl_stack, ++ u32 *ctl_stack_used_size, ++ u32 *save_area_used_size); + }; + + struct device_queue_manager_asic_ops { +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h +index 4e84052d4e21..f8261313ae7b 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h +@@ -43,6 +43,9 @@ + * + * @is_occupied: Checks if the relevant HQD slot is occupied. + * ++ * @get_wave_state: Retrieves context save state and optionally copies the ++ * control stack, if kept in the MQD, to the given userspace address. ++ * + * @mqd_mutex: Mqd manager mutex. + * + * @dev: The kfd device structure coupled with this module. +@@ -85,6 +88,11 @@ struct mqd_manager { + uint64_t queue_address, uint32_t pipe_id, + uint32_t queue_id); + ++ int (*get_wave_state)(struct mqd_manager *mm, void *mqd, ++ void __user *ctl_stack, ++ u32 *ctl_stack_used_size, ++ u32 *save_area_used_size); ++ + #if defined(CONFIG_DEBUG_FS) + int (*debugfs_show_mqd)(struct seq_file *m, void *data); + #endif +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c +index 0cedb37cf513..f381c1cb27bd 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c +@@ -266,6 +266,28 @@ static bool is_occupied(struct mqd_manager *mm, void *mqd, + pipe_id, queue_id); + } + ++static int get_wave_state(struct mqd_manager *mm, void *mqd, ++ void __user *ctl_stack, ++ u32 *ctl_stack_used_size, ++ u32 *save_area_used_size) ++{ ++ struct v9_mqd *m; ++ ++ /* Control stack is located one page after MQD. */ ++ void *mqd_ctl_stack = (void *)((uintptr_t)mqd + PAGE_SIZE); ++ ++ m = get_mqd(mqd); ++ ++ *ctl_stack_used_size = m->cp_hqd_cntl_stack_size - ++ m->cp_hqd_cntl_stack_offset; ++ *save_area_used_size = m->cp_hqd_wg_state_offset; ++ ++ if (copy_to_user(ctl_stack, mqd_ctl_stack, m->cp_hqd_cntl_stack_size)) ++ return -EFAULT; ++ ++ return 0; ++} ++ + static int init_mqd_hiq(struct mqd_manager *mm, void **mqd, + struct kfd_mem_obj **mqd_mem_obj, uint64_t *gart_addr, + struct queue_properties *q) +@@ -435,6 +457,7 @@ struct mqd_manager *mqd_manager_init_v9(enum KFD_MQD_TYPE type, + mqd->update_mqd = update_mqd; + mqd->destroy_mqd = destroy_mqd; + mqd->is_occupied = is_occupied; ++ mqd->get_wave_state = get_wave_state; + #if defined(CONFIG_DEBUG_FS) + mqd->debugfs_show_mqd = debugfs_show_mqd; + #endif +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c +index b81fda3754da..6469b3456f00 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c +@@ -269,6 +269,28 @@ static bool is_occupied(struct mqd_manager *mm, void *mqd, + pipe_id, queue_id); + } + ++static int get_wave_state(struct mqd_manager *mm, void *mqd, ++ void __user *ctl_stack, ++ u32 *ctl_stack_used_size, ++ u32 *save_area_used_size) ++{ ++ struct vi_mqd *m; ++ ++ m = get_mqd(mqd); ++ ++ *ctl_stack_used_size = m->cp_hqd_cntl_stack_size - ++ m->cp_hqd_cntl_stack_offset; ++ *save_area_used_size = m->cp_hqd_wg_state_offset - ++ m->cp_hqd_cntl_stack_size; ++ ++ /* Control stack is not copied to user mode for GFXv8 because ++ * it's part of the context save area that is already ++ * accessible to user mode ++ */ ++ ++ return 0; ++} ++ + static int init_mqd_hiq(struct mqd_manager *mm, void **mqd, + struct kfd_mem_obj **mqd_mem_obj, uint64_t *gart_addr, + struct queue_properties *q) +@@ -436,6 +458,7 @@ struct mqd_manager *mqd_manager_init_vi(enum KFD_MQD_TYPE type, + mqd->update_mqd = update_mqd; + mqd->destroy_mqd = destroy_mqd; + mqd->is_occupied = is_occupied; ++ mqd->get_wave_state = get_wave_state; + #if defined(CONFIG_DEBUG_FS) + mqd->debugfs_show_mqd = debugfs_show_mqd; + #endif +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +index 73b8df95eb89..e23ff42803f5 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +@@ -890,6 +890,11 @@ int pqm_set_cu_mask(struct process_queue_manager *pqm, unsigned int qid, + struct queue_properties *p); + struct kernel_queue *pqm_get_kernel_queue(struct process_queue_manager *pqm, + unsigned int qid); ++int pqm_get_wave_state(struct process_queue_manager *pqm, ++ unsigned int qid, ++ void __user *ctl_stack, ++ u32 *ctl_stack_used_size, ++ u32 *save_area_used_size); + + int amdkfd_fence_wait_timeout(unsigned int *fence_addr, + unsigned int fence_value, +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +index c8cad9c078ae..fcaaf93681ac 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +@@ -408,6 +408,28 @@ struct kernel_queue *pqm_get_kernel_queue( + return NULL; + } + ++int pqm_get_wave_state(struct process_queue_manager *pqm, ++ unsigned int qid, ++ void __user *ctl_stack, ++ u32 *ctl_stack_used_size, ++ u32 *save_area_used_size) ++{ ++ struct process_queue_node *pqn; ++ ++ pqn = get_queue_by_qid(pqm, qid); ++ if (!pqn) { ++ pr_debug("amdkfd: No queue %d exists for operation\n", ++ qid); ++ return -EFAULT; ++ } ++ ++ return pqn->q->device->dqm->ops.get_wave_state(pqn->q->device->dqm, ++ pqn->q, ++ ctl_stack, ++ ctl_stack_used_size, ++ save_area_used_size); ++} ++ + #if defined(CONFIG_DEBUG_FS) + + int pqm_debugfs_mqds(struct seq_file *m, void *data) +diff --git a/include/uapi/linux/kfd_ioctl.h b/include/uapi/linux/kfd_ioctl.h +index e02346d26c59..fe97d25b1d9b 100644 +--- a/include/uapi/linux/kfd_ioctl.h ++++ b/include/uapi/linux/kfd_ioctl.h +@@ -82,6 +82,14 @@ struct kfd_ioctl_set_cu_mask_args { + __u64 cu_mask_ptr; /* to KFD */ + }; + ++struct kfd_ioctl_get_queue_wave_state_args { ++ uint64_t ctl_stack_address; /* to KFD */ ++ uint32_t ctl_stack_used_size; /* from KFD */ ++ uint32_t save_area_used_size; /* from KFD */ ++ uint32_t queue_id; /* to KFD */ ++ uint32_t pad; ++}; ++ + /* For kfd_ioctl_set_memory_policy_args.default_policy and alternate_policy */ + #define KFD_IOC_CACHE_POLICY_COHERENT 0 + #define KFD_IOC_CACHE_POLICY_NONCOHERENT 1 +@@ -482,7 +490,10 @@ enum kfd_mmio_remap { + #define AMDKFD_IOC_SET_CU_MASK \ + AMDKFD_IOW(0x1A, struct kfd_ioctl_set_cu_mask_args) + ++#define AMDKFD_IOC_GET_QUEUE_WAVE_STATE \ ++ AMDKFD_IOWR(0x1B, struct kfd_ioctl_get_queue_wave_state_args) ++ + #define AMDKFD_COMMAND_START 0x01 +-#define AMDKFD_COMMAND_END 0x1B ++#define AMDKFD_COMMAND_END 0x1C + + #endif +-- +2.17.1 + |