[PATCH 03/25] dma-buf.rst: Document why idenfinite fences are a bad idea
Christian König
christian.koenig at amd.com
Thu Jul 9 11:53:14 UTC 2020
Am 07.07.20 um 22:12 schrieb Daniel Vetter:
> Comes up every few years, gets somewhat tedious to discuss, let's
> write this down once and for all.
>
> What I'm not sure about is whether the text should be more explicit in
> flat out mandating the amdkfd eviction fences for long running compute
> workloads or workloads where userspace fencing is allowed.
>
> v2: Now with dot graph!
>
> Cc: Jesse Natalie <jenatali at microsoft.com>
> Cc: Steve Pronovost <spronovo at microsoft.com>
> Cc: Jason Ekstrand <jason at jlekstrand.net>
> Cc: Felix Kuehling <Felix.Kuehling at amd.com>
> Cc: Mika Kuoppala <mika.kuoppala at intel.com>
> Cc: Thomas Hellstrom <thomas.hellstrom at intel.com>
> Cc: linux-media at vger.kernel.org
> Cc: linaro-mm-sig at lists.linaro.org
> Cc: linux-rdma at vger.kernel.org
> Cc: amd-gfx at lists.freedesktop.org
> Cc: intel-gfx at lists.freedesktop.org
> Cc: Chris Wilson <chris at chris-wilson.co.uk>
> Cc: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
> Cc: Christian König <christian.koenig at amd.com>
> Signed-off-by: Daniel Vetter <daniel.vetter at intel.com>
Acked-by: Christian König <christian.koenig at amd.com>
> ---
> Documentation/driver-api/dma-buf.rst | 70 ++++++++++++++++++++++++
> drivers/gpu/drm/virtio/virtgpu_display.c | 20 -------
> 2 files changed, 70 insertions(+), 20 deletions(-)
>
> diff --git a/Documentation/driver-api/dma-buf.rst b/Documentation/driver-api/dma-buf.rst
> index f8f6decde359..037ba0078bb4 100644
> --- a/Documentation/driver-api/dma-buf.rst
> +++ b/Documentation/driver-api/dma-buf.rst
> @@ -178,3 +178,73 @@ DMA Fence uABI/Sync File
> .. kernel-doc:: include/linux/sync_file.h
> :internal:
>
> +Idefinite DMA Fences
> +~~~~~~~~~~~~~~~~~~~~
> +
> +At various times &dma_fence with an indefinite time until dma_fence_wait()
> +finishes have been proposed. Examples include:
> +
> +* Future fences, used in HWC1 to signal when a buffer isn't used by the display
> + any longer, and created with the screen update that makes the buffer visible.
> + The time this fence completes is entirely under userspace's control.
> +
> +* Proxy fences, proposed to handle &drm_syncobj for which the fence has not yet
> + been set. Used to asynchronously delay command submission.
> +
> +* Userspace fences or gpu futexes, fine-grained locking within a command buffer
> + that userspace uses for synchronization across engines or with the CPU, which
> + are then imported as a DMA fence for integration into existing winsys
> + protocols.
> +
> +* Long-running compute command buffers, while still using traditional end of
> + batch DMA fences for memory management instead of context preemption DMA
> + fences which get reattached when the compute job is rescheduled.
> +
> +Common to all these schemes is that userspace controls the dependencies of these
> +fences and controls when they fire. Mixing indefinite fences with normal
> +in-kernel DMA fences does not work, even when a fallback timeout is included to
> +protect against malicious userspace:
> +
> +* Only the kernel knows about all DMA fence dependencies, userspace is not aware
> + of dependencies injected due to memory management or scheduler decisions.
> +
> +* Only userspace knows about all dependencies in indefinite fences and when
> + exactly they will complete, the kernel has no visibility.
> +
> +Furthermore the kernel has to be able to hold up userspace command submission
> +for memory management needs, which means we must support indefinite fences being
> +dependent upon DMA fences. If the kernel also support indefinite fences in the
> +kernel like a DMA fence, like any of the above proposal would, there is the
> +potential for deadlocks.
> +
> +.. kernel-render:: DOT
> + :alt: Indefinite Fencing Dependency Cycle
> + :caption: Indefinite Fencing Dependency Cycle
> +
> + digraph "Fencing Cycle" {
> + node [shape=box bgcolor=grey style=filled]
> + kernel [label="Kernel DMA Fences"]
> + userspace [label="userspace controlled fences"]
> + kernel -> userspace [label="memory management"]
> + userspace -> kernel [label="Future fence, fence proxy, ..."]
> +
> + { rank=same; kernel userspace }
> + }
> +
> +This means that the kernel might accidentally create deadlocks
> +through memory management dependencies which userspace is unaware of, which
> +randomly hangs workloads until the timeout kicks in. Workloads, which from
> +userspace's perspective, do not contain a deadlock. In such a mixed fencing
> +architecture there is no single entity with knowledge of all dependencies.
> +Thefore preventing such deadlocks from within the kernel is not possible.
> +
> +The only solution to avoid dependencies loops is by not allowing indefinite
> +fences in the kernel. This means:
> +
> +* No future fences, proxy fences or userspace fences imported as DMA fences,
> + with or without a timeout.
> +
> +* No DMA fences that signal end of batchbuffer for command submission where
> + userspace is allowed to use userspace fencing or long running compute
> + workloads. This also means no implicit fencing for shared buffers in these
> + cases.
> diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c
> index f3ce49c5a34c..af55b334be2f 100644
> --- a/drivers/gpu/drm/virtio/virtgpu_display.c
> +++ b/drivers/gpu/drm/virtio/virtgpu_display.c
> @@ -314,25 +314,6 @@ virtio_gpu_user_framebuffer_create(struct drm_device *dev,
> return &virtio_gpu_fb->base;
> }
>
> -static void vgdev_atomic_commit_tail(struct drm_atomic_state *state)
> -{
> - struct drm_device *dev = state->dev;
> -
> - drm_atomic_helper_commit_modeset_disables(dev, state);
> - drm_atomic_helper_commit_modeset_enables(dev, state);
> - drm_atomic_helper_commit_planes(dev, state, 0);
> -
> - drm_atomic_helper_fake_vblank(state);
> - drm_atomic_helper_commit_hw_done(state);
> -
> - drm_atomic_helper_wait_for_vblanks(dev, state);
> - drm_atomic_helper_cleanup_planes(dev, state);
> -}
> -
> -static const struct drm_mode_config_helper_funcs virtio_mode_config_helpers = {
> - .atomic_commit_tail = vgdev_atomic_commit_tail,
> -};
> -
> static const struct drm_mode_config_funcs virtio_gpu_mode_funcs = {
> .fb_create = virtio_gpu_user_framebuffer_create,
> .atomic_check = drm_atomic_helper_check,
> @@ -346,7 +327,6 @@ void virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev)
> drm_mode_config_init(vgdev->ddev);
> vgdev->ddev->mode_config.quirk_addfb_prefer_host_byte_order = true;
> vgdev->ddev->mode_config.funcs = &virtio_gpu_mode_funcs;
> - vgdev->ddev->mode_config.helper_private = &virtio_mode_config_helpers;
>
> /* modes will be validated against the framebuffer size */
> vgdev->ddev->mode_config.min_width = XRES_MIN;
More information about the amd-gfx
mailing list