[PATCH 2/4] drm/amdgpu: add support for per VM BOs v2

Christian König deathsimple at vodafone.de
Thu Aug 31 12:20:58 UTC 2017


Am 31.08.2017 um 00:50 schrieb Felix Kuehling:
> Reviewed-by: Felix Kuehling <Felix.Kuehling at amd.com>
>
> Some more thoughts inline, but nothing that should be addressed in this
> change.
>
> Regards,
>    Felix
>
>
> On 2017-08-30 11:00 AM, Christian König wrote:
>> From: Christian König <christian.koenig at amd.com>
>>
>> Per VM BOs are handled like VM PDs and PTs. They are always valid and don't
>> need to be specified in the BO lists.
>>
>> v2: validate PDs/PTs first
>>
>> Signed-off-by: Christian König <christian.koenig at amd.com>
>> ---
>>   drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c |  2 +-
>>   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 79 ++++++++++++++++++++++++----------
>>   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h |  5 ++-
>>   3 files changed, 60 insertions(+), 26 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
>> index f68ac56..48e18cc 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
>> @@ -813,7 +813,7 @@ static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p)
>>   
>>   	}
>>   
>> -	r = amdgpu_vm_clear_moved(adev, vm, &p->job->sync);
>> +	r = amdgpu_vm_handle_moved(adev, vm, &p->job->sync);
>>   
>>   	if (amdgpu_vm_debug && p->bo_list) {
>>   		/* Invalidate all BOs to test for userspace bugs */
>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
>> index 4cdfb70..6cd20e7 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
>> @@ -189,14 +189,18 @@ int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm,
>>   			spin_unlock(&glob->lru_lock);
>>   		}
>>   
>> -		if (vm->use_cpu_for_update) {
>> +		if (bo->tbo.type == ttm_bo_type_kernel &&
>> +		    vm->use_cpu_for_update) {
>>   			r = amdgpu_bo_kmap(bo, NULL);
>>   			if (r)
>>   				return r;
>>   		}
>>   
>>   		spin_lock(&vm->status_lock);
>> -		list_move(&bo_base->vm_status, &vm->relocated);
>> +		if (bo->tbo.type != ttm_bo_type_kernel)
>> +			list_move(&bo_base->vm_status, &vm->moved);
>> +		else
>> +			list_move(&bo_base->vm_status, &vm->relocated);
>>   	}
>>   	spin_unlock(&vm->status_lock);
>>   
>> @@ -1994,20 +1998,23 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
>>   }
>>   
>>   /**
>> - * amdgpu_vm_clear_moved - clear moved BOs in the PT
>> + * amdgpu_vm_handle_moved - handle moved BOs in the PT
>>    *
>>    * @adev: amdgpu_device pointer
>>    * @vm: requested vm
>> + * @sync: sync object to add fences to
>>    *
>> - * Make sure all moved BOs are cleared in the PT.
>> + * Make sure all BOs which are moved are updated in the PTs.
>>    * Returns 0 for success.
>>    *
>> - * PTs have to be reserved and mutex must be locked!
>> + * PTs have to be reserved!
>>    */
>> -int amdgpu_vm_clear_moved(struct amdgpu_device *adev, struct amdgpu_vm *vm,
>> -			    struct amdgpu_sync *sync)
>> +int amdgpu_vm_handle_moved(struct amdgpu_device *adev,
>> +			   struct amdgpu_vm *vm,
>> +			   struct amdgpu_sync *sync)
>>   {
>>   	struct amdgpu_bo_va *bo_va = NULL;
>> +	bool clear;
>>   	int r = 0;
>>   
>>   	spin_lock(&vm->status_lock);
>> @@ -2016,7 +2023,10 @@ int amdgpu_vm_clear_moved(struct amdgpu_device *adev, struct amdgpu_vm *vm,
>>   			struct amdgpu_bo_va, base.vm_status);
>>   		spin_unlock(&vm->status_lock);
>>   
>> -		r = amdgpu_vm_bo_update(adev, bo_va, true);
>> +		/* Per VM BOs never need to bo cleared in the page tables */
>> +		clear = bo_va->base.bo->tbo.resv != vm->root.base.bo->tbo.resv;
>> +
>> +		r = amdgpu_vm_bo_update(adev, bo_va, clear);
> Just thinking out loud: Per VM BOs don't need to be cleared because they
> have separate lists for evicted and moved (but valid) BOs.

Actually the reason is that we know they are reserved together with the 
page directory.

> If we had a
> similar thing for non-VM BOs (but without the automatic validation),
> this case could be optimized. Then moved but valid BOs could be updated
> in the page table instead of clearing them here and updating the page
> table again later.

Well, that won't work because other BOs can change their location while 
we try to use their location.

But what I'm speculating about for a while now is to use trylock on the 
BOs here. That might not work all the time, but clearly most of the time.

Going to give that a try now,
Christian.

>
>>   		if (r)
>>   			return r;
>>   
>> @@ -2068,6 +2078,37 @@ struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev,
>>   	return bo_va;
>>   }
>>   
>> +
>> +/**
>> + * amdgpu_vm_bo_insert_mapping - insert a new mapping
>> + *
>> + * @adev: amdgpu_device pointer
>> + * @bo_va: bo_va to store the address
>> + * @mapping: the mapping to insert
>> + *
>> + * Insert a new mapping into all structures.
>> + */
>> +static void amdgpu_vm_bo_insert_map(struct amdgpu_device *adev,
>> +				    struct amdgpu_bo_va *bo_va,
>> +				    struct amdgpu_bo_va_mapping *mapping)
>> +{
>> +	struct amdgpu_vm *vm = bo_va->base.vm;
>> +	struct amdgpu_bo *bo = bo_va->base.bo;
>> +
>> +	list_add(&mapping->list, &bo_va->invalids);
>> +	amdgpu_vm_it_insert(mapping, &vm->va);
>> +
>> +	if (mapping->flags & AMDGPU_PTE_PRT)
>> +		amdgpu_vm_prt_get(adev);
>> +
>> +	if (bo && bo->tbo.resv == vm->root.base.bo->tbo.resv) {
>> +		spin_lock(&vm->status_lock);
>> +		list_move(&bo_va->base.vm_status, &vm->moved);
>> +		spin_unlock(&vm->status_lock);
>> +	}
>> +	trace_amdgpu_vm_bo_map(bo_va, mapping);
>> +}
>> +
>>   /**
>>    * amdgpu_vm_bo_map - map bo inside a vm
>>    *
>> @@ -2119,18 +2160,12 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
>>   	if (!mapping)
>>   		return -ENOMEM;
>>   
>> -	INIT_LIST_HEAD(&mapping->list);
>>   	mapping->start = saddr;
>>   	mapping->last = eaddr;
>>   	mapping->offset = offset;
>>   	mapping->flags = flags;
>>   
>> -	list_add(&mapping->list, &bo_va->invalids);
>> -	amdgpu_vm_it_insert(mapping, &vm->va);
>> -
>> -	if (flags & AMDGPU_PTE_PRT)
>> -		amdgpu_vm_prt_get(adev);
>> -	trace_amdgpu_vm_bo_map(bo_va, mapping);
>> +	amdgpu_vm_bo_insert_map(adev, bo_va, mapping);
>>   
>>   	return 0;
>>   }
>> @@ -2157,7 +2192,6 @@ int amdgpu_vm_bo_replace_map(struct amdgpu_device *adev,
>>   {
>>   	struct amdgpu_bo_va_mapping *mapping;
>>   	struct amdgpu_bo *bo = bo_va->base.bo;
>> -	struct amdgpu_vm *vm = bo_va->base.vm;
>>   	uint64_t eaddr;
>>   	int r;
>>   
>> @@ -2191,12 +2225,7 @@ int amdgpu_vm_bo_replace_map(struct amdgpu_device *adev,
>>   	mapping->offset = offset;
>>   	mapping->flags = flags;
>>   
>> -	list_add(&mapping->list, &bo_va->invalids);
>> -	amdgpu_vm_it_insert(mapping, &vm->va);
>> -
>> -	if (flags & AMDGPU_PTE_PRT)
>> -		amdgpu_vm_prt_get(adev);
>> -	trace_amdgpu_vm_bo_map(bo_va, mapping);
>> +	amdgpu_vm_bo_insert_map(adev, bo_va, mapping);
>>   
>>   	return 0;
>>   }
>> @@ -2411,7 +2440,11 @@ void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev,
>>   		bo_base->moved = true;
>>   		if (evicted && bo->tbo.resv == vm->root.base.bo->tbo.resv) {
>>   			spin_lock(&bo_base->vm->status_lock);
>> -			list_move(&bo_base->vm_status, &vm->evicted);
>> +			if (bo->tbo.type == ttm_bo_type_kernel)
>> +				list_move(&bo_base->vm_status, &vm->evicted);
>> +			else
>> +				list_move_tail(&bo_base->vm_status,
>> +					       &vm->evicted);
>>   			spin_unlock(&bo_base->vm->status_lock);
>>   			continue;
>>   		}
>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
>> index c3753af..90b7741 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
>> @@ -249,8 +249,9 @@ int amdgpu_vm_update_directories(struct amdgpu_device *adev,
>>   int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
>>   			  struct amdgpu_vm *vm,
>>   			  struct dma_fence **fence);
>> -int amdgpu_vm_clear_moved(struct amdgpu_device *adev, struct amdgpu_vm *vm,
>> -			  struct amdgpu_sync *sync);
>> +int amdgpu_vm_handle_moved(struct amdgpu_device *adev,
>> +			   struct amdgpu_vm *vm,
>> +			   struct amdgpu_sync *sync);
>>   int amdgpu_vm_bo_update(struct amdgpu_device *adev,
>>   			struct amdgpu_bo_va *bo_va,
>>   			bool clear);
> _______________________________________________
> amd-gfx mailing list
> amd-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx




More information about the amd-gfx mailing list