<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<p><br>
</p>
<div class="moz-cite-prefix">On 2022-06-15 10:06, Christian König
wrote:<br>
</div>
<blockquote type="cite" cite="mid:26836141-d84a-363e-32c8-bd65dc8cdd22@amd.com">Am
15.06.22 um 15:17 schrieb Sider, Graham:
<br>
<blockquote type="cite">[AMD Official Use Only - General]
<br>
<br>
<blockquote type="cite">-----Original Message-----
<br>
From: Koenig, Christian <a class="moz-txt-link-rfc2396E" href="mailto:Christian.Koenig@amd.com"><Christian.Koenig@amd.com></a>
<br>
Sent: Wednesday, June 15, 2022 3:29 AM
<br>
To: Sider, Graham <a class="moz-txt-link-rfc2396E" href="mailto:Graham.Sider@amd.com"><Graham.Sider@amd.com></a>; amd-
<br>
<a class="moz-txt-link-abbreviated" href="mailto:gfx@lists.freedesktop.org">gfx@lists.freedesktop.org</a>
<br>
Cc: Joshi, Mukul <a class="moz-txt-link-rfc2396E" href="mailto:Mukul.Joshi@amd.com"><Mukul.Joshi@amd.com></a>; Kuehling, Felix
<br>
<a class="moz-txt-link-rfc2396E" href="mailto:Felix.Kuehling@amd.com"><Felix.Kuehling@amd.com></a>; Yang, Philip
<a class="moz-txt-link-rfc2396E" href="mailto:Philip.Yang@amd.com"><Philip.Yang@amd.com></a>
<br>
Subject: Re: [PATCH v3 2/3] drm/amdkfd: Enable GFX11 usermode
queue
<br>
oversubscription
<br>
<br>
<br>
<br>
Am 13.06.22 um 17:20 schrieb Graham Sider:
<br>
<blockquote type="cite">Starting with GFX11, MES requires wptr
BOs to be GTT allocated/mapped
<br>
to GART for usermode queues in order to support
oversubscription. In
<br>
the case that work is submitted to an unmapped queue, MES
must have a
<br>
GART wptr address to determine whether the queue should be
mapped.
<br>
<br>
This change is accompanied with changes in MES and is
applicable for
<br>
MES_VERSION >= 3.
<br>
<br>
v2:
<br>
- Update MES_VERSION check from 2 to 3.
<br>
v3:
<br>
- Use amdgpu_vm_bo_lookup_mapping for wptr_bo mapping lookup
<br>
- Move wptr_bo refcount increment to
<br>
</blockquote>
amdgpu_amdkfd_map_gtt_bo_to_gart
<br>
<blockquote type="cite">- Remove list_del_init from
amdgpu_amdkfd_map_gtt_bo_to_gart
<br>
- Cleanup/fix create_queue wptr_bo error handling
<br>
<br>
Signed-off-by: Graham Sider <a class="moz-txt-link-rfc2396E" href="mailto:Graham.Sider@amd.com"><Graham.Sider@amd.com></a>
<br>
---
<br>
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 1 +
<br>
.../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 49
<br>
</blockquote>
+++++++++++++++++++
<br>
<blockquote type="cite">
drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 37
+++++++++++++-
<br>
.../drm/amd/amdkfd/kfd_device_queue_manager.c | 9 +++-
<br>
.../gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c | 2 +
<br>
drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 3 ++
<br>
.../amd/amdkfd/kfd_process_queue_manager.c | 17
+++++--
<br>
7 files changed, 110 insertions(+), 8 deletions(-)
<br>
<br>
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
<br>
b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
<br>
index 429b16ba10bf..dba26d1e3be9 100644
<br>
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
<br>
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
<br>
@@ -301,6 +301,7 @@ int
<br>
</blockquote>
amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct amdgpu_device
<br>
*adev,
<br>
<blockquote type="cite"> struct kgd_mem *mem, void
**kptr, uint64_t *size);
<br>
void amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(struct
<br>
</blockquote>
amdgpu_device *adev,
<br>
<blockquote type="cite"> struct kgd_mem *mem);
<br>
+int amdgpu_amdkfd_map_gtt_bo_to_gart(struct amdgpu_device
*adev,
<br>
+struct amdgpu_bo *bo);
<br>
<br>
int amdgpu_amdkfd_gpuvm_restore_process_bos(void
*process_info,
<br>
struct dma_fence **ef);
<br>
diff --git
a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
<br>
b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
<br>
index efab923056f4..888d08128a94 100644
<br>
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
<br>
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
<br>
@@ -2030,6 +2030,55 @@ int amdgpu_amdkfd_gpuvm_sync_memory(
<br>
return ret;
<br>
}
<br>
<br>
+/**
<br>
+ * amdgpu_amdkfd_map_gtt_bo_to_gart - Map BO to GART and
<br>
</blockquote>
increment
<br>
<blockquote type="cite">+reference count
<br>
+ * @adev: Device to which allocated BO belongs
<br>
+ * @bo: Buffer object to be mapped
<br>
+ *
<br>
+ * Before return, bo reference count is incremented. To
release the
<br>
+reference and unpin/
<br>
+ * unmap the BO, call amdgpu_amdkfd_free_gtt_mem.
<br>
+ */
<br>
+int amdgpu_amdkfd_map_gtt_bo_to_gart(struct amdgpu_device
*adev,
<br>
+struct amdgpu_bo *bo) {
<br>
+ int ret;
<br>
+
<br>
+ ret = amdgpu_bo_reserve(bo, true);
<br>
+ if (ret) {
<br>
+ pr_err("Failed to reserve bo. ret %d\n", ret);
<br>
+ goto err_reserve_bo_failed;
<br>
+ }
<br>
+
<br>
+ ret = amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_GTT);
<br>
+ if (ret) {
<br>
+ pr_err("Failed to pin bo. ret %d\n", ret);
<br>
+ goto err_pin_bo_failed;
<br>
+ }
<br>
</blockquote>
<br>
Oh! Is that something we do for every MQD? When yes that here
is pretty
<br>
much a NAK.
<br>
<br>
We can't do this or create a trivial deny of service attack
against the kernel
<br>
driver.
<br>
<br>
Regards,
<br>
Christian.
<br>
<br>
</blockquote>
Hi Christian, could you elaborate on this? Right now this is
only being used to pin the queue wptr BO.
<br>
</blockquote>
<br>
Well is this wptr BO per process, per queue or global?
<br>
<br>
amdgpu_bo_pin() is only allowed if we pin global resources,
otherwise I have to reject that.
<br>
</blockquote>
<p>wptr BO is per queue, allocated as queue structure, 1 page size
on system memory.</p>
<p> KFD limit number of queues globally, max_queues = 127; /* HWS
limit */, so this will pin max 508KB and take max 127 GART page
mapping.</p>
<p>wptr is updated by app and read by HWS, if we don't pin wptr, we
have to evict queue when wptr bo is moved on system memory, then
update GART mapping and restore queue.</p>
<p>Regards,</p>
<p>Philip<br>
</p>
<blockquote type="cite" cite="mid:26836141-d84a-363e-32c8-bd65dc8cdd22@amd.com">
<br>
Regards,
<br>
Christian.
<br>
<br>
<blockquote type="cite">
<br>
Best,
<br>
Graham
<br>
<br>
<blockquote type="cite">
<blockquote type="cite">+
<br>
+ ret = amdgpu_ttm_alloc_gart(&bo->tbo);
<br>
+ if (ret) {
<br>
+ pr_err("Failed to bind bo to GART. ret %d\n", ret);
<br>
+ goto err_map_bo_gart_failed;
<br>
+ }
<br>
+
<br>
+ amdgpu_amdkfd_remove_eviction_fence(
<br>
+ bo,
bo->kfd_bo->process_info->eviction_fence);
<br>
+
list_del_init(&bo->kfd_bo->validate_list.head);
<br>
+
<br>
+ amdgpu_bo_unreserve(bo);
<br>
+
<br>
+ bo = amdgpu_bo_ref(bo);
<br>
+
<br>
+ return 0;
<br>
+
<br>
+err_map_bo_gart_failed:
<br>
+ amdgpu_bo_unpin(bo);
<br>
+err_pin_bo_failed:
<br>
+ amdgpu_bo_unreserve(bo);
<br>
+err_reserve_bo_failed:
<br>
+
<br>
+ return ret;
<br>
+}
<br>
+
<br>
int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct
<br>
</blockquote>
amdgpu_device *adev,
<br>
<blockquote type="cite"> struct kgd_mem *mem, void
**kptr, uint64_t *size)
<br>
{
<br>
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
<br>
b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
<br>
index e9766e165c38..1789ed8b79f5 100644
<br>
--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
<br>
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
<br>
@@ -289,6 +289,7 @@ static int kfd_ioctl_create_queue(struct
file *filep,
<br>
</blockquote>
struct kfd_process *p,
<br>
<blockquote type="cite"> struct kfd_process_device *pdd;
<br>
struct queue_properties q_properties;
<br>
uint32_t doorbell_offset_in_process = 0;
<br>
+ struct amdgpu_bo *wptr_bo = NULL;
<br>
<br>
memset(&q_properties, 0, sizeof(struct
queue_properties));
<br>
<br>
@@ -316,12 +317,41 @@ static int
kfd_ioctl_create_queue(struct file
<br>
</blockquote>
*filep, struct kfd_process *p,
<br>
<blockquote type="cite"> goto err_bind_process;
<br>
}
<br>
<br>
+ /* Starting with GFX11, wptr BOs must be mapped to GART
for MES
<br>
</blockquote>
to determine work
<br>
<blockquote type="cite">+ * on unmapped queues for
usermode queue oversubscription (no
<br>
</blockquote>
aggregated doorbell)
<br>
<blockquote type="cite">+ */
<br>
+ if (dev->shared_resources.enable_mes &&
(dev->adev-
<br>
mes.sched_version & 0xff) >= 3) {
<br>
+ struct amdgpu_bo_va_mapping *wptr_mapping;
<br>
+ struct amdgpu_vm *wptr_vm;
<br>
+
<br>
+ wptr_vm = drm_priv_to_vm(pdd->drm_priv);
<br>
+ err = amdgpu_bo_reserve(wptr_vm->root.bo,
false);
<br>
+ if (err)
<br>
+ goto err_wptr_map_gart;
<br>
+
<br>
+ wptr_mapping = amdgpu_vm_bo_lookup_mapping(
<br>
+ wptr_vm, args->write_pointer_address
>>
<br>
</blockquote>
PAGE_SHIFT);
<br>
<blockquote type="cite">+
amdgpu_bo_unreserve(wptr_vm->root.bo);
<br>
+ if (!wptr_mapping) {
<br>
+ pr_err("Failed to lookup wptr bo\n");
<br>
+ err = -EINVAL;
<br>
+ goto err_wptr_map_gart;
<br>
+ }
<br>
+
<br>
+ wptr_bo = wptr_mapping->bo_va->base.bo;
<br>
+ err =
amdgpu_amdkfd_map_gtt_bo_to_gart(dev->adev,
<br>
</blockquote>
wptr_bo);
<br>
<blockquote type="cite">+ if (err) {
<br>
+ pr_err("Failed to map wptr bo to GART\n");
<br>
+ goto err_wptr_map_gart;
<br>
+ }
<br>
+ }
<br>
+
<br>
pr_debug("Creating queue for PASID 0x%x on gpu
0x%x\n",
<br>
p->pasid,
<br>
dev->id);
<br>
<br>
- err = pqm_create_queue(&p->pqm, dev, filep,
&q_properties,
<br>
</blockquote>
&queue_id, NULL, NULL, NULL,
<br>
<blockquote type="cite">-
&doorbell_offset_in_process);
<br>
+ err = pqm_create_queue(&p->pqm, dev, filep,
&q_properties,
<br>
</blockquote>
&queue_id, wptr_bo,
<br>
<blockquote type="cite">+ NULL, NULL, NULL,
&doorbell_offset_in_process);
<br>
if (err != 0)
<br>
goto err_create_queue;
<br>
<br>
@@ -354,6 +384,9 @@ static int kfd_ioctl_create_queue(struct
file *filep,
<br>
</blockquote>
struct kfd_process *p,
<br>
<blockquote type="cite"> return 0;
<br>
<br>
err_create_queue:
<br>
+ if (wptr_bo)
<br>
+ amdgpu_amdkfd_free_gtt_mem(dev->adev, wptr_bo);
<br>
+err_wptr_map_gart:
<br>
err_bind_process:
<br>
err_pdd:
<br>
mutex_unlock(&p->mutex);
<br>
diff --git
a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
<br>
b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
<br>
index b39d89c52887..d8de2fbdfc7d 100644
<br>
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
<br>
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
<br>
@@ -208,6 +208,7 @@ static int add_queue_mes(struct
<br>
</blockquote>
device_queue_manager *dqm, struct queue *q,
<br>
<blockquote type="cite"> struct kfd_process_device *pdd
= qpd_to_pdd(qpd);
<br>
struct mes_add_queue_input queue_input;
<br>
int r, queue_type;
<br>
+ uint64_t wptr_addr_off;
<br>
<br>
if (dqm->is_hws_hang)
<br>
return -EIO;
<br>
@@ -227,7 +228,13 @@ static int add_queue_mes(struct
<br>
</blockquote>
device_queue_manager *dqm, struct queue *q,
<br>
AMDGPU_MES_PRIORITY_LEVEL_NORMAL;
<br>
<blockquote type="cite"> queue_input.doorbell_offset =
q->properties.doorbell_off;
<br>
queue_input.mqd_addr = q->gart_mqd_addr;
<br>
- queue_input.wptr_addr =
(uint64_t)q->properties.write_ptr;
<br>
+
<br>
+ if (q->wptr_bo) {
<br>
+ wptr_addr_off =
(uint64_t)q->properties.write_ptr -
<br>
</blockquote>
(uint64_t)q->wptr_bo->kfd_bo->va;
<br>
<blockquote type="cite">+ queue_input.wptr_addr =
((uint64_t)q->wptr_bo-
<br>
tbo.resource->start << PAGE_SHIFT) + wptr_addr_off;
<br>
+ } else
<br>
+ queue_input.wptr_addr = (uint64_t)q-
<br>
properties.write_ptr;
<br>
+
<br>
queue_input.paging = false;
<br>
queue_input.tba_addr = qpd->tba_addr;
<br>
queue_input.tma_addr = qpd->tma_addr; diff --git
<br>
a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c
<br>
b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c
<br>
index f1654b4da856..35e74bdd81da 100644
<br>
--- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c
<br>
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c
<br>
@@ -377,6 +377,8 @@ static void update_mqd_sdma(struct
mqd_manager
<br>
</blockquote>
*mm, void *mqd,
<br>
<blockquote type="cite"> m->sdmax_rlcx_rb_base_hi =
upper_32_bits(q->queue_address >>
<br>
</blockquote>
8);
<br>
<blockquote type="cite">
m->sdmax_rlcx_rb_rptr_addr_lo =
lower_32_bits((uint64_t)q-
<br>
read_ptr);
<br>
m->sdmax_rlcx_rb_rptr_addr_hi =
<br>
upper_32_bits((uint64_t)q->read_ptr);
<br>
+ m->sdmax_rlcx_rb_wptr_poll_addr_lo =
lower_32_bits((uint64_t)q-
<br>
write_ptr);
<br>
+ m->sdmax_rlcx_rb_wptr_poll_addr_hi =
<br>
+upper_32_bits((uint64_t)q->write_ptr);
<br>
m->sdmax_rlcx_doorbell_offset =
<br>
q->doorbell_off <<
<br>
</blockquote>
SDMA0_QUEUE0_DOORBELL_OFFSET__OFFSET__SHIFT;
<br>
<blockquote type="cite">diff --git
a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
<br>
b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
<br>
index a5d3963537d7..dcddee0d6f06 100644
<br>
--- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
<br>
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
<br>
@@ -639,6 +639,8 @@ struct queue {
<br>
void *gang_ctx_bo;
<br>
uint64_t gang_ctx_gpu_addr;
<br>
void *gang_ctx_cpu_ptr;
<br>
+
<br>
+ struct amdgpu_bo *wptr_bo;
<br>
};
<br>
<br>
enum KFD_MQD_TYPE {
<br>
@@ -1404,6 +1406,7 @@ int pqm_create_queue(struct
<br>
</blockquote>
process_queue_manager *pqm,
<br>
<blockquote type="cite"> struct file *f,
<br>
struct queue_properties *properties,
<br>
unsigned int *qid,
<br>
+ struct amdgpu_bo *wptr_bo,
<br>
const struct kfd_criu_queue_priv_data
*q_data,
<br>
const void *restore_mqd,
<br>
const void *restore_ctl_stack, diff --git
<br>
a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
<br>
b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
<br>
index f99e09dc43ea..3a17c1ebc527 100644
<br>
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
<br>
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
<br>
@@ -190,7 +190,8 @@ void pqm_uninit(struct
process_queue_manager
<br>
</blockquote>
*pqm)
<br>
<blockquote type="cite"> static int init_user_queue(struct
process_queue_manager *pqm,
<br>
struct kfd_dev *dev, struct queue **q,
<br>
struct queue_properties *q_properties,
<br>
- struct file *f, unsigned int qid)
<br>
+ struct file *f, struct amdgpu_bo *wptr_bo,
<br>
+ unsigned int qid)
<br>
{
<br>
int retval;
<br>
<br>
@@ -221,6 +222,7 @@ static int init_user_queue(struct
<br>
</blockquote>
process_queue_manager *pqm,
<br>
<blockquote type="cite"> goto cleanup;
<br>
}
<br>
memset((*q)->gang_ctx_cpu_ptr, 0,
<br>
</blockquote>
AMDGPU_MES_GANG_CTX_SIZE);
<br>
<blockquote type="cite">+ (*q)->wptr_bo = wptr_bo;
<br>
}
<br>
<br>
pr_debug("PQM After init queue");
<br>
@@ -237,6 +239,7 @@ int pqm_create_queue(struct
<br>
</blockquote>
process_queue_manager *pqm,
<br>
<blockquote type="cite"> struct file *f,
<br>
struct queue_properties *properties,
<br>
unsigned int *qid,
<br>
+ struct amdgpu_bo *wptr_bo,
<br>
const struct kfd_criu_queue_priv_data
*q_data,
<br>
const void *restore_mqd,
<br>
const void *restore_ctl_stack, @@ -299,7
+302,7
<br>
</blockquote>
@@ int
<br>
<blockquote type="cite">pqm_create_queue(struct
process_queue_manager *pqm,
<br>
* allocate_sdma_queue() in create_queue() has
the
<br>
* corresponding check logic.
<br>
*/
<br>
- retval = init_user_queue(pqm, dev, &q,
properties, f, *qid);
<br>
+ retval = init_user_queue(pqm, dev, &q,
properties, f,
<br>
</blockquote>
wptr_bo,
<br>
<blockquote type="cite">+*qid);
<br>
if (retval != 0)
<br>
goto err_create_queue;
<br>
pqn->q = q;
<br>
@@ -320,7 +323,7 @@ int pqm_create_queue(struct
<br>
</blockquote>
process_queue_manager *pqm,
<br>
<blockquote type="cite"> goto err_create_queue;
<br>
}
<br>
<br>
- retval = init_user_queue(pqm, dev, &q,
properties, f, *qid);
<br>
+ retval = init_user_queue(pqm, dev, &q,
properties, f,
<br>
</blockquote>
wptr_bo,
<br>
<blockquote type="cite">+*qid);
<br>
if (retval != 0)
<br>
goto err_create_queue;
<br>
pqn->q = q;
<br>
@@ -457,9 +460,13 @@ int pqm_destroy_queue(struct
<br>
</blockquote>
process_queue_manager *pqm, unsigned int qid)
<br>
<blockquote type="cite"> pdd->qpd.num_gws =
0;
<br>
}
<br>
<br>
- if (dev->shared_resources.enable_mes)
<br>
+ if (dev->shared_resources.enable_mes) {
<br>
amdgpu_amdkfd_free_gtt_mem(dev->adev,
<br>
pqn->q->gang_ctx_bo);
<br>
+ if (pqn->q->wptr_bo)
<br>
+ amdgpu_amdkfd_free_gtt_mem(dev-
<br>
adev, pqn->q->wptr_bo);
<br>
+
<br>
+ }
<br>
uninit_queue(pqn->q);
<br>
}
<br>
<br>
@@ -900,7 +907,7 @@ int kfd_criu_restore_queue(struct
kfd_process *p,
<br>
<br>
print_queue_properties(&qp);
<br>
<br>
- ret = pqm_create_queue(&p->pqm, pdd->dev,
NULL, &qp,
<br>
</blockquote>
&queue_id, q_data, mqd, ctl_stack,
<br>
<blockquote type="cite">+ ret =
pqm_create_queue(&p->pqm, pdd->dev, NULL, &qp,
<br>
</blockquote>
&queue_id,
<br>
<blockquote type="cite">+NULL, q_data, mqd, ctl_stack,
<br>
NULL);
<br>
if (ret) {
<br>
pr_err("Failed to create new queue err:%d\n",
ret);
<br>
</blockquote>
</blockquote>
</blockquote>
<br>
</blockquote>
</body>
</html>