From 81a00960d3fa83bbff9939ff52e89f0b74801937 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 15 Jan 2020 21:48:19 +0100 Subject: drm/vmwgfx: Fix the refuse_dma mode when using guest-backed objects When we refuse DMA from system pages for whatever reason, we don't handle that correctly when guest-backed objects was enabled. Since guest-backed objects by definition require DMA to and from system pages, disable all functionality that relies on them. That basically amounts to 3D acceleration and screen targets. Signed-off-by: Thomas Hellstrom Reviewed-by: Brian Paul --- drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c | 3 ++- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 6 ++++-- drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c index 065015d2a8f6..3b41cf63110a 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c @@ -1241,7 +1241,8 @@ int vmw_cmdbuf_set_pool_size(struct vmw_cmdbuf_man *man, * actually call into the already enabled manager, when * binding the MOB. */ - if (!(dev_priv->capabilities & SVGA_CAP_DX)) + if (!(dev_priv->capabilities & SVGA_CAP_DX) || + !dev_priv->has_mob) return -ENOMEM; ret = ttm_bo_create(&dev_priv->bdev, size, ttm_bo_type_device, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index cf3dc56d7cf4..f2ec3155468d 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -682,8 +682,10 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) ret = vmw_dma_select_mode(dev_priv); if (unlikely(ret != 0)) { - DRM_INFO("Restricting capabilities due to IOMMU setup.\n"); + DRM_INFO("Restricting capabilities since DMA not available.\n"); refuse_dma = true; + if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS) + DRM_INFO("Disabling 3D acceleration.\n"); } dev_priv->vram_size = vmw_read(dev_priv, SVGA_REG_VRAM_SIZE); @@ -866,7 +868,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) dev_priv->has_gmr = false; } - if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS) { + if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS && !refuse_dma) { dev_priv->has_mob = true; if (ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_MOB, VMW_PL_MOB) != 0) { diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index 570687a1a327..68aecb6d9f87 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c @@ -1888,7 +1888,7 @@ int vmw_kms_stdu_init_display(struct vmw_private *dev_priv) /* Do nothing if Screen Target support is turned off */ - if (!VMWGFX_ENABLE_SCREEN_TARGET_OTABLE) + if (!VMWGFX_ENABLE_SCREEN_TARGET_OTABLE || !dev_priv->has_mob) return -ENOSYS; if (!(dev_priv->capabilities & SVGA_CAP_GBOBJECTS)) -- cgit v1.2.3 From 3b0d6458c7052af1795489976b600797ca07f7e9 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 15 Jan 2020 21:48:19 +0100 Subject: drm/vmwgfx: Refuse DMA operation when SEV encryption is active TTM doesn't yet fully support mapping of DMA memory when SEV is active, so in that case, refuse DMA operation. For guest-backed object operation this means 3D acceleration will be disabled. For host-backed, VRAM will be used for data transfer between the guest and the device. Signed-off-by: Thomas Hellstrom Reviewed-by: Brian Paul --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index f2ec3155468d..4f58364421ce 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -575,6 +576,10 @@ static int vmw_dma_select_mode(struct vmw_private *dev_priv) [vmw_dma_map_populate] = "Caching DMA mappings.", [vmw_dma_map_bind] = "Giving up DMA mappings early."}; + /* TTM currently doesn't fully support SEV encryption. */ + if (mem_encrypt_active()) + return -EINVAL; + if (vmw_force_coherent) dev_priv->map_mode = vmw_dma_alloc_coherent; else if (vmw_restrict_iommu) -- cgit v1.2.3 From 44e5f9311cf0116635541099023ff54a86dcfb51 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 24 Feb 2020 15:07:25 +0100 Subject: drm/vmwgfx: Drop preempt_disable() in vmw_fifo_ping_host() vmw_fifo_ping_host() disables preemption around a test and a register write via vmw_write(). The write function acquires a spinlock_t typed lock which is not allowed in a preempt_disable()ed section on PREEMPT_RT. This has been reported in the bugzilla. It has been explained by Thomas Hellstrom that this preempt_disable()ed section is not required for correctness. Remove the preempt_disable() section. Link: https://bugzilla.kernel.org/show_bug.cgi?id=206591 Link: https://lkml.kernel.org/r/0b5e1c65d89951de993deab06d1d197b40fd67aa.camel@vmware.com Signed-off-by: Sebastian Andrzej Siewior Reviewed-by: Thomas Hellstrom Signed-off-by: Thomas Hellstrom --- drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c index e5252ef3812f..6941689085ed 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c @@ -169,10 +169,8 @@ void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason) { u32 *fifo_mem = dev_priv->mmio_virt; - preempt_disable(); if (cmpxchg(fifo_mem + SVGA_FIFO_BUSY, 0, 1) == 0) vmw_write(dev_priv, SVGA_REG_SYNC, reason); - preempt_enable(); } void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) -- cgit v1.2.3 From 2bdb7380fe128481f30b8db7558cef248ca27434 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 2 Mar 2020 10:35:10 +0100 Subject: drm/vmwgfx: Remove a few unused functions I noticed that there is a prototype for vmw_fifo_ping_host_locked() but no function. Then I looked further and noticed more functions which are not used anymore or functions protoypes which remained after the function was removed. Remove unused function (prototypes). Signed-off-by: Sebastian Andrzej Siewior Reviewed-by: Thomas Hellstrom Signed-off-by: Thomas Hellstrom --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 28 ------------ drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 81 --------------------------------- drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c | 31 ------------- 3 files changed, 140 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 4ce39c94c0eb..b70d73225707 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -479,19 +479,6 @@ struct vmw_private { bool assume_16bpp; bool has_sm4_1; - /* - * VGA registers. - */ - - struct vmw_vga_topology_state vga_save[VMWGFX_MAX_DISPLAYS]; - uint32_t vga_width; - uint32_t vga_height; - uint32_t vga_bpp; - uint32_t vga_bpl; - uint32_t vga_pitchlock; - - uint32_t num_displays; - /* * Framebuffer info. */ @@ -900,7 +887,6 @@ extern void vmw_fifo_commit(struct vmw_private *dev_priv, uint32_t bytes); extern void vmw_fifo_commit_flush(struct vmw_private *dev_priv, uint32_t bytes); extern int vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *seqno); -extern void vmw_fifo_ping_host_locked(struct vmw_private *, uint32_t reason); extern void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason); extern bool vmw_fifo_have_3d(struct vmw_private *dev_priv); extern bool vmw_fifo_have_pitchlock(struct vmw_private *dev_priv); @@ -947,7 +933,6 @@ extern struct ttm_placement vmw_mob_placement; extern struct ttm_placement vmw_mob_ne_placement; extern struct ttm_placement vmw_nonfixed_placement; extern struct ttm_bo_driver vmw_bo_driver; -extern int vmw_dma_quiescent(struct drm_device *dev); extern int vmw_bo_map_dma(struct ttm_buffer_object *bo); extern void vmw_bo_unmap_dma(struct ttm_buffer_object *bo); extern const struct vmw_sg_table * @@ -1085,8 +1070,6 @@ int vmw_fb_on(struct vmw_private *vmw_priv); int vmw_kms_init(struct vmw_private *dev_priv); int vmw_kms_close(struct vmw_private *dev_priv); -int vmw_kms_save_vga(struct vmw_private *vmw_priv); -int vmw_kms_restore_vga(struct vmw_private *vmw_priv); int vmw_kms_cursor_bypass_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv); @@ -1139,7 +1122,6 @@ int vmw_overlay_init(struct vmw_private *dev_priv); int vmw_overlay_close(struct vmw_private *dev_priv); int vmw_overlay_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -int vmw_overlay_stop_all(struct vmw_private *dev_priv); int vmw_overlay_resume_all(struct vmw_private *dev_priv); int vmw_overlay_pause_all(struct vmw_private *dev_priv); int vmw_overlay_claim(struct vmw_private *dev_priv, uint32_t *out); @@ -1186,10 +1168,6 @@ extern void vmw_otables_takedown(struct vmw_private *dev_priv); extern const struct vmw_user_resource_conv *user_context_converter; -extern int vmw_context_check(struct vmw_private *dev_priv, - struct ttm_object_file *tfile, - int id, - struct vmw_resource **p_res); extern int vmw_context_define_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int vmw_extended_context_define_ioctl(struct drm_device *dev, void *data, @@ -1219,7 +1197,6 @@ vmw_context_get_dx_query_mob(struct vmw_resource *ctx_res); extern const struct vmw_user_resource_conv *user_surface_converter; -extern void vmw_surface_res_free(struct vmw_resource *res); extern int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int vmw_surface_define_ioctl(struct drm_device *dev, void *data, @@ -1230,11 +1207,6 @@ extern int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int vmw_surface_check(struct vmw_private *dev_priv, - struct ttm_object_file *tfile, - uint32_t handle, int *id); -extern int vmw_surface_validate(struct vmw_private *dev_priv, - struct vmw_surface *srf); int vmw_surface_gb_priv_define(struct drm_device *dev, uint32_t user_accounting_size, SVGA3dSurfaceAllFlags svga3d_flags, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index eb6e23e8d8ef..52e086a5691e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1897,87 +1897,6 @@ int vmw_kms_write_svga(struct vmw_private *vmw_priv, return 0; } -int vmw_kms_save_vga(struct vmw_private *vmw_priv) -{ - struct vmw_vga_topology_state *save; - uint32_t i; - - vmw_priv->vga_width = vmw_read(vmw_priv, SVGA_REG_WIDTH); - vmw_priv->vga_height = vmw_read(vmw_priv, SVGA_REG_HEIGHT); - vmw_priv->vga_bpp = vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL); - if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK) - vmw_priv->vga_pitchlock = - vmw_read(vmw_priv, SVGA_REG_PITCHLOCK); - else if (vmw_fifo_have_pitchlock(vmw_priv)) - vmw_priv->vga_pitchlock = vmw_mmio_read(vmw_priv->mmio_virt + - SVGA_FIFO_PITCHLOCK); - - if (!(vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY)) - return 0; - - vmw_priv->num_displays = vmw_read(vmw_priv, - SVGA_REG_NUM_GUEST_DISPLAYS); - - if (vmw_priv->num_displays == 0) - vmw_priv->num_displays = 1; - - for (i = 0; i < vmw_priv->num_displays; ++i) { - save = &vmw_priv->vga_save[i]; - vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, i); - save->primary = vmw_read(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY); - save->pos_x = vmw_read(vmw_priv, SVGA_REG_DISPLAY_POSITION_X); - save->pos_y = vmw_read(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y); - save->width = vmw_read(vmw_priv, SVGA_REG_DISPLAY_WIDTH); - save->height = vmw_read(vmw_priv, SVGA_REG_DISPLAY_HEIGHT); - vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID); - if (i == 0 && vmw_priv->num_displays == 1 && - save->width == 0 && save->height == 0) { - - /* - * It should be fairly safe to assume that these - * values are uninitialized. - */ - - save->width = vmw_priv->vga_width - save->pos_x; - save->height = vmw_priv->vga_height - save->pos_y; - } - } - - return 0; -} - -int vmw_kms_restore_vga(struct vmw_private *vmw_priv) -{ - struct vmw_vga_topology_state *save; - uint32_t i; - - vmw_write(vmw_priv, SVGA_REG_WIDTH, vmw_priv->vga_width); - vmw_write(vmw_priv, SVGA_REG_HEIGHT, vmw_priv->vga_height); - vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, vmw_priv->vga_bpp); - if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK) - vmw_write(vmw_priv, SVGA_REG_PITCHLOCK, - vmw_priv->vga_pitchlock); - else if (vmw_fifo_have_pitchlock(vmw_priv)) - vmw_mmio_write(vmw_priv->vga_pitchlock, - vmw_priv->mmio_virt + SVGA_FIFO_PITCHLOCK); - - if (!(vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY)) - return 0; - - for (i = 0; i < vmw_priv->num_displays; ++i) { - save = &vmw_priv->vga_save[i]; - vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, i); - vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, save->primary); - vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, save->pos_x); - vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y, save->pos_y); - vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, save->width); - vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, save->height); - vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID); - } - - return 0; -} - bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv, uint32_t pitch, uint32_t height) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c index fdb52f6d29fb..cd7ed1650d60 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c @@ -353,37 +353,6 @@ static int vmw_overlay_update_stream(struct vmw_private *dev_priv, return 0; } -/** - * Stop all streams. - * - * Used by the fb code when starting. - * - * Takes the overlay lock. - */ -int vmw_overlay_stop_all(struct vmw_private *dev_priv) -{ - struct vmw_overlay *overlay = dev_priv->overlay_priv; - int i, ret; - - if (!overlay) - return 0; - - mutex_lock(&overlay->mutex); - - for (i = 0; i < VMW_MAX_NUM_STREAMS; i++) { - struct vmw_stream *stream = &overlay->stream[i]; - if (!stream->buf) - continue; - - ret = vmw_overlay_stop(dev_priv, i, false, false); - WARN_ON(ret != 0); - } - - mutex_unlock(&overlay->mutex); - - return 0; -} - /** * Try to resume all paused streams. * -- cgit v1.2.3 From 6b656755428dc0c96d21d7af697dc2a10c7ff175 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 5 Mar 2020 04:58:42 -0600 Subject: drm/vmwgfx: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertently introduced[3] to the codebase from now on. Also, notice that, dynamic memory allocations won't be affected by this change: "Flexible array members have incomplete type, and so the sizeof operator may not be applied. As a quirk of the original implementation of zero-length arrays, sizeof evaluates to zero."[1] This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Reviewed-by: Thomas Hellstrom Signed-off-by: Thomas Hellstrom --- drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c b/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c index f07aa857587c..60cfbfadd3f2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c @@ -69,7 +69,7 @@ struct vmw_bo_dirty { unsigned int ref_count; unsigned long bitmap_size; size_t size; - unsigned long bitmap[0]; + unsigned long bitmap[]; }; /** diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c index 3ce630aa4fde..ec893cd17b50 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c @@ -79,7 +79,7 @@ struct vmw_surface_dirty { struct svga3dsurface_cache cache; size_t size; u32 num_subres; - SVGA3dBox boxes[0]; + SVGA3dBox boxes[]; }; static void vmw_user_surface_free(struct vmw_resource *res); -- cgit v1.2.3