[PATCH 1/3] drm/amdgpu: Add interface to protect VRAM at exact position

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Am 01.11.2017 um 09:58 schrieb Horace Chen:
> 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>

Modifying amdgpu_bo_do_create is still a NAK from myside, that function 
is why to complicated as it already is.

If you need to assign a specific placement without clearing it you can 
call ttm_bo_mem_space() manually to do so.

E.g. something like this:

ttm_bo_mem_put(&bo->tbo, &bo->tbo.mem);
r = ttm_bo_mem_space(&bo->tbo, &placement, &bo->tbo.mem, false, false);

That assigns the new memory without any copy operation.

Regards,
Christian.

> ---
>   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);




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux