* [PATCH v5 00/10] AMDGPU Usermode queues
@ 2023-07-06 12:35 Shashank Sharma
2023-07-06 12:35 ` [PATCH v5 01/10] drm/amdgpu: UAPI for user queue management Shashank Sharma
` (9 more replies)
0 siblings, 10 replies; 50+ messages in thread
From: Shashank Sharma @ 2023-07-06 12:35 UTC (permalink / raw)
To: amd-gfx; +Cc: arvind.yadav, Shashank Sharma
This patch series introduces AMDGPU usermode queues for gfx workloads.
Usermode queues is a method of GPU workload submission into the graphics
hardware without any interaction with kernel/DRM schedulers. In this
method, a userspace graphics application can create its own workqueue
and submit it directly in the GPU HW.
The general idea of how this is supposed to work:
- The application creates the following GPU objetcs:
- A queue object to hold the workload packets.
- A read pointer object.
- A write pointer object.
- A doorbell page.
- Shadow bufffer pages.
- GDS buffer pages (if required).
- The application picks a 32-bit offset in the doorbell page for this
queue.
- The application uses the usermode_queue_create IOCTL introduced in
this patch, by passing the GPU addresses of these objects (read ptr,
write ptr, queue base address, shadow, gds) with doorbell object and
32-bit doorbell offset in the doorbell page.
- The kernel creates the queue and maps it in the HW.
- The application can start submitting the data in the queue as soon as
the kernel IOCTL returns.
- After filling the workload data in the queue, the app must write the
number of dwords added in the queue into the doorbell offset, and the
GPU will start fetching the data.
libDRM changes for this series and a sample DRM test program can be found
in the MESA merge request here:
https://gitlab.freedesktop.org/mesa/drm/-/merge_requests/287
This patch series depends on the doorbell-manager changes, which are being
reviewed here:
https://patchwork.freedesktop.org/series/115802/
Alex Deucher (1):
drm/amdgpu: UAPI for user queue management
Shashank Sharma (9):
drm/amdgpu: add usermode queue base code
drm/amdgpu: add new IOCTL for usermode queue
drm/amdgpu: create GFX-gen11 usermode queue
drm/amdgpu: create context space for usermode queue
drm/amdgpu: map usermode queue into MES
drm/amdgpu: map wptr BO into GART
drm/amdgpu: generate doorbell index for userqueue
drm/amdgpu: cleanup leftover queues
drm/amdgpu: add delay after userqueue mapping
drivers/gpu/drm/amd/amdgpu/Makefile | 2 +
drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 +
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 2 +
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 6 +
drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 221 +++++++++++++
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 294 ++++++++++++++++++
.../gpu/drm/amd/include/amdgpu_userqueue.h | 76 +++++
include/uapi/drm/amdgpu_drm.h | 110 +++++++
8 files changed, 713 insertions(+)
create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
create mode 100644 drivers/gpu/drm/amd/include/amdgpu_userqueue.h
--
2.40.1
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH v5 01/10] drm/amdgpu: UAPI for user queue management
2023-07-06 12:35 [PATCH v5 00/10] AMDGPU Usermode queues Shashank Sharma
@ 2023-07-06 12:35 ` Shashank Sharma
2023-07-06 12:35 ` [PATCH v5 02/10] drm/amdgpu: add usermode queue base code Shashank Sharma
` (8 subsequent siblings)
9 siblings, 0 replies; 50+ messages in thread
From: Shashank Sharma @ 2023-07-06 12:35 UTC (permalink / raw)
To: amd-gfx; +Cc: Alex Deucher, Christian Koenig, arvind.yadav, Shashank Sharma
From: Alex Deucher <alexander.deucher@amd.com>
This patch intorduces new UAPI/IOCTL for usermode graphics
queue. The userspace app will fill this structure and request
the graphics driver to add a graphics work queue for it. The
output of this UAPI is a queue id.
This UAPI maps the queue into GPU, so the graphics app can start
submitting work to the queue as soon as the call returns.
V2: Addressed review comments from Alex and Christian
- Make the doorbell offset's comment clearer
- Change the output parameter name to queue_id
V3: Integration with doorbell manager
V4:
- Updated the UAPI doc (Pierre-Eric)
- Created a Union for engine specific MQDs (Alex)
- Added Christian's R-B
V5:
- Add variables for GDS and CSA in MQD structure (Alex)
- Make MQD data a ptr-size pair instead of union (Alex)
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: Christian Koenig <christian.koenig@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
---
include/uapi/drm/amdgpu_drm.h | 110 ++++++++++++++++++++++++++++++++++
1 file changed, 110 insertions(+)
diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h
index b6eb90df5d05..4f1178c6ee34 100644
--- a/include/uapi/drm/amdgpu_drm.h
+++ b/include/uapi/drm/amdgpu_drm.h
@@ -54,6 +54,7 @@ extern "C" {
#define DRM_AMDGPU_VM 0x13
#define DRM_AMDGPU_FENCE_TO_HANDLE 0x14
#define DRM_AMDGPU_SCHED 0x15
+#define DRM_AMDGPU_USERQ 0x16
#define DRM_IOCTL_AMDGPU_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_CREATE, union drm_amdgpu_gem_create)
#define DRM_IOCTL_AMDGPU_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_MMAP, union drm_amdgpu_gem_mmap)
@@ -71,6 +72,7 @@ extern "C" {
#define DRM_IOCTL_AMDGPU_VM DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_VM, union drm_amdgpu_vm)
#define DRM_IOCTL_AMDGPU_FENCE_TO_HANDLE DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_FENCE_TO_HANDLE, union drm_amdgpu_fence_to_handle)
#define DRM_IOCTL_AMDGPU_SCHED DRM_IOW(DRM_COMMAND_BASE + DRM_AMDGPU_SCHED, union drm_amdgpu_sched)
+#define DRM_IOCTL_AMDGPU_USERQ DRM_IOW(DRM_COMMAND_BASE + DRM_AMDGPU_USERQ, union drm_amdgpu_userq)
/**
* DOC: memory domains
@@ -302,6 +304,114 @@ union drm_amdgpu_ctx {
union drm_amdgpu_ctx_out out;
};
+/* user queue IOCTL */
+#define AMDGPU_USERQ_OP_CREATE 1
+#define AMDGPU_USERQ_OP_FREE 2
+
+/* Flag to indicate secure buffer related workload, unused for now */
+#define AMDGPU_USERQ_MQD_FLAGS_SECURE (1 << 0)
+/* Flag to indicate AQL workload, unused for now */
+#define AMDGPU_USERQ_MQD_FLAGS_AQL (1 << 1)
+
+/*
+ * MQD (memory queue descriptor) is a set of parameters which allow
+ * the GPU to uniquely define and identify a usermode queue. This
+ * structure defines the MQD for GFX-V11 IP ver 0.
+ */
+struct drm_amdgpu_userq_mqd_gfx_v11_0 {
+ /**
+ * @queue_va: Virtual address of the GPU memory which holds the queue
+ * object. The queue holds the workload packets.
+ */
+ __u64 queue_va;
+ /**
+ * @queue_size: Size of the queue in bytes, this needs to be 256-byte
+ * aligned.
+ */
+ __u64 queue_size;
+ /**
+ * @rptr_va : Virtual address of the GPU memory which holds the ring RPTR.
+ * This object must be at least 8 byte in size and aligned to 8-byte offset.
+ */
+ __u64 rptr_va;
+ /**
+ * @wptr_va : Virtual address of the GPU memory which holds the ring WPTR.
+ * This object must be at least 8 byte in size and aligned to 8-byte offset.
+ *
+ * Queue, RPTR and WPTR can come from the same object, as long as the size
+ * and alignment related requirements are met.
+ */
+ __u64 wptr_va;
+ /**
+ * @shadow_va: Virtual address of the GPU memory to hold the shadow buffer.
+ * This must be a from a separate GPU object, and must be at least 4-page
+ * sized.
+ */
+ __u64 shadow_va;
+ /**
+ * @gds_va: Virtual address of the GPU memory to hold the GDS buffer.
+ * This must be a from a separate GPU object, and must be at least 1-page
+ * sized.
+ */
+ __u64 gds_va;
+ /**
+ * @csa_va: Virtual address of the GPU memory to hold the CSA buffer.
+ * This must be a from a separate GPU object, and must be at least 1-page
+ * sized.
+ */
+ __u64 csa_va;
+};
+
+struct drm_amdgpu_userq_in {
+ /** AMDGPU_USERQ_OP_* */
+ __u32 op;
+ /** Queue handle for USERQ_OP_FREE */
+ __u32 queue_id;
+ /** the target GPU engine to execute workload (AMDGPU_HW_IP_*) */
+ __u32 ip_type;
+ /**
+ * @flags: flags to indicate special function for queue like secure
+ * buffer (TMZ). Unused for now.
+ */
+ __u32 flags;
+ /**
+ * @doorbell_handle: the handle of doorbell GEM object
+ * associated to this client.
+ */
+ __u32 doorbell_handle;
+ /**
+ * @doorbell_offset: 32-bit offset of the doorbell in the doorbell bo.
+ * Kernel will generate absolute doorbell offset using doorbell_handle
+ * and doorbell_offset in the doorbell bo.
+ */
+ __u32 doorbell_offset;
+ /**
+ * @mqd: Queue descriptor for USERQ_OP_CREATE
+ * MQD data can be of different size for different GPU IP/engine and
+ * their respective versions/revisions, so this points to a __u64 *
+ * which holds MQD of this usermode queue.
+ */
+ __u64 mqd;
+ /**
+ * @size: size of MQD data in bytes, it must match the MQD structure
+ * size of the respective engine/revision defined in UAPI for ex, for
+ * gfx_v11 workloads, size = sizeof(drm_amdgpu_userq_mqd_gfx_v11).
+ */
+ __u64 mqd_size;
+};
+
+struct drm_amdgpu_userq_out {
+ /** Queue handle */
+ __u32 queue_id;
+ /** Flags */
+ __u32 flags;
+};
+
+union drm_amdgpu_userq {
+ struct drm_amdgpu_userq_in in;
+ struct drm_amdgpu_userq_out out;
+};
+
/* vm ioctl */
#define AMDGPU_VM_OP_RESERVE_VMID 1
#define AMDGPU_VM_OP_UNRESERVE_VMID 2
--
2.40.1
^ permalink raw reply related [flat|nested] 50+ messages in thread
* [PATCH v5 02/10] drm/amdgpu: add usermode queue base code
2023-07-06 12:35 [PATCH v5 00/10] AMDGPU Usermode queues Shashank Sharma
2023-07-06 12:35 ` [PATCH v5 01/10] drm/amdgpu: UAPI for user queue management Shashank Sharma
@ 2023-07-06 12:35 ` Shashank Sharma
2023-07-06 12:46 ` Christian König
2023-07-06 16:36 ` Alex Deucher
2023-07-06 12:35 ` [PATCH v5 03/10] drm/amdgpu: add new IOCTL for usermode queue Shashank Sharma
` (7 subsequent siblings)
9 siblings, 2 replies; 50+ messages in thread
From: Shashank Sharma @ 2023-07-06 12:35 UTC (permalink / raw)
To: amd-gfx; +Cc: Alex Deucher, Christian Koenig, arvind.yadav, Shashank Sharma
This patch adds skeleton code for amdgpu usermode queue.
It contains:
- A new files with init functions of usermode queues.
- A queue context manager in driver private data.
V1: Worked on design review comments from RFC patch series:
(https://patchwork.freedesktop.org/series/112214/)
- Alex: Keep a list of queues, instead of single queue per process.
- Christian: Use the queue manager instead of global ptrs,
Don't keep the queue structure in amdgpu_ctx
V2:
- Reformatted code, split the big patch into two
V3:
- Integration with doorbell manager
V4:
- Align the structure member names to the largest member's column
(Luben)
- Added SPDX license (Luben)
V5:
- Do not add amdgpu.h in amdgpu_userqueue.h (Christian).
- Move struct amdgpu_userq_mgr into amdgpu_userqueue.h (Christian).
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: Christian Koenig <christian.koenig@amd.com>
Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
---
drivers/gpu/drm/amd/amdgpu/Makefile | 2 +
drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 +
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 1 +
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 6 ++
drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 40 ++++++++++++
.../gpu/drm/amd/include/amdgpu_userqueue.h | 62 +++++++++++++++++++
6 files changed, 113 insertions(+)
create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
create mode 100644 drivers/gpu/drm/amd/include/amdgpu_userqueue.h
diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
index 415a7fa395c4..4b9bae995094 100644
--- a/drivers/gpu/drm/amd/amdgpu/Makefile
+++ b/drivers/gpu/drm/amd/amdgpu/Makefile
@@ -216,6 +216,8 @@ amdgpu-y += \
# add amdkfd interfaces
amdgpu-y += amdgpu_amdkfd.o
+# add usermode queue
+amdgpu-y += amdgpu_userqueue.o
ifneq ($(CONFIG_HSA_AMD),)
AMDKFD_PATH := ../amdkfd
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 02b827785e39..fab842138cd5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -107,6 +107,7 @@
#include "amdgpu_fdinfo.h"
#include "amdgpu_mca.h"
#include "amdgpu_ras.h"
+#include "amdgpu_userqueue.h"
#define MAX_GPU_INSTANCE 16
@@ -463,6 +464,7 @@ struct amdgpu_fpriv {
struct mutex bo_list_lock;
struct idr bo_list_handles;
struct amdgpu_ctx_mgr ctx_mgr;
+ struct amdgpu_userq_mgr userq_mgr;
};
int amdgpu_file_to_fpriv(struct file *filp, struct amdgpu_fpriv **fpriv);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index b1ca1ab6d6ad..4c5e44d41652 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -50,6 +50,7 @@
#include "amdgpu_ras.h"
#include "amdgpu_xgmi.h"
#include "amdgpu_reset.h"
+#include "amdgpu_userqueue.h"
/*
* KMS wrapper.
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index 0efb38539d70..68e5375b648b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -44,6 +44,7 @@
#include "amdgpu_display.h"
#include "amdgpu_ras.h"
#include "amd_pcie.h"
+#include "amdgpu_userqueue.h"
void amdgpu_unregister_gpu_instance(struct amdgpu_device *adev)
{
@@ -1234,6 +1235,10 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
amdgpu_ctx_mgr_init(&fpriv->ctx_mgr, adev);
+ r = amdgpu_userq_mgr_init(&fpriv->userq_mgr, adev);
+ if (r)
+ DRM_WARN("Can't setup usermode queues, use legacy workload submission only\n");
+
file_priv->driver_priv = fpriv;
goto out_suspend;
@@ -1301,6 +1306,7 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,
amdgpu_ctx_mgr_fini(&fpriv->ctx_mgr);
amdgpu_vm_fini(adev, &fpriv->vm);
+ amdgpu_userq_mgr_fini(&fpriv->userq_mgr);
if (pasid)
amdgpu_pasid_free_delayed(pd->tbo.base.resv, pasid);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
new file mode 100644
index 000000000000..effc0c7c02cf
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "amdgpu.h"
+
+int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct amdgpu_device *adev)
+{
+ mutex_init(&userq_mgr->userq_mutex);
+ idr_init_base(&userq_mgr->userq_idr, 1);
+ userq_mgr->adev = adev;
+
+ return 0;
+}
+
+void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr)
+{
+ idr_destroy(&userq_mgr->userq_idr);
+ mutex_destroy(&userq_mgr->userq_mutex);
+}
diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
new file mode 100644
index 000000000000..79ffa131a514
--- /dev/null
+++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef AMDGPU_USERQUEUE_H_
+#define AMDGPU_USERQUEUE_H_
+
+#define AMDGPU_MAX_USERQ_COUNT 512
+
+struct amdgpu_mqd_prop;
+
+struct amdgpu_usermode_queue {
+ int queue_type;
+ uint64_t doorbell_handle;
+ uint64_t doorbell_index;
+ uint64_t flags;
+ struct amdgpu_mqd_prop *userq_prop;
+ struct amdgpu_userq_mgr *userq_mgr;
+ struct amdgpu_vm *vm;
+};
+
+struct amdgpu_userq_funcs {
+ int (*mqd_create)(struct amdgpu_userq_mgr *uq_mgr,
+ struct drm_amdgpu_userq_in *args,
+ struct amdgpu_usermode_queue *queue);
+ void (*mqd_destroy)(struct amdgpu_userq_mgr *uq_mgr,
+ struct amdgpu_usermode_queue *uq);
+};
+
+/* Usermode queues for gfx */
+struct amdgpu_userq_mgr {
+ struct idr userq_idr;
+ struct mutex userq_mutex;
+ struct amdgpu_device *adev;
+ const struct amdgpu_userq_funcs *userq_funcs[AMDGPU_HW_IP_NUM];
+};
+
+int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct amdgpu_device *adev);
+
+void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr);
+
+#endif
--
2.40.1
^ permalink raw reply related [flat|nested] 50+ messages in thread
* [PATCH v5 03/10] drm/amdgpu: add new IOCTL for usermode queue
2023-07-06 12:35 [PATCH v5 00/10] AMDGPU Usermode queues Shashank Sharma
2023-07-06 12:35 ` [PATCH v5 01/10] drm/amdgpu: UAPI for user queue management Shashank Sharma
2023-07-06 12:35 ` [PATCH v5 02/10] drm/amdgpu: add usermode queue base code Shashank Sharma
@ 2023-07-06 12:35 ` Shashank Sharma
2023-07-06 13:20 ` Christian König
2023-07-06 12:35 ` [PATCH v5 04/10] drm/amdgpu: create GFX-gen11 " Shashank Sharma
` (6 subsequent siblings)
9 siblings, 1 reply; 50+ messages in thread
From: Shashank Sharma @ 2023-07-06 12:35 UTC (permalink / raw)
To: amd-gfx; +Cc: Alex Deucher, Christian Koenig, arvind.yadav, Shashank Sharma
This patch adds:
- A new IOCTL function to create and destroy
- A new structure to keep all the user queue data in one place.
- A function to generate unique index for the queue.
V1: Worked on review comments from RFC patch series:
- Alex: Keep a list of queues, instead of single queue per process.
- Christian: Use the queue manager instead of global ptrs,
Don't keep the queue structure in amdgpu_ctx
V2: Worked on review comments:
- Christian:
- Formatting of text
- There is no need for queuing of userqueues, with idr in place
- Alex:
- Remove use_doorbell, its unnecessary
- Reuse amdgpu_mqd_props for saving mqd fields
- Code formatting and re-arrangement
V3:
- Integration with doorbell manager
V4:
- Accommodate MQD union related changes in UAPI (Alex)
- Do not set the queue size twice (Bas)
V5:
- Remove wrapper functions for queue indexing (Christian)
- Do not save the queue id/idr in queue itself (Christian)
- Move the idr allocation in the IP independent generic space
(Christian)
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: Christian Koenig <christian.koenig@amd.com>
Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 1 +
drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 110 ++++++++++++++++++
.../gpu/drm/amd/include/amdgpu_userqueue.h | 2 +
3 files changed, 113 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 4c5e44d41652..43cb37f097af 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -2786,6 +2786,7 @@ const struct drm_ioctl_desc amdgpu_ioctls_kms[] = {
DRM_IOCTL_DEF_DRV(AMDGPU_GEM_VA, amdgpu_gem_va_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(AMDGPU_GEM_OP, amdgpu_gem_op_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(AMDGPU_GEM_USERPTR, amdgpu_gem_userptr_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(AMDGPU_USERQ, amdgpu_userq_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
};
static const struct drm_driver amdgpu_kms_driver = {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
index effc0c7c02cf..e37b5da5a0d0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
@@ -23,6 +23,116 @@
*/
#include "amdgpu.h"
+#include "amdgpu_vm.h"
+#include "amdgpu_userqueue.h"
+
+static struct amdgpu_usermode_queue *
+amdgpu_userqueue_find(struct amdgpu_userq_mgr *uq_mgr, int qid)
+{
+ return idr_find(&uq_mgr->userq_idr, qid);
+}
+
+static int
+amdgpu_userqueue_destroy(struct drm_file *filp, int queue_id)
+{
+ struct amdgpu_fpriv *fpriv = filp->driver_priv;
+ struct amdgpu_userq_mgr *uq_mgr = &fpriv->userq_mgr;
+ const struct amdgpu_userq_funcs *uq_funcs;
+ struct amdgpu_usermode_queue *queue;
+
+ mutex_lock(&uq_mgr->userq_mutex);
+
+ queue = amdgpu_userqueue_find(uq_mgr, queue_id);
+ if (!queue) {
+ DRM_DEBUG_DRIVER("Invalid queue id to destroy\n");
+ mutex_unlock(&uq_mgr->userq_mutex);
+ return -EINVAL;
+ }
+ uq_funcs = uq_mgr->userq_funcs[queue->queue_type];
+ uq_funcs->mqd_destroy(uq_mgr, queue);
+ idr_remove(&uq_mgr->userq_idr, queue_id);
+ kfree(queue);
+
+ mutex_unlock(&uq_mgr->userq_mutex);
+ return 0;
+}
+
+static int
+amdgpu_userqueue_create(struct drm_file *filp, union drm_amdgpu_userq *args)
+{
+ struct amdgpu_fpriv *fpriv = filp->driver_priv;
+ struct amdgpu_userq_mgr *uq_mgr = &fpriv->userq_mgr;
+ const struct amdgpu_userq_funcs *uq_funcs;
+ struct amdgpu_usermode_queue *queue;
+ int qid, r = 0;
+
+ mutex_lock(&uq_mgr->userq_mutex);
+
+ uq_funcs = uq_mgr->userq_funcs[args->in.ip_type];
+ if (!uq_funcs) {
+ DRM_ERROR("Usermode queue is not supported for this IP (%u)\n", args->in.ip_type);
+ r = -EINVAL;
+ goto unlock;
+ }
+
+ queue = kzalloc(sizeof(struct amdgpu_usermode_queue), GFP_KERNEL);
+ if (!queue) {
+ DRM_ERROR("Failed to allocate memory for queue\n");
+ r = -ENOMEM;
+ goto unlock;
+ }
+ queue->doorbell_handle = args->in.doorbell_handle;
+ queue->doorbell_index = args->in.doorbell_offset;
+ queue->queue_type = args->in.ip_type;
+ queue->flags = args->in.flags;
+ queue->vm = &fpriv->vm;
+
+ r = uq_funcs->mqd_create(uq_mgr, &args->in, queue);
+ if (r) {
+ DRM_ERROR("Failed to create Queue\n");
+ goto unlock;
+ }
+
+ qid = idr_alloc(&uq_mgr->userq_idr, queue, 1, AMDGPU_MAX_USERQ_COUNT, GFP_KERNEL);
+ if (qid < 0) {
+ DRM_ERROR("Failed to allocate a queue id\n");
+ uq_funcs->mqd_destroy(uq_mgr, queue);
+ r = -ENOMEM;
+ goto unlock;
+ }
+ args->out.queue_id = qid;
+
+unlock:
+ mutex_unlock(&uq_mgr->userq_mutex);
+ return r;
+}
+
+int amdgpu_userq_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *filp)
+{
+ union drm_amdgpu_userq *args = data;
+ int r = 0;
+
+ switch (args->in.op) {
+ case AMDGPU_USERQ_OP_CREATE:
+ r = amdgpu_userqueue_create(filp->driver_priv, args);
+ if (r)
+ DRM_ERROR("Failed to create usermode queue\n");
+ break;
+
+ case AMDGPU_USERQ_OP_FREE:
+ r = amdgpu_userqueue_destroy(filp, args->in.queue_id);
+ if (r)
+ DRM_ERROR("Failed to destroy usermode queue\n");
+ break;
+
+ default:
+ DRM_ERROR("Invalid user queue op specified: %d\n", args->in.op);
+ return -EINVAL;
+ }
+
+ return r;
+}
int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct amdgpu_device *adev)
{
diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
index 79ffa131a514..55ed6512a565 100644
--- a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
+++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
@@ -55,6 +55,8 @@ struct amdgpu_userq_mgr {
const struct amdgpu_userq_funcs *userq_funcs[AMDGPU_HW_IP_NUM];
};
+int amdgpu_userq_ioctl(struct drm_device *dev, void *data, struct drm_file *filp);
+
int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct amdgpu_device *adev);
void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr);
--
2.40.1
^ permalink raw reply related [flat|nested] 50+ messages in thread
* [PATCH v5 04/10] drm/amdgpu: create GFX-gen11 usermode queue
2023-07-06 12:35 [PATCH v5 00/10] AMDGPU Usermode queues Shashank Sharma
` (2 preceding siblings ...)
2023-07-06 12:35 ` [PATCH v5 03/10] drm/amdgpu: add new IOCTL for usermode queue Shashank Sharma
@ 2023-07-06 12:35 ` Shashank Sharma
2023-07-06 13:22 ` Christian König
` (2 more replies)
2023-07-06 12:35 ` [PATCH v5 05/10] drm/amdgpu: create context space for " Shashank Sharma
` (5 subsequent siblings)
9 siblings, 3 replies; 50+ messages in thread
From: Shashank Sharma @ 2023-07-06 12:35 UTC (permalink / raw)
To: amd-gfx; +Cc: Alex Deucher, Christian Koenig, arvind.yadav, Shashank Sharma
A Memory queue descriptor (MQD) of a userqueue defines it in
the hw's context. As MQD format can vary between different
graphics IPs, we need gfx GEN specific handlers to create MQDs.
This patch:
- Introduces MQD handler functions for the usermode queues.
- Adds new functions to create and destroy userqueue MQD for
GFX-GEN-11 IP
V1: Worked on review comments from Alex:
- Make MQD functions GEN and IP specific
V2: Worked on review comments from Alex:
- Reuse the existing adev->mqd[ip] for MQD creation
- Formatting and arrangement of code
V3:
- Integration with doorbell manager
V4: Review comments addressed:
- Do not create a new file for userq, reuse gfx_v11_0.c (Alex)
- Align name of structure members (Luben)
- Don't break up the Cc tag list and the Sob tag list in commit
message (Luben)
V5:
- No need to reserve the bo for MQD (Christian).
- Some more changes to support IP specific MQD creation.
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: Christian Koenig <christian.koenig@amd.com>
Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
Signed-off-by: Arvind Yadav <arvind.yadav@amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 16 ++++
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 73 +++++++++++++++++++
.../gpu/drm/amd/include/amdgpu_userqueue.h | 7 ++
3 files changed, 96 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
index e37b5da5a0d0..bb774144c372 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
@@ -134,12 +134,28 @@ int amdgpu_userq_ioctl(struct drm_device *dev, void *data,
return r;
}
+extern const struct amdgpu_userq_funcs userq_gfx_v11_funcs;
+
+static void
+amdgpu_userqueue_setup_gfx(struct amdgpu_userq_mgr *uq_mgr)
+{
+ int maj;
+ struct amdgpu_device *adev = uq_mgr->adev;
+ uint32_t version = adev->ip_versions[GC_HWIP][0];
+
+ /* We support usermode queue only for GFX V11 as of now */
+ maj = IP_VERSION_MAJ(version);
+ if (maj == 11)
+ uq_mgr->userq_funcs[AMDGPU_HW_IP_GFX] = &userq_gfx_v11_funcs;
+}
+
int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct amdgpu_device *adev)
{
mutex_init(&userq_mgr->userq_mutex);
idr_init_base(&userq_mgr->userq_idr, 1);
userq_mgr->adev = adev;
+ amdgpu_userqueue_setup_gfx(userq_mgr);
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
index c4940b6ea1c4..e76e1b86b434 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -30,6 +30,7 @@
#include "amdgpu_psp.h"
#include "amdgpu_smu.h"
#include "amdgpu_atomfirmware.h"
+#include "amdgpu_userqueue.h"
#include "imu_v11_0.h"
#include "soc21.h"
#include "nvd.h"
@@ -6486,3 +6487,75 @@ const struct amdgpu_ip_block_version gfx_v11_0_ip_block =
.rev = 0,
.funcs = &gfx_v11_0_ip_funcs,
};
+
+static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
+ struct drm_amdgpu_userq_in *args_in,
+ struct amdgpu_usermode_queue *queue)
+{
+ struct amdgpu_device *adev = uq_mgr->adev;
+ struct amdgpu_mqd *mqd_gfx_generic = &adev->mqds[AMDGPU_HW_IP_GFX];
+ struct drm_amdgpu_userq_mqd_gfx_v11_0 mqd_user;
+ struct amdgpu_mqd_prop userq_props;
+ int r;
+
+ /* Incoming MQD parameters from userspace to be saved here */
+ memset(&mqd_user, 0, sizeof(mqd_user));
+
+ /* Structure to initialize MQD for userqueue using generic MQD init function */
+ memset(&userq_props, 0, sizeof(userq_props));
+
+ if (args_in->mqd_size != sizeof(struct drm_amdgpu_userq_mqd_gfx_v11_0)) {
+ DRM_ERROR("MQD size mismatch\n");
+ return -EINVAL;
+ }
+
+ if (copy_from_user(&mqd_user, u64_to_user_ptr(args_in->mqd), args_in->mqd_size)) {
+ DRM_ERROR("Failed to get user MQD\n");
+ return -EFAULT;
+ }
+
+ /* Create BO for actual Userqueue MQD now */
+ r = amdgpu_bo_create_kernel(adev, mqd_gfx_generic->mqd_size, PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_GTT,
+ &queue->mqd.obj,
+ &queue->mqd.gpu_addr,
+ &queue->mqd.cpu_ptr);
+ if (r) {
+ DRM_ERROR("Failed to allocate BO for userqueue (%d)", r);
+ return -ENOMEM;
+ }
+ memset(queue->mqd.cpu_ptr, 0, mqd_gfx_generic->mqd_size);
+
+ /* Initialize the MQD BO with user given values */
+ userq_props.wptr_gpu_addr = mqd_user.wptr_va;
+ userq_props.rptr_gpu_addr = mqd_user.rptr_va;
+ userq_props.queue_size = mqd_user.queue_size;
+ userq_props.hqd_base_gpu_addr = mqd_user.queue_va;
+ userq_props.mqd_gpu_addr = queue->mqd.gpu_addr;
+ userq_props.use_doorbell = true;
+
+ r = mqd_gfx_generic->init_mqd(adev, (void *)queue->mqd.cpu_ptr, &userq_props);
+ if (r) {
+ DRM_ERROR("Failed to initialize MQD for userqueue\n");
+ goto free_mqd;
+ }
+
+ return 0;
+
+free_mqd:
+ amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr, &queue->mqd.cpu_ptr);
+ return r;
+}
+
+static void
+gfx_v11_0_userq_mqd_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_queue *queue)
+{
+ struct amdgpu_userq_obj *mqd = &queue->mqd;
+
+ amdgpu_bo_free_kernel(&mqd->obj, &mqd->gpu_addr, &mqd->cpu_ptr);
+}
+
+const struct amdgpu_userq_funcs userq_gfx_v11_funcs = {
+ .mqd_create = gfx_v11_0_userq_mqd_create,
+ .mqd_destroy = gfx_v11_0_userq_mqd_destroy,
+};
diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
index 55ed6512a565..240f92796f00 100644
--- a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
+++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
@@ -29,6 +29,12 @@
struct amdgpu_mqd_prop;
+struct amdgpu_userq_obj {
+ void *cpu_ptr;
+ uint64_t gpu_addr;
+ struct amdgpu_bo *obj;
+};
+
struct amdgpu_usermode_queue {
int queue_type;
uint64_t doorbell_handle;
@@ -37,6 +43,7 @@ struct amdgpu_usermode_queue {
struct amdgpu_mqd_prop *userq_prop;
struct amdgpu_userq_mgr *userq_mgr;
struct amdgpu_vm *vm;
+ struct amdgpu_userq_obj mqd;
};
struct amdgpu_userq_funcs {
--
2.40.1
^ permalink raw reply related [flat|nested] 50+ messages in thread
* [PATCH v5 05/10] drm/amdgpu: create context space for usermode queue
2023-07-06 12:35 [PATCH v5 00/10] AMDGPU Usermode queues Shashank Sharma
` (3 preceding siblings ...)
2023-07-06 12:35 ` [PATCH v5 04/10] drm/amdgpu: create GFX-gen11 " Shashank Sharma
@ 2023-07-06 12:35 ` Shashank Sharma
2023-07-06 13:28 ` Christian König
2023-07-06 16:44 ` Alex Deucher
2023-07-06 12:35 ` [PATCH v5 06/10] drm/amdgpu: map usermode queue into MES Shashank Sharma
` (4 subsequent siblings)
9 siblings, 2 replies; 50+ messages in thread
From: Shashank Sharma @ 2023-07-06 12:35 UTC (permalink / raw)
To: amd-gfx; +Cc: Alex Deucher, Christian Koenig, arvind.yadav, Shashank Sharma
The FW expects us to allocate at least one page as context
space to process gang, process, GDS and FW related work.
This patch creates a joint object for the same, and calculates
GPU space offsets for each of these spaces.
V1: Addressed review comments on RFC patch:
Alex: Make this function IP specific
V2: Addressed review comments from Christian
- Allocate only one object for total FW space, and calculate
offsets for each of these objects.
V3: Integration with doorbell manager
V4: Review comments:
- Remove shadow from FW space list from cover letter (Alex)
- Alignment of macro (Luben)
V5: Merged patches 5 and 6 into this single patch
Addressed review comments:
- Use lower_32_bits instead of mask (Christian)
- gfx_v11_0 instead of gfx_v11 in function names (Alex)
- Shadow and GDS objects are now coming from userspace (Christian,
Alex)
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: Christian Koenig <christian.koenig@amd.com>
Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
Signed-off-by: Arvind Yadav <arvind.yadav@amd.com>
---
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 62 +++++++++++++++++++
.../gpu/drm/amd/include/amdgpu_userqueue.h | 4 ++
2 files changed, 66 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
index e76e1b86b434..7d3b19e08bbb 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -61,6 +61,9 @@
#define regCGTT_WD_CLK_CTRL_BASE_IDX 1
#define regRLC_RLCS_BOOTLOAD_STATUS_gc_11_0_1 0x4e7e
#define regRLC_RLCS_BOOTLOAD_STATUS_gc_11_0_1_BASE_IDX 1
+#define AMDGPU_USERQ_PROC_CTX_SZ PAGE_SIZE
+#define AMDGPU_USERQ_GANG_CTX_SZ PAGE_SIZE
+#define AMDGPU_USERQ_FW_CTX_SZ PAGE_SIZE
MODULE_FIRMWARE("amdgpu/gc_11_0_0_pfp.bin");
MODULE_FIRMWARE("amdgpu/gc_11_0_0_me.bin");
@@ -6488,6 +6491,57 @@ const struct amdgpu_ip_block_version gfx_v11_0_ip_block =
.funcs = &gfx_v11_0_ip_funcs,
};
+static void gfx_v11_0_userq_destroy_ctx_space(struct amdgpu_userq_mgr *uq_mgr,
+ struct amdgpu_usermode_queue *queue)
+{
+ struct amdgpu_userq_obj *ctx = &queue->fw_obj;
+
+ amdgpu_bo_free_kernel(&ctx->obj, &ctx->gpu_addr, &ctx->cpu_ptr);
+}
+
+static int gfx_v11_0_userq_create_ctx_space(struct amdgpu_userq_mgr *uq_mgr,
+ struct amdgpu_usermode_queue *queue,
+ struct drm_amdgpu_userq_mqd_gfx_v11_0 *mqd_user)
+{
+ struct amdgpu_device *adev = uq_mgr->adev;
+ struct amdgpu_userq_obj *ctx = &queue->fw_obj;
+ struct v11_gfx_mqd *mqd = queue->mqd.cpu_ptr;
+ int r, size;
+
+ /*
+ * The FW expects at least one page space allocated for
+ * process ctx, gang ctx and fw ctx each. Create an object
+ * for the same.
+ */
+ size = AMDGPU_USERQ_PROC_CTX_SZ + AMDGPU_USERQ_FW_CTX_SZ +
+ AMDGPU_USERQ_GANG_CTX_SZ;
+ r = amdgpu_bo_create_kernel(adev, size, PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_GTT,
+ &ctx->obj,
+ &ctx->gpu_addr,
+ &ctx->cpu_ptr);
+ if (r) {
+ DRM_ERROR("Failed to allocate ctx space bo for userqueue, err:%d\n", r);
+ return r;
+ }
+
+ queue->proc_ctx_gpu_addr = ctx->gpu_addr;
+ queue->gang_ctx_gpu_addr = queue->proc_ctx_gpu_addr + AMDGPU_USERQ_PROC_CTX_SZ;
+ queue->fw_ctx_gpu_addr = queue->gang_ctx_gpu_addr + AMDGPU_USERQ_GANG_CTX_SZ;
+
+ mqd->fw_work_area_base_lo = lower_32_bits(queue->fw_ctx_gpu_addr);
+ mqd->fw_work_area_base_lo = upper_32_bits(queue->fw_ctx_gpu_addr);
+
+ /* Shadow and GDS objects come directly from userspace */
+ mqd->shadow_base_lo = lower_32_bits(mqd_user->shadow_va);
+ mqd->shadow_base_hi = upper_32_bits(mqd_user->shadow_va);
+
+ mqd->gds_bkup_base_lo = lower_32_bits(mqd_user->gds_va);
+ mqd->gds_bkup_base_hi = upper_32_bits(mqd_user->gds_va);
+
+ return 0;
+}
+
static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
struct drm_amdgpu_userq_in *args_in,
struct amdgpu_usermode_queue *queue)
@@ -6540,6 +6594,13 @@ static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
goto free_mqd;
}
+ /* Create BO for FW operations */
+ r = gfx_v11_0_userq_create_ctx_space(uq_mgr, queue, &mqd_user);
+ if (r) {
+ DRM_ERROR("Failed to allocate BO for userqueue (%d)", r);
+ goto free_mqd;
+ }
+
return 0;
free_mqd:
@@ -6552,6 +6613,7 @@ gfx_v11_0_userq_mqd_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_userm
{
struct amdgpu_userq_obj *mqd = &queue->mqd;
+ gfx_v11_0_userq_destroy_ctx_space(uq_mgr, queue);
amdgpu_bo_free_kernel(&mqd->obj, &mqd->gpu_addr, &mqd->cpu_ptr);
}
diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
index 240f92796f00..a5cdb319193d 100644
--- a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
+++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
@@ -40,10 +40,14 @@ struct amdgpu_usermode_queue {
uint64_t doorbell_handle;
uint64_t doorbell_index;
uint64_t flags;
+ uint64_t proc_ctx_gpu_addr;
+ uint64_t gang_ctx_gpu_addr;
+ uint64_t fw_ctx_gpu_addr;
struct amdgpu_mqd_prop *userq_prop;
struct amdgpu_userq_mgr *userq_mgr;
struct amdgpu_vm *vm;
struct amdgpu_userq_obj mqd;
+ struct amdgpu_userq_obj fw_obj;
};
struct amdgpu_userq_funcs {
--
2.40.1
^ permalink raw reply related [flat|nested] 50+ messages in thread
* [PATCH v5 06/10] drm/amdgpu: map usermode queue into MES
2023-07-06 12:35 [PATCH v5 00/10] AMDGPU Usermode queues Shashank Sharma
` (4 preceding siblings ...)
2023-07-06 12:35 ` [PATCH v5 05/10] drm/amdgpu: create context space for " Shashank Sharma
@ 2023-07-06 12:35 ` Shashank Sharma
2023-07-06 14:47 ` Christian König
2023-07-06 16:52 ` Alex Deucher
2023-07-06 12:35 ` [PATCH v5 07/10] drm/amdgpu: map wptr BO into GART Shashank Sharma
` (3 subsequent siblings)
9 siblings, 2 replies; 50+ messages in thread
From: Shashank Sharma @ 2023-07-06 12:35 UTC (permalink / raw)
To: amd-gfx; +Cc: Alex Deucher, Christian Koenig, arvind.yadav, Shashank Sharma
This patch adds new functions to map/unmap a usermode queue into
the FW, using the MES ring. As soon as this mapping is done, the
queue would be considered ready to accept the workload.
V1: Addressed review comments from Alex on the RFC patch series
- Map/Unmap should be IP specific.
V2:
Addressed review comments from Christian:
- Fix the wptr_mc_addr calculation (moved into another patch)
Addressed review comments from Alex:
- Do not add fptrs for map/unmap
V3: Integration with doorbell manager
V4: Rebase
V5: Use gfx_v11_0 for function names (Alex)
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: Christian Koenig <christian.koenig@amd.com>
Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
---
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 70 ++++++++++++++++++++++++++
1 file changed, 70 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
index 7d3b19e08bbb..b4a0f26a0e8c 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -6491,6 +6491,65 @@ const struct amdgpu_ip_block_version gfx_v11_0_ip_block =
.funcs = &gfx_v11_0_ip_funcs,
};
+static void gfx_v11_0_userq_unmap(struct amdgpu_userq_mgr *uq_mgr,
+ struct amdgpu_usermode_queue *queue)
+{
+ struct amdgpu_device *adev = uq_mgr->adev;
+ struct mes_remove_queue_input queue_input;
+ int r;
+
+ memset(&queue_input, 0x0, sizeof(struct mes_remove_queue_input));
+ queue_input.doorbell_offset = queue->doorbell_index;
+ queue_input.gang_context_addr = queue->gang_ctx_gpu_addr;
+
+ amdgpu_mes_lock(&adev->mes);
+ r = adev->mes.funcs->remove_hw_queue(&adev->mes, &queue_input);
+ amdgpu_mes_unlock(&adev->mes);
+ if (r)
+ DRM_ERROR("Failed to unmap queue in HW, err (%d)\n", r);
+}
+
+static int gfx_v11_0_userq_map(struct amdgpu_userq_mgr *uq_mgr,
+ struct amdgpu_usermode_queue *queue,
+ struct amdgpu_mqd_prop *userq_props)
+{
+ struct amdgpu_device *adev = uq_mgr->adev;
+ struct mes_add_queue_input queue_input;
+ int r;
+
+ memset(&queue_input, 0x0, sizeof(struct mes_add_queue_input));
+
+ queue_input.process_va_start = 0;
+ queue_input.process_va_end = (adev->vm_manager.max_pfn - 1) << AMDGPU_GPU_PAGE_SHIFT;
+ queue_input.process_quantum = 100000; /* 10ms */
+ queue_input.gang_quantum = 10000; /* 1ms */
+ queue_input.paging = false;
+
+ queue_input.gang_context_addr = queue->gang_ctx_gpu_addr;
+ queue_input.process_context_addr = queue->proc_ctx_gpu_addr;
+ queue_input.inprocess_gang_priority = AMDGPU_MES_PRIORITY_LEVEL_NORMAL;
+ queue_input.gang_global_priority_level = AMDGPU_MES_PRIORITY_LEVEL_NORMAL;
+
+ queue_input.process_id = queue->vm->pasid;
+ queue_input.queue_type = queue->queue_type;
+ queue_input.mqd_addr = queue->mqd.gpu_addr;
+ queue_input.wptr_addr = userq_props->wptr_gpu_addr;
+ queue_input.queue_size = userq_props->queue_size >> 2;
+ queue_input.doorbell_offset = userq_props->doorbell_index;
+ queue_input.page_table_base_addr = amdgpu_gmc_pd_addr(queue->vm->root.bo);
+
+ amdgpu_mes_lock(&adev->mes);
+ r = adev->mes.funcs->add_hw_queue(&adev->mes, &queue_input);
+ amdgpu_mes_unlock(&adev->mes);
+ if (r) {
+ DRM_ERROR("Failed to map queue in HW, err (%d)\n", r);
+ return r;
+ }
+
+ DRM_DEBUG_DRIVER("Queue (doorbell:%d) mapped successfully\n", userq_props->doorbell_index);
+ return 0;
+}
+
static void gfx_v11_0_userq_destroy_ctx_space(struct amdgpu_userq_mgr *uq_mgr,
struct amdgpu_usermode_queue *queue)
{
@@ -6601,8 +6660,18 @@ static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
goto free_mqd;
}
+ /* Map userqueue into FW using MES */
+ r = gfx_v11_0_userq_map(uq_mgr, queue, &userq_props);
+ if (r) {
+ DRM_ERROR("Failed to init MQD\n");
+ goto free_ctx;
+ }
+
return 0;
+free_ctx:
+ gfx_v11_0_userq_destroy_ctx_space(uq_mgr, queue);
+
free_mqd:
amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr, &queue->mqd.cpu_ptr);
return r;
@@ -6613,6 +6682,7 @@ gfx_v11_0_userq_mqd_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_userm
{
struct amdgpu_userq_obj *mqd = &queue->mqd;
+ gfx_v11_0_userq_unmap(uq_mgr, queue);
gfx_v11_0_userq_destroy_ctx_space(uq_mgr, queue);
amdgpu_bo_free_kernel(&mqd->obj, &mqd->gpu_addr, &mqd->cpu_ptr);
}
--
2.40.1
^ permalink raw reply related [flat|nested] 50+ messages in thread
* [PATCH v5 07/10] drm/amdgpu: map wptr BO into GART
2023-07-06 12:35 [PATCH v5 00/10] AMDGPU Usermode queues Shashank Sharma
` (5 preceding siblings ...)
2023-07-06 12:35 ` [PATCH v5 06/10] drm/amdgpu: map usermode queue into MES Shashank Sharma
@ 2023-07-06 12:35 ` Shashank Sharma
2023-07-06 12:36 ` [PATCH v5 08/10] drm/amdgpu: generate doorbell index for userqueue Shashank Sharma
` (2 subsequent siblings)
9 siblings, 0 replies; 50+ messages in thread
From: Shashank Sharma @ 2023-07-06 12:35 UTC (permalink / raw)
To: amd-gfx; +Cc: Alex Deucher, Christian Koenig, arvind.yadav, Shashank Sharma
To support oversubscription, MES FW expects WPTR BOs to
be mapped into GART, before they are submitted to usermode
queues. This patch adds a function for the same.
V4: fix the wptr value before mapping lookup (Bas, Christian).
V5: Addressed review comments from Christian:
- Either pin object or allocate from GART, but not both.
- All the handling must be done with the VM locks held.
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: Christian Koenig <christian.koenig@amd.com>
Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
Signed-off-by: Arvind Yadav <arvind.yadav@amd.com>
---
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 81 +++++++++++++++++++
.../gpu/drm/amd/include/amdgpu_userqueue.h | 1 +
2 files changed, 82 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
index b4a0f26a0e8c..afaeecb9940a 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -6491,6 +6491,79 @@ const struct amdgpu_ip_block_version gfx_v11_0_ip_block =
.funcs = &gfx_v11_0_ip_funcs,
};
+static int
+gfx_v11_0_map_gtt_bo_to_gart(struct amdgpu_device *adev, struct amdgpu_bo *bo)
+{
+ int ret;
+
+ ret = amdgpu_bo_reserve(bo, true);
+ if (ret) {
+ DRM_ERROR("Failed to reserve bo. ret %d\n", ret);
+ goto err_reserve_bo_failed;
+ }
+
+ ret = amdgpu_ttm_alloc_gart(&bo->tbo);
+ if (ret) {
+ DRM_ERROR("Failed to bind bo to GART. ret %d\n", ret);
+ goto err_map_bo_gart_failed;
+ }
+
+ amdgpu_bo_unreserve(bo);
+ bo = amdgpu_bo_ref(bo);
+
+ return 0;
+
+err_map_bo_gart_failed:
+ amdgpu_bo_unreserve(bo);
+err_reserve_bo_failed:
+ return ret;
+}
+
+static int
+gfx_v11_0_create_wptr_mapping(struct amdgpu_device *adev,
+ struct amdgpu_usermode_queue *queue,
+ uint64_t wptr)
+{
+ struct amdgpu_bo_va_mapping *wptr_mapping;
+ struct amdgpu_vm *wptr_vm;
+ struct amdgpu_bo *wptr_bo = NULL;
+ int ret;
+
+ mutex_lock(&queue->vm->eviction_lock);
+ wptr_vm = queue->vm;
+ ret = amdgpu_bo_reserve(wptr_vm->root.bo, false);
+ if (ret)
+ goto unlock;
+
+ wptr &= AMDGPU_GMC_HOLE_MASK;
+ wptr_mapping = amdgpu_vm_bo_lookup_mapping(wptr_vm, wptr >> PAGE_SHIFT);
+ amdgpu_bo_unreserve(wptr_vm->root.bo);
+ if (!wptr_mapping) {
+ DRM_ERROR("Failed to lookup wptr bo\n");
+ ret = -EINVAL;
+ goto unlock;
+ }
+
+ wptr_bo = wptr_mapping->bo_va->base.bo;
+ if (wptr_bo->tbo.base.size > PAGE_SIZE) {
+ DRM_ERROR("Requested GART mapping for wptr bo larger than one page\n");
+ ret = -EINVAL;
+ goto unlock;
+ }
+
+ ret = gfx_v11_0_map_gtt_bo_to_gart(adev, wptr_bo);
+ if (ret) {
+ DRM_ERROR("Failed to map wptr bo to GART\n");
+ goto unlock;
+ }
+
+ queue->wptr_mc_addr = wptr_bo->tbo.resource->start << PAGE_SHIFT;
+
+unlock:
+ mutex_unlock(&queue->vm->eviction_lock);
+ return ret;
+}
+
static void gfx_v11_0_userq_unmap(struct amdgpu_userq_mgr *uq_mgr,
struct amdgpu_usermode_queue *queue)
{
@@ -6537,6 +6610,7 @@ static int gfx_v11_0_userq_map(struct amdgpu_userq_mgr *uq_mgr,
queue_input.queue_size = userq_props->queue_size >> 2;
queue_input.doorbell_offset = userq_props->doorbell_index;
queue_input.page_table_base_addr = amdgpu_gmc_pd_addr(queue->vm->root.bo);
+ queue_input.wptr_mc_addr = queue->wptr_mc_addr;
amdgpu_mes_lock(&adev->mes);
r = adev->mes.funcs->add_hw_queue(&adev->mes, &queue_input);
@@ -6660,6 +6734,13 @@ static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
goto free_mqd;
}
+ /* FW expects WPTR BOs to be mapped into GART */
+ r = gfx_v11_0_create_wptr_mapping(adev, queue, userq_props.wptr_gpu_addr);
+ if (r) {
+ DRM_ERROR("Failed to create WPTR mapping\n");
+ goto free_ctx;
+ }
+
/* Map userqueue into FW using MES */
r = gfx_v11_0_userq_map(uq_mgr, queue, &userq_props);
if (r) {
diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
index a5cdb319193d..f530df3ebcc0 100644
--- a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
+++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
@@ -39,6 +39,7 @@ struct amdgpu_usermode_queue {
int queue_type;
uint64_t doorbell_handle;
uint64_t doorbell_index;
+ uint64_t wptr_mc_addr;
uint64_t flags;
uint64_t proc_ctx_gpu_addr;
uint64_t gang_ctx_gpu_addr;
--
2.40.1
^ permalink raw reply related [flat|nested] 50+ messages in thread
* [PATCH v5 08/10] drm/amdgpu: generate doorbell index for userqueue
2023-07-06 12:35 [PATCH v5 00/10] AMDGPU Usermode queues Shashank Sharma
` (6 preceding siblings ...)
2023-07-06 12:35 ` [PATCH v5 07/10] drm/amdgpu: map wptr BO into GART Shashank Sharma
@ 2023-07-06 12:36 ` Shashank Sharma
2023-07-07 7:15 ` Christian König
2023-07-06 12:36 ` [PATCH v5 09/10] drm/amdgpu: cleanup leftover queues Shashank Sharma
2023-07-06 12:36 ` [PATCH v5 10/10] drm/amdgpu: add delay after userqueue mapping Shashank Sharma
9 siblings, 1 reply; 50+ messages in thread
From: Shashank Sharma @ 2023-07-06 12:36 UTC (permalink / raw)
To: amd-gfx; +Cc: Alex Deucher, Christian Koenig, arvind.yadav, Shashank Sharma
The userspace sends us the doorbell object and the relative doobell
index in the object to be used for the usermode queue, but the FW
expects the absolute doorbell index on the PCI BAR in the MQD. This
patch adds a function to convert this relative doorbell index to
absolute doorbell index.
This patch is dependent on the doorbell manager series:
Link: https://patchwork.freedesktop.org/series/115802/
V5: Fix the db object reference leak (Christian)
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: Christian Koenig <christian.koenig@amd.com>
Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 34 +++++++++++++++++++
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 1 +
2 files changed, 35 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
index bb774144c372..61064266c4f8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
@@ -32,6 +32,31 @@ amdgpu_userqueue_find(struct amdgpu_userq_mgr *uq_mgr, int qid)
return idr_find(&uq_mgr->userq_idr, qid);
}
+static uint64_t
+amdgpu_userqueue_get_doorbell_index(struct amdgpu_userq_mgr *uq_mgr,
+ struct amdgpu_usermode_queue *queue,
+ struct drm_file *filp,
+ uint32_t doorbell_offset)
+{
+ struct drm_gem_object *gobj;
+ struct amdgpu_bo *db_bo;
+ uint64_t index;
+
+ gobj = drm_gem_object_lookup(filp, queue->doorbell_handle);
+ if (gobj == NULL) {
+ DRM_ERROR("Can't find GEM object for doorbell\n");
+ return -EINVAL;
+ }
+
+ db_bo = amdgpu_bo_ref(gem_to_amdgpu_bo(gobj));
+ drm_gem_object_put(gobj);
+
+ index = amdgpu_doorbell_index_on_bar(uq_mgr->adev, db_bo, doorbell_offset);
+ amdgpu_bo_unref(&db_bo);
+ DRM_DEBUG_DRIVER("[Usermode queues] doorbell index=%lld\n", index);
+ return index;
+}
+
static int
amdgpu_userqueue_destroy(struct drm_file *filp, int queue_id)
{
@@ -64,6 +89,7 @@ amdgpu_userqueue_create(struct drm_file *filp, union drm_amdgpu_userq *args)
struct amdgpu_userq_mgr *uq_mgr = &fpriv->userq_mgr;
const struct amdgpu_userq_funcs *uq_funcs;
struct amdgpu_usermode_queue *queue;
+ uint64_t index;
int qid, r = 0;
mutex_lock(&uq_mgr->userq_mutex);
@@ -87,6 +113,14 @@ amdgpu_userqueue_create(struct drm_file *filp, union drm_amdgpu_userq *args)
queue->flags = args->in.flags;
queue->vm = &fpriv->vm;
+ /* Convert relative doorbell offset into absolute doorbell index */
+ index = amdgpu_userqueue_get_doorbell_index(uq_mgr, queue, filp, args->in.doorbell_offset);
+ if (index == (uint64_t)-EINVAL) {
+ DRM_ERROR("Failed to get doorbell for queue\n");
+ goto unlock;
+ }
+ queue->doorbell_index = index;
+
r = uq_funcs->mqd_create(uq_mgr, &args->in, queue);
if (r) {
DRM_ERROR("Failed to create Queue\n");
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
index afaeecb9940a..8edb020683a1 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -6719,6 +6719,7 @@ static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
userq_props.queue_size = mqd_user.queue_size;
userq_props.hqd_base_gpu_addr = mqd_user.queue_va;
userq_props.mqd_gpu_addr = queue->mqd.gpu_addr;
+ userq_props.doorbell_index = queue->doorbell_index;
userq_props.use_doorbell = true;
r = mqd_gfx_generic->init_mqd(adev, (void *)queue->mqd.cpu_ptr, &userq_props);
--
2.40.1
^ permalink raw reply related [flat|nested] 50+ messages in thread
* [PATCH v5 09/10] drm/amdgpu: cleanup leftover queues
2023-07-06 12:35 [PATCH v5 00/10] AMDGPU Usermode queues Shashank Sharma
` (7 preceding siblings ...)
2023-07-06 12:36 ` [PATCH v5 08/10] drm/amdgpu: generate doorbell index for userqueue Shashank Sharma
@ 2023-07-06 12:36 ` Shashank Sharma
2023-07-07 7:17 ` Christian König
2023-07-06 12:36 ` [PATCH v5 10/10] drm/amdgpu: add delay after userqueue mapping Shashank Sharma
9 siblings, 1 reply; 50+ messages in thread
From: Shashank Sharma @ 2023-07-06 12:36 UTC (permalink / raw)
To: amd-gfx
Cc: Alex Deucher, Bas Nieuwenhuizen, Christian Koenig, arvind.yadav,
Shashank Sharma
This patch adds code to cleanup any leftover userqueues which
a user might have missed to destroy due to a crash or any other
programming error.
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: Christian Koenig <christian.koenig@amd.com>
Suggested-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Signed-off-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 31 ++++++++++++++++---
1 file changed, 26 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
index 61064266c4f8..6e32e2854a58 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
@@ -57,12 +57,23 @@ amdgpu_userqueue_get_doorbell_index(struct amdgpu_userq_mgr *uq_mgr,
return index;
}
+static void
+amdgpu_userqueue_cleanup(struct amdgpu_userq_mgr *uq_mgr,
+ struct amdgpu_usermode_queue *queue,
+ int queue_id)
+{
+ const struct amdgpu_userq_funcs *uq_funcs = uq_mgr->userq_funcs[queue->queue_type];
+
+ uq_funcs->mqd_destroy(uq_mgr, queue);
+ idr_remove(&uq_mgr->userq_idr, queue_id);
+ kfree(queue);
+}
+
static int
amdgpu_userqueue_destroy(struct drm_file *filp, int queue_id)
{
struct amdgpu_fpriv *fpriv = filp->driver_priv;
struct amdgpu_userq_mgr *uq_mgr = &fpriv->userq_mgr;
- const struct amdgpu_userq_funcs *uq_funcs;
struct amdgpu_usermode_queue *queue;
mutex_lock(&uq_mgr->userq_mutex);
@@ -73,11 +84,8 @@ amdgpu_userqueue_destroy(struct drm_file *filp, int queue_id)
mutex_unlock(&uq_mgr->userq_mutex);
return -EINVAL;
}
- uq_funcs = uq_mgr->userq_funcs[queue->queue_type];
- uq_funcs->mqd_destroy(uq_mgr, queue);
- idr_remove(&uq_mgr->userq_idr, queue_id);
- kfree(queue);
+ amdgpu_userqueue_cleanup(uq_mgr, queue, queue_id);
mutex_unlock(&uq_mgr->userq_mutex);
return 0;
}
@@ -193,8 +201,21 @@ int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct amdgpu_devi
return 0;
}
+static int amdgpu_userqueue_cleanup_residue(int queue_id, void *ptr, void *data)
+{
+ struct amdgpu_userq_mgr *uq_mgr = data;
+ struct amdgpu_usermode_queue *queue = ptr;
+
+ amdgpu_userqueue_cleanup(uq_mgr, queue, queue_id);
+ return 0;
+}
+
void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr)
{
+ idr_for_each(&userq_mgr->userq_idr,
+ amdgpu_userqueue_cleanup_residue,
+ userq_mgr);
+
idr_destroy(&userq_mgr->userq_idr);
mutex_destroy(&userq_mgr->userq_mutex);
}
--
2.40.1
^ permalink raw reply related [flat|nested] 50+ messages in thread
* [PATCH v5 10/10] drm/amdgpu: add delay after userqueue mapping
2023-07-06 12:35 [PATCH v5 00/10] AMDGPU Usermode queues Shashank Sharma
` (8 preceding siblings ...)
2023-07-06 12:36 ` [PATCH v5 09/10] drm/amdgpu: cleanup leftover queues Shashank Sharma
@ 2023-07-06 12:36 ` Shashank Sharma
2023-07-06 17:41 ` Alex Deucher
9 siblings, 1 reply; 50+ messages in thread
From: Shashank Sharma @ 2023-07-06 12:36 UTC (permalink / raw)
To: amd-gfx; +Cc: Alex Deucher, Christian Koenig, arvind.yadav, Shashank Sharma
It has been observed that the MES FW needs 250-300us to map the gfx
userqueue, and if the user rings the doorbell before this duration,
the FW never recognizes the work. This patch adds the delay of 300
us after the queue mapping.
V1: Moved the delay from userspace IOCTL to kernel (Alex).
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: Christian Koenig <christian.koenig@amd.com>
Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
Signed-off-by: Arvind Yadav <arvind.yadav@amd.com>
---
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
index 8edb020683a1..78b58c5d0fd8 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -25,6 +25,7 @@
#include <linux/firmware.h>
#include <linux/module.h>
#include <linux/pci.h>
+#include <linux/delay.h>
#include "amdgpu.h"
#include "amdgpu_gfx.h"
#include "amdgpu_psp.h"
@@ -6749,6 +6750,12 @@ static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
goto free_ctx;
}
+ /*
+ * It has been observed that HWS needs appx 250-300us to map the queue, and the
+ * user needs to wait this duration before ringing the doorbell, or else the FW
+ * will never recognize the work.
+ */
+ udelay(300);
return 0;
free_ctx:
--
2.40.1
^ permalink raw reply related [flat|nested] 50+ messages in thread
* Re: [PATCH v5 02/10] drm/amdgpu: add usermode queue base code
2023-07-06 12:35 ` [PATCH v5 02/10] drm/amdgpu: add usermode queue base code Shashank Sharma
@ 2023-07-06 12:46 ` Christian König
2023-07-06 16:36 ` Alex Deucher
1 sibling, 0 replies; 50+ messages in thread
From: Christian König @ 2023-07-06 12:46 UTC (permalink / raw)
To: Shashank Sharma, amd-gfx; +Cc: Alex Deucher, arvind.yadav
Am 06.07.23 um 14:35 schrieb Shashank Sharma:
> This patch adds skeleton code for amdgpu usermode queue.
> It contains:
> - A new files with init functions of usermode queues.
> - A queue context manager in driver private data.
>
> V1: Worked on design review comments from RFC patch series:
> (https://patchwork.freedesktop.org/series/112214/)
> - Alex: Keep a list of queues, instead of single queue per process.
> - Christian: Use the queue manager instead of global ptrs,
> Don't keep the queue structure in amdgpu_ctx
>
> V2:
> - Reformatted code, split the big patch into two
>
> V3:
> - Integration with doorbell manager
>
> V4:
> - Align the structure member names to the largest member's column
> (Luben)
> - Added SPDX license (Luben)
>
> V5:
> - Do not add amdgpu.h in amdgpu_userqueue.h (Christian).
> - Move struct amdgpu_userq_mgr into amdgpu_userqueue.h (Christian).
>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Christian Koenig <christian.koenig@amd.com>
> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
> ---
> drivers/gpu/drm/amd/amdgpu/Makefile | 2 +
> drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 +
> drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 1 +
> drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 6 ++
> drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 40 ++++++++++++
> .../gpu/drm/amd/include/amdgpu_userqueue.h | 62 +++++++++++++++++++
> 6 files changed, 113 insertions(+)
> create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
> create mode 100644 drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
> index 415a7fa395c4..4b9bae995094 100644
> --- a/drivers/gpu/drm/amd/amdgpu/Makefile
> +++ b/drivers/gpu/drm/amd/amdgpu/Makefile
> @@ -216,6 +216,8 @@ amdgpu-y += \
> # add amdkfd interfaces
> amdgpu-y += amdgpu_amdkfd.o
>
> +# add usermode queue
> +amdgpu-y += amdgpu_userqueue.o
>
> ifneq ($(CONFIG_HSA_AMD),)
> AMDKFD_PATH := ../amdkfd
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> index 02b827785e39..fab842138cd5 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> @@ -107,6 +107,7 @@
> #include "amdgpu_fdinfo.h"
> #include "amdgpu_mca.h"
> #include "amdgpu_ras.h"
> +#include "amdgpu_userqueue.h"
>
> #define MAX_GPU_INSTANCE 16
>
> @@ -463,6 +464,7 @@ struct amdgpu_fpriv {
> struct mutex bo_list_lock;
> struct idr bo_list_handles;
> struct amdgpu_ctx_mgr ctx_mgr;
> + struct amdgpu_userq_mgr userq_mgr;
> };
>
> int amdgpu_file_to_fpriv(struct file *filp, struct amdgpu_fpriv **fpriv);
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> index b1ca1ab6d6ad..4c5e44d41652 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> @@ -50,6 +50,7 @@
> #include "amdgpu_ras.h"
> #include "amdgpu_xgmi.h"
> #include "amdgpu_reset.h"
> +#include "amdgpu_userqueue.h"
>
> /*
> * KMS wrapper.
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> index 0efb38539d70..68e5375b648b 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> @@ -44,6 +44,7 @@
> #include "amdgpu_display.h"
> #include "amdgpu_ras.h"
> #include "amd_pcie.h"
> +#include "amdgpu_userqueue.h"
>
> void amdgpu_unregister_gpu_instance(struct amdgpu_device *adev)
> {
> @@ -1234,6 +1235,10 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
>
> amdgpu_ctx_mgr_init(&fpriv->ctx_mgr, adev);
>
> + r = amdgpu_userq_mgr_init(&fpriv->userq_mgr, adev);
> + if (r)
> + DRM_WARN("Can't setup usermode queues, use legacy workload submission only\n");
> +
> file_priv->driver_priv = fpriv;
> goto out_suspend;
>
> @@ -1301,6 +1306,7 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,
>
> amdgpu_ctx_mgr_fini(&fpriv->ctx_mgr);
> amdgpu_vm_fini(adev, &fpriv->vm);
> + amdgpu_userq_mgr_fini(&fpriv->userq_mgr);
>
> if (pasid)
> amdgpu_pasid_free_delayed(pd->tbo.base.resv, pasid);
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
> new file mode 100644
> index 000000000000..effc0c7c02cf
> --- /dev/null
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
> @@ -0,0 +1,40 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright 2023 Advanced Micro Devices, Inc.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + *
> + */
> +
> +#include "amdgpu.h"
> +
> +int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct amdgpu_device *adev)
> +{
> + mutex_init(&userq_mgr->userq_mutex);
> + idr_init_base(&userq_mgr->userq_idr, 1);
> + userq_mgr->adev = adev;
> +
> + return 0;
> +}
> +
> +void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr)
> +{
> + idr_destroy(&userq_mgr->userq_idr);
> + mutex_destroy(&userq_mgr->userq_mutex);
> +}
> diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
> new file mode 100644
> index 000000000000..79ffa131a514
> --- /dev/null
> +++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
> @@ -0,0 +1,62 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright 2023 Advanced Micro Devices, Inc.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + *
> + */
> +
> +#ifndef AMDGPU_USERQUEUE_H_
> +#define AMDGPU_USERQUEUE_H_
> +
> +#define AMDGPU_MAX_USERQ_COUNT 512
> +
> +struct amdgpu_mqd_prop;
> +
> +struct amdgpu_usermode_queue {
> + int queue_type;
> + uint64_t doorbell_handle;
> + uint64_t doorbell_index;
> + uint64_t flags;
> + struct amdgpu_mqd_prop *userq_prop;
> + struct amdgpu_userq_mgr *userq_mgr;
> + struct amdgpu_vm *vm;
> +};
> +
> +struct amdgpu_userq_funcs {
> + int (*mqd_create)(struct amdgpu_userq_mgr *uq_mgr,
> + struct drm_amdgpu_userq_in *args,
> + struct amdgpu_usermode_queue *queue);
> + void (*mqd_destroy)(struct amdgpu_userq_mgr *uq_mgr,
> + struct amdgpu_usermode_queue *uq);
> +};
> +
> +/* Usermode queues for gfx */
> +struct amdgpu_userq_mgr {
> + struct idr userq_idr;
> + struct mutex userq_mutex;
> + struct amdgpu_device *adev;
> + const struct amdgpu_userq_funcs *userq_funcs[AMDGPU_HW_IP_NUM];
> +};
> +
> +int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct amdgpu_device *adev);
> +
> +void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr);
> +
> +#endif
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 03/10] drm/amdgpu: add new IOCTL for usermode queue
2023-07-06 12:35 ` [PATCH v5 03/10] drm/amdgpu: add new IOCTL for usermode queue Shashank Sharma
@ 2023-07-06 13:20 ` Christian König
0 siblings, 0 replies; 50+ messages in thread
From: Christian König @ 2023-07-06 13:20 UTC (permalink / raw)
To: Shashank Sharma, amd-gfx; +Cc: Alex Deucher, arvind.yadav
Am 06.07.23 um 14:35 schrieb Shashank Sharma:
> This patch adds:
> - A new IOCTL function to create and destroy
> - A new structure to keep all the user queue data in one place.
> - A function to generate unique index for the queue.
>
> V1: Worked on review comments from RFC patch series:
> - Alex: Keep a list of queues, instead of single queue per process.
> - Christian: Use the queue manager instead of global ptrs,
> Don't keep the queue structure in amdgpu_ctx
>
> V2: Worked on review comments:
> - Christian:
> - Formatting of text
> - There is no need for queuing of userqueues, with idr in place
> - Alex:
> - Remove use_doorbell, its unnecessary
> - Reuse amdgpu_mqd_props for saving mqd fields
>
> - Code formatting and re-arrangement
>
> V3:
> - Integration with doorbell manager
>
> V4:
> - Accommodate MQD union related changes in UAPI (Alex)
> - Do not set the queue size twice (Bas)
>
> V5:
> - Remove wrapper functions for queue indexing (Christian)
> - Do not save the queue id/idr in queue itself (Christian)
> - Move the idr allocation in the IP independent generic space
> (Christian)
>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Christian Koenig <christian.koenig@amd.com>
> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
> ---
> drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 1 +
> drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 110 ++++++++++++++++++
> .../gpu/drm/amd/include/amdgpu_userqueue.h | 2 +
> 3 files changed, 113 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> index 4c5e44d41652..43cb37f097af 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> @@ -2786,6 +2786,7 @@ const struct drm_ioctl_desc amdgpu_ioctls_kms[] = {
> DRM_IOCTL_DEF_DRV(AMDGPU_GEM_VA, amdgpu_gem_va_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
> DRM_IOCTL_DEF_DRV(AMDGPU_GEM_OP, amdgpu_gem_op_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
> DRM_IOCTL_DEF_DRV(AMDGPU_GEM_USERPTR, amdgpu_gem_userptr_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
> + DRM_IOCTL_DEF_DRV(AMDGPU_USERQ, amdgpu_userq_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
> };
>
> static const struct drm_driver amdgpu_kms_driver = {
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
> index effc0c7c02cf..e37b5da5a0d0 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
> @@ -23,6 +23,116 @@
> */
>
> #include "amdgpu.h"
> +#include "amdgpu_vm.h"
> +#include "amdgpu_userqueue.h"
> +
> +static struct amdgpu_usermode_queue *
> +amdgpu_userqueue_find(struct amdgpu_userq_mgr *uq_mgr, int qid)
> +{
> + return idr_find(&uq_mgr->userq_idr, qid);
> +}
> +
> +static int
> +amdgpu_userqueue_destroy(struct drm_file *filp, int queue_id)
> +{
> + struct amdgpu_fpriv *fpriv = filp->driver_priv;
> + struct amdgpu_userq_mgr *uq_mgr = &fpriv->userq_mgr;
> + const struct amdgpu_userq_funcs *uq_funcs;
> + struct amdgpu_usermode_queue *queue;
> +
> + mutex_lock(&uq_mgr->userq_mutex);
> +
> + queue = amdgpu_userqueue_find(uq_mgr, queue_id);
> + if (!queue) {
> + DRM_DEBUG_DRIVER("Invalid queue id to destroy\n");
> + mutex_unlock(&uq_mgr->userq_mutex);
> + return -EINVAL;
> + }
> + uq_funcs = uq_mgr->userq_funcs[queue->queue_type];
> + uq_funcs->mqd_destroy(uq_mgr, queue);
> + idr_remove(&uq_mgr->userq_idr, queue_id);
> + kfree(queue);
> +
> + mutex_unlock(&uq_mgr->userq_mutex);
> + return 0;
> +}
> +
> +static int
> +amdgpu_userqueue_create(struct drm_file *filp, union drm_amdgpu_userq *args)
> +{
> + struct amdgpu_fpriv *fpriv = filp->driver_priv;
> + struct amdgpu_userq_mgr *uq_mgr = &fpriv->userq_mgr;
> + const struct amdgpu_userq_funcs *uq_funcs;
> + struct amdgpu_usermode_queue *queue;
> + int qid, r = 0;
> +
> + mutex_lock(&uq_mgr->userq_mutex);
> +
> + uq_funcs = uq_mgr->userq_funcs[args->in.ip_type];
I think you need to validate the ip_type here or otherwise userspace
could send you invalid values.
> + if (!uq_funcs) {
> + DRM_ERROR("Usermode queue is not supported for this IP (%u)\n", args->in.ip_type);
> + r = -EINVAL;
> + goto unlock;
> + }
> +
> + queue = kzalloc(sizeof(struct amdgpu_usermode_queue), GFP_KERNEL);
> + if (!queue) {
> + DRM_ERROR("Failed to allocate memory for queue\n");
> + r = -ENOMEM;
> + goto unlock;
> + }
> + queue->doorbell_handle = args->in.doorbell_handle;
That doorbell_handle should probably translated into a doorbell object
(BO?).
Or otherwise userspace could potentially do quite a bunch of nonsense
with that.
Regards,
Christian.
> + queue->doorbell_index = args->in.doorbell_offset;
> + queue->queue_type = args->in.ip_type;
> + queue->flags = args->in.flags;
> + queue->vm = &fpriv->vm;
> +
> + r = uq_funcs->mqd_create(uq_mgr, &args->in, queue);
> + if (r) {
> + DRM_ERROR("Failed to create Queue\n");
> + goto unlock;
> + }
> +
> + qid = idr_alloc(&uq_mgr->userq_idr, queue, 1, AMDGPU_MAX_USERQ_COUNT, GFP_KERNEL);
> + if (qid < 0) {
> + DRM_ERROR("Failed to allocate a queue id\n");
> + uq_funcs->mqd_destroy(uq_mgr, queue);
> + r = -ENOMEM;
> + goto unlock;
> + }
> + args->out.queue_id = qid;
> +
> +unlock:
> + mutex_unlock(&uq_mgr->userq_mutex);
> + return r;
> +}
> +
> +int amdgpu_userq_ioctl(struct drm_device *dev, void *data,
> + struct drm_file *filp)
> +{
> + union drm_amdgpu_userq *args = data;
> + int r = 0;
> +
> + switch (args->in.op) {
> + case AMDGPU_USERQ_OP_CREATE:
> + r = amdgpu_userqueue_create(filp->driver_priv, args);
> + if (r)
> + DRM_ERROR("Failed to create usermode queue\n");
> + break;
> +
> + case AMDGPU_USERQ_OP_FREE:
> + r = amdgpu_userqueue_destroy(filp, args->in.queue_id);
> + if (r)
> + DRM_ERROR("Failed to destroy usermode queue\n");
> + break;
> +
> + default:
> + DRM_ERROR("Invalid user queue op specified: %d\n", args->in.op);
> + return -EINVAL;
> + }
> +
> + return r;
> +}
>
> int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct amdgpu_device *adev)
> {
> diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
> index 79ffa131a514..55ed6512a565 100644
> --- a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
> +++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
> @@ -55,6 +55,8 @@ struct amdgpu_userq_mgr {
> const struct amdgpu_userq_funcs *userq_funcs[AMDGPU_HW_IP_NUM];
> };
>
> +int amdgpu_userq_ioctl(struct drm_device *dev, void *data, struct drm_file *filp);
> +
> int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct amdgpu_device *adev);
>
> void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr);
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 04/10] drm/amdgpu: create GFX-gen11 usermode queue
2023-07-06 12:35 ` [PATCH v5 04/10] drm/amdgpu: create GFX-gen11 " Shashank Sharma
@ 2023-07-06 13:22 ` Christian König
2023-07-06 13:37 ` Shashank Sharma
2023-07-06 16:27 ` Alex Deucher
2023-07-07 7:24 ` Christian König
2 siblings, 1 reply; 50+ messages in thread
From: Christian König @ 2023-07-06 13:22 UTC (permalink / raw)
To: Shashank Sharma, amd-gfx; +Cc: Alex Deucher, arvind.yadav
Am 06.07.23 um 14:35 schrieb Shashank Sharma:
> A Memory queue descriptor (MQD) of a userqueue defines it in
> the hw's context. As MQD format can vary between different
> graphics IPs, we need gfx GEN specific handlers to create MQDs.
>
> This patch:
> - Introduces MQD handler functions for the usermode queues.
> - Adds new functions to create and destroy userqueue MQD for
> GFX-GEN-11 IP
>
> V1: Worked on review comments from Alex:
> - Make MQD functions GEN and IP specific
>
> V2: Worked on review comments from Alex:
> - Reuse the existing adev->mqd[ip] for MQD creation
> - Formatting and arrangement of code
>
> V3:
> - Integration with doorbell manager
>
> V4: Review comments addressed:
> - Do not create a new file for userq, reuse gfx_v11_0.c (Alex)
> - Align name of structure members (Luben)
> - Don't break up the Cc tag list and the Sob tag list in commit
> message (Luben)
> V5:
> - No need to reserve the bo for MQD (Christian).
> - Some more changes to support IP specific MQD creation.
>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Christian Koenig <christian.koenig@amd.com>
> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
> Signed-off-by: Arvind Yadav <arvind.yadav@amd.com>
> ---
> drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 16 ++++
> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 73 +++++++++++++++++++
> .../gpu/drm/amd/include/amdgpu_userqueue.h | 7 ++
> 3 files changed, 96 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
> index e37b5da5a0d0..bb774144c372 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
> @@ -134,12 +134,28 @@ int amdgpu_userq_ioctl(struct drm_device *dev, void *data,
> return r;
> }
>
> +extern const struct amdgpu_userq_funcs userq_gfx_v11_funcs;
> +
> +static void
> +amdgpu_userqueue_setup_gfx(struct amdgpu_userq_mgr *uq_mgr)
> +{
> + int maj;
> + struct amdgpu_device *adev = uq_mgr->adev;
> + uint32_t version = adev->ip_versions[GC_HWIP][0];
> +
> + /* We support usermode queue only for GFX V11 as of now */
> + maj = IP_VERSION_MAJ(version);
> + if (maj == 11)
> + uq_mgr->userq_funcs[AMDGPU_HW_IP_GFX] = &userq_gfx_v11_funcs;
> +}
> +
> int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct amdgpu_device *adev)
> {
> mutex_init(&userq_mgr->userq_mutex);
> idr_init_base(&userq_mgr->userq_idr, 1);
> userq_mgr->adev = adev;
>
> + amdgpu_userqueue_setup_gfx(userq_mgr);
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> index c4940b6ea1c4..e76e1b86b434 100644
> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> @@ -30,6 +30,7 @@
> #include "amdgpu_psp.h"
> #include "amdgpu_smu.h"
> #include "amdgpu_atomfirmware.h"
> +#include "amdgpu_userqueue.h"
> #include "imu_v11_0.h"
> #include "soc21.h"
> #include "nvd.h"
> @@ -6486,3 +6487,75 @@ const struct amdgpu_ip_block_version gfx_v11_0_ip_block =
> .rev = 0,
> .funcs = &gfx_v11_0_ip_funcs,
> };
> +
> +static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
> + struct drm_amdgpu_userq_in *args_in,
> + struct amdgpu_usermode_queue *queue)
> +{
> + struct amdgpu_device *adev = uq_mgr->adev;
> + struct amdgpu_mqd *mqd_gfx_generic = &adev->mqds[AMDGPU_HW_IP_GFX];
> + struct drm_amdgpu_userq_mqd_gfx_v11_0 mqd_user;
> + struct amdgpu_mqd_prop userq_props;
> + int r;
> +
> + /* Incoming MQD parameters from userspace to be saved here */
> + memset(&mqd_user, 0, sizeof(mqd_user));
> +
> + /* Structure to initialize MQD for userqueue using generic MQD init function */
> + memset(&userq_props, 0, sizeof(userq_props));
> +
> + if (args_in->mqd_size != sizeof(struct drm_amdgpu_userq_mqd_gfx_v11_0)) {
> + DRM_ERROR("MQD size mismatch\n");
> + return -EINVAL;
> + }
> +
> + if (copy_from_user(&mqd_user, u64_to_user_ptr(args_in->mqd), args_in->mqd_size)) {
> + DRM_ERROR("Failed to get user MQD\n");
> + return -EFAULT;
> + }
> +
> + /* Create BO for actual Userqueue MQD now */
> + r = amdgpu_bo_create_kernel(adev, mqd_gfx_generic->mqd_size, PAGE_SIZE,
> + AMDGPU_GEM_DOMAIN_GTT,
> + &queue->mqd.obj,
> + &queue->mqd.gpu_addr,
> + &queue->mqd.cpu_ptr);
> + if (r) {
> + DRM_ERROR("Failed to allocate BO for userqueue (%d)", r);
> + return -ENOMEM;
> + }
Using amdgpu_bo_create_kernel() for the MQD is most likely not a good
idea in the long term, but should work for now.
Probably best to add a comment here that this needs to be improved.
Apart from that looks good to me,
Christian.
> + memset(queue->mqd.cpu_ptr, 0, mqd_gfx_generic->mqd_size);
> +
> + /* Initialize the MQD BO with user given values */
> + userq_props.wptr_gpu_addr = mqd_user.wptr_va;
> + userq_props.rptr_gpu_addr = mqd_user.rptr_va;
> + userq_props.queue_size = mqd_user.queue_size;
> + userq_props.hqd_base_gpu_addr = mqd_user.queue_va;
> + userq_props.mqd_gpu_addr = queue->mqd.gpu_addr;
> + userq_props.use_doorbell = true;
> +
> + r = mqd_gfx_generic->init_mqd(adev, (void *)queue->mqd.cpu_ptr, &userq_props);
> + if (r) {
> + DRM_ERROR("Failed to initialize MQD for userqueue\n");
> + goto free_mqd;
> + }
> +
> + return 0;
> +
> +free_mqd:
> + amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr, &queue->mqd.cpu_ptr);
> + return r;
> +}
> +
> +static void
> +gfx_v11_0_userq_mqd_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_queue *queue)
> +{
> + struct amdgpu_userq_obj *mqd = &queue->mqd;
> +
> + amdgpu_bo_free_kernel(&mqd->obj, &mqd->gpu_addr, &mqd->cpu_ptr);
> +}
> +
> +const struct amdgpu_userq_funcs userq_gfx_v11_funcs = {
> + .mqd_create = gfx_v11_0_userq_mqd_create,
> + .mqd_destroy = gfx_v11_0_userq_mqd_destroy,
> +};
> diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
> index 55ed6512a565..240f92796f00 100644
> --- a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
> +++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
> @@ -29,6 +29,12 @@
>
> struct amdgpu_mqd_prop;
>
> +struct amdgpu_userq_obj {
> + void *cpu_ptr;
> + uint64_t gpu_addr;
> + struct amdgpu_bo *obj;
> +};
> +
> struct amdgpu_usermode_queue {
> int queue_type;
> uint64_t doorbell_handle;
> @@ -37,6 +43,7 @@ struct amdgpu_usermode_queue {
> struct amdgpu_mqd_prop *userq_prop;
> struct amdgpu_userq_mgr *userq_mgr;
> struct amdgpu_vm *vm;
> + struct amdgpu_userq_obj mqd;
> };
>
> struct amdgpu_userq_funcs {
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 05/10] drm/amdgpu: create context space for usermode queue
2023-07-06 12:35 ` [PATCH v5 05/10] drm/amdgpu: create context space for " Shashank Sharma
@ 2023-07-06 13:28 ` Christian König
2023-07-06 13:33 ` Shashank Sharma
2023-07-06 16:44 ` Alex Deucher
1 sibling, 1 reply; 50+ messages in thread
From: Christian König @ 2023-07-06 13:28 UTC (permalink / raw)
To: Shashank Sharma, amd-gfx; +Cc: Alex Deucher, arvind.yadav
Am 06.07.23 um 14:35 schrieb Shashank Sharma:
> The FW expects us to allocate at least one page as context
> space to process gang, process, GDS and FW related work.
> This patch creates a joint object for the same, and calculates
> GPU space offsets for each of these spaces.
>
> V1: Addressed review comments on RFC patch:
> Alex: Make this function IP specific
>
> V2: Addressed review comments from Christian
> - Allocate only one object for total FW space, and calculate
> offsets for each of these objects.
>
> V3: Integration with doorbell manager
>
> V4: Review comments:
> - Remove shadow from FW space list from cover letter (Alex)
> - Alignment of macro (Luben)
>
> V5: Merged patches 5 and 6 into this single patch
> Addressed review comments:
> - Use lower_32_bits instead of mask (Christian)
> - gfx_v11_0 instead of gfx_v11 in function names (Alex)
> - Shadow and GDS objects are now coming from userspace (Christian,
> Alex)
>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Christian Koenig <christian.koenig@amd.com>
> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
> Signed-off-by: Arvind Yadav <arvind.yadav@amd.com>
> ---
> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 62 +++++++++++++++++++
> .../gpu/drm/amd/include/amdgpu_userqueue.h | 4 ++
> 2 files changed, 66 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> index e76e1b86b434..7d3b19e08bbb 100644
> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> @@ -61,6 +61,9 @@
> #define regCGTT_WD_CLK_CTRL_BASE_IDX 1
> #define regRLC_RLCS_BOOTLOAD_STATUS_gc_11_0_1 0x4e7e
> #define regRLC_RLCS_BOOTLOAD_STATUS_gc_11_0_1_BASE_IDX 1
> +#define AMDGPU_USERQ_PROC_CTX_SZ PAGE_SIZE
> +#define AMDGPU_USERQ_GANG_CTX_SZ PAGE_SIZE
> +#define AMDGPU_USERQ_FW_CTX_SZ PAGE_SIZE
>
> MODULE_FIRMWARE("amdgpu/gc_11_0_0_pfp.bin");
> MODULE_FIRMWARE("amdgpu/gc_11_0_0_me.bin");
> @@ -6488,6 +6491,57 @@ const struct amdgpu_ip_block_version gfx_v11_0_ip_block =
> .funcs = &gfx_v11_0_ip_funcs,
> };
>
> +static void gfx_v11_0_userq_destroy_ctx_space(struct amdgpu_userq_mgr *uq_mgr,
> + struct amdgpu_usermode_queue *queue)
> +{
> + struct amdgpu_userq_obj *ctx = &queue->fw_obj;
> +
> + amdgpu_bo_free_kernel(&ctx->obj, &ctx->gpu_addr, &ctx->cpu_ptr);
> +}
> +
> +static int gfx_v11_0_userq_create_ctx_space(struct amdgpu_userq_mgr *uq_mgr,
> + struct amdgpu_usermode_queue *queue,
> + struct drm_amdgpu_userq_mqd_gfx_v11_0 *mqd_user)
> +{
> + struct amdgpu_device *adev = uq_mgr->adev;
> + struct amdgpu_userq_obj *ctx = &queue->fw_obj;
> + struct v11_gfx_mqd *mqd = queue->mqd.cpu_ptr;
> + int r, size;
> +
> + /*
> + * The FW expects at least one page space allocated for
> + * process ctx, gang ctx and fw ctx each. Create an object
> + * for the same.
> + */
> + size = AMDGPU_USERQ_PROC_CTX_SZ + AMDGPU_USERQ_FW_CTX_SZ +
> + AMDGPU_USERQ_GANG_CTX_SZ;
> + r = amdgpu_bo_create_kernel(adev, size, PAGE_SIZE,
> + AMDGPU_GEM_DOMAIN_GTT,
> + &ctx->obj,
> + &ctx->gpu_addr,
> + &ctx->cpu_ptr);
> + if (r) {
> + DRM_ERROR("Failed to allocate ctx space bo for userqueue, err:%d\n", r);
> + return r;
> + }
I think I asked that before, but shouldn't this stuff be allocated by
userspace now?
Regards,
Christian.
> +
> + queue->proc_ctx_gpu_addr = ctx->gpu_addr;
> + queue->gang_ctx_gpu_addr = queue->proc_ctx_gpu_addr + AMDGPU_USERQ_PROC_CTX_SZ;
> + queue->fw_ctx_gpu_addr = queue->gang_ctx_gpu_addr + AMDGPU_USERQ_GANG_CTX_SZ;
> +
> + mqd->fw_work_area_base_lo = lower_32_bits(queue->fw_ctx_gpu_addr);
> + mqd->fw_work_area_base_lo = upper_32_bits(queue->fw_ctx_gpu_addr);
> +
> + /* Shadow and GDS objects come directly from userspace */
> + mqd->shadow_base_lo = lower_32_bits(mqd_user->shadow_va);
> + mqd->shadow_base_hi = upper_32_bits(mqd_user->shadow_va);
> +
> + mqd->gds_bkup_base_lo = lower_32_bits(mqd_user->gds_va);
> + mqd->gds_bkup_base_hi = upper_32_bits(mqd_user->gds_va);
> +
> + return 0;
> +}
> +
> static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
> struct drm_amdgpu_userq_in *args_in,
> struct amdgpu_usermode_queue *queue)
> @@ -6540,6 +6594,13 @@ static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
> goto free_mqd;
> }
>
> + /* Create BO for FW operations */
> + r = gfx_v11_0_userq_create_ctx_space(uq_mgr, queue, &mqd_user);
> + if (r) {
> + DRM_ERROR("Failed to allocate BO for userqueue (%d)", r);
> + goto free_mqd;
> + }
> +
> return 0;
>
> free_mqd:
> @@ -6552,6 +6613,7 @@ gfx_v11_0_userq_mqd_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_userm
> {
> struct amdgpu_userq_obj *mqd = &queue->mqd;
>
> + gfx_v11_0_userq_destroy_ctx_space(uq_mgr, queue);
> amdgpu_bo_free_kernel(&mqd->obj, &mqd->gpu_addr, &mqd->cpu_ptr);
> }
>
> diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
> index 240f92796f00..a5cdb319193d 100644
> --- a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
> +++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
> @@ -40,10 +40,14 @@ struct amdgpu_usermode_queue {
> uint64_t doorbell_handle;
> uint64_t doorbell_index;
> uint64_t flags;
> + uint64_t proc_ctx_gpu_addr;
> + uint64_t gang_ctx_gpu_addr;
> + uint64_t fw_ctx_gpu_addr;
> struct amdgpu_mqd_prop *userq_prop;
> struct amdgpu_userq_mgr *userq_mgr;
> struct amdgpu_vm *vm;
> struct amdgpu_userq_obj mqd;
> + struct amdgpu_userq_obj fw_obj;
> };
>
> struct amdgpu_userq_funcs {
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 05/10] drm/amdgpu: create context space for usermode queue
2023-07-06 13:28 ` Christian König
@ 2023-07-06 13:33 ` Shashank Sharma
2023-07-06 13:37 ` Christian König
0 siblings, 1 reply; 50+ messages in thread
From: Shashank Sharma @ 2023-07-06 13:33 UTC (permalink / raw)
To: Christian König, amd-gfx; +Cc: Alex Deucher, arvind.yadav
Hey Christian,
On 06/07/2023 15:28, Christian König wrote:
> Am 06.07.23 um 14:35 schrieb Shashank Sharma:
>> The FW expects us to allocate at least one page as context
>> space to process gang, process, GDS and FW related work.
>> This patch creates a joint object for the same, and calculates
>> GPU space offsets for each of these spaces.
>>
>> V1: Addressed review comments on RFC patch:
>> Alex: Make this function IP specific
>>
>> V2: Addressed review comments from Christian
>> - Allocate only one object for total FW space, and calculate
>> offsets for each of these objects.
>>
>> V3: Integration with doorbell manager
>>
>> V4: Review comments:
>> - Remove shadow from FW space list from cover letter (Alex)
>> - Alignment of macro (Luben)
>>
>> V5: Merged patches 5 and 6 into this single patch
>> Addressed review comments:
>> - Use lower_32_bits instead of mask (Christian)
>> - gfx_v11_0 instead of gfx_v11 in function names (Alex)
>> - Shadow and GDS objects are now coming from userspace (Christian,
>> Alex)
>>
>> Cc: Alex Deucher <alexander.deucher@amd.com>
>> Cc: Christian Koenig <christian.koenig@amd.com>
>> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
>> Signed-off-by: Arvind Yadav <arvind.yadav@amd.com>
>> ---
>> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 62 +++++++++++++++++++
>> .../gpu/drm/amd/include/amdgpu_userqueue.h | 4 ++
>> 2 files changed, 66 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>> b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>> index e76e1b86b434..7d3b19e08bbb 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>> @@ -61,6 +61,9 @@
>> #define regCGTT_WD_CLK_CTRL_BASE_IDX 1
>> #define regRLC_RLCS_BOOTLOAD_STATUS_gc_11_0_1 0x4e7e
>> #define regRLC_RLCS_BOOTLOAD_STATUS_gc_11_0_1_BASE_IDX 1
>> +#define AMDGPU_USERQ_PROC_CTX_SZ PAGE_SIZE
>> +#define AMDGPU_USERQ_GANG_CTX_SZ PAGE_SIZE
>> +#define AMDGPU_USERQ_FW_CTX_SZ PAGE_SIZE
>> MODULE_FIRMWARE("amdgpu/gc_11_0_0_pfp.bin");
>> MODULE_FIRMWARE("amdgpu/gc_11_0_0_me.bin");
>> @@ -6488,6 +6491,57 @@ const struct amdgpu_ip_block_version
>> gfx_v11_0_ip_block =
>> .funcs = &gfx_v11_0_ip_funcs,
>> };
>> +static void gfx_v11_0_userq_destroy_ctx_space(struct
>> amdgpu_userq_mgr *uq_mgr,
>> + struct amdgpu_usermode_queue *queue)
>> +{
>> + struct amdgpu_userq_obj *ctx = &queue->fw_obj;
>> +
>> + amdgpu_bo_free_kernel(&ctx->obj, &ctx->gpu_addr, &ctx->cpu_ptr);
>> +}
>> +
>> +static int gfx_v11_0_userq_create_ctx_space(struct amdgpu_userq_mgr
>> *uq_mgr,
>> + struct amdgpu_usermode_queue *queue,
>> + struct drm_amdgpu_userq_mqd_gfx_v11_0
>> *mqd_user)
>> +{
>> + struct amdgpu_device *adev = uq_mgr->adev;
>> + struct amdgpu_userq_obj *ctx = &queue->fw_obj;
>> + struct v11_gfx_mqd *mqd = queue->mqd.cpu_ptr;
>> + int r, size;
>> +
>> + /*
>> + * The FW expects at least one page space allocated for
>> + * process ctx, gang ctx and fw ctx each. Create an object
>> + * for the same.
>> + */
>> + size = AMDGPU_USERQ_PROC_CTX_SZ + AMDGPU_USERQ_FW_CTX_SZ +
>> + AMDGPU_USERQ_GANG_CTX_SZ;
>> + r = amdgpu_bo_create_kernel(adev, size, PAGE_SIZE,
>> + AMDGPU_GEM_DOMAIN_GTT,
>> + &ctx->obj,
>> + &ctx->gpu_addr,
>> + &ctx->cpu_ptr);
>> + if (r) {
>> + DRM_ERROR("Failed to allocate ctx space bo for userqueue,
>> err:%d\n", r);
>> + return r;
>> + }
>
> I think I asked that before, but shouldn't this stuff be allocated by
> userspace now?
Following your comments, we have already moved the Shadow and the GDS
object space to user, but the Proc and Gang context is required for MES
mapping (which is kernel internal process and usermode doesn't know
anything about that), so it needs to be created by Kernel only.
- Shashank
>
> Regards,
> Christian.
>
>> +
>> + queue->proc_ctx_gpu_addr = ctx->gpu_addr;
>> + queue->gang_ctx_gpu_addr = queue->proc_ctx_gpu_addr +
>> AMDGPU_USERQ_PROC_CTX_SZ;
>> + queue->fw_ctx_gpu_addr = queue->gang_ctx_gpu_addr +
>> AMDGPU_USERQ_GANG_CTX_SZ;
>> +
>> + mqd->fw_work_area_base_lo = lower_32_bits(queue->fw_ctx_gpu_addr);
>> + mqd->fw_work_area_base_lo = upper_32_bits(queue->fw_ctx_gpu_addr);
>> +
>> + /* Shadow and GDS objects come directly from userspace */
>> + mqd->shadow_base_lo = lower_32_bits(mqd_user->shadow_va);
>> + mqd->shadow_base_hi = upper_32_bits(mqd_user->shadow_va);
>> +
>> + mqd->gds_bkup_base_lo = lower_32_bits(mqd_user->gds_va);
>> + mqd->gds_bkup_base_hi = upper_32_bits(mqd_user->gds_va);
>> +
>> + return 0;
>> +}
>> +
>> static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
>> struct drm_amdgpu_userq_in *args_in,
>> struct amdgpu_usermode_queue *queue)
>> @@ -6540,6 +6594,13 @@ static int gfx_v11_0_userq_mqd_create(struct
>> amdgpu_userq_mgr *uq_mgr,
>> goto free_mqd;
>> }
>> + /* Create BO for FW operations */
>> + r = gfx_v11_0_userq_create_ctx_space(uq_mgr, queue, &mqd_user);
>> + if (r) {
>> + DRM_ERROR("Failed to allocate BO for userqueue (%d)", r);
>> + goto free_mqd;
>> + }
>> +
>> return 0;
>> free_mqd:
>> @@ -6552,6 +6613,7 @@ gfx_v11_0_userq_mqd_destroy(struct
>> amdgpu_userq_mgr *uq_mgr, struct amdgpu_userm
>> {
>> struct amdgpu_userq_obj *mqd = &queue->mqd;
>> + gfx_v11_0_userq_destroy_ctx_space(uq_mgr, queue);
>> amdgpu_bo_free_kernel(&mqd->obj, &mqd->gpu_addr, &mqd->cpu_ptr);
>> }
>> diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>> b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>> index 240f92796f00..a5cdb319193d 100644
>> --- a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>> +++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>> @@ -40,10 +40,14 @@ struct amdgpu_usermode_queue {
>> uint64_t doorbell_handle;
>> uint64_t doorbell_index;
>> uint64_t flags;
>> + uint64_t proc_ctx_gpu_addr;
>> + uint64_t gang_ctx_gpu_addr;
>> + uint64_t fw_ctx_gpu_addr;
>> struct amdgpu_mqd_prop *userq_prop;
>> struct amdgpu_userq_mgr *userq_mgr;
>> struct amdgpu_vm *vm;
>> struct amdgpu_userq_obj mqd;
>> + struct amdgpu_userq_obj fw_obj;
>> };
>> struct amdgpu_userq_funcs {
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 04/10] drm/amdgpu: create GFX-gen11 usermode queue
2023-07-06 13:22 ` Christian König
@ 2023-07-06 13:37 ` Shashank Sharma
2023-07-06 13:39 ` Christian König
0 siblings, 1 reply; 50+ messages in thread
From: Shashank Sharma @ 2023-07-06 13:37 UTC (permalink / raw)
To: Christian König, amd-gfx; +Cc: Alex Deucher, arvind.yadav
On 06/07/2023 15:22, Christian König wrote:
> Am 06.07.23 um 14:35 schrieb Shashank Sharma:
>> A Memory queue descriptor (MQD) of a userqueue defines it in
>> the hw's context. As MQD format can vary between different
>> graphics IPs, we need gfx GEN specific handlers to create MQDs.
>>
>> This patch:
>> - Introduces MQD handler functions for the usermode queues.
>> - Adds new functions to create and destroy userqueue MQD for
>> GFX-GEN-11 IP
>>
>> V1: Worked on review comments from Alex:
>> - Make MQD functions GEN and IP specific
>>
>> V2: Worked on review comments from Alex:
>> - Reuse the existing adev->mqd[ip] for MQD creation
>> - Formatting and arrangement of code
>>
>> V3:
>> - Integration with doorbell manager
>>
>> V4: Review comments addressed:
>> - Do not create a new file for userq, reuse gfx_v11_0.c (Alex)
>> - Align name of structure members (Luben)
>> - Don't break up the Cc tag list and the Sob tag list in commit
>> message (Luben)
>> V5:
>> - No need to reserve the bo for MQD (Christian).
>> - Some more changes to support IP specific MQD creation.
>>
>> Cc: Alex Deucher <alexander.deucher@amd.com>
>> Cc: Christian Koenig <christian.koenig@amd.com>
>> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
>> Signed-off-by: Arvind Yadav <arvind.yadav@amd.com>
>> ---
>> drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 16 ++++
>> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 73 +++++++++++++++++++
>> .../gpu/drm/amd/include/amdgpu_userqueue.h | 7 ++
>> 3 files changed, 96 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>> index e37b5da5a0d0..bb774144c372 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>> @@ -134,12 +134,28 @@ int amdgpu_userq_ioctl(struct drm_device *dev,
>> void *data,
>> return r;
>> }
>> +extern const struct amdgpu_userq_funcs userq_gfx_v11_funcs;
>> +
>> +static void
>> +amdgpu_userqueue_setup_gfx(struct amdgpu_userq_mgr *uq_mgr)
>> +{
>> + int maj;
>> + struct amdgpu_device *adev = uq_mgr->adev;
>> + uint32_t version = adev->ip_versions[GC_HWIP][0];
>> +
>> + /* We support usermode queue only for GFX V11 as of now */
>> + maj = IP_VERSION_MAJ(version);
>> + if (maj == 11)
>> + uq_mgr->userq_funcs[AMDGPU_HW_IP_GFX] = &userq_gfx_v11_funcs;
>> +}
>> +
>> int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr,
>> struct amdgpu_device *adev)
>> {
>> mutex_init(&userq_mgr->userq_mutex);
>> idr_init_base(&userq_mgr->userq_idr, 1);
>> userq_mgr->adev = adev;
>> + amdgpu_userqueue_setup_gfx(userq_mgr);
>> return 0;
>> }
>> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>> b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>> index c4940b6ea1c4..e76e1b86b434 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>> @@ -30,6 +30,7 @@
>> #include "amdgpu_psp.h"
>> #include "amdgpu_smu.h"
>> #include "amdgpu_atomfirmware.h"
>> +#include "amdgpu_userqueue.h"
>> #include "imu_v11_0.h"
>> #include "soc21.h"
>> #include "nvd.h"
>> @@ -6486,3 +6487,75 @@ const struct amdgpu_ip_block_version
>> gfx_v11_0_ip_block =
>> .rev = 0,
>> .funcs = &gfx_v11_0_ip_funcs,
>> };
>> +
>> +static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
>> + struct drm_amdgpu_userq_in *args_in,
>> + struct amdgpu_usermode_queue *queue)
>> +{
>> + struct amdgpu_device *adev = uq_mgr->adev;
>> + struct amdgpu_mqd *mqd_gfx_generic = &adev->mqds[AMDGPU_HW_IP_GFX];
>> + struct drm_amdgpu_userq_mqd_gfx_v11_0 mqd_user;
>> + struct amdgpu_mqd_prop userq_props;
>> + int r;
>> +
>> + /* Incoming MQD parameters from userspace to be saved here */
>> + memset(&mqd_user, 0, sizeof(mqd_user));
>> +
>> + /* Structure to initialize MQD for userqueue using generic MQD
>> init function */
>> + memset(&userq_props, 0, sizeof(userq_props));
>> +
>> + if (args_in->mqd_size != sizeof(struct
>> drm_amdgpu_userq_mqd_gfx_v11_0)) {
>> + DRM_ERROR("MQD size mismatch\n");
>> + return -EINVAL;
>> + }
>> +
>> + if (copy_from_user(&mqd_user, u64_to_user_ptr(args_in->mqd),
>> args_in->mqd_size)) {
>> + DRM_ERROR("Failed to get user MQD\n");
>> + return -EFAULT;
>> + }
>> +
>> + /* Create BO for actual Userqueue MQD now */
>> + r = amdgpu_bo_create_kernel(adev, mqd_gfx_generic->mqd_size,
>> PAGE_SIZE,
>> + AMDGPU_GEM_DOMAIN_GTT,
>> + &queue->mqd.obj,
>> + &queue->mqd.gpu_addr,
>> + &queue->mqd.cpu_ptr);
>> + if (r) {
>> + DRM_ERROR("Failed to allocate BO for userqueue (%d)", r);
>> + return -ENOMEM;
>> + }
>
> Using amdgpu_bo_create_kernel() for the MQD is most likely not a good
> idea in the long term, but should work for now.
>
I was a bit curious about this, the scope of this MQD object is kernel
internal and used for queue mapping only, userspace doesn't know much
about it. Do you still think we should not create a kernel object for it ?
- Shashank
> Probably best to add a comment here that this needs to be improved.
>
> Apart from that looks good to me,
> Christian.
>
>> + memset(queue->mqd.cpu_ptr, 0, mqd_gfx_generic->mqd_size);
>> +
>> + /* Initialize the MQD BO with user given values */
>> + userq_props.wptr_gpu_addr = mqd_user.wptr_va;
>> + userq_props.rptr_gpu_addr = mqd_user.rptr_va;
>> + userq_props.queue_size = mqd_user.queue_size;
>> + userq_props.hqd_base_gpu_addr = mqd_user.queue_va;
>> + userq_props.mqd_gpu_addr = queue->mqd.gpu_addr;
>> + userq_props.use_doorbell = true;
>> +
>> + r = mqd_gfx_generic->init_mqd(adev, (void *)queue->mqd.cpu_ptr,
>> &userq_props);
>> + if (r) {
>> + DRM_ERROR("Failed to initialize MQD for userqueue\n");
>> + goto free_mqd;
>> + }
>> +
>> + return 0;
>> +
>> +free_mqd:
>> + amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr,
>> &queue->mqd.cpu_ptr);
>> + return r;
>> +}
>> +
>> +static void
>> +gfx_v11_0_userq_mqd_destroy(struct amdgpu_userq_mgr *uq_mgr, struct
>> amdgpu_usermode_queue *queue)
>> +{
>> + struct amdgpu_userq_obj *mqd = &queue->mqd;
>> +
>> + amdgpu_bo_free_kernel(&mqd->obj, &mqd->gpu_addr, &mqd->cpu_ptr);
>> +}
>> +
>> +const struct amdgpu_userq_funcs userq_gfx_v11_funcs = {
>> + .mqd_create = gfx_v11_0_userq_mqd_create,
>> + .mqd_destroy = gfx_v11_0_userq_mqd_destroy,
>> +};
>> diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>> b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>> index 55ed6512a565..240f92796f00 100644
>> --- a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>> +++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>> @@ -29,6 +29,12 @@
>> struct amdgpu_mqd_prop;
>> +struct amdgpu_userq_obj {
>> + void *cpu_ptr;
>> + uint64_t gpu_addr;
>> + struct amdgpu_bo *obj;
>> +};
>> +
>> struct amdgpu_usermode_queue {
>> int queue_type;
>> uint64_t doorbell_handle;
>> @@ -37,6 +43,7 @@ struct amdgpu_usermode_queue {
>> struct amdgpu_mqd_prop *userq_prop;
>> struct amdgpu_userq_mgr *userq_mgr;
>> struct amdgpu_vm *vm;
>> + struct amdgpu_userq_obj mqd;
>> };
>> struct amdgpu_userq_funcs {
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 05/10] drm/amdgpu: create context space for usermode queue
2023-07-06 13:33 ` Shashank Sharma
@ 2023-07-06 13:37 ` Christian König
0 siblings, 0 replies; 50+ messages in thread
From: Christian König @ 2023-07-06 13:37 UTC (permalink / raw)
To: Shashank Sharma, amd-gfx; +Cc: Alex Deucher, arvind.yadav
Am 06.07.23 um 15:33 schrieb Shashank Sharma:
> Hey Christian,
>
> On 06/07/2023 15:28, Christian König wrote:
>> Am 06.07.23 um 14:35 schrieb Shashank Sharma:
>>> The FW expects us to allocate at least one page as context
>>> space to process gang, process, GDS and FW related work.
>>> This patch creates a joint object for the same, and calculates
>>> GPU space offsets for each of these spaces.
>>>
>>> V1: Addressed review comments on RFC patch:
>>> Alex: Make this function IP specific
>>>
>>> V2: Addressed review comments from Christian
>>> - Allocate only one object for total FW space, and calculate
>>> offsets for each of these objects.
>>>
>>> V3: Integration with doorbell manager
>>>
>>> V4: Review comments:
>>> - Remove shadow from FW space list from cover letter (Alex)
>>> - Alignment of macro (Luben)
>>>
>>> V5: Merged patches 5 and 6 into this single patch
>>> Addressed review comments:
>>> - Use lower_32_bits instead of mask (Christian)
>>> - gfx_v11_0 instead of gfx_v11 in function names (Alex)
>>> - Shadow and GDS objects are now coming from userspace (Christian,
>>> Alex)
>>>
>>> Cc: Alex Deucher <alexander.deucher@amd.com>
>>> Cc: Christian Koenig <christian.koenig@amd.com>
>>> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
>>> Signed-off-by: Arvind Yadav <arvind.yadav@amd.com>
>>> ---
>>> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 62
>>> +++++++++++++++++++
>>> .../gpu/drm/amd/include/amdgpu_userqueue.h | 4 ++
>>> 2 files changed, 66 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>> b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>> index e76e1b86b434..7d3b19e08bbb 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>> @@ -61,6 +61,9 @@
>>> #define regCGTT_WD_CLK_CTRL_BASE_IDX 1
>>> #define regRLC_RLCS_BOOTLOAD_STATUS_gc_11_0_1 0x4e7e
>>> #define regRLC_RLCS_BOOTLOAD_STATUS_gc_11_0_1_BASE_IDX 1
>>> +#define AMDGPU_USERQ_PROC_CTX_SZ PAGE_SIZE
>>> +#define AMDGPU_USERQ_GANG_CTX_SZ PAGE_SIZE
>>> +#define AMDGPU_USERQ_FW_CTX_SZ PAGE_SIZE
>>> MODULE_FIRMWARE("amdgpu/gc_11_0_0_pfp.bin");
>>> MODULE_FIRMWARE("amdgpu/gc_11_0_0_me.bin");
>>> @@ -6488,6 +6491,57 @@ const struct amdgpu_ip_block_version
>>> gfx_v11_0_ip_block =
>>> .funcs = &gfx_v11_0_ip_funcs,
>>> };
>>> +static void gfx_v11_0_userq_destroy_ctx_space(struct
>>> amdgpu_userq_mgr *uq_mgr,
>>> + struct amdgpu_usermode_queue *queue)
>>> +{
>>> + struct amdgpu_userq_obj *ctx = &queue->fw_obj;
>>> +
>>> + amdgpu_bo_free_kernel(&ctx->obj, &ctx->gpu_addr, &ctx->cpu_ptr);
>>> +}
>>> +
>>> +static int gfx_v11_0_userq_create_ctx_space(struct amdgpu_userq_mgr
>>> *uq_mgr,
>>> + struct amdgpu_usermode_queue *queue,
>>> + struct drm_amdgpu_userq_mqd_gfx_v11_0
>>> *mqd_user)
>>> +{
>>> + struct amdgpu_device *adev = uq_mgr->adev;
>>> + struct amdgpu_userq_obj *ctx = &queue->fw_obj;
>>> + struct v11_gfx_mqd *mqd = queue->mqd.cpu_ptr;
>>> + int r, size;
>>> +
>>> + /*
>>> + * The FW expects at least one page space allocated for
>>> + * process ctx, gang ctx and fw ctx each. Create an object
>>> + * for the same.
>>> + */
>>> + size = AMDGPU_USERQ_PROC_CTX_SZ + AMDGPU_USERQ_FW_CTX_SZ +
>>> + AMDGPU_USERQ_GANG_CTX_SZ;
>>> + r = amdgpu_bo_create_kernel(adev, size, PAGE_SIZE,
>>> + AMDGPU_GEM_DOMAIN_GTT,
>>> + &ctx->obj,
>>> + &ctx->gpu_addr,
>>> + &ctx->cpu_ptr);
>>> + if (r) {
>>> + DRM_ERROR("Failed to allocate ctx space bo for userqueue,
>>> err:%d\n", r);
>>> + return r;
>>> + }
>>
>> I think I asked that before, but shouldn't this stuff be allocated by
>> userspace now?
>
> Following your comments, we have already moved the Shadow and the GDS
> object space to user, but the Proc and Gang context is required for
> MES mapping (which is kernel internal process and usermode doesn't
> know anything about that), so it needs to be created by Kernel only.
Ok in this case please just add a comment that we shouldn't use
amdgpu_bo_create_kernel() for that as well.
Thanks,
Christian.
>
> - Shashank
>
>>
>> Regards,
>> Christian.
>>
>>> +
>>> + queue->proc_ctx_gpu_addr = ctx->gpu_addr;
>>> + queue->gang_ctx_gpu_addr = queue->proc_ctx_gpu_addr +
>>> AMDGPU_USERQ_PROC_CTX_SZ;
>>> + queue->fw_ctx_gpu_addr = queue->gang_ctx_gpu_addr +
>>> AMDGPU_USERQ_GANG_CTX_SZ;
>>> +
>>> + mqd->fw_work_area_base_lo = lower_32_bits(queue->fw_ctx_gpu_addr);
>>> + mqd->fw_work_area_base_lo = upper_32_bits(queue->fw_ctx_gpu_addr);
>>> +
>>> + /* Shadow and GDS objects come directly from userspace */
>>> + mqd->shadow_base_lo = lower_32_bits(mqd_user->shadow_va);
>>> + mqd->shadow_base_hi = upper_32_bits(mqd_user->shadow_va);
>>> +
>>> + mqd->gds_bkup_base_lo = lower_32_bits(mqd_user->gds_va);
>>> + mqd->gds_bkup_base_hi = upper_32_bits(mqd_user->gds_va);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr
>>> *uq_mgr,
>>> struct drm_amdgpu_userq_in *args_in,
>>> struct amdgpu_usermode_queue *queue)
>>> @@ -6540,6 +6594,13 @@ static int gfx_v11_0_userq_mqd_create(struct
>>> amdgpu_userq_mgr *uq_mgr,
>>> goto free_mqd;
>>> }
>>> + /* Create BO for FW operations */
>>> + r = gfx_v11_0_userq_create_ctx_space(uq_mgr, queue, &mqd_user);
>>> + if (r) {
>>> + DRM_ERROR("Failed to allocate BO for userqueue (%d)", r);
>>> + goto free_mqd;
>>> + }
>>> +
>>> return 0;
>>> free_mqd:
>>> @@ -6552,6 +6613,7 @@ gfx_v11_0_userq_mqd_destroy(struct
>>> amdgpu_userq_mgr *uq_mgr, struct amdgpu_userm
>>> {
>>> struct amdgpu_userq_obj *mqd = &queue->mqd;
>>> + gfx_v11_0_userq_destroy_ctx_space(uq_mgr, queue);
>>> amdgpu_bo_free_kernel(&mqd->obj, &mqd->gpu_addr, &mqd->cpu_ptr);
>>> }
>>> diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>> b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>> index 240f92796f00..a5cdb319193d 100644
>>> --- a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>> +++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>> @@ -40,10 +40,14 @@ struct amdgpu_usermode_queue {
>>> uint64_t doorbell_handle;
>>> uint64_t doorbell_index;
>>> uint64_t flags;
>>> + uint64_t proc_ctx_gpu_addr;
>>> + uint64_t gang_ctx_gpu_addr;
>>> + uint64_t fw_ctx_gpu_addr;
>>> struct amdgpu_mqd_prop *userq_prop;
>>> struct amdgpu_userq_mgr *userq_mgr;
>>> struct amdgpu_vm *vm;
>>> struct amdgpu_userq_obj mqd;
>>> + struct amdgpu_userq_obj fw_obj;
>>> };
>>> struct amdgpu_userq_funcs {
>>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 04/10] drm/amdgpu: create GFX-gen11 usermode queue
2023-07-06 13:37 ` Shashank Sharma
@ 2023-07-06 13:39 ` Christian König
2023-07-06 13:43 ` Shashank Sharma
2023-07-11 19:51 ` Felix Kuehling
0 siblings, 2 replies; 50+ messages in thread
From: Christian König @ 2023-07-06 13:39 UTC (permalink / raw)
To: Shashank Sharma, amd-gfx; +Cc: Alex Deucher, arvind.yadav
Am 06.07.23 um 15:37 schrieb Shashank Sharma:
>
> On 06/07/2023 15:22, Christian König wrote:
>> Am 06.07.23 um 14:35 schrieb Shashank Sharma:
>>> A Memory queue descriptor (MQD) of a userqueue defines it in
>>> the hw's context. As MQD format can vary between different
>>> graphics IPs, we need gfx GEN specific handlers to create MQDs.
>>>
>>> This patch:
>>> - Introduces MQD handler functions for the usermode queues.
>>> - Adds new functions to create and destroy userqueue MQD for
>>> GFX-GEN-11 IP
>>>
>>> V1: Worked on review comments from Alex:
>>> - Make MQD functions GEN and IP specific
>>>
>>> V2: Worked on review comments from Alex:
>>> - Reuse the existing adev->mqd[ip] for MQD creation
>>> - Formatting and arrangement of code
>>>
>>> V3:
>>> - Integration with doorbell manager
>>>
>>> V4: Review comments addressed:
>>> - Do not create a new file for userq, reuse gfx_v11_0.c (Alex)
>>> - Align name of structure members (Luben)
>>> - Don't break up the Cc tag list and the Sob tag list in commit
>>> message (Luben)
>>> V5:
>>> - No need to reserve the bo for MQD (Christian).
>>> - Some more changes to support IP specific MQD creation.
>>>
>>> Cc: Alex Deucher <alexander.deucher@amd.com>
>>> Cc: Christian Koenig <christian.koenig@amd.com>
>>> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
>>> Signed-off-by: Arvind Yadav <arvind.yadav@amd.com>
>>> ---
>>> drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 16 ++++
>>> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 73
>>> +++++++++++++++++++
>>> .../gpu/drm/amd/include/amdgpu_userqueue.h | 7 ++
>>> 3 files changed, 96 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>> index e37b5da5a0d0..bb774144c372 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>> @@ -134,12 +134,28 @@ int amdgpu_userq_ioctl(struct drm_device *dev,
>>> void *data,
>>> return r;
>>> }
>>> +extern const struct amdgpu_userq_funcs userq_gfx_v11_funcs;
>>> +
>>> +static void
>>> +amdgpu_userqueue_setup_gfx(struct amdgpu_userq_mgr *uq_mgr)
>>> +{
>>> + int maj;
>>> + struct amdgpu_device *adev = uq_mgr->adev;
>>> + uint32_t version = adev->ip_versions[GC_HWIP][0];
>>> +
>>> + /* We support usermode queue only for GFX V11 as of now */
>>> + maj = IP_VERSION_MAJ(version);
>>> + if (maj == 11)
>>> + uq_mgr->userq_funcs[AMDGPU_HW_IP_GFX] = &userq_gfx_v11_funcs;
>>> +}
>>> +
>>> int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr,
>>> struct amdgpu_device *adev)
>>> {
>>> mutex_init(&userq_mgr->userq_mutex);
>>> idr_init_base(&userq_mgr->userq_idr, 1);
>>> userq_mgr->adev = adev;
>>> + amdgpu_userqueue_setup_gfx(userq_mgr);
>>> return 0;
>>> }
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>> b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>> index c4940b6ea1c4..e76e1b86b434 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>> @@ -30,6 +30,7 @@
>>> #include "amdgpu_psp.h"
>>> #include "amdgpu_smu.h"
>>> #include "amdgpu_atomfirmware.h"
>>> +#include "amdgpu_userqueue.h"
>>> #include "imu_v11_0.h"
>>> #include "soc21.h"
>>> #include "nvd.h"
>>> @@ -6486,3 +6487,75 @@ const struct amdgpu_ip_block_version
>>> gfx_v11_0_ip_block =
>>> .rev = 0,
>>> .funcs = &gfx_v11_0_ip_funcs,
>>> };
>>> +
>>> +static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
>>> + struct drm_amdgpu_userq_in *args_in,
>>> + struct amdgpu_usermode_queue *queue)
>>> +{
>>> + struct amdgpu_device *adev = uq_mgr->adev;
>>> + struct amdgpu_mqd *mqd_gfx_generic =
>>> &adev->mqds[AMDGPU_HW_IP_GFX];
>>> + struct drm_amdgpu_userq_mqd_gfx_v11_0 mqd_user;
>>> + struct amdgpu_mqd_prop userq_props;
>>> + int r;
>>> +
>>> + /* Incoming MQD parameters from userspace to be saved here */
>>> + memset(&mqd_user, 0, sizeof(mqd_user));
>>> +
>>> + /* Structure to initialize MQD for userqueue using generic MQD
>>> init function */
>>> + memset(&userq_props, 0, sizeof(userq_props));
>>> +
>>> + if (args_in->mqd_size != sizeof(struct
>>> drm_amdgpu_userq_mqd_gfx_v11_0)) {
>>> + DRM_ERROR("MQD size mismatch\n");
>>> + return -EINVAL;
>>> + }
>>> +
>>> + if (copy_from_user(&mqd_user, u64_to_user_ptr(args_in->mqd),
>>> args_in->mqd_size)) {
>>> + DRM_ERROR("Failed to get user MQD\n");
>>> + return -EFAULT;
>>> + }
>>> +
>>> + /* Create BO for actual Userqueue MQD now */
>>> + r = amdgpu_bo_create_kernel(adev, mqd_gfx_generic->mqd_size,
>>> PAGE_SIZE,
>>> + AMDGPU_GEM_DOMAIN_GTT,
>>> + &queue->mqd.obj,
>>> + &queue->mqd.gpu_addr,
>>> + &queue->mqd.cpu_ptr);
>>> + if (r) {
>>> + DRM_ERROR("Failed to allocate BO for userqueue (%d)", r);
>>> + return -ENOMEM;
>>> + }
>>
>> Using amdgpu_bo_create_kernel() for the MQD is most likely not a good
>> idea in the long term, but should work for now.
>>
> I was a bit curious about this, the scope of this MQD object is kernel
> internal and used for queue mapping only, userspace doesn't know much
> about it. Do you still think we should not create a kernel object for
> it ?
Well we should use a kernel BO. But amdgpu_bo_create_kernel() not only
creates a kernel BO but also pins it! And that is problematic because it
allows userspace to do a deny of service attach on the kernel module.
What we need is an eviction fence, e.g. what KFD is already using. Then
the BO is created similar to how VM page tables are created, maybe even
using the same reservation object.
But for a test this here is probably ok.
Christian.
>
> - Shashank
>
>> Probably best to add a comment here that this needs to be improved.
>>
>> Apart from that looks good to me,
>> Christian.
>>
>>> + memset(queue->mqd.cpu_ptr, 0, mqd_gfx_generic->mqd_size);
>>> +
>>> + /* Initialize the MQD BO with user given values */
>>> + userq_props.wptr_gpu_addr = mqd_user.wptr_va;
>>> + userq_props.rptr_gpu_addr = mqd_user.rptr_va;
>>> + userq_props.queue_size = mqd_user.queue_size;
>>> + userq_props.hqd_base_gpu_addr = mqd_user.queue_va;
>>> + userq_props.mqd_gpu_addr = queue->mqd.gpu_addr;
>>> + userq_props.use_doorbell = true;
>>> +
>>> + r = mqd_gfx_generic->init_mqd(adev, (void *)queue->mqd.cpu_ptr,
>>> &userq_props);
>>> + if (r) {
>>> + DRM_ERROR("Failed to initialize MQD for userqueue\n");
>>> + goto free_mqd;
>>> + }
>>> +
>>> + return 0;
>>> +
>>> +free_mqd:
>>> + amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr,
>>> &queue->mqd.cpu_ptr);
>>> + return r;
>>> +}
>>> +
>>> +static void
>>> +gfx_v11_0_userq_mqd_destroy(struct amdgpu_userq_mgr *uq_mgr, struct
>>> amdgpu_usermode_queue *queue)
>>> +{
>>> + struct amdgpu_userq_obj *mqd = &queue->mqd;
>>> +
>>> + amdgpu_bo_free_kernel(&mqd->obj, &mqd->gpu_addr, &mqd->cpu_ptr);
>>> +}
>>> +
>>> +const struct amdgpu_userq_funcs userq_gfx_v11_funcs = {
>>> + .mqd_create = gfx_v11_0_userq_mqd_create,
>>> + .mqd_destroy = gfx_v11_0_userq_mqd_destroy,
>>> +};
>>> diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>> b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>> index 55ed6512a565..240f92796f00 100644
>>> --- a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>> +++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>> @@ -29,6 +29,12 @@
>>> struct amdgpu_mqd_prop;
>>> +struct amdgpu_userq_obj {
>>> + void *cpu_ptr;
>>> + uint64_t gpu_addr;
>>> + struct amdgpu_bo *obj;
>>> +};
>>> +
>>> struct amdgpu_usermode_queue {
>>> int queue_type;
>>> uint64_t doorbell_handle;
>>> @@ -37,6 +43,7 @@ struct amdgpu_usermode_queue {
>>> struct amdgpu_mqd_prop *userq_prop;
>>> struct amdgpu_userq_mgr *userq_mgr;
>>> struct amdgpu_vm *vm;
>>> + struct amdgpu_userq_obj mqd;
>>> };
>>> struct amdgpu_userq_funcs {
>>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 04/10] drm/amdgpu: create GFX-gen11 usermode queue
2023-07-06 13:39 ` Christian König
@ 2023-07-06 13:43 ` Shashank Sharma
2023-07-11 19:51 ` Felix Kuehling
1 sibling, 0 replies; 50+ messages in thread
From: Shashank Sharma @ 2023-07-06 13:43 UTC (permalink / raw)
To: Christian König, amd-gfx; +Cc: Alex Deucher, arvind.yadav
On 06/07/2023 15:39, Christian König wrote:
> Am 06.07.23 um 15:37 schrieb Shashank Sharma:
>>
>> On 06/07/2023 15:22, Christian König wrote:
>>> Am 06.07.23 um 14:35 schrieb Shashank Sharma:
>>>> A Memory queue descriptor (MQD) of a userqueue defines it in
>>>> the hw's context. As MQD format can vary between different
>>>> graphics IPs, we need gfx GEN specific handlers to create MQDs.
>>>>
>>>> This patch:
>>>> - Introduces MQD handler functions for the usermode queues.
>>>> - Adds new functions to create and destroy userqueue MQD for
>>>> GFX-GEN-11 IP
>>>>
>>>> V1: Worked on review comments from Alex:
>>>> - Make MQD functions GEN and IP specific
>>>>
>>>> V2: Worked on review comments from Alex:
>>>> - Reuse the existing adev->mqd[ip] for MQD creation
>>>> - Formatting and arrangement of code
>>>>
>>>> V3:
>>>> - Integration with doorbell manager
>>>>
>>>> V4: Review comments addressed:
>>>> - Do not create a new file for userq, reuse gfx_v11_0.c (Alex)
>>>> - Align name of structure members (Luben)
>>>> - Don't break up the Cc tag list and the Sob tag list in commit
>>>> message (Luben)
>>>> V5:
>>>> - No need to reserve the bo for MQD (Christian).
>>>> - Some more changes to support IP specific MQD creation.
>>>>
>>>> Cc: Alex Deucher <alexander.deucher@amd.com>
>>>> Cc: Christian Koenig <christian.koenig@amd.com>
>>>> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
>>>> Signed-off-by: Arvind Yadav <arvind.yadav@amd.com>
>>>> ---
>>>> drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 16 ++++
>>>> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 73
>>>> +++++++++++++++++++
>>>> .../gpu/drm/amd/include/amdgpu_userqueue.h | 7 ++
>>>> 3 files changed, 96 insertions(+)
>>>>
>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>> index e37b5da5a0d0..bb774144c372 100644
>>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>> @@ -134,12 +134,28 @@ int amdgpu_userq_ioctl(struct drm_device
>>>> *dev, void *data,
>>>> return r;
>>>> }
>>>> +extern const struct amdgpu_userq_funcs userq_gfx_v11_funcs;
>>>> +
>>>> +static void
>>>> +amdgpu_userqueue_setup_gfx(struct amdgpu_userq_mgr *uq_mgr)
>>>> +{
>>>> + int maj;
>>>> + struct amdgpu_device *adev = uq_mgr->adev;
>>>> + uint32_t version = adev->ip_versions[GC_HWIP][0];
>>>> +
>>>> + /* We support usermode queue only for GFX V11 as of now */
>>>> + maj = IP_VERSION_MAJ(version);
>>>> + if (maj == 11)
>>>> + uq_mgr->userq_funcs[AMDGPU_HW_IP_GFX] = &userq_gfx_v11_funcs;
>>>> +}
>>>> +
>>>> int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr,
>>>> struct amdgpu_device *adev)
>>>> {
>>>> mutex_init(&userq_mgr->userq_mutex);
>>>> idr_init_base(&userq_mgr->userq_idr, 1);
>>>> userq_mgr->adev = adev;
>>>> + amdgpu_userqueue_setup_gfx(userq_mgr);
>>>> return 0;
>>>> }
>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>> b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>> index c4940b6ea1c4..e76e1b86b434 100644
>>>> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>> @@ -30,6 +30,7 @@
>>>> #include "amdgpu_psp.h"
>>>> #include "amdgpu_smu.h"
>>>> #include "amdgpu_atomfirmware.h"
>>>> +#include "amdgpu_userqueue.h"
>>>> #include "imu_v11_0.h"
>>>> #include "soc21.h"
>>>> #include "nvd.h"
>>>> @@ -6486,3 +6487,75 @@ const struct amdgpu_ip_block_version
>>>> gfx_v11_0_ip_block =
>>>> .rev = 0,
>>>> .funcs = &gfx_v11_0_ip_funcs,
>>>> };
>>>> +
>>>> +static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr
>>>> *uq_mgr,
>>>> + struct drm_amdgpu_userq_in *args_in,
>>>> + struct amdgpu_usermode_queue *queue)
>>>> +{
>>>> + struct amdgpu_device *adev = uq_mgr->adev;
>>>> + struct amdgpu_mqd *mqd_gfx_generic =
>>>> &adev->mqds[AMDGPU_HW_IP_GFX];
>>>> + struct drm_amdgpu_userq_mqd_gfx_v11_0 mqd_user;
>>>> + struct amdgpu_mqd_prop userq_props;
>>>> + int r;
>>>> +
>>>> + /* Incoming MQD parameters from userspace to be saved here */
>>>> + memset(&mqd_user, 0, sizeof(mqd_user));
>>>> +
>>>> + /* Structure to initialize MQD for userqueue using generic MQD
>>>> init function */
>>>> + memset(&userq_props, 0, sizeof(userq_props));
>>>> +
>>>> + if (args_in->mqd_size != sizeof(struct
>>>> drm_amdgpu_userq_mqd_gfx_v11_0)) {
>>>> + DRM_ERROR("MQD size mismatch\n");
>>>> + return -EINVAL;
>>>> + }
>>>> +
>>>> + if (copy_from_user(&mqd_user, u64_to_user_ptr(args_in->mqd),
>>>> args_in->mqd_size)) {
>>>> + DRM_ERROR("Failed to get user MQD\n");
>>>> + return -EFAULT;
>>>> + }
>>>> +
>>>> + /* Create BO for actual Userqueue MQD now */
>>>> + r = amdgpu_bo_create_kernel(adev, mqd_gfx_generic->mqd_size,
>>>> PAGE_SIZE,
>>>> + AMDGPU_GEM_DOMAIN_GTT,
>>>> + &queue->mqd.obj,
>>>> + &queue->mqd.gpu_addr,
>>>> + &queue->mqd.cpu_ptr);
>>>> + if (r) {
>>>> + DRM_ERROR("Failed to allocate BO for userqueue (%d)", r);
>>>> + return -ENOMEM;
>>>> + }
>>>
>>> Using amdgpu_bo_create_kernel() for the MQD is most likely not a
>>> good idea in the long term, but should work for now.
>>>
>> I was a bit curious about this, the scope of this MQD object is
>> kernel internal and used for queue mapping only, userspace doesn't
>> know much about it. Do you still think we should not create a kernel
>> object for it ?
>
>
> Well we should use a kernel BO. But amdgpu_bo_create_kernel() not only
> creates a kernel BO but also pins it! And that is problematic because
> it allows userspace to do a deny of service attach on the kernel module.
Ah, that explains it, thank you.
>
> What we need is an eviction fence, e.g. what KFD is already using.
> Then the BO is created similar to how VM page tables are created,
> maybe even using the same reservation object.
>
> But for a test this here is probably ok.
>
I Agree, I am working on eviction fences in parallel. May be when that
series is ready, I can add one clean-up patches in the end of that
series which will change all these amdgpu_bo_create_kernel()s to
amdgpu_bo_create()
- Shashank
> Christian.
>
>>
>> - Shashank
>>
>>> Probably best to add a comment here that this needs to be improved.
>>>
>>> Apart from that looks good to me,
>>> Christian.
>>>
>>>> + memset(queue->mqd.cpu_ptr, 0, mqd_gfx_generic->mqd_size);
>>>> +
>>>> + /* Initialize the MQD BO with user given values */
>>>> + userq_props.wptr_gpu_addr = mqd_user.wptr_va;
>>>> + userq_props.rptr_gpu_addr = mqd_user.rptr_va;
>>>> + userq_props.queue_size = mqd_user.queue_size;
>>>> + userq_props.hqd_base_gpu_addr = mqd_user.queue_va;
>>>> + userq_props.mqd_gpu_addr = queue->mqd.gpu_addr;
>>>> + userq_props.use_doorbell = true;
>>>> +
>>>> + r = mqd_gfx_generic->init_mqd(adev, (void
>>>> *)queue->mqd.cpu_ptr, &userq_props);
>>>> + if (r) {
>>>> + DRM_ERROR("Failed to initialize MQD for userqueue\n");
>>>> + goto free_mqd;
>>>> + }
>>>> +
>>>> + return 0;
>>>> +
>>>> +free_mqd:
>>>> + amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr,
>>>> &queue->mqd.cpu_ptr);
>>>> + return r;
>>>> +}
>>>> +
>>>> +static void
>>>> +gfx_v11_0_userq_mqd_destroy(struct amdgpu_userq_mgr *uq_mgr,
>>>> struct amdgpu_usermode_queue *queue)
>>>> +{
>>>> + struct amdgpu_userq_obj *mqd = &queue->mqd;
>>>> +
>>>> + amdgpu_bo_free_kernel(&mqd->obj, &mqd->gpu_addr, &mqd->cpu_ptr);
>>>> +}
>>>> +
>>>> +const struct amdgpu_userq_funcs userq_gfx_v11_funcs = {
>>>> + .mqd_create = gfx_v11_0_userq_mqd_create,
>>>> + .mqd_destroy = gfx_v11_0_userq_mqd_destroy,
>>>> +};
>>>> diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>> b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>> index 55ed6512a565..240f92796f00 100644
>>>> --- a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>> +++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>> @@ -29,6 +29,12 @@
>>>> struct amdgpu_mqd_prop;
>>>> +struct amdgpu_userq_obj {
>>>> + void *cpu_ptr;
>>>> + uint64_t gpu_addr;
>>>> + struct amdgpu_bo *obj;
>>>> +};
>>>> +
>>>> struct amdgpu_usermode_queue {
>>>> int queue_type;
>>>> uint64_t doorbell_handle;
>>>> @@ -37,6 +43,7 @@ struct amdgpu_usermode_queue {
>>>> struct amdgpu_mqd_prop *userq_prop;
>>>> struct amdgpu_userq_mgr *userq_mgr;
>>>> struct amdgpu_vm *vm;
>>>> + struct amdgpu_userq_obj mqd;
>>>> };
>>>> struct amdgpu_userq_funcs {
>>>
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 06/10] drm/amdgpu: map usermode queue into MES
2023-07-06 12:35 ` [PATCH v5 06/10] drm/amdgpu: map usermode queue into MES Shashank Sharma
@ 2023-07-06 14:47 ` Christian König
2023-07-06 16:52 ` Alex Deucher
1 sibling, 0 replies; 50+ messages in thread
From: Christian König @ 2023-07-06 14:47 UTC (permalink / raw)
To: Shashank Sharma, amd-gfx; +Cc: Alex Deucher, arvind.yadav
Am 06.07.23 um 14:35 schrieb Shashank Sharma:
> This patch adds new functions to map/unmap a usermode queue into
> the FW, using the MES ring. As soon as this mapping is done, the
> queue would be considered ready to accept the workload.
>
> V1: Addressed review comments from Alex on the RFC patch series
> - Map/Unmap should be IP specific.
> V2:
> Addressed review comments from Christian:
> - Fix the wptr_mc_addr calculation (moved into another patch)
> Addressed review comments from Alex:
> - Do not add fptrs for map/unmap
>
> V3: Integration with doorbell manager
> V4: Rebase
> V5: Use gfx_v11_0 for function names (Alex)
>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Christian Koenig <christian.koenig@amd.com>
> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
Acked-by: Christian König <christian.koenig@amd.com>
> ---
> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 70 ++++++++++++++++++++++++++
> 1 file changed, 70 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> index 7d3b19e08bbb..b4a0f26a0e8c 100644
> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> @@ -6491,6 +6491,65 @@ const struct amdgpu_ip_block_version gfx_v11_0_ip_block =
> .funcs = &gfx_v11_0_ip_funcs,
> };
>
> +static void gfx_v11_0_userq_unmap(struct amdgpu_userq_mgr *uq_mgr,
> + struct amdgpu_usermode_queue *queue)
> +{
> + struct amdgpu_device *adev = uq_mgr->adev;
> + struct mes_remove_queue_input queue_input;
> + int r;
> +
> + memset(&queue_input, 0x0, sizeof(struct mes_remove_queue_input));
> + queue_input.doorbell_offset = queue->doorbell_index;
> + queue_input.gang_context_addr = queue->gang_ctx_gpu_addr;
> +
> + amdgpu_mes_lock(&adev->mes);
> + r = adev->mes.funcs->remove_hw_queue(&adev->mes, &queue_input);
> + amdgpu_mes_unlock(&adev->mes);
> + if (r)
> + DRM_ERROR("Failed to unmap queue in HW, err (%d)\n", r);
> +}
> +
> +static int gfx_v11_0_userq_map(struct amdgpu_userq_mgr *uq_mgr,
> + struct amdgpu_usermode_queue *queue,
> + struct amdgpu_mqd_prop *userq_props)
> +{
> + struct amdgpu_device *adev = uq_mgr->adev;
> + struct mes_add_queue_input queue_input;
> + int r;
> +
> + memset(&queue_input, 0x0, sizeof(struct mes_add_queue_input));
> +
> + queue_input.process_va_start = 0;
> + queue_input.process_va_end = (adev->vm_manager.max_pfn - 1) << AMDGPU_GPU_PAGE_SHIFT;
> + queue_input.process_quantum = 100000; /* 10ms */
> + queue_input.gang_quantum = 10000; /* 1ms */
> + queue_input.paging = false;
> +
> + queue_input.gang_context_addr = queue->gang_ctx_gpu_addr;
> + queue_input.process_context_addr = queue->proc_ctx_gpu_addr;
> + queue_input.inprocess_gang_priority = AMDGPU_MES_PRIORITY_LEVEL_NORMAL;
> + queue_input.gang_global_priority_level = AMDGPU_MES_PRIORITY_LEVEL_NORMAL;
> +
> + queue_input.process_id = queue->vm->pasid;
> + queue_input.queue_type = queue->queue_type;
> + queue_input.mqd_addr = queue->mqd.gpu_addr;
> + queue_input.wptr_addr = userq_props->wptr_gpu_addr;
> + queue_input.queue_size = userq_props->queue_size >> 2;
> + queue_input.doorbell_offset = userq_props->doorbell_index;
> + queue_input.page_table_base_addr = amdgpu_gmc_pd_addr(queue->vm->root.bo);
> +
> + amdgpu_mes_lock(&adev->mes);
> + r = adev->mes.funcs->add_hw_queue(&adev->mes, &queue_input);
> + amdgpu_mes_unlock(&adev->mes);
> + if (r) {
> + DRM_ERROR("Failed to map queue in HW, err (%d)\n", r);
> + return r;
> + }
> +
> + DRM_DEBUG_DRIVER("Queue (doorbell:%d) mapped successfully\n", userq_props->doorbell_index);
> + return 0;
> +}
> +
> static void gfx_v11_0_userq_destroy_ctx_space(struct amdgpu_userq_mgr *uq_mgr,
> struct amdgpu_usermode_queue *queue)
> {
> @@ -6601,8 +6660,18 @@ static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
> goto free_mqd;
> }
>
> + /* Map userqueue into FW using MES */
> + r = gfx_v11_0_userq_map(uq_mgr, queue, &userq_props);
> + if (r) {
> + DRM_ERROR("Failed to init MQD\n");
> + goto free_ctx;
> + }
> +
> return 0;
>
> +free_ctx:
> + gfx_v11_0_userq_destroy_ctx_space(uq_mgr, queue);
> +
> free_mqd:
> amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr, &queue->mqd.cpu_ptr);
> return r;
> @@ -6613,6 +6682,7 @@ gfx_v11_0_userq_mqd_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_userm
> {
> struct amdgpu_userq_obj *mqd = &queue->mqd;
>
> + gfx_v11_0_userq_unmap(uq_mgr, queue);
> gfx_v11_0_userq_destroy_ctx_space(uq_mgr, queue);
> amdgpu_bo_free_kernel(&mqd->obj, &mqd->gpu_addr, &mqd->cpu_ptr);
> }
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 04/10] drm/amdgpu: create GFX-gen11 usermode queue
2023-07-06 12:35 ` [PATCH v5 04/10] drm/amdgpu: create GFX-gen11 " Shashank Sharma
2023-07-06 13:22 ` Christian König
@ 2023-07-06 16:27 ` Alex Deucher
2023-07-06 16:29 ` Shashank Sharma
2023-07-07 7:24 ` Christian König
2 siblings, 1 reply; 50+ messages in thread
From: Alex Deucher @ 2023-07-06 16:27 UTC (permalink / raw)
To: Shashank Sharma; +Cc: Alex Deucher, arvind.yadav, Christian Koenig, amd-gfx
On Thu, Jul 6, 2023 at 8:36 AM Shashank Sharma <shashank.sharma@amd.com> wrote:
>
> A Memory queue descriptor (MQD) of a userqueue defines it in
> the hw's context. As MQD format can vary between different
> graphics IPs, we need gfx GEN specific handlers to create MQDs.
>
> This patch:
> - Introduces MQD handler functions for the usermode queues.
> - Adds new functions to create and destroy userqueue MQD for
> GFX-GEN-11 IP
>
> V1: Worked on review comments from Alex:
> - Make MQD functions GEN and IP specific
>
> V2: Worked on review comments from Alex:
> - Reuse the existing adev->mqd[ip] for MQD creation
> - Formatting and arrangement of code
>
> V3:
> - Integration with doorbell manager
>
> V4: Review comments addressed:
> - Do not create a new file for userq, reuse gfx_v11_0.c (Alex)
> - Align name of structure members (Luben)
> - Don't break up the Cc tag list and the Sob tag list in commit
> message (Luben)
> V5:
> - No need to reserve the bo for MQD (Christian).
> - Some more changes to support IP specific MQD creation.
>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Christian Koenig <christian.koenig@amd.com>
> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
> Signed-off-by: Arvind Yadav <arvind.yadav@amd.com>
> ---
> drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 16 ++++
> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 73 +++++++++++++++++++
> .../gpu/drm/amd/include/amdgpu_userqueue.h | 7 ++
> 3 files changed, 96 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
> index e37b5da5a0d0..bb774144c372 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
> @@ -134,12 +134,28 @@ int amdgpu_userq_ioctl(struct drm_device *dev, void *data,
> return r;
> }
>
> +extern const struct amdgpu_userq_funcs userq_gfx_v11_funcs;
Just add this to gfx_v11_0.h and include that here.
> +
> +static void
> +amdgpu_userqueue_setup_gfx(struct amdgpu_userq_mgr *uq_mgr)
> +{
> + int maj;
> + struct amdgpu_device *adev = uq_mgr->adev;
> + uint32_t version = adev->ip_versions[GC_HWIP][0];
> +
> + /* We support usermode queue only for GFX V11 as of now */
> + maj = IP_VERSION_MAJ(version);
> + if (maj == 11)
> + uq_mgr->userq_funcs[AMDGPU_HW_IP_GFX] = &userq_gfx_v11_funcs;
> +}
> +
> int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct amdgpu_device *adev)
> {
> mutex_init(&userq_mgr->userq_mutex);
> idr_init_base(&userq_mgr->userq_idr, 1);
> userq_mgr->adev = adev;
>
> + amdgpu_userqueue_setup_gfx(userq_mgr);
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> index c4940b6ea1c4..e76e1b86b434 100644
> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> @@ -30,6 +30,7 @@
> #include "amdgpu_psp.h"
> #include "amdgpu_smu.h"
> #include "amdgpu_atomfirmware.h"
> +#include "amdgpu_userqueue.h"
> #include "imu_v11_0.h"
> #include "soc21.h"
> #include "nvd.h"
> @@ -6486,3 +6487,75 @@ const struct amdgpu_ip_block_version gfx_v11_0_ip_block =
> .rev = 0,
> .funcs = &gfx_v11_0_ip_funcs,
> };
> +
> +static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
> + struct drm_amdgpu_userq_in *args_in,
> + struct amdgpu_usermode_queue *queue)
> +{
> + struct amdgpu_device *adev = uq_mgr->adev;
> + struct amdgpu_mqd *mqd_gfx_generic = &adev->mqds[AMDGPU_HW_IP_GFX];
> + struct drm_amdgpu_userq_mqd_gfx_v11_0 mqd_user;
> + struct amdgpu_mqd_prop userq_props;
> + int r;
> +
> + /* Incoming MQD parameters from userspace to be saved here */
> + memset(&mqd_user, 0, sizeof(mqd_user));
> +
> + /* Structure to initialize MQD for userqueue using generic MQD init function */
> + memset(&userq_props, 0, sizeof(userq_props));
> +
> + if (args_in->mqd_size != sizeof(struct drm_amdgpu_userq_mqd_gfx_v11_0)) {
> + DRM_ERROR("MQD size mismatch\n");
> + return -EINVAL;
> + }
> +
> + if (copy_from_user(&mqd_user, u64_to_user_ptr(args_in->mqd), args_in->mqd_size)) {
> + DRM_ERROR("Failed to get user MQD\n");
> + return -EFAULT;
> + }
> +
> + /* Create BO for actual Userqueue MQD now */
> + r = amdgpu_bo_create_kernel(adev, mqd_gfx_generic->mqd_size, PAGE_SIZE,
> + AMDGPU_GEM_DOMAIN_GTT,
> + &queue->mqd.obj,
> + &queue->mqd.gpu_addr,
> + &queue->mqd.cpu_ptr);
> + if (r) {
> + DRM_ERROR("Failed to allocate BO for userqueue (%d)", r);
> + return -ENOMEM;
> + }
> + memset(queue->mqd.cpu_ptr, 0, mqd_gfx_generic->mqd_size);
> +
> + /* Initialize the MQD BO with user given values */
> + userq_props.wptr_gpu_addr = mqd_user.wptr_va;
> + userq_props.rptr_gpu_addr = mqd_user.rptr_va;
> + userq_props.queue_size = mqd_user.queue_size;
> + userq_props.hqd_base_gpu_addr = mqd_user.queue_va;
> + userq_props.mqd_gpu_addr = queue->mqd.gpu_addr;
> + userq_props.use_doorbell = true;
> +
> + r = mqd_gfx_generic->init_mqd(adev, (void *)queue->mqd.cpu_ptr, &userq_props);
> + if (r) {
> + DRM_ERROR("Failed to initialize MQD for userqueue\n");
> + goto free_mqd;
> + }
> +
> + return 0;
> +
> +free_mqd:
> + amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr, &queue->mqd.cpu_ptr);
> + return r;
> +}
> +
> +static void
> +gfx_v11_0_userq_mqd_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_queue *queue)
> +{
> + struct amdgpu_userq_obj *mqd = &queue->mqd;
> +
> + amdgpu_bo_free_kernel(&mqd->obj, &mqd->gpu_addr, &mqd->cpu_ptr);
> +}
> +
> +const struct amdgpu_userq_funcs userq_gfx_v11_funcs = {
gfx_v11_0_userq_funcs for consistency with the rest of the file.
Alex
> + .mqd_create = gfx_v11_0_userq_mqd_create,
> + .mqd_destroy = gfx_v11_0_userq_mqd_destroy,
> +};
> diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
> index 55ed6512a565..240f92796f00 100644
> --- a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
> +++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
> @@ -29,6 +29,12 @@
>
> struct amdgpu_mqd_prop;
>
> +struct amdgpu_userq_obj {
> + void *cpu_ptr;
> + uint64_t gpu_addr;
> + struct amdgpu_bo *obj;
> +};
> +
> struct amdgpu_usermode_queue {
> int queue_type;
> uint64_t doorbell_handle;
> @@ -37,6 +43,7 @@ struct amdgpu_usermode_queue {
> struct amdgpu_mqd_prop *userq_prop;
> struct amdgpu_userq_mgr *userq_mgr;
> struct amdgpu_vm *vm;
> + struct amdgpu_userq_obj mqd;
> };
>
> struct amdgpu_userq_funcs {
> --
> 2.40.1
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 04/10] drm/amdgpu: create GFX-gen11 usermode queue
2023-07-06 16:27 ` Alex Deucher
@ 2023-07-06 16:29 ` Shashank Sharma
0 siblings, 0 replies; 50+ messages in thread
From: Shashank Sharma @ 2023-07-06 16:29 UTC (permalink / raw)
To: Alex Deucher; +Cc: Alex Deucher, amd-gfx, Christian Koenig, arvind.yadav
Hey Alex,
On 06/07/2023 18:27, Alex Deucher wrote:
> On Thu, Jul 6, 2023 at 8:36 AM Shashank Sharma <shashank.sharma@amd.com> wrote:
>> A Memory queue descriptor (MQD) of a userqueue defines it in
>> the hw's context. As MQD format can vary between different
>> graphics IPs, we need gfx GEN specific handlers to create MQDs.
>>
>> This patch:
>> - Introduces MQD handler functions for the usermode queues.
>> - Adds new functions to create and destroy userqueue MQD for
>> GFX-GEN-11 IP
>>
>> V1: Worked on review comments from Alex:
>> - Make MQD functions GEN and IP specific
>>
>> V2: Worked on review comments from Alex:
>> - Reuse the existing adev->mqd[ip] for MQD creation
>> - Formatting and arrangement of code
>>
>> V3:
>> - Integration with doorbell manager
>>
>> V4: Review comments addressed:
>> - Do not create a new file for userq, reuse gfx_v11_0.c (Alex)
>> - Align name of structure members (Luben)
>> - Don't break up the Cc tag list and the Sob tag list in commit
>> message (Luben)
>> V5:
>> - No need to reserve the bo for MQD (Christian).
>> - Some more changes to support IP specific MQD creation.
>>
>> Cc: Alex Deucher <alexander.deucher@amd.com>
>> Cc: Christian Koenig <christian.koenig@amd.com>
>> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
>> Signed-off-by: Arvind Yadav <arvind.yadav@amd.com>
>> ---
>> drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 16 ++++
>> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 73 +++++++++++++++++++
>> .../gpu/drm/amd/include/amdgpu_userqueue.h | 7 ++
>> 3 files changed, 96 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>> index e37b5da5a0d0..bb774144c372 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>> @@ -134,12 +134,28 @@ int amdgpu_userq_ioctl(struct drm_device *dev, void *data,
>> return r;
>> }
>>
>> +extern const struct amdgpu_userq_funcs userq_gfx_v11_funcs;
> Just add this to gfx_v11_0.h and include that here.
Noted,
>
>> +
>> +static void
>> +amdgpu_userqueue_setup_gfx(struct amdgpu_userq_mgr *uq_mgr)
>> +{
>> + int maj;
>> + struct amdgpu_device *adev = uq_mgr->adev;
>> + uint32_t version = adev->ip_versions[GC_HWIP][0];
>> +
>> + /* We support usermode queue only for GFX V11 as of now */
>> + maj = IP_VERSION_MAJ(version);
>> + if (maj == 11)
>> + uq_mgr->userq_funcs[AMDGPU_HW_IP_GFX] = &userq_gfx_v11_funcs;
>> +}
>> +
>> int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct amdgpu_device *adev)
>> {
>> mutex_init(&userq_mgr->userq_mutex);
>> idr_init_base(&userq_mgr->userq_idr, 1);
>> userq_mgr->adev = adev;
>>
>> + amdgpu_userqueue_setup_gfx(userq_mgr);
>> return 0;
>> }
>>
>> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>> index c4940b6ea1c4..e76e1b86b434 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>> @@ -30,6 +30,7 @@
>> #include "amdgpu_psp.h"
>> #include "amdgpu_smu.h"
>> #include "amdgpu_atomfirmware.h"
>> +#include "amdgpu_userqueue.h"
>> #include "imu_v11_0.h"
>> #include "soc21.h"
>> #include "nvd.h"
>> @@ -6486,3 +6487,75 @@ const struct amdgpu_ip_block_version gfx_v11_0_ip_block =
>> .rev = 0,
>> .funcs = &gfx_v11_0_ip_funcs,
>> };
>> +
>> +static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
>> + struct drm_amdgpu_userq_in *args_in,
>> + struct amdgpu_usermode_queue *queue)
>> +{
>> + struct amdgpu_device *adev = uq_mgr->adev;
>> + struct amdgpu_mqd *mqd_gfx_generic = &adev->mqds[AMDGPU_HW_IP_GFX];
>> + struct drm_amdgpu_userq_mqd_gfx_v11_0 mqd_user;
>> + struct amdgpu_mqd_prop userq_props;
>> + int r;
>> +
>> + /* Incoming MQD parameters from userspace to be saved here */
>> + memset(&mqd_user, 0, sizeof(mqd_user));
>> +
>> + /* Structure to initialize MQD for userqueue using generic MQD init function */
>> + memset(&userq_props, 0, sizeof(userq_props));
>> +
>> + if (args_in->mqd_size != sizeof(struct drm_amdgpu_userq_mqd_gfx_v11_0)) {
>> + DRM_ERROR("MQD size mismatch\n");
>> + return -EINVAL;
>> + }
>> +
>> + if (copy_from_user(&mqd_user, u64_to_user_ptr(args_in->mqd), args_in->mqd_size)) {
>> + DRM_ERROR("Failed to get user MQD\n");
>> + return -EFAULT;
>> + }
>> +
>> + /* Create BO for actual Userqueue MQD now */
>> + r = amdgpu_bo_create_kernel(adev, mqd_gfx_generic->mqd_size, PAGE_SIZE,
>> + AMDGPU_GEM_DOMAIN_GTT,
>> + &queue->mqd.obj,
>> + &queue->mqd.gpu_addr,
>> + &queue->mqd.cpu_ptr);
>> + if (r) {
>> + DRM_ERROR("Failed to allocate BO for userqueue (%d)", r);
>> + return -ENOMEM;
>> + }
>> + memset(queue->mqd.cpu_ptr, 0, mqd_gfx_generic->mqd_size);
>> +
>> + /* Initialize the MQD BO with user given values */
>> + userq_props.wptr_gpu_addr = mqd_user.wptr_va;
>> + userq_props.rptr_gpu_addr = mqd_user.rptr_va;
>> + userq_props.queue_size = mqd_user.queue_size;
>> + userq_props.hqd_base_gpu_addr = mqd_user.queue_va;
>> + userq_props.mqd_gpu_addr = queue->mqd.gpu_addr;
>> + userq_props.use_doorbell = true;
>> +
>> + r = mqd_gfx_generic->init_mqd(adev, (void *)queue->mqd.cpu_ptr, &userq_props);
>> + if (r) {
>> + DRM_ERROR("Failed to initialize MQD for userqueue\n");
>> + goto free_mqd;
>> + }
>> +
>> + return 0;
>> +
>> +free_mqd:
>> + amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr, &queue->mqd.cpu_ptr);
>> + return r;
>> +}
>> +
>> +static void
>> +gfx_v11_0_userq_mqd_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_queue *queue)
>> +{
>> + struct amdgpu_userq_obj *mqd = &queue->mqd;
>> +
>> + amdgpu_bo_free_kernel(&mqd->obj, &mqd->gpu_addr, &mqd->cpu_ptr);
>> +}
>> +
>> +const struct amdgpu_userq_funcs userq_gfx_v11_funcs = {
> gfx_v11_0_userq_funcs for consistency with the rest of the file.
Noted.
- Shashank
>
> Alex
>
>
>> + .mqd_create = gfx_v11_0_userq_mqd_create,
>> + .mqd_destroy = gfx_v11_0_userq_mqd_destroy,
>> +};
>> diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>> index 55ed6512a565..240f92796f00 100644
>> --- a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>> +++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>> @@ -29,6 +29,12 @@
>>
>> struct amdgpu_mqd_prop;
>>
>> +struct amdgpu_userq_obj {
>> + void *cpu_ptr;
>> + uint64_t gpu_addr;
>> + struct amdgpu_bo *obj;
>> +};
>> +
>> struct amdgpu_usermode_queue {
>> int queue_type;
>> uint64_t doorbell_handle;
>> @@ -37,6 +43,7 @@ struct amdgpu_usermode_queue {
>> struct amdgpu_mqd_prop *userq_prop;
>> struct amdgpu_userq_mgr *userq_mgr;
>> struct amdgpu_vm *vm;
>> + struct amdgpu_userq_obj mqd;
>> };
>>
>> struct amdgpu_userq_funcs {
>> --
>> 2.40.1
>>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 02/10] drm/amdgpu: add usermode queue base code
2023-07-06 12:35 ` [PATCH v5 02/10] drm/amdgpu: add usermode queue base code Shashank Sharma
2023-07-06 12:46 ` Christian König
@ 2023-07-06 16:36 ` Alex Deucher
2023-07-06 16:52 ` Shashank Sharma
1 sibling, 1 reply; 50+ messages in thread
From: Alex Deucher @ 2023-07-06 16:36 UTC (permalink / raw)
To: Shashank Sharma; +Cc: Alex Deucher, arvind.yadav, Christian Koenig, amd-gfx
On Thu, Jul 6, 2023 at 8:36 AM Shashank Sharma <shashank.sharma@amd.com> wrote:
>
> This patch adds skeleton code for amdgpu usermode queue.
> It contains:
> - A new files with init functions of usermode queues.
> - A queue context manager in driver private data.
>
> V1: Worked on design review comments from RFC patch series:
> (https://patchwork.freedesktop.org/series/112214/)
> - Alex: Keep a list of queues, instead of single queue per process.
> - Christian: Use the queue manager instead of global ptrs,
> Don't keep the queue structure in amdgpu_ctx
>
> V2:
> - Reformatted code, split the big patch into two
>
> V3:
> - Integration with doorbell manager
>
> V4:
> - Align the structure member names to the largest member's column
> (Luben)
> - Added SPDX license (Luben)
>
> V5:
> - Do not add amdgpu.h in amdgpu_userqueue.h (Christian).
> - Move struct amdgpu_userq_mgr into amdgpu_userqueue.h (Christian).
>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Christian Koenig <christian.koenig@amd.com>
> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
> ---
> drivers/gpu/drm/amd/amdgpu/Makefile | 2 +
> drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 +
> drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 1 +
> drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 6 ++
> drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 40 ++++++++++++
> .../gpu/drm/amd/include/amdgpu_userqueue.h | 62 +++++++++++++++++++
> 6 files changed, 113 insertions(+)
> create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
> create mode 100644 drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
> index 415a7fa395c4..4b9bae995094 100644
> --- a/drivers/gpu/drm/amd/amdgpu/Makefile
> +++ b/drivers/gpu/drm/amd/amdgpu/Makefile
> @@ -216,6 +216,8 @@ amdgpu-y += \
> # add amdkfd interfaces
> amdgpu-y += amdgpu_amdkfd.o
>
> +# add usermode queue
> +amdgpu-y += amdgpu_userqueue.o
>
> ifneq ($(CONFIG_HSA_AMD),)
> AMDKFD_PATH := ../amdkfd
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> index 02b827785e39..fab842138cd5 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> @@ -107,6 +107,7 @@
> #include "amdgpu_fdinfo.h"
> #include "amdgpu_mca.h"
> #include "amdgpu_ras.h"
> +#include "amdgpu_userqueue.h"
>
> #define MAX_GPU_INSTANCE 16
>
> @@ -463,6 +464,7 @@ struct amdgpu_fpriv {
> struct mutex bo_list_lock;
> struct idr bo_list_handles;
> struct amdgpu_ctx_mgr ctx_mgr;
> + struct amdgpu_userq_mgr userq_mgr;
> };
>
> int amdgpu_file_to_fpriv(struct file *filp, struct amdgpu_fpriv **fpriv);
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> index b1ca1ab6d6ad..4c5e44d41652 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> @@ -50,6 +50,7 @@
> #include "amdgpu_ras.h"
> #include "amdgpu_xgmi.h"
> #include "amdgpu_reset.h"
> +#include "amdgpu_userqueue.h"
>
> /*
> * KMS wrapper.
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> index 0efb38539d70..68e5375b648b 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> @@ -44,6 +44,7 @@
> #include "amdgpu_display.h"
> #include "amdgpu_ras.h"
> #include "amd_pcie.h"
> +#include "amdgpu_userqueue.h"
>
> void amdgpu_unregister_gpu_instance(struct amdgpu_device *adev)
> {
> @@ -1234,6 +1235,10 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
>
> amdgpu_ctx_mgr_init(&fpriv->ctx_mgr, adev);
>
> + r = amdgpu_userq_mgr_init(&fpriv->userq_mgr, adev);
> + if (r)
> + DRM_WARN("Can't setup usermode queues, use legacy workload submission only\n");
> +
> file_priv->driver_priv = fpriv;
> goto out_suspend;
>
> @@ -1301,6 +1306,7 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,
>
> amdgpu_ctx_mgr_fini(&fpriv->ctx_mgr);
> amdgpu_vm_fini(adev, &fpriv->vm);
> + amdgpu_userq_mgr_fini(&fpriv->userq_mgr);
>
> if (pasid)
> amdgpu_pasid_free_delayed(pd->tbo.base.resv, pasid);
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
> new file mode 100644
> index 000000000000..effc0c7c02cf
> --- /dev/null
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
> @@ -0,0 +1,40 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright 2023 Advanced Micro Devices, Inc.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + *
> + */
> +
> +#include "amdgpu.h"
> +
> +int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct amdgpu_device *adev)
> +{
> + mutex_init(&userq_mgr->userq_mutex);
> + idr_init_base(&userq_mgr->userq_idr, 1);
> + userq_mgr->adev = adev;
> +
> + return 0;
> +}
> +
> +void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr)
> +{
> + idr_destroy(&userq_mgr->userq_idr);
> + mutex_destroy(&userq_mgr->userq_mutex);
> +}
> diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
> new file mode 100644
> index 000000000000..79ffa131a514
> --- /dev/null
> +++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
> @@ -0,0 +1,62 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright 2023 Advanced Micro Devices, Inc.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + *
> + */
> +
> +#ifndef AMDGPU_USERQUEUE_H_
> +#define AMDGPU_USERQUEUE_H_
> +
> +#define AMDGPU_MAX_USERQ_COUNT 512
> +
> +struct amdgpu_mqd_prop;
> +
> +struct amdgpu_usermode_queue {
> + int queue_type;
> + uint64_t doorbell_handle;
> + uint64_t doorbell_index;
> + uint64_t flags;
> + struct amdgpu_mqd_prop *userq_prop;
> + struct amdgpu_userq_mgr *userq_mgr;
> + struct amdgpu_vm *vm;
> +};
> +
> +struct amdgpu_userq_funcs {
> + int (*mqd_create)(struct amdgpu_userq_mgr *uq_mgr,
> + struct drm_amdgpu_userq_in *args,
> + struct amdgpu_usermode_queue *queue);
> + void (*mqd_destroy)(struct amdgpu_userq_mgr *uq_mgr,
> + struct amdgpu_usermode_queue *uq);
> +};
> +
> +/* Usermode queues for gfx */
> +struct amdgpu_userq_mgr {
> + struct idr userq_idr;
> + struct mutex userq_mutex;
> + struct amdgpu_device *adev;
> + const struct amdgpu_userq_funcs *userq_funcs[AMDGPU_HW_IP_NUM];
Why did we decide to put these in the userq_mgr rather than having
them in adev? I tried to find the original v1 thread. It just seems
like extra work to assign a bunch of pointers every time we create a
userq_mgr. I don't see a case where we would ever want them to be
different per userq_mgr instance. It also keeps all of the IP
specific knowledge in the IP specific code. E.g., if some IP only
supports this for specific versions, we could assign the pointers to
adev in that IP's code rather than adding a bunch of logic to the
generic userq code to know which IP versions may or may not support
this.
Alex
> +};
> +
> +int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct amdgpu_device *adev);
> +
> +void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr);
> +
> +#endif
> --
> 2.40.1
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 05/10] drm/amdgpu: create context space for usermode queue
2023-07-06 12:35 ` [PATCH v5 05/10] drm/amdgpu: create context space for " Shashank Sharma
2023-07-06 13:28 ` Christian König
@ 2023-07-06 16:44 ` Alex Deucher
1 sibling, 0 replies; 50+ messages in thread
From: Alex Deucher @ 2023-07-06 16:44 UTC (permalink / raw)
To: Shashank Sharma; +Cc: Alex Deucher, arvind.yadav, Christian Koenig, amd-gfx
On Thu, Jul 6, 2023 at 8:36 AM Shashank Sharma <shashank.sharma@amd.com> wrote:
>
> The FW expects us to allocate at least one page as context
> space to process gang, process, GDS and FW related work.
> This patch creates a joint object for the same, and calculates
> GPU space offsets for each of these spaces.
>
> V1: Addressed review comments on RFC patch:
> Alex: Make this function IP specific
>
> V2: Addressed review comments from Christian
> - Allocate only one object for total FW space, and calculate
> offsets for each of these objects.
>
> V3: Integration with doorbell manager
>
> V4: Review comments:
> - Remove shadow from FW space list from cover letter (Alex)
> - Alignment of macro (Luben)
>
> V5: Merged patches 5 and 6 into this single patch
> Addressed review comments:
> - Use lower_32_bits instead of mask (Christian)
> - gfx_v11_0 instead of gfx_v11 in function names (Alex)
> - Shadow and GDS objects are now coming from userspace (Christian,
> Alex)
>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Christian Koenig <christian.koenig@amd.com>
> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
> Signed-off-by: Arvind Yadav <arvind.yadav@amd.com>
> ---
> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 62 +++++++++++++++++++
> .../gpu/drm/amd/include/amdgpu_userqueue.h | 4 ++
> 2 files changed, 66 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> index e76e1b86b434..7d3b19e08bbb 100644
> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> @@ -61,6 +61,9 @@
> #define regCGTT_WD_CLK_CTRL_BASE_IDX 1
> #define regRLC_RLCS_BOOTLOAD_STATUS_gc_11_0_1 0x4e7e
> #define regRLC_RLCS_BOOTLOAD_STATUS_gc_11_0_1_BASE_IDX 1
> +#define AMDGPU_USERQ_PROC_CTX_SZ PAGE_SIZE
> +#define AMDGPU_USERQ_GANG_CTX_SZ PAGE_SIZE
> +#define AMDGPU_USERQ_FW_CTX_SZ PAGE_SIZE
>
> MODULE_FIRMWARE("amdgpu/gc_11_0_0_pfp.bin");
> MODULE_FIRMWARE("amdgpu/gc_11_0_0_me.bin");
> @@ -6488,6 +6491,57 @@ const struct amdgpu_ip_block_version gfx_v11_0_ip_block =
> .funcs = &gfx_v11_0_ip_funcs,
> };
>
> +static void gfx_v11_0_userq_destroy_ctx_space(struct amdgpu_userq_mgr *uq_mgr,
> + struct amdgpu_usermode_queue *queue)
> +{
> + struct amdgpu_userq_obj *ctx = &queue->fw_obj;
> +
> + amdgpu_bo_free_kernel(&ctx->obj, &ctx->gpu_addr, &ctx->cpu_ptr);
> +}
> +
> +static int gfx_v11_0_userq_create_ctx_space(struct amdgpu_userq_mgr *uq_mgr,
> + struct amdgpu_usermode_queue *queue,
> + struct drm_amdgpu_userq_mqd_gfx_v11_0 *mqd_user)
> +{
> + struct amdgpu_device *adev = uq_mgr->adev;
> + struct amdgpu_userq_obj *ctx = &queue->fw_obj;
> + struct v11_gfx_mqd *mqd = queue->mqd.cpu_ptr;
> + int r, size;
> +
> + /*
> + * The FW expects at least one page space allocated for
> + * process ctx, gang ctx and fw ctx each. Create an object
> + * for the same.
> + */
> + size = AMDGPU_USERQ_PROC_CTX_SZ + AMDGPU_USERQ_FW_CTX_SZ +
> + AMDGPU_USERQ_GANG_CTX_SZ;
> + r = amdgpu_bo_create_kernel(adev, size, PAGE_SIZE,
> + AMDGPU_GEM_DOMAIN_GTT,
> + &ctx->obj,
> + &ctx->gpu_addr,
> + &ctx->cpu_ptr);
> + if (r) {
> + DRM_ERROR("Failed to allocate ctx space bo for userqueue, err:%d\n", r);
> + return r;
> + }
> +
> + queue->proc_ctx_gpu_addr = ctx->gpu_addr;
> + queue->gang_ctx_gpu_addr = queue->proc_ctx_gpu_addr + AMDGPU_USERQ_PROC_CTX_SZ;
> + queue->fw_ctx_gpu_addr = queue->gang_ctx_gpu_addr + AMDGPU_USERQ_GANG_CTX_SZ;
> +
> + mqd->fw_work_area_base_lo = lower_32_bits(queue->fw_ctx_gpu_addr);
> + mqd->fw_work_area_base_lo = upper_32_bits(queue->fw_ctx_gpu_addr);
> +
> + /* Shadow and GDS objects come directly from userspace */
> + mqd->shadow_base_lo = lower_32_bits(mqd_user->shadow_va);
> + mqd->shadow_base_hi = upper_32_bits(mqd_user->shadow_va);
> +
> + mqd->gds_bkup_base_lo = lower_32_bits(mqd_user->gds_va);
> + mqd->gds_bkup_base_hi = upper_32_bits(mqd_user->gds_va);
> +
> + return 0;
> +}
> +
> static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
> struct drm_amdgpu_userq_in *args_in,
> struct amdgpu_usermode_queue *queue)
> @@ -6540,6 +6594,13 @@ static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
> goto free_mqd;
> }
>
> + /* Create BO for FW operations */
> + r = gfx_v11_0_userq_create_ctx_space(uq_mgr, queue, &mqd_user);
> + if (r) {
> + DRM_ERROR("Failed to allocate BO for userqueue (%d)", r);
> + goto free_mqd;
> + }
> +
> return 0;
>
> free_mqd:
> @@ -6552,6 +6613,7 @@ gfx_v11_0_userq_mqd_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_userm
> {
> struct amdgpu_userq_obj *mqd = &queue->mqd;
>
> + gfx_v11_0_userq_destroy_ctx_space(uq_mgr, queue);
> amdgpu_bo_free_kernel(&mqd->obj, &mqd->gpu_addr, &mqd->cpu_ptr);
> }
>
> diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
> index 240f92796f00..a5cdb319193d 100644
> --- a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
> +++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
> @@ -40,10 +40,14 @@ struct amdgpu_usermode_queue {
> uint64_t doorbell_handle;
> uint64_t doorbell_index;
> uint64_t flags;
> + uint64_t proc_ctx_gpu_addr;
> + uint64_t gang_ctx_gpu_addr;
> + uint64_t fw_ctx_gpu_addr;
Is there a way we could store these in some gfx11 structure? These
are specific to gfx11 and other IPs may have other metadata buffers
they need to allocate. maybe subclass a gfx11 userq structure or add
a priv ptr off of the the userq structure so IPs can add their
implementation details there.
Alex
Alex
> struct amdgpu_mqd_prop *userq_prop;
> struct amdgpu_userq_mgr *userq_mgr;
> struct amdgpu_vm *vm;
> struct amdgpu_userq_obj mqd;
> + struct amdgpu_userq_obj fw_obj;
> };
>
> struct amdgpu_userq_funcs {
> --
> 2.40.1
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 06/10] drm/amdgpu: map usermode queue into MES
2023-07-06 12:35 ` [PATCH v5 06/10] drm/amdgpu: map usermode queue into MES Shashank Sharma
2023-07-06 14:47 ` Christian König
@ 2023-07-06 16:52 ` Alex Deucher
2023-07-06 17:15 ` Shashank Sharma
1 sibling, 1 reply; 50+ messages in thread
From: Alex Deucher @ 2023-07-06 16:52 UTC (permalink / raw)
To: Shashank Sharma; +Cc: Alex Deucher, arvind.yadav, Christian Koenig, amd-gfx
On Thu, Jul 6, 2023 at 8:36 AM Shashank Sharma <shashank.sharma@amd.com> wrote:
>
> This patch adds new functions to map/unmap a usermode queue into
> the FW, using the MES ring. As soon as this mapping is done, the
> queue would be considered ready to accept the workload.
>
> V1: Addressed review comments from Alex on the RFC patch series
> - Map/Unmap should be IP specific.
> V2:
> Addressed review comments from Christian:
> - Fix the wptr_mc_addr calculation (moved into another patch)
> Addressed review comments from Alex:
> - Do not add fptrs for map/unmap
>
> V3: Integration with doorbell manager
> V4: Rebase
> V5: Use gfx_v11_0 for function names (Alex)
>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Christian Koenig <christian.koenig@amd.com>
> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
> ---
> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 70 ++++++++++++++++++++++++++
> 1 file changed, 70 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> index 7d3b19e08bbb..b4a0f26a0e8c 100644
> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> @@ -6491,6 +6491,65 @@ const struct amdgpu_ip_block_version gfx_v11_0_ip_block =
> .funcs = &gfx_v11_0_ip_funcs,
> };
>
> +static void gfx_v11_0_userq_unmap(struct amdgpu_userq_mgr *uq_mgr,
> + struct amdgpu_usermode_queue *queue)
> +{
> + struct amdgpu_device *adev = uq_mgr->adev;
> + struct mes_remove_queue_input queue_input;
> + int r;
> +
> + memset(&queue_input, 0x0, sizeof(struct mes_remove_queue_input));
> + queue_input.doorbell_offset = queue->doorbell_index;
> + queue_input.gang_context_addr = queue->gang_ctx_gpu_addr;
> +
> + amdgpu_mes_lock(&adev->mes);
> + r = adev->mes.funcs->remove_hw_queue(&adev->mes, &queue_input);
> + amdgpu_mes_unlock(&adev->mes);
> + if (r)
> + DRM_ERROR("Failed to unmap queue in HW, err (%d)\n", r);
> +}
> +
> +static int gfx_v11_0_userq_map(struct amdgpu_userq_mgr *uq_mgr,
> + struct amdgpu_usermode_queue *queue,
> + struct amdgpu_mqd_prop *userq_props)
> +{
> + struct amdgpu_device *adev = uq_mgr->adev;
> + struct mes_add_queue_input queue_input;
> + int r;
> +
> + memset(&queue_input, 0x0, sizeof(struct mes_add_queue_input));
> +
> + queue_input.process_va_start = 0;
> + queue_input.process_va_end = (adev->vm_manager.max_pfn - 1) << AMDGPU_GPU_PAGE_SHIFT;
> + queue_input.process_quantum = 100000; /* 10ms */
> + queue_input.gang_quantum = 10000; /* 1ms */
> + queue_input.paging = false;
> +
> + queue_input.gang_context_addr = queue->gang_ctx_gpu_addr;
> + queue_input.process_context_addr = queue->proc_ctx_gpu_addr;
> + queue_input.inprocess_gang_priority = AMDGPU_MES_PRIORITY_LEVEL_NORMAL;
> + queue_input.gang_global_priority_level = AMDGPU_MES_PRIORITY_LEVEL_NORMAL;
Was there an option in the MQD to specify a priority? What about
secure settings? If not, we should validate those flags properly and
return an error if they are not currently supported.
> +
> + queue_input.process_id = queue->vm->pasid;
> + queue_input.queue_type = queue->queue_type;
> + queue_input.mqd_addr = queue->mqd.gpu_addr;
> + queue_input.wptr_addr = userq_props->wptr_gpu_addr;
> + queue_input.queue_size = userq_props->queue_size >> 2;
Do we validate the size anywhere?
> + queue_input.doorbell_offset = userq_props->doorbell_index;
> + queue_input.page_table_base_addr = amdgpu_gmc_pd_addr(queue->vm->root.bo);
> +
> + amdgpu_mes_lock(&adev->mes);
> + r = adev->mes.funcs->add_hw_queue(&adev->mes, &queue_input);
> + amdgpu_mes_unlock(&adev->mes);
> + if (r) {
> + DRM_ERROR("Failed to map queue in HW, err (%d)\n", r);
> + return r;
> + }
> +
> + DRM_DEBUG_DRIVER("Queue (doorbell:%d) mapped successfully\n", userq_props->doorbell_index);
> + return 0;
> +}
> +
> static void gfx_v11_0_userq_destroy_ctx_space(struct amdgpu_userq_mgr *uq_mgr,
> struct amdgpu_usermode_queue *queue)
> {
> @@ -6601,8 +6660,18 @@ static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
> goto free_mqd;
> }
>
> + /* Map userqueue into FW using MES */
> + r = gfx_v11_0_userq_map(uq_mgr, queue, &userq_props);
> + if (r) {
> + DRM_ERROR("Failed to init MQD\n");
> + goto free_ctx;
> + }
> +
> return 0;
>
> +free_ctx:
> + gfx_v11_0_userq_destroy_ctx_space(uq_mgr, queue);
> +
> free_mqd:
> amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr, &queue->mqd.cpu_ptr);
> return r;
> @@ -6613,6 +6682,7 @@ gfx_v11_0_userq_mqd_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_userm
> {
> struct amdgpu_userq_obj *mqd = &queue->mqd;
>
> + gfx_v11_0_userq_unmap(uq_mgr, queue);
> gfx_v11_0_userq_destroy_ctx_space(uq_mgr, queue);
> amdgpu_bo_free_kernel(&mqd->obj, &mqd->gpu_addr, &mqd->cpu_ptr);
> }
> --
> 2.40.1
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 02/10] drm/amdgpu: add usermode queue base code
2023-07-06 16:36 ` Alex Deucher
@ 2023-07-06 16:52 ` Shashank Sharma
2023-07-06 17:34 ` Alex Deucher
0 siblings, 1 reply; 50+ messages in thread
From: Shashank Sharma @ 2023-07-06 16:52 UTC (permalink / raw)
To: Alex Deucher; +Cc: Alex Deucher, arvind.yadav, Christian Koenig, amd-gfx
On 06/07/2023 18:36, Alex Deucher wrote:
> On Thu, Jul 6, 2023 at 8:36 AM Shashank Sharma <shashank.sharma@amd.com> wrote:
>> This patch adds skeleton code for amdgpu usermode queue.
>> It contains:
>> - A new files with init functions of usermode queues.
>> - A queue context manager in driver private data.
>>
>> V1: Worked on design review comments from RFC patch series:
>> (https://patchwork.freedesktop.org/series/112214/)
>> - Alex: Keep a list of queues, instead of single queue per process.
>> - Christian: Use the queue manager instead of global ptrs,
>> Don't keep the queue structure in amdgpu_ctx
>>
>> V2:
>> - Reformatted code, split the big patch into two
>>
>> V3:
>> - Integration with doorbell manager
>>
>> V4:
>> - Align the structure member names to the largest member's column
>> (Luben)
>> - Added SPDX license (Luben)
>>
>> V5:
>> - Do not add amdgpu.h in amdgpu_userqueue.h (Christian).
>> - Move struct amdgpu_userq_mgr into amdgpu_userqueue.h (Christian).
>>
>> Cc: Alex Deucher <alexander.deucher@amd.com>
>> Cc: Christian Koenig <christian.koenig@amd.com>
>> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
>> ---
>> drivers/gpu/drm/amd/amdgpu/Makefile | 2 +
>> drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 +
>> drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 1 +
>> drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 6 ++
>> drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 40 ++++++++++++
>> .../gpu/drm/amd/include/amdgpu_userqueue.h | 62 +++++++++++++++++++
>> 6 files changed, 113 insertions(+)
>> create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>> create mode 100644 drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>
>> diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
>> index 415a7fa395c4..4b9bae995094 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/Makefile
>> +++ b/drivers/gpu/drm/amd/amdgpu/Makefile
>> @@ -216,6 +216,8 @@ amdgpu-y += \
>> # add amdkfd interfaces
>> amdgpu-y += amdgpu_amdkfd.o
>>
>> +# add usermode queue
>> +amdgpu-y += amdgpu_userqueue.o
>>
>> ifneq ($(CONFIG_HSA_AMD),)
>> AMDKFD_PATH := ../amdkfd
>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
>> index 02b827785e39..fab842138cd5 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
>> @@ -107,6 +107,7 @@
>> #include "amdgpu_fdinfo.h"
>> #include "amdgpu_mca.h"
>> #include "amdgpu_ras.h"
>> +#include "amdgpu_userqueue.h"
>>
>> #define MAX_GPU_INSTANCE 16
>>
>> @@ -463,6 +464,7 @@ struct amdgpu_fpriv {
>> struct mutex bo_list_lock;
>> struct idr bo_list_handles;
>> struct amdgpu_ctx_mgr ctx_mgr;
>> + struct amdgpu_userq_mgr userq_mgr;
>> };
>>
>> int amdgpu_file_to_fpriv(struct file *filp, struct amdgpu_fpriv **fpriv);
>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
>> index b1ca1ab6d6ad..4c5e44d41652 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
>> @@ -50,6 +50,7 @@
>> #include "amdgpu_ras.h"
>> #include "amdgpu_xgmi.h"
>> #include "amdgpu_reset.h"
>> +#include "amdgpu_userqueue.h"
>>
>> /*
>> * KMS wrapper.
>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
>> index 0efb38539d70..68e5375b648b 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
>> @@ -44,6 +44,7 @@
>> #include "amdgpu_display.h"
>> #include "amdgpu_ras.h"
>> #include "amd_pcie.h"
>> +#include "amdgpu_userqueue.h"
>>
>> void amdgpu_unregister_gpu_instance(struct amdgpu_device *adev)
>> {
>> @@ -1234,6 +1235,10 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
>>
>> amdgpu_ctx_mgr_init(&fpriv->ctx_mgr, adev);
>>
>> + r = amdgpu_userq_mgr_init(&fpriv->userq_mgr, adev);
>> + if (r)
>> + DRM_WARN("Can't setup usermode queues, use legacy workload submission only\n");
>> +
>> file_priv->driver_priv = fpriv;
>> goto out_suspend;
>>
>> @@ -1301,6 +1306,7 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,
>>
>> amdgpu_ctx_mgr_fini(&fpriv->ctx_mgr);
>> amdgpu_vm_fini(adev, &fpriv->vm);
>> + amdgpu_userq_mgr_fini(&fpriv->userq_mgr);
>>
>> if (pasid)
>> amdgpu_pasid_free_delayed(pd->tbo.base.resv, pasid);
>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>> new file mode 100644
>> index 000000000000..effc0c7c02cf
>> --- /dev/null
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>> @@ -0,0 +1,40 @@
>> +// SPDX-License-Identifier: MIT
>> +/*
>> + * Copyright 2023 Advanced Micro Devices, Inc.
>> + *
>> + * Permission is hereby granted, free of charge, to any person obtaining a
>> + * copy of this software and associated documentation files (the "Software"),
>> + * to deal in the Software without restriction, including without limitation
>> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
>> + * and/or sell copies of the Software, and to permit persons to whom the
>> + * Software is furnished to do so, subject to the following conditions:
>> + *
>> + * The above copyright notice and this permission notice shall be included in
>> + * all copies or substantial portions of the Software.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
>> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
>> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
>> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>> + * OTHER DEALINGS IN THE SOFTWARE.
>> + *
>> + */
>> +
>> +#include "amdgpu.h"
>> +
>> +int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct amdgpu_device *adev)
>> +{
>> + mutex_init(&userq_mgr->userq_mutex);
>> + idr_init_base(&userq_mgr->userq_idr, 1);
>> + userq_mgr->adev = adev;
>> +
>> + return 0;
>> +}
>> +
>> +void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr)
>> +{
>> + idr_destroy(&userq_mgr->userq_idr);
>> + mutex_destroy(&userq_mgr->userq_mutex);
>> +}
>> diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>> new file mode 100644
>> index 000000000000..79ffa131a514
>> --- /dev/null
>> +++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>> @@ -0,0 +1,62 @@
>> +/* SPDX-License-Identifier: MIT */
>> +/*
>> + * Copyright 2023 Advanced Micro Devices, Inc.
>> + *
>> + * Permission is hereby granted, free of charge, to any person obtaining a
>> + * copy of this software and associated documentation files (the "Software"),
>> + * to deal in the Software without restriction, including without limitation
>> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
>> + * and/or sell copies of the Software, and to permit persons to whom the
>> + * Software is furnished to do so, subject to the following conditions:
>> + *
>> + * The above copyright notice and this permission notice shall be included in
>> + * all copies or substantial portions of the Software.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
>> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
>> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
>> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>> + * OTHER DEALINGS IN THE SOFTWARE.
>> + *
>> + */
>> +
>> +#ifndef AMDGPU_USERQUEUE_H_
>> +#define AMDGPU_USERQUEUE_H_
>> +
>> +#define AMDGPU_MAX_USERQ_COUNT 512
>> +
>> +struct amdgpu_mqd_prop;
>> +
>> +struct amdgpu_usermode_queue {
>> + int queue_type;
>> + uint64_t doorbell_handle;
>> + uint64_t doorbell_index;
>> + uint64_t flags;
>> + struct amdgpu_mqd_prop *userq_prop;
>> + struct amdgpu_userq_mgr *userq_mgr;
>> + struct amdgpu_vm *vm;
>> +};
>> +
>> +struct amdgpu_userq_funcs {
>> + int (*mqd_create)(struct amdgpu_userq_mgr *uq_mgr,
>> + struct drm_amdgpu_userq_in *args,
>> + struct amdgpu_usermode_queue *queue);
>> + void (*mqd_destroy)(struct amdgpu_userq_mgr *uq_mgr,
>> + struct amdgpu_usermode_queue *uq);
>> +};
>> +
>> +/* Usermode queues for gfx */
>> +struct amdgpu_userq_mgr {
>> + struct idr userq_idr;
>> + struct mutex userq_mutex;
>> + struct amdgpu_device *adev;
>> + const struct amdgpu_userq_funcs *userq_funcs[AMDGPU_HW_IP_NUM];
> Why did we decide to put these in the userq_mgr rather than having
> them in adev? I tried to find the original v1 thread. It just seems
> like extra work to assign a bunch of pointers every time we create a
> userq_mgr. I don't see a case where we would ever want them to be
> different per userq_mgr instance. It also keeps all of the IP
> specific knowledge in the IP specific code. E.g., if some IP only
> supports this for specific versions, we could assign the pointers to
> adev in that IP's code rather than adding a bunch of logic to the
> generic userq code to know which IP versions may or may not support
> this.
So far we have been discussing on why not to keep this whole structure
in adev, which was as discussed due to a previous review comment (want
to make this data specific to a session between open() and close(), and
also not to overpopulate adev), but we do not have a specific reason to
keep these function ptrs in uq_mgr. I can move just these function
pointers in adev and we can initialize this once during the IP init, the
small cost to pay would be right now all the things related to usermode
queue is at this one place, in the other case it would be scattered
across two (Which can be ignored, if we prefer :))
- Shashank
> Alex
>
>
>> +};
>> +
>> +int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct amdgpu_device *adev);
>> +
>> +void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr);
>> +
>> +#endif
>> --
>> 2.40.1
>>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 06/10] drm/amdgpu: map usermode queue into MES
2023-07-06 16:52 ` Alex Deucher
@ 2023-07-06 17:15 ` Shashank Sharma
2023-07-06 17:26 ` Alex Deucher
0 siblings, 1 reply; 50+ messages in thread
From: Shashank Sharma @ 2023-07-06 17:15 UTC (permalink / raw)
To: Alex Deucher; +Cc: Alex Deucher, arvind.yadav, Christian Koenig, amd-gfx
On 06/07/2023 18:52, Alex Deucher wrote:
> On Thu, Jul 6, 2023 at 8:36 AM Shashank Sharma <shashank.sharma@amd.com> wrote:
>> This patch adds new functions to map/unmap a usermode queue into
>> the FW, using the MES ring. As soon as this mapping is done, the
>> queue would be considered ready to accept the workload.
>>
>> V1: Addressed review comments from Alex on the RFC patch series
>> - Map/Unmap should be IP specific.
>> V2:
>> Addressed review comments from Christian:
>> - Fix the wptr_mc_addr calculation (moved into another patch)
>> Addressed review comments from Alex:
>> - Do not add fptrs for map/unmap
>>
>> V3: Integration with doorbell manager
>> V4: Rebase
>> V5: Use gfx_v11_0 for function names (Alex)
>>
>> Cc: Alex Deucher <alexander.deucher@amd.com>
>> Cc: Christian Koenig <christian.koenig@amd.com>
>> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
>> ---
>> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 70 ++++++++++++++++++++++++++
>> 1 file changed, 70 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>> index 7d3b19e08bbb..b4a0f26a0e8c 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>> @@ -6491,6 +6491,65 @@ const struct amdgpu_ip_block_version gfx_v11_0_ip_block =
>> .funcs = &gfx_v11_0_ip_funcs,
>> };
>>
>> +static void gfx_v11_0_userq_unmap(struct amdgpu_userq_mgr *uq_mgr,
>> + struct amdgpu_usermode_queue *queue)
>> +{
>> + struct amdgpu_device *adev = uq_mgr->adev;
>> + struct mes_remove_queue_input queue_input;
>> + int r;
>> +
>> + memset(&queue_input, 0x0, sizeof(struct mes_remove_queue_input));
>> + queue_input.doorbell_offset = queue->doorbell_index;
>> + queue_input.gang_context_addr = queue->gang_ctx_gpu_addr;
>> +
>> + amdgpu_mes_lock(&adev->mes);
>> + r = adev->mes.funcs->remove_hw_queue(&adev->mes, &queue_input);
>> + amdgpu_mes_unlock(&adev->mes);
>> + if (r)
>> + DRM_ERROR("Failed to unmap queue in HW, err (%d)\n", r);
>> +}
>> +
>> +static int gfx_v11_0_userq_map(struct amdgpu_userq_mgr *uq_mgr,
>> + struct amdgpu_usermode_queue *queue,
>> + struct amdgpu_mqd_prop *userq_props)
>> +{
>> + struct amdgpu_device *adev = uq_mgr->adev;
>> + struct mes_add_queue_input queue_input;
>> + int r;
>> +
>> + memset(&queue_input, 0x0, sizeof(struct mes_add_queue_input));
>> +
>> + queue_input.process_va_start = 0;
>> + queue_input.process_va_end = (adev->vm_manager.max_pfn - 1) << AMDGPU_GPU_PAGE_SHIFT;
>> + queue_input.process_quantum = 100000; /* 10ms */
>> + queue_input.gang_quantum = 10000; /* 1ms */
>> + queue_input.paging = false;
>> +
>> + queue_input.gang_context_addr = queue->gang_ctx_gpu_addr;
>> + queue_input.process_context_addr = queue->proc_ctx_gpu_addr;
>> + queue_input.inprocess_gang_priority = AMDGPU_MES_PRIORITY_LEVEL_NORMAL;
>> + queue_input.gang_global_priority_level = AMDGPU_MES_PRIORITY_LEVEL_NORMAL;
> Was there an option in the MQD to specify a priority?
I checked the gfx_v11_MQD structure and this MQD does have an option to
specify the priority of a queue (offset 134), but as we are re-using the
mqd_init function from gfx_v11_ip_funcs which sets this offset to 0 by
default, its not being used.
We can add a parameter for queue priority and overwrite the init values.
The priority which we are setting here in this function, is for queue
mapping using MES, and its the gang priority.
> What about
> secure settings? If not, we should validate those flags properly and
> return an error if they are not currently supported.
>> +
>> + queue_input.process_id = queue->vm->pasid;
>> + queue_input.queue_type = queue->queue_type;
>> + queue_input.mqd_addr = queue->mqd.gpu_addr;
>> + queue_input.wptr_addr = userq_props->wptr_gpu_addr;
>> + queue_input.queue_size = userq_props->queue_size >> 2;
> Do we validate the size anywhere?
We are validating the whole structure/user_MQD size, but not
specifically queue size. But based on your suggestion on libDRM UAPI, we
are planing to add an USERQ_INFO_IOCTL in a separate patch series, which
will then introduce the IP based dynamic size checking, and also the
checks related to alignment and queue size.
- Shashank
>
>> + queue_input.doorbell_offset = userq_props->doorbell_index;
>> + queue_input.page_table_base_addr = amdgpu_gmc_pd_addr(queue->vm->root.bo);
>> +
>> + amdgpu_mes_lock(&adev->mes);
>> + r = adev->mes.funcs->add_hw_queue(&adev->mes, &queue_input);
>> + amdgpu_mes_unlock(&adev->mes);
>> + if (r) {
>> + DRM_ERROR("Failed to map queue in HW, err (%d)\n", r);
>> + return r;
>> + }
>> +
>> + DRM_DEBUG_DRIVER("Queue (doorbell:%d) mapped successfully\n", userq_props->doorbell_index);
>> + return 0;
>> +}
>> +
>> static void gfx_v11_0_userq_destroy_ctx_space(struct amdgpu_userq_mgr *uq_mgr,
>> struct amdgpu_usermode_queue *queue)
>> {
>> @@ -6601,8 +6660,18 @@ static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
>> goto free_mqd;
>> }
>>
>> + /* Map userqueue into FW using MES */
>> + r = gfx_v11_0_userq_map(uq_mgr, queue, &userq_props);
>> + if (r) {
>> + DRM_ERROR("Failed to init MQD\n");
>> + goto free_ctx;
>> + }
>> +
>> return 0;
>>
>> +free_ctx:
>> + gfx_v11_0_userq_destroy_ctx_space(uq_mgr, queue);
>> +
>> free_mqd:
>> amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr, &queue->mqd.cpu_ptr);
>> return r;
>> @@ -6613,6 +6682,7 @@ gfx_v11_0_userq_mqd_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_userm
>> {
>> struct amdgpu_userq_obj *mqd = &queue->mqd;
>>
>> + gfx_v11_0_userq_unmap(uq_mgr, queue);
>> gfx_v11_0_userq_destroy_ctx_space(uq_mgr, queue);
>> amdgpu_bo_free_kernel(&mqd->obj, &mqd->gpu_addr, &mqd->cpu_ptr);
>> }
>> --
>> 2.40.1
>>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 06/10] drm/amdgpu: map usermode queue into MES
2023-07-06 17:15 ` Shashank Sharma
@ 2023-07-06 17:26 ` Alex Deucher
2023-07-06 17:32 ` Shashank Sharma
0 siblings, 1 reply; 50+ messages in thread
From: Alex Deucher @ 2023-07-06 17:26 UTC (permalink / raw)
To: Shashank Sharma; +Cc: Alex Deucher, arvind.yadav, Christian Koenig, amd-gfx
On Thu, Jul 6, 2023 at 1:15 PM Shashank Sharma <shashank.sharma@amd.com> wrote:
>
>
> On 06/07/2023 18:52, Alex Deucher wrote:
> > On Thu, Jul 6, 2023 at 8:36 AM Shashank Sharma <shashank.sharma@amd.com> wrote:
> >> This patch adds new functions to map/unmap a usermode queue into
> >> the FW, using the MES ring. As soon as this mapping is done, the
> >> queue would be considered ready to accept the workload.
> >>
> >> V1: Addressed review comments from Alex on the RFC patch series
> >> - Map/Unmap should be IP specific.
> >> V2:
> >> Addressed review comments from Christian:
> >> - Fix the wptr_mc_addr calculation (moved into another patch)
> >> Addressed review comments from Alex:
> >> - Do not add fptrs for map/unmap
> >>
> >> V3: Integration with doorbell manager
> >> V4: Rebase
> >> V5: Use gfx_v11_0 for function names (Alex)
> >>
> >> Cc: Alex Deucher <alexander.deucher@amd.com>
> >> Cc: Christian Koenig <christian.koenig@amd.com>
> >> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
> >> ---
> >> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 70 ++++++++++++++++++++++++++
> >> 1 file changed, 70 insertions(+)
> >>
> >> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> >> index 7d3b19e08bbb..b4a0f26a0e8c 100644
> >> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> >> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> >> @@ -6491,6 +6491,65 @@ const struct amdgpu_ip_block_version gfx_v11_0_ip_block =
> >> .funcs = &gfx_v11_0_ip_funcs,
> >> };
> >>
> >> +static void gfx_v11_0_userq_unmap(struct amdgpu_userq_mgr *uq_mgr,
> >> + struct amdgpu_usermode_queue *queue)
> >> +{
> >> + struct amdgpu_device *adev = uq_mgr->adev;
> >> + struct mes_remove_queue_input queue_input;
> >> + int r;
> >> +
> >> + memset(&queue_input, 0x0, sizeof(struct mes_remove_queue_input));
> >> + queue_input.doorbell_offset = queue->doorbell_index;
> >> + queue_input.gang_context_addr = queue->gang_ctx_gpu_addr;
> >> +
> >> + amdgpu_mes_lock(&adev->mes);
> >> + r = adev->mes.funcs->remove_hw_queue(&adev->mes, &queue_input);
> >> + amdgpu_mes_unlock(&adev->mes);
> >> + if (r)
> >> + DRM_ERROR("Failed to unmap queue in HW, err (%d)\n", r);
> >> +}
> >> +
> >> +static int gfx_v11_0_userq_map(struct amdgpu_userq_mgr *uq_mgr,
> >> + struct amdgpu_usermode_queue *queue,
> >> + struct amdgpu_mqd_prop *userq_props)
> >> +{
> >> + struct amdgpu_device *adev = uq_mgr->adev;
> >> + struct mes_add_queue_input queue_input;
> >> + int r;
> >> +
> >> + memset(&queue_input, 0x0, sizeof(struct mes_add_queue_input));
> >> +
> >> + queue_input.process_va_start = 0;
> >> + queue_input.process_va_end = (adev->vm_manager.max_pfn - 1) << AMDGPU_GPU_PAGE_SHIFT;
> >> + queue_input.process_quantum = 100000; /* 10ms */
> >> + queue_input.gang_quantum = 10000; /* 1ms */
> >> + queue_input.paging = false;
> >> +
> >> + queue_input.gang_context_addr = queue->gang_ctx_gpu_addr;
> >> + queue_input.process_context_addr = queue->proc_ctx_gpu_addr;
> >> + queue_input.inprocess_gang_priority = AMDGPU_MES_PRIORITY_LEVEL_NORMAL;
> >> + queue_input.gang_global_priority_level = AMDGPU_MES_PRIORITY_LEVEL_NORMAL;
> > Was there an option in the MQD to specify a priority?
>
> I checked the gfx_v11_MQD structure and this MQD does have an option to
> specify the priority of a queue (offset 134), but as we are re-using the
> mqd_init function from gfx_v11_ip_funcs which sets this offset to 0 by
> default, its not being used.
>
> We can add a parameter for queue priority and overwrite the init values.
>
> The priority which we are setting here in this function, is for queue
> mapping using MES, and its the gang priority.
Thinking about this more, the priority would come from the context.
E.g., ctx->init_priority and ctx->override_priority (see
amdgpu_ctx_init()). We should take that into account when creating
the queue.
>
> > What about
> > secure settings? If not, we should validate those flags properly and
> > return an error if they are not currently supported.
> >> +
> >> + queue_input.process_id = queue->vm->pasid;
> >> + queue_input.queue_type = queue->queue_type;
> >> + queue_input.mqd_addr = queue->mqd.gpu_addr;
> >> + queue_input.wptr_addr = userq_props->wptr_gpu_addr;
> >> + queue_input.queue_size = userq_props->queue_size >> 2;
> > Do we validate the size anywhere?
>
> We are validating the whole structure/user_MQD size, but not
> specifically queue size. But based on your suggestion on libDRM UAPI, we
> are planing to add an USERQ_INFO_IOCTL in a separate patch series, which
> will then introduce the IP based dynamic size checking, and also the
> checks related to alignment and queue size.
We just want to protect from userspace doing something crazy like
making a 10M queue or something like that. We should add an interface
to query the sizes per IP, but we need to validate the inputs as well.
Alex
>
> - Shashank
>
> >
> >> + queue_input.doorbell_offset = userq_props->doorbell_index;
> >> + queue_input.page_table_base_addr = amdgpu_gmc_pd_addr(queue->vm->root.bo);
> >> +
> >> + amdgpu_mes_lock(&adev->mes);
> >> + r = adev->mes.funcs->add_hw_queue(&adev->mes, &queue_input);
> >> + amdgpu_mes_unlock(&adev->mes);
> >> + if (r) {
> >> + DRM_ERROR("Failed to map queue in HW, err (%d)\n", r);
> >> + return r;
> >> + }
> >> +
> >> + DRM_DEBUG_DRIVER("Queue (doorbell:%d) mapped successfully\n", userq_props->doorbell_index);
> >> + return 0;
> >> +}
> >> +
> >> static void gfx_v11_0_userq_destroy_ctx_space(struct amdgpu_userq_mgr *uq_mgr,
> >> struct amdgpu_usermode_queue *queue)
> >> {
> >> @@ -6601,8 +6660,18 @@ static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
> >> goto free_mqd;
> >> }
> >>
> >> + /* Map userqueue into FW using MES */
> >> + r = gfx_v11_0_userq_map(uq_mgr, queue, &userq_props);
> >> + if (r) {
> >> + DRM_ERROR("Failed to init MQD\n");
> >> + goto free_ctx;
> >> + }
> >> +
> >> return 0;
> >>
> >> +free_ctx:
> >> + gfx_v11_0_userq_destroy_ctx_space(uq_mgr, queue);
> >> +
> >> free_mqd:
> >> amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr, &queue->mqd.cpu_ptr);
> >> return r;
> >> @@ -6613,6 +6682,7 @@ gfx_v11_0_userq_mqd_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_userm
> >> {
> >> struct amdgpu_userq_obj *mqd = &queue->mqd;
> >>
> >> + gfx_v11_0_userq_unmap(uq_mgr, queue);
> >> gfx_v11_0_userq_destroy_ctx_space(uq_mgr, queue);
> >> amdgpu_bo_free_kernel(&mqd->obj, &mqd->gpu_addr, &mqd->cpu_ptr);
> >> }
> >> --
> >> 2.40.1
> >>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 06/10] drm/amdgpu: map usermode queue into MES
2023-07-06 17:26 ` Alex Deucher
@ 2023-07-06 17:32 ` Shashank Sharma
2023-07-06 17:36 ` Alex Deucher
0 siblings, 1 reply; 50+ messages in thread
From: Shashank Sharma @ 2023-07-06 17:32 UTC (permalink / raw)
To: Alex Deucher; +Cc: Alex Deucher, arvind.yadav, Christian Koenig, amd-gfx
On 06/07/2023 19:26, Alex Deucher wrote:
> On Thu, Jul 6, 2023 at 1:15 PM Shashank Sharma <shashank.sharma@amd.com> wrote:
>>
>> On 06/07/2023 18:52, Alex Deucher wrote:
>>> On Thu, Jul 6, 2023 at 8:36 AM Shashank Sharma <shashank.sharma@amd.com> wrote:
>>>> This patch adds new functions to map/unmap a usermode queue into
>>>> the FW, using the MES ring. As soon as this mapping is done, the
>>>> queue would be considered ready to accept the workload.
>>>>
>>>> V1: Addressed review comments from Alex on the RFC patch series
>>>> - Map/Unmap should be IP specific.
>>>> V2:
>>>> Addressed review comments from Christian:
>>>> - Fix the wptr_mc_addr calculation (moved into another patch)
>>>> Addressed review comments from Alex:
>>>> - Do not add fptrs for map/unmap
>>>>
>>>> V3: Integration with doorbell manager
>>>> V4: Rebase
>>>> V5: Use gfx_v11_0 for function names (Alex)
>>>>
>>>> Cc: Alex Deucher <alexander.deucher@amd.com>
>>>> Cc: Christian Koenig <christian.koenig@amd.com>
>>>> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
>>>> ---
>>>> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 70 ++++++++++++++++++++++++++
>>>> 1 file changed, 70 insertions(+)
>>>>
>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>> index 7d3b19e08bbb..b4a0f26a0e8c 100644
>>>> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>> @@ -6491,6 +6491,65 @@ const struct amdgpu_ip_block_version gfx_v11_0_ip_block =
>>>> .funcs = &gfx_v11_0_ip_funcs,
>>>> };
>>>>
>>>> +static void gfx_v11_0_userq_unmap(struct amdgpu_userq_mgr *uq_mgr,
>>>> + struct amdgpu_usermode_queue *queue)
>>>> +{
>>>> + struct amdgpu_device *adev = uq_mgr->adev;
>>>> + struct mes_remove_queue_input queue_input;
>>>> + int r;
>>>> +
>>>> + memset(&queue_input, 0x0, sizeof(struct mes_remove_queue_input));
>>>> + queue_input.doorbell_offset = queue->doorbell_index;
>>>> + queue_input.gang_context_addr = queue->gang_ctx_gpu_addr;
>>>> +
>>>> + amdgpu_mes_lock(&adev->mes);
>>>> + r = adev->mes.funcs->remove_hw_queue(&adev->mes, &queue_input);
>>>> + amdgpu_mes_unlock(&adev->mes);
>>>> + if (r)
>>>> + DRM_ERROR("Failed to unmap queue in HW, err (%d)\n", r);
>>>> +}
>>>> +
>>>> +static int gfx_v11_0_userq_map(struct amdgpu_userq_mgr *uq_mgr,
>>>> + struct amdgpu_usermode_queue *queue,
>>>> + struct amdgpu_mqd_prop *userq_props)
>>>> +{
>>>> + struct amdgpu_device *adev = uq_mgr->adev;
>>>> + struct mes_add_queue_input queue_input;
>>>> + int r;
>>>> +
>>>> + memset(&queue_input, 0x0, sizeof(struct mes_add_queue_input));
>>>> +
>>>> + queue_input.process_va_start = 0;
>>>> + queue_input.process_va_end = (adev->vm_manager.max_pfn - 1) << AMDGPU_GPU_PAGE_SHIFT;
>>>> + queue_input.process_quantum = 100000; /* 10ms */
>>>> + queue_input.gang_quantum = 10000; /* 1ms */
>>>> + queue_input.paging = false;
>>>> +
>>>> + queue_input.gang_context_addr = queue->gang_ctx_gpu_addr;
>>>> + queue_input.process_context_addr = queue->proc_ctx_gpu_addr;
>>>> + queue_input.inprocess_gang_priority = AMDGPU_MES_PRIORITY_LEVEL_NORMAL;
>>>> + queue_input.gang_global_priority_level = AMDGPU_MES_PRIORITY_LEVEL_NORMAL;
>>> Was there an option in the MQD to specify a priority?
>> I checked the gfx_v11_MQD structure and this MQD does have an option to
>> specify the priority of a queue (offset 134), but as we are re-using the
>> mqd_init function from gfx_v11_ip_funcs which sets this offset to 0 by
>> default, its not being used.
>>
>> We can add a parameter for queue priority and overwrite the init values.
>>
>> The priority which we are setting here in this function, is for queue
>> mapping using MES, and its the gang priority.
> Thinking about this more, the priority would come from the context.
> E.g., ctx->init_priority and ctx->override_priority (see
> amdgpu_ctx_init()). We should take that into account when creating
> the queue.
In the current design, the userqueue is completely independent of the
GFX ctx (we discussed this in V2 I think, and that's when we introduced
the user_mgr). I agree that we should consider the queue priority, but
we might have to get this parameter specifically from the mqd_user_in.
>
>>> What about
>>> secure settings? If not, we should validate those flags properly and
>>> return an error if they are not currently supported.
>>>> +
>>>> + queue_input.process_id = queue->vm->pasid;
>>>> + queue_input.queue_type = queue->queue_type;
>>>> + queue_input.mqd_addr = queue->mqd.gpu_addr;
>>>> + queue_input.wptr_addr = userq_props->wptr_gpu_addr;
>>>> + queue_input.queue_size = userq_props->queue_size >> 2;
>>> Do we validate the size anywhere?
>> We are validating the whole structure/user_MQD size, but not
>> specifically queue size. But based on your suggestion on libDRM UAPI, we
>> are planing to add an USERQ_INFO_IOCTL in a separate patch series, which
>> will then introduce the IP based dynamic size checking, and also the
>> checks related to alignment and queue size.
> We just want to protect from userspace doing something crazy like
> making a 10M queue or something like that. We should add an interface
> to query the sizes per IP, but we need to validate the inputs as well.
Agree, I will add this queue size validation check in this series
itself, will cross check some other inputs as well.
- Shashank
>
> Alex
>
>> - Shashank
>>
>>>> + queue_input.doorbell_offset = userq_props->doorbell_index;
>>>> + queue_input.page_table_base_addr = amdgpu_gmc_pd_addr(queue->vm->root.bo);
>>>> +
>>>> + amdgpu_mes_lock(&adev->mes);
>>>> + r = adev->mes.funcs->add_hw_queue(&adev->mes, &queue_input);
>>>> + amdgpu_mes_unlock(&adev->mes);
>>>> + if (r) {
>>>> + DRM_ERROR("Failed to map queue in HW, err (%d)\n", r);
>>>> + return r;
>>>> + }
>>>> +
>>>> + DRM_DEBUG_DRIVER("Queue (doorbell:%d) mapped successfully\n", userq_props->doorbell_index);
>>>> + return 0;
>>>> +}
>>>> +
>>>> static void gfx_v11_0_userq_destroy_ctx_space(struct amdgpu_userq_mgr *uq_mgr,
>>>> struct amdgpu_usermode_queue *queue)
>>>> {
>>>> @@ -6601,8 +6660,18 @@ static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
>>>> goto free_mqd;
>>>> }
>>>>
>>>> + /* Map userqueue into FW using MES */
>>>> + r = gfx_v11_0_userq_map(uq_mgr, queue, &userq_props);
>>>> + if (r) {
>>>> + DRM_ERROR("Failed to init MQD\n");
>>>> + goto free_ctx;
>>>> + }
>>>> +
>>>> return 0;
>>>>
>>>> +free_ctx:
>>>> + gfx_v11_0_userq_destroy_ctx_space(uq_mgr, queue);
>>>> +
>>>> free_mqd:
>>>> amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr, &queue->mqd.cpu_ptr);
>>>> return r;
>>>> @@ -6613,6 +6682,7 @@ gfx_v11_0_userq_mqd_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_userm
>>>> {
>>>> struct amdgpu_userq_obj *mqd = &queue->mqd;
>>>>
>>>> + gfx_v11_0_userq_unmap(uq_mgr, queue);
>>>> gfx_v11_0_userq_destroy_ctx_space(uq_mgr, queue);
>>>> amdgpu_bo_free_kernel(&mqd->obj, &mqd->gpu_addr, &mqd->cpu_ptr);
>>>> }
>>>> --
>>>> 2.40.1
>>>>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 02/10] drm/amdgpu: add usermode queue base code
2023-07-06 16:52 ` Shashank Sharma
@ 2023-07-06 17:34 ` Alex Deucher
0 siblings, 0 replies; 50+ messages in thread
From: Alex Deucher @ 2023-07-06 17:34 UTC (permalink / raw)
To: Shashank Sharma; +Cc: Alex Deucher, arvind.yadav, Christian Koenig, amd-gfx
On Thu, Jul 6, 2023 at 12:53 PM Shashank Sharma <shashank.sharma@amd.com> wrote:
>
>
> On 06/07/2023 18:36, Alex Deucher wrote:
> > On Thu, Jul 6, 2023 at 8:36 AM Shashank Sharma <shashank.sharma@amd.com> wrote:
> >> This patch adds skeleton code for amdgpu usermode queue.
> >> It contains:
> >> - A new files with init functions of usermode queues.
> >> - A queue context manager in driver private data.
> >>
> >> V1: Worked on design review comments from RFC patch series:
> >> (https://patchwork.freedesktop.org/series/112214/)
> >> - Alex: Keep a list of queues, instead of single queue per process.
> >> - Christian: Use the queue manager instead of global ptrs,
> >> Don't keep the queue structure in amdgpu_ctx
> >>
> >> V2:
> >> - Reformatted code, split the big patch into two
> >>
> >> V3:
> >> - Integration with doorbell manager
> >>
> >> V4:
> >> - Align the structure member names to the largest member's column
> >> (Luben)
> >> - Added SPDX license (Luben)
> >>
> >> V5:
> >> - Do not add amdgpu.h in amdgpu_userqueue.h (Christian).
> >> - Move struct amdgpu_userq_mgr into amdgpu_userqueue.h (Christian).
> >>
> >> Cc: Alex Deucher <alexander.deucher@amd.com>
> >> Cc: Christian Koenig <christian.koenig@amd.com>
> >> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
> >> ---
> >> drivers/gpu/drm/amd/amdgpu/Makefile | 2 +
> >> drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 +
> >> drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 1 +
> >> drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 6 ++
> >> drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 40 ++++++++++++
> >> .../gpu/drm/amd/include/amdgpu_userqueue.h | 62 +++++++++++++++++++
> >> 6 files changed, 113 insertions(+)
> >> create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
> >> create mode 100644 drivers/gpu/drm/amd/include/amdgpu_userqueue.h
> >>
> >> diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
> >> index 415a7fa395c4..4b9bae995094 100644
> >> --- a/drivers/gpu/drm/amd/amdgpu/Makefile
> >> +++ b/drivers/gpu/drm/amd/amdgpu/Makefile
> >> @@ -216,6 +216,8 @@ amdgpu-y += \
> >> # add amdkfd interfaces
> >> amdgpu-y += amdgpu_amdkfd.o
> >>
> >> +# add usermode queue
> >> +amdgpu-y += amdgpu_userqueue.o
> >>
> >> ifneq ($(CONFIG_HSA_AMD),)
> >> AMDKFD_PATH := ../amdkfd
> >> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> >> index 02b827785e39..fab842138cd5 100644
> >> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> >> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> >> @@ -107,6 +107,7 @@
> >> #include "amdgpu_fdinfo.h"
> >> #include "amdgpu_mca.h"
> >> #include "amdgpu_ras.h"
> >> +#include "amdgpu_userqueue.h"
> >>
> >> #define MAX_GPU_INSTANCE 16
> >>
> >> @@ -463,6 +464,7 @@ struct amdgpu_fpriv {
> >> struct mutex bo_list_lock;
> >> struct idr bo_list_handles;
> >> struct amdgpu_ctx_mgr ctx_mgr;
> >> + struct amdgpu_userq_mgr userq_mgr;
> >> };
> >>
> >> int amdgpu_file_to_fpriv(struct file *filp, struct amdgpu_fpriv **fpriv);
> >> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> >> index b1ca1ab6d6ad..4c5e44d41652 100644
> >> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> >> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> >> @@ -50,6 +50,7 @@
> >> #include "amdgpu_ras.h"
> >> #include "amdgpu_xgmi.h"
> >> #include "amdgpu_reset.h"
> >> +#include "amdgpu_userqueue.h"
> >>
> >> /*
> >> * KMS wrapper.
> >> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> >> index 0efb38539d70..68e5375b648b 100644
> >> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> >> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> >> @@ -44,6 +44,7 @@
> >> #include "amdgpu_display.h"
> >> #include "amdgpu_ras.h"
> >> #include "amd_pcie.h"
> >> +#include "amdgpu_userqueue.h"
> >>
> >> void amdgpu_unregister_gpu_instance(struct amdgpu_device *adev)
> >> {
> >> @@ -1234,6 +1235,10 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
> >>
> >> amdgpu_ctx_mgr_init(&fpriv->ctx_mgr, adev);
> >>
> >> + r = amdgpu_userq_mgr_init(&fpriv->userq_mgr, adev);
> >> + if (r)
> >> + DRM_WARN("Can't setup usermode queues, use legacy workload submission only\n");
> >> +
> >> file_priv->driver_priv = fpriv;
> >> goto out_suspend;
> >>
> >> @@ -1301,6 +1306,7 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,
> >>
> >> amdgpu_ctx_mgr_fini(&fpriv->ctx_mgr);
> >> amdgpu_vm_fini(adev, &fpriv->vm);
> >> + amdgpu_userq_mgr_fini(&fpriv->userq_mgr);
> >>
> >> if (pasid)
> >> amdgpu_pasid_free_delayed(pd->tbo.base.resv, pasid);
> >> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
> >> new file mode 100644
> >> index 000000000000..effc0c7c02cf
> >> --- /dev/null
> >> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
> >> @@ -0,0 +1,40 @@
> >> +// SPDX-License-Identifier: MIT
> >> +/*
> >> + * Copyright 2023 Advanced Micro Devices, Inc.
> >> + *
> >> + * Permission is hereby granted, free of charge, to any person obtaining a
> >> + * copy of this software and associated documentation files (the "Software"),
> >> + * to deal in the Software without restriction, including without limitation
> >> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> >> + * and/or sell copies of the Software, and to permit persons to whom the
> >> + * Software is furnished to do so, subject to the following conditions:
> >> + *
> >> + * The above copyright notice and this permission notice shall be included in
> >> + * all copies or substantial portions of the Software.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> >> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> >> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> >> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
> >> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> >> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> >> + * OTHER DEALINGS IN THE SOFTWARE.
> >> + *
> >> + */
> >> +
> >> +#include "amdgpu.h"
> >> +
> >> +int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct amdgpu_device *adev)
> >> +{
> >> + mutex_init(&userq_mgr->userq_mutex);
> >> + idr_init_base(&userq_mgr->userq_idr, 1);
> >> + userq_mgr->adev = adev;
> >> +
> >> + return 0;
> >> +}
> >> +
> >> +void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr)
> >> +{
> >> + idr_destroy(&userq_mgr->userq_idr);
> >> + mutex_destroy(&userq_mgr->userq_mutex);
> >> +}
> >> diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
> >> new file mode 100644
> >> index 000000000000..79ffa131a514
> >> --- /dev/null
> >> +++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
> >> @@ -0,0 +1,62 @@
> >> +/* SPDX-License-Identifier: MIT */
> >> +/*
> >> + * Copyright 2023 Advanced Micro Devices, Inc.
> >> + *
> >> + * Permission is hereby granted, free of charge, to any person obtaining a
> >> + * copy of this software and associated documentation files (the "Software"),
> >> + * to deal in the Software without restriction, including without limitation
> >> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> >> + * and/or sell copies of the Software, and to permit persons to whom the
> >> + * Software is furnished to do so, subject to the following conditions:
> >> + *
> >> + * The above copyright notice and this permission notice shall be included in
> >> + * all copies or substantial portions of the Software.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> >> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> >> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> >> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
> >> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> >> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> >> + * OTHER DEALINGS IN THE SOFTWARE.
> >> + *
> >> + */
> >> +
> >> +#ifndef AMDGPU_USERQUEUE_H_
> >> +#define AMDGPU_USERQUEUE_H_
> >> +
> >> +#define AMDGPU_MAX_USERQ_COUNT 512
> >> +
> >> +struct amdgpu_mqd_prop;
> >> +
> >> +struct amdgpu_usermode_queue {
> >> + int queue_type;
> >> + uint64_t doorbell_handle;
> >> + uint64_t doorbell_index;
> >> + uint64_t flags;
> >> + struct amdgpu_mqd_prop *userq_prop;
> >> + struct amdgpu_userq_mgr *userq_mgr;
> >> + struct amdgpu_vm *vm;
> >> +};
> >> +
> >> +struct amdgpu_userq_funcs {
> >> + int (*mqd_create)(struct amdgpu_userq_mgr *uq_mgr,
> >> + struct drm_amdgpu_userq_in *args,
> >> + struct amdgpu_usermode_queue *queue);
> >> + void (*mqd_destroy)(struct amdgpu_userq_mgr *uq_mgr,
> >> + struct amdgpu_usermode_queue *uq);
> >> +};
> >> +
> >> +/* Usermode queues for gfx */
> >> +struct amdgpu_userq_mgr {
> >> + struct idr userq_idr;
> >> + struct mutex userq_mutex;
> >> + struct amdgpu_device *adev;
> >> + const struct amdgpu_userq_funcs *userq_funcs[AMDGPU_HW_IP_NUM];
> > Why did we decide to put these in the userq_mgr rather than having
> > them in adev? I tried to find the original v1 thread. It just seems
> > like extra work to assign a bunch of pointers every time we create a
> > userq_mgr. I don't see a case where we would ever want them to be
> > different per userq_mgr instance. It also keeps all of the IP
> > specific knowledge in the IP specific code. E.g., if some IP only
> > supports this for specific versions, we could assign the pointers to
> > adev in that IP's code rather than adding a bunch of logic to the
> > generic userq code to know which IP versions may or may not support
> > this.
>
> So far we have been discussing on why not to keep this whole structure
> in adev, which was as discussed due to a previous review comment (want
> to make this data specific to a session between open() and close(), and
> also not to overpopulate adev), but we do not have a specific reason to
> keep these function ptrs in uq_mgr. I can move just these function
> pointers in adev and we can initialize this once during the IP init, the
> small cost to pay would be right now all the things related to usermode
> queue is at this one place, in the other case it would be scattered
> across two (Which can be ignored, if we prefer :))
Having a single structure somewhere makes more sense to me. It
wouldn't have to live in adev if there is some other per device
structure that makes more sense as long as the IP specific code is the
one that populates it. That said, if you or Christian feel strongly
about it, I could be persuaded.
Alex
Alex
>
> - Shashank
>
> > Alex
> >
> >
> >> +};
> >> +
> >> +int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct amdgpu_device *adev);
> >> +
> >> +void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr);
> >> +
> >> +#endif
> >> --
> >> 2.40.1
> >>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 06/10] drm/amdgpu: map usermode queue into MES
2023-07-06 17:32 ` Shashank Sharma
@ 2023-07-06 17:36 ` Alex Deucher
0 siblings, 0 replies; 50+ messages in thread
From: Alex Deucher @ 2023-07-06 17:36 UTC (permalink / raw)
To: Shashank Sharma; +Cc: Alex Deucher, arvind.yadav, Christian Koenig, amd-gfx
On Thu, Jul 6, 2023 at 1:32 PM Shashank Sharma <shashank.sharma@amd.com> wrote:
>
>
> On 06/07/2023 19:26, Alex Deucher wrote:
> > On Thu, Jul 6, 2023 at 1:15 PM Shashank Sharma <shashank.sharma@amd.com> wrote:
> >>
> >> On 06/07/2023 18:52, Alex Deucher wrote:
> >>> On Thu, Jul 6, 2023 at 8:36 AM Shashank Sharma <shashank.sharma@amd.com> wrote:
> >>>> This patch adds new functions to map/unmap a usermode queue into
> >>>> the FW, using the MES ring. As soon as this mapping is done, the
> >>>> queue would be considered ready to accept the workload.
> >>>>
> >>>> V1: Addressed review comments from Alex on the RFC patch series
> >>>> - Map/Unmap should be IP specific.
> >>>> V2:
> >>>> Addressed review comments from Christian:
> >>>> - Fix the wptr_mc_addr calculation (moved into another patch)
> >>>> Addressed review comments from Alex:
> >>>> - Do not add fptrs for map/unmap
> >>>>
> >>>> V3: Integration with doorbell manager
> >>>> V4: Rebase
> >>>> V5: Use gfx_v11_0 for function names (Alex)
> >>>>
> >>>> Cc: Alex Deucher <alexander.deucher@amd.com>
> >>>> Cc: Christian Koenig <christian.koenig@amd.com>
> >>>> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
> >>>> ---
> >>>> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 70 ++++++++++++++++++++++++++
> >>>> 1 file changed, 70 insertions(+)
> >>>>
> >>>> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> >>>> index 7d3b19e08bbb..b4a0f26a0e8c 100644
> >>>> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> >>>> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> >>>> @@ -6491,6 +6491,65 @@ const struct amdgpu_ip_block_version gfx_v11_0_ip_block =
> >>>> .funcs = &gfx_v11_0_ip_funcs,
> >>>> };
> >>>>
> >>>> +static void gfx_v11_0_userq_unmap(struct amdgpu_userq_mgr *uq_mgr,
> >>>> + struct amdgpu_usermode_queue *queue)
> >>>> +{
> >>>> + struct amdgpu_device *adev = uq_mgr->adev;
> >>>> + struct mes_remove_queue_input queue_input;
> >>>> + int r;
> >>>> +
> >>>> + memset(&queue_input, 0x0, sizeof(struct mes_remove_queue_input));
> >>>> + queue_input.doorbell_offset = queue->doorbell_index;
> >>>> + queue_input.gang_context_addr = queue->gang_ctx_gpu_addr;
> >>>> +
> >>>> + amdgpu_mes_lock(&adev->mes);
> >>>> + r = adev->mes.funcs->remove_hw_queue(&adev->mes, &queue_input);
> >>>> + amdgpu_mes_unlock(&adev->mes);
> >>>> + if (r)
> >>>> + DRM_ERROR("Failed to unmap queue in HW, err (%d)\n", r);
> >>>> +}
> >>>> +
> >>>> +static int gfx_v11_0_userq_map(struct amdgpu_userq_mgr *uq_mgr,
> >>>> + struct amdgpu_usermode_queue *queue,
> >>>> + struct amdgpu_mqd_prop *userq_props)
> >>>> +{
> >>>> + struct amdgpu_device *adev = uq_mgr->adev;
> >>>> + struct mes_add_queue_input queue_input;
> >>>> + int r;
> >>>> +
> >>>> + memset(&queue_input, 0x0, sizeof(struct mes_add_queue_input));
> >>>> +
> >>>> + queue_input.process_va_start = 0;
> >>>> + queue_input.process_va_end = (adev->vm_manager.max_pfn - 1) << AMDGPU_GPU_PAGE_SHIFT;
> >>>> + queue_input.process_quantum = 100000; /* 10ms */
> >>>> + queue_input.gang_quantum = 10000; /* 1ms */
> >>>> + queue_input.paging = false;
> >>>> +
> >>>> + queue_input.gang_context_addr = queue->gang_ctx_gpu_addr;
> >>>> + queue_input.process_context_addr = queue->proc_ctx_gpu_addr;
> >>>> + queue_input.inprocess_gang_priority = AMDGPU_MES_PRIORITY_LEVEL_NORMAL;
> >>>> + queue_input.gang_global_priority_level = AMDGPU_MES_PRIORITY_LEVEL_NORMAL;
> >>> Was there an option in the MQD to specify a priority?
> >> I checked the gfx_v11_MQD structure and this MQD does have an option to
> >> specify the priority of a queue (offset 134), but as we are re-using the
> >> mqd_init function from gfx_v11_ip_funcs which sets this offset to 0 by
> >> default, its not being used.
> >>
> >> We can add a parameter for queue priority and overwrite the init values.
> >>
> >> The priority which we are setting here in this function, is for queue
> >> mapping using MES, and its the gang priority.
> > Thinking about this more, the priority would come from the context.
> > E.g., ctx->init_priority and ctx->override_priority (see
> > amdgpu_ctx_init()). We should take that into account when creating
> > the queue.
>
> In the current design, the userqueue is completely independent of the
> GFX ctx (we discussed this in V2 I think, and that's when we introduced
> the user_mgr). I agree that we should consider the queue priority, but
> we might have to get this parameter specifically from the mqd_user_in.
Ah, right. I forgot we decoupled it from the ctx. We can look at
adding priorities as a future enhancement.
Alex
>
>
> >
> >>> What about
> >>> secure settings? If not, we should validate those flags properly and
> >>> return an error if they are not currently supported.
> >>>> +
> >>>> + queue_input.process_id = queue->vm->pasid;
> >>>> + queue_input.queue_type = queue->queue_type;
> >>>> + queue_input.mqd_addr = queue->mqd.gpu_addr;
> >>>> + queue_input.wptr_addr = userq_props->wptr_gpu_addr;
> >>>> + queue_input.queue_size = userq_props->queue_size >> 2;
> >>> Do we validate the size anywhere?
> >> We are validating the whole structure/user_MQD size, but not
> >> specifically queue size. But based on your suggestion on libDRM UAPI, we
> >> are planing to add an USERQ_INFO_IOCTL in a separate patch series, which
> >> will then introduce the IP based dynamic size checking, and also the
> >> checks related to alignment and queue size.
> > We just want to protect from userspace doing something crazy like
> > making a 10M queue or something like that. We should add an interface
> > to query the sizes per IP, but we need to validate the inputs as well.
>
> Agree, I will add this queue size validation check in this series
> itself, will cross check some other inputs as well.
>
> - Shashank
>
> >
> > Alex
> >
> >> - Shashank
> >>
> >>>> + queue_input.doorbell_offset = userq_props->doorbell_index;
> >>>> + queue_input.page_table_base_addr = amdgpu_gmc_pd_addr(queue->vm->root.bo);
> >>>> +
> >>>> + amdgpu_mes_lock(&adev->mes);
> >>>> + r = adev->mes.funcs->add_hw_queue(&adev->mes, &queue_input);
> >>>> + amdgpu_mes_unlock(&adev->mes);
> >>>> + if (r) {
> >>>> + DRM_ERROR("Failed to map queue in HW, err (%d)\n", r);
> >>>> + return r;
> >>>> + }
> >>>> +
> >>>> + DRM_DEBUG_DRIVER("Queue (doorbell:%d) mapped successfully\n", userq_props->doorbell_index);
> >>>> + return 0;
> >>>> +}
> >>>> +
> >>>> static void gfx_v11_0_userq_destroy_ctx_space(struct amdgpu_userq_mgr *uq_mgr,
> >>>> struct amdgpu_usermode_queue *queue)
> >>>> {
> >>>> @@ -6601,8 +6660,18 @@ static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
> >>>> goto free_mqd;
> >>>> }
> >>>>
> >>>> + /* Map userqueue into FW using MES */
> >>>> + r = gfx_v11_0_userq_map(uq_mgr, queue, &userq_props);
> >>>> + if (r) {
> >>>> + DRM_ERROR("Failed to init MQD\n");
> >>>> + goto free_ctx;
> >>>> + }
> >>>> +
> >>>> return 0;
> >>>>
> >>>> +free_ctx:
> >>>> + gfx_v11_0_userq_destroy_ctx_space(uq_mgr, queue);
> >>>> +
> >>>> free_mqd:
> >>>> amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr, &queue->mqd.cpu_ptr);
> >>>> return r;
> >>>> @@ -6613,6 +6682,7 @@ gfx_v11_0_userq_mqd_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_userm
> >>>> {
> >>>> struct amdgpu_userq_obj *mqd = &queue->mqd;
> >>>>
> >>>> + gfx_v11_0_userq_unmap(uq_mgr, queue);
> >>>> gfx_v11_0_userq_destroy_ctx_space(uq_mgr, queue);
> >>>> amdgpu_bo_free_kernel(&mqd->obj, &mqd->gpu_addr, &mqd->cpu_ptr);
> >>>> }
> >>>> --
> >>>> 2.40.1
> >>>>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 10/10] drm/amdgpu: add delay after userqueue mapping
2023-07-06 12:36 ` [PATCH v5 10/10] drm/amdgpu: add delay after userqueue mapping Shashank Sharma
@ 2023-07-06 17:41 ` Alex Deucher
2023-07-06 18:30 ` Shashank Sharma
0 siblings, 1 reply; 50+ messages in thread
From: Alex Deucher @ 2023-07-06 17:41 UTC (permalink / raw)
To: Shashank Sharma; +Cc: Alex Deucher, arvind.yadav, Christian Koenig, amd-gfx
On Thu, Jul 6, 2023 at 8:36 AM Shashank Sharma <shashank.sharma@amd.com> wrote:
>
> It has been observed that the MES FW needs 250-300us to map the gfx
> userqueue, and if the user rings the doorbell before this duration,
> the FW never recognizes the work. This patch adds the delay of 300
> us after the queue mapping.
>
> V1: Moved the delay from userspace IOCTL to kernel (Alex).
>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Christian Koenig <christian.koenig@amd.com>
> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
> Signed-off-by: Arvind Yadav <arvind.yadav@amd.com>
> ---
> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 7 +++++++
> 1 file changed, 7 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> index 8edb020683a1..78b58c5d0fd8 100644
> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> @@ -25,6 +25,7 @@
> #include <linux/firmware.h>
> #include <linux/module.h>
> #include <linux/pci.h>
> +#include <linux/delay.h>
> #include "amdgpu.h"
> #include "amdgpu_gfx.h"
> #include "amdgpu_psp.h"
> @@ -6749,6 +6750,12 @@ static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
> goto free_ctx;
> }
>
> + /*
> + * It has been observed that HWS needs appx 250-300us to map the queue, and the
> + * user needs to wait this duration before ringing the doorbell, or else the FW
> + * will never recognize the work.
> + */
> + udelay(300);
Is there a way we can query the MES to verify that the queue is mapped
and ready? We should talk to the MES team. This is hacky and may
fail if the MES is busy, etc.
Alex
> return 0;
>
> free_ctx:
> --
> 2.40.1
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 10/10] drm/amdgpu: add delay after userqueue mapping
2023-07-06 17:41 ` Alex Deucher
@ 2023-07-06 18:30 ` Shashank Sharma
0 siblings, 0 replies; 50+ messages in thread
From: Shashank Sharma @ 2023-07-06 18:30 UTC (permalink / raw)
To: Alex Deucher; +Cc: Alex Deucher, arvind.yadav, Christian Koenig, amd-gfx
On 06/07/2023 19:41, Alex Deucher wrote:
> On Thu, Jul 6, 2023 at 8:36 AM Shashank Sharma <shashank.sharma@amd.com> wrote:
>> It has been observed that the MES FW needs 250-300us to map the gfx
>> userqueue, and if the user rings the doorbell before this duration,
>> the FW never recognizes the work. This patch adds the delay of 300
>> us after the queue mapping.
>>
>> V1: Moved the delay from userspace IOCTL to kernel (Alex).
>>
>> Cc: Alex Deucher <alexander.deucher@amd.com>
>> Cc: Christian Koenig <christian.koenig@amd.com>
>> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
>> Signed-off-by: Arvind Yadav <arvind.yadav@amd.com>
>> ---
>> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 7 +++++++
>> 1 file changed, 7 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>> index 8edb020683a1..78b58c5d0fd8 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>> @@ -25,6 +25,7 @@
>> #include <linux/firmware.h>
>> #include <linux/module.h>
>> #include <linux/pci.h>
>> +#include <linux/delay.h>
>> #include "amdgpu.h"
>> #include "amdgpu_gfx.h"
>> #include "amdgpu_psp.h"
>> @@ -6749,6 +6750,12 @@ static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
>> goto free_ctx;
>> }
>>
>> + /*
>> + * It has been observed that HWS needs appx 250-300us to map the queue, and the
>> + * user needs to wait this duration before ringing the doorbell, or else the FW
>> + * will never recognize the work.
>> + */
>> + udelay(300);
> Is there a way we can query the MES to verify that the queue is mapped
> and ready? We should talk to the MES team. This is hacky and may
> fail if the MES is busy, etc.
So far I have not received any input on this, I can restart a discussion.
- Shashank
> Alex
>
>
>> return 0;
>>
>> free_ctx:
>> --
>> 2.40.1
>>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 08/10] drm/amdgpu: generate doorbell index for userqueue
2023-07-06 12:36 ` [PATCH v5 08/10] drm/amdgpu: generate doorbell index for userqueue Shashank Sharma
@ 2023-07-07 7:15 ` Christian König
2023-07-07 7:39 ` Shashank Sharma
0 siblings, 1 reply; 50+ messages in thread
From: Christian König @ 2023-07-07 7:15 UTC (permalink / raw)
To: Shashank Sharma, amd-gfx; +Cc: Alex Deucher, arvind.yadav
Am 06.07.23 um 14:36 schrieb Shashank Sharma:
> The userspace sends us the doorbell object and the relative doobell
> index in the object to be used for the usermode queue, but the FW
> expects the absolute doorbell index on the PCI BAR in the MQD. This
> patch adds a function to convert this relative doorbell index to
> absolute doorbell index.
>
> This patch is dependent on the doorbell manager series:
> Link: https://patchwork.freedesktop.org/series/115802/
>
> V5: Fix the db object reference leak (Christian)
>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Christian Koenig <christian.koenig@amd.com>
> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
> ---
> drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 34 +++++++++++++++++++
> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 1 +
> 2 files changed, 35 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
> index bb774144c372..61064266c4f8 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
> @@ -32,6 +32,31 @@ amdgpu_userqueue_find(struct amdgpu_userq_mgr *uq_mgr, int qid)
> return idr_find(&uq_mgr->userq_idr, qid);
> }
>
> +static uint64_t
> +amdgpu_userqueue_get_doorbell_index(struct amdgpu_userq_mgr *uq_mgr,
> + struct amdgpu_usermode_queue *queue,
> + struct drm_file *filp,
> + uint32_t doorbell_offset)
> +{
> + struct drm_gem_object *gobj;
> + struct amdgpu_bo *db_bo;
> + uint64_t index;
> +
> + gobj = drm_gem_object_lookup(filp, queue->doorbell_handle);
> + if (gobj == NULL) {
> + DRM_ERROR("Can't find GEM object for doorbell\n");
> + return -EINVAL;
> + }
> +
> + db_bo = amdgpu_bo_ref(gem_to_amdgpu_bo(gobj));
> + drm_gem_object_put(gobj);
> +
> + index = amdgpu_doorbell_index_on_bar(uq_mgr->adev, db_bo, doorbell_offset);
This can only be done with the doorbell BO locked and as soon as you
unlock it the value becomes invalid unless you pin the BO.
Regards,
Christian.
> + amdgpu_bo_unref(&db_bo);
> + DRM_DEBUG_DRIVER("[Usermode queues] doorbell index=%lld\n", index);
> + return index;
> +}
> +
> static int
> amdgpu_userqueue_destroy(struct drm_file *filp, int queue_id)
> {
> @@ -64,6 +89,7 @@ amdgpu_userqueue_create(struct drm_file *filp, union drm_amdgpu_userq *args)
> struct amdgpu_userq_mgr *uq_mgr = &fpriv->userq_mgr;
> const struct amdgpu_userq_funcs *uq_funcs;
> struct amdgpu_usermode_queue *queue;
> + uint64_t index;
> int qid, r = 0;
>
> mutex_lock(&uq_mgr->userq_mutex);
> @@ -87,6 +113,14 @@ amdgpu_userqueue_create(struct drm_file *filp, union drm_amdgpu_userq *args)
> queue->flags = args->in.flags;
> queue->vm = &fpriv->vm;
>
> + /* Convert relative doorbell offset into absolute doorbell index */
> + index = amdgpu_userqueue_get_doorbell_index(uq_mgr, queue, filp, args->in.doorbell_offset);
> + if (index == (uint64_t)-EINVAL) {
> + DRM_ERROR("Failed to get doorbell for queue\n");
> + goto unlock;
> + }
> + queue->doorbell_index = index;
> +
> r = uq_funcs->mqd_create(uq_mgr, &args->in, queue);
> if (r) {
> DRM_ERROR("Failed to create Queue\n");
> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> index afaeecb9940a..8edb020683a1 100644
> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> @@ -6719,6 +6719,7 @@ static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
> userq_props.queue_size = mqd_user.queue_size;
> userq_props.hqd_base_gpu_addr = mqd_user.queue_va;
> userq_props.mqd_gpu_addr = queue->mqd.gpu_addr;
> + userq_props.doorbell_index = queue->doorbell_index;
> userq_props.use_doorbell = true;
>
> r = mqd_gfx_generic->init_mqd(adev, (void *)queue->mqd.cpu_ptr, &userq_props);
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 09/10] drm/amdgpu: cleanup leftover queues
2023-07-06 12:36 ` [PATCH v5 09/10] drm/amdgpu: cleanup leftover queues Shashank Sharma
@ 2023-07-07 7:17 ` Christian König
2023-07-07 7:40 ` Shashank Sharma
0 siblings, 1 reply; 50+ messages in thread
From: Christian König @ 2023-07-07 7:17 UTC (permalink / raw)
To: Shashank Sharma, amd-gfx; +Cc: Alex Deucher, arvind.yadav, Bas Nieuwenhuizen
Am 06.07.23 um 14:36 schrieb Shashank Sharma:
> This patch adds code to cleanup any leftover userqueues which
> a user might have missed to destroy due to a crash or any other
> programming error.
>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Christian Koenig <christian.koenig@amd.com>
> Suggested-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
> Signed-off-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
> ---
> drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 31 ++++++++++++++++---
> 1 file changed, 26 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
> index 61064266c4f8..6e32e2854a58 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
> @@ -57,12 +57,23 @@ amdgpu_userqueue_get_doorbell_index(struct amdgpu_userq_mgr *uq_mgr,
> return index;
> }
>
> +static void
> +amdgpu_userqueue_cleanup(struct amdgpu_userq_mgr *uq_mgr,
> + struct amdgpu_usermode_queue *queue,
> + int queue_id)
> +{
> + const struct amdgpu_userq_funcs *uq_funcs = uq_mgr->userq_funcs[queue->queue_type];
> +
> + uq_funcs->mqd_destroy(uq_mgr, queue);
> + idr_remove(&uq_mgr->userq_idr, queue_id);
> + kfree(queue);
> +}
> +
> static int
> amdgpu_userqueue_destroy(struct drm_file *filp, int queue_id)
> {
> struct amdgpu_fpriv *fpriv = filp->driver_priv;
> struct amdgpu_userq_mgr *uq_mgr = &fpriv->userq_mgr;
> - const struct amdgpu_userq_funcs *uq_funcs;
> struct amdgpu_usermode_queue *queue;
>
> mutex_lock(&uq_mgr->userq_mutex);
> @@ -73,11 +84,8 @@ amdgpu_userqueue_destroy(struct drm_file *filp, int queue_id)
> mutex_unlock(&uq_mgr->userq_mutex);
> return -EINVAL;
> }
> - uq_funcs = uq_mgr->userq_funcs[queue->queue_type];
> - uq_funcs->mqd_destroy(uq_mgr, queue);
> - idr_remove(&uq_mgr->userq_idr, queue_id);
> - kfree(queue);
>
> + amdgpu_userqueue_cleanup(uq_mgr, queue, queue_id);
> mutex_unlock(&uq_mgr->userq_mutex);
> return 0;
> }
> @@ -193,8 +201,21 @@ int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct amdgpu_devi
> return 0;
> }
>
> +static int amdgpu_userqueue_cleanup_residue(int queue_id, void *ptr, void *data)
> +{
> + struct amdgpu_userq_mgr *uq_mgr = data;
> + struct amdgpu_usermode_queue *queue = ptr;
> +
> + amdgpu_userqueue_cleanup(uq_mgr, queue, queue_id);
> + return 0;
> +}
> +
> void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr)
> {
> + idr_for_each(&userq_mgr->userq_idr,
> + amdgpu_userqueue_cleanup_residue,
> + userq_mgr);
> +
Better use idr_for_each_entry() here which avoids the mid layer function.
Apart from that it would be nice to have to merge this patch into the
original one adding the user queues, but really only nice to have.
Christian.
> idr_destroy(&userq_mgr->userq_idr);
> mutex_destroy(&userq_mgr->userq_mutex);
> }
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 04/10] drm/amdgpu: create GFX-gen11 usermode queue
2023-07-06 12:35 ` [PATCH v5 04/10] drm/amdgpu: create GFX-gen11 " Shashank Sharma
2023-07-06 13:22 ` Christian König
2023-07-06 16:27 ` Alex Deucher
@ 2023-07-07 7:24 ` Christian König
2023-07-07 7:46 ` Shashank Sharma
2 siblings, 1 reply; 50+ messages in thread
From: Christian König @ 2023-07-07 7:24 UTC (permalink / raw)
To: Shashank Sharma, amd-gfx; +Cc: Alex Deucher, arvind.yadav
Am 06.07.23 um 14:35 schrieb Shashank Sharma:
> A Memory queue descriptor (MQD) of a userqueue defines it in
> the hw's context. As MQD format can vary between different
> graphics IPs, we need gfx GEN specific handlers to create MQDs.
>
> This patch:
> - Introduces MQD handler functions for the usermode queues.
> - Adds new functions to create and destroy userqueue MQD for
> GFX-GEN-11 IP
>
> V1: Worked on review comments from Alex:
> - Make MQD functions GEN and IP specific
>
> V2: Worked on review comments from Alex:
> - Reuse the existing adev->mqd[ip] for MQD creation
> - Formatting and arrangement of code
>
> V3:
> - Integration with doorbell manager
>
> V4: Review comments addressed:
> - Do not create a new file for userq, reuse gfx_v11_0.c (Alex)
> - Align name of structure members (Luben)
> - Don't break up the Cc tag list and the Sob tag list in commit
> message (Luben)
> V5:
> - No need to reserve the bo for MQD (Christian).
> - Some more changes to support IP specific MQD creation.
>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Christian Koenig <christian.koenig@amd.com>
> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
> Signed-off-by: Arvind Yadav <arvind.yadav@amd.com>
> ---
> drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 16 ++++
> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 73 +++++++++++++++++++
> .../gpu/drm/amd/include/amdgpu_userqueue.h | 7 ++
> 3 files changed, 96 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
> index e37b5da5a0d0..bb774144c372 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
> @@ -134,12 +134,28 @@ int amdgpu_userq_ioctl(struct drm_device *dev, void *data,
> return r;
> }
>
> +extern const struct amdgpu_userq_funcs userq_gfx_v11_funcs;
> +
> +static void
> +amdgpu_userqueue_setup_gfx(struct amdgpu_userq_mgr *uq_mgr)
> +{
> + int maj;
> + struct amdgpu_device *adev = uq_mgr->adev;
> + uint32_t version = adev->ip_versions[GC_HWIP][0];
> +
> + /* We support usermode queue only for GFX V11 as of now */
> + maj = IP_VERSION_MAJ(version);
> + if (maj == 11)
> + uq_mgr->userq_funcs[AMDGPU_HW_IP_GFX] = &userq_gfx_v11_funcs;
> +}
> +
> int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct amdgpu_device *adev)
> {
> mutex_init(&userq_mgr->userq_mutex);
> idr_init_base(&userq_mgr->userq_idr, 1);
> userq_mgr->adev = adev;
>
> + amdgpu_userqueue_setup_gfx(userq_mgr);
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> index c4940b6ea1c4..e76e1b86b434 100644
> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> @@ -30,6 +30,7 @@
> #include "amdgpu_psp.h"
> #include "amdgpu_smu.h"
> #include "amdgpu_atomfirmware.h"
> +#include "amdgpu_userqueue.h"
> #include "imu_v11_0.h"
> #include "soc21.h"
> #include "nvd.h"
> @@ -6486,3 +6487,75 @@ const struct amdgpu_ip_block_version gfx_v11_0_ip_block =
> .rev = 0,
> .funcs = &gfx_v11_0_ip_funcs,
> };
> +
> +static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
> + struct drm_amdgpu_userq_in *args_in,
> + struct amdgpu_usermode_queue *queue)
> +{
> + struct amdgpu_device *adev = uq_mgr->adev;
> + struct amdgpu_mqd *mqd_gfx_generic = &adev->mqds[AMDGPU_HW_IP_GFX];
> + struct drm_amdgpu_userq_mqd_gfx_v11_0 mqd_user;
> + struct amdgpu_mqd_prop userq_props;
> + int r;
> +
> + /* Incoming MQD parameters from userspace to be saved here */
> + memset(&mqd_user, 0, sizeof(mqd_user));
> +
> + /* Structure to initialize MQD for userqueue using generic MQD init function */
> + memset(&userq_props, 0, sizeof(userq_props));
> +
> + if (args_in->mqd_size != sizeof(struct drm_amdgpu_userq_mqd_gfx_v11_0)) {
> + DRM_ERROR("MQD size mismatch\n");
> + return -EINVAL;
> + }
> +
> + if (copy_from_user(&mqd_user, u64_to_user_ptr(args_in->mqd), args_in->mqd_size)) {
> + DRM_ERROR("Failed to get user MQD\n");
> + return -EFAULT;
> + }
Sorry, I've just seen that now. Please don't have a copy_from_user() in
the backend!
This is pure front end stuff which we shouldn't do in hw generation
specific code.
Regards,
Christian.
> +
> + /* Create BO for actual Userqueue MQD now */
> + r = amdgpu_bo_create_kernel(adev, mqd_gfx_generic->mqd_size, PAGE_SIZE,
> + AMDGPU_GEM_DOMAIN_GTT,
> + &queue->mqd.obj,
> + &queue->mqd.gpu_addr,
> + &queue->mqd.cpu_ptr);
> + if (r) {
> + DRM_ERROR("Failed to allocate BO for userqueue (%d)", r);
> + return -ENOMEM;
> + }
> + memset(queue->mqd.cpu_ptr, 0, mqd_gfx_generic->mqd_size);
> +
> + /* Initialize the MQD BO with user given values */
> + userq_props.wptr_gpu_addr = mqd_user.wptr_va;
> + userq_props.rptr_gpu_addr = mqd_user.rptr_va;
> + userq_props.queue_size = mqd_user.queue_size;
> + userq_props.hqd_base_gpu_addr = mqd_user.queue_va;
> + userq_props.mqd_gpu_addr = queue->mqd.gpu_addr;
> + userq_props.use_doorbell = true;
> +
> + r = mqd_gfx_generic->init_mqd(adev, (void *)queue->mqd.cpu_ptr, &userq_props);
> + if (r) {
> + DRM_ERROR("Failed to initialize MQD for userqueue\n");
> + goto free_mqd;
> + }
> +
> + return 0;
> +
> +free_mqd:
> + amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr, &queue->mqd.cpu_ptr);
> + return r;
> +}
> +
> +static void
> +gfx_v11_0_userq_mqd_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_queue *queue)
> +{
> + struct amdgpu_userq_obj *mqd = &queue->mqd;
> +
> + amdgpu_bo_free_kernel(&mqd->obj, &mqd->gpu_addr, &mqd->cpu_ptr);
> +}
> +
> +const struct amdgpu_userq_funcs userq_gfx_v11_funcs = {
> + .mqd_create = gfx_v11_0_userq_mqd_create,
> + .mqd_destroy = gfx_v11_0_userq_mqd_destroy,
> +};
> diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
> index 55ed6512a565..240f92796f00 100644
> --- a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
> +++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
> @@ -29,6 +29,12 @@
>
> struct amdgpu_mqd_prop;
>
> +struct amdgpu_userq_obj {
> + void *cpu_ptr;
> + uint64_t gpu_addr;
> + struct amdgpu_bo *obj;
> +};
> +
> struct amdgpu_usermode_queue {
> int queue_type;
> uint64_t doorbell_handle;
> @@ -37,6 +43,7 @@ struct amdgpu_usermode_queue {
> struct amdgpu_mqd_prop *userq_prop;
> struct amdgpu_userq_mgr *userq_mgr;
> struct amdgpu_vm *vm;
> + struct amdgpu_userq_obj mqd;
> };
>
> struct amdgpu_userq_funcs {
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 08/10] drm/amdgpu: generate doorbell index for userqueue
2023-07-07 7:15 ` Christian König
@ 2023-07-07 7:39 ` Shashank Sharma
2023-07-07 7:57 ` Christian König
0 siblings, 1 reply; 50+ messages in thread
From: Shashank Sharma @ 2023-07-07 7:39 UTC (permalink / raw)
To: Christian König, amd-gfx; +Cc: Alex Deucher, arvind.yadav
On 07/07/2023 09:15, Christian König wrote:
> Am 06.07.23 um 14:36 schrieb Shashank Sharma:
>> The userspace sends us the doorbell object and the relative doobell
>> index in the object to be used for the usermode queue, but the FW
>> expects the absolute doorbell index on the PCI BAR in the MQD. This
>> patch adds a function to convert this relative doorbell index to
>> absolute doorbell index.
>>
>> This patch is dependent on the doorbell manager series:
>> Link: https://patchwork.freedesktop.org/series/115802/
>>
>> V5: Fix the db object reference leak (Christian)
>>
>> Cc: Alex Deucher <alexander.deucher@amd.com>
>> Cc: Christian Koenig <christian.koenig@amd.com>
>> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
>> ---
>> drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 34 +++++++++++++++++++
>> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 1 +
>> 2 files changed, 35 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>> index bb774144c372..61064266c4f8 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>> @@ -32,6 +32,31 @@ amdgpu_userqueue_find(struct amdgpu_userq_mgr
>> *uq_mgr, int qid)
>> return idr_find(&uq_mgr->userq_idr, qid);
>> }
>> +static uint64_t
>> +amdgpu_userqueue_get_doorbell_index(struct amdgpu_userq_mgr *uq_mgr,
>> + struct amdgpu_usermode_queue *queue,
>> + struct drm_file *filp,
>> + uint32_t doorbell_offset)
>> +{
>> + struct drm_gem_object *gobj;
>> + struct amdgpu_bo *db_bo;
>> + uint64_t index;
>> +
>> + gobj = drm_gem_object_lookup(filp, queue->doorbell_handle);
>> + if (gobj == NULL) {
>> + DRM_ERROR("Can't find GEM object for doorbell\n");
>> + return -EINVAL;
>> + }
>> +
>> + db_bo = amdgpu_bo_ref(gem_to_amdgpu_bo(gobj));
>> + drm_gem_object_put(gobj);
>> +
>> + index = amdgpu_doorbell_index_on_bar(uq_mgr->adev, db_bo,
>> doorbell_offset);
>
> This can only be done with the doorbell BO locked and as soon as you
> unlock it the value becomes invalid unless you pin the BO.
>
Which means I need to use create_bo_kernel() for doorbell BO's or
specifically pin it while creating it ?
- Shashank
> Regards,
> Christian.
>
>> + amdgpu_bo_unref(&db_bo);
>> + DRM_DEBUG_DRIVER("[Usermode queues] doorbell index=%lld\n", index);
>> + return index;
>> +}
>> +
>> static int
>> amdgpu_userqueue_destroy(struct drm_file *filp, int queue_id)
>> {
>> @@ -64,6 +89,7 @@ amdgpu_userqueue_create(struct drm_file *filp,
>> union drm_amdgpu_userq *args)
>> struct amdgpu_userq_mgr *uq_mgr = &fpriv->userq_mgr;
>> const struct amdgpu_userq_funcs *uq_funcs;
>> struct amdgpu_usermode_queue *queue;
>> + uint64_t index;
>> int qid, r = 0;
>> mutex_lock(&uq_mgr->userq_mutex);
>> @@ -87,6 +113,14 @@ amdgpu_userqueue_create(struct drm_file *filp,
>> union drm_amdgpu_userq *args)
>> queue->flags = args->in.flags;
>> queue->vm = &fpriv->vm;
>> + /* Convert relative doorbell offset into absolute doorbell
>> index */
>> + index = amdgpu_userqueue_get_doorbell_index(uq_mgr, queue, filp,
>> args->in.doorbell_offset);
>> + if (index == (uint64_t)-EINVAL) {
>> + DRM_ERROR("Failed to get doorbell for queue\n");
>> + goto unlock;
>> + }
>> + queue->doorbell_index = index;
>> +
>> r = uq_funcs->mqd_create(uq_mgr, &args->in, queue);
>> if (r) {
>> DRM_ERROR("Failed to create Queue\n");
>> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>> b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>> index afaeecb9940a..8edb020683a1 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>> @@ -6719,6 +6719,7 @@ static int gfx_v11_0_userq_mqd_create(struct
>> amdgpu_userq_mgr *uq_mgr,
>> userq_props.queue_size = mqd_user.queue_size;
>> userq_props.hqd_base_gpu_addr = mqd_user.queue_va;
>> userq_props.mqd_gpu_addr = queue->mqd.gpu_addr;
>> + userq_props.doorbell_index = queue->doorbell_index;
>> userq_props.use_doorbell = true;
>> r = mqd_gfx_generic->init_mqd(adev, (void
>> *)queue->mqd.cpu_ptr, &userq_props);
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 09/10] drm/amdgpu: cleanup leftover queues
2023-07-07 7:17 ` Christian König
@ 2023-07-07 7:40 ` Shashank Sharma
0 siblings, 0 replies; 50+ messages in thread
From: Shashank Sharma @ 2023-07-07 7:40 UTC (permalink / raw)
To: Christian König, amd-gfx
Cc: Alex Deucher, arvind.yadav, Bas Nieuwenhuizen
On 07/07/2023 09:17, Christian König wrote:
>
>
> Am 06.07.23 um 14:36 schrieb Shashank Sharma:
>> This patch adds code to cleanup any leftover userqueues which
>> a user might have missed to destroy due to a crash or any other
>> programming error.
>>
>> Cc: Alex Deucher <alexander.deucher@amd.com>
>> Cc: Christian Koenig <christian.koenig@amd.com>
>> Suggested-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
>> Signed-off-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
>> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
>> ---
>> drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 31 ++++++++++++++++---
>> 1 file changed, 26 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>> index 61064266c4f8..6e32e2854a58 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>> @@ -57,12 +57,23 @@ amdgpu_userqueue_get_doorbell_index(struct
>> amdgpu_userq_mgr *uq_mgr,
>> return index;
>> }
>> +static void
>> +amdgpu_userqueue_cleanup(struct amdgpu_userq_mgr *uq_mgr,
>> + struct amdgpu_usermode_queue *queue,
>> + int queue_id)
>> +{
>> + const struct amdgpu_userq_funcs *uq_funcs =
>> uq_mgr->userq_funcs[queue->queue_type];
>> +
>> + uq_funcs->mqd_destroy(uq_mgr, queue);
>> + idr_remove(&uq_mgr->userq_idr, queue_id);
>> + kfree(queue);
>> +}
>> +
>> static int
>> amdgpu_userqueue_destroy(struct drm_file *filp, int queue_id)
>> {
>> struct amdgpu_fpriv *fpriv = filp->driver_priv;
>> struct amdgpu_userq_mgr *uq_mgr = &fpriv->userq_mgr;
>> - const struct amdgpu_userq_funcs *uq_funcs;
>> struct amdgpu_usermode_queue *queue;
>> mutex_lock(&uq_mgr->userq_mutex);
>> @@ -73,11 +84,8 @@ amdgpu_userqueue_destroy(struct drm_file *filp,
>> int queue_id)
>> mutex_unlock(&uq_mgr->userq_mutex);
>> return -EINVAL;
>> }
>> - uq_funcs = uq_mgr->userq_funcs[queue->queue_type];
>> - uq_funcs->mqd_destroy(uq_mgr, queue);
>> - idr_remove(&uq_mgr->userq_idr, queue_id);
>> - kfree(queue);
>> + amdgpu_userqueue_cleanup(uq_mgr, queue, queue_id);
>> mutex_unlock(&uq_mgr->userq_mutex);
>> return 0;
>> }
>> @@ -193,8 +201,21 @@ int amdgpu_userq_mgr_init(struct
>> amdgpu_userq_mgr *userq_mgr, struct amdgpu_devi
>> return 0;
>> }
>> +static int amdgpu_userqueue_cleanup_residue(int queue_id, void
>> *ptr, void *data)
>> +{
>> + struct amdgpu_userq_mgr *uq_mgr = data;
>> + struct amdgpu_usermode_queue *queue = ptr;
>> +
>> + amdgpu_userqueue_cleanup(uq_mgr, queue, queue_id);
>> + return 0;
>> +}
>> +
>> void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr)
>> {
>> + idr_for_each(&userq_mgr->userq_idr,
>> + amdgpu_userqueue_cleanup_residue,
>> + userq_mgr);
>> +
>
> Better use idr_for_each_entry() here which avoids the mid layer function.
>
> Apart from that it would be nice to have to merge this patch into the
> original one adding the user queues, but really only nice to have.
Noted, will check that out.
- Shashank
>
> Christian.
>
>> idr_destroy(&userq_mgr->userq_idr);
>> mutex_destroy(&userq_mgr->userq_mutex);
>> }
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 04/10] drm/amdgpu: create GFX-gen11 usermode queue
2023-07-07 7:24 ` Christian König
@ 2023-07-07 7:46 ` Shashank Sharma
2023-07-07 8:37 ` Christian König
0 siblings, 1 reply; 50+ messages in thread
From: Shashank Sharma @ 2023-07-07 7:46 UTC (permalink / raw)
To: Christian König, amd-gfx; +Cc: Alex Deucher, arvind.yadav
On 07/07/2023 09:24, Christian König wrote:
>
>
> Am 06.07.23 um 14:35 schrieb Shashank Sharma:
>> A Memory queue descriptor (MQD) of a userqueue defines it in
>> the hw's context. As MQD format can vary between different
>> graphics IPs, we need gfx GEN specific handlers to create MQDs.
>>
>> This patch:
>> - Introduces MQD handler functions for the usermode queues.
>> - Adds new functions to create and destroy userqueue MQD for
>> GFX-GEN-11 IP
>>
>> V1: Worked on review comments from Alex:
>> - Make MQD functions GEN and IP specific
>>
>> V2: Worked on review comments from Alex:
>> - Reuse the existing adev->mqd[ip] for MQD creation
>> - Formatting and arrangement of code
>>
>> V3:
>> - Integration with doorbell manager
>>
>> V4: Review comments addressed:
>> - Do not create a new file for userq, reuse gfx_v11_0.c (Alex)
>> - Align name of structure members (Luben)
>> - Don't break up the Cc tag list and the Sob tag list in commit
>> message (Luben)
>> V5:
>> - No need to reserve the bo for MQD (Christian).
>> - Some more changes to support IP specific MQD creation.
>>
>> Cc: Alex Deucher <alexander.deucher@amd.com>
>> Cc: Christian Koenig <christian.koenig@amd.com>
>> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
>> Signed-off-by: Arvind Yadav <arvind.yadav@amd.com>
>> ---
>> drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 16 ++++
>> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 73 +++++++++++++++++++
>> .../gpu/drm/amd/include/amdgpu_userqueue.h | 7 ++
>> 3 files changed, 96 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>> index e37b5da5a0d0..bb774144c372 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>> @@ -134,12 +134,28 @@ int amdgpu_userq_ioctl(struct drm_device *dev,
>> void *data,
>> return r;
>> }
>> +extern const struct amdgpu_userq_funcs userq_gfx_v11_funcs;
>> +
>> +static void
>> +amdgpu_userqueue_setup_gfx(struct amdgpu_userq_mgr *uq_mgr)
>> +{
>> + int maj;
>> + struct amdgpu_device *adev = uq_mgr->adev;
>> + uint32_t version = adev->ip_versions[GC_HWIP][0];
>> +
>> + /* We support usermode queue only for GFX V11 as of now */
>> + maj = IP_VERSION_MAJ(version);
>> + if (maj == 11)
>> + uq_mgr->userq_funcs[AMDGPU_HW_IP_GFX] = &userq_gfx_v11_funcs;
>> +}
>> +
>> int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr,
>> struct amdgpu_device *adev)
>> {
>> mutex_init(&userq_mgr->userq_mutex);
>> idr_init_base(&userq_mgr->userq_idr, 1);
>> userq_mgr->adev = adev;
>> + amdgpu_userqueue_setup_gfx(userq_mgr);
>> return 0;
>> }
>> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>> b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>> index c4940b6ea1c4..e76e1b86b434 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>> @@ -30,6 +30,7 @@
>> #include "amdgpu_psp.h"
>> #include "amdgpu_smu.h"
>> #include "amdgpu_atomfirmware.h"
>> +#include "amdgpu_userqueue.h"
>> #include "imu_v11_0.h"
>> #include "soc21.h"
>> #include "nvd.h"
>> @@ -6486,3 +6487,75 @@ const struct amdgpu_ip_block_version
>> gfx_v11_0_ip_block =
>> .rev = 0,
>> .funcs = &gfx_v11_0_ip_funcs,
>> };
>> +
>> +static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
>> + struct drm_amdgpu_userq_in *args_in,
>> + struct amdgpu_usermode_queue *queue)
>> +{
>> + struct amdgpu_device *adev = uq_mgr->adev;
>> + struct amdgpu_mqd *mqd_gfx_generic = &adev->mqds[AMDGPU_HW_IP_GFX];
>> + struct drm_amdgpu_userq_mqd_gfx_v11_0 mqd_user;
>> + struct amdgpu_mqd_prop userq_props;
>> + int r;
>> +
>> + /* Incoming MQD parameters from userspace to be saved here */
>> + memset(&mqd_user, 0, sizeof(mqd_user));
>> +
>> + /* Structure to initialize MQD for userqueue using generic MQD
>> init function */
>> + memset(&userq_props, 0, sizeof(userq_props));
>> +
>> + if (args_in->mqd_size != sizeof(struct
>> drm_amdgpu_userq_mqd_gfx_v11_0)) {
>> + DRM_ERROR("MQD size mismatch\n");
>> + return -EINVAL;
>> + }
>> +
>> + if (copy_from_user(&mqd_user, u64_to_user_ptr(args_in->mqd),
>> args_in->mqd_size)) {
>> + DRM_ERROR("Failed to get user MQD\n");
>> + return -EFAULT;
>> + }
>
> Sorry, I've just seen that now. Please don't have a copy_from_user()
> in the backend!
>
> This is pure front end stuff which we shouldn't do in hw generation
> specific code.
>
This is a bit difficult to achieve, as you know:
- the whole reason we moved to ptr/size based approach from
fix-mqd-structure approach is so that we can support multiple MQD
structures using the same UAPI.
- which means that in file amdgpu_userqueue.c layer (say front-end) I do
not know what is the right size of MQD, its independent of IP.
- the correct size of MQD can only be known in IP specific functions
which are in gfx_v11.c (back end).
- I may be able to achieve it by adding a new fptr get_mqd_size() which
can return the right MQD size for me from backend IP function, and then
I can move this copy from user to front-end. Does it sound like a good
idea to you ?
- Shashank
> Regards,
> Christian.
>
>> +
>> + /* Create BO for actual Userqueue MQD now */
>> + r = amdgpu_bo_create_kernel(adev, mqd_gfx_generic->mqd_size,
>> PAGE_SIZE,
>> + AMDGPU_GEM_DOMAIN_GTT,
>> + &queue->mqd.obj,
>> + &queue->mqd.gpu_addr,
>> + &queue->mqd.cpu_ptr);
>> + if (r) {
>> + DRM_ERROR("Failed to allocate BO for userqueue (%d)", r);
>> + return -ENOMEM;
>> + }
>> + memset(queue->mqd.cpu_ptr, 0, mqd_gfx_generic->mqd_size);
>> +
>> + /* Initialize the MQD BO with user given values */
>> + userq_props.wptr_gpu_addr = mqd_user.wptr_va;
>> + userq_props.rptr_gpu_addr = mqd_user.rptr_va;
>> + userq_props.queue_size = mqd_user.queue_size;
>> + userq_props.hqd_base_gpu_addr = mqd_user.queue_va;
>> + userq_props.mqd_gpu_addr = queue->mqd.gpu_addr;
>> + userq_props.use_doorbell = true;
>> +
>> + r = mqd_gfx_generic->init_mqd(adev, (void *)queue->mqd.cpu_ptr,
>> &userq_props);
>> + if (r) {
>> + DRM_ERROR("Failed to initialize MQD for userqueue\n");
>> + goto free_mqd;
>> + }
>> +
>> + return 0;
>> +
>> +free_mqd:
>> + amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr,
>> &queue->mqd.cpu_ptr);
>> + return r;
>> +}
>> +
>> +static void
>> +gfx_v11_0_userq_mqd_destroy(struct amdgpu_userq_mgr *uq_mgr, struct
>> amdgpu_usermode_queue *queue)
>> +{
>> + struct amdgpu_userq_obj *mqd = &queue->mqd;
>> +
>> + amdgpu_bo_free_kernel(&mqd->obj, &mqd->gpu_addr, &mqd->cpu_ptr);
>> +}
>> +
>> +const struct amdgpu_userq_funcs userq_gfx_v11_funcs = {
>> + .mqd_create = gfx_v11_0_userq_mqd_create,
>> + .mqd_destroy = gfx_v11_0_userq_mqd_destroy,
>> +};
>> diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>> b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>> index 55ed6512a565..240f92796f00 100644
>> --- a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>> +++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>> @@ -29,6 +29,12 @@
>> struct amdgpu_mqd_prop;
>> +struct amdgpu_userq_obj {
>> + void *cpu_ptr;
>> + uint64_t gpu_addr;
>> + struct amdgpu_bo *obj;
>> +};
>> +
>> struct amdgpu_usermode_queue {
>> int queue_type;
>> uint64_t doorbell_handle;
>> @@ -37,6 +43,7 @@ struct amdgpu_usermode_queue {
>> struct amdgpu_mqd_prop *userq_prop;
>> struct amdgpu_userq_mgr *userq_mgr;
>> struct amdgpu_vm *vm;
>> + struct amdgpu_userq_obj mqd;
>> };
>> struct amdgpu_userq_funcs {
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 08/10] drm/amdgpu: generate doorbell index for userqueue
2023-07-07 7:39 ` Shashank Sharma
@ 2023-07-07 7:57 ` Christian König
2023-07-07 9:00 ` Shashank Sharma
0 siblings, 1 reply; 50+ messages in thread
From: Christian König @ 2023-07-07 7:57 UTC (permalink / raw)
To: Shashank Sharma, amd-gfx; +Cc: Alex Deucher, arvind.yadav
Am 07.07.23 um 09:39 schrieb Shashank Sharma:
>
> On 07/07/2023 09:15, Christian König wrote:
>> Am 06.07.23 um 14:36 schrieb Shashank Sharma:
>>> The userspace sends us the doorbell object and the relative doobell
>>> index in the object to be used for the usermode queue, but the FW
>>> expects the absolute doorbell index on the PCI BAR in the MQD. This
>>> patch adds a function to convert this relative doorbell index to
>>> absolute doorbell index.
>>>
>>> This patch is dependent on the doorbell manager series:
>>> Link: https://patchwork.freedesktop.org/series/115802/
>>>
>>> V5: Fix the db object reference leak (Christian)
>>>
>>> Cc: Alex Deucher <alexander.deucher@amd.com>
>>> Cc: Christian Koenig <christian.koenig@amd.com>
>>> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
>>> ---
>>> drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 34
>>> +++++++++++++++++++
>>> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 1 +
>>> 2 files changed, 35 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>> index bb774144c372..61064266c4f8 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>> @@ -32,6 +32,31 @@ amdgpu_userqueue_find(struct amdgpu_userq_mgr
>>> *uq_mgr, int qid)
>>> return idr_find(&uq_mgr->userq_idr, qid);
>>> }
>>> +static uint64_t
>>> +amdgpu_userqueue_get_doorbell_index(struct amdgpu_userq_mgr *uq_mgr,
>>> + struct amdgpu_usermode_queue *queue,
>>> + struct drm_file *filp,
>>> + uint32_t doorbell_offset)
>>> +{
>>> + struct drm_gem_object *gobj;
>>> + struct amdgpu_bo *db_bo;
>>> + uint64_t index;
>>> +
>>> + gobj = drm_gem_object_lookup(filp, queue->doorbell_handle);
>>> + if (gobj == NULL) {
>>> + DRM_ERROR("Can't find GEM object for doorbell\n");
>>> + return -EINVAL;
>>> + }
>>> +
>>> + db_bo = amdgpu_bo_ref(gem_to_amdgpu_bo(gobj));
>>> + drm_gem_object_put(gobj);
>>> +
>>> + index = amdgpu_doorbell_index_on_bar(uq_mgr->adev, db_bo,
>>> doorbell_offset);
>>
>> This can only be done with the doorbell BO locked and as soon as you
>> unlock it the value becomes invalid unless you pin the BO.
>>
> Which means I need to use create_bo_kernel() for doorbell BO's or
> specifically pin it while creating it ?
For now I think you need to pin it when amdgpu_userqueue_create() is
called and unpin it when the userqueue is destroyed again.
It's probably a good idea to not use amdgpu_bo_create_kernel() for the
MQD and context BO either, but rather explicitly pin it during queue
create as well.
Christian.
>
> - Shashank
>
>> Regards,
>> Christian.
>>
>>> + amdgpu_bo_unref(&db_bo);
>>> + DRM_DEBUG_DRIVER("[Usermode queues] doorbell index=%lld\n",
>>> index);
>>> + return index;
>>> +}
>>> +
>>> static int
>>> amdgpu_userqueue_destroy(struct drm_file *filp, int queue_id)
>>> {
>>> @@ -64,6 +89,7 @@ amdgpu_userqueue_create(struct drm_file *filp,
>>> union drm_amdgpu_userq *args)
>>> struct amdgpu_userq_mgr *uq_mgr = &fpriv->userq_mgr;
>>> const struct amdgpu_userq_funcs *uq_funcs;
>>> struct amdgpu_usermode_queue *queue;
>>> + uint64_t index;
>>> int qid, r = 0;
>>> mutex_lock(&uq_mgr->userq_mutex);
>>> @@ -87,6 +113,14 @@ amdgpu_userqueue_create(struct drm_file *filp,
>>> union drm_amdgpu_userq *args)
>>> queue->flags = args->in.flags;
>>> queue->vm = &fpriv->vm;
>>> + /* Convert relative doorbell offset into absolute doorbell
>>> index */
>>> + index = amdgpu_userqueue_get_doorbell_index(uq_mgr, queue,
>>> filp, args->in.doorbell_offset);
>>> + if (index == (uint64_t)-EINVAL) {
>>> + DRM_ERROR("Failed to get doorbell for queue\n");
>>> + goto unlock;
>>> + }
>>> + queue->doorbell_index = index;
>>> +
>>> r = uq_funcs->mqd_create(uq_mgr, &args->in, queue);
>>> if (r) {
>>> DRM_ERROR("Failed to create Queue\n");
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>> b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>> index afaeecb9940a..8edb020683a1 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>> @@ -6719,6 +6719,7 @@ static int gfx_v11_0_userq_mqd_create(struct
>>> amdgpu_userq_mgr *uq_mgr,
>>> userq_props.queue_size = mqd_user.queue_size;
>>> userq_props.hqd_base_gpu_addr = mqd_user.queue_va;
>>> userq_props.mqd_gpu_addr = queue->mqd.gpu_addr;
>>> + userq_props.doorbell_index = queue->doorbell_index;
>>> userq_props.use_doorbell = true;
>>> r = mqd_gfx_generic->init_mqd(adev, (void
>>> *)queue->mqd.cpu_ptr, &userq_props);
>>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 04/10] drm/amdgpu: create GFX-gen11 usermode queue
2023-07-07 7:46 ` Shashank Sharma
@ 2023-07-07 8:37 ` Christian König
2023-07-07 10:02 ` Shashank Sharma
0 siblings, 1 reply; 50+ messages in thread
From: Christian König @ 2023-07-07 8:37 UTC (permalink / raw)
To: Shashank Sharma, amd-gfx; +Cc: Alex Deucher, arvind.yadav
Am 07.07.23 um 09:46 schrieb Shashank Sharma:
>
> On 07/07/2023 09:24, Christian König wrote:
>>
>>
>> Am 06.07.23 um 14:35 schrieb Shashank Sharma:
>>> A Memory queue descriptor (MQD) of a userqueue defines it in
>>> the hw's context. As MQD format can vary between different
>>> graphics IPs, we need gfx GEN specific handlers to create MQDs.
>>>
>>> This patch:
>>> - Introduces MQD handler functions for the usermode queues.
>>> - Adds new functions to create and destroy userqueue MQD for
>>> GFX-GEN-11 IP
>>>
>>> V1: Worked on review comments from Alex:
>>> - Make MQD functions GEN and IP specific
>>>
>>> V2: Worked on review comments from Alex:
>>> - Reuse the existing adev->mqd[ip] for MQD creation
>>> - Formatting and arrangement of code
>>>
>>> V3:
>>> - Integration with doorbell manager
>>>
>>> V4: Review comments addressed:
>>> - Do not create a new file for userq, reuse gfx_v11_0.c (Alex)
>>> - Align name of structure members (Luben)
>>> - Don't break up the Cc tag list and the Sob tag list in commit
>>> message (Luben)
>>> V5:
>>> - No need to reserve the bo for MQD (Christian).
>>> - Some more changes to support IP specific MQD creation.
>>>
>>> Cc: Alex Deucher <alexander.deucher@amd.com>
>>> Cc: Christian Koenig <christian.koenig@amd.com>
>>> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
>>> Signed-off-by: Arvind Yadav <arvind.yadav@amd.com>
>>> ---
>>> drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 16 ++++
>>> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 73
>>> +++++++++++++++++++
>>> .../gpu/drm/amd/include/amdgpu_userqueue.h | 7 ++
>>> 3 files changed, 96 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>> index e37b5da5a0d0..bb774144c372 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>> @@ -134,12 +134,28 @@ int amdgpu_userq_ioctl(struct drm_device *dev,
>>> void *data,
>>> return r;
>>> }
>>> +extern const struct amdgpu_userq_funcs userq_gfx_v11_funcs;
>>> +
>>> +static void
>>> +amdgpu_userqueue_setup_gfx(struct amdgpu_userq_mgr *uq_mgr)
>>> +{
>>> + int maj;
>>> + struct amdgpu_device *adev = uq_mgr->adev;
>>> + uint32_t version = adev->ip_versions[GC_HWIP][0];
>>> +
>>> + /* We support usermode queue only for GFX V11 as of now */
>>> + maj = IP_VERSION_MAJ(version);
>>> + if (maj == 11)
>>> + uq_mgr->userq_funcs[AMDGPU_HW_IP_GFX] = &userq_gfx_v11_funcs;
>>> +}
>>> +
>>> int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr,
>>> struct amdgpu_device *adev)
>>> {
>>> mutex_init(&userq_mgr->userq_mutex);
>>> idr_init_base(&userq_mgr->userq_idr, 1);
>>> userq_mgr->adev = adev;
>>> + amdgpu_userqueue_setup_gfx(userq_mgr);
>>> return 0;
>>> }
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>> b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>> index c4940b6ea1c4..e76e1b86b434 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>> @@ -30,6 +30,7 @@
>>> #include "amdgpu_psp.h"
>>> #include "amdgpu_smu.h"
>>> #include "amdgpu_atomfirmware.h"
>>> +#include "amdgpu_userqueue.h"
>>> #include "imu_v11_0.h"
>>> #include "soc21.h"
>>> #include "nvd.h"
>>> @@ -6486,3 +6487,75 @@ const struct amdgpu_ip_block_version
>>> gfx_v11_0_ip_block =
>>> .rev = 0,
>>> .funcs = &gfx_v11_0_ip_funcs,
>>> };
>>> +
>>> +static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr *uq_mgr,
>>> + struct drm_amdgpu_userq_in *args_in,
>>> + struct amdgpu_usermode_queue *queue)
>>> +{
>>> + struct amdgpu_device *adev = uq_mgr->adev;
>>> + struct amdgpu_mqd *mqd_gfx_generic =
>>> &adev->mqds[AMDGPU_HW_IP_GFX];
>>> + struct drm_amdgpu_userq_mqd_gfx_v11_0 mqd_user;
>>> + struct amdgpu_mqd_prop userq_props;
>>> + int r;
>>> +
>>> + /* Incoming MQD parameters from userspace to be saved here */
>>> + memset(&mqd_user, 0, sizeof(mqd_user));
>>> +
>>> + /* Structure to initialize MQD for userqueue using generic MQD
>>> init function */
>>> + memset(&userq_props, 0, sizeof(userq_props));
>>> +
>>> + if (args_in->mqd_size != sizeof(struct
>>> drm_amdgpu_userq_mqd_gfx_v11_0)) {
>>> + DRM_ERROR("MQD size mismatch\n");
>>> + return -EINVAL;
>>> + }
>>> +
>>> + if (copy_from_user(&mqd_user, u64_to_user_ptr(args_in->mqd),
>>> args_in->mqd_size)) {
>>> + DRM_ERROR("Failed to get user MQD\n");
>>> + return -EFAULT;
>>> + }
>>
>> Sorry, I've just seen that now. Please don't have a copy_from_user()
>> in the backend!
>>
>> This is pure front end stuff which we shouldn't do in hw generation
>> specific code.
>>
> This is a bit difficult to achieve, as you know:
>
> - the whole reason we moved to ptr/size based approach from
> fix-mqd-structure approach is so that we can support multiple MQD
> structures using the same UAPI.
>
> - which means that in file amdgpu_userqueue.c layer (say front-end) I
> do not know what is the right size of MQD, its independent of IP.
>
> - the correct size of MQD can only be known in IP specific functions
> which are in gfx_v11.c (back end).
>
> - I may be able to achieve it by adding a new fptr get_mqd_size()
> which can return the right MQD size for me from backend IP function,
> and then I can move this copy from user to front-end. Does it sound
> like a good idea to you ?
Just use memdup_user() in the frontend. Allocating structures which are
copied from userspace on the stack is usually a bad idea as well.
Then pass in the kernel ptr and size as argument here and validate if
what userspace gave us is correct.
Regards,
Christian.
>
> - Shashank
>
>> Regards,
>> Christian.
>>
>>> +
>>> + /* Create BO for actual Userqueue MQD now */
>>> + r = amdgpu_bo_create_kernel(adev, mqd_gfx_generic->mqd_size,
>>> PAGE_SIZE,
>>> + AMDGPU_GEM_DOMAIN_GTT,
>>> + &queue->mqd.obj,
>>> + &queue->mqd.gpu_addr,
>>> + &queue->mqd.cpu_ptr);
>>> + if (r) {
>>> + DRM_ERROR("Failed to allocate BO for userqueue (%d)", r);
>>> + return -ENOMEM;
>>> + }
>>> + memset(queue->mqd.cpu_ptr, 0, mqd_gfx_generic->mqd_size);
>>> +
>>> + /* Initialize the MQD BO with user given values */
>>> + userq_props.wptr_gpu_addr = mqd_user.wptr_va;
>>> + userq_props.rptr_gpu_addr = mqd_user.rptr_va;
>>> + userq_props.queue_size = mqd_user.queue_size;
>>> + userq_props.hqd_base_gpu_addr = mqd_user.queue_va;
>>> + userq_props.mqd_gpu_addr = queue->mqd.gpu_addr;
>>> + userq_props.use_doorbell = true;
>>> +
>>> + r = mqd_gfx_generic->init_mqd(adev, (void *)queue->mqd.cpu_ptr,
>>> &userq_props);
>>> + if (r) {
>>> + DRM_ERROR("Failed to initialize MQD for userqueue\n");
>>> + goto free_mqd;
>>> + }
>>> +
>>> + return 0;
>>> +
>>> +free_mqd:
>>> + amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr,
>>> &queue->mqd.cpu_ptr);
>>> + return r;
>>> +}
>>> +
>>> +static void
>>> +gfx_v11_0_userq_mqd_destroy(struct amdgpu_userq_mgr *uq_mgr, struct
>>> amdgpu_usermode_queue *queue)
>>> +{
>>> + struct amdgpu_userq_obj *mqd = &queue->mqd;
>>> +
>>> + amdgpu_bo_free_kernel(&mqd->obj, &mqd->gpu_addr, &mqd->cpu_ptr);
>>> +}
>>> +
>>> +const struct amdgpu_userq_funcs userq_gfx_v11_funcs = {
>>> + .mqd_create = gfx_v11_0_userq_mqd_create,
>>> + .mqd_destroy = gfx_v11_0_userq_mqd_destroy,
>>> +};
>>> diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>> b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>> index 55ed6512a565..240f92796f00 100644
>>> --- a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>> +++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>> @@ -29,6 +29,12 @@
>>> struct amdgpu_mqd_prop;
>>> +struct amdgpu_userq_obj {
>>> + void *cpu_ptr;
>>> + uint64_t gpu_addr;
>>> + struct amdgpu_bo *obj;
>>> +};
>>> +
>>> struct amdgpu_usermode_queue {
>>> int queue_type;
>>> uint64_t doorbell_handle;
>>> @@ -37,6 +43,7 @@ struct amdgpu_usermode_queue {
>>> struct amdgpu_mqd_prop *userq_prop;
>>> struct amdgpu_userq_mgr *userq_mgr;
>>> struct amdgpu_vm *vm;
>>> + struct amdgpu_userq_obj mqd;
>>> };
>>> struct amdgpu_userq_funcs {
>>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 08/10] drm/amdgpu: generate doorbell index for userqueue
2023-07-07 7:57 ` Christian König
@ 2023-07-07 9:00 ` Shashank Sharma
0 siblings, 0 replies; 50+ messages in thread
From: Shashank Sharma @ 2023-07-07 9:00 UTC (permalink / raw)
To: Christian König, amd-gfx; +Cc: Alex Deucher, arvind.yadav
On 07/07/2023 09:57, Christian König wrote:
> Am 07.07.23 um 09:39 schrieb Shashank Sharma:
>>
>> On 07/07/2023 09:15, Christian König wrote:
>>> Am 06.07.23 um 14:36 schrieb Shashank Sharma:
>>>> The userspace sends us the doorbell object and the relative doobell
>>>> index in the object to be used for the usermode queue, but the FW
>>>> expects the absolute doorbell index on the PCI BAR in the MQD. This
>>>> patch adds a function to convert this relative doorbell index to
>>>> absolute doorbell index.
>>>>
>>>> This patch is dependent on the doorbell manager series:
>>>> Link: https://patchwork.freedesktop.org/series/115802/
>>>>
>>>> V5: Fix the db object reference leak (Christian)
>>>>
>>>> Cc: Alex Deucher <alexander.deucher@amd.com>
>>>> Cc: Christian Koenig <christian.koenig@amd.com>
>>>> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
>>>> ---
>>>> drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 34
>>>> +++++++++++++++++++
>>>> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 1 +
>>>> 2 files changed, 35 insertions(+)
>>>>
>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>> index bb774144c372..61064266c4f8 100644
>>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>> @@ -32,6 +32,31 @@ amdgpu_userqueue_find(struct amdgpu_userq_mgr
>>>> *uq_mgr, int qid)
>>>> return idr_find(&uq_mgr->userq_idr, qid);
>>>> }
>>>> +static uint64_t
>>>> +amdgpu_userqueue_get_doorbell_index(struct amdgpu_userq_mgr *uq_mgr,
>>>> + struct amdgpu_usermode_queue *queue,
>>>> + struct drm_file *filp,
>>>> + uint32_t doorbell_offset)
>>>> +{
>>>> + struct drm_gem_object *gobj;
>>>> + struct amdgpu_bo *db_bo;
>>>> + uint64_t index;
>>>> +
>>>> + gobj = drm_gem_object_lookup(filp, queue->doorbell_handle);
>>>> + if (gobj == NULL) {
>>>> + DRM_ERROR("Can't find GEM object for doorbell\n");
>>>> + return -EINVAL;
>>>> + }
>>>> +
>>>> + db_bo = amdgpu_bo_ref(gem_to_amdgpu_bo(gobj));
>>>> + drm_gem_object_put(gobj);
>>>> +
>>>> + index = amdgpu_doorbell_index_on_bar(uq_mgr->adev, db_bo,
>>>> doorbell_offset);
>>>
>>> This can only be done with the doorbell BO locked and as soon as you
>>> unlock it the value becomes invalid unless you pin the BO.
>>>
>> Which means I need to use create_bo_kernel() for doorbell BO's or
>> specifically pin it while creating it ?
>
> For now I think you need to pin it when amdgpu_userqueue_create() is
> called and unpin it when the userqueue is destroyed again.
>
> It's probably a good idea to not use amdgpu_bo_create_kernel() for the
> MQD and context BO either, but rather explicitly pin it during queue
> create as well.
Noted, will do that.
- Shashank
>
> Christian.
>
>>
>> - Shashank
>>
>>> Regards,
>>> Christian.
>>>
>>>> + amdgpu_bo_unref(&db_bo);
>>>> + DRM_DEBUG_DRIVER("[Usermode queues] doorbell index=%lld\n",
>>>> index);
>>>> + return index;
>>>> +}
>>>> +
>>>> static int
>>>> amdgpu_userqueue_destroy(struct drm_file *filp, int queue_id)
>>>> {
>>>> @@ -64,6 +89,7 @@ amdgpu_userqueue_create(struct drm_file *filp,
>>>> union drm_amdgpu_userq *args)
>>>> struct amdgpu_userq_mgr *uq_mgr = &fpriv->userq_mgr;
>>>> const struct amdgpu_userq_funcs *uq_funcs;
>>>> struct amdgpu_usermode_queue *queue;
>>>> + uint64_t index;
>>>> int qid, r = 0;
>>>> mutex_lock(&uq_mgr->userq_mutex);
>>>> @@ -87,6 +113,14 @@ amdgpu_userqueue_create(struct drm_file *filp,
>>>> union drm_amdgpu_userq *args)
>>>> queue->flags = args->in.flags;
>>>> queue->vm = &fpriv->vm;
>>>> + /* Convert relative doorbell offset into absolute doorbell
>>>> index */
>>>> + index = amdgpu_userqueue_get_doorbell_index(uq_mgr, queue,
>>>> filp, args->in.doorbell_offset);
>>>> + if (index == (uint64_t)-EINVAL) {
>>>> + DRM_ERROR("Failed to get doorbell for queue\n");
>>>> + goto unlock;
>>>> + }
>>>> + queue->doorbell_index = index;
>>>> +
>>>> r = uq_funcs->mqd_create(uq_mgr, &args->in, queue);
>>>> if (r) {
>>>> DRM_ERROR("Failed to create Queue\n");
>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>> b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>> index afaeecb9940a..8edb020683a1 100644
>>>> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>> @@ -6719,6 +6719,7 @@ static int gfx_v11_0_userq_mqd_create(struct
>>>> amdgpu_userq_mgr *uq_mgr,
>>>> userq_props.queue_size = mqd_user.queue_size;
>>>> userq_props.hqd_base_gpu_addr = mqd_user.queue_va;
>>>> userq_props.mqd_gpu_addr = queue->mqd.gpu_addr;
>>>> + userq_props.doorbell_index = queue->doorbell_index;
>>>> userq_props.use_doorbell = true;
>>>> r = mqd_gfx_generic->init_mqd(adev, (void
>>>> *)queue->mqd.cpu_ptr, &userq_props);
>>>
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 04/10] drm/amdgpu: create GFX-gen11 usermode queue
2023-07-07 8:37 ` Christian König
@ 2023-07-07 10:02 ` Shashank Sharma
2023-07-07 12:28 ` Christian König
0 siblings, 1 reply; 50+ messages in thread
From: Shashank Sharma @ 2023-07-07 10:02 UTC (permalink / raw)
To: Christian König, amd-gfx; +Cc: Alex Deucher, arvind.yadav
On 07/07/2023 10:37, Christian König wrote:
> Am 07.07.23 um 09:46 schrieb Shashank Sharma:
>>
>> On 07/07/2023 09:24, Christian König wrote:
>>>
>>>
>>> Am 06.07.23 um 14:35 schrieb Shashank Sharma:
>>>> A Memory queue descriptor (MQD) of a userqueue defines it in
>>>> the hw's context. As MQD format can vary between different
>>>> graphics IPs, we need gfx GEN specific handlers to create MQDs.
>>>>
>>>> This patch:
>>>> - Introduces MQD handler functions for the usermode queues.
>>>> - Adds new functions to create and destroy userqueue MQD for
>>>> GFX-GEN-11 IP
>>>>
>>>> V1: Worked on review comments from Alex:
>>>> - Make MQD functions GEN and IP specific
>>>>
>>>> V2: Worked on review comments from Alex:
>>>> - Reuse the existing adev->mqd[ip] for MQD creation
>>>> - Formatting and arrangement of code
>>>>
>>>> V3:
>>>> - Integration with doorbell manager
>>>>
>>>> V4: Review comments addressed:
>>>> - Do not create a new file for userq, reuse gfx_v11_0.c (Alex)
>>>> - Align name of structure members (Luben)
>>>> - Don't break up the Cc tag list and the Sob tag list in commit
>>>> message (Luben)
>>>> V5:
>>>> - No need to reserve the bo for MQD (Christian).
>>>> - Some more changes to support IP specific MQD creation.
>>>>
>>>> Cc: Alex Deucher <alexander.deucher@amd.com>
>>>> Cc: Christian Koenig <christian.koenig@amd.com>
>>>> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
>>>> Signed-off-by: Arvind Yadav <arvind.yadav@amd.com>
>>>> ---
>>>> drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 16 ++++
>>>> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 73
>>>> +++++++++++++++++++
>>>> .../gpu/drm/amd/include/amdgpu_userqueue.h | 7 ++
>>>> 3 files changed, 96 insertions(+)
>>>>
>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>> index e37b5da5a0d0..bb774144c372 100644
>>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>> @@ -134,12 +134,28 @@ int amdgpu_userq_ioctl(struct drm_device
>>>> *dev, void *data,
>>>> return r;
>>>> }
>>>> +extern const struct amdgpu_userq_funcs userq_gfx_v11_funcs;
>>>> +
>>>> +static void
>>>> +amdgpu_userqueue_setup_gfx(struct amdgpu_userq_mgr *uq_mgr)
>>>> +{
>>>> + int maj;
>>>> + struct amdgpu_device *adev = uq_mgr->adev;
>>>> + uint32_t version = adev->ip_versions[GC_HWIP][0];
>>>> +
>>>> + /* We support usermode queue only for GFX V11 as of now */
>>>> + maj = IP_VERSION_MAJ(version);
>>>> + if (maj == 11)
>>>> + uq_mgr->userq_funcs[AMDGPU_HW_IP_GFX] = &userq_gfx_v11_funcs;
>>>> +}
>>>> +
>>>> int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr,
>>>> struct amdgpu_device *adev)
>>>> {
>>>> mutex_init(&userq_mgr->userq_mutex);
>>>> idr_init_base(&userq_mgr->userq_idr, 1);
>>>> userq_mgr->adev = adev;
>>>> + amdgpu_userqueue_setup_gfx(userq_mgr);
>>>> return 0;
>>>> }
>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>> b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>> index c4940b6ea1c4..e76e1b86b434 100644
>>>> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>> @@ -30,6 +30,7 @@
>>>> #include "amdgpu_psp.h"
>>>> #include "amdgpu_smu.h"
>>>> #include "amdgpu_atomfirmware.h"
>>>> +#include "amdgpu_userqueue.h"
>>>> #include "imu_v11_0.h"
>>>> #include "soc21.h"
>>>> #include "nvd.h"
>>>> @@ -6486,3 +6487,75 @@ const struct amdgpu_ip_block_version
>>>> gfx_v11_0_ip_block =
>>>> .rev = 0,
>>>> .funcs = &gfx_v11_0_ip_funcs,
>>>> };
>>>> +
>>>> +static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr
>>>> *uq_mgr,
>>>> + struct drm_amdgpu_userq_in *args_in,
>>>> + struct amdgpu_usermode_queue *queue)
>>>> +{
>>>> + struct amdgpu_device *adev = uq_mgr->adev;
>>>> + struct amdgpu_mqd *mqd_gfx_generic =
>>>> &adev->mqds[AMDGPU_HW_IP_GFX];
>>>> + struct drm_amdgpu_userq_mqd_gfx_v11_0 mqd_user;
>>>> + struct amdgpu_mqd_prop userq_props;
>>>> + int r;
>>>> +
>>>> + /* Incoming MQD parameters from userspace to be saved here */
>>>> + memset(&mqd_user, 0, sizeof(mqd_user));
>>>> +
>>>> + /* Structure to initialize MQD for userqueue using generic MQD
>>>> init function */
>>>> + memset(&userq_props, 0, sizeof(userq_props));
>>>> +
>>>> + if (args_in->mqd_size != sizeof(struct
>>>> drm_amdgpu_userq_mqd_gfx_v11_0)) {
>>>> + DRM_ERROR("MQD size mismatch\n");
>>>> + return -EINVAL;
>>>> + }
>>>> +
>>>> + if (copy_from_user(&mqd_user, u64_to_user_ptr(args_in->mqd),
>>>> args_in->mqd_size)) {
>>>> + DRM_ERROR("Failed to get user MQD\n");
>>>> + return -EFAULT;
>>>> + }
>>>
>>> Sorry, I've just seen that now. Please don't have a copy_from_user()
>>> in the backend!
>>>
>>> This is pure front end stuff which we shouldn't do in hw generation
>>> specific code.
>>>
>> This is a bit difficult to achieve, as you know:
>>
>> - the whole reason we moved to ptr/size based approach from
>> fix-mqd-structure approach is so that we can support multiple MQD
>> structures using the same UAPI.
>>
>> - which means that in file amdgpu_userqueue.c layer (say front-end) I
>> do not know what is the right size of MQD, its independent of IP.
>>
>> - the correct size of MQD can only be known in IP specific functions
>> which are in gfx_v11.c (back end).
>>
>> - I may be able to achieve it by adding a new fptr get_mqd_size()
>> which can return the right MQD size for me from backend IP function,
>> and then I can move this copy from user to front-end. Does it sound
>> like a good idea to you ?
>
> Just use memdup_user() in the frontend. Allocating structures which
> are copied from userspace on the stack is usually a bad idea as well.
>
> Then pass in the kernel ptr and size as argument here and validate if
> what userspace gave us is correct.
>
This can still allow the user to pass invalid size (0 or too big), how
to prevent that ? I can still add a check for 0 size, but how about a
very big but invalid size for MQD ?
- Shashank
> Regards,
> Christian.
>
>>
>> - Shashank
>>
>>> Regards,
>>> Christian.
>>>
>>>> +
>>>> + /* Create BO for actual Userqueue MQD now */
>>>> + r = amdgpu_bo_create_kernel(adev, mqd_gfx_generic->mqd_size,
>>>> PAGE_SIZE,
>>>> + AMDGPU_GEM_DOMAIN_GTT,
>>>> + &queue->mqd.obj,
>>>> + &queue->mqd.gpu_addr,
>>>> + &queue->mqd.cpu_ptr);
>>>> + if (r) {
>>>> + DRM_ERROR("Failed to allocate BO for userqueue (%d)", r);
>>>> + return -ENOMEM;
>>>> + }
>>>> + memset(queue->mqd.cpu_ptr, 0, mqd_gfx_generic->mqd_size);
>>>> +
>>>> + /* Initialize the MQD BO with user given values */
>>>> + userq_props.wptr_gpu_addr = mqd_user.wptr_va;
>>>> + userq_props.rptr_gpu_addr = mqd_user.rptr_va;
>>>> + userq_props.queue_size = mqd_user.queue_size;
>>>> + userq_props.hqd_base_gpu_addr = mqd_user.queue_va;
>>>> + userq_props.mqd_gpu_addr = queue->mqd.gpu_addr;
>>>> + userq_props.use_doorbell = true;
>>>> +
>>>> + r = mqd_gfx_generic->init_mqd(adev, (void
>>>> *)queue->mqd.cpu_ptr, &userq_props);
>>>> + if (r) {
>>>> + DRM_ERROR("Failed to initialize MQD for userqueue\n");
>>>> + goto free_mqd;
>>>> + }
>>>> +
>>>> + return 0;
>>>> +
>>>> +free_mqd:
>>>> + amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr,
>>>> &queue->mqd.cpu_ptr);
>>>> + return r;
>>>> +}
>>>> +
>>>> +static void
>>>> +gfx_v11_0_userq_mqd_destroy(struct amdgpu_userq_mgr *uq_mgr,
>>>> struct amdgpu_usermode_queue *queue)
>>>> +{
>>>> + struct amdgpu_userq_obj *mqd = &queue->mqd;
>>>> +
>>>> + amdgpu_bo_free_kernel(&mqd->obj, &mqd->gpu_addr, &mqd->cpu_ptr);
>>>> +}
>>>> +
>>>> +const struct amdgpu_userq_funcs userq_gfx_v11_funcs = {
>>>> + .mqd_create = gfx_v11_0_userq_mqd_create,
>>>> + .mqd_destroy = gfx_v11_0_userq_mqd_destroy,
>>>> +};
>>>> diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>> b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>> index 55ed6512a565..240f92796f00 100644
>>>> --- a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>> +++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>> @@ -29,6 +29,12 @@
>>>> struct amdgpu_mqd_prop;
>>>> +struct amdgpu_userq_obj {
>>>> + void *cpu_ptr;
>>>> + uint64_t gpu_addr;
>>>> + struct amdgpu_bo *obj;
>>>> +};
>>>> +
>>>> struct amdgpu_usermode_queue {
>>>> int queue_type;
>>>> uint64_t doorbell_handle;
>>>> @@ -37,6 +43,7 @@ struct amdgpu_usermode_queue {
>>>> struct amdgpu_mqd_prop *userq_prop;
>>>> struct amdgpu_userq_mgr *userq_mgr;
>>>> struct amdgpu_vm *vm;
>>>> + struct amdgpu_userq_obj mqd;
>>>> };
>>>> struct amdgpu_userq_funcs {
>>>
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 04/10] drm/amdgpu: create GFX-gen11 usermode queue
2023-07-07 10:02 ` Shashank Sharma
@ 2023-07-07 12:28 ` Christian König
2023-07-07 12:46 ` Shashank Sharma
0 siblings, 1 reply; 50+ messages in thread
From: Christian König @ 2023-07-07 12:28 UTC (permalink / raw)
To: Shashank Sharma, amd-gfx; +Cc: Alex Deucher, arvind.yadav
Am 07.07.23 um 12:02 schrieb Shashank Sharma:
>
> On 07/07/2023 10:37, Christian König wrote:
>> Am 07.07.23 um 09:46 schrieb Shashank Sharma:
>>>
>>> On 07/07/2023 09:24, Christian König wrote:
>>>>
>>>>
>>>> Am 06.07.23 um 14:35 schrieb Shashank Sharma:
>>>>> A Memory queue descriptor (MQD) of a userqueue defines it in
>>>>> the hw's context. As MQD format can vary between different
>>>>> graphics IPs, we need gfx GEN specific handlers to create MQDs.
>>>>>
>>>>> This patch:
>>>>> - Introduces MQD handler functions for the usermode queues.
>>>>> - Adds new functions to create and destroy userqueue MQD for
>>>>> GFX-GEN-11 IP
>>>>>
>>>>> V1: Worked on review comments from Alex:
>>>>> - Make MQD functions GEN and IP specific
>>>>>
>>>>> V2: Worked on review comments from Alex:
>>>>> - Reuse the existing adev->mqd[ip] for MQD creation
>>>>> - Formatting and arrangement of code
>>>>>
>>>>> V3:
>>>>> - Integration with doorbell manager
>>>>>
>>>>> V4: Review comments addressed:
>>>>> - Do not create a new file for userq, reuse gfx_v11_0.c (Alex)
>>>>> - Align name of structure members (Luben)
>>>>> - Don't break up the Cc tag list and the Sob tag list in commit
>>>>> message (Luben)
>>>>> V5:
>>>>> - No need to reserve the bo for MQD (Christian).
>>>>> - Some more changes to support IP specific MQD creation.
>>>>>
>>>>> Cc: Alex Deucher <alexander.deucher@amd.com>
>>>>> Cc: Christian Koenig <christian.koenig@amd.com>
>>>>> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
>>>>> Signed-off-by: Arvind Yadav <arvind.yadav@amd.com>
>>>>> ---
>>>>> drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 16 ++++
>>>>> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 73
>>>>> +++++++++++++++++++
>>>>> .../gpu/drm/amd/include/amdgpu_userqueue.h | 7 ++
>>>>> 3 files changed, 96 insertions(+)
>>>>>
>>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>>> index e37b5da5a0d0..bb774144c372 100644
>>>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>>> @@ -134,12 +134,28 @@ int amdgpu_userq_ioctl(struct drm_device
>>>>> *dev, void *data,
>>>>> return r;
>>>>> }
>>>>> +extern const struct amdgpu_userq_funcs userq_gfx_v11_funcs;
>>>>> +
>>>>> +static void
>>>>> +amdgpu_userqueue_setup_gfx(struct amdgpu_userq_mgr *uq_mgr)
>>>>> +{
>>>>> + int maj;
>>>>> + struct amdgpu_device *adev = uq_mgr->adev;
>>>>> + uint32_t version = adev->ip_versions[GC_HWIP][0];
>>>>> +
>>>>> + /* We support usermode queue only for GFX V11 as of now */
>>>>> + maj = IP_VERSION_MAJ(version);
>>>>> + if (maj == 11)
>>>>> + uq_mgr->userq_funcs[AMDGPU_HW_IP_GFX] =
>>>>> &userq_gfx_v11_funcs;
>>>>> +}
>>>>> +
>>>>> int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr,
>>>>> struct amdgpu_device *adev)
>>>>> {
>>>>> mutex_init(&userq_mgr->userq_mutex);
>>>>> idr_init_base(&userq_mgr->userq_idr, 1);
>>>>> userq_mgr->adev = adev;
>>>>> + amdgpu_userqueue_setup_gfx(userq_mgr);
>>>>> return 0;
>>>>> }
>>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>>> b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>>> index c4940b6ea1c4..e76e1b86b434 100644
>>>>> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>>> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>>> @@ -30,6 +30,7 @@
>>>>> #include "amdgpu_psp.h"
>>>>> #include "amdgpu_smu.h"
>>>>> #include "amdgpu_atomfirmware.h"
>>>>> +#include "amdgpu_userqueue.h"
>>>>> #include "imu_v11_0.h"
>>>>> #include "soc21.h"
>>>>> #include "nvd.h"
>>>>> @@ -6486,3 +6487,75 @@ const struct amdgpu_ip_block_version
>>>>> gfx_v11_0_ip_block =
>>>>> .rev = 0,
>>>>> .funcs = &gfx_v11_0_ip_funcs,
>>>>> };
>>>>> +
>>>>> +static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr
>>>>> *uq_mgr,
>>>>> + struct drm_amdgpu_userq_in *args_in,
>>>>> + struct amdgpu_usermode_queue *queue)
>>>>> +{
>>>>> + struct amdgpu_device *adev = uq_mgr->adev;
>>>>> + struct amdgpu_mqd *mqd_gfx_generic =
>>>>> &adev->mqds[AMDGPU_HW_IP_GFX];
>>>>> + struct drm_amdgpu_userq_mqd_gfx_v11_0 mqd_user;
>>>>> + struct amdgpu_mqd_prop userq_props;
>>>>> + int r;
>>>>> +
>>>>> + /* Incoming MQD parameters from userspace to be saved here */
>>>>> + memset(&mqd_user, 0, sizeof(mqd_user));
>>>>> +
>>>>> + /* Structure to initialize MQD for userqueue using generic
>>>>> MQD init function */
>>>>> + memset(&userq_props, 0, sizeof(userq_props));
>>>>> +
>>>>> + if (args_in->mqd_size != sizeof(struct
>>>>> drm_amdgpu_userq_mqd_gfx_v11_0)) {
>>>>> + DRM_ERROR("MQD size mismatch\n");
>>>>> + return -EINVAL;
>>>>> + }
>>>>> +
>>>>> + if (copy_from_user(&mqd_user, u64_to_user_ptr(args_in->mqd),
>>>>> args_in->mqd_size)) {
>>>>> + DRM_ERROR("Failed to get user MQD\n");
>>>>> + return -EFAULT;
>>>>> + }
>>>>
>>>> Sorry, I've just seen that now. Please don't have a
>>>> copy_from_user() in the backend!
>>>>
>>>> This is pure front end stuff which we shouldn't do in hw generation
>>>> specific code.
>>>>
>>> This is a bit difficult to achieve, as you know:
>>>
>>> - the whole reason we moved to ptr/size based approach from
>>> fix-mqd-structure approach is so that we can support multiple MQD
>>> structures using the same UAPI.
>>>
>>> - which means that in file amdgpu_userqueue.c layer (say front-end)
>>> I do not know what is the right size of MQD, its independent of IP.
>>>
>>> - the correct size of MQD can only be known in IP specific functions
>>> which are in gfx_v11.c (back end).
>>>
>>> - I may be able to achieve it by adding a new fptr get_mqd_size()
>>> which can return the right MQD size for me from backend IP function,
>>> and then I can move this copy from user to front-end. Does it sound
>>> like a good idea to you ?
>>
>> Just use memdup_user() in the frontend. Allocating structures which
>> are copied from userspace on the stack is usually a bad idea as well.
>>
>> Then pass in the kernel ptr and size as argument here and validate if
>> what userspace gave us is correct.
>>
> This can still allow the user to pass invalid size (0 or too big), how
> to prevent that ? I can still add a check for 0 size, but how about a
> very big but invalid size for MQD ?
memdup_user() already takes care of that (has a maximum of 2MiB IIRC)
and the hw specific function should still validate the size to filter
out 0 and other invalid values.
Christian.
>
> - Shashank
>
>> Regards,
>> Christian.
>>
>>>
>>> - Shashank
>>>
>>>> Regards,
>>>> Christian.
>>>>
>>>>> +
>>>>> + /* Create BO for actual Userqueue MQD now */
>>>>> + r = amdgpu_bo_create_kernel(adev, mqd_gfx_generic->mqd_size,
>>>>> PAGE_SIZE,
>>>>> + AMDGPU_GEM_DOMAIN_GTT,
>>>>> + &queue->mqd.obj,
>>>>> + &queue->mqd.gpu_addr,
>>>>> + &queue->mqd.cpu_ptr);
>>>>> + if (r) {
>>>>> + DRM_ERROR("Failed to allocate BO for userqueue (%d)", r);
>>>>> + return -ENOMEM;
>>>>> + }
>>>>> + memset(queue->mqd.cpu_ptr, 0, mqd_gfx_generic->mqd_size);
>>>>> +
>>>>> + /* Initialize the MQD BO with user given values */
>>>>> + userq_props.wptr_gpu_addr = mqd_user.wptr_va;
>>>>> + userq_props.rptr_gpu_addr = mqd_user.rptr_va;
>>>>> + userq_props.queue_size = mqd_user.queue_size;
>>>>> + userq_props.hqd_base_gpu_addr = mqd_user.queue_va;
>>>>> + userq_props.mqd_gpu_addr = queue->mqd.gpu_addr;
>>>>> + userq_props.use_doorbell = true;
>>>>> +
>>>>> + r = mqd_gfx_generic->init_mqd(adev, (void
>>>>> *)queue->mqd.cpu_ptr, &userq_props);
>>>>> + if (r) {
>>>>> + DRM_ERROR("Failed to initialize MQD for userqueue\n");
>>>>> + goto free_mqd;
>>>>> + }
>>>>> +
>>>>> + return 0;
>>>>> +
>>>>> +free_mqd:
>>>>> + amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr,
>>>>> &queue->mqd.cpu_ptr);
>>>>> + return r;
>>>>> +}
>>>>> +
>>>>> +static void
>>>>> +gfx_v11_0_userq_mqd_destroy(struct amdgpu_userq_mgr *uq_mgr,
>>>>> struct amdgpu_usermode_queue *queue)
>>>>> +{
>>>>> + struct amdgpu_userq_obj *mqd = &queue->mqd;
>>>>> +
>>>>> + amdgpu_bo_free_kernel(&mqd->obj, &mqd->gpu_addr, &mqd->cpu_ptr);
>>>>> +}
>>>>> +
>>>>> +const struct amdgpu_userq_funcs userq_gfx_v11_funcs = {
>>>>> + .mqd_create = gfx_v11_0_userq_mqd_create,
>>>>> + .mqd_destroy = gfx_v11_0_userq_mqd_destroy,
>>>>> +};
>>>>> diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>>> b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>>> index 55ed6512a565..240f92796f00 100644
>>>>> --- a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>>> +++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>>> @@ -29,6 +29,12 @@
>>>>> struct amdgpu_mqd_prop;
>>>>> +struct amdgpu_userq_obj {
>>>>> + void *cpu_ptr;
>>>>> + uint64_t gpu_addr;
>>>>> + struct amdgpu_bo *obj;
>>>>> +};
>>>>> +
>>>>> struct amdgpu_usermode_queue {
>>>>> int queue_type;
>>>>> uint64_t doorbell_handle;
>>>>> @@ -37,6 +43,7 @@ struct amdgpu_usermode_queue {
>>>>> struct amdgpu_mqd_prop *userq_prop;
>>>>> struct amdgpu_userq_mgr *userq_mgr;
>>>>> struct amdgpu_vm *vm;
>>>>> + struct amdgpu_userq_obj mqd;
>>>>> };
>>>>> struct amdgpu_userq_funcs {
>>>>
>>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 04/10] drm/amdgpu: create GFX-gen11 usermode queue
2023-07-07 12:28 ` Christian König
@ 2023-07-07 12:46 ` Shashank Sharma
0 siblings, 0 replies; 50+ messages in thread
From: Shashank Sharma @ 2023-07-07 12:46 UTC (permalink / raw)
To: Christian König, amd-gfx; +Cc: Alex Deucher, arvind.yadav
On 07/07/2023 14:28, Christian König wrote:
>
>
> Am 07.07.23 um 12:02 schrieb Shashank Sharma:
>>
>> On 07/07/2023 10:37, Christian König wrote:
>>> Am 07.07.23 um 09:46 schrieb Shashank Sharma:
>>>>
>>>> On 07/07/2023 09:24, Christian König wrote:
>>>>>
>>>>>
>>>>> Am 06.07.23 um 14:35 schrieb Shashank Sharma:
>>>>>> A Memory queue descriptor (MQD) of a userqueue defines it in
>>>>>> the hw's context. As MQD format can vary between different
>>>>>> graphics IPs, we need gfx GEN specific handlers to create MQDs.
>>>>>>
>>>>>> This patch:
>>>>>> - Introduces MQD handler functions for the usermode queues.
>>>>>> - Adds new functions to create and destroy userqueue MQD for
>>>>>> GFX-GEN-11 IP
>>>>>>
>>>>>> V1: Worked on review comments from Alex:
>>>>>> - Make MQD functions GEN and IP specific
>>>>>>
>>>>>> V2: Worked on review comments from Alex:
>>>>>> - Reuse the existing adev->mqd[ip] for MQD creation
>>>>>> - Formatting and arrangement of code
>>>>>>
>>>>>> V3:
>>>>>> - Integration with doorbell manager
>>>>>>
>>>>>> V4: Review comments addressed:
>>>>>> - Do not create a new file for userq, reuse gfx_v11_0.c (Alex)
>>>>>> - Align name of structure members (Luben)
>>>>>> - Don't break up the Cc tag list and the Sob tag list in commit
>>>>>> message (Luben)
>>>>>> V5:
>>>>>> - No need to reserve the bo for MQD (Christian).
>>>>>> - Some more changes to support IP specific MQD creation.
>>>>>>
>>>>>> Cc: Alex Deucher <alexander.deucher@amd.com>
>>>>>> Cc: Christian Koenig <christian.koenig@amd.com>
>>>>>> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
>>>>>> Signed-off-by: Arvind Yadav <arvind.yadav@amd.com>
>>>>>> ---
>>>>>> drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 16 ++++
>>>>>> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 73
>>>>>> +++++++++++++++++++
>>>>>> .../gpu/drm/amd/include/amdgpu_userqueue.h | 7 ++
>>>>>> 3 files changed, 96 insertions(+)
>>>>>>
>>>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>>>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>>>> index e37b5da5a0d0..bb774144c372 100644
>>>>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>>>> @@ -134,12 +134,28 @@ int amdgpu_userq_ioctl(struct drm_device
>>>>>> *dev, void *data,
>>>>>> return r;
>>>>>> }
>>>>>> +extern const struct amdgpu_userq_funcs userq_gfx_v11_funcs;
>>>>>> +
>>>>>> +static void
>>>>>> +amdgpu_userqueue_setup_gfx(struct amdgpu_userq_mgr *uq_mgr)
>>>>>> +{
>>>>>> + int maj;
>>>>>> + struct amdgpu_device *adev = uq_mgr->adev;
>>>>>> + uint32_t version = adev->ip_versions[GC_HWIP][0];
>>>>>> +
>>>>>> + /* We support usermode queue only for GFX V11 as of now */
>>>>>> + maj = IP_VERSION_MAJ(version);
>>>>>> + if (maj == 11)
>>>>>> + uq_mgr->userq_funcs[AMDGPU_HW_IP_GFX] =
>>>>>> &userq_gfx_v11_funcs;
>>>>>> +}
>>>>>> +
>>>>>> int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr,
>>>>>> struct amdgpu_device *adev)
>>>>>> {
>>>>>> mutex_init(&userq_mgr->userq_mutex);
>>>>>> idr_init_base(&userq_mgr->userq_idr, 1);
>>>>>> userq_mgr->adev = adev;
>>>>>> + amdgpu_userqueue_setup_gfx(userq_mgr);
>>>>>> return 0;
>>>>>> }
>>>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>>>> b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>>>> index c4940b6ea1c4..e76e1b86b434 100644
>>>>>> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>>>> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>>>> @@ -30,6 +30,7 @@
>>>>>> #include "amdgpu_psp.h"
>>>>>> #include "amdgpu_smu.h"
>>>>>> #include "amdgpu_atomfirmware.h"
>>>>>> +#include "amdgpu_userqueue.h"
>>>>>> #include "imu_v11_0.h"
>>>>>> #include "soc21.h"
>>>>>> #include "nvd.h"
>>>>>> @@ -6486,3 +6487,75 @@ const struct amdgpu_ip_block_version
>>>>>> gfx_v11_0_ip_block =
>>>>>> .rev = 0,
>>>>>> .funcs = &gfx_v11_0_ip_funcs,
>>>>>> };
>>>>>> +
>>>>>> +static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr
>>>>>> *uq_mgr,
>>>>>> + struct drm_amdgpu_userq_in *args_in,
>>>>>> + struct amdgpu_usermode_queue *queue)
>>>>>> +{
>>>>>> + struct amdgpu_device *adev = uq_mgr->adev;
>>>>>> + struct amdgpu_mqd *mqd_gfx_generic =
>>>>>> &adev->mqds[AMDGPU_HW_IP_GFX];
>>>>>> + struct drm_amdgpu_userq_mqd_gfx_v11_0 mqd_user;
>>>>>> + struct amdgpu_mqd_prop userq_props;
>>>>>> + int r;
>>>>>> +
>>>>>> + /* Incoming MQD parameters from userspace to be saved here */
>>>>>> + memset(&mqd_user, 0, sizeof(mqd_user));
>>>>>> +
>>>>>> + /* Structure to initialize MQD for userqueue using generic
>>>>>> MQD init function */
>>>>>> + memset(&userq_props, 0, sizeof(userq_props));
>>>>>> +
>>>>>> + if (args_in->mqd_size != sizeof(struct
>>>>>> drm_amdgpu_userq_mqd_gfx_v11_0)) {
>>>>>> + DRM_ERROR("MQD size mismatch\n");
>>>>>> + return -EINVAL;
>>>>>> + }
>>>>>> +
>>>>>> + if (copy_from_user(&mqd_user, u64_to_user_ptr(args_in->mqd),
>>>>>> args_in->mqd_size)) {
>>>>>> + DRM_ERROR("Failed to get user MQD\n");
>>>>>> + return -EFAULT;
>>>>>> + }
>>>>>
>>>>> Sorry, I've just seen that now. Please don't have a
>>>>> copy_from_user() in the backend!
>>>>>
>>>>> This is pure front end stuff which we shouldn't do in hw
>>>>> generation specific code.
>>>>>
>>>> This is a bit difficult to achieve, as you know:
>>>>
>>>> - the whole reason we moved to ptr/size based approach from
>>>> fix-mqd-structure approach is so that we can support multiple MQD
>>>> structures using the same UAPI.
>>>>
>>>> - which means that in file amdgpu_userqueue.c layer (say front-end)
>>>> I do not know what is the right size of MQD, its independent of IP.
>>>>
>>>> - the correct size of MQD can only be known in IP specific
>>>> functions which are in gfx_v11.c (back end).
>>>>
>>>> - I may be able to achieve it by adding a new fptr get_mqd_size()
>>>> which can return the right MQD size for me from backend IP
>>>> function, and then I can move this copy from user to front-end.
>>>> Does it sound like a good idea to you ?
>>>
>>> Just use memdup_user() in the frontend. Allocating structures which
>>> are copied from userspace on the stack is usually a bad idea as well.
>>>
>>> Then pass in the kernel ptr and size as argument here and validate
>>> if what userspace gave us is correct.
>>>
>> This can still allow the user to pass invalid size (0 or too big),
>> how to prevent that ? I can still add a check for 0 size, but how
>> about a very big but invalid size for MQD ?
>
> memdup_user() already takes care of that (has a maximum of 2MiB IIRC)
> and the hw specific function should still validate the size to filter
> out 0 and other invalid values.
Perfect, I will change it.
- Shashank
>
> Christian.
>
>>
>> - Shashank
>>
>>> Regards,
>>> Christian.
>>>
>>>>
>>>> - Shashank
>>>>
>>>>> Regards,
>>>>> Christian.
>>>>>
>>>>>> +
>>>>>> + /* Create BO for actual Userqueue MQD now */
>>>>>> + r = amdgpu_bo_create_kernel(adev, mqd_gfx_generic->mqd_size,
>>>>>> PAGE_SIZE,
>>>>>> + AMDGPU_GEM_DOMAIN_GTT,
>>>>>> + &queue->mqd.obj,
>>>>>> + &queue->mqd.gpu_addr,
>>>>>> + &queue->mqd.cpu_ptr);
>>>>>> + if (r) {
>>>>>> + DRM_ERROR("Failed to allocate BO for userqueue (%d)", r);
>>>>>> + return -ENOMEM;
>>>>>> + }
>>>>>> + memset(queue->mqd.cpu_ptr, 0, mqd_gfx_generic->mqd_size);
>>>>>> +
>>>>>> + /* Initialize the MQD BO with user given values */
>>>>>> + userq_props.wptr_gpu_addr = mqd_user.wptr_va;
>>>>>> + userq_props.rptr_gpu_addr = mqd_user.rptr_va;
>>>>>> + userq_props.queue_size = mqd_user.queue_size;
>>>>>> + userq_props.hqd_base_gpu_addr = mqd_user.queue_va;
>>>>>> + userq_props.mqd_gpu_addr = queue->mqd.gpu_addr;
>>>>>> + userq_props.use_doorbell = true;
>>>>>> +
>>>>>> + r = mqd_gfx_generic->init_mqd(adev, (void
>>>>>> *)queue->mqd.cpu_ptr, &userq_props);
>>>>>> + if (r) {
>>>>>> + DRM_ERROR("Failed to initialize MQD for userqueue\n");
>>>>>> + goto free_mqd;
>>>>>> + }
>>>>>> +
>>>>>> + return 0;
>>>>>> +
>>>>>> +free_mqd:
>>>>>> + amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr,
>>>>>> &queue->mqd.cpu_ptr);
>>>>>> + return r;
>>>>>> +}
>>>>>> +
>>>>>> +static void
>>>>>> +gfx_v11_0_userq_mqd_destroy(struct amdgpu_userq_mgr *uq_mgr,
>>>>>> struct amdgpu_usermode_queue *queue)
>>>>>> +{
>>>>>> + struct amdgpu_userq_obj *mqd = &queue->mqd;
>>>>>> +
>>>>>> + amdgpu_bo_free_kernel(&mqd->obj, &mqd->gpu_addr,
>>>>>> &mqd->cpu_ptr);
>>>>>> +}
>>>>>> +
>>>>>> +const struct amdgpu_userq_funcs userq_gfx_v11_funcs = {
>>>>>> + .mqd_create = gfx_v11_0_userq_mqd_create,
>>>>>> + .mqd_destroy = gfx_v11_0_userq_mqd_destroy,
>>>>>> +};
>>>>>> diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>>>> b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>>>> index 55ed6512a565..240f92796f00 100644
>>>>>> --- a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>>>> +++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>>>> @@ -29,6 +29,12 @@
>>>>>> struct amdgpu_mqd_prop;
>>>>>> +struct amdgpu_userq_obj {
>>>>>> + void *cpu_ptr;
>>>>>> + uint64_t gpu_addr;
>>>>>> + struct amdgpu_bo *obj;
>>>>>> +};
>>>>>> +
>>>>>> struct amdgpu_usermode_queue {
>>>>>> int queue_type;
>>>>>> uint64_t doorbell_handle;
>>>>>> @@ -37,6 +43,7 @@ struct amdgpu_usermode_queue {
>>>>>> struct amdgpu_mqd_prop *userq_prop;
>>>>>> struct amdgpu_userq_mgr *userq_mgr;
>>>>>> struct amdgpu_vm *vm;
>>>>>> + struct amdgpu_userq_obj mqd;
>>>>>> };
>>>>>> struct amdgpu_userq_funcs {
>>>>>
>>>
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 04/10] drm/amdgpu: create GFX-gen11 usermode queue
2023-07-06 13:39 ` Christian König
2023-07-06 13:43 ` Shashank Sharma
@ 2023-07-11 19:51 ` Felix Kuehling
2023-07-12 15:55 ` Shashank Sharma
1 sibling, 1 reply; 50+ messages in thread
From: Felix Kuehling @ 2023-07-11 19:51 UTC (permalink / raw)
To: Christian König, Shashank Sharma, amd-gfx; +Cc: Alex Deucher, arvind.yadav
On 2023-07-06 09:39, Christian König wrote:
> Am 06.07.23 um 15:37 schrieb Shashank Sharma:
>>
>> On 06/07/2023 15:22, Christian König wrote:
>>> Am 06.07.23 um 14:35 schrieb Shashank Sharma:
>>>> A Memory queue descriptor (MQD) of a userqueue defines it in
>>>> the hw's context. As MQD format can vary between different
>>>> graphics IPs, we need gfx GEN specific handlers to create MQDs.
>>>>
>>>> This patch:
>>>> - Introduces MQD handler functions for the usermode queues.
>>>> - Adds new functions to create and destroy userqueue MQD for
>>>> GFX-GEN-11 IP
>>>>
>>>> V1: Worked on review comments from Alex:
>>>> - Make MQD functions GEN and IP specific
>>>>
>>>> V2: Worked on review comments from Alex:
>>>> - Reuse the existing adev->mqd[ip] for MQD creation
>>>> - Formatting and arrangement of code
>>>>
>>>> V3:
>>>> - Integration with doorbell manager
>>>>
>>>> V4: Review comments addressed:
>>>> - Do not create a new file for userq, reuse gfx_v11_0.c (Alex)
>>>> - Align name of structure members (Luben)
>>>> - Don't break up the Cc tag list and the Sob tag list in commit
>>>> message (Luben)
>>>> V5:
>>>> - No need to reserve the bo for MQD (Christian).
>>>> - Some more changes to support IP specific MQD creation.
>>>>
>>>> Cc: Alex Deucher <alexander.deucher@amd.com>
>>>> Cc: Christian Koenig <christian.koenig@amd.com>
>>>> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
>>>> Signed-off-by: Arvind Yadav <arvind.yadav@amd.com>
>>>> ---
>>>> drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 16 ++++
>>>> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 73
>>>> +++++++++++++++++++
>>>> .../gpu/drm/amd/include/amdgpu_userqueue.h | 7 ++
>>>> 3 files changed, 96 insertions(+)
>>>>
>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>> index e37b5da5a0d0..bb774144c372 100644
>>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>> @@ -134,12 +134,28 @@ int amdgpu_userq_ioctl(struct drm_device
>>>> *dev, void *data,
>>>> return r;
>>>> }
>>>> +extern const struct amdgpu_userq_funcs userq_gfx_v11_funcs;
>>>> +
>>>> +static void
>>>> +amdgpu_userqueue_setup_gfx(struct amdgpu_userq_mgr *uq_mgr)
>>>> +{
>>>> + int maj;
>>>> + struct amdgpu_device *adev = uq_mgr->adev;
>>>> + uint32_t version = adev->ip_versions[GC_HWIP][0];
>>>> +
>>>> + /* We support usermode queue only for GFX V11 as of now */
>>>> + maj = IP_VERSION_MAJ(version);
>>>> + if (maj == 11)
>>>> + uq_mgr->userq_funcs[AMDGPU_HW_IP_GFX] = &userq_gfx_v11_funcs;
>>>> +}
>>>> +
>>>> int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr,
>>>> struct amdgpu_device *adev)
>>>> {
>>>> mutex_init(&userq_mgr->userq_mutex);
>>>> idr_init_base(&userq_mgr->userq_idr, 1);
>>>> userq_mgr->adev = adev;
>>>> + amdgpu_userqueue_setup_gfx(userq_mgr);
>>>> return 0;
>>>> }
>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>> b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>> index c4940b6ea1c4..e76e1b86b434 100644
>>>> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>> @@ -30,6 +30,7 @@
>>>> #include "amdgpu_psp.h"
>>>> #include "amdgpu_smu.h"
>>>> #include "amdgpu_atomfirmware.h"
>>>> +#include "amdgpu_userqueue.h"
>>>> #include "imu_v11_0.h"
>>>> #include "soc21.h"
>>>> #include "nvd.h"
>>>> @@ -6486,3 +6487,75 @@ const struct amdgpu_ip_block_version
>>>> gfx_v11_0_ip_block =
>>>> .rev = 0,
>>>> .funcs = &gfx_v11_0_ip_funcs,
>>>> };
>>>> +
>>>> +static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr
>>>> *uq_mgr,
>>>> + struct drm_amdgpu_userq_in *args_in,
>>>> + struct amdgpu_usermode_queue *queue)
>>>> +{
>>>> + struct amdgpu_device *adev = uq_mgr->adev;
>>>> + struct amdgpu_mqd *mqd_gfx_generic =
>>>> &adev->mqds[AMDGPU_HW_IP_GFX];
>>>> + struct drm_amdgpu_userq_mqd_gfx_v11_0 mqd_user;
>>>> + struct amdgpu_mqd_prop userq_props;
>>>> + int r;
>>>> +
>>>> + /* Incoming MQD parameters from userspace to be saved here */
>>>> + memset(&mqd_user, 0, sizeof(mqd_user));
>>>> +
>>>> + /* Structure to initialize MQD for userqueue using generic MQD
>>>> init function */
>>>> + memset(&userq_props, 0, sizeof(userq_props));
>>>> +
>>>> + if (args_in->mqd_size != sizeof(struct
>>>> drm_amdgpu_userq_mqd_gfx_v11_0)) {
>>>> + DRM_ERROR("MQD size mismatch\n");
>>>> + return -EINVAL;
>>>> + }
>>>> +
>>>> + if (copy_from_user(&mqd_user, u64_to_user_ptr(args_in->mqd),
>>>> args_in->mqd_size)) {
>>>> + DRM_ERROR("Failed to get user MQD\n");
>>>> + return -EFAULT;
>>>> + }
>>>> +
>>>> + /* Create BO for actual Userqueue MQD now */
>>>> + r = amdgpu_bo_create_kernel(adev, mqd_gfx_generic->mqd_size,
>>>> PAGE_SIZE,
>>>> + AMDGPU_GEM_DOMAIN_GTT,
>>>> + &queue->mqd.obj,
>>>> + &queue->mqd.gpu_addr,
>>>> + &queue->mqd.cpu_ptr);
>>>> + if (r) {
>>>> + DRM_ERROR("Failed to allocate BO for userqueue (%d)", r);
>>>> + return -ENOMEM;
>>>> + }
>>>
>>> Using amdgpu_bo_create_kernel() for the MQD is most likely not a
>>> good idea in the long term, but should work for now.
>>>
>> I was a bit curious about this, the scope of this MQD object is
>> kernel internal and used for queue mapping only, userspace doesn't
>> know much about it. Do you still think we should not create a kernel
>> object for it ?
>
>
> Well we should use a kernel BO. But amdgpu_bo_create_kernel() not only
> creates a kernel BO but also pins it! And that is problematic because
> it allows userspace to do a deny of service attach on the kernel module.
>
> What we need is an eviction fence, e.g. what KFD is already using.
> Then the BO is created similar to how VM page tables are created,
> maybe even using the same reservation object.
KFD doesn't currently use eviction fences on MQDs. Those are pinned. I
guess you could treat the MQDs more like we treat page tables. They are
allocated in kernel mode but protected with fences rather than pinning.
I'm not sure if MES needs to be able to access MQDs while queues are not
mapped. If that's the case, pinning can't be avoided.
Regards,
Felix
>
> But for a test this here is probably ok.
>
> Christian.
>
>>
>> - Shashank
>>
>>> Probably best to add a comment here that this needs to be improved.
>>>
>>> Apart from that looks good to me,
>>> Christian.
>>>
>>>> + memset(queue->mqd.cpu_ptr, 0, mqd_gfx_generic->mqd_size);
>>>> +
>>>> + /* Initialize the MQD BO with user given values */
>>>> + userq_props.wptr_gpu_addr = mqd_user.wptr_va;
>>>> + userq_props.rptr_gpu_addr = mqd_user.rptr_va;
>>>> + userq_props.queue_size = mqd_user.queue_size;
>>>> + userq_props.hqd_base_gpu_addr = mqd_user.queue_va;
>>>> + userq_props.mqd_gpu_addr = queue->mqd.gpu_addr;
>>>> + userq_props.use_doorbell = true;
>>>> +
>>>> + r = mqd_gfx_generic->init_mqd(adev, (void
>>>> *)queue->mqd.cpu_ptr, &userq_props);
>>>> + if (r) {
>>>> + DRM_ERROR("Failed to initialize MQD for userqueue\n");
>>>> + goto free_mqd;
>>>> + }
>>>> +
>>>> + return 0;
>>>> +
>>>> +free_mqd:
>>>> + amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr,
>>>> &queue->mqd.cpu_ptr);
>>>> + return r;
>>>> +}
>>>> +
>>>> +static void
>>>> +gfx_v11_0_userq_mqd_destroy(struct amdgpu_userq_mgr *uq_mgr,
>>>> struct amdgpu_usermode_queue *queue)
>>>> +{
>>>> + struct amdgpu_userq_obj *mqd = &queue->mqd;
>>>> +
>>>> + amdgpu_bo_free_kernel(&mqd->obj, &mqd->gpu_addr, &mqd->cpu_ptr);
>>>> +}
>>>> +
>>>> +const struct amdgpu_userq_funcs userq_gfx_v11_funcs = {
>>>> + .mqd_create = gfx_v11_0_userq_mqd_create,
>>>> + .mqd_destroy = gfx_v11_0_userq_mqd_destroy,
>>>> +};
>>>> diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>> b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>> index 55ed6512a565..240f92796f00 100644
>>>> --- a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>> +++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>> @@ -29,6 +29,12 @@
>>>> struct amdgpu_mqd_prop;
>>>> +struct amdgpu_userq_obj {
>>>> + void *cpu_ptr;
>>>> + uint64_t gpu_addr;
>>>> + struct amdgpu_bo *obj;
>>>> +};
>>>> +
>>>> struct amdgpu_usermode_queue {
>>>> int queue_type;
>>>> uint64_t doorbell_handle;
>>>> @@ -37,6 +43,7 @@ struct amdgpu_usermode_queue {
>>>> struct amdgpu_mqd_prop *userq_prop;
>>>> struct amdgpu_userq_mgr *userq_mgr;
>>>> struct amdgpu_vm *vm;
>>>> + struct amdgpu_userq_obj mqd;
>>>> };
>>>> struct amdgpu_userq_funcs {
>>>
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 04/10] drm/amdgpu: create GFX-gen11 usermode queue
2023-07-11 19:51 ` Felix Kuehling
@ 2023-07-12 15:55 ` Shashank Sharma
2023-07-12 16:01 ` Felix Kuehling
0 siblings, 1 reply; 50+ messages in thread
From: Shashank Sharma @ 2023-07-12 15:55 UTC (permalink / raw)
To: Felix Kuehling, Christian König, amd-gfx; +Cc: Alex Deucher, arvind.yadav
On 11/07/2023 21:51, Felix Kuehling wrote:
>
> On 2023-07-06 09:39, Christian König wrote:
>> Am 06.07.23 um 15:37 schrieb Shashank Sharma:
>>>
>>> On 06/07/2023 15:22, Christian König wrote:
>>>> Am 06.07.23 um 14:35 schrieb Shashank Sharma:
>>>>> A Memory queue descriptor (MQD) of a userqueue defines it in
>>>>> the hw's context. As MQD format can vary between different
>>>>> graphics IPs, we need gfx GEN specific handlers to create MQDs.
>>>>>
>>>>> This patch:
>>>>> - Introduces MQD handler functions for the usermode queues.
>>>>> - Adds new functions to create and destroy userqueue MQD for
>>>>> GFX-GEN-11 IP
>>>>>
>>>>> V1: Worked on review comments from Alex:
>>>>> - Make MQD functions GEN and IP specific
>>>>>
>>>>> V2: Worked on review comments from Alex:
>>>>> - Reuse the existing adev->mqd[ip] for MQD creation
>>>>> - Formatting and arrangement of code
>>>>>
>>>>> V3:
>>>>> - Integration with doorbell manager
>>>>>
>>>>> V4: Review comments addressed:
>>>>> - Do not create a new file for userq, reuse gfx_v11_0.c (Alex)
>>>>> - Align name of structure members (Luben)
>>>>> - Don't break up the Cc tag list and the Sob tag list in commit
>>>>> message (Luben)
>>>>> V5:
>>>>> - No need to reserve the bo for MQD (Christian).
>>>>> - Some more changes to support IP specific MQD creation.
>>>>>
>>>>> Cc: Alex Deucher <alexander.deucher@amd.com>
>>>>> Cc: Christian Koenig <christian.koenig@amd.com>
>>>>> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
>>>>> Signed-off-by: Arvind Yadav <arvind.yadav@amd.com>
>>>>> ---
>>>>> drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 16 ++++
>>>>> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 73
>>>>> +++++++++++++++++++
>>>>> .../gpu/drm/amd/include/amdgpu_userqueue.h | 7 ++
>>>>> 3 files changed, 96 insertions(+)
>>>>>
>>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>>> index e37b5da5a0d0..bb774144c372 100644
>>>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>>> @@ -134,12 +134,28 @@ int amdgpu_userq_ioctl(struct drm_device
>>>>> *dev, void *data,
>>>>> return r;
>>>>> }
>>>>> +extern const struct amdgpu_userq_funcs userq_gfx_v11_funcs;
>>>>> +
>>>>> +static void
>>>>> +amdgpu_userqueue_setup_gfx(struct amdgpu_userq_mgr *uq_mgr)
>>>>> +{
>>>>> + int maj;
>>>>> + struct amdgpu_device *adev = uq_mgr->adev;
>>>>> + uint32_t version = adev->ip_versions[GC_HWIP][0];
>>>>> +
>>>>> + /* We support usermode queue only for GFX V11 as of now */
>>>>> + maj = IP_VERSION_MAJ(version);
>>>>> + if (maj == 11)
>>>>> + uq_mgr->userq_funcs[AMDGPU_HW_IP_GFX] =
>>>>> &userq_gfx_v11_funcs;
>>>>> +}
>>>>> +
>>>>> int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr,
>>>>> struct amdgpu_device *adev)
>>>>> {
>>>>> mutex_init(&userq_mgr->userq_mutex);
>>>>> idr_init_base(&userq_mgr->userq_idr, 1);
>>>>> userq_mgr->adev = adev;
>>>>> + amdgpu_userqueue_setup_gfx(userq_mgr);
>>>>> return 0;
>>>>> }
>>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>>> b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>>> index c4940b6ea1c4..e76e1b86b434 100644
>>>>> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>>> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>>> @@ -30,6 +30,7 @@
>>>>> #include "amdgpu_psp.h"
>>>>> #include "amdgpu_smu.h"
>>>>> #include "amdgpu_atomfirmware.h"
>>>>> +#include "amdgpu_userqueue.h"
>>>>> #include "imu_v11_0.h"
>>>>> #include "soc21.h"
>>>>> #include "nvd.h"
>>>>> @@ -6486,3 +6487,75 @@ const struct amdgpu_ip_block_version
>>>>> gfx_v11_0_ip_block =
>>>>> .rev = 0,
>>>>> .funcs = &gfx_v11_0_ip_funcs,
>>>>> };
>>>>> +
>>>>> +static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr
>>>>> *uq_mgr,
>>>>> + struct drm_amdgpu_userq_in *args_in,
>>>>> + struct amdgpu_usermode_queue *queue)
>>>>> +{
>>>>> + struct amdgpu_device *adev = uq_mgr->adev;
>>>>> + struct amdgpu_mqd *mqd_gfx_generic =
>>>>> &adev->mqds[AMDGPU_HW_IP_GFX];
>>>>> + struct drm_amdgpu_userq_mqd_gfx_v11_0 mqd_user;
>>>>> + struct amdgpu_mqd_prop userq_props;
>>>>> + int r;
>>>>> +
>>>>> + /* Incoming MQD parameters from userspace to be saved here */
>>>>> + memset(&mqd_user, 0, sizeof(mqd_user));
>>>>> +
>>>>> + /* Structure to initialize MQD for userqueue using generic
>>>>> MQD init function */
>>>>> + memset(&userq_props, 0, sizeof(userq_props));
>>>>> +
>>>>> + if (args_in->mqd_size != sizeof(struct
>>>>> drm_amdgpu_userq_mqd_gfx_v11_0)) {
>>>>> + DRM_ERROR("MQD size mismatch\n");
>>>>> + return -EINVAL;
>>>>> + }
>>>>> +
>>>>> + if (copy_from_user(&mqd_user, u64_to_user_ptr(args_in->mqd),
>>>>> args_in->mqd_size)) {
>>>>> + DRM_ERROR("Failed to get user MQD\n");
>>>>> + return -EFAULT;
>>>>> + }
>>>>> +
>>>>> + /* Create BO for actual Userqueue MQD now */
>>>>> + r = amdgpu_bo_create_kernel(adev, mqd_gfx_generic->mqd_size,
>>>>> PAGE_SIZE,
>>>>> + AMDGPU_GEM_DOMAIN_GTT,
>>>>> + &queue->mqd.obj,
>>>>> + &queue->mqd.gpu_addr,
>>>>> + &queue->mqd.cpu_ptr);
>>>>> + if (r) {
>>>>> + DRM_ERROR("Failed to allocate BO for userqueue (%d)", r);
>>>>> + return -ENOMEM;
>>>>> + }
>>>>
>>>> Using amdgpu_bo_create_kernel() for the MQD is most likely not a
>>>> good idea in the long term, but should work for now.
>>>>
>>> I was a bit curious about this, the scope of this MQD object is
>>> kernel internal and used for queue mapping only, userspace doesn't
>>> know much about it. Do you still think we should not create a kernel
>>> object for it ?
>>
>>
>> Well we should use a kernel BO. But amdgpu_bo_create_kernel() not
>> only creates a kernel BO but also pins it! And that is problematic
>> because it allows userspace to do a deny of service attach on the
>> kernel module.
>>
>> What we need is an eviction fence, e.g. what KFD is already using.
>> Then the BO is created similar to how VM page tables are created,
>> maybe even using the same reservation object.
>
> KFD doesn't currently use eviction fences on MQDs. Those are pinned. I
> guess you could treat the MQDs more like we treat page tables. They
> are allocated in kernel mode but protected with fences rather than
> pinning.
>
> I'm not sure if MES needs to be able to access MQDs while queues are
> not mapped. If that's the case, pinning can't be avoided.
>
I was planning to do something like this keep userqueue objects from
eviction:
- Add a new mutex in queue struct (say userq_eviction_fence)
- lock this while mapping the queue, and unlock it while unmapping of
the queue
- add checks in amdgpu_vm_evictable() to add a
mutex_trylock(userq_eviction_fence)
Does it sound like what we want to do here or should I need something else ?
> Regards,
> Felix
>
>
>>
>> But for a test this here is probably ok.
>>
>> Christian.
>>
>>>
>>> - Shashank
>>>
>>>> Probably best to add a comment here that this needs to be improved.
>>>>
>>>> Apart from that looks good to me,
>>>> Christian.
>>>>
>>>>> + memset(queue->mqd.cpu_ptr, 0, mqd_gfx_generic->mqd_size);
>>>>> +
>>>>> + /* Initialize the MQD BO with user given values */
>>>>> + userq_props.wptr_gpu_addr = mqd_user.wptr_va;
>>>>> + userq_props.rptr_gpu_addr = mqd_user.rptr_va;
>>>>> + userq_props.queue_size = mqd_user.queue_size;
>>>>> + userq_props.hqd_base_gpu_addr = mqd_user.queue_va;
>>>>> + userq_props.mqd_gpu_addr = queue->mqd.gpu_addr;
>>>>> + userq_props.use_doorbell = true;
>>>>> +
>>>>> + r = mqd_gfx_generic->init_mqd(adev, (void
>>>>> *)queue->mqd.cpu_ptr, &userq_props);
>>>>> + if (r) {
>>>>> + DRM_ERROR("Failed to initialize MQD for userqueue\n");
>>>>> + goto free_mqd;
>>>>> + }
>>>>> +
>>>>> + return 0;
>>>>> +
>>>>> +free_mqd:
>>>>> + amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr,
>>>>> &queue->mqd.cpu_ptr);
>>>>> + return r;
>>>>> +}
>>>>> +
>>>>> +static void
>>>>> +gfx_v11_0_userq_mqd_destroy(struct amdgpu_userq_mgr *uq_mgr,
>>>>> struct amdgpu_usermode_queue *queue)
>>>>> +{
>>>>> + struct amdgpu_userq_obj *mqd = &queue->mqd;
>>>>> +
>>>>> + amdgpu_bo_free_kernel(&mqd->obj, &mqd->gpu_addr, &mqd->cpu_ptr);
>>>>> +}
>>>>> +
>>>>> +const struct amdgpu_userq_funcs userq_gfx_v11_funcs = {
>>>>> + .mqd_create = gfx_v11_0_userq_mqd_create,
>>>>> + .mqd_destroy = gfx_v11_0_userq_mqd_destroy,
>>>>> +};
>>>>> diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>>> b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>>> index 55ed6512a565..240f92796f00 100644
>>>>> --- a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>>> +++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>>> @@ -29,6 +29,12 @@
>>>>> struct amdgpu_mqd_prop;
>>>>> +struct amdgpu_userq_obj {
>>>>> + void *cpu_ptr;
>>>>> + uint64_t gpu_addr;
>>>>> + struct amdgpu_bo *obj;
>>>>> +};
>>>>> +
>>>>> struct amdgpu_usermode_queue {
>>>>> int queue_type;
>>>>> uint64_t doorbell_handle;
>>>>> @@ -37,6 +43,7 @@ struct amdgpu_usermode_queue {
>>>>> struct amdgpu_mqd_prop *userq_prop;
>>>>> struct amdgpu_userq_mgr *userq_mgr;
>>>>> struct amdgpu_vm *vm;
>>>>> + struct amdgpu_userq_obj mqd;
>>>>> };
>>>>> struct amdgpu_userq_funcs {
>>>>
>>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 04/10] drm/amdgpu: create GFX-gen11 usermode queue
2023-07-12 15:55 ` Shashank Sharma
@ 2023-07-12 16:01 ` Felix Kuehling
2023-07-12 16:07 ` Shashank Sharma
0 siblings, 1 reply; 50+ messages in thread
From: Felix Kuehling @ 2023-07-12 16:01 UTC (permalink / raw)
To: Shashank Sharma, Christian König, amd-gfx; +Cc: Alex Deucher, arvind.yadav
Am 2023-07-12 um 11:55 schrieb Shashank Sharma:
>
> On 11/07/2023 21:51, Felix Kuehling wrote:
>>
>> On 2023-07-06 09:39, Christian König wrote:
>>> Am 06.07.23 um 15:37 schrieb Shashank Sharma:
>>>>
>>>> On 06/07/2023 15:22, Christian König wrote:
>>>>> Am 06.07.23 um 14:35 schrieb Shashank Sharma:
>>>>>> A Memory queue descriptor (MQD) of a userqueue defines it in
>>>>>> the hw's context. As MQD format can vary between different
>>>>>> graphics IPs, we need gfx GEN specific handlers to create MQDs.
>>>>>>
>>>>>> This patch:
>>>>>> - Introduces MQD handler functions for the usermode queues.
>>>>>> - Adds new functions to create and destroy userqueue MQD for
>>>>>> GFX-GEN-11 IP
>>>>>>
>>>>>> V1: Worked on review comments from Alex:
>>>>>> - Make MQD functions GEN and IP specific
>>>>>>
>>>>>> V2: Worked on review comments from Alex:
>>>>>> - Reuse the existing adev->mqd[ip] for MQD creation
>>>>>> - Formatting and arrangement of code
>>>>>>
>>>>>> V3:
>>>>>> - Integration with doorbell manager
>>>>>>
>>>>>> V4: Review comments addressed:
>>>>>> - Do not create a new file for userq, reuse gfx_v11_0.c (Alex)
>>>>>> - Align name of structure members (Luben)
>>>>>> - Don't break up the Cc tag list and the Sob tag list in commit
>>>>>> message (Luben)
>>>>>> V5:
>>>>>> - No need to reserve the bo for MQD (Christian).
>>>>>> - Some more changes to support IP specific MQD creation.
>>>>>>
>>>>>> Cc: Alex Deucher <alexander.deucher@amd.com>
>>>>>> Cc: Christian Koenig <christian.koenig@amd.com>
>>>>>> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
>>>>>> Signed-off-by: Arvind Yadav <arvind.yadav@amd.com>
>>>>>> ---
>>>>>> drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 16 ++++
>>>>>> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 73
>>>>>> +++++++++++++++++++
>>>>>> .../gpu/drm/amd/include/amdgpu_userqueue.h | 7 ++
>>>>>> 3 files changed, 96 insertions(+)
>>>>>>
>>>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>>>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>>>> index e37b5da5a0d0..bb774144c372 100644
>>>>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>>>> @@ -134,12 +134,28 @@ int amdgpu_userq_ioctl(struct drm_device
>>>>>> *dev, void *data,
>>>>>> return r;
>>>>>> }
>>>>>> +extern const struct amdgpu_userq_funcs userq_gfx_v11_funcs;
>>>>>> +
>>>>>> +static void
>>>>>> +amdgpu_userqueue_setup_gfx(struct amdgpu_userq_mgr *uq_mgr)
>>>>>> +{
>>>>>> + int maj;
>>>>>> + struct amdgpu_device *adev = uq_mgr->adev;
>>>>>> + uint32_t version = adev->ip_versions[GC_HWIP][0];
>>>>>> +
>>>>>> + /* We support usermode queue only for GFX V11 as of now */
>>>>>> + maj = IP_VERSION_MAJ(version);
>>>>>> + if (maj == 11)
>>>>>> + uq_mgr->userq_funcs[AMDGPU_HW_IP_GFX] =
>>>>>> &userq_gfx_v11_funcs;
>>>>>> +}
>>>>>> +
>>>>>> int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr,
>>>>>> struct amdgpu_device *adev)
>>>>>> {
>>>>>> mutex_init(&userq_mgr->userq_mutex);
>>>>>> idr_init_base(&userq_mgr->userq_idr, 1);
>>>>>> userq_mgr->adev = adev;
>>>>>> + amdgpu_userqueue_setup_gfx(userq_mgr);
>>>>>> return 0;
>>>>>> }
>>>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>>>> b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>>>> index c4940b6ea1c4..e76e1b86b434 100644
>>>>>> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>>>> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>>>> @@ -30,6 +30,7 @@
>>>>>> #include "amdgpu_psp.h"
>>>>>> #include "amdgpu_smu.h"
>>>>>> #include "amdgpu_atomfirmware.h"
>>>>>> +#include "amdgpu_userqueue.h"
>>>>>> #include "imu_v11_0.h"
>>>>>> #include "soc21.h"
>>>>>> #include "nvd.h"
>>>>>> @@ -6486,3 +6487,75 @@ const struct amdgpu_ip_block_version
>>>>>> gfx_v11_0_ip_block =
>>>>>> .rev = 0,
>>>>>> .funcs = &gfx_v11_0_ip_funcs,
>>>>>> };
>>>>>> +
>>>>>> +static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr
>>>>>> *uq_mgr,
>>>>>> + struct drm_amdgpu_userq_in *args_in,
>>>>>> + struct amdgpu_usermode_queue *queue)
>>>>>> +{
>>>>>> + struct amdgpu_device *adev = uq_mgr->adev;
>>>>>> + struct amdgpu_mqd *mqd_gfx_generic =
>>>>>> &adev->mqds[AMDGPU_HW_IP_GFX];
>>>>>> + struct drm_amdgpu_userq_mqd_gfx_v11_0 mqd_user;
>>>>>> + struct amdgpu_mqd_prop userq_props;
>>>>>> + int r;
>>>>>> +
>>>>>> + /* Incoming MQD parameters from userspace to be saved here */
>>>>>> + memset(&mqd_user, 0, sizeof(mqd_user));
>>>>>> +
>>>>>> + /* Structure to initialize MQD for userqueue using generic
>>>>>> MQD init function */
>>>>>> + memset(&userq_props, 0, sizeof(userq_props));
>>>>>> +
>>>>>> + if (args_in->mqd_size != sizeof(struct
>>>>>> drm_amdgpu_userq_mqd_gfx_v11_0)) {
>>>>>> + DRM_ERROR("MQD size mismatch\n");
>>>>>> + return -EINVAL;
>>>>>> + }
>>>>>> +
>>>>>> + if (copy_from_user(&mqd_user, u64_to_user_ptr(args_in->mqd),
>>>>>> args_in->mqd_size)) {
>>>>>> + DRM_ERROR("Failed to get user MQD\n");
>>>>>> + return -EFAULT;
>>>>>> + }
>>>>>> +
>>>>>> + /* Create BO for actual Userqueue MQD now */
>>>>>> + r = amdgpu_bo_create_kernel(adev, mqd_gfx_generic->mqd_size,
>>>>>> PAGE_SIZE,
>>>>>> + AMDGPU_GEM_DOMAIN_GTT,
>>>>>> + &queue->mqd.obj,
>>>>>> + &queue->mqd.gpu_addr,
>>>>>> + &queue->mqd.cpu_ptr);
>>>>>> + if (r) {
>>>>>> + DRM_ERROR("Failed to allocate BO for userqueue (%d)", r);
>>>>>> + return -ENOMEM;
>>>>>> + }
>>>>>
>>>>> Using amdgpu_bo_create_kernel() for the MQD is most likely not a
>>>>> good idea in the long term, but should work for now.
>>>>>
>>>> I was a bit curious about this, the scope of this MQD object is
>>>> kernel internal and used for queue mapping only, userspace doesn't
>>>> know much about it. Do you still think we should not create a
>>>> kernel object for it ?
>>>
>>>
>>> Well we should use a kernel BO. But amdgpu_bo_create_kernel() not
>>> only creates a kernel BO but also pins it! And that is problematic
>>> because it allows userspace to do a deny of service attach on the
>>> kernel module.
>>>
>>> What we need is an eviction fence, e.g. what KFD is already using.
>>> Then the BO is created similar to how VM page tables are created,
>>> maybe even using the same reservation object.
>>
>> KFD doesn't currently use eviction fences on MQDs. Those are pinned.
>> I guess you could treat the MQDs more like we treat page tables. They
>> are allocated in kernel mode but protected with fences rather than
>> pinning.
>>
>> I'm not sure if MES needs to be able to access MQDs while queues are
>> not mapped. If that's the case, pinning can't be avoided.
>>
> I was planning to do something like this keep userqueue objects from
> eviction:
>
> - Add a new mutex in queue struct (say userq_eviction_fence)
>
> - lock this while mapping the queue, and unlock it while unmapping of
> the queue
>
> - add checks in amdgpu_vm_evictable() to add a
> mutex_trylock(userq_eviction_fence)
>
> Does it sound like what we want to do here or should I need something
> else ?
A mutex is not a fence. The eviction fences we have in KFD are
dma_fences. They interact with TTM's memory eviction logic, which allows
us to stop user mode queues before TTM moves memory. A mutex cannot do that.
Regards,
Felix
>
>> Regards,
>> Felix
>>
>>
>>>
>>> But for a test this here is probably ok.
>>>
>>> Christian.
>>>
>>>>
>>>> - Shashank
>>>>
>>>>> Probably best to add a comment here that this needs to be improved.
>>>>>
>>>>> Apart from that looks good to me,
>>>>> Christian.
>>>>>
>>>>>> + memset(queue->mqd.cpu_ptr, 0, mqd_gfx_generic->mqd_size);
>>>>>> +
>>>>>> + /* Initialize the MQD BO with user given values */
>>>>>> + userq_props.wptr_gpu_addr = mqd_user.wptr_va;
>>>>>> + userq_props.rptr_gpu_addr = mqd_user.rptr_va;
>>>>>> + userq_props.queue_size = mqd_user.queue_size;
>>>>>> + userq_props.hqd_base_gpu_addr = mqd_user.queue_va;
>>>>>> + userq_props.mqd_gpu_addr = queue->mqd.gpu_addr;
>>>>>> + userq_props.use_doorbell = true;
>>>>>> +
>>>>>> + r = mqd_gfx_generic->init_mqd(adev, (void
>>>>>> *)queue->mqd.cpu_ptr, &userq_props);
>>>>>> + if (r) {
>>>>>> + DRM_ERROR("Failed to initialize MQD for userqueue\n");
>>>>>> + goto free_mqd;
>>>>>> + }
>>>>>> +
>>>>>> + return 0;
>>>>>> +
>>>>>> +free_mqd:
>>>>>> + amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr,
>>>>>> &queue->mqd.cpu_ptr);
>>>>>> + return r;
>>>>>> +}
>>>>>> +
>>>>>> +static void
>>>>>> +gfx_v11_0_userq_mqd_destroy(struct amdgpu_userq_mgr *uq_mgr,
>>>>>> struct amdgpu_usermode_queue *queue)
>>>>>> +{
>>>>>> + struct amdgpu_userq_obj *mqd = &queue->mqd;
>>>>>> +
>>>>>> + amdgpu_bo_free_kernel(&mqd->obj, &mqd->gpu_addr,
>>>>>> &mqd->cpu_ptr);
>>>>>> +}
>>>>>> +
>>>>>> +const struct amdgpu_userq_funcs userq_gfx_v11_funcs = {
>>>>>> + .mqd_create = gfx_v11_0_userq_mqd_create,
>>>>>> + .mqd_destroy = gfx_v11_0_userq_mqd_destroy,
>>>>>> +};
>>>>>> diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>>>> b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>>>> index 55ed6512a565..240f92796f00 100644
>>>>>> --- a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>>>> +++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>>>> @@ -29,6 +29,12 @@
>>>>>> struct amdgpu_mqd_prop;
>>>>>> +struct amdgpu_userq_obj {
>>>>>> + void *cpu_ptr;
>>>>>> + uint64_t gpu_addr;
>>>>>> + struct amdgpu_bo *obj;
>>>>>> +};
>>>>>> +
>>>>>> struct amdgpu_usermode_queue {
>>>>>> int queue_type;
>>>>>> uint64_t doorbell_handle;
>>>>>> @@ -37,6 +43,7 @@ struct amdgpu_usermode_queue {
>>>>>> struct amdgpu_mqd_prop *userq_prop;
>>>>>> struct amdgpu_userq_mgr *userq_mgr;
>>>>>> struct amdgpu_vm *vm;
>>>>>> + struct amdgpu_userq_obj mqd;
>>>>>> };
>>>>>> struct amdgpu_userq_funcs {
>>>>>
>>>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v5 04/10] drm/amdgpu: create GFX-gen11 usermode queue
2023-07-12 16:01 ` Felix Kuehling
@ 2023-07-12 16:07 ` Shashank Sharma
0 siblings, 0 replies; 50+ messages in thread
From: Shashank Sharma @ 2023-07-12 16:07 UTC (permalink / raw)
To: Felix Kuehling, Christian König, amd-gfx; +Cc: Alex Deucher, arvind.yadav
On 12/07/2023 18:01, Felix Kuehling wrote:
> Am 2023-07-12 um 11:55 schrieb Shashank Sharma:
>>
>> On 11/07/2023 21:51, Felix Kuehling wrote:
>>>
>>> On 2023-07-06 09:39, Christian König wrote:
>>>> Am 06.07.23 um 15:37 schrieb Shashank Sharma:
>>>>>
>>>>> On 06/07/2023 15:22, Christian König wrote:
>>>>>> Am 06.07.23 um 14:35 schrieb Shashank Sharma:
>>>>>>> A Memory queue descriptor (MQD) of a userqueue defines it in
>>>>>>> the hw's context. As MQD format can vary between different
>>>>>>> graphics IPs, we need gfx GEN specific handlers to create MQDs.
>>>>>>>
>>>>>>> This patch:
>>>>>>> - Introduces MQD handler functions for the usermode queues.
>>>>>>> - Adds new functions to create and destroy userqueue MQD for
>>>>>>> GFX-GEN-11 IP
>>>>>>>
>>>>>>> V1: Worked on review comments from Alex:
>>>>>>> - Make MQD functions GEN and IP specific
>>>>>>>
>>>>>>> V2: Worked on review comments from Alex:
>>>>>>> - Reuse the existing adev->mqd[ip] for MQD creation
>>>>>>> - Formatting and arrangement of code
>>>>>>>
>>>>>>> V3:
>>>>>>> - Integration with doorbell manager
>>>>>>>
>>>>>>> V4: Review comments addressed:
>>>>>>> - Do not create a new file for userq, reuse gfx_v11_0.c (Alex)
>>>>>>> - Align name of structure members (Luben)
>>>>>>> - Don't break up the Cc tag list and the Sob tag list in
>>>>>>> commit
>>>>>>> message (Luben)
>>>>>>> V5:
>>>>>>> - No need to reserve the bo for MQD (Christian).
>>>>>>> - Some more changes to support IP specific MQD creation.
>>>>>>>
>>>>>>> Cc: Alex Deucher <alexander.deucher@amd.com>
>>>>>>> Cc: Christian Koenig <christian.koenig@amd.com>
>>>>>>> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com>
>>>>>>> Signed-off-by: Arvind Yadav <arvind.yadav@amd.com>
>>>>>>> ---
>>>>>>> drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c | 16 ++++
>>>>>>> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 73
>>>>>>> +++++++++++++++++++
>>>>>>> .../gpu/drm/amd/include/amdgpu_userqueue.h | 7 ++
>>>>>>> 3 files changed, 96 insertions(+)
>>>>>>>
>>>>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>>>>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>>>>> index e37b5da5a0d0..bb774144c372 100644
>>>>>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>>>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userqueue.c
>>>>>>> @@ -134,12 +134,28 @@ int amdgpu_userq_ioctl(struct drm_device
>>>>>>> *dev, void *data,
>>>>>>> return r;
>>>>>>> }
>>>>>>> +extern const struct amdgpu_userq_funcs userq_gfx_v11_funcs;
>>>>>>> +
>>>>>>> +static void
>>>>>>> +amdgpu_userqueue_setup_gfx(struct amdgpu_userq_mgr *uq_mgr)
>>>>>>> +{
>>>>>>> + int maj;
>>>>>>> + struct amdgpu_device *adev = uq_mgr->adev;
>>>>>>> + uint32_t version = adev->ip_versions[GC_HWIP][0];
>>>>>>> +
>>>>>>> + /* We support usermode queue only for GFX V11 as of now */
>>>>>>> + maj = IP_VERSION_MAJ(version);
>>>>>>> + if (maj == 11)
>>>>>>> + uq_mgr->userq_funcs[AMDGPU_HW_IP_GFX] =
>>>>>>> &userq_gfx_v11_funcs;
>>>>>>> +}
>>>>>>> +
>>>>>>> int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr,
>>>>>>> struct amdgpu_device *adev)
>>>>>>> {
>>>>>>> mutex_init(&userq_mgr->userq_mutex);
>>>>>>> idr_init_base(&userq_mgr->userq_idr, 1);
>>>>>>> userq_mgr->adev = adev;
>>>>>>> + amdgpu_userqueue_setup_gfx(userq_mgr);
>>>>>>> return 0;
>>>>>>> }
>>>>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>>>>> b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>>>>> index c4940b6ea1c4..e76e1b86b434 100644
>>>>>>> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>>>>> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
>>>>>>> @@ -30,6 +30,7 @@
>>>>>>> #include "amdgpu_psp.h"
>>>>>>> #include "amdgpu_smu.h"
>>>>>>> #include "amdgpu_atomfirmware.h"
>>>>>>> +#include "amdgpu_userqueue.h"
>>>>>>> #include "imu_v11_0.h"
>>>>>>> #include "soc21.h"
>>>>>>> #include "nvd.h"
>>>>>>> @@ -6486,3 +6487,75 @@ const struct amdgpu_ip_block_version
>>>>>>> gfx_v11_0_ip_block =
>>>>>>> .rev = 0,
>>>>>>> .funcs = &gfx_v11_0_ip_funcs,
>>>>>>> };
>>>>>>> +
>>>>>>> +static int gfx_v11_0_userq_mqd_create(struct amdgpu_userq_mgr
>>>>>>> *uq_mgr,
>>>>>>> + struct drm_amdgpu_userq_in *args_in,
>>>>>>> + struct amdgpu_usermode_queue *queue)
>>>>>>> +{
>>>>>>> + struct amdgpu_device *adev = uq_mgr->adev;
>>>>>>> + struct amdgpu_mqd *mqd_gfx_generic =
>>>>>>> &adev->mqds[AMDGPU_HW_IP_GFX];
>>>>>>> + struct drm_amdgpu_userq_mqd_gfx_v11_0 mqd_user;
>>>>>>> + struct amdgpu_mqd_prop userq_props;
>>>>>>> + int r;
>>>>>>> +
>>>>>>> + /* Incoming MQD parameters from userspace to be saved here */
>>>>>>> + memset(&mqd_user, 0, sizeof(mqd_user));
>>>>>>> +
>>>>>>> + /* Structure to initialize MQD for userqueue using generic
>>>>>>> MQD init function */
>>>>>>> + memset(&userq_props, 0, sizeof(userq_props));
>>>>>>> +
>>>>>>> + if (args_in->mqd_size != sizeof(struct
>>>>>>> drm_amdgpu_userq_mqd_gfx_v11_0)) {
>>>>>>> + DRM_ERROR("MQD size mismatch\n");
>>>>>>> + return -EINVAL;
>>>>>>> + }
>>>>>>> +
>>>>>>> + if (copy_from_user(&mqd_user,
>>>>>>> u64_to_user_ptr(args_in->mqd), args_in->mqd_size)) {
>>>>>>> + DRM_ERROR("Failed to get user MQD\n");
>>>>>>> + return -EFAULT;
>>>>>>> + }
>>>>>>> +
>>>>>>> + /* Create BO for actual Userqueue MQD now */
>>>>>>> + r = amdgpu_bo_create_kernel(adev,
>>>>>>> mqd_gfx_generic->mqd_size, PAGE_SIZE,
>>>>>>> + AMDGPU_GEM_DOMAIN_GTT,
>>>>>>> + &queue->mqd.obj,
>>>>>>> + &queue->mqd.gpu_addr,
>>>>>>> + &queue->mqd.cpu_ptr);
>>>>>>> + if (r) {
>>>>>>> + DRM_ERROR("Failed to allocate BO for userqueue (%d)", r);
>>>>>>> + return -ENOMEM;
>>>>>>> + }
>>>>>>
>>>>>> Using amdgpu_bo_create_kernel() for the MQD is most likely not a
>>>>>> good idea in the long term, but should work for now.
>>>>>>
>>>>> I was a bit curious about this, the scope of this MQD object is
>>>>> kernel internal and used for queue mapping only, userspace doesn't
>>>>> know much about it. Do you still think we should not create a
>>>>> kernel object for it ?
>>>>
>>>>
>>>> Well we should use a kernel BO. But amdgpu_bo_create_kernel() not
>>>> only creates a kernel BO but also pins it! And that is problematic
>>>> because it allows userspace to do a deny of service attach on the
>>>> kernel module.
>>>>
>>>> What we need is an eviction fence, e.g. what KFD is already using.
>>>> Then the BO is created similar to how VM page tables are created,
>>>> maybe even using the same reservation object.
>>>
>>> KFD doesn't currently use eviction fences on MQDs. Those are pinned.
>>> I guess you could treat the MQDs more like we treat page tables.
>>> They are allocated in kernel mode but protected with fences rather
>>> than pinning.
>>>
>>> I'm not sure if MES needs to be able to access MQDs while queues are
>>> not mapped. If that's the case, pinning can't be avoided.
>>>
>> I was planning to do something like this keep userqueue objects from
>> eviction:
>>
>> - Add a new mutex in queue struct (say userq_eviction_fence)
>>
>> - lock this while mapping the queue, and unlock it while unmapping of
>> the queue
>>
>> - add checks in amdgpu_vm_evictable() to add a
>> mutex_trylock(userq_eviction_fence)
>>
>> Does it sound like what we want to do here or should I need something
>> else ?
>
> A mutex is not a fence. The eviction fences we have in KFD are
> dma_fences. They interact with TTM's memory eviction logic, which
> allows us to stop user mode queues before TTM moves memory. A mutex
> cannot do that.
>
Ah, I meant userq_eviction_lock (not fence), as I was curious if we just
want to keep the GPUVM from eviction, a lock can also do that for us.
But now I realize that we actually want to keep all the GPU BOs (which
are related to this queue, one of which is MQD) to be saved from
internal TTM movement, and need to be embedded in form of dma/ttm
interaction.
- Shashank
> Regards,
> Felix
>
>
>>
>>> Regards,
>>> Felix
>>>
>>>
>>>>
>>>> But for a test this here is probably ok.
>>>>
>>>> Christian.
>>>>
>>>>>
>>>>> - Shashank
>>>>>
>>>>>> Probably best to add a comment here that this needs to be improved.
>>>>>>
>>>>>> Apart from that looks good to me,
>>>>>> Christian.
>>>>>>
>>>>>>> + memset(queue->mqd.cpu_ptr, 0, mqd_gfx_generic->mqd_size);
>>>>>>> +
>>>>>>> + /* Initialize the MQD BO with user given values */
>>>>>>> + userq_props.wptr_gpu_addr = mqd_user.wptr_va;
>>>>>>> + userq_props.rptr_gpu_addr = mqd_user.rptr_va;
>>>>>>> + userq_props.queue_size = mqd_user.queue_size;
>>>>>>> + userq_props.hqd_base_gpu_addr = mqd_user.queue_va;
>>>>>>> + userq_props.mqd_gpu_addr = queue->mqd.gpu_addr;
>>>>>>> + userq_props.use_doorbell = true;
>>>>>>> +
>>>>>>> + r = mqd_gfx_generic->init_mqd(adev, (void
>>>>>>> *)queue->mqd.cpu_ptr, &userq_props);
>>>>>>> + if (r) {
>>>>>>> + DRM_ERROR("Failed to initialize MQD for userqueue\n");
>>>>>>> + goto free_mqd;
>>>>>>> + }
>>>>>>> +
>>>>>>> + return 0;
>>>>>>> +
>>>>>>> +free_mqd:
>>>>>>> + amdgpu_bo_free_kernel(&queue->mqd.obj,
>>>>>>> &queue->mqd.gpu_addr, &queue->mqd.cpu_ptr);
>>>>>>> + return r;
>>>>>>> +}
>>>>>>> +
>>>>>>> +static void
>>>>>>> +gfx_v11_0_userq_mqd_destroy(struct amdgpu_userq_mgr *uq_mgr,
>>>>>>> struct amdgpu_usermode_queue *queue)
>>>>>>> +{
>>>>>>> + struct amdgpu_userq_obj *mqd = &queue->mqd;
>>>>>>> +
>>>>>>> + amdgpu_bo_free_kernel(&mqd->obj, &mqd->gpu_addr,
>>>>>>> &mqd->cpu_ptr);
>>>>>>> +}
>>>>>>> +
>>>>>>> +const struct amdgpu_userq_funcs userq_gfx_v11_funcs = {
>>>>>>> + .mqd_create = gfx_v11_0_userq_mqd_create,
>>>>>>> + .mqd_destroy = gfx_v11_0_userq_mqd_destroy,
>>>>>>> +};
>>>>>>> diff --git a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>>>>> b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>>>>> index 55ed6512a565..240f92796f00 100644
>>>>>>> --- a/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>>>>> +++ b/drivers/gpu/drm/amd/include/amdgpu_userqueue.h
>>>>>>> @@ -29,6 +29,12 @@
>>>>>>> struct amdgpu_mqd_prop;
>>>>>>> +struct amdgpu_userq_obj {
>>>>>>> + void *cpu_ptr;
>>>>>>> + uint64_t gpu_addr;
>>>>>>> + struct amdgpu_bo *obj;
>>>>>>> +};
>>>>>>> +
>>>>>>> struct amdgpu_usermode_queue {
>>>>>>> int queue_type;
>>>>>>> uint64_t doorbell_handle;
>>>>>>> @@ -37,6 +43,7 @@ struct amdgpu_usermode_queue {
>>>>>>> struct amdgpu_mqd_prop *userq_prop;
>>>>>>> struct amdgpu_userq_mgr *userq_mgr;
>>>>>>> struct amdgpu_vm *vm;
>>>>>>> + struct amdgpu_userq_obj mqd;
>>>>>>> };
>>>>>>> struct amdgpu_userq_funcs {
>>>>>>
>>>>
^ permalink raw reply [flat|nested] 50+ messages in thread
end of thread, other threads:[~2023-07-12 16:07 UTC | newest]
Thread overview: 50+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-07-06 12:35 [PATCH v5 00/10] AMDGPU Usermode queues Shashank Sharma
2023-07-06 12:35 ` [PATCH v5 01/10] drm/amdgpu: UAPI for user queue management Shashank Sharma
2023-07-06 12:35 ` [PATCH v5 02/10] drm/amdgpu: add usermode queue base code Shashank Sharma
2023-07-06 12:46 ` Christian König
2023-07-06 16:36 ` Alex Deucher
2023-07-06 16:52 ` Shashank Sharma
2023-07-06 17:34 ` Alex Deucher
2023-07-06 12:35 ` [PATCH v5 03/10] drm/amdgpu: add new IOCTL for usermode queue Shashank Sharma
2023-07-06 13:20 ` Christian König
2023-07-06 12:35 ` [PATCH v5 04/10] drm/amdgpu: create GFX-gen11 " Shashank Sharma
2023-07-06 13:22 ` Christian König
2023-07-06 13:37 ` Shashank Sharma
2023-07-06 13:39 ` Christian König
2023-07-06 13:43 ` Shashank Sharma
2023-07-11 19:51 ` Felix Kuehling
2023-07-12 15:55 ` Shashank Sharma
2023-07-12 16:01 ` Felix Kuehling
2023-07-12 16:07 ` Shashank Sharma
2023-07-06 16:27 ` Alex Deucher
2023-07-06 16:29 ` Shashank Sharma
2023-07-07 7:24 ` Christian König
2023-07-07 7:46 ` Shashank Sharma
2023-07-07 8:37 ` Christian König
2023-07-07 10:02 ` Shashank Sharma
2023-07-07 12:28 ` Christian König
2023-07-07 12:46 ` Shashank Sharma
2023-07-06 12:35 ` [PATCH v5 05/10] drm/amdgpu: create context space for " Shashank Sharma
2023-07-06 13:28 ` Christian König
2023-07-06 13:33 ` Shashank Sharma
2023-07-06 13:37 ` Christian König
2023-07-06 16:44 ` Alex Deucher
2023-07-06 12:35 ` [PATCH v5 06/10] drm/amdgpu: map usermode queue into MES Shashank Sharma
2023-07-06 14:47 ` Christian König
2023-07-06 16:52 ` Alex Deucher
2023-07-06 17:15 ` Shashank Sharma
2023-07-06 17:26 ` Alex Deucher
2023-07-06 17:32 ` Shashank Sharma
2023-07-06 17:36 ` Alex Deucher
2023-07-06 12:35 ` [PATCH v5 07/10] drm/amdgpu: map wptr BO into GART Shashank Sharma
2023-07-06 12:36 ` [PATCH v5 08/10] drm/amdgpu: generate doorbell index for userqueue Shashank Sharma
2023-07-07 7:15 ` Christian König
2023-07-07 7:39 ` Shashank Sharma
2023-07-07 7:57 ` Christian König
2023-07-07 9:00 ` Shashank Sharma
2023-07-06 12:36 ` [PATCH v5 09/10] drm/amdgpu: cleanup leftover queues Shashank Sharma
2023-07-07 7:17 ` Christian König
2023-07-07 7:40 ` Shashank Sharma
2023-07-06 12:36 ` [PATCH v5 10/10] drm/amdgpu: add delay after userqueue mapping Shashank Sharma
2023-07-06 17:41 ` Alex Deucher
2023-07-06 18:30 ` Shashank Sharma
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox