From dc84dbcc54d2f0f35942ca54aa7a04770aa97199 Mon Sep 17 00:00:00 2001 From: Alexandr Sapozhnikov Date: Mon, 22 Sep 2025 17:44:13 +0300 Subject: drm/virtio: Handle drm_crtc_init_with_planes() errors Return value of function drm_crtc_init_with_planes(), called by vgdev_output_init(), is not checked, but it is usually checked for this function. Found by Linux Verification Center (linuxtesting.org) with SVACE. Signed-off-by: Alexandr Sapozhnikov Reviewed-by: Dmitry Osipenko Signed-off-by: Dmitry Osipenko [dmitry.osipenko@collabora.com: coding style fix, edit commit message] Link: https://lore.kernel.org/r/20250922144418.41-1-alsp705@gmail.com --- drivers/gpu/drm/virtio/virtgpu_display.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/virtio/virtgpu_display.c') diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index c3315935d8bc..4b1252c04b7a 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -257,6 +257,7 @@ static int vgdev_output_init(struct virtio_gpu_device *vgdev, int index) struct drm_encoder *encoder = &output->enc; struct drm_crtc *crtc = &output->crtc; struct drm_plane *primary, *cursor; + int ret; output->index = index; if (index == 0) { @@ -271,8 +272,10 @@ static int vgdev_output_init(struct virtio_gpu_device *vgdev, int index) cursor = virtio_gpu_plane_init(vgdev, DRM_PLANE_TYPE_CURSOR, index); if (IS_ERR(cursor)) return PTR_ERR(cursor); - drm_crtc_init_with_planes(dev, crtc, primary, cursor, - &virtio_gpu_crtc_funcs, NULL); + ret = drm_crtc_init_with_planes(dev, crtc, primary, cursor, + &virtio_gpu_crtc_funcs, NULL); + if (ret) + return ret; drm_crtc_helper_add(crtc, &virtio_gpu_crtc_helper_funcs); drm_connector_init(dev, connector, &virtio_gpu_connector_funcs, -- cgit v1.2.3 From a036f5fceedb9fbd715565fef7b824a121503de7 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Wed, 8 Oct 2025 15:06:51 +0200 Subject: drm/virtgpu: Use vblank timer Use a vblank timer to simulate the vblank interrupt. The DRM vblank helpers provide an implementation on top of Linux' hrtimer. Virtgpu enables and disables the timer as part of the CRTC. The atomic_flush callback sets up the event. Like vblank interrupts, the vblank timer fires at the rate of the display refresh. Most userspace limits its page flip rate according to the DRM vblank event. Virtgpu's virtual hardware does not provide vblank interrupts, so DRM sends each event ASAP. With the fast access times of virtual display memory, the event rate is much higher than the display mode's refresh rate; creating the next page flip almost immediately. This leads to excessive CPU overhead from even small display updates, such as moving the mouse pointer. This problem affects virtgpu and all other virtual displays. See [1] for a discussion in the context of hypervdrm. Signed-off-by: Thomas Zimmermann Link: https://lore.kernel.org/dri-devel/SN6PR02MB415702B00D6D52B0EE962C98D46CA@SN6PR02MB4157.namprd02.prod.outlook.com/ # [1] Acked-by: Gerd Hoffmann Reviewed-by: Dmitry Osipenko Tested-by: Dmitry Osipenko Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20251008130701.246988-1-tzimmermann@suse.de --- drivers/gpu/drm/virtio/virtgpu_display.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/virtio/virtgpu_display.c') diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index 4b1252c04b7a..e972d9b015a9 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include "virtgpu_drv.h" @@ -55,6 +57,7 @@ static const struct drm_crtc_funcs virtio_gpu_crtc_funcs = { .reset = drm_atomic_helper_crtc_reset, .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, + DRM_CRTC_VBLANK_TIMER_FUNCS, }; static const struct drm_framebuffer_funcs virtio_gpu_fb_funcs = { @@ -99,6 +102,7 @@ static void virtio_gpu_crtc_mode_set_nofb(struct drm_crtc *crtc) static void virtio_gpu_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state) { + drm_crtc_vblank_on(crtc); } static void virtio_gpu_crtc_atomic_disable(struct drm_crtc *crtc, @@ -108,6 +112,8 @@ static void virtio_gpu_crtc_atomic_disable(struct drm_crtc *crtc, struct virtio_gpu_device *vgdev = dev->dev_private; struct virtio_gpu_output *output = drm_crtc_to_virtio_gpu_output(crtc); + drm_crtc_vblank_off(crtc); + virtio_gpu_cmd_set_scanout(vgdev, output->index, 0, 0, 0, 0, 0); virtio_gpu_notify(vgdev); } @@ -121,9 +127,10 @@ static int virtio_gpu_crtc_atomic_check(struct drm_crtc *crtc, static void virtio_gpu_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *state) { - struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, - crtc); + struct drm_device *dev = crtc->dev; + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); struct virtio_gpu_output *output = drm_crtc_to_virtio_gpu_output(crtc); + struct drm_pending_vblank_event *event; /* * virtio-gpu can't do modeset and plane update operations @@ -133,6 +140,20 @@ static void virtio_gpu_crtc_atomic_flush(struct drm_crtc *crtc, */ if (drm_atomic_crtc_needs_modeset(crtc_state)) output->needs_modeset = true; + + spin_lock_irq(&dev->event_lock); + + event = crtc_state->event; + crtc_state->event = NULL; + + if (event) { + if (drm_crtc_vblank_get(crtc) == 0) + drm_crtc_arm_vblank_event(crtc, event); + else + drm_crtc_send_vblank_event(crtc, event); + } + + spin_unlock_irq(&dev->event_lock); } static const struct drm_crtc_helper_funcs virtio_gpu_crtc_helper_funcs = { @@ -359,6 +380,10 @@ int virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev) for (i = 0 ; i < vgdev->num_scanouts; ++i) vgdev_output_init(vgdev, i); + ret = drm_vblank_init(vgdev->ddev, vgdev->num_scanouts); + if (ret) + return ret; + drm_mode_config_reset(vgdev->ddev); return 0; } -- cgit v1.2.3 From f6e8dc9edf963dbc99085e54f6ced6da9daa6100 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 29 Oct 2025 12:39:45 +0200 Subject: drm: include drm_print.h where needed There are a gazillion files that depend on drm_print.h being indirectly included via drm_buddy.h, drm_mm.h, or ttm/ttm_resource.h. In preparation for removing those includes, explicitly include drm_print.h where needed. Cc: Thomas Zimmermann Reviewed-by: Thomas Zimmermann Signed-off-by: Jani Nikula Link: https://lore.kernel.org/r/5fe67395907be33eb5199ea6d540e29fddee71c8.1761734313.git.jani.nikula@intel.com --- drivers/gpu/drm/virtio/virtgpu_display.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm/virtio/virtgpu_display.c') diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index e972d9b015a9..6a962c1d6e95 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3