AMDGPU_BO_MAX_PLACEMENTS was 3 but amdgpu_bo_placement_from_domain()
can emit up to four entries for CPU|GTT|VRAM|DOORBELL. Unprivileged
GEM_CREATE with domains=0x47 writes past placements[] and triggers
BUG_ON().

Increase the array to four and normalize mixed GDS/GWS/OA domain
masks to CPU-only placement on all rebuild paths.

Signed-off-by: Candice Li <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c    |  3 +--
 drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h    |  2 ++
 drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 18 ++++++++++++++++--
 drivers/gpu/drm/amd/amdgpu/amdgpu_object.h |  3 ++-
 4 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
index 6a0699746fbcd6..bcf81aba942842 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -431,8 +431,7 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void 
*data,
        flags |= AMDGPU_GEM_CREATE_VRAM_CLEARED;
 
        /* create a gem object to contain this object in */
-       if (args->in.domains & (AMDGPU_GEM_DOMAIN_GDS |
-           AMDGPU_GEM_DOMAIN_GWS | AMDGPU_GEM_DOMAIN_OA)) {
+       if (args->in.domains & AMDGPU_GEM_DOMAIN_GDS_GWS_OA) {
                if (flags & AMDGPU_GEM_CREATE_VM_ALWAYS_VALID) {
                        /* if gds bo is created from user space, it must be
                         * passed to bo list
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h
index b558336bc4c6ca..321db2ca29f4a3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h
@@ -31,6 +31,8 @@
  */
 
 #define AMDGPU_GEM_DOMAIN_MAX          0x3
+#define AMDGPU_GEM_DOMAIN_GDS_GWS_OA \
+       (AMDGPU_GEM_DOMAIN_GDS | AMDGPU_GEM_DOMAIN_GWS | AMDGPU_GEM_DOMAIN_OA)
 #define gem_to_amdgpu_bo(gobj) container_of((gobj), struct amdgpu_bo, tbo.base)
 
 extern const struct drm_gem_object_funcs amdgpu_gem_object_funcs;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
index d4a9d5e8fb429a..bb02858cbebf0d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
@@ -99,6 +99,19 @@ bool amdgpu_bo_is_amdgpu_bo(struct ttm_buffer_object *bo)
        return false;
 }
 
+static u32 amdgpu_bo_filter_placement_domain(u32 domain)
+{
+       /*
+        * GDS/GWS/OA are not normal fallback placement domains. When mixed
+        * with CPU/GTT/VRAM/DOORBELL, fall back to CPU like amdgpu_bo_create().
+        */
+       if ((domain & AMDGPU_GEM_DOMAIN_GDS_GWS_OA) &&
+           (domain & ~AMDGPU_GEM_DOMAIN_GDS_GWS_OA))
+               return AMDGPU_GEM_DOMAIN_CPU;
+
+       return domain;
+}
+
 /**
  * amdgpu_bo_placement_from_domain - set buffer's placement
  * @abo: &amdgpu_bo buffer object whose placement is to be set
@@ -115,6 +128,8 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, 
u32 domain)
        u64 flags = abo->flags;
        u32 c = 0;
 
+       domain = amdgpu_bo_filter_placement_domain(domain);
+
        if (domain & AMDGPU_GEM_DOMAIN_VRAM) {
                unsigned int visible_pfn = adev->gmc.visible_vram_size >> 
PAGE_SHIFT;
                int8_t mem_id = KFD_XCP_MEM_ID(adev, abo->xcp_id);
@@ -690,8 +705,7 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
                bo->flags &= ~AMDGPU_GEM_CREATE_CPU_GTT_USWC;
 
        bo->tbo.bdev = &adev->mman.bdev;
-       if (bp->domain & (AMDGPU_GEM_DOMAIN_GWS | AMDGPU_GEM_DOMAIN_OA |
-                         AMDGPU_GEM_DOMAIN_GDS))
+       if (bp->domain & AMDGPU_GEM_DOMAIN_GDS_GWS_OA)
                amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_CPU);
        else
                amdgpu_bo_placement_from_domain(bo, bp->domain);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
index ff11a09034997e..20f4d8c243afdd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
@@ -37,7 +37,8 @@
 #endif
 
 #define AMDGPU_BO_INVALID_OFFSET       LONG_MAX
-#define AMDGPU_BO_MAX_PLACEMENTS       3
+/* Covers CPU | GTT | VRAM | DOORBELL placement candidates */
+#define AMDGPU_BO_MAX_PLACEMENTS       4
 
 /* BO flag to indicate a KFD userptr BO */
 #define AMDGPU_AMDKFD_CREATE_USERPTR_BO        (1ULL << 63)
-- 
2.25.1

Reply via email to