From nobody Mon Apr 6 10:42:01 2026 Received: from mail-wr1-f49.google.com (mail-wr1-f49.google.com [209.85.221.49]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8B7D63FE35C for ; Thu, 19 Mar 2026 20:25:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773951960; cv=none; b=XIOwsCvfpAIl3is6fk0Uq2Jeg3TjenUWYwvewQzyp29o7yQLaJZnjMyGKREbwuJsfK35WXg5eMjSrIBIwGjWoUHyZpXxwpq6MRVAIqpIdQLjHxVRwxeDuMJiC+K3NCDPGo3vlU8FS4sZPxrmswHwsiJPfvxRxe93iOrgvcJgpMw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773951960; c=relaxed/simple; bh=PZhfdkz6l06fsjXhfbGY5sTpwcEke0jta0C1rvcvPOg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jWifNmNtNh/7kaA9RLYF7aRFvqvNYQmyGEJdN9KfpE3VzJNlOSWZhrPfUeVaj8xYZoe3mDLyVBf+B3tEb61ufLnjCD0XAGjq9Tq77jrmc2ESsa/QOCVtDEX7yb6V6hCg6enOvq0evGcWggA+HNhUeQ7mIPPGPVbB/9/EkOFjs/o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=lUR0p8Vx; arc=none smtp.client-ip=209.85.221.49 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="lUR0p8Vx" Received: by mail-wr1-f49.google.com with SMTP id ffacd0b85a97d-43b49819938so713035f8f.0 for ; Thu, 19 Mar 2026 13:25:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773951954; x=1774556754; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=i9rYNHxfIvxcKsQ5ZLeeb8g2hhtOSjW/hV2qStJ99hI=; b=lUR0p8VxV4zsNnG1lqlfthJciimVjKCi7azHXERgNIMeFGEsRCU4btg2ReH8Lgd6xL ktPdfmGYD6uV2I3ZqL0ufomjcAqH0YPuVXoWO3dEMFCmNtnEwZNymzv94HIj+uqYW0x7 J8uaRoqPuJA5IsLzazNfz1AN3dFvidUtoKmo3hB7P1qDPRUmJEi7r+c5DAe50/HnePM1 k6exZI/H9dFbLrtFV3olantFSnxONx9CjPtptaU9Bi02RYiUcOp9Fz5B72Ta1UshKT/E kjHnPT1zxsRuXxZNc/jSls8ohbg25303CmhiJR7CFeA0w8F+KNJrXO6zfsQdatPujDhk PkBg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773951954; x=1774556754; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=i9rYNHxfIvxcKsQ5ZLeeb8g2hhtOSjW/hV2qStJ99hI=; b=krqzIV658nlsnQ+YOYuLgg5l/Ot9jecgsIsvMan2TFO4HGhLuGnm3gWIS2wEQ5JCvT wiisYe/7i2nwt/synGhVnWwz3OxS+YRCpl7Ehn2kl77OQ+00qEKWokOHwg9YJtS1g5In OjpOnBEFVgASrfsqScsdtChNb7W3HIZXrkv1bkVwCdvkhSQ/vgbNJfJwz57NYw+T66P6 S9x5Sl7p1PQpiCiPWgv69HDNZn1F3Ex4QLk4r9UyJEOJ6YkX6SfcRCfbml2N0ElTNIMQ 6MH26vKOT74XNOqYTfx1AGacVLWT01wkqZGV7cvSQfMICxSYp8oVgjDWX4G2j15N+o62 vZZw== X-Gm-Message-State: AOJu0Yw1Ti6zUH6EjBQxpqjFxc+7urBRFSML9mKQg+mPfs+uKeiUzuEI XF5AD1B+Q3xoeQcgPlpoUffC4mP37G40PnuS1/GKgIE7cR9pZbXb4vrI3aR77PEqleY= X-Gm-Gg: ATEYQzxnvKMG/RjUtzXZGTPQenqKTohM4xR+GFr2wdX8fv5lM+QqcswXootsVyeBoRz iCyCzbsiUPMPawtTy8f1wlzBrT1rN7jRTobevgnwG1/lEAvdAgF4C2gjgasQV4X7Z+Wn7PH8bRj AmsxMFVHNZ+S5sJe5LBAj/5tTUMuCI4kJooWfDsOGP2dGhOkLwbG3zVkAUuTB6O0l70FERotQAj bFcM66oLKPMwNNygbNokBv/ktDUxTG3Ga9MnD7cs7zCPKVoiXsl6GZ5tgOyHOSh/56XfHBD1TNV c8k1SmrHY6x6E/SLkj0HviNnWgPQEQtmBdZQatXUyxxTX+O8EQ5jKRafpYteNYMM3gz6kTJOSX2 PVJ8E+9FetZCuZdOJuaimLIB9uTWTyFouIKPbtio2RUExoWrDGzwzVBDESsJHXrVQj6AJL9/8wD JqG34wXZBoj2uRjl042Z8CMnV9AJZhQ+WOcftBC/7KZabHPynX X-Received: by 2002:a05:6000:22c2:b0:43b:44e6:6e4a with SMTP id ffacd0b85a97d-43b6428ad26mr1156153f8f.52.1773951953472; Thu, 19 Mar 2026 13:25:53 -0700 (PDT) Received: from LQ5W56KC4T ([2001:8a0:672f:7800:e0e1:55cd:f0b:b1e5]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-43b644ae16fsm1347544f8f.8.2026.03.19.13.25.52 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Thu, 19 Mar 2026 13:25:53 -0700 (PDT) From: Eric Curtin X-Google-Original-From: Eric Curtin To: linux-hyperv@vger.kernel.org Cc: linux-kernel@vger.kernel.org, iourit@linux.microsoft.com, wei.liu@kernel.org, decui@microsoft.com, haiyangz@microsoft.com Subject: [PATCH 35/55] drivers: hv: dxgkrnl: Fix synchronization locks Date: Thu, 19 Mar 2026 20:24:49 +0000 Message-ID: <20260319202509.63802-36-eric.curtin@docker.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260319202509.63802-1-eric.curtin@docker.com> References: <20260319202509.63802-1-eric.curtin@docker.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Iouri Tarassov Signed-off-by: Iouri Tarassov [kms: forward port to 6.6 from 6.1. No code changes made.] Signed-off-by: Kelsey Steele --- drivers/hv/dxgkrnl/dxgadapter.c | 19 ++++---- drivers/hv/dxgkrnl/dxgkrnl.h | 8 +++- drivers/hv/dxgkrnl/dxgmodule.c | 3 +- drivers/hv/dxgkrnl/dxgprocess.c | 11 +++-- drivers/hv/dxgkrnl/dxgvmbus.c | 85 +++++++++++++++++++++++---------- drivers/hv/dxgkrnl/ioctl.c | 24 ++++++---- drivers/hv/dxgkrnl/misc.h | 1 + 7 files changed, 101 insertions(+), 50 deletions(-) diff --git a/drivers/hv/dxgkrnl/dxgadapter.c b/drivers/hv/dxgkrnl/dxgadapte= r.c index 3d8bec295b87..d9d45bd4a31e 100644 --- a/drivers/hv/dxgkrnl/dxgadapter.c +++ b/drivers/hv/dxgkrnl/dxgadapter.c @@ -136,7 +136,7 @@ void dxgadapter_release(struct kref *refcount) struct dxgadapter *adapter; =20 adapter =3D container_of(refcount, struct dxgadapter, adapter_kref); - DXG_TRACE("%p", adapter); + DXG_TRACE("Destroying adapter: %px", adapter); kfree(adapter); } =20 @@ -270,6 +270,8 @@ struct dxgdevice *dxgdevice_create(struct dxgadapter *a= dapter, if (ret < 0) { kref_put(&device->device_kref, dxgdevice_release); device =3D NULL; + } else { + DXG_TRACE("dxgdevice created: %px", device); } } return device; @@ -413,11 +415,8 @@ void dxgdevice_destroy(struct dxgdevice *device) =20 cleanup: =20 - if (device->adapter) { + if (device->adapter) dxgprocess_adapter_remove_device(device); - kref_put(&device->adapter->adapter_kref, dxgadapter_release); - device->adapter =3D NULL; - } =20 up_write(&device->device_lock); =20 @@ -721,6 +720,8 @@ void dxgdevice_release(struct kref *refcount) struct dxgdevice *device; =20 device =3D container_of(refcount, struct dxgdevice, device_kref); + DXG_TRACE("Destroying device: %px", device); + kref_put(&device->adapter->adapter_kref, dxgadapter_release); kfree(device); } =20 @@ -999,6 +1000,9 @@ void dxgpagingqueue_destroy(struct dxgpagingqueue *pqu= eue) kfree(pqueue); } =20 +/* + * Process_adapter_mutex is held. + */ struct dxgprocess_adapter *dxgprocess_adapter_create(struct dxgprocess *pr= ocess, struct dxgadapter *adapter) { @@ -1108,7 +1112,7 @@ int dxgprocess_adapter_add_device(struct dxgprocess *= process, =20 void dxgprocess_adapter_remove_device(struct dxgdevice *device) { - DXG_TRACE("Removing device: %p", device); + DXG_TRACE("Removing device: %px", device); mutex_lock(&device->adapter_info->device_list_mutex); if (device->device_list_entry.next) { list_del(&device->device_list_entry); @@ -1147,8 +1151,7 @@ void dxgsharedsyncobj_release(struct kref *refcount) if (syncobj->adapter) { dxgadapter_remove_shared_syncobj(syncobj->adapter, syncobj); - kref_put(&syncobj->adapter->adapter_kref, - dxgadapter_release); + kref_put(&syncobj->adapter->adapter_kref, dxgadapter_release); } kfree(syncobj); } diff --git a/drivers/hv/dxgkrnl/dxgkrnl.h b/drivers/hv/dxgkrnl/dxgkrnl.h index f63aa6f7a9dc..1b40d6e39085 100644 --- a/drivers/hv/dxgkrnl/dxgkrnl.h +++ b/drivers/hv/dxgkrnl/dxgkrnl.h @@ -404,7 +404,10 @@ struct dxgprocess { /* Handle of the corresponding objec on the host */ struct d3dkmthandle host_handle; =20 - /* List of opened adapters (dxgprocess_adapter) */ + /* + * List of opened adapters (dxgprocess_adapter). + * Protected by process_adapter_mutex. + */ struct list_head process_adapter_list_head; }; =20 @@ -451,6 +454,8 @@ enum dxgadapter_state { struct dxgadapter { struct rw_semaphore core_lock; struct kref adapter_kref; + /* Protects creation and destruction of dxgdevice objects */ + struct mutex device_creation_lock; /* Entry in the list of adapters in dxgglobal */ struct list_head adapter_list_entry; /* The list of dxgprocess_adapter entries */ @@ -997,6 +1002,7 @@ void dxgk_validate_ioctls(void); =20 #define DXG_TRACE(fmt, ...) do { \ trace_printk(dev_fmt(fmt) "\n", ##__VA_ARGS__); \ + dev_dbg(DXGDEV, "%s: " fmt, __func__, ##__VA_ARGS__); \ } while (0) =20 #define DXG_ERR(fmt, ...) do { \ diff --git a/drivers/hv/dxgkrnl/dxgmodule.c b/drivers/hv/dxgkrnl/dxgmodule.c index aa27931a3447..f419597f711a 100644 --- a/drivers/hv/dxgkrnl/dxgmodule.c +++ b/drivers/hv/dxgkrnl/dxgmodule.c @@ -272,6 +272,7 @@ int dxgglobal_create_adapter(struct pci_dev *dev, guid_= t *guid, adapter->host_vgpu_luid =3D host_vgpu_luid; kref_init(&adapter->adapter_kref); init_rwsem(&adapter->core_lock); + mutex_init(&adapter->device_creation_lock); =20 INIT_LIST_HEAD(&adapter->adapter_process_list_head); INIT_LIST_HEAD(&adapter->shared_resource_list_head); @@ -961,4 +962,4 @@ module_exit(dxg_drv_exit); =20 MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Microsoft Dxgkrnl virtual compute device Driver"); -MODULE_VERSION("2.0.0"); +MODULE_VERSION("2.0.1"); diff --git a/drivers/hv/dxgkrnl/dxgprocess.c b/drivers/hv/dxgkrnl/dxgproces= s.c index e77e3a4983f8..fd51fd968049 100644 --- a/drivers/hv/dxgkrnl/dxgprocess.c +++ b/drivers/hv/dxgkrnl/dxgprocess.c @@ -214,14 +214,15 @@ int dxgprocess_close_adapter(struct dxgprocess *proce= ss, hmgrtable_unlock(&process->local_handle_table, DXGLOCK_EXCL); =20 if (adapter) { + mutex_lock(&adapter->device_creation_lock); + dxgglobal_acquire_process_adapter_lock(); adapter_info =3D dxgprocess_get_adapter_info(process, adapter); - if (adapter_info) { - dxgglobal_acquire_process_adapter_lock(); + if (adapter_info) dxgprocess_adapter_release(adapter_info); - dxgglobal_release_process_adapter_lock(); - } else { + else ret =3D -EINVAL; - } + dxgglobal_release_process_adapter_lock(); + mutex_unlock(&adapter->device_creation_lock); } else { DXG_ERR("Adapter not found %x", handle.v); ret =3D -EINVAL; diff --git a/drivers/hv/dxgkrnl/dxgvmbus.c b/drivers/hv/dxgkrnl/dxgvmbus.c index 566ccb6d01c9..8c99f141482e 100644 --- a/drivers/hv/dxgkrnl/dxgvmbus.c +++ b/drivers/hv/dxgkrnl/dxgvmbus.c @@ -1573,8 +1573,27 @@ process_allocation_handles(struct dxgprocess *proces= s, struct dxgresource *resource) { int ret =3D 0; - int i; + int i =3D 0; + int k; + struct dxgkvmb_command_allocinfo_return *host_alloc; =20 + /* + * Assign handle to the internal objects, so VM bus messages will be + * sent to the host to free them during object destruction. + */ + if (args->flags.create_resource) + resource->handle =3D res->resource; + for (i =3D 0; i < args->alloc_count; i++) { + host_alloc =3D &res->allocation_info[i]; + dxgalloc[i]->alloc_handle =3D host_alloc->allocation; + } + + /* + * Assign handle to the handle table. + * In case of a failure all handles should be freed. + * When the function returns, the objects could be destroyed by + * handle immediately. + */ hmgrtable_lock(&process->handle_table, DXGLOCK_EXCL); if (args->flags.create_resource) { ret =3D hmgrtable_assign_handle(&process->handle_table, resource, @@ -1583,14 +1602,12 @@ process_allocation_handles(struct dxgprocess *proce= ss, if (ret < 0) { DXG_ERR("failed to assign resource handle %x", res->resource.v); + goto cleanup; } else { - resource->handle =3D res->resource; resource->handle_valid =3D 1; } } for (i =3D 0; i < args->alloc_count; i++) { - struct dxgkvmb_command_allocinfo_return *host_alloc; - host_alloc =3D &res->allocation_info[i]; ret =3D hmgrtable_assign_handle(&process->handle_table, dxgalloc[i], @@ -1602,9 +1619,26 @@ process_allocation_handles(struct dxgprocess *proces= s, args->alloc_count, i); break; } - dxgalloc[i]->alloc_handle =3D host_alloc->allocation; dxgalloc[i]->handle_valid =3D 1; } + if (ret < 0) { + if (args->flags.create_resource) { + hmgrtable_free_handle(&process->handle_table, + HMGRENTRY_TYPE_DXGRESOURCE, + res->resource); + resource->handle_valid =3D 0; + } + for (k =3D 0; k < i; k++) { + host_alloc =3D &res->allocation_info[i]; + hmgrtable_free_handle(&process->handle_table, + HMGRENTRY_TYPE_DXGALLOCATION, + host_alloc->allocation); + dxgalloc[i]->handle_valid =3D 0; + } + } + +cleanup: + hmgrtable_unlock(&process->handle_table, DXGLOCK_EXCL); =20 if (ret) @@ -1705,18 +1739,17 @@ create_local_allocations(struct dxgprocess *process, } } =20 - ret =3D process_allocation_handles(process, device, args, result, - dxgalloc, resource); - if (ret < 0) - goto cleanup; - ret =3D copy_to_user(&input_args->global_share, &args->global_share, sizeof(struct d3dkmthandle)); if (ret) { DXG_ERR("failed to copy global share"); ret =3D -EFAULT; + goto cleanup; } =20 + ret =3D process_allocation_handles(process, device, args, result, + dxgalloc, resource); + cleanup: =20 if (ret < 0) { @@ -3576,22 +3609,6 @@ int dxgvmb_send_create_hwqueue(struct dxgprocess *pr= ocess, goto cleanup; } =20 - ret =3D hmgrtable_assign_handle_safe(&process->handle_table, hwqueue, - HMGRENTRY_TYPE_DXGHWQUEUE, - command->hwqueue); - if (ret < 0) - goto cleanup; - - ret =3D hmgrtable_assign_handle_safe(&process->handle_table, - NULL, - HMGRENTRY_TYPE_MONITOREDFENCE, - command->hwqueue_progress_fence); - if (ret < 0) - goto cleanup; - - hwqueue->handle =3D command->hwqueue; - hwqueue->progress_fence_sync_object =3D command->hwqueue_progress_fence; - hwqueue->progress_fence_mapped_address =3D dxg_map_iospace((u64)command->hwqueue_progress_fence_cpuva, PAGE_SIZE, PROT_READ | PROT_WRITE, true); @@ -3641,6 +3658,22 @@ int dxgvmb_send_create_hwqueue(struct dxgprocess *pr= ocess, } } =20 + ret =3D hmgrtable_assign_handle_safe(&process->handle_table, + NULL, + HMGRENTRY_TYPE_MONITOREDFENCE, + command->hwqueue_progress_fence); + if (ret < 0) + goto cleanup; + + hwqueue->progress_fence_sync_object =3D command->hwqueue_progress_fence; + hwqueue->handle =3D command->hwqueue; + + ret =3D hmgrtable_assign_handle_safe(&process->handle_table, hwqueue, + HMGRENTRY_TYPE_DXGHWQUEUE, + command->hwqueue); + if (ret < 0) + hwqueue->handle.v =3D 0; + cleanup: if (ret < 0) { DXG_ERR("failed %x", ret); diff --git a/drivers/hv/dxgkrnl/ioctl.c b/drivers/hv/dxgkrnl/ioctl.c index 3dc9e76f4f3d..7c72790f917f 100644 --- a/drivers/hv/dxgkrnl/ioctl.c +++ b/drivers/hv/dxgkrnl/ioctl.c @@ -636,6 +636,7 @@ dxgkio_create_device(struct dxgprocess *process, void *= __user inargs) struct dxgdevice *device =3D NULL; struct d3dkmthandle host_device_handle =3D {}; bool adapter_locked =3D false; + bool device_creation_locked =3D false; =20 ret =3D copy_from_user(&args, inargs, sizeof(args)); if (ret) { @@ -651,6 +652,9 @@ dxgkio_create_device(struct dxgprocess *process, void *= __user inargs) goto cleanup; } =20 + mutex_lock(&adapter->device_creation_lock); + device_creation_locked =3D true; + device =3D dxgdevice_create(adapter, process); if (device =3D=3D NULL) { ret =3D -ENOMEM; @@ -699,6 +703,9 @@ dxgkio_create_device(struct dxgprocess *process, void *= __user inargs) if (adapter_locked) dxgadapter_release_lock_shared(adapter); =20 + if (device_creation_locked) + mutex_unlock(&adapter->device_creation_lock); + if (adapter) kref_put(&adapter->adapter_kref, dxgadapter_release); =20 @@ -803,22 +810,21 @@ dxgkio_create_context_virtual(struct dxgprocess *proc= ess, void *__user inargs) host_context_handle =3D dxgvmb_send_create_context(adapter, process, &args); if (host_context_handle.v) { - hmgrtable_lock(&process->handle_table, DXGLOCK_EXCL); - ret =3D hmgrtable_assign_handle(&process->handle_table, context, - HMGRENTRY_TYPE_DXGCONTEXT, - host_context_handle); - if (ret >=3D 0) - context->handle =3D host_context_handle; - hmgrtable_unlock(&process->handle_table, DXGLOCK_EXCL); - if (ret < 0) - goto cleanup; ret =3D copy_to_user(&((struct d3dkmt_createcontextvirtual *) inargs)->context, &host_context_handle, sizeof(struct d3dkmthandle)); if (ret) { DXG_ERR("failed to copy context handle"); ret =3D -EFAULT; + goto cleanup; } + hmgrtable_lock(&process->handle_table, DXGLOCK_EXCL); + ret =3D hmgrtable_assign_handle(&process->handle_table, context, + HMGRENTRY_TYPE_DXGCONTEXT, + host_context_handle); + if (ret >=3D 0) + context->handle =3D host_context_handle; + hmgrtable_unlock(&process->handle_table, DXGLOCK_EXCL); } else { DXG_ERR("invalid host handle"); ret =3D -EINVAL; diff --git a/drivers/hv/dxgkrnl/misc.h b/drivers/hv/dxgkrnl/misc.h index ee2ebfdd1c13..9fcab4ae2c0c 100644 --- a/drivers/hv/dxgkrnl/misc.h +++ b/drivers/hv/dxgkrnl/misc.h @@ -38,6 +38,7 @@ extern const struct d3dkmthandle zerohandle; * core_lock (dxgadapter lock) * device_lock (dxgdevice lock) * process_adapter_mutex + * device_creation_lock in dxgadapter * adapter_list_lock * device_mutex (dxgglobal mutex) */