dri-devel.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
* [PATCH drm-misc-next 0/1] add drm_panic_support for stdu
@ 2025-09-01  8:36 Ryosuke Yasuoka
  2025-09-01  8:36 ` [PATCH drm-misc-next 1/1] drm/vmwgfx: add drm_panic support " Ryosuke Yasuoka
  0 siblings, 1 reply; 6+ messages in thread
From: Ryosuke Yasuoka @ 2025-09-01  8:36 UTC (permalink / raw)
  To: zack.rusin, maarten.lankhorst, mripard, tzimmermann, airlied,
	simona, jfalempe
  Cc: Ryosuke Yasuoka, bcm-kernel-feedback-list, linux-kernel,
	dri-devel

Add drm_panic support for stdu in vmwgfx. This patch was tested in 
a VM with VMSVGA on Virtual Box.

Ryosuke Yasuoka (1):
  drm/vmwgfx: add drm_panic support for stdu

 drivers/gpu/drm/vmwgfx/vmwgfx_blit.c   |  43 ++++++++
 drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c |  11 ++
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.h    |   4 +
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c    |  48 +++++++++
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.h    |   1 +
 drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c   | 139 +++++++++++++++++++++++++
 6 files changed, 246 insertions(+)


base-commit: 73cfd166e045769a1b42d36897accaa6e06b8102
-- 
2.51.0


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH drm-misc-next 1/1] drm/vmwgfx: add drm_panic support for stdu
  2025-09-01  8:36 [PATCH drm-misc-next 0/1] add drm_panic_support for stdu Ryosuke Yasuoka
@ 2025-09-01  8:36 ` Ryosuke Yasuoka
  2025-09-02  8:02   ` Jocelyn Falempe
  0 siblings, 1 reply; 6+ messages in thread
From: Ryosuke Yasuoka @ 2025-09-01  8:36 UTC (permalink / raw)
  To: zack.rusin, maarten.lankhorst, mripard, tzimmermann, airlied,
	simona, jfalempe
  Cc: Ryosuke Yasuoka, bcm-kernel-feedback-list, linux-kernel,
	dri-devel

Add drm_panic module for vmwgfx stdu so that panic screen can be
displayed on panic.

Signed-off-by: Ryosuke Yasuoka <ryasuoka@redhat.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_blit.c   |  43 ++++++++
 drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c |  11 ++
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.h    |   4 +
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c    |  48 +++++++++
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.h    |   1 +
 drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c   | 139 +++++++++++++++++++++++++
 6 files changed, 246 insertions(+)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
index fa5841fda659..d7ed04531249 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
@@ -514,6 +514,49 @@ static int vmw_external_bo_copy(struct vmw_bo *dst, u32 dst_offset,
 	return ret;
 }
 
+/* For drm_panic */
+void vmw_panic_bo_cpu_blit(struct vmw_bo *vmw_dst, u32 dst_stride,
+			   struct vmw_bo *vmw_src, u32 src_stride,
+			   u32 w, u32 h, struct vmw_diff_cpy *diff)
+{
+	struct ttm_buffer_object *src = &vmw_src->tbo;
+	struct ttm_buffer_object *dst = &vmw_dst->tbo;
+	u32 j;
+	u32 initial_line = 0;
+	u32 dst_offset = 0;
+	u32 src_offset = 0;
+	int ret = 0;
+	struct vmw_bo_blit_line_data d = {
+		.mapped_dst = 0,
+		.mapped_src = 0,
+		.dst_addr = NULL,
+		.src_addr = NULL,
+		.dst_pages = dst->ttm->pages,
+		.src_pages = src->ttm->pages,
+		.dst_num_pages = PFN_UP(dst->resource->size),
+		.src_num_pages = PFN_UP(src->resource->size),
+		.dst_prot = ttm_io_prot(dst, dst->resource, PAGE_KERNEL),
+		.src_prot = ttm_io_prot(src, src->resource, PAGE_KERNEL),
+		.diff = diff,
+	};
+
+	for (j = 0; j < h; ++j) {
+		diff->line = j + initial_line;
+		diff->line_offset = dst_offset % dst_stride;
+		ret = vmw_bo_cpu_blit_line(&d, dst_offset, src_offset, w);
+		if (ret)
+			goto out;
+
+		dst_offset += dst_stride;
+		src_offset += src_stride;
+	}
+out:
+	if (d.src_addr)
+		kunmap_atomic(d.src_addr);
+	if (d.dst_addr)
+		kunmap_atomic(d.dst_addr);
+}
+
 /**
  * vmw_bo_cpu_blit - in-kernel cpu blit.
  *
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
index 94e8982f5616..e39cc2f214be 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
@@ -983,6 +983,17 @@ void *vmw_cmdbuf_alloc(struct vmw_cmdbuf_man *man,
 	return header->cmd;
 }
 
+/* For drm_panic */
+char *vmw_panic_cmdbuf_reserve_cur(struct vmw_cmdbuf_man *man, size_t size)
+{
+	/* Refer to cur without cur_mutex since this func is called in panic handler */
+	struct vmw_cmdbuf_header *cur = man->cur;
+
+	cur->reserved = size;
+
+	return (char *) (man->cur->cmd + man->cur_pos);
+}
+
 /**
  * vmw_cmdbuf_reserve_cur - Reserve space for commands in the current
  * command buffer.
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index eda5b6f8f4c4..c71ce975bf52 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -1271,6 +1271,7 @@ extern int vmw_cmdbuf_idle(struct vmw_cmdbuf_man *man, bool interruptible,
 extern void *vmw_cmdbuf_reserve(struct vmw_cmdbuf_man *man, size_t size,
 				int ctx_id, bool interruptible,
 				struct vmw_cmdbuf_header *header);
+extern char *vmw_panic_cmdbuf_reserve_cur(struct vmw_cmdbuf_man *man, size_t size);
 extern void vmw_cmdbuf_commit(struct vmw_cmdbuf_man *man, size_t size,
 			      struct vmw_cmdbuf_header *header,
 			      bool flush);
@@ -1329,6 +1330,9 @@ int vmw_bo_cpu_blit(struct vmw_bo *dst,
 		    u32 src_offset, u32 src_stride,
 		    u32 w, u32 h,
 		    struct vmw_diff_cpy *diff);
+void vmw_panic_bo_cpu_blit(struct vmw_bo *dst, u32 dst_stride,
+			   struct vmw_bo *src, u32 src_stride,
+			   u32 w, u32 h, struct vmw_diff_cpy *diff);
 
 /* Host messaging -vmwgfx_msg.c: */
 void vmw_disable_backdoor(void);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 54ea1b513950..160a4efbf342 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -1717,6 +1717,54 @@ void vmw_kms_lost_device(struct drm_device *dev)
 	drm_atomic_helper_shutdown(dev);
 }
 
+/* For drm_panic */
+int vmw_du_panic_helper_plane_update(struct vmw_du_update_plane *update)
+{
+	struct drm_plane_state *state = update->plane->state;
+	struct vmw_framebuffer_bo *vfbbo =
+		container_of(update->vfb, typeof(*vfbbo), base);
+	struct drm_rect src = drm_plane_state_src(state);
+	struct drm_rect clip = {
+		.x1 = 0,
+		.y1 = 0,
+		.x2 = (src.x2 >> 16) + !!(src.x2 & 0xFFFF),
+		.y2 = (src.y2 >> 16) + !!(src.y2 & 0xFFFF),
+	};
+	DECLARE_VAL_CONTEXT(val_ctx, NULL, 0);
+	uint32_t reserved_size = 0;
+	uint32_t submit_size = 0;
+	char *cmd;
+	int ret;
+
+	vmw_bo_placement_set(vfbbo->buffer,
+			     VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_GMR,
+			     VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_GMR);
+
+	ret = vmw_validation_add_bo(&val_ctx, vfbbo->buffer);
+	if (ret)
+		return ret;
+
+	ret = vmw_validation_prepare(&val_ctx, NULL, false);
+	if (ret)
+		return ret;
+
+	reserved_size = update->calc_fifo_size(update, 1);
+	cmd = vmw_panic_cmdbuf_reserve_cur(update->dev_priv->cman, reserved_size);
+	if (!cmd)
+		return -ENOMEM;
+
+	vmw_du_translate_to_crtc(state, &clip);
+
+	update->clip(update, cmd, &clip, 0, 0);
+	submit_size = update->post_clip(update, cmd, &clip);
+
+	vmw_cmd_commit(update->dev_priv, submit_size);
+
+	vmw_kms_helper_validation_finish(update->dev_priv, NULL, &val_ctx,
+					 NULL, NULL);
+	return ret;
+}
+
 /**
  * vmw_du_helper_plane_update - Helper to do plane update on a display unit.
  * @update: The closure structure.
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index 445471fe9be6..e6299390ffea 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -499,6 +499,7 @@ int vmw_kms_stdu_readback(struct vmw_private *dev_priv,
 			  struct drm_crtc *crtc);
 
 int vmw_du_helper_plane_update(struct vmw_du_update_plane *update);
+int vmw_du_panic_helper_plane_update(struct vmw_du_update_plane *update);
 
 /**
  * vmw_du_translate_to_crtc - Translate a rect from framebuffer to crtc
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index 20aab725e53a..65b41338c620 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -36,6 +36,7 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_damage_helper.h>
 #include <drm/drm_fourcc.h>
+#include <drm/drm_panic.h>
 #include <drm/drm_vblank.h>
 
 #define vmw_crtc_to_stdu(x) \
@@ -1164,6 +1165,66 @@ static uint32_t vmw_stdu_bo_clip_cpu(struct vmw_du_update_plane  *update,
 	return 0;
 }
 
+/* For drm_panic */
+static uint32_t
+vmw_stdu_panic_bo_populate_update_cpu(struct vmw_du_update_plane  *update, void *cmd,
+				      struct drm_rect *bb)
+{
+	struct vmw_du_update_plane_buffer *bo_update;
+	struct vmw_screen_target_display_unit *stdu;
+	struct vmw_framebuffer_bo *vfbbo;
+	struct vmw_diff_cpy diff = VMW_CPU_BLIT_DIFF_INITIALIZER(0);
+	struct vmw_stdu_update_gb_image *cmd_img = cmd;
+	struct vmw_stdu_update *cmd_update;
+	struct vmw_bo *src_bo, *dst_bo;
+	s32 src_pitch, dst_pitch;
+	s32 width, height;
+
+	bo_update = container_of(update, typeof(*bo_update), base);
+	stdu = container_of(update->du, typeof(*stdu), base);
+	vfbbo = container_of(update->vfb, typeof(*vfbbo), base);
+
+	width = bb->x2;
+	height = bb->y2;
+
+	diff.cpp = stdu->cpp;
+
+	dst_bo = stdu->display_srf->res.guest_memory_bo;
+	dst_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp;
+
+	src_bo = vfbbo->buffer;
+	src_pitch = update->vfb->base.pitches[0];
+
+	vmw_panic_bo_cpu_blit(dst_bo, dst_pitch, src_bo, src_pitch,
+			      width * stdu->cpp, height, &diff);
+
+	if (drm_rect_visible(&diff.rect)) {
+		SVGA3dBox *box = &cmd_img->body.box;
+
+		cmd_img->header.id = SVGA_3D_CMD_UPDATE_GB_IMAGE;
+		cmd_img->header.size = sizeof(cmd_img->body);
+		cmd_img->body.image.sid = stdu->display_srf->res.id;
+		cmd_img->body.image.face = 0;
+		cmd_img->body.image.mipmap = 0;
+
+		box->x = diff.rect.x1;
+		box->y = diff.rect.y1;
+		box->z = 0;
+		box->w = drm_rect_width(&diff.rect);
+		box->h = drm_rect_height(&diff.rect);
+		box->d = 1;
+
+		cmd_update = (struct vmw_stdu_update *)&cmd_img[1];
+		vmw_stdu_populate_update(cmd_update, stdu->base.unit,
+					 diff.rect.x1, diff.rect.x2,
+					 diff.rect.y1, diff.rect.y2);
+
+		return sizeof(*cmd_img) + sizeof(*cmd_update);
+	}
+
+	return 0;
+}
+
 static uint32_t
 vmw_stdu_bo_populate_update_cpu(struct vmw_du_update_plane  *update, void *cmd,
 				struct drm_rect *bb)
@@ -1228,6 +1289,28 @@ vmw_stdu_bo_populate_update_cpu(struct vmw_du_update_plane  *update, void *cmd,
 	return 0;
 }
 
+/* For drm_panic */
+static int vmw_stdu_panic_plane_update_bo(struct vmw_private *dev_priv,
+					  struct drm_plane *plane,
+					  struct vmw_framebuffer *vfb)
+{
+	struct vmw_du_update_plane_buffer bo_update;
+
+	memset(&bo_update, 0, sizeof(struct vmw_du_update_plane_buffer));
+	bo_update.base.plane = plane;
+	bo_update.base.old_state = plane->state;
+	bo_update.base.dev_priv = dev_priv;
+	bo_update.base.du = vmw_crtc_to_du(plane->state->crtc);
+	bo_update.base.vfb = vfb;
+
+	bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size_cpu;
+	bo_update.base.pre_clip = vmw_stdu_bo_pre_clip_cpu;
+	bo_update.base.clip = vmw_stdu_bo_clip_cpu;
+	bo_update.base.post_clip = vmw_stdu_panic_bo_populate_update_cpu;
+
+	return vmw_du_panic_helper_plane_update(&bo_update.base);
+}
+
 /**
  * vmw_stdu_plane_update_bo - Update display unit for bo backed fb.
  * @dev_priv: device private.
@@ -1458,6 +1541,60 @@ vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane,
 		vmw_fence_obj_unreference(&fence);
 }
 
+static int
+vmw_stdu_primary_plane_get_scanout_buffer(struct drm_plane *plane,
+					  struct drm_scanout_buffer *sb)
+{
+	struct vmw_framebuffer *vfb;
+	struct vmw_framebuffer_bo *vfbbo;
+	void *virtual;
+
+	if (!plane->state || !plane->state->fb || !plane->state->visible)
+		return -ENODEV;
+
+	vfb = vmw_framebuffer_to_vfb(plane->state->fb);
+
+	if (!vfb->bo)
+		return -ENODEV;
+
+	vfbbo = container_of(vfb, typeof(*vfbbo), base);
+	virtual = vmw_bo_map_and_cache(vfbbo->buffer);
+	if (!virtual)
+		return -ENODEV;
+	iosys_map_set_vaddr(&sb->map[0], virtual);
+
+	sb->format = plane->state->fb->format;
+	sb->width = plane->state->fb->width;
+	sb->height = plane->state->fb->height;
+	sb->pitch[0] = plane->state->fb->pitches[0];
+
+	return 0;
+}
+
+static void vmw_stdu_primary_plane_panic_flush(struct drm_plane *plane)
+{
+	struct drm_plane_state *state = plane->state;
+	struct vmw_plane_state *vps = vmw_plane_state_to_vps(state);
+	struct drm_crtc *crtc = state->crtc;
+	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
+	struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(state->fb);
+	struct vmw_screen_target_display_unit *stdu = vmw_crtc_to_stdu(crtc);
+	int ret;
+
+	stdu->display_srf = vmw_user_object_surface(&vps->uo);
+	stdu->content_fb_type = vps->content_fb_type;
+	stdu->cpp = vps->cpp;
+
+	ret = vmw_stdu_bind_st(dev_priv, stdu, &stdu->display_srf->res);
+	if (ret)
+		DRM_ERROR("Failed to bind surface to STDU.\n");
+
+	if (vfb->bo)
+		ret = vmw_stdu_panic_plane_update_bo(dev_priv, plane, vfb);
+	if (ret)
+		DRM_ERROR("Failed to update STDU.\n");
+}
+
 static void
 vmw_stdu_crtc_atomic_flush(struct drm_crtc *crtc,
 			   struct drm_atomic_state *state)
@@ -1506,6 +1643,8 @@ drm_plane_helper_funcs vmw_stdu_primary_plane_helper_funcs = {
 	.atomic_update = vmw_stdu_primary_plane_atomic_update,
 	.prepare_fb = vmw_stdu_primary_plane_prepare_fb,
 	.cleanup_fb = vmw_stdu_primary_plane_cleanup_fb,
+	.get_scanout_buffer = vmw_stdu_primary_plane_get_scanout_buffer,
+	.panic_flush = vmw_stdu_primary_plane_panic_flush,
 };
 
 static const struct drm_crtc_helper_funcs vmw_stdu_crtc_helper_funcs = {
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH drm-misc-next 1/1] drm/vmwgfx: add drm_panic support for stdu
  2025-09-01  8:36 ` [PATCH drm-misc-next 1/1] drm/vmwgfx: add drm_panic support " Ryosuke Yasuoka
@ 2025-09-02  8:02   ` Jocelyn Falempe
  2025-09-02 13:50     ` Ian Forbes
  0 siblings, 1 reply; 6+ messages in thread
From: Jocelyn Falempe @ 2025-09-02  8:02 UTC (permalink / raw)
  To: Ryosuke Yasuoka, zack.rusin, maarten.lankhorst, mripard,
	tzimmermann, airlied, simona
  Cc: bcm-kernel-feedback-list, linux-kernel, dri-devel

On 01/09/2025 10:36, Ryosuke Yasuoka wrote:
> Add drm_panic module for vmwgfx stdu so that panic screen can be
> displayed on panic.

Thanks for this work.

If I understand correctly, this will draw the panic screen to the vfbo 
buffer, and then in the panic_flush() function, use 
vmw_panic_bo_cpu_blit() to copy that to the guest_memory_bo.

I think it should be easier to directly write the panic screen to the 
guest_memory_bo.
To write to the guest_memory_bo, you can do something similar as 
vmw_bo_cpu_blit_line(), but using kmap_local_page_try_from_panic() 
instead of kmap_atomic_prot().

You will probably need a custom set_pixel() function, like what I've 
done for i915
https://elixir.bootlin.com/linux/v6.17-rc4/source/drivers/gpu/drm/xe/display/intel_bo.c#L98

Best regards,

-- 

Jocelyn

> 
> Signed-off-by: Ryosuke Yasuoka <ryasuoka@redhat.com>
> ---
>   drivers/gpu/drm/vmwgfx/vmwgfx_blit.c   |  43 ++++++++
>   drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c |  11 ++
>   drivers/gpu/drm/vmwgfx/vmwgfx_drv.h    |   4 +
>   drivers/gpu/drm/vmwgfx/vmwgfx_kms.c    |  48 +++++++++
>   drivers/gpu/drm/vmwgfx/vmwgfx_kms.h    |   1 +
>   drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c   | 139 +++++++++++++++++++++++++
>   6 files changed, 246 insertions(+)
> 
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
> index fa5841fda659..d7ed04531249 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
> @@ -514,6 +514,49 @@ static int vmw_external_bo_copy(struct vmw_bo *dst, u32 dst_offset,
>   	return ret;
>   }
>   
> +/* For drm_panic */
> +void vmw_panic_bo_cpu_blit(struct vmw_bo *vmw_dst, u32 dst_stride,
> +			   struct vmw_bo *vmw_src, u32 src_stride,
> +			   u32 w, u32 h, struct vmw_diff_cpy *diff)
> +{
> +	struct ttm_buffer_object *src = &vmw_src->tbo;
> +	struct ttm_buffer_object *dst = &vmw_dst->tbo;
> +	u32 j;
> +	u32 initial_line = 0;
> +	u32 dst_offset = 0;
> +	u32 src_offset = 0;
> +	int ret = 0;
> +	struct vmw_bo_blit_line_data d = {
> +		.mapped_dst = 0,
> +		.mapped_src = 0,
> +		.dst_addr = NULL,
> +		.src_addr = NULL,
> +		.dst_pages = dst->ttm->pages,
> +		.src_pages = src->ttm->pages,
> +		.dst_num_pages = PFN_UP(dst->resource->size),
> +		.src_num_pages = PFN_UP(src->resource->size),
> +		.dst_prot = ttm_io_prot(dst, dst->resource, PAGE_KERNEL),
> +		.src_prot = ttm_io_prot(src, src->resource, PAGE_KERNEL),
> +		.diff = diff,
> +	};
> +
> +	for (j = 0; j < h; ++j) {
> +		diff->line = j + initial_line;
> +		diff->line_offset = dst_offset % dst_stride;
> +		ret = vmw_bo_cpu_blit_line(&d, dst_offset, src_offset, w);
> +		if (ret)
> +			goto out;
> +
> +		dst_offset += dst_stride;
> +		src_offset += src_stride;
> +	}
> +out:
> +	if (d.src_addr)
> +		kunmap_atomic(d.src_addr);
> +	if (d.dst_addr)
> +		kunmap_atomic(d.dst_addr);
> +}
> +
>   /**
>    * vmw_bo_cpu_blit - in-kernel cpu blit.
>    *
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
> index 94e8982f5616..e39cc2f214be 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
> @@ -983,6 +983,17 @@ void *vmw_cmdbuf_alloc(struct vmw_cmdbuf_man *man,
>   	return header->cmd;
>   }
>   
> +/* For drm_panic */
> +char *vmw_panic_cmdbuf_reserve_cur(struct vmw_cmdbuf_man *man, size_t size)
> +{
> +	/* Refer to cur without cur_mutex since this func is called in panic handler */
> +	struct vmw_cmdbuf_header *cur = man->cur;
> +
> +	cur->reserved = size;
> +
> +	return (char *) (man->cur->cmd + man->cur_pos);
> +}
> +
>   /**
>    * vmw_cmdbuf_reserve_cur - Reserve space for commands in the current
>    * command buffer.
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
> index eda5b6f8f4c4..c71ce975bf52 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
> @@ -1271,6 +1271,7 @@ extern int vmw_cmdbuf_idle(struct vmw_cmdbuf_man *man, bool interruptible,
>   extern void *vmw_cmdbuf_reserve(struct vmw_cmdbuf_man *man, size_t size,
>   				int ctx_id, bool interruptible,
>   				struct vmw_cmdbuf_header *header);
> +extern char *vmw_panic_cmdbuf_reserve_cur(struct vmw_cmdbuf_man *man, size_t size);
>   extern void vmw_cmdbuf_commit(struct vmw_cmdbuf_man *man, size_t size,
>   			      struct vmw_cmdbuf_header *header,
>   			      bool flush);
> @@ -1329,6 +1330,9 @@ int vmw_bo_cpu_blit(struct vmw_bo *dst,
>   		    u32 src_offset, u32 src_stride,
>   		    u32 w, u32 h,
>   		    struct vmw_diff_cpy *diff);
> +void vmw_panic_bo_cpu_blit(struct vmw_bo *dst, u32 dst_stride,
> +			   struct vmw_bo *src, u32 src_stride,
> +			   u32 w, u32 h, struct vmw_diff_cpy *diff);
>   
>   /* Host messaging -vmwgfx_msg.c: */
>   void vmw_disable_backdoor(void);
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> index 54ea1b513950..160a4efbf342 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> @@ -1717,6 +1717,54 @@ void vmw_kms_lost_device(struct drm_device *dev)
>   	drm_atomic_helper_shutdown(dev);
>   }
>   
> +/* For drm_panic */
> +int vmw_du_panic_helper_plane_update(struct vmw_du_update_plane *update)
> +{
> +	struct drm_plane_state *state = update->plane->state;
> +	struct vmw_framebuffer_bo *vfbbo =
> +		container_of(update->vfb, typeof(*vfbbo), base);
> +	struct drm_rect src = drm_plane_state_src(state);
> +	struct drm_rect clip = {
> +		.x1 = 0,
> +		.y1 = 0,
> +		.x2 = (src.x2 >> 16) + !!(src.x2 & 0xFFFF),
> +		.y2 = (src.y2 >> 16) + !!(src.y2 & 0xFFFF),
> +	};
> +	DECLARE_VAL_CONTEXT(val_ctx, NULL, 0);
> +	uint32_t reserved_size = 0;
> +	uint32_t submit_size = 0;
> +	char *cmd;
> +	int ret;
> +
> +	vmw_bo_placement_set(vfbbo->buffer,
> +			     VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_GMR,
> +			     VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_GMR);
> +
> +	ret = vmw_validation_add_bo(&val_ctx, vfbbo->buffer);
> +	if (ret)
> +		return ret;
> +
> +	ret = vmw_validation_prepare(&val_ctx, NULL, false);
> +	if (ret)
> +		return ret;
> +
> +	reserved_size = update->calc_fifo_size(update, 1);
> +	cmd = vmw_panic_cmdbuf_reserve_cur(update->dev_priv->cman, reserved_size);
> +	if (!cmd)
> +		return -ENOMEM;
> +
> +	vmw_du_translate_to_crtc(state, &clip);
> +
> +	update->clip(update, cmd, &clip, 0, 0);
> +	submit_size = update->post_clip(update, cmd, &clip);
> +
> +	vmw_cmd_commit(update->dev_priv, submit_size);
> +
> +	vmw_kms_helper_validation_finish(update->dev_priv, NULL, &val_ctx,
> +					 NULL, NULL);
> +	return ret;
> +}
> +
>   /**
>    * vmw_du_helper_plane_update - Helper to do plane update on a display unit.
>    * @update: The closure structure.
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> index 445471fe9be6..e6299390ffea 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> @@ -499,6 +499,7 @@ int vmw_kms_stdu_readback(struct vmw_private *dev_priv,
>   			  struct drm_crtc *crtc);
>   
>   int vmw_du_helper_plane_update(struct vmw_du_update_plane *update);
> +int vmw_du_panic_helper_plane_update(struct vmw_du_update_plane *update);
>   
>   /**
>    * vmw_du_translate_to_crtc - Translate a rect from framebuffer to crtc
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> index 20aab725e53a..65b41338c620 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> @@ -36,6 +36,7 @@
>   #include <drm/drm_atomic_helper.h>
>   #include <drm/drm_damage_helper.h>
>   #include <drm/drm_fourcc.h>
> +#include <drm/drm_panic.h>
>   #include <drm/drm_vblank.h>
>   
>   #define vmw_crtc_to_stdu(x) \
> @@ -1164,6 +1165,66 @@ static uint32_t vmw_stdu_bo_clip_cpu(struct vmw_du_update_plane  *update,
>   	return 0;
>   }
>   
> +/* For drm_panic */
> +static uint32_t
> +vmw_stdu_panic_bo_populate_update_cpu(struct vmw_du_update_plane  *update, void *cmd,
> +				      struct drm_rect *bb)
> +{
> +	struct vmw_du_update_plane_buffer *bo_update;
> +	struct vmw_screen_target_display_unit *stdu;
> +	struct vmw_framebuffer_bo *vfbbo;
> +	struct vmw_diff_cpy diff = VMW_CPU_BLIT_DIFF_INITIALIZER(0);
> +	struct vmw_stdu_update_gb_image *cmd_img = cmd;
> +	struct vmw_stdu_update *cmd_update;
> +	struct vmw_bo *src_bo, *dst_bo;
> +	s32 src_pitch, dst_pitch;
> +	s32 width, height;
> +
> +	bo_update = container_of(update, typeof(*bo_update), base);
> +	stdu = container_of(update->du, typeof(*stdu), base);
> +	vfbbo = container_of(update->vfb, typeof(*vfbbo), base);
> +
> +	width = bb->x2;
> +	height = bb->y2;
> +
> +	diff.cpp = stdu->cpp;
> +
> +	dst_bo = stdu->display_srf->res.guest_memory_bo;
> +	dst_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp;
> +
> +	src_bo = vfbbo->buffer;
> +	src_pitch = update->vfb->base.pitches[0];
> +
> +	vmw_panic_bo_cpu_blit(dst_bo, dst_pitch, src_bo, src_pitch,
> +			      width * stdu->cpp, height, &diff);
> +
> +	if (drm_rect_visible(&diff.rect)) {
> +		SVGA3dBox *box = &cmd_img->body.box;
> +
> +		cmd_img->header.id = SVGA_3D_CMD_UPDATE_GB_IMAGE;
> +		cmd_img->header.size = sizeof(cmd_img->body);
> +		cmd_img->body.image.sid = stdu->display_srf->res.id;
> +		cmd_img->body.image.face = 0;
> +		cmd_img->body.image.mipmap = 0;
> +
> +		box->x = diff.rect.x1;
> +		box->y = diff.rect.y1;
> +		box->z = 0;
> +		box->w = drm_rect_width(&diff.rect);
> +		box->h = drm_rect_height(&diff.rect);
> +		box->d = 1;
> +
> +		cmd_update = (struct vmw_stdu_update *)&cmd_img[1];
> +		vmw_stdu_populate_update(cmd_update, stdu->base.unit,
> +					 diff.rect.x1, diff.rect.x2,
> +					 diff.rect.y1, diff.rect.y2);
> +
> +		return sizeof(*cmd_img) + sizeof(*cmd_update);
> +	}
> +
> +	return 0;
> +}
> +
>   static uint32_t
>   vmw_stdu_bo_populate_update_cpu(struct vmw_du_update_plane  *update, void *cmd,
>   				struct drm_rect *bb)
> @@ -1228,6 +1289,28 @@ vmw_stdu_bo_populate_update_cpu(struct vmw_du_update_plane  *update, void *cmd,
>   	return 0;
>   }
>   
> +/* For drm_panic */
> +static int vmw_stdu_panic_plane_update_bo(struct vmw_private *dev_priv,
> +					  struct drm_plane *plane,
> +					  struct vmw_framebuffer *vfb)
> +{
> +	struct vmw_du_update_plane_buffer bo_update;
> +
> +	memset(&bo_update, 0, sizeof(struct vmw_du_update_plane_buffer));
> +	bo_update.base.plane = plane;
> +	bo_update.base.old_state = plane->state;
> +	bo_update.base.dev_priv = dev_priv;
> +	bo_update.base.du = vmw_crtc_to_du(plane->state->crtc);
> +	bo_update.base.vfb = vfb;
> +
> +	bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size_cpu;
> +	bo_update.base.pre_clip = vmw_stdu_bo_pre_clip_cpu;
> +	bo_update.base.clip = vmw_stdu_bo_clip_cpu;
> +	bo_update.base.post_clip = vmw_stdu_panic_bo_populate_update_cpu;
> +
> +	return vmw_du_panic_helper_plane_update(&bo_update.base);
> +}
> +
>   /**
>    * vmw_stdu_plane_update_bo - Update display unit for bo backed fb.
>    * @dev_priv: device private.
> @@ -1458,6 +1541,60 @@ vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane,
>   		vmw_fence_obj_unreference(&fence);
>   }
>   
> +static int
> +vmw_stdu_primary_plane_get_scanout_buffer(struct drm_plane *plane,
> +					  struct drm_scanout_buffer *sb)
> +{
> +	struct vmw_framebuffer *vfb;
> +	struct vmw_framebuffer_bo *vfbbo;
> +	void *virtual;
> +
> +	if (!plane->state || !plane->state->fb || !plane->state->visible)
> +		return -ENODEV;
> +
> +	vfb = vmw_framebuffer_to_vfb(plane->state->fb);
> +
> +	if (!vfb->bo)
> +		return -ENODEV;
> +
> +	vfbbo = container_of(vfb, typeof(*vfbbo), base);
> +	virtual = vmw_bo_map_and_cache(vfbbo->buffer);
> +	if (!virtual)
> +		return -ENODEV;
> +	iosys_map_set_vaddr(&sb->map[0], virtual);
> +
> +	sb->format = plane->state->fb->format;
> +	sb->width = plane->state->fb->width;
> +	sb->height = plane->state->fb->height;
> +	sb->pitch[0] = plane->state->fb->pitches[0];
> +
> +	return 0;
> +}
> +
> +static void vmw_stdu_primary_plane_panic_flush(struct drm_plane *plane)
> +{
> +	struct drm_plane_state *state = plane->state;
> +	struct vmw_plane_state *vps = vmw_plane_state_to_vps(state);
> +	struct drm_crtc *crtc = state->crtc;
> +	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
> +	struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(state->fb);
> +	struct vmw_screen_target_display_unit *stdu = vmw_crtc_to_stdu(crtc);
> +	int ret;
> +
> +	stdu->display_srf = vmw_user_object_surface(&vps->uo);
> +	stdu->content_fb_type = vps->content_fb_type;
> +	stdu->cpp = vps->cpp;
> +
> +	ret = vmw_stdu_bind_st(dev_priv, stdu, &stdu->display_srf->res);
> +	if (ret)
> +		DRM_ERROR("Failed to bind surface to STDU.\n");
> +
> +	if (vfb->bo)
> +		ret = vmw_stdu_panic_plane_update_bo(dev_priv, plane, vfb);
> +	if (ret)
> +		DRM_ERROR("Failed to update STDU.\n");
> +}
> +
>   static void
>   vmw_stdu_crtc_atomic_flush(struct drm_crtc *crtc,
>   			   struct drm_atomic_state *state)
> @@ -1506,6 +1643,8 @@ drm_plane_helper_funcs vmw_stdu_primary_plane_helper_funcs = {
>   	.atomic_update = vmw_stdu_primary_plane_atomic_update,
>   	.prepare_fb = vmw_stdu_primary_plane_prepare_fb,
>   	.cleanup_fb = vmw_stdu_primary_plane_cleanup_fb,
> +	.get_scanout_buffer = vmw_stdu_primary_plane_get_scanout_buffer,
> +	.panic_flush = vmw_stdu_primary_plane_panic_flush,
>   };
>   
>   static const struct drm_crtc_helper_funcs vmw_stdu_crtc_helper_funcs = {


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH drm-misc-next 1/1] drm/vmwgfx: add drm_panic support for stdu
  2025-09-02  8:02   ` Jocelyn Falempe
@ 2025-09-02 13:50     ` Ian Forbes
  2025-09-02 16:28       ` Ryosuke Yasuoka
  0 siblings, 1 reply; 6+ messages in thread
From: Ian Forbes @ 2025-09-02 13:50 UTC (permalink / raw)
  To: Jocelyn Falempe
  Cc: Ryosuke Yasuoka, zack.rusin, maarten.lankhorst, mripard,
	tzimmermann, airlied, simona, bcm-kernel-feedback-list,
	linux-kernel, dri-devel

[-- Attachment #1: Type: text/plain, Size: 16404 bytes --]

I don't think this is the right approach. It would be better to write
to VRAM and then switch back to legacy mode. That shouldn't require
any allocations or command submissions which are unlikely to succeed
in a panic situation.

On Tue, Sep 2, 2025 at 3:02 AM Jocelyn Falempe <jfalempe@redhat.com> wrote:
>
> On 01/09/2025 10:36, Ryosuke Yasuoka wrote:
> > Add drm_panic module for vmwgfx stdu so that panic screen can be
> > displayed on panic.
>
> Thanks for this work.
>
> If I understand correctly, this will draw the panic screen to the vfbo
> buffer, and then in the panic_flush() function, use
> vmw_panic_bo_cpu_blit() to copy that to the guest_memory_bo.
>
> I think it should be easier to directly write the panic screen to the
> guest_memory_bo.
> To write to the guest_memory_bo, you can do something similar as
> vmw_bo_cpu_blit_line(), but using kmap_local_page_try_from_panic()
> instead of kmap_atomic_prot().
>
> You will probably need a custom set_pixel() function, like what I've
> done for i915
> https://elixir.bootlin.com/linux/v6.17-rc4/source/drivers/gpu/drm/xe/display/intel_bo.c#L98
>
> Best regards,
>
> --
>
> Jocelyn
>
> >
> > Signed-off-by: Ryosuke Yasuoka <ryasuoka@redhat.com>
> > ---
> >   drivers/gpu/drm/vmwgfx/vmwgfx_blit.c   |  43 ++++++++
> >   drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c |  11 ++
> >   drivers/gpu/drm/vmwgfx/vmwgfx_drv.h    |   4 +
> >   drivers/gpu/drm/vmwgfx/vmwgfx_kms.c    |  48 +++++++++
> >   drivers/gpu/drm/vmwgfx/vmwgfx_kms.h    |   1 +
> >   drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c   | 139 +++++++++++++++++++++++++
> >   6 files changed, 246 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
> > index fa5841fda659..d7ed04531249 100644
> > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
> > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
> > @@ -514,6 +514,49 @@ static int vmw_external_bo_copy(struct vmw_bo *dst, u32 dst_offset,
> >       return ret;
> >   }
> >
> > +/* For drm_panic */
> > +void vmw_panic_bo_cpu_blit(struct vmw_bo *vmw_dst, u32 dst_stride,
> > +                        struct vmw_bo *vmw_src, u32 src_stride,
> > +                        u32 w, u32 h, struct vmw_diff_cpy *diff)
> > +{
> > +     struct ttm_buffer_object *src = &vmw_src->tbo;
> > +     struct ttm_buffer_object *dst = &vmw_dst->tbo;
> > +     u32 j;
> > +     u32 initial_line = 0;
> > +     u32 dst_offset = 0;
> > +     u32 src_offset = 0;
> > +     int ret = 0;
> > +     struct vmw_bo_blit_line_data d = {
> > +             .mapped_dst = 0,
> > +             .mapped_src = 0,
> > +             .dst_addr = NULL,
> > +             .src_addr = NULL,
> > +             .dst_pages = dst->ttm->pages,
> > +             .src_pages = src->ttm->pages,
> > +             .dst_num_pages = PFN_UP(dst->resource->size),
> > +             .src_num_pages = PFN_UP(src->resource->size),
> > +             .dst_prot = ttm_io_prot(dst, dst->resource, PAGE_KERNEL),
> > +             .src_prot = ttm_io_prot(src, src->resource, PAGE_KERNEL),
> > +             .diff = diff,
> > +     };
> > +
> > +     for (j = 0; j < h; ++j) {
> > +             diff->line = j + initial_line;
> > +             diff->line_offset = dst_offset % dst_stride;
> > +             ret = vmw_bo_cpu_blit_line(&d, dst_offset, src_offset, w);
> > +             if (ret)
> > +                     goto out;
> > +
> > +             dst_offset += dst_stride;
> > +             src_offset += src_stride;
> > +     }
> > +out:
> > +     if (d.src_addr)
> > +             kunmap_atomic(d.src_addr);
> > +     if (d.dst_addr)
> > +             kunmap_atomic(d.dst_addr);
> > +}
> > +
> >   /**
> >    * vmw_bo_cpu_blit - in-kernel cpu blit.
> >    *
> > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
> > index 94e8982f5616..e39cc2f214be 100644
> > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
> > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
> > @@ -983,6 +983,17 @@ void *vmw_cmdbuf_alloc(struct vmw_cmdbuf_man *man,
> >       return header->cmd;
> >   }
> >
> > +/* For drm_panic */
> > +char *vmw_panic_cmdbuf_reserve_cur(struct vmw_cmdbuf_man *man, size_t size)
> > +{
> > +     /* Refer to cur without cur_mutex since this func is called in panic handler */
> > +     struct vmw_cmdbuf_header *cur = man->cur;
> > +
> > +     cur->reserved = size;
> > +
> > +     return (char *) (man->cur->cmd + man->cur_pos);
> > +}
> > +
> >   /**
> >    * vmw_cmdbuf_reserve_cur - Reserve space for commands in the current
> >    * command buffer.
> > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
> > index eda5b6f8f4c4..c71ce975bf52 100644
> > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
> > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
> > @@ -1271,6 +1271,7 @@ extern int vmw_cmdbuf_idle(struct vmw_cmdbuf_man *man, bool interruptible,
> >   extern void *vmw_cmdbuf_reserve(struct vmw_cmdbuf_man *man, size_t size,
> >                               int ctx_id, bool interruptible,
> >                               struct vmw_cmdbuf_header *header);
> > +extern char *vmw_panic_cmdbuf_reserve_cur(struct vmw_cmdbuf_man *man, size_t size);
> >   extern void vmw_cmdbuf_commit(struct vmw_cmdbuf_man *man, size_t size,
> >                             struct vmw_cmdbuf_header *header,
> >                             bool flush);
> > @@ -1329,6 +1330,9 @@ int vmw_bo_cpu_blit(struct vmw_bo *dst,
> >                   u32 src_offset, u32 src_stride,
> >                   u32 w, u32 h,
> >                   struct vmw_diff_cpy *diff);
> > +void vmw_panic_bo_cpu_blit(struct vmw_bo *dst, u32 dst_stride,
> > +                        struct vmw_bo *src, u32 src_stride,
> > +                        u32 w, u32 h, struct vmw_diff_cpy *diff);
> >
> >   /* Host messaging -vmwgfx_msg.c: */
> >   void vmw_disable_backdoor(void);
> > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> > index 54ea1b513950..160a4efbf342 100644
> > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> > @@ -1717,6 +1717,54 @@ void vmw_kms_lost_device(struct drm_device *dev)
> >       drm_atomic_helper_shutdown(dev);
> >   }
> >
> > +/* For drm_panic */
> > +int vmw_du_panic_helper_plane_update(struct vmw_du_update_plane *update)
> > +{
> > +     struct drm_plane_state *state = update->plane->state;
> > +     struct vmw_framebuffer_bo *vfbbo =
> > +             container_of(update->vfb, typeof(*vfbbo), base);
> > +     struct drm_rect src = drm_plane_state_src(state);
> > +     struct drm_rect clip = {
> > +             .x1 = 0,
> > +             .y1 = 0,
> > +             .x2 = (src.x2 >> 16) + !!(src.x2 & 0xFFFF),
> > +             .y2 = (src.y2 >> 16) + !!(src.y2 & 0xFFFF),
> > +     };
> > +     DECLARE_VAL_CONTEXT(val_ctx, NULL, 0);
> > +     uint32_t reserved_size = 0;
> > +     uint32_t submit_size = 0;
> > +     char *cmd;
> > +     int ret;
> > +
> > +     vmw_bo_placement_set(vfbbo->buffer,
> > +                          VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_GMR,
> > +                          VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_GMR);
> > +
> > +     ret = vmw_validation_add_bo(&val_ctx, vfbbo->buffer);
> > +     if (ret)
> > +             return ret;
> > +
> > +     ret = vmw_validation_prepare(&val_ctx, NULL, false);
> > +     if (ret)
> > +             return ret;
> > +
> > +     reserved_size = update->calc_fifo_size(update, 1);
> > +     cmd = vmw_panic_cmdbuf_reserve_cur(update->dev_priv->cman, reserved_size);
> > +     if (!cmd)
> > +             return -ENOMEM;
> > +
> > +     vmw_du_translate_to_crtc(state, &clip);
> > +
> > +     update->clip(update, cmd, &clip, 0, 0);
> > +     submit_size = update->post_clip(update, cmd, &clip);
> > +
> > +     vmw_cmd_commit(update->dev_priv, submit_size);
> > +
> > +     vmw_kms_helper_validation_finish(update->dev_priv, NULL, &val_ctx,
> > +                                      NULL, NULL);
> > +     return ret;
> > +}
> > +
> >   /**
> >    * vmw_du_helper_plane_update - Helper to do plane update on a display unit.
> >    * @update: The closure structure.
> > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> > index 445471fe9be6..e6299390ffea 100644
> > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> > @@ -499,6 +499,7 @@ int vmw_kms_stdu_readback(struct vmw_private *dev_priv,
> >                         struct drm_crtc *crtc);
> >
> >   int vmw_du_helper_plane_update(struct vmw_du_update_plane *update);
> > +int vmw_du_panic_helper_plane_update(struct vmw_du_update_plane *update);
> >
> >   /**
> >    * vmw_du_translate_to_crtc - Translate a rect from framebuffer to crtc
> > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> > index 20aab725e53a..65b41338c620 100644
> > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> > @@ -36,6 +36,7 @@
> >   #include <drm/drm_atomic_helper.h>
> >   #include <drm/drm_damage_helper.h>
> >   #include <drm/drm_fourcc.h>
> > +#include <drm/drm_panic.h>
> >   #include <drm/drm_vblank.h>
> >
> >   #define vmw_crtc_to_stdu(x) \
> > @@ -1164,6 +1165,66 @@ static uint32_t vmw_stdu_bo_clip_cpu(struct vmw_du_update_plane  *update,
> >       return 0;
> >   }
> >
> > +/* For drm_panic */
> > +static uint32_t
> > +vmw_stdu_panic_bo_populate_update_cpu(struct vmw_du_update_plane  *update, void *cmd,
> > +                                   struct drm_rect *bb)
> > +{
> > +     struct vmw_du_update_plane_buffer *bo_update;
> > +     struct vmw_screen_target_display_unit *stdu;
> > +     struct vmw_framebuffer_bo *vfbbo;
> > +     struct vmw_diff_cpy diff = VMW_CPU_BLIT_DIFF_INITIALIZER(0);
> > +     struct vmw_stdu_update_gb_image *cmd_img = cmd;
> > +     struct vmw_stdu_update *cmd_update;
> > +     struct vmw_bo *src_bo, *dst_bo;
> > +     s32 src_pitch, dst_pitch;
> > +     s32 width, height;
> > +
> > +     bo_update = container_of(update, typeof(*bo_update), base);
> > +     stdu = container_of(update->du, typeof(*stdu), base);
> > +     vfbbo = container_of(update->vfb, typeof(*vfbbo), base);
> > +
> > +     width = bb->x2;
> > +     height = bb->y2;
> > +
> > +     diff.cpp = stdu->cpp;
> > +
> > +     dst_bo = stdu->display_srf->res.guest_memory_bo;
> > +     dst_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp;
> > +
> > +     src_bo = vfbbo->buffer;
> > +     src_pitch = update->vfb->base.pitches[0];
> > +
> > +     vmw_panic_bo_cpu_blit(dst_bo, dst_pitch, src_bo, src_pitch,
> > +                           width * stdu->cpp, height, &diff);
> > +
> > +     if (drm_rect_visible(&diff.rect)) {
> > +             SVGA3dBox *box = &cmd_img->body.box;
> > +
> > +             cmd_img->header.id = SVGA_3D_CMD_UPDATE_GB_IMAGE;
> > +             cmd_img->header.size = sizeof(cmd_img->body);
> > +             cmd_img->body.image.sid = stdu->display_srf->res.id;
> > +             cmd_img->body.image.face = 0;
> > +             cmd_img->body.image.mipmap = 0;
> > +
> > +             box->x = diff.rect.x1;
> > +             box->y = diff.rect.y1;
> > +             box->z = 0;
> > +             box->w = drm_rect_width(&diff.rect);
> > +             box->h = drm_rect_height(&diff.rect);
> > +             box->d = 1;
> > +
> > +             cmd_update = (struct vmw_stdu_update *)&cmd_img[1];
> > +             vmw_stdu_populate_update(cmd_update, stdu->base.unit,
> > +                                      diff.rect.x1, diff.rect.x2,
> > +                                      diff.rect.y1, diff.rect.y2);
> > +
> > +             return sizeof(*cmd_img) + sizeof(*cmd_update);
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> >   static uint32_t
> >   vmw_stdu_bo_populate_update_cpu(struct vmw_du_update_plane  *update, void *cmd,
> >                               struct drm_rect *bb)
> > @@ -1228,6 +1289,28 @@ vmw_stdu_bo_populate_update_cpu(struct vmw_du_update_plane  *update, void *cmd,
> >       return 0;
> >   }
> >
> > +/* For drm_panic */
> > +static int vmw_stdu_panic_plane_update_bo(struct vmw_private *dev_priv,
> > +                                       struct drm_plane *plane,
> > +                                       struct vmw_framebuffer *vfb)
> > +{
> > +     struct vmw_du_update_plane_buffer bo_update;
> > +
> > +     memset(&bo_update, 0, sizeof(struct vmw_du_update_plane_buffer));
> > +     bo_update.base.plane = plane;
> > +     bo_update.base.old_state = plane->state;
> > +     bo_update.base.dev_priv = dev_priv;
> > +     bo_update.base.du = vmw_crtc_to_du(plane->state->crtc);
> > +     bo_update.base.vfb = vfb;
> > +
> > +     bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size_cpu;
> > +     bo_update.base.pre_clip = vmw_stdu_bo_pre_clip_cpu;
> > +     bo_update.base.clip = vmw_stdu_bo_clip_cpu;
> > +     bo_update.base.post_clip = vmw_stdu_panic_bo_populate_update_cpu;
> > +
> > +     return vmw_du_panic_helper_plane_update(&bo_update.base);
> > +}
> > +
> >   /**
> >    * vmw_stdu_plane_update_bo - Update display unit for bo backed fb.
> >    * @dev_priv: device private.
> > @@ -1458,6 +1541,60 @@ vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane,
> >               vmw_fence_obj_unreference(&fence);
> >   }
> >
> > +static int
> > +vmw_stdu_primary_plane_get_scanout_buffer(struct drm_plane *plane,
> > +                                       struct drm_scanout_buffer *sb)
> > +{
> > +     struct vmw_framebuffer *vfb;
> > +     struct vmw_framebuffer_bo *vfbbo;
> > +     void *virtual;
> > +
> > +     if (!plane->state || !plane->state->fb || !plane->state->visible)
> > +             return -ENODEV;
> > +
> > +     vfb = vmw_framebuffer_to_vfb(plane->state->fb);
> > +
> > +     if (!vfb->bo)
> > +             return -ENODEV;
> > +
> > +     vfbbo = container_of(vfb, typeof(*vfbbo), base);
> > +     virtual = vmw_bo_map_and_cache(vfbbo->buffer);
> > +     if (!virtual)
> > +             return -ENODEV;
> > +     iosys_map_set_vaddr(&sb->map[0], virtual);
> > +
> > +     sb->format = plane->state->fb->format;
> > +     sb->width = plane->state->fb->width;
> > +     sb->height = plane->state->fb->height;
> > +     sb->pitch[0] = plane->state->fb->pitches[0];
> > +
> > +     return 0;
> > +}
> > +
> > +static void vmw_stdu_primary_plane_panic_flush(struct drm_plane *plane)
> > +{
> > +     struct drm_plane_state *state = plane->state;
> > +     struct vmw_plane_state *vps = vmw_plane_state_to_vps(state);
> > +     struct drm_crtc *crtc = state->crtc;
> > +     struct vmw_private *dev_priv = vmw_priv(crtc->dev);
> > +     struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(state->fb);
> > +     struct vmw_screen_target_display_unit *stdu = vmw_crtc_to_stdu(crtc);
> > +     int ret;
> > +
> > +     stdu->display_srf = vmw_user_object_surface(&vps->uo);
> > +     stdu->content_fb_type = vps->content_fb_type;
> > +     stdu->cpp = vps->cpp;
> > +
> > +     ret = vmw_stdu_bind_st(dev_priv, stdu, &stdu->display_srf->res);
> > +     if (ret)
> > +             DRM_ERROR("Failed to bind surface to STDU.\n");
> > +
> > +     if (vfb->bo)
> > +             ret = vmw_stdu_panic_plane_update_bo(dev_priv, plane, vfb);
> > +     if (ret)
> > +             DRM_ERROR("Failed to update STDU.\n");
> > +}
> > +
> >   static void
> >   vmw_stdu_crtc_atomic_flush(struct drm_crtc *crtc,
> >                          struct drm_atomic_state *state)
> > @@ -1506,6 +1643,8 @@ drm_plane_helper_funcs vmw_stdu_primary_plane_helper_funcs = {
> >       .atomic_update = vmw_stdu_primary_plane_atomic_update,
> >       .prepare_fb = vmw_stdu_primary_plane_prepare_fb,
> >       .cleanup_fb = vmw_stdu_primary_plane_cleanup_fb,
> > +     .get_scanout_buffer = vmw_stdu_primary_plane_get_scanout_buffer,
> > +     .panic_flush = vmw_stdu_primary_plane_panic_flush,
> >   };
> >
> >   static const struct drm_crtc_helper_funcs vmw_stdu_crtc_helper_funcs = {
>

[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 5414 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH drm-misc-next 1/1] drm/vmwgfx: add drm_panic support for stdu
  2025-09-02 13:50     ` Ian Forbes
@ 2025-09-02 16:28       ` Ryosuke Yasuoka
  2025-09-02 18:24         ` Ian Forbes
  0 siblings, 1 reply; 6+ messages in thread
From: Ryosuke Yasuoka @ 2025-09-02 16:28 UTC (permalink / raw)
  To: Ian Forbes, Jocelyn Falempe
  Cc: zack.rusin, maarten.lankhorst, mripard, tzimmermann, airlied,
	simona, bcm-kernel-feedback-list, linux-kernel, dri-devel

On Tue, Sep 02, 2025 at 08:50:53AM -0500, Ian Forbes wrote:
> I don't think this is the right approach. It would be better to write
> to VRAM and then switch back to legacy mode. That shouldn't require
> any allocations or command submissions which are unlikely to succeed
> in a panic situation.
> 
> On Tue, Sep 2, 2025 at 3:02 AM Jocelyn Falempe <jfalempe@redhat.com> wrote:
> >
> > On 01/09/2025 10:36, Ryosuke Yasuoka wrote:
> > > Add drm_panic module for vmwgfx stdu so that panic screen can be
> > > displayed on panic.
> >
> > Thanks for this work.
> >
> > If I understand correctly, this will draw the panic screen to the vfbo
> > buffer, and then in the panic_flush() function, use
> > vmw_panic_bo_cpu_blit() to copy that to the guest_memory_bo.
> >
> > I think it should be easier to directly write the panic screen to the
> > guest_memory_bo.
> > To write to the guest_memory_bo, you can do something similar as
> > vmw_bo_cpu_blit_line(), but using kmap_local_page_try_from_panic()
> > instead of kmap_atomic_prot().
> >
> > You will probably need a custom set_pixel() function, like what I've
> > done for i915
> > https://elixir.bootlin.com/linux/v6.17-rc4/source/drivers/gpu/drm/xe/display/intel_bo.c#L98

Thank you for your valuable comments, Jocelyn and Ian.

Based on your all comments, my next plan is to write the panic screen 
to some bo directly, pass them to a VRAM, and output it using 
legacy mode.

Ian, I have a clarifying question regarding your suggestion to "switch
back to legacy mode". Could you please elaborate on what this entails?
I've found some possibly related code like vmw_ldu_fb_pin(), but I'm not
sure if my understanding is correct.

As I am new to this vmwgfx driver, any information or pointers on which
I should check would be greatly appreciated.

Regards,
Ryosuke

> > Best regards,
> >
> > --
> >
> > Jocelyn
> >
> > >
> > > Signed-off-by: Ryosuke Yasuoka <ryasuoka@redhat.com>
> > > ---
> > >   drivers/gpu/drm/vmwgfx/vmwgfx_blit.c   |  43 ++++++++
> > >   drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c |  11 ++
> > >   drivers/gpu/drm/vmwgfx/vmwgfx_drv.h    |   4 +
> > >   drivers/gpu/drm/vmwgfx/vmwgfx_kms.c    |  48 +++++++++
> > >   drivers/gpu/drm/vmwgfx/vmwgfx_kms.h    |   1 +
> > >   drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c   | 139 +++++++++++++++++++++++++
> > >   6 files changed, 246 insertions(+)
> > >
> > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
> > > index fa5841fda659..d7ed04531249 100644
> > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
> > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
> > > @@ -514,6 +514,49 @@ static int vmw_external_bo_copy(struct vmw_bo *dst, u32 dst_offset,
> > >       return ret;
> > >   }
> > >
> > > +/* For drm_panic */
> > > +void vmw_panic_bo_cpu_blit(struct vmw_bo *vmw_dst, u32 dst_stride,
> > > +                        struct vmw_bo *vmw_src, u32 src_stride,
> > > +                        u32 w, u32 h, struct vmw_diff_cpy *diff)
> > > +{
> > > +     struct ttm_buffer_object *src = &vmw_src->tbo;
> > > +     struct ttm_buffer_object *dst = &vmw_dst->tbo;
> > > +     u32 j;
> > > +     u32 initial_line = 0;
> > > +     u32 dst_offset = 0;
> > > +     u32 src_offset = 0;
> > > +     int ret = 0;
> > > +     struct vmw_bo_blit_line_data d = {
> > > +             .mapped_dst = 0,
> > > +             .mapped_src = 0,
> > > +             .dst_addr = NULL,
> > > +             .src_addr = NULL,
> > > +             .dst_pages = dst->ttm->pages,
> > > +             .src_pages = src->ttm->pages,
> > > +             .dst_num_pages = PFN_UP(dst->resource->size),
> > > +             .src_num_pages = PFN_UP(src->resource->size),
> > > +             .dst_prot = ttm_io_prot(dst, dst->resource, PAGE_KERNEL),
> > > +             .src_prot = ttm_io_prot(src, src->resource, PAGE_KERNEL),
> > > +             .diff = diff,
> > > +     };
> > > +
> > > +     for (j = 0; j < h; ++j) {
> > > +             diff->line = j + initial_line;
> > > +             diff->line_offset = dst_offset % dst_stride;
> > > +             ret = vmw_bo_cpu_blit_line(&d, dst_offset, src_offset, w);
> > > +             if (ret)
> > > +                     goto out;
> > > +
> > > +             dst_offset += dst_stride;
> > > +             src_offset += src_stride;
> > > +     }
> > > +out:
> > > +     if (d.src_addr)
> > > +             kunmap_atomic(d.src_addr);
> > > +     if (d.dst_addr)
> > > +             kunmap_atomic(d.dst_addr);
> > > +}
> > > +
> > >   /**
> > >    * vmw_bo_cpu_blit - in-kernel cpu blit.
> > >    *
> > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
> > > index 94e8982f5616..e39cc2f214be 100644
> > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
> > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
> > > @@ -983,6 +983,17 @@ void *vmw_cmdbuf_alloc(struct vmw_cmdbuf_man *man,
> > >       return header->cmd;
> > >   }
> > >
> > > +/* For drm_panic */
> > > +char *vmw_panic_cmdbuf_reserve_cur(struct vmw_cmdbuf_man *man, size_t size)
> > > +{
> > > +     /* Refer to cur without cur_mutex since this func is called in panic handler */
> > > +     struct vmw_cmdbuf_header *cur = man->cur;
> > > +
> > > +     cur->reserved = size;
> > > +
> > > +     return (char *) (man->cur->cmd + man->cur_pos);
> > > +}
> > > +
> > >   /**
> > >    * vmw_cmdbuf_reserve_cur - Reserve space for commands in the current
> > >    * command buffer.
> > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
> > > index eda5b6f8f4c4..c71ce975bf52 100644
> > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
> > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
> > > @@ -1271,6 +1271,7 @@ extern int vmw_cmdbuf_idle(struct vmw_cmdbuf_man *man, bool interruptible,
> > >   extern void *vmw_cmdbuf_reserve(struct vmw_cmdbuf_man *man, size_t size,
> > >                               int ctx_id, bool interruptible,
> > >                               struct vmw_cmdbuf_header *header);
> > > +extern char *vmw_panic_cmdbuf_reserve_cur(struct vmw_cmdbuf_man *man, size_t size);
> > >   extern void vmw_cmdbuf_commit(struct vmw_cmdbuf_man *man, size_t size,
> > >                             struct vmw_cmdbuf_header *header,
> > >                             bool flush);
> > > @@ -1329,6 +1330,9 @@ int vmw_bo_cpu_blit(struct vmw_bo *dst,
> > >                   u32 src_offset, u32 src_stride,
> > >                   u32 w, u32 h,
> > >                   struct vmw_diff_cpy *diff);
> > > +void vmw_panic_bo_cpu_blit(struct vmw_bo *dst, u32 dst_stride,
> > > +                        struct vmw_bo *src, u32 src_stride,
> > > +                        u32 w, u32 h, struct vmw_diff_cpy *diff);
> > >
> > >   /* Host messaging -vmwgfx_msg.c: */
> > >   void vmw_disable_backdoor(void);
> > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> > > index 54ea1b513950..160a4efbf342 100644
> > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> > > @@ -1717,6 +1717,54 @@ void vmw_kms_lost_device(struct drm_device *dev)
> > >       drm_atomic_helper_shutdown(dev);
> > >   }
> > >
> > > +/* For drm_panic */
> > > +int vmw_du_panic_helper_plane_update(struct vmw_du_update_plane *update)
> > > +{
> > > +     struct drm_plane_state *state = update->plane->state;
> > > +     struct vmw_framebuffer_bo *vfbbo =
> > > +             container_of(update->vfb, typeof(*vfbbo), base);
> > > +     struct drm_rect src = drm_plane_state_src(state);
> > > +     struct drm_rect clip = {
> > > +             .x1 = 0,
> > > +             .y1 = 0,
> > > +             .x2 = (src.x2 >> 16) + !!(src.x2 & 0xFFFF),
> > > +             .y2 = (src.y2 >> 16) + !!(src.y2 & 0xFFFF),
> > > +     };
> > > +     DECLARE_VAL_CONTEXT(val_ctx, NULL, 0);
> > > +     uint32_t reserved_size = 0;
> > > +     uint32_t submit_size = 0;
> > > +     char *cmd;
> > > +     int ret;
> > > +
> > > +     vmw_bo_placement_set(vfbbo->buffer,
> > > +                          VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_GMR,
> > > +                          VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_GMR);
> > > +
> > > +     ret = vmw_validation_add_bo(&val_ctx, vfbbo->buffer);
> > > +     if (ret)
> > > +             return ret;
> > > +
> > > +     ret = vmw_validation_prepare(&val_ctx, NULL, false);
> > > +     if (ret)
> > > +             return ret;
> > > +
> > > +     reserved_size = update->calc_fifo_size(update, 1);
> > > +     cmd = vmw_panic_cmdbuf_reserve_cur(update->dev_priv->cman, reserved_size);
> > > +     if (!cmd)
> > > +             return -ENOMEM;
> > > +
> > > +     vmw_du_translate_to_crtc(state, &clip);
> > > +
> > > +     update->clip(update, cmd, &clip, 0, 0);
> > > +     submit_size = update->post_clip(update, cmd, &clip);
> > > +
> > > +     vmw_cmd_commit(update->dev_priv, submit_size);
> > > +
> > > +     vmw_kms_helper_validation_finish(update->dev_priv, NULL, &val_ctx,
> > > +                                      NULL, NULL);
> > > +     return ret;
> > > +}
> > > +
> > >   /**
> > >    * vmw_du_helper_plane_update - Helper to do plane update on a display unit.
> > >    * @update: The closure structure.
> > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> > > index 445471fe9be6..e6299390ffea 100644
> > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> > > @@ -499,6 +499,7 @@ int vmw_kms_stdu_readback(struct vmw_private *dev_priv,
> > >                         struct drm_crtc *crtc);
> > >
> > >   int vmw_du_helper_plane_update(struct vmw_du_update_plane *update);
> > > +int vmw_du_panic_helper_plane_update(struct vmw_du_update_plane *update);
> > >
> > >   /**
> > >    * vmw_du_translate_to_crtc - Translate a rect from framebuffer to crtc
> > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> > > index 20aab725e53a..65b41338c620 100644
> > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> > > @@ -36,6 +36,7 @@
> > >   #include <drm/drm_atomic_helper.h>
> > >   #include <drm/drm_damage_helper.h>
> > >   #include <drm/drm_fourcc.h>
> > > +#include <drm/drm_panic.h>
> > >   #include <drm/drm_vblank.h>
> > >
> > >   #define vmw_crtc_to_stdu(x) \
> > > @@ -1164,6 +1165,66 @@ static uint32_t vmw_stdu_bo_clip_cpu(struct vmw_du_update_plane  *update,
> > >       return 0;
> > >   }
> > >
> > > +/* For drm_panic */
> > > +static uint32_t
> > > +vmw_stdu_panic_bo_populate_update_cpu(struct vmw_du_update_plane  *update, void *cmd,
> > > +                                   struct drm_rect *bb)
> > > +{
> > > +     struct vmw_du_update_plane_buffer *bo_update;
> > > +     struct vmw_screen_target_display_unit *stdu;
> > > +     struct vmw_framebuffer_bo *vfbbo;
> > > +     struct vmw_diff_cpy diff = VMW_CPU_BLIT_DIFF_INITIALIZER(0);
> > > +     struct vmw_stdu_update_gb_image *cmd_img = cmd;
> > > +     struct vmw_stdu_update *cmd_update;
> > > +     struct vmw_bo *src_bo, *dst_bo;
> > > +     s32 src_pitch, dst_pitch;
> > > +     s32 width, height;
> > > +
> > > +     bo_update = container_of(update, typeof(*bo_update), base);
> > > +     stdu = container_of(update->du, typeof(*stdu), base);
> > > +     vfbbo = container_of(update->vfb, typeof(*vfbbo), base);
> > > +
> > > +     width = bb->x2;
> > > +     height = bb->y2;
> > > +
> > > +     diff.cpp = stdu->cpp;
> > > +
> > > +     dst_bo = stdu->display_srf->res.guest_memory_bo;
> > > +     dst_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp;
> > > +
> > > +     src_bo = vfbbo->buffer;
> > > +     src_pitch = update->vfb->base.pitches[0];
> > > +
> > > +     vmw_panic_bo_cpu_blit(dst_bo, dst_pitch, src_bo, src_pitch,
> > > +                           width * stdu->cpp, height, &diff);
> > > +
> > > +     if (drm_rect_visible(&diff.rect)) {
> > > +             SVGA3dBox *box = &cmd_img->body.box;
> > > +
> > > +             cmd_img->header.id = SVGA_3D_CMD_UPDATE_GB_IMAGE;
> > > +             cmd_img->header.size = sizeof(cmd_img->body);
> > > +             cmd_img->body.image.sid = stdu->display_srf->res.id;
> > > +             cmd_img->body.image.face = 0;
> > > +             cmd_img->body.image.mipmap = 0;
> > > +
> > > +             box->x = diff.rect.x1;
> > > +             box->y = diff.rect.y1;
> > > +             box->z = 0;
> > > +             box->w = drm_rect_width(&diff.rect);
> > > +             box->h = drm_rect_height(&diff.rect);
> > > +             box->d = 1;
> > > +
> > > +             cmd_update = (struct vmw_stdu_update *)&cmd_img[1];
> > > +             vmw_stdu_populate_update(cmd_update, stdu->base.unit,
> > > +                                      diff.rect.x1, diff.rect.x2,
> > > +                                      diff.rect.y1, diff.rect.y2);
> > > +
> > > +             return sizeof(*cmd_img) + sizeof(*cmd_update);
> > > +     }
> > > +
> > > +     return 0;
> > > +}
> > > +
> > >   static uint32_t
> > >   vmw_stdu_bo_populate_update_cpu(struct vmw_du_update_plane  *update, void *cmd,
> > >                               struct drm_rect *bb)
> > > @@ -1228,6 +1289,28 @@ vmw_stdu_bo_populate_update_cpu(struct vmw_du_update_plane  *update, void *cmd,
> > >       return 0;
> > >   }
> > >
> > > +/* For drm_panic */
> > > +static int vmw_stdu_panic_plane_update_bo(struct vmw_private *dev_priv,
> > > +                                       struct drm_plane *plane,
> > > +                                       struct vmw_framebuffer *vfb)
> > > +{
> > > +     struct vmw_du_update_plane_buffer bo_update;
> > > +
> > > +     memset(&bo_update, 0, sizeof(struct vmw_du_update_plane_buffer));
> > > +     bo_update.base.plane = plane;
> > > +     bo_update.base.old_state = plane->state;
> > > +     bo_update.base.dev_priv = dev_priv;
> > > +     bo_update.base.du = vmw_crtc_to_du(plane->state->crtc);
> > > +     bo_update.base.vfb = vfb;
> > > +
> > > +     bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size_cpu;
> > > +     bo_update.base.pre_clip = vmw_stdu_bo_pre_clip_cpu;
> > > +     bo_update.base.clip = vmw_stdu_bo_clip_cpu;
> > > +     bo_update.base.post_clip = vmw_stdu_panic_bo_populate_update_cpu;
> > > +
> > > +     return vmw_du_panic_helper_plane_update(&bo_update.base);
> > > +}
> > > +
> > >   /**
> > >    * vmw_stdu_plane_update_bo - Update display unit for bo backed fb.
> > >    * @dev_priv: device private.
> > > @@ -1458,6 +1541,60 @@ vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane,
> > >               vmw_fence_obj_unreference(&fence);
> > >   }
> > >
> > > +static int
> > > +vmw_stdu_primary_plane_get_scanout_buffer(struct drm_plane *plane,
> > > +                                       struct drm_scanout_buffer *sb)
> > > +{
> > > +     struct vmw_framebuffer *vfb;
> > > +     struct vmw_framebuffer_bo *vfbbo;
> > > +     void *virtual;
> > > +
> > > +     if (!plane->state || !plane->state->fb || !plane->state->visible)
> > > +             return -ENODEV;
> > > +
> > > +     vfb = vmw_framebuffer_to_vfb(plane->state->fb);
> > > +
> > > +     if (!vfb->bo)
> > > +             return -ENODEV;
> > > +
> > > +     vfbbo = container_of(vfb, typeof(*vfbbo), base);
> > > +     virtual = vmw_bo_map_and_cache(vfbbo->buffer);
> > > +     if (!virtual)
> > > +             return -ENODEV;
> > > +     iosys_map_set_vaddr(&sb->map[0], virtual);
> > > +
> > > +     sb->format = plane->state->fb->format;
> > > +     sb->width = plane->state->fb->width;
> > > +     sb->height = plane->state->fb->height;
> > > +     sb->pitch[0] = plane->state->fb->pitches[0];
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static void vmw_stdu_primary_plane_panic_flush(struct drm_plane *plane)
> > > +{
> > > +     struct drm_plane_state *state = plane->state;
> > > +     struct vmw_plane_state *vps = vmw_plane_state_to_vps(state);
> > > +     struct drm_crtc *crtc = state->crtc;
> > > +     struct vmw_private *dev_priv = vmw_priv(crtc->dev);
> > > +     struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(state->fb);
> > > +     struct vmw_screen_target_display_unit *stdu = vmw_crtc_to_stdu(crtc);
> > > +     int ret;
> > > +
> > > +     stdu->display_srf = vmw_user_object_surface(&vps->uo);
> > > +     stdu->content_fb_type = vps->content_fb_type;
> > > +     stdu->cpp = vps->cpp;
> > > +
> > > +     ret = vmw_stdu_bind_st(dev_priv, stdu, &stdu->display_srf->res);
> > > +     if (ret)
> > > +             DRM_ERROR("Failed to bind surface to STDU.\n");
> > > +
> > > +     if (vfb->bo)
> > > +             ret = vmw_stdu_panic_plane_update_bo(dev_priv, plane, vfb);
> > > +     if (ret)
> > > +             DRM_ERROR("Failed to update STDU.\n");
> > > +}
> > > +
> > >   static void
> > >   vmw_stdu_crtc_atomic_flush(struct drm_crtc *crtc,
> > >                          struct drm_atomic_state *state)
> > > @@ -1506,6 +1643,8 @@ drm_plane_helper_funcs vmw_stdu_primary_plane_helper_funcs = {
> > >       .atomic_update = vmw_stdu_primary_plane_atomic_update,
> > >       .prepare_fb = vmw_stdu_primary_plane_prepare_fb,
> > >       .cleanup_fb = vmw_stdu_primary_plane_cleanup_fb,
> > > +     .get_scanout_buffer = vmw_stdu_primary_plane_get_scanout_buffer,
> > > +     .panic_flush = vmw_stdu_primary_plane_panic_flush,
> > >   };
> > >
> > >   static const struct drm_crtc_helper_funcs vmw_stdu_crtc_helper_funcs = {
> >



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH drm-misc-next 1/1] drm/vmwgfx: add drm_panic support for stdu
  2025-09-02 16:28       ` Ryosuke Yasuoka
@ 2025-09-02 18:24         ` Ian Forbes
  0 siblings, 0 replies; 6+ messages in thread
From: Ian Forbes @ 2025-09-02 18:24 UTC (permalink / raw)
  To: Ryosuke Yasuoka
  Cc: Jocelyn Falempe, zack.rusin, maarten.lankhorst, mripard,
	tzimmermann, airlied, simona, bcm-kernel-feedback-list,
	linux-kernel, dri-devel

[-- Attachment #1: Type: text/plain, Size: 18994 bytes --]

In get_scanout_buffer you want to return a drm_scanout_buffer with
something like `sb->maps[0].vaddr = memremap(dev_priv->vram_start,
...);` and in panic_flush you want to issue a sequence similar to
what's in `vmw_ldu_commit_list`

On Tue, Sep 2, 2025 at 11:28 AM Ryosuke Yasuoka <ryasuoka@redhat.com> wrote:
>
> On Tue, Sep 02, 2025 at 08:50:53AM -0500, Ian Forbes wrote:
> > I don't think this is the right approach. It would be better to write
> > to VRAM and then switch back to legacy mode. That shouldn't require
> > any allocations or command submissions which are unlikely to succeed
> > in a panic situation.
> >
> > On Tue, Sep 2, 2025 at 3:02 AM Jocelyn Falempe <jfalempe@redhat.com> wrote:
> > >
> > > On 01/09/2025 10:36, Ryosuke Yasuoka wrote:
> > > > Add drm_panic module for vmwgfx stdu so that panic screen can be
> > > > displayed on panic.
> > >
> > > Thanks for this work.
> > >
> > > If I understand correctly, this will draw the panic screen to the vfbo
> > > buffer, and then in the panic_flush() function, use
> > > vmw_panic_bo_cpu_blit() to copy that to the guest_memory_bo.
> > >
> > > I think it should be easier to directly write the panic screen to the
> > > guest_memory_bo.
> > > To write to the guest_memory_bo, you can do something similar as
> > > vmw_bo_cpu_blit_line(), but using kmap_local_page_try_from_panic()
> > > instead of kmap_atomic_prot().
> > >
> > > You will probably need a custom set_pixel() function, like what I've
> > > done for i915
> > > https://elixir.bootlin.com/linux/v6.17-rc4/source/drivers/gpu/drm/xe/display/intel_bo.c#L98
>
> Thank you for your valuable comments, Jocelyn and Ian.
>
> Based on your all comments, my next plan is to write the panic screen
> to some bo directly, pass them to a VRAM, and output it using
> legacy mode.
>
> Ian, I have a clarifying question regarding your suggestion to "switch
> back to legacy mode". Could you please elaborate on what this entails?
> I've found some possibly related code like vmw_ldu_fb_pin(), but I'm not
> sure if my understanding is correct.
>
> As I am new to this vmwgfx driver, any information or pointers on which
> I should check would be greatly appreciated.
>
> Regards,
> Ryosuke
>
> > > Best regards,
> > >
> > > --
> > >
> > > Jocelyn
> > >
> > > >
> > > > Signed-off-by: Ryosuke Yasuoka <ryasuoka@redhat.com>
> > > > ---
> > > >   drivers/gpu/drm/vmwgfx/vmwgfx_blit.c   |  43 ++++++++
> > > >   drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c |  11 ++
> > > >   drivers/gpu/drm/vmwgfx/vmwgfx_drv.h    |   4 +
> > > >   drivers/gpu/drm/vmwgfx/vmwgfx_kms.c    |  48 +++++++++
> > > >   drivers/gpu/drm/vmwgfx/vmwgfx_kms.h    |   1 +
> > > >   drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c   | 139 +++++++++++++++++++++++++
> > > >   6 files changed, 246 insertions(+)
> > > >
> > > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
> > > > index fa5841fda659..d7ed04531249 100644
> > > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
> > > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
> > > > @@ -514,6 +514,49 @@ static int vmw_external_bo_copy(struct vmw_bo *dst, u32 dst_offset,
> > > >       return ret;
> > > >   }
> > > >
> > > > +/* For drm_panic */
> > > > +void vmw_panic_bo_cpu_blit(struct vmw_bo *vmw_dst, u32 dst_stride,
> > > > +                        struct vmw_bo *vmw_src, u32 src_stride,
> > > > +                        u32 w, u32 h, struct vmw_diff_cpy *diff)
> > > > +{
> > > > +     struct ttm_buffer_object *src = &vmw_src->tbo;
> > > > +     struct ttm_buffer_object *dst = &vmw_dst->tbo;
> > > > +     u32 j;
> > > > +     u32 initial_line = 0;
> > > > +     u32 dst_offset = 0;
> > > > +     u32 src_offset = 0;
> > > > +     int ret = 0;
> > > > +     struct vmw_bo_blit_line_data d = {
> > > > +             .mapped_dst = 0,
> > > > +             .mapped_src = 0,
> > > > +             .dst_addr = NULL,
> > > > +             .src_addr = NULL,
> > > > +             .dst_pages = dst->ttm->pages,
> > > > +             .src_pages = src->ttm->pages,
> > > > +             .dst_num_pages = PFN_UP(dst->resource->size),
> > > > +             .src_num_pages = PFN_UP(src->resource->size),
> > > > +             .dst_prot = ttm_io_prot(dst, dst->resource, PAGE_KERNEL),
> > > > +             .src_prot = ttm_io_prot(src, src->resource, PAGE_KERNEL),
> > > > +             .diff = diff,
> > > > +     };
> > > > +
> > > > +     for (j = 0; j < h; ++j) {
> > > > +             diff->line = j + initial_line;
> > > > +             diff->line_offset = dst_offset % dst_stride;
> > > > +             ret = vmw_bo_cpu_blit_line(&d, dst_offset, src_offset, w);
> > > > +             if (ret)
> > > > +                     goto out;
> > > > +
> > > > +             dst_offset += dst_stride;
> > > > +             src_offset += src_stride;
> > > > +     }
> > > > +out:
> > > > +     if (d.src_addr)
> > > > +             kunmap_atomic(d.src_addr);
> > > > +     if (d.dst_addr)
> > > > +             kunmap_atomic(d.dst_addr);
> > > > +}
> > > > +
> > > >   /**
> > > >    * vmw_bo_cpu_blit - in-kernel cpu blit.
> > > >    *
> > > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
> > > > index 94e8982f5616..e39cc2f214be 100644
> > > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
> > > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
> > > > @@ -983,6 +983,17 @@ void *vmw_cmdbuf_alloc(struct vmw_cmdbuf_man *man,
> > > >       return header->cmd;
> > > >   }
> > > >
> > > > +/* For drm_panic */
> > > > +char *vmw_panic_cmdbuf_reserve_cur(struct vmw_cmdbuf_man *man, size_t size)
> > > > +{
> > > > +     /* Refer to cur without cur_mutex since this func is called in panic handler */
> > > > +     struct vmw_cmdbuf_header *cur = man->cur;
> > > > +
> > > > +     cur->reserved = size;
> > > > +
> > > > +     return (char *) (man->cur->cmd + man->cur_pos);
> > > > +}
> > > > +
> > > >   /**
> > > >    * vmw_cmdbuf_reserve_cur - Reserve space for commands in the current
> > > >    * command buffer.
> > > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
> > > > index eda5b6f8f4c4..c71ce975bf52 100644
> > > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
> > > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
> > > > @@ -1271,6 +1271,7 @@ extern int vmw_cmdbuf_idle(struct vmw_cmdbuf_man *man, bool interruptible,
> > > >   extern void *vmw_cmdbuf_reserve(struct vmw_cmdbuf_man *man, size_t size,
> > > >                               int ctx_id, bool interruptible,
> > > >                               struct vmw_cmdbuf_header *header);
> > > > +extern char *vmw_panic_cmdbuf_reserve_cur(struct vmw_cmdbuf_man *man, size_t size);
> > > >   extern void vmw_cmdbuf_commit(struct vmw_cmdbuf_man *man, size_t size,
> > > >                             struct vmw_cmdbuf_header *header,
> > > >                             bool flush);
> > > > @@ -1329,6 +1330,9 @@ int vmw_bo_cpu_blit(struct vmw_bo *dst,
> > > >                   u32 src_offset, u32 src_stride,
> > > >                   u32 w, u32 h,
> > > >                   struct vmw_diff_cpy *diff);
> > > > +void vmw_panic_bo_cpu_blit(struct vmw_bo *dst, u32 dst_stride,
> > > > +                        struct vmw_bo *src, u32 src_stride,
> > > > +                        u32 w, u32 h, struct vmw_diff_cpy *diff);
> > > >
> > > >   /* Host messaging -vmwgfx_msg.c: */
> > > >   void vmw_disable_backdoor(void);
> > > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> > > > index 54ea1b513950..160a4efbf342 100644
> > > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> > > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> > > > @@ -1717,6 +1717,54 @@ void vmw_kms_lost_device(struct drm_device *dev)
> > > >       drm_atomic_helper_shutdown(dev);
> > > >   }
> > > >
> > > > +/* For drm_panic */
> > > > +int vmw_du_panic_helper_plane_update(struct vmw_du_update_plane *update)
> > > > +{
> > > > +     struct drm_plane_state *state = update->plane->state;
> > > > +     struct vmw_framebuffer_bo *vfbbo =
> > > > +             container_of(update->vfb, typeof(*vfbbo), base);
> > > > +     struct drm_rect src = drm_plane_state_src(state);
> > > > +     struct drm_rect clip = {
> > > > +             .x1 = 0,
> > > > +             .y1 = 0,
> > > > +             .x2 = (src.x2 >> 16) + !!(src.x2 & 0xFFFF),
> > > > +             .y2 = (src.y2 >> 16) + !!(src.y2 & 0xFFFF),
> > > > +     };
> > > > +     DECLARE_VAL_CONTEXT(val_ctx, NULL, 0);
> > > > +     uint32_t reserved_size = 0;
> > > > +     uint32_t submit_size = 0;
> > > > +     char *cmd;
> > > > +     int ret;
> > > > +
> > > > +     vmw_bo_placement_set(vfbbo->buffer,
> > > > +                          VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_GMR,
> > > > +                          VMW_BO_DOMAIN_SYS | VMW_BO_DOMAIN_MOB | VMW_BO_DOMAIN_GMR);
> > > > +
> > > > +     ret = vmw_validation_add_bo(&val_ctx, vfbbo->buffer);
> > > > +     if (ret)
> > > > +             return ret;
> > > > +
> > > > +     ret = vmw_validation_prepare(&val_ctx, NULL, false);
> > > > +     if (ret)
> > > > +             return ret;
> > > > +
> > > > +     reserved_size = update->calc_fifo_size(update, 1);
> > > > +     cmd = vmw_panic_cmdbuf_reserve_cur(update->dev_priv->cman, reserved_size);
> > > > +     if (!cmd)
> > > > +             return -ENOMEM;
> > > > +
> > > > +     vmw_du_translate_to_crtc(state, &clip);
> > > > +
> > > > +     update->clip(update, cmd, &clip, 0, 0);
> > > > +     submit_size = update->post_clip(update, cmd, &clip);
> > > > +
> > > > +     vmw_cmd_commit(update->dev_priv, submit_size);
> > > > +
> > > > +     vmw_kms_helper_validation_finish(update->dev_priv, NULL, &val_ctx,
> > > > +                                      NULL, NULL);
> > > > +     return ret;
> > > > +}
> > > > +
> > > >   /**
> > > >    * vmw_du_helper_plane_update - Helper to do plane update on a display unit.
> > > >    * @update: The closure structure.
> > > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> > > > index 445471fe9be6..e6299390ffea 100644
> > > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> > > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> > > > @@ -499,6 +499,7 @@ int vmw_kms_stdu_readback(struct vmw_private *dev_priv,
> > > >                         struct drm_crtc *crtc);
> > > >
> > > >   int vmw_du_helper_plane_update(struct vmw_du_update_plane *update);
> > > > +int vmw_du_panic_helper_plane_update(struct vmw_du_update_plane *update);
> > > >
> > > >   /**
> > > >    * vmw_du_translate_to_crtc - Translate a rect from framebuffer to crtc
> > > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> > > > index 20aab725e53a..65b41338c620 100644
> > > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> > > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> > > > @@ -36,6 +36,7 @@
> > > >   #include <drm/drm_atomic_helper.h>
> > > >   #include <drm/drm_damage_helper.h>
> > > >   #include <drm/drm_fourcc.h>
> > > > +#include <drm/drm_panic.h>
> > > >   #include <drm/drm_vblank.h>
> > > >
> > > >   #define vmw_crtc_to_stdu(x) \
> > > > @@ -1164,6 +1165,66 @@ static uint32_t vmw_stdu_bo_clip_cpu(struct vmw_du_update_plane  *update,
> > > >       return 0;
> > > >   }
> > > >
> > > > +/* For drm_panic */
> > > > +static uint32_t
> > > > +vmw_stdu_panic_bo_populate_update_cpu(struct vmw_du_update_plane  *update, void *cmd,
> > > > +                                   struct drm_rect *bb)
> > > > +{
> > > > +     struct vmw_du_update_plane_buffer *bo_update;
> > > > +     struct vmw_screen_target_display_unit *stdu;
> > > > +     struct vmw_framebuffer_bo *vfbbo;
> > > > +     struct vmw_diff_cpy diff = VMW_CPU_BLIT_DIFF_INITIALIZER(0);
> > > > +     struct vmw_stdu_update_gb_image *cmd_img = cmd;
> > > > +     struct vmw_stdu_update *cmd_update;
> > > > +     struct vmw_bo *src_bo, *dst_bo;
> > > > +     s32 src_pitch, dst_pitch;
> > > > +     s32 width, height;
> > > > +
> > > > +     bo_update = container_of(update, typeof(*bo_update), base);
> > > > +     stdu = container_of(update->du, typeof(*stdu), base);
> > > > +     vfbbo = container_of(update->vfb, typeof(*vfbbo), base);
> > > > +
> > > > +     width = bb->x2;
> > > > +     height = bb->y2;
> > > > +
> > > > +     diff.cpp = stdu->cpp;
> > > > +
> > > > +     dst_bo = stdu->display_srf->res.guest_memory_bo;
> > > > +     dst_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp;
> > > > +
> > > > +     src_bo = vfbbo->buffer;
> > > > +     src_pitch = update->vfb->base.pitches[0];
> > > > +
> > > > +     vmw_panic_bo_cpu_blit(dst_bo, dst_pitch, src_bo, src_pitch,
> > > > +                           width * stdu->cpp, height, &diff);
> > > > +
> > > > +     if (drm_rect_visible(&diff.rect)) {
> > > > +             SVGA3dBox *box = &cmd_img->body.box;
> > > > +
> > > > +             cmd_img->header.id = SVGA_3D_CMD_UPDATE_GB_IMAGE;
> > > > +             cmd_img->header.size = sizeof(cmd_img->body);
> > > > +             cmd_img->body.image.sid = stdu->display_srf->res.id;
> > > > +             cmd_img->body.image.face = 0;
> > > > +             cmd_img->body.image.mipmap = 0;
> > > > +
> > > > +             box->x = diff.rect.x1;
> > > > +             box->y = diff.rect.y1;
> > > > +             box->z = 0;
> > > > +             box->w = drm_rect_width(&diff.rect);
> > > > +             box->h = drm_rect_height(&diff.rect);
> > > > +             box->d = 1;
> > > > +
> > > > +             cmd_update = (struct vmw_stdu_update *)&cmd_img[1];
> > > > +             vmw_stdu_populate_update(cmd_update, stdu->base.unit,
> > > > +                                      diff.rect.x1, diff.rect.x2,
> > > > +                                      diff.rect.y1, diff.rect.y2);
> > > > +
> > > > +             return sizeof(*cmd_img) + sizeof(*cmd_update);
> > > > +     }
> > > > +
> > > > +     return 0;
> > > > +}
> > > > +
> > > >   static uint32_t
> > > >   vmw_stdu_bo_populate_update_cpu(struct vmw_du_update_plane  *update, void *cmd,
> > > >                               struct drm_rect *bb)
> > > > @@ -1228,6 +1289,28 @@ vmw_stdu_bo_populate_update_cpu(struct vmw_du_update_plane  *update, void *cmd,
> > > >       return 0;
> > > >   }
> > > >
> > > > +/* For drm_panic */
> > > > +static int vmw_stdu_panic_plane_update_bo(struct vmw_private *dev_priv,
> > > > +                                       struct drm_plane *plane,
> > > > +                                       struct vmw_framebuffer *vfb)
> > > > +{
> > > > +     struct vmw_du_update_plane_buffer bo_update;
> > > > +
> > > > +     memset(&bo_update, 0, sizeof(struct vmw_du_update_plane_buffer));
> > > > +     bo_update.base.plane = plane;
> > > > +     bo_update.base.old_state = plane->state;
> > > > +     bo_update.base.dev_priv = dev_priv;
> > > > +     bo_update.base.du = vmw_crtc_to_du(plane->state->crtc);
> > > > +     bo_update.base.vfb = vfb;
> > > > +
> > > > +     bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size_cpu;
> > > > +     bo_update.base.pre_clip = vmw_stdu_bo_pre_clip_cpu;
> > > > +     bo_update.base.clip = vmw_stdu_bo_clip_cpu;
> > > > +     bo_update.base.post_clip = vmw_stdu_panic_bo_populate_update_cpu;
> > > > +
> > > > +     return vmw_du_panic_helper_plane_update(&bo_update.base);
> > > > +}
> > > > +
> > > >   /**
> > > >    * vmw_stdu_plane_update_bo - Update display unit for bo backed fb.
> > > >    * @dev_priv: device private.
> > > > @@ -1458,6 +1541,60 @@ vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane,
> > > >               vmw_fence_obj_unreference(&fence);
> > > >   }
> > > >
> > > > +static int
> > > > +vmw_stdu_primary_plane_get_scanout_buffer(struct drm_plane *plane,
> > > > +                                       struct drm_scanout_buffer *sb)
> > > > +{
> > > > +     struct vmw_framebuffer *vfb;
> > > > +     struct vmw_framebuffer_bo *vfbbo;
> > > > +     void *virtual;
> > > > +
> > > > +     if (!plane->state || !plane->state->fb || !plane->state->visible)
> > > > +             return -ENODEV;
> > > > +
> > > > +     vfb = vmw_framebuffer_to_vfb(plane->state->fb);
> > > > +
> > > > +     if (!vfb->bo)
> > > > +             return -ENODEV;
> > > > +
> > > > +     vfbbo = container_of(vfb, typeof(*vfbbo), base);
> > > > +     virtual = vmw_bo_map_and_cache(vfbbo->buffer);
> > > > +     if (!virtual)
> > > > +             return -ENODEV;
> > > > +     iosys_map_set_vaddr(&sb->map[0], virtual);
> > > > +
> > > > +     sb->format = plane->state->fb->format;
> > > > +     sb->width = plane->state->fb->width;
> > > > +     sb->height = plane->state->fb->height;
> > > > +     sb->pitch[0] = plane->state->fb->pitches[0];
> > > > +
> > > > +     return 0;
> > > > +}
> > > > +
> > > > +static void vmw_stdu_primary_plane_panic_flush(struct drm_plane *plane)
> > > > +{
> > > > +     struct drm_plane_state *state = plane->state;
> > > > +     struct vmw_plane_state *vps = vmw_plane_state_to_vps(state);
> > > > +     struct drm_crtc *crtc = state->crtc;
> > > > +     struct vmw_private *dev_priv = vmw_priv(crtc->dev);
> > > > +     struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(state->fb);
> > > > +     struct vmw_screen_target_display_unit *stdu = vmw_crtc_to_stdu(crtc);
> > > > +     int ret;
> > > > +
> > > > +     stdu->display_srf = vmw_user_object_surface(&vps->uo);
> > > > +     stdu->content_fb_type = vps->content_fb_type;
> > > > +     stdu->cpp = vps->cpp;
> > > > +
> > > > +     ret = vmw_stdu_bind_st(dev_priv, stdu, &stdu->display_srf->res);
> > > > +     if (ret)
> > > > +             DRM_ERROR("Failed to bind surface to STDU.\n");
> > > > +
> > > > +     if (vfb->bo)
> > > > +             ret = vmw_stdu_panic_plane_update_bo(dev_priv, plane, vfb);
> > > > +     if (ret)
> > > > +             DRM_ERROR("Failed to update STDU.\n");
> > > > +}
> > > > +
> > > >   static void
> > > >   vmw_stdu_crtc_atomic_flush(struct drm_crtc *crtc,
> > > >                          struct drm_atomic_state *state)
> > > > @@ -1506,6 +1643,8 @@ drm_plane_helper_funcs vmw_stdu_primary_plane_helper_funcs = {
> > > >       .atomic_update = vmw_stdu_primary_plane_atomic_update,
> > > >       .prepare_fb = vmw_stdu_primary_plane_prepare_fb,
> > > >       .cleanup_fb = vmw_stdu_primary_plane_cleanup_fb,
> > > > +     .get_scanout_buffer = vmw_stdu_primary_plane_get_scanout_buffer,
> > > > +     .panic_flush = vmw_stdu_primary_plane_panic_flush,
> > > >   };
> > > >
> > > >   static const struct drm_crtc_helper_funcs vmw_stdu_crtc_helper_funcs = {
> > >
>
>

[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 5414 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2025-09-02 18:24 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-01  8:36 [PATCH drm-misc-next 0/1] add drm_panic_support for stdu Ryosuke Yasuoka
2025-09-01  8:36 ` [PATCH drm-misc-next 1/1] drm/vmwgfx: add drm_panic support " Ryosuke Yasuoka
2025-09-02  8:02   ` Jocelyn Falempe
2025-09-02 13:50     ` Ian Forbes
2025-09-02 16:28       ` Ryosuke Yasuoka
2025-09-02 18:24         ` Ian Forbes

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).