mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "Thomas Hellström" <thomas.hellstrom@linux.intel.com>
To: "Christian König" <christian.koenig@amd.com>,
	"Danilo Krummrich" <dakr@redhat.com>
Cc: airlied@gmail.com, daniel@ffwll.ch, matthew.brost@intel.com,
	sarah.walker@imgtec.com, donald.robson@imgtec.com,
	boris.brezillon@collabora.com, faith@gfxstrand.net,
	dri-devel@lists.freedesktop.org, nouveau@lists.freedesktop.org,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH drm-misc-next v8 09/12] drm/gpuvm: reference count drm_gpuvm structures
Date: Fri, 10 Nov 2023 10:39:59 +0100	[thread overview]
Message-ID: <f7a64e17-d8b0-a20a-4e27-46f448a10bd4@linux.intel.com> (raw)
In-Reply-To: <1d4ca394-ee0c-4617-adbe-1d47e295c8fb@amd.com>


On 11/10/23 09:50, Christian König wrote:
> Am 09.11.23 um 19:34 schrieb Danilo Krummrich:
>> On 11/9/23 17:03, Christian König wrote:
>>> Am 09.11.23 um 16:50 schrieb Thomas Hellström:
>>>> [SNIP]
>>>>>>
>>>> Did we get any resolution on this?
>>>>
>>>> FWIW, my take on this is that it would be possible to get GPUVM to 
>>>> work both with and without internal refcounting; If with, the 
>>>> driver needs a vm close to resolve cyclic references, if without 
>>>> that's not necessary. If GPUVM is allowed to refcount in mappings 
>>>> and vm_bos, that comes with a slight performance drop but as Danilo 
>>>> pointed out, the VM lifetime problem iterating over a vm_bo's 
>>>> mapping becomes much easier and the code thus becomes easier to 
>>>> maintain moving forward. That convinced me it's a good thing.
>>>
>>> I strongly believe you guys stumbled over one of the core problems 
>>> with the VM here and I think that reference counting is the right 
>>> answer to solving this.
>>>
>>> The big question is that what is reference counted and in which 
>>> direction does the dependency points, e.g. we have here VM, BO, 
>>> BO_VM and Mapping objects.
>>>
>>> Those patches here suggest a counted Mapping -> VM reference and I'm 
>>> pretty sure that this isn't a good idea. What we should rather 
>>> really have is a BO -> VM or BO_VM ->VM reference. In other words 
>>> that each BO which is part of the VM keeps a reference to the VM.
>>
>> We have both. Please see the subsequent patch introducing VM_BO 
>> structures for that.
>>
>> As I explained, mappings (struct drm_gpuva) keep a pointer to their 
>> VM they're mapped
>> in and besides that it doesn't make sense to free a VM that still 
>> contains mappings,
>> the reference count ensures that. This simply ensures memory safety.
>>
>>>
>>> BTW: At least in amdgpu we can have BOs which (temporary) doesn't 
>>> have any mappings, but are still considered part of the VM.
>>
>> That should be possible.
>>
>>>
>>>>
>>>> Another issue Christian brought up is that something intended to be 
>>>> embeddable (a base class) shouldn't really have its own refcount. I 
>>>> think that's a valid point. If you at some point need to derive 
>>>> from multiple such structs each having its own refcount, things 
>>>> will start to get weird. One way to resolve that would be to have 
>>>> the driver's subclass provide get() and put() ops, and export a 
>>>> destructor for the base-class, rather than to have the base-class 
>>>> provide the refcount and a destructor  ops.
>>
>> GPUVM simply follows the same pattern we have with drm_gem_objects. 
>> And I think it makes
>> sense. Why would we want to embed two struct drm_gpuvm in a single 
>> driver structure?
>
> Because you need one drm_gpuvm structure for each application using 
> the driver? Or am I missing something?
>
> As far as I can see a driver would want to embed that into your fpriv 
> structure which is allocated during drm_driver.open callback.

I was thinking more of the general design of a base-class that needs to 
be refcounted. Say a driver vm that inherits from gpu-vm, gem_object and 
yet another base-class that supplies its own refcount. What's the 
best-practice way to do refcounting? All base-classes supplying a 
refcount of its own, or the subclass supplying a refcount and the 
base-classes supply destroy helpers.

But to be clear this is nothing I see needing urgent attention.

>
>>
>>>
>>> Well, I have never seen stuff like that in the kernel. Might be that 
>>> this works, but I would rather not try if avoidable.
>>>
>>>>
>>>> That would also make it possible for the driver to decide the 
>>>> context for the put() call: If the driver needs to be able to call 
>>>> put() from irq / atomic context but the base-class'es destructor 
>>>> doesn't allow atomic context, the driver can push freeing out to a 
>>>> work item if needed.
>>>>
>>>> Finally, the refcount overflow Christian pointed out. Limiting the 
>>>> number of mapping sounds like a reasonable remedy to me.
>>>
>>> Well that depends, I would rather avoid having a dependency for 
>>> mappings.
>>>
>>> Taking the CPU VM handling as example as far as I know 
>>> vm_area_structs doesn't grab a reference to their mm_struct either. 
>>> Instead they get automatically destroyed when the mm_struct is 
>>> destroyed.
>>
>> Certainly, that would be possible. However, thinking about it, this 
>> might call for
>> huge trouble.
>>
>> First of all, we'd still need to reference count a GPUVM and take a 
>> reference for each
>> VM_BO, as we do already. Now instead of simply increasing the 
>> reference count for each
>> mapping as well, we'd need a *mandatory* driver callback that is 
>> called when the GPUVM
>> reference count drops to zero. Maybe something like vm_destroy().
>>
>> The reason is that GPUVM can't just remove all mappings from the tree 
>> nor can it free them
>> by itself, since drivers might use them for tracking their allocated 
>> page tables and/or
>> other stuff.
>>
>> Now, let's think about the scope this callback might be called from. 
>> When a VM_BO is destroyed
>> the driver might hold a couple of locks (for Xe it would be the VM's 
>> shared dma-resv lock and
>> potentially the corresponding object's dma-resv lock if they're not 
>> the same already). If
>> destroying this VM_BO leads to the VM being destroyed, the drivers 
>> vm_destroy() callback would
>> be called with those locks being held as well.
>>
>> I feel like doing this finally opens the doors of the locking hell 
>> entirely. I think we should
>> really avoid that.

I don't think we need to worry much about this particular locking hell 
because if we hold, for example a vm and bo resv when putting the vm_bo, 
we need to keep additional strong references for the bo / vm pointer we 
use for unlocking. Hence putting the vm_bo under those locks can never 
lead to the vm getting destroyed.

Also, don't we already sort of have a mandatory vm_destroy callback?

+	if (drm_WARN_ON(gpuvm->drm, !gpuvm->ops->vm_free))
+		return;



>
> That's a really good point, but I fear exactly that's the use case.
>
> I would expect that VM_BO structures are added in the 
> drm_gem_object_funcs.open callback and freed in 
> drm_gem_object_funcs.close.
>
> Since it is perfectly legal for userspace to close a BO while there 
> are still mappings (can trivial be that the app is killed) I would 
> expect that the drm_gem_object_funcs.close handling is something like 
> asking drm_gpuvm destroying the VM_BO and getting the mappings which 
> should be cleared in the page table in return.
>
> In amdgpu we even go a step further and the VM structure keeps track 
> of all the mappings of deleted VM_BOs so that higher level can query 
> those and clear them later on.
>
> Background is that the drm_gem_object_funcs.close can't fail, but it 
> can perfectly be that the app is killed because of an OOM situation 
> and we can't do page tables updates in that moment because of this.
>
>>
>>>
>>> Which makes sense in that case because when the mm_struct is gone 
>>> the vm_area_struct doesn't make sense any more either.
>>>
>>> What we clearly need is a reference to prevent the VM or at least 
>>> the shared resv to go away to early.
>>
>> Yeah, that was a good hint and we've covered that.
>>
>>>
>>> Regards,
>>> Christian.
>>>
>>>>
>>>> But I think all of this is fixable as follow-ups if needed, unless 
>>>> I'm missing something crucial.
>>
>> Fully agree, I think at this point we should go ahead and land this 
>> series.

+1.

/Thomas


>>
>
> Yeah, agree this is not UAPI so not nailed in stone. Feel free to add 
> my acked-by as well if you want.
>
> Only keep in mind that when you give drivers some functionality in a 
> common component they usually expect to keep that functionality.
>
> For example changing the dma_resv object to make sure that drivers 
> can't cause use after free errors any more was an extremely annoying 
> experience since every user of those interface had to change at once.
>
> Regards,
> Christian.
>
>>
>>>>
>>>> Just my 2 cents.
>>>>
>>>> /Thomas
>>>>
>>>>
>>>
>>
>

  reply	other threads:[~2023-11-10 18:29 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-11-01 23:30 [PATCH drm-misc-next v8 00/12] [RFC] DRM GPUVM features Danilo Krummrich
2023-11-01 23:30 ` [PATCH drm-misc-next v8 01/12] drm/gpuvm: convert WARN() to drm_WARN() variants Danilo Krummrich
2023-11-01 23:30 ` [PATCH drm-misc-next v8 02/12] drm/gpuvm: don't always WARN in drm_gpuvm_check_overflow() Danilo Krummrich
2023-11-02 13:19   ` Thomas Hellström
2023-11-01 23:30 ` [PATCH drm-misc-next v8 03/12] drm/gpuvm: export drm_gpuvm_range_valid() Danilo Krummrich
2023-11-02 13:20   ` Thomas Hellström
2023-11-01 23:30 ` [PATCH drm-misc-next v8 04/12] drm/nouveau: make use of drm_gpuvm_range_valid() Danilo Krummrich
2023-11-02  4:46   ` Dave Airlie
2023-11-01 23:30 ` [PATCH drm-misc-next v8 05/12] drm/gpuvm: add common dma-resv per struct drm_gpuvm Danilo Krummrich
2023-11-01 23:30 ` [PATCH drm-misc-next v8 06/12] drm/nouveau: make use of the GPUVM's shared dma-resv Danilo Krummrich
2023-11-01 23:30 ` [PATCH drm-misc-next v8 07/12] drm/gpuvm: add drm_gpuvm_flags to drm_gpuvm Danilo Krummrich
2023-11-01 23:31 ` [PATCH drm-misc-next v8 08/12] drm/nouveau: separately allocate struct nouveau_uvmm Danilo Krummrich
2023-11-02  4:44   ` Dave Airlie
2023-11-01 23:31 ` [PATCH drm-misc-next v8 09/12] drm/gpuvm: reference count drm_gpuvm structures Danilo Krummrich
2023-11-02 10:46   ` kernel test robot
2023-11-02 13:21   ` Thomas Hellström
2023-11-02 17:09   ` Thomas Hellström
2023-11-02 17:32     ` Danilo Krummrich
2023-11-02 18:04       ` Thomas Hellström
2023-11-03  7:18   ` Christian König
2023-11-03 13:14     ` Danilo Krummrich
     [not found]       ` <a2e13a27-d2e5-4ae3-9c11-c18b425b69cc@amd.com>
2023-11-03 15:34         ` Danilo Krummrich
2023-11-06  9:14           ` Christian König
2023-11-06 12:16             ` Danilo Krummrich
     [not found]               ` <8e87d962-c80c-40d9-94d7-58b6cd9dd794@amd.com>
2023-11-06 14:11                 ` Danilo Krummrich
     [not found]                   ` <6d3c48f6-a92d-49b3-b836-ee1bc95b56bf@amd.com>
2023-11-06 16:42                     ` Danilo Krummrich
2023-11-09 15:50                       ` Thomas Hellström
2023-11-09 16:03                         ` Christian König
2023-11-09 18:34                           ` Danilo Krummrich
2023-11-10  8:50                             ` Christian König
2023-11-10  9:39                               ` Thomas Hellström [this message]
2023-11-10 10:42                                 ` Christian König
2023-11-10 10:52                                   ` Thomas Hellström
2023-11-10 16:49                                     ` Danilo Krummrich
2023-11-10 16:43                                 ` Danilo Krummrich
2023-11-10 16:57                               ` Danilo Krummrich
2023-11-13  7:22                                 ` Christian König
2023-11-13 12:57                                   ` Danilo Krummrich
2023-11-01 23:31 ` [PATCH drm-misc-next v8 10/12] drm/gpuvm: add an abstraction for a VM / BO combination Danilo Krummrich
2023-11-02 13:25   ` Thomas Hellström
2023-11-02 17:16   ` Thomas Hellström
2023-11-01 23:31 ` [PATCH drm-misc-next v8 11/12] drm/gpuvm: track/lock/validate external/evicted objects Danilo Krummrich
2023-11-01 23:31 ` [PATCH drm-misc-next v8 12/12] drm/nouveau: use GPUVM common infrastructure Danilo Krummrich
2023-11-02  4:47   ` Dave Airlie
2023-11-02 13:18   ` Thomas Hellström

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=f7a64e17-d8b0-a20a-4e27-46f448a10bd4@linux.intel.com \
    --to=thomas.hellstrom@linux.intel.com \
    --cc=airlied@gmail.com \
    --cc=boris.brezillon@collabora.com \
    --cc=christian.koenig@amd.com \
    --cc=dakr@redhat.com \
    --cc=daniel@ffwll.ch \
    --cc=donald.robson@imgtec.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=faith@gfxstrand.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=matthew.brost@intel.com \
    --cc=nouveau@lists.freedesktop.org \
    --cc=sarah.walker@imgtec.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®