+ if (((domain & AMDGPU_GEM_DOMAIN_VRAM) || + (domain & AMDGPU_GEM_DOMAIN_GTT)) && offset != ~0) { Why not make it simple? Like: if ((domain & (AMDGPU_GEM_DOMAIN_VRAM|AMDGPU_GEM_DOMAIN_GTT)) && offset !=~0) -----Original Message----- From: amd-gfx [mailto:amd-gfx-bounces@xxxxxxxxxxxxxxxxxxxxx] On Behalf Of Horace Chen Sent: 2017å¹´11æ??1æ?¥ 16:58 To: amd-gfx at lists.freedesktop.org Cc: Chen, Horace <Horace.Chen at amd.com> Subject: [PATCH 1/3] drm/amdgpu: Add interface to protect VRAM at exact position The existing method to reserve specified VRAM is to create a bo on system domain then pin it to VRAM. But in this process the existing data on the VRAM will be broken, because ttm will allocate a zero buffer on system domain then copy the zeroes to VRAM. Actually SRIOV need to reserve VRAM to protect data at exact position. So here add a new interface to create bo at the exact position directly and then pin it immediately to avoid eviction and avoid breaking the existing data on the VRAM. Signed-off-by: Horace Chen <horace.chen at amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 84 ++++++++++++++++++++++++++++-- drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 4 ++ 2 files changed, 85 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index e44b880..7108dc5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -281,7 +281,7 @@ void amdgpu_bo_free_kernel(struct amdgpu_bo **bo, u64 *gpu_addr, *cpu_addr = NULL; } -static int amdgpu_bo_do_create(struct amdgpu_device *adev, +static int amdgpu_bo_do_create(struct amdgpu_device *adev, u64 offset, unsigned long size, int byte_align, bool kernel, u32 domain, u64 flags, struct sg_table *sg, @@ -295,6 +295,7 @@ static int amdgpu_bo_do_create(struct amdgpu_device *adev, u64 initial_bytes_moved, bytes_moved; size_t acc_size; int r; + int i; page_align = roundup(byte_align, PAGE_SIZE) >> PAGE_SHIFT; size = ALIGN(size, PAGE_SIZE); @@ -364,6 +365,21 @@ static int amdgpu_bo_do_create(struct amdgpu_device *adev, bo->tbo.bdev = &adev->mman.bdev; amdgpu_ttm_placement_from_domain(bo, domain); + /* + * if offset is not ~0, it means the offset of this bo is restricted. + * modify the placement to create bo at the exact place. + */ + if (((domain & AMDGPU_GEM_DOMAIN_VRAM) || + (domain & AMDGPU_GEM_DOMAIN_GTT)) && offset != ~0) { + offset = ALIGN(offset, PAGE_SIZE); + for (i = 0; i < bo->placement.num_placement; ++i) { + bo->placements[i].fpfn = + offset >> PAGE_SHIFT; + bo->placements[i].lpfn = + (offset + size) >> PAGE_SHIFT; + } + } + initial_bytes_moved = atomic64_read(&adev->num_bytes_moved); /* Kernel allocation are uninterruptible */ r = ttm_bo_init_reserved(&adev->mman.bdev, &bo->tbo, size, type, @@ -416,6 +432,68 @@ static int amdgpu_bo_do_create(struct amdgpu_device *adev, return r; } +/** + * amdgpu_bo_create_vram_restricted_kernel - + * create BO at the specified place on the VRAM. + * + * @adev: amdgpu device object + * @offset: start offset of the new BO + * @size: size for the new BO + * @byte_align: alignment for the new BO + * @flags: addition flags for the BO + * @bo_ptr: resulting BO + * @gpu_addr: GPU addr of the pinned BO + * @cpu_addr: optional CPU address mapping + * + * Allocates and pins a BO at the specified place on the VRAM. + * + * Returns 0 on success, negative error code otherwise. + */ +int amdgpu_bo_create_vram_restricted_kernel(struct amdgpu_device *adev, + u64 offset, unsigned long size, int byte_align, + u64 flags, struct amdgpu_bo **bo_ptr, + u64 *gpu_addr, void **cpu_addr) +{ + int r; + /* specified memory must be in contiguous*/ + flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS; + + r = amdgpu_bo_do_create(adev, offset, size, byte_align, true, + AMDGPU_GEM_DOMAIN_VRAM, flags, NULL, NULL, 0, bo_ptr); + if (r) + return r; + + r = amdgpu_bo_reserve(*bo_ptr, false); + if (r) + goto error_reserve; + r = amdgpu_bo_pin_restricted(*bo_ptr, + AMDGPU_GEM_DOMAIN_VRAM, offset, (offset + size), + gpu_addr); + if (r) + goto error_pin; + if (cpu_addr) { + r = amdgpu_bo_kmap(*bo_ptr, + cpu_addr); + if (r) + goto error_kmap; + } + + amdgpu_bo_unreserve(*bo_ptr); + + return r; +error_kmap: + amdgpu_bo_unpin(*bo_ptr); +error_pin: + amdgpu_bo_unreserve(*bo_ptr); +error_reserve: + amdgpu_bo_unref(bo_ptr); + if (cpu_addr) + *cpu_addr = NULL; + if (gpu_addr) + *gpu_addr = 0; + return r; +} + static int amdgpu_bo_create_shadow(struct amdgpu_device *adev, unsigned long size, int byte_align, struct amdgpu_bo *bo) @@ -425,7 +503,7 @@ static int amdgpu_bo_create_shadow(struct amdgpu_device *adev, if (bo->shadow) return 0; - r = amdgpu_bo_do_create(adev, size, byte_align, true, + r = amdgpu_bo_do_create(adev, ~0, size, byte_align, true, AMDGPU_GEM_DOMAIN_GTT, AMDGPU_GEM_CREATE_CPU_GTT_USWC | AMDGPU_GEM_CREATE_SHADOW, @@ -455,7 +533,7 @@ int amdgpu_bo_create(struct amdgpu_device *adev, uint64_t parent_flags = flags & ~AMDGPU_GEM_CREATE_SHADOW; int r; - r = amdgpu_bo_do_create(adev, size, byte_align, kernel, domain, + r = amdgpu_bo_do_create(adev, ~0, size, byte_align, kernel, domain, parent_flags, sg, resv, init_value, bo_ptr); if (r) return r; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index 33615e2..71f4f82 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h @@ -216,6 +216,10 @@ int amdgpu_bo_create_kernel(struct amdgpu_device *adev, unsigned long size, int align, u32 domain, struct amdgpu_bo **bo_ptr, u64 *gpu_addr, void **cpu_addr); +int amdgpu_bo_create_vram_restricted_kernel(struct amdgpu_device *adev, + u64 offset, unsigned long size, int byte_align, + u64 flags, struct amdgpu_bo **bo_ptr, + u64 *gpu_addr, void **cpu_addr); void amdgpu_bo_free_kernel(struct amdgpu_bo **bo, u64 *gpu_addr, void **cpu_addr); int amdgpu_bo_kmap(struct amdgpu_bo *bo, void **ptr); -- 2.7.4 _______________________________________________ amd-gfx mailing list amd-gfx at lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx