All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Koenig, Christian" <Christian.Koenig@amd.com>
To: Jason Gunthorpe <jgg@ziepe.ca>,
	"linux-mm@kvack.org" <linux-mm@kvack.org>,
	Jerome Glisse <jglisse@redhat.com>,
	Ralph Campbell <rcampbell@nvidia.com>,
	John Hubbard <jhubbard@nvidia.com>,
	"Kuehling, Felix" <Felix.Kuehling@amd.com>
Cc: "linux-rdma@vger.kernel.org" <linux-rdma@vger.kernel.org>,
	"dri-devel@lists.freedesktop.org"
	<dri-devel@lists.freedesktop.org>,
	"amd-gfx@lists.freedesktop.org" <amd-gfx@lists.freedesktop.org>,
	"Deucher, Alexander" <Alexander.Deucher@amd.com>,
	Ben Skeggs <bskeggs@redhat.com>,
	Boris Ostrovsky <boris.ostrovsky@oracle.com>,
	"Zhou, David(ChunMing)" <David1.Zhou@amd.com>,
	Dennis Dalessandro <dennis.dalessandro@intel.com>,
	Juergen Gross <jgross@suse.com>,
	Mike Marciniszyn <mike.marciniszyn@intel.com>,
	Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>,
	Petr Cvek <petrcvekcz@gmail.com>,
	Stefano Stabellini <sstabellini@kernel.org>,
	"nouveau@lists.freedesktop.org" <nouveau@lists.freedesktop.org>,
	"xen-devel@lists.xenproject.org" <xen-devel@lists.xenproject.org>,
	Christoph Hellwig <hch@infradead.org>,
	Jason Gunthorpe <jgg@mellanox.com>
Subject: Re: [PATCH v2 13/15] drm/amdgpu: Use mmu_range_insert instead of hmm_mirror
Date: Tue, 29 Oct 2019 07:51:30 +0000	[thread overview]
Message-ID: <bc44f331-5448-ddc0-ecc3-d0ccb92e11a4@amd.com> (raw)
In-Reply-To: <20191028201032.6352-14-jgg@ziepe.ca>

Am 28.10.19 um 21:10 schrieb Jason Gunthorpe:
> From: Jason Gunthorpe <jgg@mellanox.com>
>
> Remove the interval tree in the driver and rely on the tree maintained by
> the mmu_notifier for delivering mmu_notifier invalidation callbacks.
>
> For some reason amdgpu has a very complicated arrangement where it tries
> to prevent duplicate entries in the interval_tree, this is not necessary,
> each amdgpu_bo can be its own stand alone entry. interval_tree already
> allows duplicates and overlaps in the tree.
>
> Also, there is no need to remove entries upon a release callback, the
> mmu_range API safely allows objects to remain registered beyond the
> lifetime of the mm. The driver only has to stop touching the pages during
> release.
>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Christian König <christian.koenig@amd.com>
> Cc: David (ChunMing) Zhou <David1.Zhou@amd.com>
> Cc: amd-gfx@lists.freedesktop.org
> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu.h           |   2 +
>   .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c  |   5 +-
>   drivers/gpu/drm/amd/amdgpu/amdgpu_device.c    |   1 +
>   drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c        | 341 ++++--------------
>   drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h        |   4 -
>   drivers/gpu/drm/amd/amdgpu/amdgpu_object.h    |  13 +-
>   6 files changed, 84 insertions(+), 282 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> index bd37df5dd6d048..60591a5d420021 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> @@ -1006,6 +1006,8 @@ struct amdgpu_device {
>   	struct mutex  lock_reset;
>   	struct amdgpu_doorbell_index doorbell_index;
>   
> +	struct mutex			notifier_lock;
> +
>   	int asic_reset_res;
>   	struct work_struct		xgmi_reset_work;
>   
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
> index 6d021ecc8d598f..47700302a08b7f 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
> @@ -481,8 +481,7 @@ static void remove_kgd_mem_from_kfd_bo_list(struct kgd_mem *mem,
>    *
>    * Returns 0 for success, negative errno for errors.
>    */
> -static int init_user_pages(struct kgd_mem *mem, struct mm_struct *mm,
> -			   uint64_t user_addr)
> +static int init_user_pages(struct kgd_mem *mem, uint64_t user_addr)
>   {
>   	struct amdkfd_process_info *process_info = mem->process_info;
>   	struct amdgpu_bo *bo = mem->bo;
> @@ -1195,7 +1194,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
>   	add_kgd_mem_to_kfd_bo_list(*mem, avm->process_info, user_addr);
>   
>   	if (user_addr) {
> -		ret = init_user_pages(*mem, current->mm, user_addr);
> +		ret = init_user_pages(*mem, user_addr);
>   		if (ret)
>   			goto allocate_init_user_pages_failed;
>   	}
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> index 5a1939dbd4e3e6..38f97998aaddb2 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> @@ -2633,6 +2633,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
>   	mutex_init(&adev->virt.vf_errors.lock);
>   	hash_init(adev->mn_hash);
>   	mutex_init(&adev->lock_reset);
> +	mutex_init(&adev->notifier_lock);
>   	mutex_init(&adev->virt.dpm_mutex);
>   	mutex_init(&adev->psp.mutex);
>   
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
> index 31d4deb5d29484..4ffd7b90f4d907 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
> @@ -50,66 +50,6 @@
>   #include "amdgpu.h"
>   #include "amdgpu_amdkfd.h"
>   
> -/**
> - * struct amdgpu_mn_node
> - *
> - * @it: interval node defining start-last of the affected address range
> - * @bos: list of all BOs in the affected address range
> - *
> - * Manages all BOs which are affected of a certain range of address space.
> - */
> -struct amdgpu_mn_node {
> -	struct interval_tree_node	it;
> -	struct list_head		bos;
> -};
> -
> -/**
> - * amdgpu_mn_destroy - destroy the HMM mirror
> - *
> - * @work: previously sheduled work item
> - *
> - * Lazy destroys the notifier from a work item
> - */
> -static void amdgpu_mn_destroy(struct work_struct *work)
> -{
> -	struct amdgpu_mn *amn = container_of(work, struct amdgpu_mn, work);
> -	struct amdgpu_device *adev = amn->adev;
> -	struct amdgpu_mn_node *node, *next_node;
> -	struct amdgpu_bo *bo, *next_bo;
> -
> -	mutex_lock(&adev->mn_lock);
> -	down_write(&amn->lock);
> -	hash_del(&amn->node);
> -	rbtree_postorder_for_each_entry_safe(node, next_node,
> -					     &amn->objects.rb_root, it.rb) {
> -		list_for_each_entry_safe(bo, next_bo, &node->bos, mn_list) {
> -			bo->mn = NULL;
> -			list_del_init(&bo->mn_list);
> -		}
> -		kfree(node);
> -	}
> -	up_write(&amn->lock);
> -	mutex_unlock(&adev->mn_lock);
> -
> -	hmm_mirror_unregister(&amn->mirror);
> -	kfree(amn);
> -}
> -
> -/**
> - * amdgpu_hmm_mirror_release - callback to notify about mm destruction
> - *
> - * @mirror: the HMM mirror (mm) this callback is about
> - *
> - * Shedule a work item to lazy destroy HMM mirror.
> - */
> -static void amdgpu_hmm_mirror_release(struct hmm_mirror *mirror)
> -{
> -	struct amdgpu_mn *amn = container_of(mirror, struct amdgpu_mn, mirror);
> -
> -	INIT_WORK(&amn->work, amdgpu_mn_destroy);
> -	schedule_work(&amn->work);
> -}
> -
>   /**
>    * amdgpu_mn_lock - take the write side lock for this notifier
>    *
> @@ -133,157 +73,86 @@ void amdgpu_mn_unlock(struct amdgpu_mn *mn)
>   }
>   
>   /**
> - * amdgpu_mn_read_lock - take the read side lock for this notifier
> - *
> - * @amn: our notifier
> - */
> -static int amdgpu_mn_read_lock(struct amdgpu_mn *amn, bool blockable)
> -{
> -	if (blockable)
> -		down_read(&amn->lock);
> -	else if (!down_read_trylock(&amn->lock))
> -		return -EAGAIN;
> -
> -	return 0;
> -}
> -
> -/**
> - * amdgpu_mn_read_unlock - drop the read side lock for this notifier
> - *
> - * @amn: our notifier
> - */
> -static void amdgpu_mn_read_unlock(struct amdgpu_mn *amn)
> -{
> -	up_read(&amn->lock);
> -}
> -
> -/**
> - * amdgpu_mn_invalidate_node - unmap all BOs of a node
> + * amdgpu_mn_invalidate_gfx - callback to notify about mm change
>    *
> - * @node: the node with the BOs to unmap
> - * @start: start of address range affected
> - * @end: end of address range affected
> + * @mrn: the range (mm) is about to update
> + * @range: details on the invalidation
>    *
>    * Block for operations on BOs to finish and mark pages as accessed and
>    * potentially dirty.
>    */
> -static void amdgpu_mn_invalidate_node(struct amdgpu_mn_node *node,
> -				      unsigned long start,
> -				      unsigned long end)
> +static bool amdgpu_mn_invalidate_gfx(struct mmu_range_notifier *mrn,
> +				     const struct mmu_notifier_range *range)
>   {
> -	struct amdgpu_bo *bo;
> +	struct amdgpu_bo *bo = container_of(mrn, struct amdgpu_bo, notifier);
> +	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
>   	long r;
>   
> -	list_for_each_entry(bo, &node->bos, mn_list) {
> -
> -		if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, start, end))
> -			continue;
> -
> -		r = dma_resv_wait_timeout_rcu(bo->tbo.base.resv,
> -			true, false, MAX_SCHEDULE_TIMEOUT);
> -		if (r <= 0)
> -			DRM_ERROR("(%ld) failed to wait for user bo\n", r);
> -	}
> +	/* FIXME: Is this necessary? */

Most likely not.

Christian.

> +	if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, range->start,
> +					  range->end))
> +		return true;
> +
> +	if (!mmu_notifier_range_blockable(range))
> +		return false;
> +
> +	mutex_lock(&adev->notifier_lock);
> +	r = dma_resv_wait_timeout_rcu(bo->tbo.base.resv, true, false,
> +				      MAX_SCHEDULE_TIMEOUT);
> +	mutex_unlock(&adev->notifier_lock);
> +	if (r <= 0)
> +		DRM_ERROR("(%ld) failed to wait for user bo\n", r);
> +	return true;
>   }
>   
> +static const struct mmu_range_notifier_ops amdgpu_mn_gfx_ops = {
> +	.invalidate = amdgpu_mn_invalidate_gfx,
> +};
> +
>   /**
> - * amdgpu_mn_sync_pagetables_gfx - callback to notify about mm change
> + * amdgpu_mn_invalidate_hsa - callback to notify about mm change
>    *
> - * @mirror: the hmm_mirror (mm) is about to update
> - * @update: the update start, end address
> + * @mrn: the range (mm) is about to update
> + * @range: details on the invalidation
>    *
> - * Block for operations on BOs to finish and mark pages as accessed and
> - * potentially dirty.
> + * We temporarily evict the BO attached to this range. This necessitates
> + * evicting all user-mode queues of the process.
>    */
> -static int
> -amdgpu_mn_sync_pagetables_gfx(struct hmm_mirror *mirror,
> -			      const struct mmu_notifier_range *update)
> +static bool amdgpu_mn_invalidate_hsa(struct mmu_range_notifier *mrn,
> +				     const struct mmu_notifier_range *range)
>   {
> -	struct amdgpu_mn *amn = container_of(mirror, struct amdgpu_mn, mirror);
> -	unsigned long start = update->start;
> -	unsigned long end = update->end;
> -	bool blockable = mmu_notifier_range_blockable(update);
> -	struct interval_tree_node *it;
> -
> -	/* notification is exclusive, but interval is inclusive */
> -	end -= 1;
> -
> -	/* TODO we should be able to split locking for interval tree and
> -	 * amdgpu_mn_invalidate_node
> -	 */
> -	if (amdgpu_mn_read_lock(amn, blockable))
> -		return -EAGAIN;
> -
> -	it = interval_tree_iter_first(&amn->objects, start, end);
> -	while (it) {
> -		struct amdgpu_mn_node *node;
> -
> -		if (!blockable) {
> -			amdgpu_mn_read_unlock(amn);
> -			return -EAGAIN;
> -		}
> +	struct amdgpu_bo *bo = container_of(mrn, struct amdgpu_bo, notifier);
> +	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
>   
> -		node = container_of(it, struct amdgpu_mn_node, it);
> -		it = interval_tree_iter_next(it, start, end);
> +	/* FIXME: Is this necessary? */
> +	if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, range->start,
> +					  range->end))
> +		return true;
>   
> -		amdgpu_mn_invalidate_node(node, start, end);
> -	}
> +	if (!mmu_notifier_range_blockable(range))
> +		return false;
>   
> -	amdgpu_mn_read_unlock(amn);
> +	mutex_lock(&adev->notifier_lock);
> +	amdgpu_amdkfd_evict_userptr(bo->kfd_bo, bo->notifier.mm);
> +	mutex_unlock(&adev->notifier_lock);
>   
> -	return 0;
> +	return true;
>   }
>   
> -/**
> - * amdgpu_mn_sync_pagetables_hsa - callback to notify about mm change
> - *
> - * @mirror: the hmm_mirror (mm) is about to update
> - * @update: the update start, end address
> - *
> - * We temporarily evict all BOs between start and end. This
> - * necessitates evicting all user-mode queues of the process. The BOs
> - * are restorted in amdgpu_mn_invalidate_range_end_hsa.
> - */
> -static int
> -amdgpu_mn_sync_pagetables_hsa(struct hmm_mirror *mirror,
> -			      const struct mmu_notifier_range *update)
> +static const struct mmu_range_notifier_ops amdgpu_mn_hsa_ops = {
> +	.invalidate = amdgpu_mn_invalidate_hsa,
> +};
> +
> +static int amdgpu_mn_sync_pagetables(struct hmm_mirror *mirror,
> +				     const struct mmu_notifier_range *update)
>   {
>   	struct amdgpu_mn *amn = container_of(mirror, struct amdgpu_mn, mirror);
> -	unsigned long start = update->start;
> -	unsigned long end = update->end;
> -	bool blockable = mmu_notifier_range_blockable(update);
> -	struct interval_tree_node *it;
>   
> -	/* notification is exclusive, but interval is inclusive */
> -	end -= 1;
> -
> -	if (amdgpu_mn_read_lock(amn, blockable))
> -		return -EAGAIN;
> -
> -	it = interval_tree_iter_first(&amn->objects, start, end);
> -	while (it) {
> -		struct amdgpu_mn_node *node;
> -		struct amdgpu_bo *bo;
> -
> -		if (!blockable) {
> -			amdgpu_mn_read_unlock(amn);
> -			return -EAGAIN;
> -		}
> -
> -		node = container_of(it, struct amdgpu_mn_node, it);
> -		it = interval_tree_iter_next(it, start, end);
> -
> -		list_for_each_entry(bo, &node->bos, mn_list) {
> -			struct kgd_mem *mem = bo->kfd_bo;
> -
> -			if (amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm,
> -							 start, end))
> -				amdgpu_amdkfd_evict_userptr(mem, amn->mm);
> -		}
> -	}
> -
> -	amdgpu_mn_read_unlock(amn);
> +	if (!mmu_notifier_range_blockable(update))
> +		return false;
>   
> +	down_read(&amn->lock);
> +	up_read(&amn->lock);
>   	return 0;
>   }
>   
> @@ -295,12 +164,10 @@ amdgpu_mn_sync_pagetables_hsa(struct hmm_mirror *mirror,
>   
>   static struct hmm_mirror_ops amdgpu_hmm_mirror_ops[] = {
>   	[AMDGPU_MN_TYPE_GFX] = {
> -		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables_gfx,
> -		.release = amdgpu_hmm_mirror_release
> +		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables,
>   	},
>   	[AMDGPU_MN_TYPE_HSA] = {
> -		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables_hsa,
> -		.release = amdgpu_hmm_mirror_release
> +		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables,
>   	},
>   };
>   
> @@ -327,7 +194,8 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev,
>   	}
>   
>   	hash_for_each_possible(adev->mn_hash, amn, node, key)
> -		if (AMDGPU_MN_KEY(amn->mm, amn->type) == key)
> +		if (AMDGPU_MN_KEY(amn->mirror.hmm->mmu_notifier.mm,
> +				  amn->type) == key)
>   			goto release_locks;
>   
>   	amn = kzalloc(sizeof(*amn), GFP_KERNEL);
> @@ -337,10 +205,8 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev,
>   	}
>   
>   	amn->adev = adev;
> -	amn->mm = mm;
>   	init_rwsem(&amn->lock);
>   	amn->type = type;
> -	amn->objects = RB_ROOT_CACHED;
>   
>   	amn->mirror.ops = &amdgpu_hmm_mirror_ops[type];
>   	r = hmm_mirror_register(&amn->mirror, mm);
> @@ -369,100 +235,33 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev,
>    * @bo: amdgpu buffer object
>    * @addr: userptr addr we should monitor
>    *
> - * Registers an HMM mirror for the given BO at the specified address.
> + * Registers a mmu_notifier for the given BO at the specified address.
>    * Returns 0 on success, -ERRNO if anything goes wrong.
>    */
>   int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr)
>   {
> -	unsigned long end = addr + amdgpu_bo_size(bo) - 1;
> -	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
> -	enum amdgpu_mn_type type =
> -		bo->kfd_bo ? AMDGPU_MN_TYPE_HSA : AMDGPU_MN_TYPE_GFX;
> -	struct amdgpu_mn *amn;
> -	struct amdgpu_mn_node *node = NULL, *new_node;
> -	struct list_head bos;
> -	struct interval_tree_node *it;
> -
> -	amn = amdgpu_mn_get(adev, type);
> -	if (IS_ERR(amn))
> -		return PTR_ERR(amn);
> -
> -	new_node = kmalloc(sizeof(*new_node), GFP_KERNEL);
> -	if (!new_node)
> -		return -ENOMEM;
> -
> -	INIT_LIST_HEAD(&bos);
> -
> -	down_write(&amn->lock);
> -
> -	while ((it = interval_tree_iter_first(&amn->objects, addr, end))) {
> -		kfree(node);
> -		node = container_of(it, struct amdgpu_mn_node, it);
> -		interval_tree_remove(&node->it, &amn->objects);
> -		addr = min(it->start, addr);
> -		end = max(it->last, end);
> -		list_splice(&node->bos, &bos);
> -	}
> -
> -	if (!node)
> -		node = new_node;
> +	if (bo->kfd_bo)
> +		bo->notifier.ops = &amdgpu_mn_hsa_ops;
>   	else
> -		kfree(new_node);
> -
> -	bo->mn = amn;
> -
> -	node->it.start = addr;
> -	node->it.last = end;
> -	INIT_LIST_HEAD(&node->bos);
> -	list_splice(&bos, &node->bos);
> -	list_add(&bo->mn_list, &node->bos);
> +		bo->notifier.ops = &amdgpu_mn_gfx_ops;
>   
> -	interval_tree_insert(&node->it, &amn->objects);
> -
> -	up_write(&amn->lock);
> -
> -	return 0;
> +	return mmu_range_notifier_insert(&bo->notifier, addr,
> +					 amdgpu_bo_size(bo), current->mm);
>   }
>   
>   /**
> - * amdgpu_mn_unregister - unregister a BO for HMM mirror updates
> + * amdgpu_mn_unregister - unregister a BO for notifier updates
>    *
>    * @bo: amdgpu buffer object
>    *
> - * Remove any registration of HMM mirror updates from the buffer object.
> + * Remove any registration of mmu notifier updates from the buffer object.
>    */
>   void amdgpu_mn_unregister(struct amdgpu_bo *bo)
>   {
> -	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
> -	struct amdgpu_mn *amn;
> -	struct list_head *head;
> -
> -	mutex_lock(&adev->mn_lock);
> -
> -	amn = bo->mn;
> -	if (amn == NULL) {
> -		mutex_unlock(&adev->mn_lock);
> +	if (!bo->notifier.mm)
>   		return;
> -	}
> -
> -	down_write(&amn->lock);
> -
> -	/* save the next list entry for later */
> -	head = bo->mn_list.next;
> -
> -	bo->mn = NULL;
> -	list_del_init(&bo->mn_list);
> -
> -	if (list_empty(head)) {
> -		struct amdgpu_mn_node *node;
> -
> -		node = container_of(head, struct amdgpu_mn_node, bos);
> -		interval_tree_remove(&node->it, &amn->objects);
> -		kfree(node);
> -	}
> -
> -	up_write(&amn->lock);
> -	mutex_unlock(&adev->mn_lock);
> +	mmu_range_notifier_remove(&bo->notifier);
> +	bo->notifier.mm = NULL;
>   }
>   
>   /* flags used by HMM internal, not related to CPU/GPU PTE flags */
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h
> index b8ed68943625c2..d73ab2947b22b2 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h
> @@ -39,12 +39,10 @@ enum amdgpu_mn_type {
>    * struct amdgpu_mn
>    *
>    * @adev: amdgpu device pointer
> - * @mm: process address space
>    * @type: type of MMU notifier
>    * @work: destruction work item
>    * @node: hash table node to find structure by adev and mn
>    * @lock: rw semaphore protecting the notifier nodes
> - * @objects: interval tree containing amdgpu_mn_nodes
>    * @mirror: HMM mirror function support
>    *
>    * Data for each amdgpu device and process address space.
> @@ -52,7 +50,6 @@ enum amdgpu_mn_type {
>   struct amdgpu_mn {
>   	/* constant after initialisation */
>   	struct amdgpu_device	*adev;
> -	struct mm_struct	*mm;
>   	enum amdgpu_mn_type	type;
>   
>   	/* only used on destruction */
> @@ -63,7 +60,6 @@ struct amdgpu_mn {
>   
>   	/* objects protected by lock */
>   	struct rw_semaphore	lock;
> -	struct rb_root_cached	objects;
>   
>   #ifdef CONFIG_HMM_MIRROR
>   	/* HMM mirror */
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
> index 658f4c9779b704..4b44ab850f94c2 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
> @@ -30,6 +30,9 @@
>   
>   #include <drm/amdgpu_drm.h>
>   #include "amdgpu.h"
> +#ifdef CONFIG_MMU_NOTIFIER
> +#include <linux/mmu_notifier.h>
> +#endif
>   
>   #define AMDGPU_BO_INVALID_OFFSET	LONG_MAX
>   #define AMDGPU_BO_MAX_PLACEMENTS	3
> @@ -100,10 +103,12 @@ struct amdgpu_bo {
>   	struct ttm_bo_kmap_obj		dma_buf_vmap;
>   	struct amdgpu_mn		*mn;
>   
> -	union {
> -		struct list_head	mn_list;
> -		struct list_head	shadow_list;
> -	};
> +
> +#ifdef CONFIG_MMU_NOTIFIER
> +	struct mmu_range_notifier	notifier;
> +#endif
> +
> +	struct list_head		shadow_list;
>   
>   	struct kgd_mem                  *kfd_bo;
>   };


WARNING: multiple messages have this Message-ID (diff)
From: "Koenig, Christian" <Christian.Koenig@amd.com>
To: Jason Gunthorpe <jgg@ziepe.ca>,
	"linux-mm@kvack.org" <linux-mm@kvack.org>,
	Jerome Glisse <jglisse@redhat.com>,
	Ralph Campbell <rcampbell@nvidia.com>,
	John Hubbard <jhubbard@nvidia.com>,
	"Kuehling, Felix" <Felix.Kuehling@amd.com>
Cc: Juergen Gross <jgross@suse.com>,
	Mike Marciniszyn <mike.marciniszyn@intel.com>,
	Stefano Stabellini <sstabellini@kernel.org>,
	Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>,
	"linux-rdma@vger.kernel.org" <linux-rdma@vger.kernel.org>,
	"nouveau@lists.freedesktop.org" <nouveau@lists.freedesktop.org>,
	Dennis Dalessandro <dennis.dalessandro@intel.com>,
	"amd-gfx@lists.freedesktop.org" <amd-gfx@lists.freedesktop.org>,
	Christoph Hellwig <hch@infradead.org>,
	Jason Gunthorpe <jgg@mellanox.com>,
	"dri-devel@lists.freedesktop.org"
	<dri-devel@lists.freedesktop.org>,
	"Deucher, Alexander" <Alexander.Deucher@amd.com>,
	"xen-devel@lists.xenproject.org" <xen-devel@lists.xenproject.org>,
	Boris Ostrovsky <boris.ostrovsky@oracle.com>,
	Petr Cvek <petrcvekcz@gmail.com>, Ben Skeggs <bskeggs@redhat.com>
Subject: Re: [PATCH v2 13/15] drm/amdgpu: Use mmu_range_insert instead of hmm_mirror
Date: Tue, 29 Oct 2019 07:51:30 +0000	[thread overview]
Message-ID: <bc44f331-5448-ddc0-ecc3-d0ccb92e11a4@amd.com> (raw)
In-Reply-To: <20191028201032.6352-14-jgg@ziepe.ca>

Am 28.10.19 um 21:10 schrieb Jason Gunthorpe:
> From: Jason Gunthorpe <jgg@mellanox.com>
>
> Remove the interval tree in the driver and rely on the tree maintained by
> the mmu_notifier for delivering mmu_notifier invalidation callbacks.
>
> For some reason amdgpu has a very complicated arrangement where it tries
> to prevent duplicate entries in the interval_tree, this is not necessary,
> each amdgpu_bo can be its own stand alone entry. interval_tree already
> allows duplicates and overlaps in the tree.
>
> Also, there is no need to remove entries upon a release callback, the
> mmu_range API safely allows objects to remain registered beyond the
> lifetime of the mm. The driver only has to stop touching the pages during
> release.
>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Christian König <christian.koenig@amd.com>
> Cc: David (ChunMing) Zhou <David1.Zhou@amd.com>
> Cc: amd-gfx@lists.freedesktop.org
> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu.h           |   2 +
>   .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c  |   5 +-
>   drivers/gpu/drm/amd/amdgpu/amdgpu_device.c    |   1 +
>   drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c        | 341 ++++--------------
>   drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h        |   4 -
>   drivers/gpu/drm/amd/amdgpu/amdgpu_object.h    |  13 +-
>   6 files changed, 84 insertions(+), 282 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> index bd37df5dd6d048..60591a5d420021 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> @@ -1006,6 +1006,8 @@ struct amdgpu_device {
>   	struct mutex  lock_reset;
>   	struct amdgpu_doorbell_index doorbell_index;
>   
> +	struct mutex			notifier_lock;
> +
>   	int asic_reset_res;
>   	struct work_struct		xgmi_reset_work;
>   
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
> index 6d021ecc8d598f..47700302a08b7f 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
> @@ -481,8 +481,7 @@ static void remove_kgd_mem_from_kfd_bo_list(struct kgd_mem *mem,
>    *
>    * Returns 0 for success, negative errno for errors.
>    */
> -static int init_user_pages(struct kgd_mem *mem, struct mm_struct *mm,
> -			   uint64_t user_addr)
> +static int init_user_pages(struct kgd_mem *mem, uint64_t user_addr)
>   {
>   	struct amdkfd_process_info *process_info = mem->process_info;
>   	struct amdgpu_bo *bo = mem->bo;
> @@ -1195,7 +1194,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
>   	add_kgd_mem_to_kfd_bo_list(*mem, avm->process_info, user_addr);
>   
>   	if (user_addr) {
> -		ret = init_user_pages(*mem, current->mm, user_addr);
> +		ret = init_user_pages(*mem, user_addr);
>   		if (ret)
>   			goto allocate_init_user_pages_failed;
>   	}
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> index 5a1939dbd4e3e6..38f97998aaddb2 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> @@ -2633,6 +2633,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
>   	mutex_init(&adev->virt.vf_errors.lock);
>   	hash_init(adev->mn_hash);
>   	mutex_init(&adev->lock_reset);
> +	mutex_init(&adev->notifier_lock);
>   	mutex_init(&adev->virt.dpm_mutex);
>   	mutex_init(&adev->psp.mutex);
>   
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
> index 31d4deb5d29484..4ffd7b90f4d907 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
> @@ -50,66 +50,6 @@
>   #include "amdgpu.h"
>   #include "amdgpu_amdkfd.h"
>   
> -/**
> - * struct amdgpu_mn_node
> - *
> - * @it: interval node defining start-last of the affected address range
> - * @bos: list of all BOs in the affected address range
> - *
> - * Manages all BOs which are affected of a certain range of address space.
> - */
> -struct amdgpu_mn_node {
> -	struct interval_tree_node	it;
> -	struct list_head		bos;
> -};
> -
> -/**
> - * amdgpu_mn_destroy - destroy the HMM mirror
> - *
> - * @work: previously sheduled work item
> - *
> - * Lazy destroys the notifier from a work item
> - */
> -static void amdgpu_mn_destroy(struct work_struct *work)
> -{
> -	struct amdgpu_mn *amn = container_of(work, struct amdgpu_mn, work);
> -	struct amdgpu_device *adev = amn->adev;
> -	struct amdgpu_mn_node *node, *next_node;
> -	struct amdgpu_bo *bo, *next_bo;
> -
> -	mutex_lock(&adev->mn_lock);
> -	down_write(&amn->lock);
> -	hash_del(&amn->node);
> -	rbtree_postorder_for_each_entry_safe(node, next_node,
> -					     &amn->objects.rb_root, it.rb) {
> -		list_for_each_entry_safe(bo, next_bo, &node->bos, mn_list) {
> -			bo->mn = NULL;
> -			list_del_init(&bo->mn_list);
> -		}
> -		kfree(node);
> -	}
> -	up_write(&amn->lock);
> -	mutex_unlock(&adev->mn_lock);
> -
> -	hmm_mirror_unregister(&amn->mirror);
> -	kfree(amn);
> -}
> -
> -/**
> - * amdgpu_hmm_mirror_release - callback to notify about mm destruction
> - *
> - * @mirror: the HMM mirror (mm) this callback is about
> - *
> - * Shedule a work item to lazy destroy HMM mirror.
> - */
> -static void amdgpu_hmm_mirror_release(struct hmm_mirror *mirror)
> -{
> -	struct amdgpu_mn *amn = container_of(mirror, struct amdgpu_mn, mirror);
> -
> -	INIT_WORK(&amn->work, amdgpu_mn_destroy);
> -	schedule_work(&amn->work);
> -}
> -
>   /**
>    * amdgpu_mn_lock - take the write side lock for this notifier
>    *
> @@ -133,157 +73,86 @@ void amdgpu_mn_unlock(struct amdgpu_mn *mn)
>   }
>   
>   /**
> - * amdgpu_mn_read_lock - take the read side lock for this notifier
> - *
> - * @amn: our notifier
> - */
> -static int amdgpu_mn_read_lock(struct amdgpu_mn *amn, bool blockable)
> -{
> -	if (blockable)
> -		down_read(&amn->lock);
> -	else if (!down_read_trylock(&amn->lock))
> -		return -EAGAIN;
> -
> -	return 0;
> -}
> -
> -/**
> - * amdgpu_mn_read_unlock - drop the read side lock for this notifier
> - *
> - * @amn: our notifier
> - */
> -static void amdgpu_mn_read_unlock(struct amdgpu_mn *amn)
> -{
> -	up_read(&amn->lock);
> -}
> -
> -/**
> - * amdgpu_mn_invalidate_node - unmap all BOs of a node
> + * amdgpu_mn_invalidate_gfx - callback to notify about mm change
>    *
> - * @node: the node with the BOs to unmap
> - * @start: start of address range affected
> - * @end: end of address range affected
> + * @mrn: the range (mm) is about to update
> + * @range: details on the invalidation
>    *
>    * Block for operations on BOs to finish and mark pages as accessed and
>    * potentially dirty.
>    */
> -static void amdgpu_mn_invalidate_node(struct amdgpu_mn_node *node,
> -				      unsigned long start,
> -				      unsigned long end)
> +static bool amdgpu_mn_invalidate_gfx(struct mmu_range_notifier *mrn,
> +				     const struct mmu_notifier_range *range)
>   {
> -	struct amdgpu_bo *bo;
> +	struct amdgpu_bo *bo = container_of(mrn, struct amdgpu_bo, notifier);
> +	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
>   	long r;
>   
> -	list_for_each_entry(bo, &node->bos, mn_list) {
> -
> -		if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, start, end))
> -			continue;
> -
> -		r = dma_resv_wait_timeout_rcu(bo->tbo.base.resv,
> -			true, false, MAX_SCHEDULE_TIMEOUT);
> -		if (r <= 0)
> -			DRM_ERROR("(%ld) failed to wait for user bo\n", r);
> -	}
> +	/* FIXME: Is this necessary? */

Most likely not.

Christian.

> +	if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, range->start,
> +					  range->end))
> +		return true;
> +
> +	if (!mmu_notifier_range_blockable(range))
> +		return false;
> +
> +	mutex_lock(&adev->notifier_lock);
> +	r = dma_resv_wait_timeout_rcu(bo->tbo.base.resv, true, false,
> +				      MAX_SCHEDULE_TIMEOUT);
> +	mutex_unlock(&adev->notifier_lock);
> +	if (r <= 0)
> +		DRM_ERROR("(%ld) failed to wait for user bo\n", r);
> +	return true;
>   }
>   
> +static const struct mmu_range_notifier_ops amdgpu_mn_gfx_ops = {
> +	.invalidate = amdgpu_mn_invalidate_gfx,
> +};
> +
>   /**
> - * amdgpu_mn_sync_pagetables_gfx - callback to notify about mm change
> + * amdgpu_mn_invalidate_hsa - callback to notify about mm change
>    *
> - * @mirror: the hmm_mirror (mm) is about to update
> - * @update: the update start, end address
> + * @mrn: the range (mm) is about to update
> + * @range: details on the invalidation
>    *
> - * Block for operations on BOs to finish and mark pages as accessed and
> - * potentially dirty.
> + * We temporarily evict the BO attached to this range. This necessitates
> + * evicting all user-mode queues of the process.
>    */
> -static int
> -amdgpu_mn_sync_pagetables_gfx(struct hmm_mirror *mirror,
> -			      const struct mmu_notifier_range *update)
> +static bool amdgpu_mn_invalidate_hsa(struct mmu_range_notifier *mrn,
> +				     const struct mmu_notifier_range *range)
>   {
> -	struct amdgpu_mn *amn = container_of(mirror, struct amdgpu_mn, mirror);
> -	unsigned long start = update->start;
> -	unsigned long end = update->end;
> -	bool blockable = mmu_notifier_range_blockable(update);
> -	struct interval_tree_node *it;
> -
> -	/* notification is exclusive, but interval is inclusive */
> -	end -= 1;
> -
> -	/* TODO we should be able to split locking for interval tree and
> -	 * amdgpu_mn_invalidate_node
> -	 */
> -	if (amdgpu_mn_read_lock(amn, blockable))
> -		return -EAGAIN;
> -
> -	it = interval_tree_iter_first(&amn->objects, start, end);
> -	while (it) {
> -		struct amdgpu_mn_node *node;
> -
> -		if (!blockable) {
> -			amdgpu_mn_read_unlock(amn);
> -			return -EAGAIN;
> -		}
> +	struct amdgpu_bo *bo = container_of(mrn, struct amdgpu_bo, notifier);
> +	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
>   
> -		node = container_of(it, struct amdgpu_mn_node, it);
> -		it = interval_tree_iter_next(it, start, end);
> +	/* FIXME: Is this necessary? */
> +	if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, range->start,
> +					  range->end))
> +		return true;
>   
> -		amdgpu_mn_invalidate_node(node, start, end);
> -	}
> +	if (!mmu_notifier_range_blockable(range))
> +		return false;
>   
> -	amdgpu_mn_read_unlock(amn);
> +	mutex_lock(&adev->notifier_lock);
> +	amdgpu_amdkfd_evict_userptr(bo->kfd_bo, bo->notifier.mm);
> +	mutex_unlock(&adev->notifier_lock);
>   
> -	return 0;
> +	return true;
>   }
>   
> -/**
> - * amdgpu_mn_sync_pagetables_hsa - callback to notify about mm change
> - *
> - * @mirror: the hmm_mirror (mm) is about to update
> - * @update: the update start, end address
> - *
> - * We temporarily evict all BOs between start and end. This
> - * necessitates evicting all user-mode queues of the process. The BOs
> - * are restorted in amdgpu_mn_invalidate_range_end_hsa.
> - */
> -static int
> -amdgpu_mn_sync_pagetables_hsa(struct hmm_mirror *mirror,
> -			      const struct mmu_notifier_range *update)
> +static const struct mmu_range_notifier_ops amdgpu_mn_hsa_ops = {
> +	.invalidate = amdgpu_mn_invalidate_hsa,
> +};
> +
> +static int amdgpu_mn_sync_pagetables(struct hmm_mirror *mirror,
> +				     const struct mmu_notifier_range *update)
>   {
>   	struct amdgpu_mn *amn = container_of(mirror, struct amdgpu_mn, mirror);
> -	unsigned long start = update->start;
> -	unsigned long end = update->end;
> -	bool blockable = mmu_notifier_range_blockable(update);
> -	struct interval_tree_node *it;
>   
> -	/* notification is exclusive, but interval is inclusive */
> -	end -= 1;
> -
> -	if (amdgpu_mn_read_lock(amn, blockable))
> -		return -EAGAIN;
> -
> -	it = interval_tree_iter_first(&amn->objects, start, end);
> -	while (it) {
> -		struct amdgpu_mn_node *node;
> -		struct amdgpu_bo *bo;
> -
> -		if (!blockable) {
> -			amdgpu_mn_read_unlock(amn);
> -			return -EAGAIN;
> -		}
> -
> -		node = container_of(it, struct amdgpu_mn_node, it);
> -		it = interval_tree_iter_next(it, start, end);
> -
> -		list_for_each_entry(bo, &node->bos, mn_list) {
> -			struct kgd_mem *mem = bo->kfd_bo;
> -
> -			if (amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm,
> -							 start, end))
> -				amdgpu_amdkfd_evict_userptr(mem, amn->mm);
> -		}
> -	}
> -
> -	amdgpu_mn_read_unlock(amn);
> +	if (!mmu_notifier_range_blockable(update))
> +		return false;
>   
> +	down_read(&amn->lock);
> +	up_read(&amn->lock);
>   	return 0;
>   }
>   
> @@ -295,12 +164,10 @@ amdgpu_mn_sync_pagetables_hsa(struct hmm_mirror *mirror,
>   
>   static struct hmm_mirror_ops amdgpu_hmm_mirror_ops[] = {
>   	[AMDGPU_MN_TYPE_GFX] = {
> -		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables_gfx,
> -		.release = amdgpu_hmm_mirror_release
> +		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables,
>   	},
>   	[AMDGPU_MN_TYPE_HSA] = {
> -		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables_hsa,
> -		.release = amdgpu_hmm_mirror_release
> +		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables,
>   	},
>   };
>   
> @@ -327,7 +194,8 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev,
>   	}
>   
>   	hash_for_each_possible(adev->mn_hash, amn, node, key)
> -		if (AMDGPU_MN_KEY(amn->mm, amn->type) == key)
> +		if (AMDGPU_MN_KEY(amn->mirror.hmm->mmu_notifier.mm,
> +				  amn->type) == key)
>   			goto release_locks;
>   
>   	amn = kzalloc(sizeof(*amn), GFP_KERNEL);
> @@ -337,10 +205,8 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev,
>   	}
>   
>   	amn->adev = adev;
> -	amn->mm = mm;
>   	init_rwsem(&amn->lock);
>   	amn->type = type;
> -	amn->objects = RB_ROOT_CACHED;
>   
>   	amn->mirror.ops = &amdgpu_hmm_mirror_ops[type];
>   	r = hmm_mirror_register(&amn->mirror, mm);
> @@ -369,100 +235,33 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev,
>    * @bo: amdgpu buffer object
>    * @addr: userptr addr we should monitor
>    *
> - * Registers an HMM mirror for the given BO at the specified address.
> + * Registers a mmu_notifier for the given BO at the specified address.
>    * Returns 0 on success, -ERRNO if anything goes wrong.
>    */
>   int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr)
>   {
> -	unsigned long end = addr + amdgpu_bo_size(bo) - 1;
> -	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
> -	enum amdgpu_mn_type type =
> -		bo->kfd_bo ? AMDGPU_MN_TYPE_HSA : AMDGPU_MN_TYPE_GFX;
> -	struct amdgpu_mn *amn;
> -	struct amdgpu_mn_node *node = NULL, *new_node;
> -	struct list_head bos;
> -	struct interval_tree_node *it;
> -
> -	amn = amdgpu_mn_get(adev, type);
> -	if (IS_ERR(amn))
> -		return PTR_ERR(amn);
> -
> -	new_node = kmalloc(sizeof(*new_node), GFP_KERNEL);
> -	if (!new_node)
> -		return -ENOMEM;
> -
> -	INIT_LIST_HEAD(&bos);
> -
> -	down_write(&amn->lock);
> -
> -	while ((it = interval_tree_iter_first(&amn->objects, addr, end))) {
> -		kfree(node);
> -		node = container_of(it, struct amdgpu_mn_node, it);
> -		interval_tree_remove(&node->it, &amn->objects);
> -		addr = min(it->start, addr);
> -		end = max(it->last, end);
> -		list_splice(&node->bos, &bos);
> -	}
> -
> -	if (!node)
> -		node = new_node;
> +	if (bo->kfd_bo)
> +		bo->notifier.ops = &amdgpu_mn_hsa_ops;
>   	else
> -		kfree(new_node);
> -
> -	bo->mn = amn;
> -
> -	node->it.start = addr;
> -	node->it.last = end;
> -	INIT_LIST_HEAD(&node->bos);
> -	list_splice(&bos, &node->bos);
> -	list_add(&bo->mn_list, &node->bos);
> +		bo->notifier.ops = &amdgpu_mn_gfx_ops;
>   
> -	interval_tree_insert(&node->it, &amn->objects);
> -
> -	up_write(&amn->lock);
> -
> -	return 0;
> +	return mmu_range_notifier_insert(&bo->notifier, addr,
> +					 amdgpu_bo_size(bo), current->mm);
>   }
>   
>   /**
> - * amdgpu_mn_unregister - unregister a BO for HMM mirror updates
> + * amdgpu_mn_unregister - unregister a BO for notifier updates
>    *
>    * @bo: amdgpu buffer object
>    *
> - * Remove any registration of HMM mirror updates from the buffer object.
> + * Remove any registration of mmu notifier updates from the buffer object.
>    */
>   void amdgpu_mn_unregister(struct amdgpu_bo *bo)
>   {
> -	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
> -	struct amdgpu_mn *amn;
> -	struct list_head *head;
> -
> -	mutex_lock(&adev->mn_lock);
> -
> -	amn = bo->mn;
> -	if (amn == NULL) {
> -		mutex_unlock(&adev->mn_lock);
> +	if (!bo->notifier.mm)
>   		return;
> -	}
> -
> -	down_write(&amn->lock);
> -
> -	/* save the next list entry for later */
> -	head = bo->mn_list.next;
> -
> -	bo->mn = NULL;
> -	list_del_init(&bo->mn_list);
> -
> -	if (list_empty(head)) {
> -		struct amdgpu_mn_node *node;
> -
> -		node = container_of(head, struct amdgpu_mn_node, bos);
> -		interval_tree_remove(&node->it, &amn->objects);
> -		kfree(node);
> -	}
> -
> -	up_write(&amn->lock);
> -	mutex_unlock(&adev->mn_lock);
> +	mmu_range_notifier_remove(&bo->notifier);
> +	bo->notifier.mm = NULL;
>   }
>   
>   /* flags used by HMM internal, not related to CPU/GPU PTE flags */
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h
> index b8ed68943625c2..d73ab2947b22b2 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h
> @@ -39,12 +39,10 @@ enum amdgpu_mn_type {
>    * struct amdgpu_mn
>    *
>    * @adev: amdgpu device pointer
> - * @mm: process address space
>    * @type: type of MMU notifier
>    * @work: destruction work item
>    * @node: hash table node to find structure by adev and mn
>    * @lock: rw semaphore protecting the notifier nodes
> - * @objects: interval tree containing amdgpu_mn_nodes
>    * @mirror: HMM mirror function support
>    *
>    * Data for each amdgpu device and process address space.
> @@ -52,7 +50,6 @@ enum amdgpu_mn_type {
>   struct amdgpu_mn {
>   	/* constant after initialisation */
>   	struct amdgpu_device	*adev;
> -	struct mm_struct	*mm;
>   	enum amdgpu_mn_type	type;
>   
>   	/* only used on destruction */
> @@ -63,7 +60,6 @@ struct amdgpu_mn {
>   
>   	/* objects protected by lock */
>   	struct rw_semaphore	lock;
> -	struct rb_root_cached	objects;
>   
>   #ifdef CONFIG_HMM_MIRROR
>   	/* HMM mirror */
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
> index 658f4c9779b704..4b44ab850f94c2 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
> @@ -30,6 +30,9 @@
>   
>   #include <drm/amdgpu_drm.h>
>   #include "amdgpu.h"
> +#ifdef CONFIG_MMU_NOTIFIER
> +#include <linux/mmu_notifier.h>
> +#endif
>   
>   #define AMDGPU_BO_INVALID_OFFSET	LONG_MAX
>   #define AMDGPU_BO_MAX_PLACEMENTS	3
> @@ -100,10 +103,12 @@ struct amdgpu_bo {
>   	struct ttm_bo_kmap_obj		dma_buf_vmap;
>   	struct amdgpu_mn		*mn;
>   
> -	union {
> -		struct list_head	mn_list;
> -		struct list_head	shadow_list;
> -	};
> +
> +#ifdef CONFIG_MMU_NOTIFIER
> +	struct mmu_range_notifier	notifier;
> +#endif
> +
> +	struct list_head		shadow_list;
>   
>   	struct kgd_mem                  *kfd_bo;
>   };

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

WARNING: multiple messages have this Message-ID (diff)
From: "Koenig, Christian" <Christian.Koenig@amd.com>
To: Jason Gunthorpe <jgg@ziepe.ca>,
	"linux-mm@kvack.org" <linux-mm@kvack.org>,
	 Jerome Glisse <jglisse@redhat.com>,
	Ralph Campbell <rcampbell@nvidia.com>,
	 John Hubbard <jhubbard@nvidia.com>,
	"Kuehling, Felix" <Felix.Kuehling@amd.com>
Cc: Juergen Gross <jgross@suse.com>,
	Mike Marciniszyn <mike.marciniszyn@intel.com>,
	Stefano Stabellini <sstabellini@kernel.org>,
	Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>,
	"linux-rdma@vger.kernel.org" <linux-rdma@vger.kernel.org>,
	"nouveau@lists.freedesktop.org" <nouveau@lists.freedesktop.org>,
	Dennis Dalessandro <dennis.dalessandro@intel.com>,
	"amd-gfx@lists.freedesktop.org" <amd-gfx@lists.freedesktop.org>,
	Christoph Hellwig <hch@infradead.org>,
	Jason Gunthorpe <jgg@mellanox.com>,
	"dri-devel@lists.freedesktop.org"
	<dri-devel@lists.freedesktop.org>,
	"Deucher, Alexander" <Alexander.Deucher@amd.com>,
	"xen-devel@lists.xenproject.org" <xen-devel@lists.xenproject.org>,
	Boris Ostrovsky <boris.ostrovsky@oracle.com>,
	Petr Cvek <petrcvekcz@gmail.com>, Ben Skeggs <bskeggs@redhat.com>
Subject: Re: [PATCH v2 13/15] drm/amdgpu: Use mmu_range_insert instead of hmm_mirror
Date: Tue, 29 Oct 2019 07:51:30 +0000	[thread overview]
Message-ID: <bc44f331-5448-ddc0-ecc3-d0ccb92e11a4@amd.com> (raw)
Message-ID: <20191029075130.Oh6sCjO74j6GN9kOqL80mW1Pq-tkbOhZ7pnic9v-FyE@z> (raw)
In-Reply-To: <20191028201032.6352-14-jgg@ziepe.ca>

Am 28.10.19 um 21:10 schrieb Jason Gunthorpe:
> From: Jason Gunthorpe <jgg@mellanox.com>
>
> Remove the interval tree in the driver and rely on the tree maintained by
> the mmu_notifier for delivering mmu_notifier invalidation callbacks.
>
> For some reason amdgpu has a very complicated arrangement where it tries
> to prevent duplicate entries in the interval_tree, this is not necessary,
> each amdgpu_bo can be its own stand alone entry. interval_tree already
> allows duplicates and overlaps in the tree.
>
> Also, there is no need to remove entries upon a release callback, the
> mmu_range API safely allows objects to remain registered beyond the
> lifetime of the mm. The driver only has to stop touching the pages during
> release.
>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Christian König <christian.koenig@amd.com>
> Cc: David (ChunMing) Zhou <David1.Zhou@amd.com>
> Cc: amd-gfx@lists.freedesktop.org
> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu.h           |   2 +
>   .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c  |   5 +-
>   drivers/gpu/drm/amd/amdgpu/amdgpu_device.c    |   1 +
>   drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c        | 341 ++++--------------
>   drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h        |   4 -
>   drivers/gpu/drm/amd/amdgpu/amdgpu_object.h    |  13 +-
>   6 files changed, 84 insertions(+), 282 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> index bd37df5dd6d048..60591a5d420021 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> @@ -1006,6 +1006,8 @@ struct amdgpu_device {
>   	struct mutex  lock_reset;
>   	struct amdgpu_doorbell_index doorbell_index;
>   
> +	struct mutex			notifier_lock;
> +
>   	int asic_reset_res;
>   	struct work_struct		xgmi_reset_work;
>   
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
> index 6d021ecc8d598f..47700302a08b7f 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
> @@ -481,8 +481,7 @@ static void remove_kgd_mem_from_kfd_bo_list(struct kgd_mem *mem,
>    *
>    * Returns 0 for success, negative errno for errors.
>    */
> -static int init_user_pages(struct kgd_mem *mem, struct mm_struct *mm,
> -			   uint64_t user_addr)
> +static int init_user_pages(struct kgd_mem *mem, uint64_t user_addr)
>   {
>   	struct amdkfd_process_info *process_info = mem->process_info;
>   	struct amdgpu_bo *bo = mem->bo;
> @@ -1195,7 +1194,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
>   	add_kgd_mem_to_kfd_bo_list(*mem, avm->process_info, user_addr);
>   
>   	if (user_addr) {
> -		ret = init_user_pages(*mem, current->mm, user_addr);
> +		ret = init_user_pages(*mem, user_addr);
>   		if (ret)
>   			goto allocate_init_user_pages_failed;
>   	}
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> index 5a1939dbd4e3e6..38f97998aaddb2 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> @@ -2633,6 +2633,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
>   	mutex_init(&adev->virt.vf_errors.lock);
>   	hash_init(adev->mn_hash);
>   	mutex_init(&adev->lock_reset);
> +	mutex_init(&adev->notifier_lock);
>   	mutex_init(&adev->virt.dpm_mutex);
>   	mutex_init(&adev->psp.mutex);
>   
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
> index 31d4deb5d29484..4ffd7b90f4d907 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
> @@ -50,66 +50,6 @@
>   #include "amdgpu.h"
>   #include "amdgpu_amdkfd.h"
>   
> -/**
> - * struct amdgpu_mn_node
> - *
> - * @it: interval node defining start-last of the affected address range
> - * @bos: list of all BOs in the affected address range
> - *
> - * Manages all BOs which are affected of a certain range of address space.
> - */
> -struct amdgpu_mn_node {
> -	struct interval_tree_node	it;
> -	struct list_head		bos;
> -};
> -
> -/**
> - * amdgpu_mn_destroy - destroy the HMM mirror
> - *
> - * @work: previously sheduled work item
> - *
> - * Lazy destroys the notifier from a work item
> - */
> -static void amdgpu_mn_destroy(struct work_struct *work)
> -{
> -	struct amdgpu_mn *amn = container_of(work, struct amdgpu_mn, work);
> -	struct amdgpu_device *adev = amn->adev;
> -	struct amdgpu_mn_node *node, *next_node;
> -	struct amdgpu_bo *bo, *next_bo;
> -
> -	mutex_lock(&adev->mn_lock);
> -	down_write(&amn->lock);
> -	hash_del(&amn->node);
> -	rbtree_postorder_for_each_entry_safe(node, next_node,
> -					     &amn->objects.rb_root, it.rb) {
> -		list_for_each_entry_safe(bo, next_bo, &node->bos, mn_list) {
> -			bo->mn = NULL;
> -			list_del_init(&bo->mn_list);
> -		}
> -		kfree(node);
> -	}
> -	up_write(&amn->lock);
> -	mutex_unlock(&adev->mn_lock);
> -
> -	hmm_mirror_unregister(&amn->mirror);
> -	kfree(amn);
> -}
> -
> -/**
> - * amdgpu_hmm_mirror_release - callback to notify about mm destruction
> - *
> - * @mirror: the HMM mirror (mm) this callback is about
> - *
> - * Shedule a work item to lazy destroy HMM mirror.
> - */
> -static void amdgpu_hmm_mirror_release(struct hmm_mirror *mirror)
> -{
> -	struct amdgpu_mn *amn = container_of(mirror, struct amdgpu_mn, mirror);
> -
> -	INIT_WORK(&amn->work, amdgpu_mn_destroy);
> -	schedule_work(&amn->work);
> -}
> -
>   /**
>    * amdgpu_mn_lock - take the write side lock for this notifier
>    *
> @@ -133,157 +73,86 @@ void amdgpu_mn_unlock(struct amdgpu_mn *mn)
>   }
>   
>   /**
> - * amdgpu_mn_read_lock - take the read side lock for this notifier
> - *
> - * @amn: our notifier
> - */
> -static int amdgpu_mn_read_lock(struct amdgpu_mn *amn, bool blockable)
> -{
> -	if (blockable)
> -		down_read(&amn->lock);
> -	else if (!down_read_trylock(&amn->lock))
> -		return -EAGAIN;
> -
> -	return 0;
> -}
> -
> -/**
> - * amdgpu_mn_read_unlock - drop the read side lock for this notifier
> - *
> - * @amn: our notifier
> - */
> -static void amdgpu_mn_read_unlock(struct amdgpu_mn *amn)
> -{
> -	up_read(&amn->lock);
> -}
> -
> -/**
> - * amdgpu_mn_invalidate_node - unmap all BOs of a node
> + * amdgpu_mn_invalidate_gfx - callback to notify about mm change
>    *
> - * @node: the node with the BOs to unmap
> - * @start: start of address range affected
> - * @end: end of address range affected
> + * @mrn: the range (mm) is about to update
> + * @range: details on the invalidation
>    *
>    * Block for operations on BOs to finish and mark pages as accessed and
>    * potentially dirty.
>    */
> -static void amdgpu_mn_invalidate_node(struct amdgpu_mn_node *node,
> -				      unsigned long start,
> -				      unsigned long end)
> +static bool amdgpu_mn_invalidate_gfx(struct mmu_range_notifier *mrn,
> +				     const struct mmu_notifier_range *range)
>   {
> -	struct amdgpu_bo *bo;
> +	struct amdgpu_bo *bo = container_of(mrn, struct amdgpu_bo, notifier);
> +	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
>   	long r;
>   
> -	list_for_each_entry(bo, &node->bos, mn_list) {
> -
> -		if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, start, end))
> -			continue;
> -
> -		r = dma_resv_wait_timeout_rcu(bo->tbo.base.resv,
> -			true, false, MAX_SCHEDULE_TIMEOUT);
> -		if (r <= 0)
> -			DRM_ERROR("(%ld) failed to wait for user bo\n", r);
> -	}
> +	/* FIXME: Is this necessary? */

Most likely not.

Christian.

> +	if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, range->start,
> +					  range->end))
> +		return true;
> +
> +	if (!mmu_notifier_range_blockable(range))
> +		return false;
> +
> +	mutex_lock(&adev->notifier_lock);
> +	r = dma_resv_wait_timeout_rcu(bo->tbo.base.resv, true, false,
> +				      MAX_SCHEDULE_TIMEOUT);
> +	mutex_unlock(&adev->notifier_lock);
> +	if (r <= 0)
> +		DRM_ERROR("(%ld) failed to wait for user bo\n", r);
> +	return true;
>   }
>   
> +static const struct mmu_range_notifier_ops amdgpu_mn_gfx_ops = {
> +	.invalidate = amdgpu_mn_invalidate_gfx,
> +};
> +
>   /**
> - * amdgpu_mn_sync_pagetables_gfx - callback to notify about mm change
> + * amdgpu_mn_invalidate_hsa - callback to notify about mm change
>    *
> - * @mirror: the hmm_mirror (mm) is about to update
> - * @update: the update start, end address
> + * @mrn: the range (mm) is about to update
> + * @range: details on the invalidation
>    *
> - * Block for operations on BOs to finish and mark pages as accessed and
> - * potentially dirty.
> + * We temporarily evict the BO attached to this range. This necessitates
> + * evicting all user-mode queues of the process.
>    */
> -static int
> -amdgpu_mn_sync_pagetables_gfx(struct hmm_mirror *mirror,
> -			      const struct mmu_notifier_range *update)
> +static bool amdgpu_mn_invalidate_hsa(struct mmu_range_notifier *mrn,
> +				     const struct mmu_notifier_range *range)
>   {
> -	struct amdgpu_mn *amn = container_of(mirror, struct amdgpu_mn, mirror);
> -	unsigned long start = update->start;
> -	unsigned long end = update->end;
> -	bool blockable = mmu_notifier_range_blockable(update);
> -	struct interval_tree_node *it;
> -
> -	/* notification is exclusive, but interval is inclusive */
> -	end -= 1;
> -
> -	/* TODO we should be able to split locking for interval tree and
> -	 * amdgpu_mn_invalidate_node
> -	 */
> -	if (amdgpu_mn_read_lock(amn, blockable))
> -		return -EAGAIN;
> -
> -	it = interval_tree_iter_first(&amn->objects, start, end);
> -	while (it) {
> -		struct amdgpu_mn_node *node;
> -
> -		if (!blockable) {
> -			amdgpu_mn_read_unlock(amn);
> -			return -EAGAIN;
> -		}
> +	struct amdgpu_bo *bo = container_of(mrn, struct amdgpu_bo, notifier);
> +	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
>   
> -		node = container_of(it, struct amdgpu_mn_node, it);
> -		it = interval_tree_iter_next(it, start, end);
> +	/* FIXME: Is this necessary? */
> +	if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, range->start,
> +					  range->end))
> +		return true;
>   
> -		amdgpu_mn_invalidate_node(node, start, end);
> -	}
> +	if (!mmu_notifier_range_blockable(range))
> +		return false;
>   
> -	amdgpu_mn_read_unlock(amn);
> +	mutex_lock(&adev->notifier_lock);
> +	amdgpu_amdkfd_evict_userptr(bo->kfd_bo, bo->notifier.mm);
> +	mutex_unlock(&adev->notifier_lock);
>   
> -	return 0;
> +	return true;
>   }
>   
> -/**
> - * amdgpu_mn_sync_pagetables_hsa - callback to notify about mm change
> - *
> - * @mirror: the hmm_mirror (mm) is about to update
> - * @update: the update start, end address
> - *
> - * We temporarily evict all BOs between start and end. This
> - * necessitates evicting all user-mode queues of the process. The BOs
> - * are restorted in amdgpu_mn_invalidate_range_end_hsa.
> - */
> -static int
> -amdgpu_mn_sync_pagetables_hsa(struct hmm_mirror *mirror,
> -			      const struct mmu_notifier_range *update)
> +static const struct mmu_range_notifier_ops amdgpu_mn_hsa_ops = {
> +	.invalidate = amdgpu_mn_invalidate_hsa,
> +};
> +
> +static int amdgpu_mn_sync_pagetables(struct hmm_mirror *mirror,
> +				     const struct mmu_notifier_range *update)
>   {
>   	struct amdgpu_mn *amn = container_of(mirror, struct amdgpu_mn, mirror);
> -	unsigned long start = update->start;
> -	unsigned long end = update->end;
> -	bool blockable = mmu_notifier_range_blockable(update);
> -	struct interval_tree_node *it;
>   
> -	/* notification is exclusive, but interval is inclusive */
> -	end -= 1;
> -
> -	if (amdgpu_mn_read_lock(amn, blockable))
> -		return -EAGAIN;
> -
> -	it = interval_tree_iter_first(&amn->objects, start, end);
> -	while (it) {
> -		struct amdgpu_mn_node *node;
> -		struct amdgpu_bo *bo;
> -
> -		if (!blockable) {
> -			amdgpu_mn_read_unlock(amn);
> -			return -EAGAIN;
> -		}
> -
> -		node = container_of(it, struct amdgpu_mn_node, it);
> -		it = interval_tree_iter_next(it, start, end);
> -
> -		list_for_each_entry(bo, &node->bos, mn_list) {
> -			struct kgd_mem *mem = bo->kfd_bo;
> -
> -			if (amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm,
> -							 start, end))
> -				amdgpu_amdkfd_evict_userptr(mem, amn->mm);
> -		}
> -	}
> -
> -	amdgpu_mn_read_unlock(amn);
> +	if (!mmu_notifier_range_blockable(update))
> +		return false;
>   
> +	down_read(&amn->lock);
> +	up_read(&amn->lock);
>   	return 0;
>   }
>   
> @@ -295,12 +164,10 @@ amdgpu_mn_sync_pagetables_hsa(struct hmm_mirror *mirror,
>   
>   static struct hmm_mirror_ops amdgpu_hmm_mirror_ops[] = {
>   	[AMDGPU_MN_TYPE_GFX] = {
> -		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables_gfx,
> -		.release = amdgpu_hmm_mirror_release
> +		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables,
>   	},
>   	[AMDGPU_MN_TYPE_HSA] = {
> -		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables_hsa,
> -		.release = amdgpu_hmm_mirror_release
> +		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables,
>   	},
>   };
>   
> @@ -327,7 +194,8 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev,
>   	}
>   
>   	hash_for_each_possible(adev->mn_hash, amn, node, key)
> -		if (AMDGPU_MN_KEY(amn->mm, amn->type) == key)
> +		if (AMDGPU_MN_KEY(amn->mirror.hmm->mmu_notifier.mm,
> +				  amn->type) == key)
>   			goto release_locks;
>   
>   	amn = kzalloc(sizeof(*amn), GFP_KERNEL);
> @@ -337,10 +205,8 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev,
>   	}
>   
>   	amn->adev = adev;
> -	amn->mm = mm;
>   	init_rwsem(&amn->lock);
>   	amn->type = type;
> -	amn->objects = RB_ROOT_CACHED;
>   
>   	amn->mirror.ops = &amdgpu_hmm_mirror_ops[type];
>   	r = hmm_mirror_register(&amn->mirror, mm);
> @@ -369,100 +235,33 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev,
>    * @bo: amdgpu buffer object
>    * @addr: userptr addr we should monitor
>    *
> - * Registers an HMM mirror for the given BO at the specified address.
> + * Registers a mmu_notifier for the given BO at the specified address.
>    * Returns 0 on success, -ERRNO if anything goes wrong.
>    */
>   int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr)
>   {
> -	unsigned long end = addr + amdgpu_bo_size(bo) - 1;
> -	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
> -	enum amdgpu_mn_type type =
> -		bo->kfd_bo ? AMDGPU_MN_TYPE_HSA : AMDGPU_MN_TYPE_GFX;
> -	struct amdgpu_mn *amn;
> -	struct amdgpu_mn_node *node = NULL, *new_node;
> -	struct list_head bos;
> -	struct interval_tree_node *it;
> -
> -	amn = amdgpu_mn_get(adev, type);
> -	if (IS_ERR(amn))
> -		return PTR_ERR(amn);
> -
> -	new_node = kmalloc(sizeof(*new_node), GFP_KERNEL);
> -	if (!new_node)
> -		return -ENOMEM;
> -
> -	INIT_LIST_HEAD(&bos);
> -
> -	down_write(&amn->lock);
> -
> -	while ((it = interval_tree_iter_first(&amn->objects, addr, end))) {
> -		kfree(node);
> -		node = container_of(it, struct amdgpu_mn_node, it);
> -		interval_tree_remove(&node->it, &amn->objects);
> -		addr = min(it->start, addr);
> -		end = max(it->last, end);
> -		list_splice(&node->bos, &bos);
> -	}
> -
> -	if (!node)
> -		node = new_node;
> +	if (bo->kfd_bo)
> +		bo->notifier.ops = &amdgpu_mn_hsa_ops;
>   	else
> -		kfree(new_node);
> -
> -	bo->mn = amn;
> -
> -	node->it.start = addr;
> -	node->it.last = end;
> -	INIT_LIST_HEAD(&node->bos);
> -	list_splice(&bos, &node->bos);
> -	list_add(&bo->mn_list, &node->bos);
> +		bo->notifier.ops = &amdgpu_mn_gfx_ops;
>   
> -	interval_tree_insert(&node->it, &amn->objects);
> -
> -	up_write(&amn->lock);
> -
> -	return 0;
> +	return mmu_range_notifier_insert(&bo->notifier, addr,
> +					 amdgpu_bo_size(bo), current->mm);
>   }
>   
>   /**
> - * amdgpu_mn_unregister - unregister a BO for HMM mirror updates
> + * amdgpu_mn_unregister - unregister a BO for notifier updates
>    *
>    * @bo: amdgpu buffer object
>    *
> - * Remove any registration of HMM mirror updates from the buffer object.
> + * Remove any registration of mmu notifier updates from the buffer object.
>    */
>   void amdgpu_mn_unregister(struct amdgpu_bo *bo)
>   {
> -	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
> -	struct amdgpu_mn *amn;
> -	struct list_head *head;
> -
> -	mutex_lock(&adev->mn_lock);
> -
> -	amn = bo->mn;
> -	if (amn == NULL) {
> -		mutex_unlock(&adev->mn_lock);
> +	if (!bo->notifier.mm)
>   		return;
> -	}
> -
> -	down_write(&amn->lock);
> -
> -	/* save the next list entry for later */
> -	head = bo->mn_list.next;
> -
> -	bo->mn = NULL;
> -	list_del_init(&bo->mn_list);
> -
> -	if (list_empty(head)) {
> -		struct amdgpu_mn_node *node;
> -
> -		node = container_of(head, struct amdgpu_mn_node, bos);
> -		interval_tree_remove(&node->it, &amn->objects);
> -		kfree(node);
> -	}
> -
> -	up_write(&amn->lock);
> -	mutex_unlock(&adev->mn_lock);
> +	mmu_range_notifier_remove(&bo->notifier);
> +	bo->notifier.mm = NULL;
>   }
>   
>   /* flags used by HMM internal, not related to CPU/GPU PTE flags */
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h
> index b8ed68943625c2..d73ab2947b22b2 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h
> @@ -39,12 +39,10 @@ enum amdgpu_mn_type {
>    * struct amdgpu_mn
>    *
>    * @adev: amdgpu device pointer
> - * @mm: process address space
>    * @type: type of MMU notifier
>    * @work: destruction work item
>    * @node: hash table node to find structure by adev and mn
>    * @lock: rw semaphore protecting the notifier nodes
> - * @objects: interval tree containing amdgpu_mn_nodes
>    * @mirror: HMM mirror function support
>    *
>    * Data for each amdgpu device and process address space.
> @@ -52,7 +50,6 @@ enum amdgpu_mn_type {
>   struct amdgpu_mn {
>   	/* constant after initialisation */
>   	struct amdgpu_device	*adev;
> -	struct mm_struct	*mm;
>   	enum amdgpu_mn_type	type;
>   
>   	/* only used on destruction */
> @@ -63,7 +60,6 @@ struct amdgpu_mn {
>   
>   	/* objects protected by lock */
>   	struct rw_semaphore	lock;
> -	struct rb_root_cached	objects;
>   
>   #ifdef CONFIG_HMM_MIRROR
>   	/* HMM mirror */
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
> index 658f4c9779b704..4b44ab850f94c2 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
> @@ -30,6 +30,9 @@
>   
>   #include <drm/amdgpu_drm.h>
>   #include "amdgpu.h"
> +#ifdef CONFIG_MMU_NOTIFIER
> +#include <linux/mmu_notifier.h>
> +#endif
>   
>   #define AMDGPU_BO_INVALID_OFFSET	LONG_MAX
>   #define AMDGPU_BO_MAX_PLACEMENTS	3
> @@ -100,10 +103,12 @@ struct amdgpu_bo {
>   	struct ttm_bo_kmap_obj		dma_buf_vmap;
>   	struct amdgpu_mn		*mn;
>   
> -	union {
> -		struct list_head	mn_list;
> -		struct list_head	shadow_list;
> -	};
> +
> +#ifdef CONFIG_MMU_NOTIFIER
> +	struct mmu_range_notifier	notifier;
> +#endif
> +
> +	struct list_head		shadow_list;
>   
>   	struct kgd_mem                  *kfd_bo;
>   };

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

WARNING: multiple messages have this Message-ID (diff)
From: "Koenig, Christian" <Christian.Koenig@amd.com>
To: Jason Gunthorpe <jgg@ziepe.ca>,
	"linux-mm@kvack.org" <linux-mm@kvack.org>,
	 Jerome Glisse <jglisse@redhat.com>,
	Ralph Campbell <rcampbell@nvidia.com>,
	 John Hubbard <jhubbard@nvidia.com>,
	"Kuehling, Felix" <Felix.Kuehling@amd.com>
Cc: Juergen Gross <jgross@suse.com>,
	"Zhou, David\(ChunMing\)" <David1.Zhou@amd.com>,
	Mike Marciniszyn <mike.marciniszyn@intel.com>,
	Stefano Stabellini <sstabellini@kernel.org>,
	Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>,
	"linux-rdma@vger.kernel.org" <linux-rdma@vger.kernel.org>,
	"nouveau@lists.freedesktop.org" <nouveau@lists.freedesktop.org>,
	Dennis Dalessandro <dennis.dalessandro@intel.com>,
	"amd-gfx@lists.freedesktop.org" <amd-gfx@lists.freedesktop.org>,
	Christoph Hellwig <hch@infradead.org>,
	Jason Gunthorpe <jgg@mellanox.com>,
	"dri-devel@lists.freedesktop.org"
	<dri-devel@lists.freedesktop.org>,
	"Deucher, Alexander" <Alexander.Deucher@amd.com>,
	"xen-devel@lists.xenproject.org" <xen-devel@lists.xenproject.org>,
	Boris Ostrovsky <boris.ostrovsky@oracle.com>,
	Petr Cvek <petrcvekcz@gmail.com>, Ben Skeggs <bskeggs@redhat.com>
Subject: Re: [Xen-devel] [PATCH v2 13/15] drm/amdgpu: Use mmu_range_insert instead of hmm_mirror
Date: Tue, 29 Oct 2019 07:51:30 +0000	[thread overview]
Message-ID: <bc44f331-5448-ddc0-ecc3-d0ccb92e11a4@amd.com> (raw)
In-Reply-To: <20191028201032.6352-14-jgg@ziepe.ca>

Am 28.10.19 um 21:10 schrieb Jason Gunthorpe:
> From: Jason Gunthorpe <jgg@mellanox.com>
>
> Remove the interval tree in the driver and rely on the tree maintained by
> the mmu_notifier for delivering mmu_notifier invalidation callbacks.
>
> For some reason amdgpu has a very complicated arrangement where it tries
> to prevent duplicate entries in the interval_tree, this is not necessary,
> each amdgpu_bo can be its own stand alone entry. interval_tree already
> allows duplicates and overlaps in the tree.
>
> Also, there is no need to remove entries upon a release callback, the
> mmu_range API safely allows objects to remain registered beyond the
> lifetime of the mm. The driver only has to stop touching the pages during
> release.
>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Christian König <christian.koenig@amd.com>
> Cc: David (ChunMing) Zhou <David1.Zhou@amd.com>
> Cc: amd-gfx@lists.freedesktop.org
> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu.h           |   2 +
>   .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c  |   5 +-
>   drivers/gpu/drm/amd/amdgpu/amdgpu_device.c    |   1 +
>   drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c        | 341 ++++--------------
>   drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h        |   4 -
>   drivers/gpu/drm/amd/amdgpu/amdgpu_object.h    |  13 +-
>   6 files changed, 84 insertions(+), 282 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> index bd37df5dd6d048..60591a5d420021 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> @@ -1006,6 +1006,8 @@ struct amdgpu_device {
>   	struct mutex  lock_reset;
>   	struct amdgpu_doorbell_index doorbell_index;
>   
> +	struct mutex			notifier_lock;
> +
>   	int asic_reset_res;
>   	struct work_struct		xgmi_reset_work;
>   
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
> index 6d021ecc8d598f..47700302a08b7f 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
> @@ -481,8 +481,7 @@ static void remove_kgd_mem_from_kfd_bo_list(struct kgd_mem *mem,
>    *
>    * Returns 0 for success, negative errno for errors.
>    */
> -static int init_user_pages(struct kgd_mem *mem, struct mm_struct *mm,
> -			   uint64_t user_addr)
> +static int init_user_pages(struct kgd_mem *mem, uint64_t user_addr)
>   {
>   	struct amdkfd_process_info *process_info = mem->process_info;
>   	struct amdgpu_bo *bo = mem->bo;
> @@ -1195,7 +1194,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
>   	add_kgd_mem_to_kfd_bo_list(*mem, avm->process_info, user_addr);
>   
>   	if (user_addr) {
> -		ret = init_user_pages(*mem, current->mm, user_addr);
> +		ret = init_user_pages(*mem, user_addr);
>   		if (ret)
>   			goto allocate_init_user_pages_failed;
>   	}
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> index 5a1939dbd4e3e6..38f97998aaddb2 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> @@ -2633,6 +2633,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
>   	mutex_init(&adev->virt.vf_errors.lock);
>   	hash_init(adev->mn_hash);
>   	mutex_init(&adev->lock_reset);
> +	mutex_init(&adev->notifier_lock);
>   	mutex_init(&adev->virt.dpm_mutex);
>   	mutex_init(&adev->psp.mutex);
>   
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
> index 31d4deb5d29484..4ffd7b90f4d907 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
> @@ -50,66 +50,6 @@
>   #include "amdgpu.h"
>   #include "amdgpu_amdkfd.h"
>   
> -/**
> - * struct amdgpu_mn_node
> - *
> - * @it: interval node defining start-last of the affected address range
> - * @bos: list of all BOs in the affected address range
> - *
> - * Manages all BOs which are affected of a certain range of address space.
> - */
> -struct amdgpu_mn_node {
> -	struct interval_tree_node	it;
> -	struct list_head		bos;
> -};
> -
> -/**
> - * amdgpu_mn_destroy - destroy the HMM mirror
> - *
> - * @work: previously sheduled work item
> - *
> - * Lazy destroys the notifier from a work item
> - */
> -static void amdgpu_mn_destroy(struct work_struct *work)
> -{
> -	struct amdgpu_mn *amn = container_of(work, struct amdgpu_mn, work);
> -	struct amdgpu_device *adev = amn->adev;
> -	struct amdgpu_mn_node *node, *next_node;
> -	struct amdgpu_bo *bo, *next_bo;
> -
> -	mutex_lock(&adev->mn_lock);
> -	down_write(&amn->lock);
> -	hash_del(&amn->node);
> -	rbtree_postorder_for_each_entry_safe(node, next_node,
> -					     &amn->objects.rb_root, it.rb) {
> -		list_for_each_entry_safe(bo, next_bo, &node->bos, mn_list) {
> -			bo->mn = NULL;
> -			list_del_init(&bo->mn_list);
> -		}
> -		kfree(node);
> -	}
> -	up_write(&amn->lock);
> -	mutex_unlock(&adev->mn_lock);
> -
> -	hmm_mirror_unregister(&amn->mirror);
> -	kfree(amn);
> -}
> -
> -/**
> - * amdgpu_hmm_mirror_release - callback to notify about mm destruction
> - *
> - * @mirror: the HMM mirror (mm) this callback is about
> - *
> - * Shedule a work item to lazy destroy HMM mirror.
> - */
> -static void amdgpu_hmm_mirror_release(struct hmm_mirror *mirror)
> -{
> -	struct amdgpu_mn *amn = container_of(mirror, struct amdgpu_mn, mirror);
> -
> -	INIT_WORK(&amn->work, amdgpu_mn_destroy);
> -	schedule_work(&amn->work);
> -}
> -
>   /**
>    * amdgpu_mn_lock - take the write side lock for this notifier
>    *
> @@ -133,157 +73,86 @@ void amdgpu_mn_unlock(struct amdgpu_mn *mn)
>   }
>   
>   /**
> - * amdgpu_mn_read_lock - take the read side lock for this notifier
> - *
> - * @amn: our notifier
> - */
> -static int amdgpu_mn_read_lock(struct amdgpu_mn *amn, bool blockable)
> -{
> -	if (blockable)
> -		down_read(&amn->lock);
> -	else if (!down_read_trylock(&amn->lock))
> -		return -EAGAIN;
> -
> -	return 0;
> -}
> -
> -/**
> - * amdgpu_mn_read_unlock - drop the read side lock for this notifier
> - *
> - * @amn: our notifier
> - */
> -static void amdgpu_mn_read_unlock(struct amdgpu_mn *amn)
> -{
> -	up_read(&amn->lock);
> -}
> -
> -/**
> - * amdgpu_mn_invalidate_node - unmap all BOs of a node
> + * amdgpu_mn_invalidate_gfx - callback to notify about mm change
>    *
> - * @node: the node with the BOs to unmap
> - * @start: start of address range affected
> - * @end: end of address range affected
> + * @mrn: the range (mm) is about to update
> + * @range: details on the invalidation
>    *
>    * Block for operations on BOs to finish and mark pages as accessed and
>    * potentially dirty.
>    */
> -static void amdgpu_mn_invalidate_node(struct amdgpu_mn_node *node,
> -				      unsigned long start,
> -				      unsigned long end)
> +static bool amdgpu_mn_invalidate_gfx(struct mmu_range_notifier *mrn,
> +				     const struct mmu_notifier_range *range)
>   {
> -	struct amdgpu_bo *bo;
> +	struct amdgpu_bo *bo = container_of(mrn, struct amdgpu_bo, notifier);
> +	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
>   	long r;
>   
> -	list_for_each_entry(bo, &node->bos, mn_list) {
> -
> -		if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, start, end))
> -			continue;
> -
> -		r = dma_resv_wait_timeout_rcu(bo->tbo.base.resv,
> -			true, false, MAX_SCHEDULE_TIMEOUT);
> -		if (r <= 0)
> -			DRM_ERROR("(%ld) failed to wait for user bo\n", r);
> -	}
> +	/* FIXME: Is this necessary? */

Most likely not.

Christian.

> +	if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, range->start,
> +					  range->end))
> +		return true;
> +
> +	if (!mmu_notifier_range_blockable(range))
> +		return false;
> +
> +	mutex_lock(&adev->notifier_lock);
> +	r = dma_resv_wait_timeout_rcu(bo->tbo.base.resv, true, false,
> +				      MAX_SCHEDULE_TIMEOUT);
> +	mutex_unlock(&adev->notifier_lock);
> +	if (r <= 0)
> +		DRM_ERROR("(%ld) failed to wait for user bo\n", r);
> +	return true;
>   }
>   
> +static const struct mmu_range_notifier_ops amdgpu_mn_gfx_ops = {
> +	.invalidate = amdgpu_mn_invalidate_gfx,
> +};
> +
>   /**
> - * amdgpu_mn_sync_pagetables_gfx - callback to notify about mm change
> + * amdgpu_mn_invalidate_hsa - callback to notify about mm change
>    *
> - * @mirror: the hmm_mirror (mm) is about to update
> - * @update: the update start, end address
> + * @mrn: the range (mm) is about to update
> + * @range: details on the invalidation
>    *
> - * Block for operations on BOs to finish and mark pages as accessed and
> - * potentially dirty.
> + * We temporarily evict the BO attached to this range. This necessitates
> + * evicting all user-mode queues of the process.
>    */
> -static int
> -amdgpu_mn_sync_pagetables_gfx(struct hmm_mirror *mirror,
> -			      const struct mmu_notifier_range *update)
> +static bool amdgpu_mn_invalidate_hsa(struct mmu_range_notifier *mrn,
> +				     const struct mmu_notifier_range *range)
>   {
> -	struct amdgpu_mn *amn = container_of(mirror, struct amdgpu_mn, mirror);
> -	unsigned long start = update->start;
> -	unsigned long end = update->end;
> -	bool blockable = mmu_notifier_range_blockable(update);
> -	struct interval_tree_node *it;
> -
> -	/* notification is exclusive, but interval is inclusive */
> -	end -= 1;
> -
> -	/* TODO we should be able to split locking for interval tree and
> -	 * amdgpu_mn_invalidate_node
> -	 */
> -	if (amdgpu_mn_read_lock(amn, blockable))
> -		return -EAGAIN;
> -
> -	it = interval_tree_iter_first(&amn->objects, start, end);
> -	while (it) {
> -		struct amdgpu_mn_node *node;
> -
> -		if (!blockable) {
> -			amdgpu_mn_read_unlock(amn);
> -			return -EAGAIN;
> -		}
> +	struct amdgpu_bo *bo = container_of(mrn, struct amdgpu_bo, notifier);
> +	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
>   
> -		node = container_of(it, struct amdgpu_mn_node, it);
> -		it = interval_tree_iter_next(it, start, end);
> +	/* FIXME: Is this necessary? */
> +	if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, range->start,
> +					  range->end))
> +		return true;
>   
> -		amdgpu_mn_invalidate_node(node, start, end);
> -	}
> +	if (!mmu_notifier_range_blockable(range))
> +		return false;
>   
> -	amdgpu_mn_read_unlock(amn);
> +	mutex_lock(&adev->notifier_lock);
> +	amdgpu_amdkfd_evict_userptr(bo->kfd_bo, bo->notifier.mm);
> +	mutex_unlock(&adev->notifier_lock);
>   
> -	return 0;
> +	return true;
>   }
>   
> -/**
> - * amdgpu_mn_sync_pagetables_hsa - callback to notify about mm change
> - *
> - * @mirror: the hmm_mirror (mm) is about to update
> - * @update: the update start, end address
> - *
> - * We temporarily evict all BOs between start and end. This
> - * necessitates evicting all user-mode queues of the process. The BOs
> - * are restorted in amdgpu_mn_invalidate_range_end_hsa.
> - */
> -static int
> -amdgpu_mn_sync_pagetables_hsa(struct hmm_mirror *mirror,
> -			      const struct mmu_notifier_range *update)
> +static const struct mmu_range_notifier_ops amdgpu_mn_hsa_ops = {
> +	.invalidate = amdgpu_mn_invalidate_hsa,
> +};
> +
> +static int amdgpu_mn_sync_pagetables(struct hmm_mirror *mirror,
> +				     const struct mmu_notifier_range *update)
>   {
>   	struct amdgpu_mn *amn = container_of(mirror, struct amdgpu_mn, mirror);
> -	unsigned long start = update->start;
> -	unsigned long end = update->end;
> -	bool blockable = mmu_notifier_range_blockable(update);
> -	struct interval_tree_node *it;
>   
> -	/* notification is exclusive, but interval is inclusive */
> -	end -= 1;
> -
> -	if (amdgpu_mn_read_lock(amn, blockable))
> -		return -EAGAIN;
> -
> -	it = interval_tree_iter_first(&amn->objects, start, end);
> -	while (it) {
> -		struct amdgpu_mn_node *node;
> -		struct amdgpu_bo *bo;
> -
> -		if (!blockable) {
> -			amdgpu_mn_read_unlock(amn);
> -			return -EAGAIN;
> -		}
> -
> -		node = container_of(it, struct amdgpu_mn_node, it);
> -		it = interval_tree_iter_next(it, start, end);
> -
> -		list_for_each_entry(bo, &node->bos, mn_list) {
> -			struct kgd_mem *mem = bo->kfd_bo;
> -
> -			if (amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm,
> -							 start, end))
> -				amdgpu_amdkfd_evict_userptr(mem, amn->mm);
> -		}
> -	}
> -
> -	amdgpu_mn_read_unlock(amn);
> +	if (!mmu_notifier_range_blockable(update))
> +		return false;
>   
> +	down_read(&amn->lock);
> +	up_read(&amn->lock);
>   	return 0;
>   }
>   
> @@ -295,12 +164,10 @@ amdgpu_mn_sync_pagetables_hsa(struct hmm_mirror *mirror,
>   
>   static struct hmm_mirror_ops amdgpu_hmm_mirror_ops[] = {
>   	[AMDGPU_MN_TYPE_GFX] = {
> -		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables_gfx,
> -		.release = amdgpu_hmm_mirror_release
> +		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables,
>   	},
>   	[AMDGPU_MN_TYPE_HSA] = {
> -		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables_hsa,
> -		.release = amdgpu_hmm_mirror_release
> +		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables,
>   	},
>   };
>   
> @@ -327,7 +194,8 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev,
>   	}
>   
>   	hash_for_each_possible(adev->mn_hash, amn, node, key)
> -		if (AMDGPU_MN_KEY(amn->mm, amn->type) == key)
> +		if (AMDGPU_MN_KEY(amn->mirror.hmm->mmu_notifier.mm,
> +				  amn->type) == key)
>   			goto release_locks;
>   
>   	amn = kzalloc(sizeof(*amn), GFP_KERNEL);
> @@ -337,10 +205,8 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev,
>   	}
>   
>   	amn->adev = adev;
> -	amn->mm = mm;
>   	init_rwsem(&amn->lock);
>   	amn->type = type;
> -	amn->objects = RB_ROOT_CACHED;
>   
>   	amn->mirror.ops = &amdgpu_hmm_mirror_ops[type];
>   	r = hmm_mirror_register(&amn->mirror, mm);
> @@ -369,100 +235,33 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev,
>    * @bo: amdgpu buffer object
>    * @addr: userptr addr we should monitor
>    *
> - * Registers an HMM mirror for the given BO at the specified address.
> + * Registers a mmu_notifier for the given BO at the specified address.
>    * Returns 0 on success, -ERRNO if anything goes wrong.
>    */
>   int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr)
>   {
> -	unsigned long end = addr + amdgpu_bo_size(bo) - 1;
> -	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
> -	enum amdgpu_mn_type type =
> -		bo->kfd_bo ? AMDGPU_MN_TYPE_HSA : AMDGPU_MN_TYPE_GFX;
> -	struct amdgpu_mn *amn;
> -	struct amdgpu_mn_node *node = NULL, *new_node;
> -	struct list_head bos;
> -	struct interval_tree_node *it;
> -
> -	amn = amdgpu_mn_get(adev, type);
> -	if (IS_ERR(amn))
> -		return PTR_ERR(amn);
> -
> -	new_node = kmalloc(sizeof(*new_node), GFP_KERNEL);
> -	if (!new_node)
> -		return -ENOMEM;
> -
> -	INIT_LIST_HEAD(&bos);
> -
> -	down_write(&amn->lock);
> -
> -	while ((it = interval_tree_iter_first(&amn->objects, addr, end))) {
> -		kfree(node);
> -		node = container_of(it, struct amdgpu_mn_node, it);
> -		interval_tree_remove(&node->it, &amn->objects);
> -		addr = min(it->start, addr);
> -		end = max(it->last, end);
> -		list_splice(&node->bos, &bos);
> -	}
> -
> -	if (!node)
> -		node = new_node;
> +	if (bo->kfd_bo)
> +		bo->notifier.ops = &amdgpu_mn_hsa_ops;
>   	else
> -		kfree(new_node);
> -
> -	bo->mn = amn;
> -
> -	node->it.start = addr;
> -	node->it.last = end;
> -	INIT_LIST_HEAD(&node->bos);
> -	list_splice(&bos, &node->bos);
> -	list_add(&bo->mn_list, &node->bos);
> +		bo->notifier.ops = &amdgpu_mn_gfx_ops;
>   
> -	interval_tree_insert(&node->it, &amn->objects);
> -
> -	up_write(&amn->lock);
> -
> -	return 0;
> +	return mmu_range_notifier_insert(&bo->notifier, addr,
> +					 amdgpu_bo_size(bo), current->mm);
>   }
>   
>   /**
> - * amdgpu_mn_unregister - unregister a BO for HMM mirror updates
> + * amdgpu_mn_unregister - unregister a BO for notifier updates
>    *
>    * @bo: amdgpu buffer object
>    *
> - * Remove any registration of HMM mirror updates from the buffer object.
> + * Remove any registration of mmu notifier updates from the buffer object.
>    */
>   void amdgpu_mn_unregister(struct amdgpu_bo *bo)
>   {
> -	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
> -	struct amdgpu_mn *amn;
> -	struct list_head *head;
> -
> -	mutex_lock(&adev->mn_lock);
> -
> -	amn = bo->mn;
> -	if (amn == NULL) {
> -		mutex_unlock(&adev->mn_lock);
> +	if (!bo->notifier.mm)
>   		return;
> -	}
> -
> -	down_write(&amn->lock);
> -
> -	/* save the next list entry for later */
> -	head = bo->mn_list.next;
> -
> -	bo->mn = NULL;
> -	list_del_init(&bo->mn_list);
> -
> -	if (list_empty(head)) {
> -		struct amdgpu_mn_node *node;
> -
> -		node = container_of(head, struct amdgpu_mn_node, bos);
> -		interval_tree_remove(&node->it, &amn->objects);
> -		kfree(node);
> -	}
> -
> -	up_write(&amn->lock);
> -	mutex_unlock(&adev->mn_lock);
> +	mmu_range_notifier_remove(&bo->notifier);
> +	bo->notifier.mm = NULL;
>   }
>   
>   /* flags used by HMM internal, not related to CPU/GPU PTE flags */
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h
> index b8ed68943625c2..d73ab2947b22b2 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h
> @@ -39,12 +39,10 @@ enum amdgpu_mn_type {
>    * struct amdgpu_mn
>    *
>    * @adev: amdgpu device pointer
> - * @mm: process address space
>    * @type: type of MMU notifier
>    * @work: destruction work item
>    * @node: hash table node to find structure by adev and mn
>    * @lock: rw semaphore protecting the notifier nodes
> - * @objects: interval tree containing amdgpu_mn_nodes
>    * @mirror: HMM mirror function support
>    *
>    * Data for each amdgpu device and process address space.
> @@ -52,7 +50,6 @@ enum amdgpu_mn_type {
>   struct amdgpu_mn {
>   	/* constant after initialisation */
>   	struct amdgpu_device	*adev;
> -	struct mm_struct	*mm;
>   	enum amdgpu_mn_type	type;
>   
>   	/* only used on destruction */
> @@ -63,7 +60,6 @@ struct amdgpu_mn {
>   
>   	/* objects protected by lock */
>   	struct rw_semaphore	lock;
> -	struct rb_root_cached	objects;
>   
>   #ifdef CONFIG_HMM_MIRROR
>   	/* HMM mirror */
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
> index 658f4c9779b704..4b44ab850f94c2 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
> @@ -30,6 +30,9 @@
>   
>   #include <drm/amdgpu_drm.h>
>   #include "amdgpu.h"
> +#ifdef CONFIG_MMU_NOTIFIER
> +#include <linux/mmu_notifier.h>
> +#endif
>   
>   #define AMDGPU_BO_INVALID_OFFSET	LONG_MAX
>   #define AMDGPU_BO_MAX_PLACEMENTS	3
> @@ -100,10 +103,12 @@ struct amdgpu_bo {
>   	struct ttm_bo_kmap_obj		dma_buf_vmap;
>   	struct amdgpu_mn		*mn;
>   
> -	union {
> -		struct list_head	mn_list;
> -		struct list_head	shadow_list;
> -	};
> +
> +#ifdef CONFIG_MMU_NOTIFIER
> +	struct mmu_range_notifier	notifier;
> +#endif
> +
> +	struct list_head		shadow_list;
>   
>   	struct kgd_mem                  *kfd_bo;
>   };

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

WARNING: multiple messages have this Message-ID (diff)
From: "Koenig, Christian" <Christian.Koenig@amd.com>
To: Jason Gunthorpe <jgg@ziepe.ca>,
	"linux-mm@kvack.org" <linux-mm@kvack.org>,
	 Jerome Glisse <jglisse@redhat.com>,
	Ralph Campbell <rcampbell@nvidia.com>,
	 John Hubbard <jhubbard@nvidia.com>,
	"Kuehling, Felix" <Felix.Kuehling@amd.com>
Cc: Juergen Gross <jgross@suse.com>,
	"Zhou, David\(ChunMing\)" <David1.Zhou@amd.com>,
	Mike Marciniszyn <mike.marciniszyn@intel.com>,
	Stefano Stabellini <sstabellini@kernel.org>,
	Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>,
	"linux-rdma@vger.kernel.org" <linux-rdma@vger.kernel.org>,
	"nouveau@lists.freedesktop.org" <nouveau@lists.freedesktop.org>,
	Dennis Dalessandro <dennis.dalessandro@intel.com>,
	"amd-gfx@lists.freedesktop.org" <amd-gfx@lists.freedesktop.org>,
	Christoph Hellwig <hch@infradead.org>,
	Jason Gunthorpe <jgg@mellanox.com>,
	"dri-devel@lists.freedesktop.org"
	<dri-devel@lists.freedesktop.org>,
	"Deucher, Alexander" <Alexander.Deucher@amd.com>,
	"xen-devel@lists.xenproject.org" <xen-devel@lists.xenproject.org>,
	Boris Ostrovsky <boris.ostrovsky@oracle.com>,
	Petr Cvek <petrcvekcz@gmail.com>, Ben Skeggs <bskeggs@redhat.com>
Subject: Re: [PATCH v2 13/15] drm/amdgpu: Use mmu_range_insert instead of hmm_mirror
Date: Tue, 29 Oct 2019 07:51:30 +0000	[thread overview]
Message-ID: <bc44f331-5448-ddc0-ecc3-d0ccb92e11a4@amd.com> (raw)
Message-ID: <20191029075130.eiZCHaVV-l6Lp2HKoPH9P2hyqaSpGr1wNaCTUkaQMYo@z> (raw)
In-Reply-To: <20191028201032.6352-14-jgg@ziepe.ca>

Am 28.10.19 um 21:10 schrieb Jason Gunthorpe:
> From: Jason Gunthorpe <jgg@mellanox.com>
>
> Remove the interval tree in the driver and rely on the tree maintained by
> the mmu_notifier for delivering mmu_notifier invalidation callbacks.
>
> For some reason amdgpu has a very complicated arrangement where it tries
> to prevent duplicate entries in the interval_tree, this is not necessary,
> each amdgpu_bo can be its own stand alone entry. interval_tree already
> allows duplicates and overlaps in the tree.
>
> Also, there is no need to remove entries upon a release callback, the
> mmu_range API safely allows objects to remain registered beyond the
> lifetime of the mm. The driver only has to stop touching the pages during
> release.
>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Christian König <christian.koenig@amd.com>
> Cc: David (ChunMing) Zhou <David1.Zhou@amd.com>
> Cc: amd-gfx@lists.freedesktop.org
> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu.h           |   2 +
>   .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c  |   5 +-
>   drivers/gpu/drm/amd/amdgpu/amdgpu_device.c    |   1 +
>   drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c        | 341 ++++--------------
>   drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h        |   4 -
>   drivers/gpu/drm/amd/amdgpu/amdgpu_object.h    |  13 +-
>   6 files changed, 84 insertions(+), 282 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> index bd37df5dd6d048..60591a5d420021 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> @@ -1006,6 +1006,8 @@ struct amdgpu_device {
>   	struct mutex  lock_reset;
>   	struct amdgpu_doorbell_index doorbell_index;
>   
> +	struct mutex			notifier_lock;
> +
>   	int asic_reset_res;
>   	struct work_struct		xgmi_reset_work;
>   
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
> index 6d021ecc8d598f..47700302a08b7f 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
> @@ -481,8 +481,7 @@ static void remove_kgd_mem_from_kfd_bo_list(struct kgd_mem *mem,
>    *
>    * Returns 0 for success, negative errno for errors.
>    */
> -static int init_user_pages(struct kgd_mem *mem, struct mm_struct *mm,
> -			   uint64_t user_addr)
> +static int init_user_pages(struct kgd_mem *mem, uint64_t user_addr)
>   {
>   	struct amdkfd_process_info *process_info = mem->process_info;
>   	struct amdgpu_bo *bo = mem->bo;
> @@ -1195,7 +1194,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
>   	add_kgd_mem_to_kfd_bo_list(*mem, avm->process_info, user_addr);
>   
>   	if (user_addr) {
> -		ret = init_user_pages(*mem, current->mm, user_addr);
> +		ret = init_user_pages(*mem, user_addr);
>   		if (ret)
>   			goto allocate_init_user_pages_failed;
>   	}
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> index 5a1939dbd4e3e6..38f97998aaddb2 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> @@ -2633,6 +2633,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
>   	mutex_init(&adev->virt.vf_errors.lock);
>   	hash_init(adev->mn_hash);
>   	mutex_init(&adev->lock_reset);
> +	mutex_init(&adev->notifier_lock);
>   	mutex_init(&adev->virt.dpm_mutex);
>   	mutex_init(&adev->psp.mutex);
>   
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
> index 31d4deb5d29484..4ffd7b90f4d907 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
> @@ -50,66 +50,6 @@
>   #include "amdgpu.h"
>   #include "amdgpu_amdkfd.h"
>   
> -/**
> - * struct amdgpu_mn_node
> - *
> - * @it: interval node defining start-last of the affected address range
> - * @bos: list of all BOs in the affected address range
> - *
> - * Manages all BOs which are affected of a certain range of address space.
> - */
> -struct amdgpu_mn_node {
> -	struct interval_tree_node	it;
> -	struct list_head		bos;
> -};
> -
> -/**
> - * amdgpu_mn_destroy - destroy the HMM mirror
> - *
> - * @work: previously sheduled work item
> - *
> - * Lazy destroys the notifier from a work item
> - */
> -static void amdgpu_mn_destroy(struct work_struct *work)
> -{
> -	struct amdgpu_mn *amn = container_of(work, struct amdgpu_mn, work);
> -	struct amdgpu_device *adev = amn->adev;
> -	struct amdgpu_mn_node *node, *next_node;
> -	struct amdgpu_bo *bo, *next_bo;
> -
> -	mutex_lock(&adev->mn_lock);
> -	down_write(&amn->lock);
> -	hash_del(&amn->node);
> -	rbtree_postorder_for_each_entry_safe(node, next_node,
> -					     &amn->objects.rb_root, it.rb) {
> -		list_for_each_entry_safe(bo, next_bo, &node->bos, mn_list) {
> -			bo->mn = NULL;
> -			list_del_init(&bo->mn_list);
> -		}
> -		kfree(node);
> -	}
> -	up_write(&amn->lock);
> -	mutex_unlock(&adev->mn_lock);
> -
> -	hmm_mirror_unregister(&amn->mirror);
> -	kfree(amn);
> -}
> -
> -/**
> - * amdgpu_hmm_mirror_release - callback to notify about mm destruction
> - *
> - * @mirror: the HMM mirror (mm) this callback is about
> - *
> - * Shedule a work item to lazy destroy HMM mirror.
> - */
> -static void amdgpu_hmm_mirror_release(struct hmm_mirror *mirror)
> -{
> -	struct amdgpu_mn *amn = container_of(mirror, struct amdgpu_mn, mirror);
> -
> -	INIT_WORK(&amn->work, amdgpu_mn_destroy);
> -	schedule_work(&amn->work);
> -}
> -
>   /**
>    * amdgpu_mn_lock - take the write side lock for this notifier
>    *
> @@ -133,157 +73,86 @@ void amdgpu_mn_unlock(struct amdgpu_mn *mn)
>   }
>   
>   /**
> - * amdgpu_mn_read_lock - take the read side lock for this notifier
> - *
> - * @amn: our notifier
> - */
> -static int amdgpu_mn_read_lock(struct amdgpu_mn *amn, bool blockable)
> -{
> -	if (blockable)
> -		down_read(&amn->lock);
> -	else if (!down_read_trylock(&amn->lock))
> -		return -EAGAIN;
> -
> -	return 0;
> -}
> -
> -/**
> - * amdgpu_mn_read_unlock - drop the read side lock for this notifier
> - *
> - * @amn: our notifier
> - */
> -static void amdgpu_mn_read_unlock(struct amdgpu_mn *amn)
> -{
> -	up_read(&amn->lock);
> -}
> -
> -/**
> - * amdgpu_mn_invalidate_node - unmap all BOs of a node
> + * amdgpu_mn_invalidate_gfx - callback to notify about mm change
>    *
> - * @node: the node with the BOs to unmap
> - * @start: start of address range affected
> - * @end: end of address range affected
> + * @mrn: the range (mm) is about to update
> + * @range: details on the invalidation
>    *
>    * Block for operations on BOs to finish and mark pages as accessed and
>    * potentially dirty.
>    */
> -static void amdgpu_mn_invalidate_node(struct amdgpu_mn_node *node,
> -				      unsigned long start,
> -				      unsigned long end)
> +static bool amdgpu_mn_invalidate_gfx(struct mmu_range_notifier *mrn,
> +				     const struct mmu_notifier_range *range)
>   {
> -	struct amdgpu_bo *bo;
> +	struct amdgpu_bo *bo = container_of(mrn, struct amdgpu_bo, notifier);
> +	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
>   	long r;
>   
> -	list_for_each_entry(bo, &node->bos, mn_list) {
> -
> -		if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, start, end))
> -			continue;
> -
> -		r = dma_resv_wait_timeout_rcu(bo->tbo.base.resv,
> -			true, false, MAX_SCHEDULE_TIMEOUT);
> -		if (r <= 0)
> -			DRM_ERROR("(%ld) failed to wait for user bo\n", r);
> -	}
> +	/* FIXME: Is this necessary? */

Most likely not.

Christian.

> +	if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, range->start,
> +					  range->end))
> +		return true;
> +
> +	if (!mmu_notifier_range_blockable(range))
> +		return false;
> +
> +	mutex_lock(&adev->notifier_lock);
> +	r = dma_resv_wait_timeout_rcu(bo->tbo.base.resv, true, false,
> +				      MAX_SCHEDULE_TIMEOUT);
> +	mutex_unlock(&adev->notifier_lock);
> +	if (r <= 0)
> +		DRM_ERROR("(%ld) failed to wait for user bo\n", r);
> +	return true;
>   }
>   
> +static const struct mmu_range_notifier_ops amdgpu_mn_gfx_ops = {
> +	.invalidate = amdgpu_mn_invalidate_gfx,
> +};
> +
>   /**
> - * amdgpu_mn_sync_pagetables_gfx - callback to notify about mm change
> + * amdgpu_mn_invalidate_hsa - callback to notify about mm change
>    *
> - * @mirror: the hmm_mirror (mm) is about to update
> - * @update: the update start, end address
> + * @mrn: the range (mm) is about to update
> + * @range: details on the invalidation
>    *
> - * Block for operations on BOs to finish and mark pages as accessed and
> - * potentially dirty.
> + * We temporarily evict the BO attached to this range. This necessitates
> + * evicting all user-mode queues of the process.
>    */
> -static int
> -amdgpu_mn_sync_pagetables_gfx(struct hmm_mirror *mirror,
> -			      const struct mmu_notifier_range *update)
> +static bool amdgpu_mn_invalidate_hsa(struct mmu_range_notifier *mrn,
> +				     const struct mmu_notifier_range *range)
>   {
> -	struct amdgpu_mn *amn = container_of(mirror, struct amdgpu_mn, mirror);
> -	unsigned long start = update->start;
> -	unsigned long end = update->end;
> -	bool blockable = mmu_notifier_range_blockable(update);
> -	struct interval_tree_node *it;
> -
> -	/* notification is exclusive, but interval is inclusive */
> -	end -= 1;
> -
> -	/* TODO we should be able to split locking for interval tree and
> -	 * amdgpu_mn_invalidate_node
> -	 */
> -	if (amdgpu_mn_read_lock(amn, blockable))
> -		return -EAGAIN;
> -
> -	it = interval_tree_iter_first(&amn->objects, start, end);
> -	while (it) {
> -		struct amdgpu_mn_node *node;
> -
> -		if (!blockable) {
> -			amdgpu_mn_read_unlock(amn);
> -			return -EAGAIN;
> -		}
> +	struct amdgpu_bo *bo = container_of(mrn, struct amdgpu_bo, notifier);
> +	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
>   
> -		node = container_of(it, struct amdgpu_mn_node, it);
> -		it = interval_tree_iter_next(it, start, end);
> +	/* FIXME: Is this necessary? */
> +	if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, range->start,
> +					  range->end))
> +		return true;
>   
> -		amdgpu_mn_invalidate_node(node, start, end);
> -	}
> +	if (!mmu_notifier_range_blockable(range))
> +		return false;
>   
> -	amdgpu_mn_read_unlock(amn);
> +	mutex_lock(&adev->notifier_lock);
> +	amdgpu_amdkfd_evict_userptr(bo->kfd_bo, bo->notifier.mm);
> +	mutex_unlock(&adev->notifier_lock);
>   
> -	return 0;
> +	return true;
>   }
>   
> -/**
> - * amdgpu_mn_sync_pagetables_hsa - callback to notify about mm change
> - *
> - * @mirror: the hmm_mirror (mm) is about to update
> - * @update: the update start, end address
> - *
> - * We temporarily evict all BOs between start and end. This
> - * necessitates evicting all user-mode queues of the process. The BOs
> - * are restorted in amdgpu_mn_invalidate_range_end_hsa.
> - */
> -static int
> -amdgpu_mn_sync_pagetables_hsa(struct hmm_mirror *mirror,
> -			      const struct mmu_notifier_range *update)
> +static const struct mmu_range_notifier_ops amdgpu_mn_hsa_ops = {
> +	.invalidate = amdgpu_mn_invalidate_hsa,
> +};
> +
> +static int amdgpu_mn_sync_pagetables(struct hmm_mirror *mirror,
> +				     const struct mmu_notifier_range *update)
>   {
>   	struct amdgpu_mn *amn = container_of(mirror, struct amdgpu_mn, mirror);
> -	unsigned long start = update->start;
> -	unsigned long end = update->end;
> -	bool blockable = mmu_notifier_range_blockable(update);
> -	struct interval_tree_node *it;
>   
> -	/* notification is exclusive, but interval is inclusive */
> -	end -= 1;
> -
> -	if (amdgpu_mn_read_lock(amn, blockable))
> -		return -EAGAIN;
> -
> -	it = interval_tree_iter_first(&amn->objects, start, end);
> -	while (it) {
> -		struct amdgpu_mn_node *node;
> -		struct amdgpu_bo *bo;
> -
> -		if (!blockable) {
> -			amdgpu_mn_read_unlock(amn);
> -			return -EAGAIN;
> -		}
> -
> -		node = container_of(it, struct amdgpu_mn_node, it);
> -		it = interval_tree_iter_next(it, start, end);
> -
> -		list_for_each_entry(bo, &node->bos, mn_list) {
> -			struct kgd_mem *mem = bo->kfd_bo;
> -
> -			if (amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm,
> -							 start, end))
> -				amdgpu_amdkfd_evict_userptr(mem, amn->mm);
> -		}
> -	}
> -
> -	amdgpu_mn_read_unlock(amn);
> +	if (!mmu_notifier_range_blockable(update))
> +		return false;
>   
> +	down_read(&amn->lock);
> +	up_read(&amn->lock);
>   	return 0;
>   }
>   
> @@ -295,12 +164,10 @@ amdgpu_mn_sync_pagetables_hsa(struct hmm_mirror *mirror,
>   
>   static struct hmm_mirror_ops amdgpu_hmm_mirror_ops[] = {
>   	[AMDGPU_MN_TYPE_GFX] = {
> -		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables_gfx,
> -		.release = amdgpu_hmm_mirror_release
> +		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables,
>   	},
>   	[AMDGPU_MN_TYPE_HSA] = {
> -		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables_hsa,
> -		.release = amdgpu_hmm_mirror_release
> +		.sync_cpu_device_pagetables = amdgpu_mn_sync_pagetables,
>   	},
>   };
>   
> @@ -327,7 +194,8 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev,
>   	}
>   
>   	hash_for_each_possible(adev->mn_hash, amn, node, key)
> -		if (AMDGPU_MN_KEY(amn->mm, amn->type) == key)
> +		if (AMDGPU_MN_KEY(amn->mirror.hmm->mmu_notifier.mm,
> +				  amn->type) == key)
>   			goto release_locks;
>   
>   	amn = kzalloc(sizeof(*amn), GFP_KERNEL);
> @@ -337,10 +205,8 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev,
>   	}
>   
>   	amn->adev = adev;
> -	amn->mm = mm;
>   	init_rwsem(&amn->lock);
>   	amn->type = type;
> -	amn->objects = RB_ROOT_CACHED;
>   
>   	amn->mirror.ops = &amdgpu_hmm_mirror_ops[type];
>   	r = hmm_mirror_register(&amn->mirror, mm);
> @@ -369,100 +235,33 @@ struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev,
>    * @bo: amdgpu buffer object
>    * @addr: userptr addr we should monitor
>    *
> - * Registers an HMM mirror for the given BO at the specified address.
> + * Registers a mmu_notifier for the given BO at the specified address.
>    * Returns 0 on success, -ERRNO if anything goes wrong.
>    */
>   int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr)
>   {
> -	unsigned long end = addr + amdgpu_bo_size(bo) - 1;
> -	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
> -	enum amdgpu_mn_type type =
> -		bo->kfd_bo ? AMDGPU_MN_TYPE_HSA : AMDGPU_MN_TYPE_GFX;
> -	struct amdgpu_mn *amn;
> -	struct amdgpu_mn_node *node = NULL, *new_node;
> -	struct list_head bos;
> -	struct interval_tree_node *it;
> -
> -	amn = amdgpu_mn_get(adev, type);
> -	if (IS_ERR(amn))
> -		return PTR_ERR(amn);
> -
> -	new_node = kmalloc(sizeof(*new_node), GFP_KERNEL);
> -	if (!new_node)
> -		return -ENOMEM;
> -
> -	INIT_LIST_HEAD(&bos);
> -
> -	down_write(&amn->lock);
> -
> -	while ((it = interval_tree_iter_first(&amn->objects, addr, end))) {
> -		kfree(node);
> -		node = container_of(it, struct amdgpu_mn_node, it);
> -		interval_tree_remove(&node->it, &amn->objects);
> -		addr = min(it->start, addr);
> -		end = max(it->last, end);
> -		list_splice(&node->bos, &bos);
> -	}
> -
> -	if (!node)
> -		node = new_node;
> +	if (bo->kfd_bo)
> +		bo->notifier.ops = &amdgpu_mn_hsa_ops;
>   	else
> -		kfree(new_node);
> -
> -	bo->mn = amn;
> -
> -	node->it.start = addr;
> -	node->it.last = end;
> -	INIT_LIST_HEAD(&node->bos);
> -	list_splice(&bos, &node->bos);
> -	list_add(&bo->mn_list, &node->bos);
> +		bo->notifier.ops = &amdgpu_mn_gfx_ops;
>   
> -	interval_tree_insert(&node->it, &amn->objects);
> -
> -	up_write(&amn->lock);
> -
> -	return 0;
> +	return mmu_range_notifier_insert(&bo->notifier, addr,
> +					 amdgpu_bo_size(bo), current->mm);
>   }
>   
>   /**
> - * amdgpu_mn_unregister - unregister a BO for HMM mirror updates
> + * amdgpu_mn_unregister - unregister a BO for notifier updates
>    *
>    * @bo: amdgpu buffer object
>    *
> - * Remove any registration of HMM mirror updates from the buffer object.
> + * Remove any registration of mmu notifier updates from the buffer object.
>    */
>   void amdgpu_mn_unregister(struct amdgpu_bo *bo)
>   {
> -	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
> -	struct amdgpu_mn *amn;
> -	struct list_head *head;
> -
> -	mutex_lock(&adev->mn_lock);
> -
> -	amn = bo->mn;
> -	if (amn == NULL) {
> -		mutex_unlock(&adev->mn_lock);
> +	if (!bo->notifier.mm)
>   		return;
> -	}
> -
> -	down_write(&amn->lock);
> -
> -	/* save the next list entry for later */
> -	head = bo->mn_list.next;
> -
> -	bo->mn = NULL;
> -	list_del_init(&bo->mn_list);
> -
> -	if (list_empty(head)) {
> -		struct amdgpu_mn_node *node;
> -
> -		node = container_of(head, struct amdgpu_mn_node, bos);
> -		interval_tree_remove(&node->it, &amn->objects);
> -		kfree(node);
> -	}
> -
> -	up_write(&amn->lock);
> -	mutex_unlock(&adev->mn_lock);
> +	mmu_range_notifier_remove(&bo->notifier);
> +	bo->notifier.mm = NULL;
>   }
>   
>   /* flags used by HMM internal, not related to CPU/GPU PTE flags */
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h
> index b8ed68943625c2..d73ab2947b22b2 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h
> @@ -39,12 +39,10 @@ enum amdgpu_mn_type {
>    * struct amdgpu_mn
>    *
>    * @adev: amdgpu device pointer
> - * @mm: process address space
>    * @type: type of MMU notifier
>    * @work: destruction work item
>    * @node: hash table node to find structure by adev and mn
>    * @lock: rw semaphore protecting the notifier nodes
> - * @objects: interval tree containing amdgpu_mn_nodes
>    * @mirror: HMM mirror function support
>    *
>    * Data for each amdgpu device and process address space.
> @@ -52,7 +50,6 @@ enum amdgpu_mn_type {
>   struct amdgpu_mn {
>   	/* constant after initialisation */
>   	struct amdgpu_device	*adev;
> -	struct mm_struct	*mm;
>   	enum amdgpu_mn_type	type;
>   
>   	/* only used on destruction */
> @@ -63,7 +60,6 @@ struct amdgpu_mn {
>   
>   	/* objects protected by lock */
>   	struct rw_semaphore	lock;
> -	struct rb_root_cached	objects;
>   
>   #ifdef CONFIG_HMM_MIRROR
>   	/* HMM mirror */
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
> index 658f4c9779b704..4b44ab850f94c2 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
> @@ -30,6 +30,9 @@
>   
>   #include <drm/amdgpu_drm.h>
>   #include "amdgpu.h"
> +#ifdef CONFIG_MMU_NOTIFIER
> +#include <linux/mmu_notifier.h>
> +#endif
>   
>   #define AMDGPU_BO_INVALID_OFFSET	LONG_MAX
>   #define AMDGPU_BO_MAX_PLACEMENTS	3
> @@ -100,10 +103,12 @@ struct amdgpu_bo {
>   	struct ttm_bo_kmap_obj		dma_buf_vmap;
>   	struct amdgpu_mn		*mn;
>   
> -	union {
> -		struct list_head	mn_list;
> -		struct list_head	shadow_list;
> -	};
> +
> +#ifdef CONFIG_MMU_NOTIFIER
> +	struct mmu_range_notifier	notifier;
> +#endif
> +
> +	struct list_head		shadow_list;
>   
>   	struct kgd_mem                  *kfd_bo;
>   };

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

  reply	other threads:[~2019-10-29  7:51 UTC|newest]

Thread overview: 335+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-28 20:10 [PATCH v2 00/15] Consolidate the mmu notifier interval_tree and locking Jason Gunthorpe
2019-10-28 20:10 ` Jason Gunthorpe
2019-10-28 20:10 ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10 ` Jason Gunthorpe
2019-10-28 20:10 ` Jason Gunthorpe
2019-10-28 20:10 ` [PATCH v2 01/15] mm/mmu_notifier: define the header pre-processor parts even if disabled Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-11-05 21:23   ` John Hubbard
2019-11-05 21:23     ` John Hubbard
2019-11-05 21:23     ` [Xen-devel] " John Hubbard
2019-11-05 21:23     ` John Hubbard
2019-11-05 21:23     ` John Hubbard
2019-11-06 13:36     ` Jason Gunthorpe
2019-11-06 13:36       ` Jason Gunthorpe
2019-11-06 13:36       ` [Xen-devel] " Jason Gunthorpe
2019-11-06 13:36       ` Jason Gunthorpe
2019-11-06 13:36       ` Jason Gunthorpe
2019-10-28 20:10 ` [PATCH v2 02/15] mm/mmu_notifier: add an interval tree notifier Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-29 22:04   ` Kuehling, Felix
2019-10-29 22:04     ` Kuehling, Felix
2019-10-29 22:04     ` [Xen-devel] " Kuehling, Felix
2019-10-29 22:04     ` Kuehling, Felix
2019-10-29 22:04     ` Kuehling, Felix
2019-10-29 22:56     ` Jason Gunthorpe
2019-10-29 22:56       ` Jason Gunthorpe
2019-10-29 22:56       ` [Xen-devel] " Jason Gunthorpe
2019-10-29 22:56       ` Jason Gunthorpe
2019-10-29 22:56       ` Jason Gunthorpe
2019-11-07  0:23   ` John Hubbard
2019-11-07  0:23     ` John Hubbard
2019-11-07  0:23     ` [Xen-devel] " John Hubbard
2019-11-07  0:23     ` John Hubbard
2019-11-07  0:23     ` John Hubbard
2019-11-07  2:08     ` Jerome Glisse
2019-11-07  2:08       ` Jerome Glisse
2019-11-07  2:08       ` [Xen-devel] " Jerome Glisse
2019-11-07  2:08       ` Jerome Glisse
2019-11-07 20:11       ` Jason Gunthorpe
2019-11-07 20:11         ` Jason Gunthorpe
2019-11-07 20:11         ` [Xen-devel] " Jason Gunthorpe
2019-11-07 20:11         ` Jason Gunthorpe
2019-11-07 20:11         ` Jason Gunthorpe
2019-11-07 21:04         ` Jerome Glisse
2019-11-07 21:04           ` Jerome Glisse
2019-11-07 21:04           ` [Xen-devel] " Jerome Glisse
2019-11-07 21:04           ` Jerome Glisse
2019-11-07 21:04           ` Jerome Glisse
2019-11-08  0:32           ` Jason Gunthorpe
2019-11-08  0:32             ` Jason Gunthorpe
2019-11-08  0:32             ` [Xen-devel] " Jason Gunthorpe
2019-11-08  0:32             ` Jason Gunthorpe
2019-11-08  0:32             ` Jason Gunthorpe
2019-11-08  2:00             ` Jerome Glisse
2019-11-08  2:00               ` Jerome Glisse
2019-11-08  2:00               ` [Xen-devel] " Jerome Glisse
2019-11-08  2:00               ` Jerome Glisse
2019-11-08  2:00               ` Jerome Glisse
2019-11-08 20:19               ` Jason Gunthorpe
2019-11-08 20:19                 ` Jason Gunthorpe
2019-11-08 20:19                 ` [Xen-devel] " Jason Gunthorpe
2019-11-08 20:19                 ` Jason Gunthorpe
2019-11-07 20:06     ` Jason Gunthorpe
2019-11-07 20:06       ` Jason Gunthorpe
2019-11-07 20:06       ` [Xen-devel] " Jason Gunthorpe
2019-11-07 20:06       ` Jason Gunthorpe
2019-11-07 20:06       ` Jason Gunthorpe
2019-11-07 20:53       ` John Hubbard
2019-11-07 20:53         ` John Hubbard
2019-11-07 20:53         ` [Xen-devel] " John Hubbard
2019-11-07 20:53         ` John Hubbard
2019-11-07 20:53         ` John Hubbard
2019-11-08 15:26         ` Jason Gunthorpe
2019-11-08 15:26           ` Jason Gunthorpe
2019-11-08 15:26           ` [Xen-devel] " Jason Gunthorpe
2019-11-08 15:26           ` Jason Gunthorpe
2019-11-08  6:33       ` Christoph Hellwig
2019-11-08  6:33         ` Christoph Hellwig
2019-11-08  6:33         ` [Xen-devel] " Christoph Hellwig
2019-11-08  6:33         ` Christoph Hellwig
2019-11-08 13:43         ` Jerome Glisse
2019-11-08 13:43           ` Jerome Glisse
2019-11-08 13:43           ` [Xen-devel] " Jerome Glisse
2019-11-08 13:43           ` Jerome Glisse
2019-11-08 13:43           ` Jerome Glisse
2019-10-28 20:10 ` [PATCH v2 03/15] mm/hmm: allow hmm_range to be used with a mmu_range_notifier or hmm_mirror Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10 ` [PATCH v2 04/15] mm/hmm: define the pre-processor related parts of hmm.h even if disabled Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10 ` [PATCH v2 05/15] RDMA/odp: Use mmu_range_notifier_insert() Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10 ` [PATCH v2 06/15] RDMA/hfi1: Use mmu_range_notifier_inset for user_exp_rcv Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-29 12:19   ` Dennis Dalessandro
2019-10-29 12:19     ` Dennis Dalessandro
2019-10-29 12:19     ` [Xen-devel] " Dennis Dalessandro
2019-10-29 12:19     ` Dennis Dalessandro
2019-10-29 12:51     ` Jason Gunthorpe
2019-10-29 12:51       ` Jason Gunthorpe
2019-10-29 12:51       ` [Xen-devel] " Jason Gunthorpe
2019-10-29 12:51       ` Jason Gunthorpe
2019-10-29 12:51       ` Jason Gunthorpe
2019-10-28 20:10 ` [PATCH v2 07/15] drm/radeon: use mmu_range_notifier_insert Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-29  7:48   ` Koenig, Christian
2019-10-29  7:48     ` Koenig, Christian
2019-10-29  7:48     ` [Xen-devel] " Koenig, Christian
2019-10-29  7:48     ` Koenig, Christian
2019-10-29  7:48     ` Koenig, Christian
2019-10-28 20:10 ` [PATCH v2 08/15] xen/gntdev: Use select for DMA_SHARED_BUFFER Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-11-01 18:26   ` Jason Gunthorpe
2019-11-01 18:26     ` Jason Gunthorpe
2019-11-01 18:26     ` [Xen-devel] " Jason Gunthorpe
2019-11-01 18:26     ` Jason Gunthorpe
2019-11-05 14:44     ` Jürgen Groß
2019-11-05 14:44       ` Jürgen Groß
2019-11-05 14:44       ` [Xen-devel] " Jürgen Groß
2019-11-05 14:44       ` Jürgen Groß
2019-11-05 14:44       ` Jürgen Groß
2019-11-07  9:39   ` Jürgen Groß
2019-11-07  9:39     ` Jürgen Groß
2019-11-07  9:39     ` [Xen-devel] " Jürgen Groß
2019-11-07  9:39     ` Jürgen Groß
2019-10-28 20:10 ` [PATCH v2 09/15] xen/gntdev: use mmu_range_notifier_insert Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-30 16:55   ` Boris Ostrovsky
2019-10-30 16:55     ` Boris Ostrovsky
2019-10-30 16:55     ` [Xen-devel] " Boris Ostrovsky
2019-10-30 16:55     ` Boris Ostrovsky
2019-10-30 16:55     ` Boris Ostrovsky
2019-11-01 17:48     ` Jason Gunthorpe
2019-11-01 17:48       ` Jason Gunthorpe
2019-11-01 17:48       ` [Xen-devel] " Jason Gunthorpe
2019-11-01 17:48       ` Jason Gunthorpe
2019-11-01 18:51       ` Boris Ostrovsky
2019-11-01 18:51         ` Boris Ostrovsky
2019-11-01 18:51         ` [Xen-devel] " Boris Ostrovsky
2019-11-01 18:51         ` Boris Ostrovsky
2019-11-01 19:17         ` Jason Gunthorpe
2019-11-01 19:17           ` Jason Gunthorpe
2019-11-01 19:17           ` [Xen-devel] " Jason Gunthorpe
2019-11-01 19:17           ` Jason Gunthorpe
2019-11-04 22:03   ` Boris Ostrovsky
2019-11-04 22:03     ` Boris Ostrovsky
2019-11-04 22:03     ` [Xen-devel] " Boris Ostrovsky
2019-11-04 22:03     ` Boris Ostrovsky
2019-11-05  2:31     ` Jason Gunthorpe
2019-11-05  2:31       ` Jason Gunthorpe
2019-11-05  2:31       ` [Xen-devel] " Jason Gunthorpe
2019-11-05  2:31       ` Jason Gunthorpe
2019-11-05 15:16       ` Boris Ostrovsky
2019-11-05 15:16         ` Boris Ostrovsky
2019-11-05 15:16         ` [Xen-devel] " Boris Ostrovsky
2019-11-05 15:16         ` Boris Ostrovsky
2019-11-05 15:16         ` Boris Ostrovsky
2019-11-07 20:36         ` Jason Gunthorpe
2019-11-07 20:36           ` Jason Gunthorpe
2019-11-07 20:36           ` [Xen-devel] " Jason Gunthorpe
2019-11-07 20:36           ` Jason Gunthorpe
2019-11-07 20:36           ` Jason Gunthorpe
2019-11-07 22:54           ` Boris Ostrovsky
2019-11-07 22:54             ` Boris Ostrovsky
2019-11-07 22:54             ` [Xen-devel] " Boris Ostrovsky
2019-11-07 22:54             ` Boris Ostrovsky
2019-11-07 22:54             ` Boris Ostrovsky
2019-11-08 14:53             ` Jason Gunthorpe
2019-11-08 14:53               ` Jason Gunthorpe
2019-11-08 14:53               ` [Xen-devel] " Jason Gunthorpe
2019-11-08 14:53               ` Jason Gunthorpe
2019-10-28 20:10 ` [PATCH v2 10/15] nouveau: use mmu_notifier directly for invalidate_range_start Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10 ` [PATCH v2 11/15] nouveau: use mmu_range_notifier instead of hmm_mirror Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10 ` [PATCH v2 12/15] drm/amdgpu: Call find_vma under mmap_sem Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-29  7:49   ` Koenig, Christian
2019-10-29  7:49     ` Koenig, Christian
2019-10-29  7:49     ` [Xen-devel] " Koenig, Christian
2019-10-29  7:49     ` Koenig, Christian
2019-10-29  7:49     ` Koenig, Christian
2019-10-29 16:28   ` Kuehling, Felix
2019-10-29 16:28     ` Kuehling, Felix
2019-10-29 16:28     ` [Xen-devel] " Kuehling, Felix
2019-10-29 16:28     ` Kuehling, Felix
2019-10-29 16:28     ` Kuehling, Felix
2019-10-29 13:07     ` Christian König
2019-10-29 13:07       ` Christian König
2019-10-29 13:07       ` [Xen-devel] " Christian König
2019-10-29 13:07       ` Christian König
2019-10-29 13:07       ` Christian König
2019-10-29 17:19     ` Jason Gunthorpe
2019-10-29 17:19       ` Jason Gunthorpe
2019-10-29 17:19       ` [Xen-devel] " Jason Gunthorpe
2019-10-29 17:19       ` Jason Gunthorpe
2019-10-29 17:19       ` Jason Gunthorpe
2019-10-28 20:10 ` [PATCH v2 13/15] drm/amdgpu: Use mmu_range_insert instead of hmm_mirror Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-29  7:51   ` Koenig, Christian [this message]
2019-10-29  7:51     ` Koenig, Christian
2019-10-29  7:51     ` [Xen-devel] " Koenig, Christian
2019-10-29  7:51     ` Koenig, Christian
2019-10-29  7:51     ` Koenig, Christian
2019-10-29 13:59     ` Jason Gunthorpe
2019-10-29 13:59       ` Jason Gunthorpe
2019-10-29 13:59       ` [Xen-devel] " Jason Gunthorpe
2019-10-29 13:59       ` Jason Gunthorpe
2019-10-29 13:59       ` Jason Gunthorpe
2019-10-29 22:14   ` Kuehling, Felix
2019-10-29 22:14     ` Kuehling, Felix
2019-10-29 22:14     ` [Xen-devel] " Kuehling, Felix
2019-10-29 22:14     ` Kuehling, Felix
2019-10-29 22:14     ` Kuehling, Felix
2019-10-29 23:09     ` Jason Gunthorpe
2019-10-29 23:09       ` Jason Gunthorpe
2019-10-29 23:09       ` [Xen-devel] " Jason Gunthorpe
2019-10-29 23:09       ` Jason Gunthorpe
2019-10-29 23:09       ` Jason Gunthorpe
2019-10-28 20:10 ` [PATCH v2 14/15] drm/amdgpu: Use mmu_range_notifier " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-29 19:22   ` Yang, Philip
2019-10-29 19:22     ` Yang, Philip
2019-10-29 19:22     ` [Xen-devel] " Yang, Philip
2019-10-29 19:22     ` Yang, Philip
2019-10-29 19:22     ` Yang, Philip
2019-10-29 19:25     ` Jason Gunthorpe
2019-10-29 19:25       ` Jason Gunthorpe
2019-10-29 19:25       ` [Xen-devel] " Jason Gunthorpe
2019-10-29 19:25       ` Jason Gunthorpe
2019-10-29 19:25       ` Jason Gunthorpe
2019-11-01 14:44       ` Yang, Philip
2019-11-01 14:44         ` Yang, Philip
2019-11-01 14:44         ` [Xen-devel] " Yang, Philip
2019-11-01 14:44         ` Yang, Philip
2019-11-01 14:44         ` Yang, Philip
2019-11-01 15:12         ` Jason Gunthorpe
2019-11-01 15:12           ` Jason Gunthorpe
2019-11-01 15:12           ` [Xen-devel] " Jason Gunthorpe
2019-11-01 15:12           ` Jason Gunthorpe
2019-11-01 15:12           ` Jason Gunthorpe
2019-11-01 15:59           ` Yang, Philip
2019-11-01 15:59             ` Yang, Philip
2019-11-01 15:59             ` [Xen-devel] " Yang, Philip
2019-11-01 15:59             ` Yang, Philip
2019-11-01 15:59             ` Yang, Philip
2019-11-01 17:42             ` Jason Gunthorpe
2019-11-01 17:42               ` Jason Gunthorpe
2019-11-01 17:42               ` [Xen-devel] " Jason Gunthorpe
2019-11-01 17:42               ` Jason Gunthorpe
2019-11-01 17:42               ` Jason Gunthorpe
2019-11-01 19:19               ` Jason Gunthorpe
2019-11-01 19:19                 ` Jason Gunthorpe
2019-11-01 19:19                 ` Jason Gunthorpe
2019-11-01 19:45               ` Yang, Philip
2019-11-01 19:45                 ` Yang, Philip
2019-11-01 19:45                 ` [Xen-devel] " Yang, Philip
2019-11-01 19:45                 ` Yang, Philip
2019-11-01 19:45                 ` Yang, Philip
2019-11-01 19:50                 ` Yang, Philip
2019-11-01 19:50                   ` Yang, Philip
2019-11-01 19:50                   ` [Xen-devel] " Yang, Philip
2019-11-01 19:50                   ` Yang, Philip
2019-11-01 19:50                   ` Yang, Philip
2019-11-01 19:51                 ` Jason Gunthorpe
2019-11-01 19:51                   ` Jason Gunthorpe
2019-11-01 19:51                   ` [Xen-devel] " Jason Gunthorpe
2019-11-01 19:51                   ` Jason Gunthorpe
2019-11-01 19:51                   ` Jason Gunthorpe
2019-11-01 18:21         ` Jason Gunthorpe
2019-11-01 18:21           ` Jason Gunthorpe
2019-11-01 18:21           ` [Xen-devel] " Jason Gunthorpe
2019-11-01 18:21           ` Jason Gunthorpe
2019-11-01 18:21           ` Jason Gunthorpe
2019-11-01 18:34         ` [PATCH v2a " Jason Gunthorpe
2019-11-01 18:34           ` Jason Gunthorpe
2019-11-01 18:34           ` [Xen-devel] " Jason Gunthorpe
2019-11-01 18:34           ` Jason Gunthorpe
2019-11-01 18:34           ` Jason Gunthorpe
2019-10-28 20:10 ` [PATCH v2 15/15] mm/hmm: remove hmm_mirror and related Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` [Xen-devel] " Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-10-28 20:10   ` Jason Gunthorpe
2019-11-01 19:54 ` [PATCH v2 00/15] Consolidate the mmu notifier interval_tree and locking Jason Gunthorpe
2019-11-01 19:54   ` Jason Gunthorpe
2019-11-01 19:54   ` [Xen-devel] " Jason Gunthorpe
2019-11-01 19:54   ` Jason Gunthorpe
2019-11-01 19:54   ` Jason Gunthorpe
2019-11-01 20:54 ` Ralph Campbell
2019-11-01 20:54   ` Ralph Campbell
2019-11-01 20:54   ` [Xen-devel] " Ralph Campbell
2019-11-01 20:54   ` Ralph Campbell
2019-11-01 20:54   ` Ralph Campbell
2019-11-04 20:40   ` Jason Gunthorpe
2019-11-04 20:40     ` Jason Gunthorpe
2019-11-04 20:40     ` [Xen-devel] " Jason Gunthorpe
2019-11-04 20:40     ` Jason Gunthorpe

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=bc44f331-5448-ddc0-ecc3-d0ccb92e11a4@amd.com \
    --to=christian.koenig@amd.com \
    --cc=Alexander.Deucher@amd.com \
    --cc=David1.Zhou@amd.com \
    --cc=Felix.Kuehling@amd.com \
    --cc=amd-gfx@lists.freedesktop.org \
    --cc=boris.ostrovsky@oracle.com \
    --cc=bskeggs@redhat.com \
    --cc=dennis.dalessandro@intel.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=hch@infradead.org \
    --cc=jgg@mellanox.com \
    --cc=jgg@ziepe.ca \
    --cc=jglisse@redhat.com \
    --cc=jgross@suse.com \
    --cc=jhubbard@nvidia.com \
    --cc=linux-mm@kvack.org \
    --cc=linux-rdma@vger.kernel.org \
    --cc=mike.marciniszyn@intel.com \
    --cc=nouveau@lists.freedesktop.org \
    --cc=oleksandr_andrushchenko@epam.com \
    --cc=petrcvekcz@gmail.com \
    --cc=rcampbell@nvidia.com \
    --cc=sstabellini@kernel.org \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.