<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <div class="moz-cite-prefix">Am 05.05.20 um 19:29 schrieb Felix
      Kuehling:<br>
    </div>
    <blockquote type="cite" cite="mid:388b628f-cfd3-b8e0-d43e-ed4cd280fee7@amd.com">
      
      <blockquote type="cite" cite="mid:ca18ec07-a6f4-292c-c800-48dbf9c8854f@amd.com"> <br>
        What we could probably do to detect this is adding a BUG_ON() in
        TTMs release function and checking if the GEM reference count is
        really dead.<br>
      </blockquote>
      <p>The problem is, that we have to guess whether there are still
        any dmabuf references to the GEM BO. There is no way amdgpu can
        know that. You can't make amdgpu responsible for keeping a
        reference to the TTM BO while the GEM BO is still referenced by
        entities completely out of the control of amdgpu.</p>
    </blockquote>
    <br>
    That sounds like you don't understand how this works on the graphics
    side, so here is a brief overview once more.<br>
    <br>
    The last object still around is always the TTM BO, which can even be
    resurrected from the dead (kref_init() called again) if necessary
    for delayed delete.<br>
    <br>
    Then we have the GEM object which holds a reference to the TTM BO.
    This reference gets dropped when the GEM object gets destroyed.<br>
    <br>
    Then we optionally have the DMA-buf object for exported BOs which
    holds a reference to the GEM object and the driver.<br>
    <br>
    <br>
    This construct guarantees that the GEM object is never destroyed nor
    the driver unloaded before the DMA-buf object referencing it is
    destroyed.<br>
    <br>
    Additional to that the reference from the GEM object to the TTM BO
    guarantees that the TTM BO is never destroyed before the GEM object
    is destroyed.<br>
    <br>
    <blockquote type="cite" cite="mid:388b628f-cfd3-b8e0-d43e-ed4cd280fee7@amd.com">Another
      weird thing I see is that amdgpu_gem_free_object calls
      amdgpu_bo_unref. That implies that the GEM object conceptually
      holds a reference to the amdpu/TTM BO. But that is not really the
      case. Amdgpu never takes that reference that GEM is supposed to
      own. If it did, we would leak all our memory because nobody would
      ever drop that reference. </blockquote>
    <br>
    See amdgpu_bo_do_create(), the GEM object is initialized with
    drm_gem_private_object_init() with a reference count of 1. Then the
    TTM BO is initialized with ttm_bo_init_reserved() with a reference
    count of 1.<br>
    <br>
    In general there are two use cases here, the first one is userspace
    allocations with a GEM object handle. In this case the initial
    reference is owned by the GEM object and dropped in
    amdgpu_gem_free_object().<br>
    <br>
    The other use case are kernel internal allocations like page tables
    and other general buffers. In this case the GEM object is ignored
    and the last TTM BO reference is dropped by calling
    amdgpu_bo_unref().<br>
    <br>
    <blockquote type="cite" cite="mid:388b628f-cfd3-b8e0-d43e-ed4cd280fee7@amd.com">
      <blockquote type="cite" cite="mid:ca18ec07-a6f4-292c-c800-48dbf9c8854f@amd.com">
        <blockquote type="cite" cite="mid:170627d3-b5f8-edf5-d809-dd197c4e2018@amd.com">I
          think the correct solution is for amdgpu_bo_ref/unref to
          delegate its reference counting to drm_gem_object_get/put
          instead of ttm_bo_get/put. The amdgpu BO would hold one token
          reference to the TTM BO, which it can drop when the GEM BO
          refcount drops to 0. Finally, the amdgpu BO should only be
          freed once the TTM BO refcount also becomes 0.<br>
        </blockquote>
        <br>
        Just the other way around, but yes the long term plan should
        probably be to merge the two.<br>
      </blockquote>
      <p>I need a short term solution. Because I have a bug that causes
        a kernel oops with applications that are valid and correct, as
        far as I can tell.</p>
      <p>I'm thinking a solution that doesn't require major changes to
        the way TTM and GEM interact would put amdgpu in charge of
        coordinating the two. Unfortunately that would mean adding a
        third reference count in amdgpu_bo, in addition to the ones in
        TTM and GEM. The amdgpu BO would hold one token reference to
        each of the GEM and TTM BO. When amdgpu refcount goes to 0 it
        releases that GEM BO token reference. When the GEM BO refcount
        goes  to 0, we get a callback amdgpu_gem_object_free. There we
        can drop the token reference to the TTM BO. Once the TTM BO
        reference goes to 0 we free the memory.</p>
      <p>Does this sound feasible?<br>
      </p>
    </blockquote>
    <br>
    Well of hand it sounds like it makes the whole thing much more
    complicated without any gain. I probably still haven't understood
    what the core problem here is.<br>
    <br>
    Regards,<br>
    Christian.<br>
    <br>
    <blockquote type="cite" cite="mid:388b628f-cfd3-b8e0-d43e-ed4cd280fee7@amd.com">
      <p> </p>
      <p>Regards,<br>
          Felix</p>
      <p><br>
      </p>
      <blockquote type="cite" cite="mid:ca18ec07-a6f4-292c-c800-48dbf9c8854f@amd.com"> <br>
        The difficult is currently we have a mismatch what locks could
        be taken when we drop the references.<br>
        <br>
        Regards,<br>
        Christian.<br>
        <br>
        <blockquote type="cite" cite="mid:170627d3-b5f8-edf5-d809-dd197c4e2018@amd.com">
          <p>Regards,<br>
              Felix<br>
          </p>
          <p><br>
          </p>
          <blockquote type="cite" cite="mid:6c4b3eb0-40b5-8c3c-dc5e-38b622864e12@gmail.com">
            <div class="moz-cite-prefix"> <br>
              Regards,<br>
              Christian.<br>
              <br>
              Am 01.05.20 um 16:44 schrieb Felix Kuehling:<br>
            </div>
          </blockquote>
          <blockquote type="cite" cite="mid:6c4b3eb0-40b5-8c3c-dc5e-38b622864e12@gmail.com">
            <blockquote type="cite" cite="mid:551849ec-bc90-0bd2-d46c-f6d8e5c0fee0@amd.com">
              <p>[dropping my gmail address]</p>
              <p>We saw this backtrace showing the call chain while
                investigating a kernel oops caused by this issue on the
                DKMS branch with the KFD IPC API. It happens after a
                dma-buf file is released with fput:</p>
              <pre>[ 1255.049330] BUG: kernel NULL pointer dereference, address: 000000000000051e
[ 1255.049727] #PF: supervisor read access in kernel mode
[ 1255.050092] #PF: error_code(0x0000) - not-present page
[ 1255.050416] PGD 0 P4D 0
[ 1255.050736] Oops: 0000 [#1] SMP PTI
[ 1255.051060] CPU: 27 PID: 2292 Comm: kworker/27:2 Tainted: G           OE     5.3.0-46-generic #38~18.04.1-Ubuntu
[ 1255.051400] Hardware name: Supermicro SYS-4029GP-TRT2/X11DPG-OT-CPU, BIOS 3.0a 02/26/2019
[ 1255.051752] Workqueue: events delayed_fput
[ 1255.052111] RIP: 0010:drm_gem_object_put_unlocked+0x1c/0x70 [drm]
[ 1255.052465] Code: 4d 80 c8 ee 0f 0b eb d8 66 0f 1f 44 00 00 0f 1f 44 00 00 48 85 ff 74 34 55 48 89 e5 41 54 53 48 89 fb 48 8b 7f 08 48 8b 47 20 <48> 83 b8 a0 00 00 00 00 74 1a 4c 8d 67 68 48 89 df 4c 89 e6 e8 9b
[ 1255.053224] RSP: 0018:ffffb4b62035fdc8 EFLAGS: 00010286
[ 1255.053613] RAX: 000000000000047e RBX: ffff9f2add197850 RCX: 0000000000000000
[ 1255.054032] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff9f2aa2548aa0
[ 1255.054440] RBP: ffffb4b62035fdd8 R08: 0000000000000000 R09: 0000000000000000
[ 1255.054860] R10: 0000000000000010 R11: ffff9f2a4b1cc310 R12: 0000000000080005
[ 1255.055268] R13: ffff9f2a4b1cc310 R14: ffff9f4e369161e0 R15: ffff9f2a1b2f9080
[ 1255.055674] FS:  0000000000000000(0000) GS:ffff9f4e3f740000(0000) knlGS:0000000000000000
[ 1255.056087] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 1255.056501] CR2: 000000000000051e CR3: 00000002df00a004 CR4: 00000000007606e0
[ 1255.056923] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 1255.057345] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[ 1255.057763] PKRU: 55555554
[ 1255.058179] Call Trace:
[ 1255.058603]  drm_gem_dmabuf_release+0x1a/0x30 [drm]
[ 1255.059025]  dma_buf_release+0x56/0x130
[ 1255.059443]  __fput+0xc6/0x260
[ 1255.059856]  delayed_fput+0x20/0x30
[ 1255.060272]  process_one_work+0x1fd/0x3f0
[ 1255.060686]  worker_thread+0x34/0x410
[ 1255.061099]  kthread+0x121/0x140
[ 1255.061510]  ? process_one_work+0x3f0/0x3f0
[ 1255.061923]  ? kthread_park+0xb0/0xb0
[ 1255.062336]  ret_from_fork+0x35/0x40
</pre>
              <p>drm_gem_object_put_unlocked calls drm_gem_object_free
                when the obj->refcount reaches 0. From there it calls
                dev->driver->gem_free_object_unlocked, which is
                amdgpu_gem_object_free in amdgpu.<br>
              </p>
              <p>Regards,<br>
                  Felix<br>
              </p>
              <div class="moz-cite-prefix">Am 2020-05-01 um 10:29 a.m.
                schrieb Christian König:<br>
              </div>
              <blockquote type="cite" cite="mid:70e5d202-34ed-532f-e6b6-c195a3effad3@gmail.com">Am
                01.05.20 um 16:21 schrieb Felix Kuehling: <br>
                <blockquote type="cite">From: Felix Kuehling <a class="moz-txt-link-rfc2396E" href="mailto:felix.kuehling@gmail.com" moz-do-not-send="true"><felix.kuehling@gmail.com></a>
                  <br>
                  <br>
                  That reference gets dropped when the the dma-buf is
                  freed. Not incrementing <br>
                  the refcount can lead to use-after-free errors. <br>
                  <br>
                  Signed-off-by: Felix Kuehling <a class="moz-txt-link-rfc2396E" href="mailto:felix.kuehling@gmail.com" moz-do-not-send="true"><felix.kuehling@gmail.com></a>
                  <br>
                  --- <br>
                    drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 9
                  ++++++++- <br>
                    1 file changed, 8 insertions(+), 1 deletion(-) <br>
                  <br>
                  diff --git
                  a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
                  b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c <br>
                  index ffeb20f11c07..a0f9b3ef4aad 100644 <br>
                  --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c <br>
                  +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c <br>
                  @@ -398,8 +398,15 @@ struct dma_buf
                  *amdgpu_gem_prime_export(struct drm_gem_object *gobj,
                  <br>
                            return ERR_PTR(-EPERM); <br>
                          buf = drm_gem_prime_export(gobj, flags); <br>
                  -    if (!IS_ERR(buf)) <br>
                  +    if (!IS_ERR(buf)) { <br>
                            buf->ops = &amdgpu_dmabuf_ops; <br>
                  +        /* GEM needs a reference to the underlying
                  object <br>
                  +         * that gets dropped when the dma-buf is
                  released, <br>
                  +         * through the amdgpu_gem_object_free
                  callback <br>
                  +         * from drm_gem_object_put_unlocked. <br>
                  +         */ <br>
                  +        amdgpu_bo_ref(bo); <br>
                  +    } <br>
                </blockquote>
                <br>
                Of hand that doesn't sounds correct to me. Why should
                the exported bo be closed through
                amdgpu_gem_object_free()? <br>
                <br>
                Regards, <br>
                Christian. <br>
                <br>
                <blockquote type="cite">        return buf; <br>
                    } <br>
                </blockquote>
                <br>
              </blockquote>
              <br>
              <fieldset class="mimeAttachmentHeader"></fieldset>
              <pre class="moz-quote-pre" wrap="">_______________________________________________
amd-gfx mailing list
<a class="moz-txt-link-abbreviated" href="mailto:amd-gfx@lists.freedesktop.org" moz-do-not-send="true">amd-gfx@lists.freedesktop.org</a>
<a class="moz-txt-link-freetext" href="https://lists.freedesktop.org/mailman/listinfo/amd-gfx" moz-do-not-send="true">https://lists.freedesktop.org/mailman/listinfo/amd-gfx</a>
</pre>
            </blockquote>
            <br>
          </blockquote>
        </blockquote>
        <br>
      </blockquote>
    </blockquote>
    <br>
  </body>
</html>