[PATCH] drm/vmwgfx: Clamp the max COTable size

Ian Forbes ian.forbes at broadcom.com
Mon Jul 28 21:08:45 UTC 2025


Due to a quirk of the SVGA device the MOB that backs the COTable cannot
exceed SVGA_COTABLE_MAX_IDS elements. This causes issues because MOBs
are allocated in PAGE_SIZE chunks which means we always round up the
size to the next page. This causes the device to error out when we try
to set a COTable that can store SVGA_COTABLE_MAX_IDS but is slightly
over-allocated by some fraction of a page. This then leaves the device
in an indeterminate state.

Due to the doubling logic in vmw_cotable_create this occurs when we
allocate slightly more than half the available IDs. As a result the
validation logic in vmw_cotable_notify never trips which is what we
currently rely on to limit the size of the COTable indirectly.

By reducing SVGA_COTABLE_MAX_IDS to a slightly smaller value we can avoid
this quirk. Any application getting close to this limit is likely
leaking resources so reducing the size by less than 1% should not have
any noticeable impact on well behaving applications.

Fixes: d80efd5cb3de ("drm/vmwgfx: Initial DX support")
Signed-off-by: Ian Forbes <ian.forbes at broadcom.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c
index 98331c4c0335..366e97a95179 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c
@@ -74,6 +74,11 @@ struct vmw_cotable_info {
 			    bool);
 };
 
+/*
+ * Due to a quirk of SVGA device we can't actually allocate SVGA_COTABLE_MAX_IDS
+ * for all resource types. This new limit will work regardless of type.
+ */
+#define SVGA_COTABLE_EFFECTIVE_MAX_IDS (SVGA_COTABLE_MAX_IDS - 510)
 
 /*
  * Getting the initial size right is difficult because it all depends
@@ -545,6 +550,7 @@ static int vmw_cotable_create(struct vmw_resource *res)
 {
 	struct vmw_cotable *vcotbl = vmw_cotable(res);
 	size_t new_size = res->guest_memory_size;
+	size_t max_size = co_info[vcotbl->type].size * SVGA_COTABLE_EFFECTIVE_MAX_IDS;
 	size_t needed_size;
 	int ret;
 
@@ -553,6 +559,8 @@ static int vmw_cotable_create(struct vmw_resource *res)
 	while (needed_size > new_size)
 		new_size *= 2;
 
+	new_size = MIN(new_size, max_size);
+
 	if (likely(new_size <= res->guest_memory_size)) {
 		if (vcotbl->scrubbed && vmw_resource_mob_attached(res)) {
 			ret = vmw_cotable_unscrub(res);
@@ -650,7 +658,7 @@ int vmw_cotable_notify(struct vmw_resource *res, int id)
 {
 	struct vmw_cotable *vcotbl = vmw_cotable(res);
 
-	if (id < 0 || id >= SVGA_COTABLE_MAX_IDS) {
+	if (id < 0 || id >= SVGA_COTABLE_EFFECTIVE_MAX_IDS) {
 		DRM_ERROR("Illegal COTable id. Type is %u. Id is %d\n",
 			  (unsigned) vcotbl->type, id);
 		return -EINVAL;
-- 
2.50.1



More information about the dri-devel mailing list