A single device-global CSA (adev->virt.csa_obj) was mapped into every
render client's GPUVM at the same fixed virtual address. The CSA is
GPU-writeable and holds CP preemption/resume (CE/DE) metadata that the
kernel and CP firmware consume to save and restore gfx queue state, so a
shared buffer lets one client overwrite the scheduler state relied upon
for another client's queue. Under SR-IOV this is a cross-tenant
scheduler-state integrity issue.

Allocate a private CSA per amdgpu_fpriv in amdgpu_driver_open_kms() and
map that into the process GPUVM instead of the global object, and free
it in amdgpu_driver_postclose_kms(). Publish its kernel mapping through
vm->csa_cpu_addr so the preemption resume path reads back this process's
own saved state. One client can no longer observe or corrupt another
client's CSA.

Signed-off-by: Xiang Liu <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu.h     |  2 ++
 drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 27 ++++++++++++++++++++++---
 2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 59670aee0fd6f..50ac52f2e0565 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -448,6 +448,8 @@ struct amdgpu_fpriv {
        struct amdgpu_vm        vm;
        struct amdgpu_bo_va     *prt_va;
        struct amdgpu_bo_va     *csa_va;
+       struct amdgpu_bo        *csa_obj;
+       void                    *csa_cpu_addr;
        struct amdgpu_bo_va     *seq64_va;
        struct mutex            bo_list_lock;
        struct idr              bo_list_handles;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index 2e1284b7887c3..e0fc16bc7ef23 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -1529,10 +1529,28 @@ int amdgpu_driver_open_kms(struct drm_device *dev, 
struct drm_file *file_priv)
        if (adev->gfx.mcbp) {
                uint64_t csa_addr = amdgpu_csa_vaddr(adev) & 
AMDGPU_GMC_HOLE_MASK;
 
-               r = amdgpu_map_static_csa(adev, &fpriv->vm, adev->virt.csa_obj,
-                                               &fpriv->csa_va, csa_addr, 
AMDGPU_CSA_SIZE);
+               /* Allocate a per-process CSA. The CSA holds CP 
preemption/resume
+                * (CE/DE) metadata that the kernel and CP firmware rely on. A
+                * single device-global CSA mapped writable into every GPUVM 
would
+                * let one client corrupt another client's (or the kernel's) 
saved
+                * scheduler state, so give each process its own isolated copy.
+                */
+               r = amdgpu_allocate_static_csa(adev, &fpriv->csa_obj,
+                                              AMDGPU_GEM_DOMAIN_VRAM |
+                                              AMDGPU_GEM_DOMAIN_GTT,
+                                              AMDGPU_CSA_SIZE,
+                                              &fpriv->csa_cpu_addr);
                if (r)
                        goto error_vm;
+
+               r = amdgpu_map_static_csa(adev, &fpriv->vm, fpriv->csa_obj,
+                                               &fpriv->csa_va, csa_addr, 
AMDGPU_CSA_SIZE);
+               if (r) {
+                       amdgpu_free_static_csa(&fpriv->csa_obj);
+                       fpriv->csa_cpu_addr = NULL;
+                       goto error_vm;
+               }
+               fpriv->vm.csa_cpu_addr = fpriv->csa_cpu_addr;
        }
 
        r = amdgpu_seq64_map(adev, &fpriv->vm, &fpriv->seq64_va);
@@ -1604,9 +1622,12 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,
        if (fpriv->csa_va) {
                uint64_t csa_addr = amdgpu_csa_vaddr(adev) & 
AMDGPU_GMC_HOLE_MASK;
 
-               WARN_ON(amdgpu_unmap_static_csa(adev, &fpriv->vm, 
adev->virt.csa_obj,
+               WARN_ON(amdgpu_unmap_static_csa(adev, &fpriv->vm, 
fpriv->csa_obj,
                                                fpriv->csa_va, csa_addr));
                fpriv->csa_va = NULL;
+               fpriv->vm.csa_cpu_addr = NULL;
+               amdgpu_free_static_csa(&fpriv->csa_obj);
+               fpriv->csa_cpu_addr = NULL;
        }
 
        amdgpu_seq64_unmap(adev, fpriv);
-- 
2.34.1

Reply via email to