* [PATCH 55/55] drivers: hv: dxgkrnl: Code cleanup for upstream submission
From: Eric Curtin @ 2026-03-19 20:25 UTC (permalink / raw)
To: linux-hyperv; +Cc: linux-kernel, iourit, wei.liu, decui, haiyangz
In-Reply-To: <20260319202509.63802-1-eric.curtin@docker.com>
Address issues raised in previous LKML submission attempts (v1-v3):
- Replace deprecated one-element arrays [1] with C99 flexible arrays []
in dxgvmbus.h and dxgkrnl.h
- Replace %px with %p in DXG_TRACE calls (avoids exposing kernel layout)
- Remove unnecessary braces from single-statement if blocks
- Remove LINUX_VERSION_CODE guard: max_pkt_size exists in all supported kernels
- Remove unused linux/version.h include from dxgkrnl.h
- Fix whitespace (space before tab) in dxgvmbus.h and d3dkmthk.h
- Replace DXG_ERR non-debug macro do{}while(0) with direct dev_err call
- Change -EBADE to -ENODEV for global channel duplicate detection
- Remove MODULE_VERSION as it is not recommended for in-tree drivers
- Add explanatory comment to guid_to_luid() cast
- Update MAINTAINERS email to iourit@linux.microsoft.com
Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
---
MAINTAINERS | 2 +-
drivers/hv/dxgkrnl/dxgadapter.c | 8 ++++----
drivers/hv/dxgkrnl/dxgkrnl.h | 13 +++++--------
drivers/hv/dxgkrnl/dxgmodule.c | 5 ++---
drivers/hv/dxgkrnl/dxgvmbus.c | 5 +----
drivers/hv/dxgkrnl/dxgvmbus.h | 26 +++++++++++++-------------
drivers/hv/dxgkrnl/hmgr.c | 3 +--
include/uapi/misc/d3dkmthk.h | 2 +-
8 files changed, 28 insertions(+), 36 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 4fe0b3501931..493c65a02b80 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9772,7 +9772,7 @@ F: drivers/mtd/hyperbus/
F: include/linux/mtd/hyperbus.h
Hyper-V vGPU DRIVER
-M: Iouri Tarassov <iourit@microsoft.com>
+M: Iouri Tarassov <iourit@linux.microsoft.com>
L: linux-hyperv@vger.kernel.org
S: Supported
F: drivers/hv/dxgkrnl/
diff --git a/drivers/hv/dxgkrnl/dxgadapter.c b/drivers/hv/dxgkrnl/dxgadapter.c
index 6d3cabb24e6f..d395fdcb63fa 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;
adapter = container_of(refcount, struct dxgadapter, adapter_kref);
- DXG_TRACE("Destroying adapter: %px", adapter);
+ DXG_TRACE("Destroying adapter: %p", adapter);
kfree(adapter);
}
@@ -271,7 +271,7 @@ struct dxgdevice *dxgdevice_create(struct dxgadapter *adapter,
kref_put(&device->device_kref, dxgdevice_release);
device = NULL;
} else {
- DXG_TRACE("dxgdevice created: %px", device);
+ DXG_TRACE("dxgdevice created: %p", device);
}
}
return device;
@@ -720,7 +720,7 @@ void dxgdevice_release(struct kref *refcount)
struct dxgdevice *device;
device = container_of(refcount, struct dxgdevice, device_kref);
- DXG_TRACE("Destroying device: %px", device);
+ DXG_TRACE("Destroying device: %p", device);
kref_put(&device->adapter->adapter_kref, dxgadapter_release);
kfree(device);
}
@@ -1103,7 +1103,7 @@ int dxgprocess_adapter_add_device(struct dxgprocess *process,
void dxgprocess_adapter_remove_device(struct dxgdevice *device)
{
- DXG_TRACE("Removing device: %px", device);
+ DXG_TRACE("Removing device: %p", device);
mutex_lock(&device->adapter_info->device_list_mutex);
if (device->device_list_entry.next) {
list_del(&device->device_list_entry);
diff --git a/drivers/hv/dxgkrnl/dxgkrnl.h b/drivers/hv/dxgkrnl/dxgkrnl.h
index d816a875d5ab..4a4605f45736 100644
--- a/drivers/hv/dxgkrnl/dxgkrnl.h
+++ b/drivers/hv/dxgkrnl/dxgkrnl.h
@@ -27,7 +27,6 @@
#include <linux/pci.h>
#include <linux/hyperv.h>
#include <uapi/misc/d3dkmthk.h>
-#include <linux/version.h>
#include "misc.h"
#include "hmgr.h"
#include <uapi/misc/d3dkmthk.h>
@@ -719,7 +718,7 @@ bool dxgresource_is_active(struct dxgresource *res);
struct privdata {
u32 data_size;
- u8 data[1];
+ u8 data[];
};
struct dxgallocation {
@@ -769,9 +768,9 @@ long dxgk_unlocked_ioctl(struct file *f, unsigned int p1, unsigned long p2);
int dxg_unmap_iospace(void *va, u32 size);
/*
- * The convention is that VNBus instance id is a GUID, but the host sets
- * the lower part of the value to the host adapter LUID. The function
- * provides the necessary conversion.
+ * The convention is that VMBus instance id is a GUID, but the host sets
+ * the lower part of the value to the host adapter LUID. The cast reads
+ * the first sizeof(winluid) bytes of the GUID as a winluid value.
*/
static inline void guid_to_luid(guid_t *guid, struct winluid *luid)
{
@@ -1029,9 +1028,7 @@ void dxgk_validate_ioctls(void);
#else
#define DXG_TRACE(...)
-#define DXG_ERR(fmt, ...) do { \
- dev_err(DXGDEV, "%s: " fmt, __func__, ##__VA_ARGS__); \
-} while (0)
+#define DXG_ERR(fmt, ...) dev_err(DXGDEV, "%s: " fmt, __func__, ##__VA_ARGS__)
#endif /* DEBUG */
diff --git a/drivers/hv/dxgkrnl/dxgmodule.c b/drivers/hv/dxgkrnl/dxgmodule.c
index c2a4a2a2136f..435dc60511b8 100644
--- a/drivers/hv/dxgkrnl/dxgmodule.c
+++ b/drivers/hv/dxgkrnl/dxgmodule.c
@@ -158,7 +158,7 @@ static void dxg_signal_dma_fence(struct dxghostevent *eventhdr)
{
struct dxgsyncpoint *event = (struct dxgsyncpoint *)eventhdr;
- DXG_TRACE("syncpoint: %px, fence: %lld", event, event->fence_value);
+ DXG_TRACE("syncpoint: %p, fence: %lld", event, event->fence_value);
event->fence_value++;
list_del(&eventhdr->host_event_list_entry);
dma_fence_signal(&event->base);
@@ -788,7 +788,7 @@ static int dxg_probe_vmbus(struct hv_device *hdev,
if (dxgglobal->hdev) {
/* This device should appear only once */
DXG_ERR("global channel already exists");
- ret = -EBADE;
+ ret = -ENODEV;
goto error;
}
dxgglobal->hdev = hdev;
@@ -969,4 +969,3 @@ module_exit(dxg_drv_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Microsoft Dxgkrnl virtual compute device Driver");
-MODULE_VERSION("2.0.3");
diff --git a/drivers/hv/dxgkrnl/dxgvmbus.c b/drivers/hv/dxgkrnl/dxgvmbus.c
index abb6d2af89ac..4b1ccaac440c 100644
--- a/drivers/hv/dxgkrnl/dxgvmbus.c
+++ b/drivers/hv/dxgkrnl/dxgvmbus.c
@@ -246,9 +246,7 @@ int dxgvmbuschannel_init(struct dxgvmbuschannel *ch, struct hv_device *hdev)
goto cleanup;
}
-#if KERNEL_VERSION(5, 15, 0) <= LINUX_VERSION_CODE
hdev->channel->max_pkt_size = DXG_MAX_VM_BUS_PACKET_SIZE;
-#endif
ret = vmbus_open(hdev->channel, RING_BUFSIZE, RING_BUFSIZE,
NULL, 0, dxgvmbuschannel_receive, ch);
if (ret) {
@@ -1482,9 +1480,8 @@ int create_existing_sysmem(struct dxgdevice *device,
dxgalloc->pages);
if (ret1 != npages) {
DXG_ERR("get_user_pages_fast failed: %d", ret1);
- if (ret1 > 0 && ret1 < npages) {
+ if (ret1 > 0 && ret1 < npages)
unpin_user_pages(dxgalloc->pages, ret1);
- }
vfree(dxgalloc->pages);
dxgalloc->pages = NULL;
ret = -ENOMEM;
diff --git a/drivers/hv/dxgkrnl/dxgvmbus.h b/drivers/hv/dxgkrnl/dxgvmbus.h
index a7e625b2f896..22246826d2f1 100644
--- a/drivers/hv/dxgkrnl/dxgvmbus.h
+++ b/drivers/hv/dxgkrnl/dxgvmbus.h
@@ -313,12 +313,12 @@ struct dxgkvmb_command_queryadapterinfo {
struct dxgkvmb_command_vgpu_to_host hdr;
enum kmtqueryadapterinfotype query_type;
u32 private_data_size;
- u8 private_data[1];
+ u8 private_data[];
};
struct dxgkvmb_command_queryadapterinfo_return {
struct ntstatus status;
- u8 private_data[1];
+ u8 private_data[];
};
/* Returns ntstatus */
@@ -391,7 +391,7 @@ struct dxgkvmb_command_makeresident {
struct d3dkmthandle paging_queue;
struct d3dddi_makeresident_flags flags;
u32 alloc_count;
- struct d3dkmthandle allocations[1];
+ struct d3dkmthandle allocations[];
};
struct dxgkvmb_command_makeresident_return {
@@ -405,7 +405,7 @@ struct dxgkvmb_command_evict {
struct d3dkmthandle device;
struct d3dddi_evict_flags flags;
u32 alloc_count;
- struct d3dkmthandle allocations[1];
+ struct d3dkmthandle allocations[];
};
struct dxgkvmb_command_evict_return {
@@ -476,7 +476,7 @@ struct dxgkvmb_command_updategpuvirtualaddress {
struct d3dkmthandle fence_object;
u32 num_operations;
u32 flags;
- struct d3dddi_updategpuvirtualaddress_operation operations[1];
+ struct d3dddi_updategpuvirtualaddress_operation operations[];
};
struct dxgkvmb_command_queryclockcalibration {
@@ -627,7 +627,7 @@ struct dxgkvmb_command_destroyallocation {
struct d3dkmthandle resource;
u32 alloc_count;
struct d3dddicb_destroyallocation2flags flags;
- struct d3dkmthandle allocations[1];
+ struct d3dkmthandle allocations[];
};
struct dxgkvmb_command_createcontextvirtual {
@@ -639,7 +639,7 @@ struct dxgkvmb_command_createcontextvirtual {
struct d3dddi_createcontextflags flags;
enum d3dkmt_clienthint client_hint;
u32 priv_drv_data_size;
- u8 priv_drv_data[1];
+ u8 priv_drv_data[];
};
/* The command returns ntstatus */
@@ -768,7 +768,7 @@ struct dxgkvmb_command_offerallocations {
enum d3dkmt_offer_priority priority;
struct d3dkmt_offer_flags flags;
bool resources;
- struct d3dkmthandle allocations[1];
+ struct d3dkmthandle allocations[];
};
struct dxgkvmb_command_reclaimallocations {
@@ -778,13 +778,13 @@ struct dxgkvmb_command_reclaimallocations {
u32 allocation_count;
bool resources;
bool write_results;
- struct d3dkmthandle allocations[1];
+ struct d3dkmthandle allocations[];
};
struct dxgkvmb_command_reclaimallocations_return {
u64 paging_fence_value;
struct ntstatus status;
- enum d3dddi_reclaim_result discarded[1];
+ enum d3dddi_reclaim_result discarded[];
};
/* Returns ntstatus */
@@ -804,7 +804,7 @@ struct dxgkvmb_command_createhwqueue {
struct d3dkmthandle context;
struct d3dddi_createhwqueueflags flags;
u32 priv_drv_data_size;
- char priv_drv_data[1];
+ char priv_drv_data[];
};
/* The command returns ntstatus */
@@ -833,7 +833,7 @@ struct dxgkvmb_command_escape {
struct d3dddi_escapeflags flags;
u32 priv_drv_data_size;
struct d3dkmthandle context;
- u8 priv_drv_data[1];
+ u8 priv_drv_data[];
};
struct dxgkvmb_command_queryvideomemoryinfo {
@@ -879,7 +879,7 @@ struct dxgk_feature_desc {
struct {
u16 supported : 1;
u16 virtualization_mode : 3;
- u16 global : 1;
+ u16 global : 1;
u16 driver_feature : 1;
u16 internal : 1;
u16 reserved : 9;
diff --git a/drivers/hv/dxgkrnl/hmgr.c b/drivers/hv/dxgkrnl/hmgr.c
index 059f94307a0e..95879f59133e 100644
--- a/drivers/hv/dxgkrnl/hmgr.c
+++ b/drivers/hv/dxgkrnl/hmgr.c
@@ -467,9 +467,8 @@ void hmgrtable_free_handle(struct hmgrtable *table, enum hmgrentry_type t,
entry->next_free_index = i;
}
table->free_handle_list_tail = i;
- if (table->free_handle_list_head == HMGRTABLE_INVALID_INDEX) {
+ if (table->free_handle_list_head == HMGRTABLE_INVALID_INDEX)
table->free_handle_list_head = i;
- }
} else {
DXG_ERR("Invalid handle to free: %d %x", i, h.v);
}
diff --git a/include/uapi/misc/d3dkmthk.h b/include/uapi/misc/d3dkmthk.h
index db40e8ff40b0..a58b2513dfd3 100644
--- a/include/uapi/misc/d3dkmthk.h
+++ b/include/uapi/misc/d3dkmthk.h
@@ -1612,7 +1612,7 @@ struct d3dkmt_opensyncobjectfromsyncfile {
};
struct d3dkmt_enumprocesses {
- struct winluid adapter_luid;
+ struct winluid adapter_luid;
#ifdef __KERNEL__
__u32 *buffer;
#else
^ permalink raw reply related
* [PATCH 54/55] drivers: hv: dxgkrnl: Fix crash at hmgrtable_free_handle
From: Eric Curtin @ 2026-03-19 20:25 UTC (permalink / raw)
To: linux-hyperv; +Cc: linux-kernel, iourit, wei.liu, decui, haiyangz
In-Reply-To: <20260319202509.63802-1-eric.curtin@docker.com>
From: Hideyuki Nagase <hideyukn@microsoft.com>
Fix a potential NULL pointer crash in hmgrtable_free_handle() when
free_handle_list_tail is HMGRTABLE_INVALID_INDEX. Guard the entry
dereference with a bounds check before writing the next_free_index.
Signed-off-by: Hideyuki Nagase <hideyukn@microsoft.com>
---
drivers/hv/dxgkrnl/hmgr.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/hv/dxgkrnl/hmgr.c b/drivers/hv/dxgkrnl/hmgr.c
index 24101d0091ab..059f94307a0e 100644
--- a/drivers/hv/dxgkrnl/hmgr.c
+++ b/drivers/hv/dxgkrnl/hmgr.c
@@ -462,9 +462,14 @@ void hmgrtable_free_handle(struct hmgrtable *table, enum hmgrentry_type t,
*/
entry->next_free_index = HMGRTABLE_INVALID_INDEX;
entry->prev_free_index = table->free_handle_list_tail;
- entry = &table->entry_table[table->free_handle_list_tail];
- entry->next_free_index = i;
+ if (table->free_handle_list_tail != HMGRTABLE_INVALID_INDEX) {
+ entry = &table->entry_table[table->free_handle_list_tail];
+ entry->next_free_index = i;
+ }
table->free_handle_list_tail = i;
+ if (table->free_handle_list_head == HMGRTABLE_INVALID_INDEX) {
+ table->free_handle_list_head = i;
+ }
} else {
DXG_ERR("Invalid handle to free: %d %x", i, h.v);
}
^ permalink raw reply related
* [PATCH 53/55] drivers: hv: dxgkrnl: Do not print error messages when virtual GPU is not present
From: Eric Curtin @ 2026-03-19 20:25 UTC (permalink / raw)
To: linux-hyperv; +Cc: linux-kernel, iourit, wei.liu, decui, haiyangz
In-Reply-To: <20260319202509.63802-1-eric.curtin@docker.com>
From: Iouri Tarassov <iourit@linux.microsoft.com>
Dxgkrnl prints the error message "Failed to acquire global channel lock"
when a process tries to open the /dev/dxg device and there is no
virtual GPU. This message should not be printed in this scenario.
Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
---
drivers/hv/dxgkrnl/dxgadapter.c | 2 +-
drivers/hv/dxgkrnl/dxgmodule.c | 4 ++++
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/hv/dxgkrnl/dxgadapter.c b/drivers/hv/dxgkrnl/dxgadapter.c
index c94283b09fa1..6d3cabb24e6f 100644
--- a/drivers/hv/dxgkrnl/dxgadapter.c
+++ b/drivers/hv/dxgkrnl/dxgadapter.c
@@ -78,12 +78,12 @@ void dxgadapter_start(struct dxgadapter *adapter)
/* The global channel is initialized when the first adapter starts */
if (!dxgglobal->global_channel_initialized) {
+ dxgglobal->global_channel_initialized = true;
ret = dxgglobal_init_global_channel();
if (ret) {
dxgglobal_destroy_global_channel();
return;
}
- dxgglobal->global_channel_initialized = true;
}
/* Initialize vGPU vm bus channel */
diff --git a/drivers/hv/dxgkrnl/dxgmodule.c b/drivers/hv/dxgkrnl/dxgmodule.c
index 8f5d6db256a3..c2a4a2a2136f 100644
--- a/drivers/hv/dxgkrnl/dxgmodule.c
+++ b/drivers/hv/dxgkrnl/dxgmodule.c
@@ -46,9 +46,13 @@ int dxgglobal_acquire_channel_lock(void)
{
struct dxgglobal *dxgglobal = dxggbl();
+ if (!dxgglobal->global_channel_initialized)
+ return -ENODEV;
+
down_read(&dxgglobal->channel_lock);
if (dxgglobal->channel.channel == NULL) {
DXG_ERR("Failed to acquire global channel lock");
+ up_read(&dxgglobal->channel_lock);
return -ENODEV;
} else {
return 0;
^ permalink raw reply related
* [PATCH 52/55] drivers: hv: dxgkrnl: Use pin_user_pages instead of get_user_pages for DMA accessible memory
From: Eric Curtin @ 2026-03-19 20:25 UTC (permalink / raw)
To: linux-hyperv; +Cc: linux-kernel, iourit, wei.liu, decui, haiyangz
In-Reply-To: <20260319202509.63802-1-eric.curtin@docker.com>
From: Iouri Tarassov <iourit@linux.microsoft.com>
Pages, which are obtained by calling get_user_pages(), can be evicted from memory.
pin_user_pages() should be used for memory, which is accessed by DMA.
Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
---
drivers/hv/dxgkrnl/dxgadapter.c | 2 +-
drivers/hv/dxgkrnl/dxgvmbus.c | 12 ++++++++----
2 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/drivers/hv/dxgkrnl/dxgadapter.c b/drivers/hv/dxgkrnl/dxgadapter.c
index cf946e476411..c94283b09fa1 100644
--- a/drivers/hv/dxgkrnl/dxgadapter.c
+++ b/drivers/hv/dxgkrnl/dxgadapter.c
@@ -882,7 +882,7 @@ struct dxgallocation *dxgallocation_create(struct dxgprocess *process)
void dxgallocation_stop(struct dxgallocation *alloc)
{
if (alloc->pages) {
- release_pages(alloc->pages, alloc->num_pages);
+ unpin_user_pages(alloc->pages, alloc->num_pages);
vfree(alloc->pages);
alloc->pages = NULL;
}
diff --git a/drivers/hv/dxgkrnl/dxgvmbus.c b/drivers/hv/dxgkrnl/dxgvmbus.c
index 467e7707c8c7..abb6d2af89ac 100644
--- a/drivers/hv/dxgkrnl/dxgvmbus.c
+++ b/drivers/hv/dxgkrnl/dxgvmbus.c
@@ -1457,6 +1457,7 @@ int create_existing_sysmem(struct dxgdevice *device,
u64 *pfn;
u32 pages_to_send;
u32 i;
+ u32 gup_flags = FOLL_LONGTERM;
struct dxgglobal *dxgglobal = dxggbl();
/*
@@ -1475,12 +1476,15 @@ int create_existing_sysmem(struct dxgdevice *device,
ret = -ENOMEM;
goto cleanup;
}
- ret1 = get_user_pages_fast((unsigned long)sysmem, npages, !read_only,
- dxgalloc->pages);
+ if (!read_only)
+ gup_flags |= FOLL_WRITE;
+ ret1 = pin_user_pages_fast((unsigned long)sysmem, npages, gup_flags,
+ dxgalloc->pages);
if (ret1 != npages) {
DXG_ERR("get_user_pages_fast failed: %d", ret1);
- if (ret1 > 0 && ret1 < npages)
- release_pages(dxgalloc->pages, ret1);
+ if (ret1 > 0 && ret1 < npages) {
+ unpin_user_pages(dxgalloc->pages, ret1);
+ }
vfree(dxgalloc->pages);
dxgalloc->pages = NULL;
ret = -ENOMEM;
^ permalink raw reply related
* [PATCH 51/55] drivers: hv: dxgkrnl: Implement D3DKMTEnumProcesses to match the Windows implementation
From: Eric Curtin @ 2026-03-19 20:25 UTC (permalink / raw)
To: linux-hyperv; +Cc: linux-kernel, iourit, wei.liu, decui, haiyangz
In-Reply-To: <20260319202509.63802-1-eric.curtin@docker.com>
From: Iouri Tarassov <iourit@linux.microsoft.com>
The behavior of D3DKMTEnumProcesses on Windows is that when buffer_count is 0 or
input buffer is NULL, the number of active processes is returned. The Linux implemenation
is updated to match this.
Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
---
drivers/hv/dxgkrnl/dxgmodule.c | 2 +-
drivers/hv/dxgkrnl/ioctl.c | 29 ++++++++++++++++++-----------
2 files changed, 19 insertions(+), 12 deletions(-)
diff --git a/drivers/hv/dxgkrnl/dxgmodule.c b/drivers/hv/dxgkrnl/dxgmodule.c
index e3ac70df1b6f..8f5d6db256a3 100644
--- a/drivers/hv/dxgkrnl/dxgmodule.c
+++ b/drivers/hv/dxgkrnl/dxgmodule.c
@@ -965,4 +965,4 @@ module_exit(dxg_drv_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Microsoft Dxgkrnl virtual compute device Driver");
-MODULE_VERSION("2.0.2");
+MODULE_VERSION("2.0.3");
diff --git a/drivers/hv/dxgkrnl/ioctl.c b/drivers/hv/dxgkrnl/ioctl.c
index f8f116a7f87f..42f3de31a63c 100644
--- a/drivers/hv/dxgkrnl/ioctl.c
+++ b/drivers/hv/dxgkrnl/ioctl.c
@@ -5373,7 +5373,7 @@ dxgkio_enum_processes(struct dxgprocess *process, void *__user inargs)
struct dxgprocess_adapter *pentry;
int nump = 0; /* Current number of processes*/
struct ntstatus status;
- int ret;
+ int ret, ret1;
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
@@ -5382,12 +5382,6 @@ dxgkio_enum_processes(struct dxgprocess *process, void *__user inargs)
goto cleanup;
}
- if (args.buffer_count == 0) {
- DXG_ERR("Invalid buffer count");
- ret = -EINVAL;
- goto cleanup;
- }
-
dxgglobal_acquire_adapter_list_lock(DXGLOCK_SHARED);
dxgglobal_acquire_process_adapter_lock();
@@ -5405,6 +5399,19 @@ dxgkio_enum_processes(struct dxgprocess *process, void *__user inargs)
goto cleanup_locks;
}
+ list_for_each_entry(pentry, &adapter->adapter_process_list_head,
+ adapter_process_list_entry) {
+ if (pentry->process->nspid == task_active_pid_ns(current))
+ nump++;
+ }
+
+ if (nump > args.buffer_count || args.buffer == NULL) {
+ status.v = STATUS_BUFFER_TOO_SMALL;
+ ret = ntstatus2int(status);
+ goto cleanup_locks;
+ }
+
+ nump = 0;
list_for_each_entry(pentry, &adapter->adapter_process_list_head,
adapter_process_list_entry) {
if (pentry->process->nspid != task_active_pid_ns(current))
@@ -5429,10 +5436,10 @@ dxgkio_enum_processes(struct dxgprocess *process, void *__user inargs)
dxgglobal_release_process_adapter_lock();
dxgglobal_release_adapter_list_lock(DXGLOCK_SHARED);
- if (ret == 0) {
- ret = copy_to_user(&input->buffer_count, &nump, sizeof(u32));
- if (ret)
- DXG_ERR("failed to copy buffer count to user");
+ ret1 = copy_to_user(&input->buffer_count, &nump, sizeof(u32));
+ if (ret1) {
+ DXG_ERR("failed to copy buffer count to user");
+ ret = -EFAULT;
}
cleanup:
^ permalink raw reply related
* [PATCH 50/55] drivers: hv: dxgkrnl: Fix build breaks when switching to 6.6 kernel due to removed uuid_le_cmp
From: Eric Curtin @ 2026-03-19 20:25 UTC (permalink / raw)
To: linux-hyperv; +Cc: linux-kernel, iourit, wei.liu, decui, haiyangz
In-Reply-To: <20260319202509.63802-1-eric.curtin@docker.com>
From: Iouri Tarassov <iourit@linux.microsoft.com>
uuid_le_cmp was removed and needs to be replaced by guid_equal. The
relevant upstream commits are:
1fb1ea0d9cb8 "mei: Move uuid.h to the MEI namespace"
f5b3c341a46e "mei: Move uuid_le_cmp() to its only user"
5e6a51787fef "uuid: Decouple guid_t and uuid_le types and respective macros"
Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
---
drivers/hv/dxgkrnl/dxgmodule.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/drivers/hv/dxgkrnl/dxgmodule.c b/drivers/hv/dxgkrnl/dxgmodule.c
index 5459bd9b82fb..e3ac70df1b6f 100644
--- a/drivers/hv/dxgkrnl/dxgmodule.c
+++ b/drivers/hv/dxgkrnl/dxgmodule.c
@@ -762,7 +762,7 @@ static int dxg_probe_vmbus(struct hv_device *hdev,
mutex_lock(&dxgglobal->device_mutex);
- if (uuid_le_cmp(hdev->dev_type, dxg_vmbus_id_table[0].guid) == 0) {
+ if (guid_equal(&hdev->dev_type, &dxg_vmbus_id_table[0].guid)) {
/* This is a new virtual GPU channel */
guid_to_luid(&hdev->channel->offermsg.offer.if_instance, &luid);
DXG_TRACE("vGPU channel: %pUb",
@@ -777,8 +777,7 @@ static int dxg_probe_vmbus(struct hv_device *hdev,
list_add_tail(&vgpuch->vgpu_ch_list_entry,
&dxgglobal->vgpu_ch_list_head);
dxgglobal_start_adapters();
- } else if (uuid_le_cmp(hdev->dev_type,
- dxg_vmbus_id_table[1].guid) == 0) {
+ } else if (guid_equal(&hdev->dev_type, &dxg_vmbus_id_table[1].guid)) {
/* This is the global Dxgkgnl channel */
DXG_TRACE("Global channel: %pUb",
&hdev->channel->offermsg.offer.if_instance);
@@ -810,7 +809,7 @@ static void dxg_remove_vmbus(struct hv_device *hdev)
mutex_lock(&dxgglobal->device_mutex);
- if (uuid_le_cmp(hdev->dev_type, dxg_vmbus_id_table[0].guid) == 0) {
+ if (guid_equal(&hdev->dev_type, &dxg_vmbus_id_table[0].guid)) {
DXG_TRACE("Remove virtual GPU channel");
dxgglobal_stop_adapter_vmbus(hdev);
list_for_each_entry(vgpu_channel,
@@ -822,8 +821,7 @@ static void dxg_remove_vmbus(struct hv_device *hdev)
break;
}
}
- } else if (uuid_le_cmp(hdev->dev_type,
- dxg_vmbus_id_table[1].guid) == 0) {
+ } else if (guid_equal(&hdev->dev_type, &dxg_vmbus_id_table[1].guid)) {
DXG_TRACE("Remove global channel device");
dxgglobal_destroy_global_channel();
} else {
^ permalink raw reply related
* [PATCH 49/55] drivers: hv: dxgkrnl: Fix build breaks when switching to 6.6 kernel due to hv_driver remove callback change.
From: Eric Curtin @ 2026-03-19 20:25 UTC (permalink / raw)
To: linux-hyperv; +Cc: linux-kernel, iourit, wei.liu, decui, haiyangz
In-Reply-To: <20260319202509.63802-1-eric.curtin@docker.com>
From: Iouri Tarassov <iourit@linux.microsoft.com>
The hv_driver remove callback has been updated to return void instead of int.
dxg_remove_vmbus() in dxgmodule.c needs to be updated to match. See this
commit for more context:
96ec2939620c "Drivers: hv: Make remove callback of hyperv driver void returned"
Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
---
drivers/hv/dxgkrnl/dxgmodule.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/drivers/hv/dxgkrnl/dxgmodule.c b/drivers/hv/dxgkrnl/dxgmodule.c
index 0fafb6167229..5459bd9b82fb 100644
--- a/drivers/hv/dxgkrnl/dxgmodule.c
+++ b/drivers/hv/dxgkrnl/dxgmodule.c
@@ -803,9 +803,8 @@ static int dxg_probe_vmbus(struct hv_device *hdev,
return ret;
}
-static int dxg_remove_vmbus(struct hv_device *hdev)
+static void dxg_remove_vmbus(struct hv_device *hdev)
{
- int ret = 0;
struct dxgvgpuchannel *vgpu_channel;
struct dxgglobal *dxgglobal = dxggbl();
@@ -830,12 +829,9 @@ static int dxg_remove_vmbus(struct hv_device *hdev)
} else {
/* Unknown device type */
DXG_ERR("Unknown device type");
- ret = -ENODEV;
}
mutex_unlock(&dxgglobal->device_mutex);
-
- return ret;
}
MODULE_DEVICE_TABLE(vmbus, dxg_vmbus_id_table);
^ permalink raw reply related
* [PATCH 48/55] drivers: hv: dxgkrnl: Add support for locking a shared allocation by not the owner
From: Eric Curtin @ 2026-03-19 20:25 UTC (permalink / raw)
To: linux-hyperv; +Cc: linux-kernel, iourit, wei.liu, decui, haiyangz
In-Reply-To: <20260319202509.63802-1-eric.curtin@docker.com>
From: Iouri Tarassov <iourit@linux.microsoft.com>
WDDM has a restriction that an allocation of a shared resource can be
locked for CPU access only by the resource creator (the owner). This
restriction is removed for system memory only allocations. This change
adds support for this feature.
Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
[kms: forward port to 6.6 from 6.1. No code changes made.]
Signed-off-by: Kelsey Steele <kelseysteele@microsoft.com>
---
drivers/hv/dxgkrnl/dxgadapter.c | 4 ++--
drivers/hv/dxgkrnl/dxgkrnl.h | 13 ++++++++++++-
drivers/hv/dxgkrnl/ioctl.c | 25 +++++++++++++++++--------
3 files changed, 31 insertions(+), 11 deletions(-)
diff --git a/drivers/hv/dxgkrnl/dxgadapter.c b/drivers/hv/dxgkrnl/dxgadapter.c
index b8ae8099847b..cf946e476411 100644
--- a/drivers/hv/dxgkrnl/dxgadapter.c
+++ b/drivers/hv/dxgkrnl/dxgadapter.c
@@ -559,8 +559,8 @@ void dxgsharedresource_destroy(struct kref *refcount)
vfree(resource->runtime_private_data);
if (resource->resource_private_data)
vfree(resource->resource_private_data);
- if (resource->alloc_private_data_sizes)
- vfree(resource->alloc_private_data_sizes);
+ if (resource->alloc_info)
+ vfree(resource->alloc_info);
if (resource->alloc_private_data)
vfree(resource->alloc_private_data);
kfree(resource);
diff --git a/drivers/hv/dxgkrnl/dxgkrnl.h b/drivers/hv/dxgkrnl/dxgkrnl.h
index a4d0c504668b..d816a875d5ab 100644
--- a/drivers/hv/dxgkrnl/dxgkrnl.h
+++ b/drivers/hv/dxgkrnl/dxgkrnl.h
@@ -613,6 +613,17 @@ struct dxghwqueue *dxghwqueue_create(struct dxgcontext *ctx);
void dxghwqueue_destroy(struct dxgprocess *pr, struct dxghwqueue *hq);
void dxghwqueue_release(struct kref *refcount);
+/*
+ * When a shared resource is created this structure provides information
+ * about every allocation in the resource. It is used when someone opens the
+ * resource and locks its allocation.
+ */
+struct dxgsharedallocdata {
+ u32 private_data_size; /* Size of private data */
+ u32 num_pages; /* Allocation size in pages */
+ bool cached; /* True is the alloc memory is cached */
+};
+
/*
* A shared resource object is created to track the list of dxgresource objects,
* which are opened for the same underlying shared resource.
@@ -658,7 +669,7 @@ struct dxgsharedresource {
};
long flags;
};
- u32 *alloc_private_data_sizes;
+ struct dxgsharedallocdata *alloc_info;
u8 *alloc_private_data;
u8 *runtime_private_data;
u8 *resource_private_data;
diff --git a/drivers/hv/dxgkrnl/ioctl.c b/drivers/hv/dxgkrnl/ioctl.c
index d91af2e176e9..f8f116a7f87f 100644
--- a/drivers/hv/dxgkrnl/ioctl.c
+++ b/drivers/hv/dxgkrnl/ioctl.c
@@ -369,6 +369,7 @@ static int dxgsharedresource_seal(struct dxgsharedresource *shared_resource)
u32 data_size;
struct dxgresource *resource;
struct dxgallocation *alloc;
+ struct dxgsharedallocdata *alloc_info;
DXG_TRACE("Sealing resource: %p", shared_resource);
@@ -409,9 +410,10 @@ static int dxgsharedresource_seal(struct dxgsharedresource *shared_resource)
ret = -EINVAL;
goto cleanup1;
}
- shared_resource->alloc_private_data_sizes =
- vzalloc(sizeof(u32)*shared_resource->allocation_count);
- if (shared_resource->alloc_private_data_sizes == NULL) {
+ shared_resource->alloc_info =
+ vzalloc(sizeof(struct dxgsharedallocdata) *
+ shared_resource->allocation_count);
+ if (shared_resource->alloc_info == NULL) {
ret = -EINVAL;
goto cleanup1;
}
@@ -429,8 +431,10 @@ static int dxgsharedresource_seal(struct dxgsharedresource *shared_resource)
ret = -EINVAL;
goto cleanup1;
}
- shared_resource->alloc_private_data_sizes[i] =
- alloc_data_size;
+ alloc_info = &shared_resource->alloc_info[i];
+ alloc_info->private_data_size = alloc_data_size;
+ alloc_info->num_pages = alloc->num_pages;
+ alloc_info->cached = alloc->cached;
memcpy(private_data,
alloc->priv_drv_data->data,
alloc_data_size);
@@ -5031,6 +5035,7 @@ assign_resource_handles(struct dxgprocess *process,
u8 *cur_priv_data;
u32 total_priv_data_size = 0;
struct d3dddi_openallocationinfo2 open_alloc_info = { };
+ struct dxgsharedallocdata *alloc_info;
hmgrtable_lock(&process->handle_table, DXGLOCK_EXCL);
ret = hmgrtable_assign_handle(&process->handle_table, resource,
@@ -5050,11 +5055,15 @@ assign_resource_handles(struct dxgprocess *process,
allocs[i]->alloc_handle = handles[i];
allocs[i]->handle_valid = 1;
open_alloc_info.allocation = handles[i];
- if (shared_resource->alloc_private_data_sizes)
+ if (shared_resource->alloc_info) {
+ alloc_info = &shared_resource->alloc_info[i];
open_alloc_info.priv_drv_data_size =
- shared_resource->alloc_private_data_sizes[i];
- else
+ alloc_info->private_data_size;
+ allocs[i]->num_pages = alloc_info->num_pages;
+ allocs[i]->cached = alloc_info->cached;
+ } else {
open_alloc_info.priv_drv_data_size = 0;
+ }
total_priv_data_size += open_alloc_info.priv_drv_data_size;
open_alloc_info.priv_drv_data = cur_priv_data;
^ permalink raw reply related
* [PATCH 47/55] drivers: hv: dxgkrnl: Retry sending a VM bus packet when there is no place in the ring buffer
From: Eric Curtin @ 2026-03-19 20:25 UTC (permalink / raw)
To: linux-hyperv; +Cc: linux-kernel, iourit, wei.liu, decui, haiyangz
In-Reply-To: <20260319202509.63802-1-eric.curtin@docker.com>
From: Iouri Tarassov <iourit@linux.microsoft.com>
When D3DKMT requests are sent too quickly, the VM bus ring buffer could be
full when a message is submitted. The change adds sleep and re-try count
to handle this condition.
Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
[kms: forward port to 6.6 from 6.1. No code changes made.]
Signed-off-by: Kelsey Steele <kelseysteele@microsoft.com>
---
drivers/hv/dxgkrnl/dxgvmbus.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/drivers/hv/dxgkrnl/dxgvmbus.c b/drivers/hv/dxgkrnl/dxgvmbus.c
index 67f55f4bf41d..467e7707c8c7 100644
--- a/drivers/hv/dxgkrnl/dxgvmbus.c
+++ b/drivers/hv/dxgkrnl/dxgvmbus.c
@@ -420,6 +420,7 @@ int dxgvmb_send_sync_msg(struct dxgvmbuschannel *channel,
struct dxgvmbuspacket *packet = NULL;
struct dxgkvmb_command_vm_to_host *cmd1;
struct dxgkvmb_command_vgpu_to_host *cmd2;
+ int try_count = 0;
if (cmd_size > DXG_MAX_VM_BUS_PACKET_SIZE ||
result_size > DXG_MAX_VM_BUS_PACKET_SIZE) {
@@ -453,9 +454,19 @@ int dxgvmb_send_sync_msg(struct dxgvmbuschannel *channel,
list_add_tail(&packet->packet_list_entry, &channel->packet_list_head);
spin_unlock_irq(&channel->packet_list_mutex);
- ret = vmbus_sendpacket(channel->channel, command, cmd_size,
- packet->request_id, VM_PKT_DATA_INBAND,
- VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+ do {
+ ret = vmbus_sendpacket(channel->channel, command, cmd_size,
+ packet->request_id, VM_PKT_DATA_INBAND,
+ VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+ /*
+ * -EAGAIN is returned when the VM bus ring buffer if full.
+ * Wait 2ms to allow the host to process messages and try again.
+ */
+ if (ret == -EAGAIN) {
+ usleep_range(1000, 2000);
+ try_count++;
+ }
+ } while (ret == -EAGAIN && try_count < 50);
if (ret) {
DXG_ERR("vmbus_sendpacket failed: %x", ret);
spin_lock_irq(&channel->packet_list_mutex);
^ permalink raw reply related
* [PATCH 46/55] drivers: hv: dxgkrnl: Fixed the implementation of D3DKMTQueryClockCalibration
From: Eric Curtin @ 2026-03-19 20:25 UTC (permalink / raw)
To: linux-hyperv; +Cc: linux-kernel, iourit, wei.liu, decui, haiyangz
In-Reply-To: <20260319202509.63802-1-eric.curtin@docker.com>
From: Iouri Tarassov <iourit@linux.microsoft.com>
The result of a VM bus call was not copied to the user output structure.
Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
[kms: forward port to 6.6 from 6.1. No code changes made.]
Signed-off-by: Kelsey Steele <kelseysteele@microsoft.com>
---
drivers/hv/dxgkrnl/dxgvmbus.c | 18 ++++++++++--------
drivers/hv/dxgkrnl/ioctl.c | 5 -----
2 files changed, 10 insertions(+), 13 deletions(-)
diff --git a/drivers/hv/dxgkrnl/dxgvmbus.c b/drivers/hv/dxgkrnl/dxgvmbus.c
index 215e2f6648e2..67f55f4bf41d 100644
--- a/drivers/hv/dxgkrnl/dxgvmbus.c
+++ b/drivers/hv/dxgkrnl/dxgvmbus.c
@@ -1966,14 +1966,16 @@ int dxgvmb_send_query_clock_calibration(struct dxgprocess *process,
*__user inargs)
{
struct dxgkvmb_command_queryclockcalibration *command;
- struct dxgkvmb_command_queryclockcalibration_return result;
+ struct dxgkvmb_command_queryclockcalibration_return *result;
int ret;
- struct dxgvmbusmsg msg = {.hdr = NULL};
+ struct dxgvmbusmsgres msg = {.hdr = NULL};
- ret = init_message(&msg, adapter, process, sizeof(*command));
+ ret = init_message_res(&msg, adapter, sizeof(*command),
+ sizeof(*result));
if (ret)
goto cleanup;
command = (void *)msg.msg;
+ result = msg.res;
command_vgpu_to_host_init2(&command->hdr,
DXGK_VMBCOMMAND_QUERYCLOCKCALIBRATION,
@@ -1981,20 +1983,20 @@ int dxgvmb_send_query_clock_calibration(struct dxgprocess *process,
command->args = *args;
ret = dxgvmb_send_sync_msg(msg.channel, msg.hdr, msg.size,
- &result, sizeof(result));
+ result, sizeof(*result));
if (ret < 0)
goto cleanup;
- ret = copy_to_user(&inargs->clock_data, &result.clock_data,
- sizeof(result.clock_data));
+ ret = copy_to_user(&inargs->clock_data, &result->clock_data,
+ sizeof(result->clock_data));
if (ret) {
DXG_ERR("failed to copy clock data");
ret = -EFAULT;
goto cleanup;
}
- ret = ntstatus2int(result.status);
+ ret = ntstatus2int(result->status);
cleanup:
- free_message(&msg);
+ free_message((struct dxgvmbusmsg *)&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
diff --git a/drivers/hv/dxgkrnl/ioctl.c b/drivers/hv/dxgkrnl/ioctl.c
index 5ac6dd1f09b9..d91af2e176e9 100644
--- a/drivers/hv/dxgkrnl/ioctl.c
+++ b/drivers/hv/dxgkrnl/ioctl.c
@@ -4303,11 +4303,6 @@ dxgkio_query_clock_calibration(struct dxgprocess *process, void *__user inargs)
&args, inargs);
if (ret < 0)
goto cleanup;
- ret = copy_to_user(inargs, &args, sizeof(args));
- if (ret) {
- DXG_ERR("failed to copy output args");
- ret = -EFAULT;
- }
cleanup:
^ permalink raw reply related
* [PATCH 45/55] drivers: hv: dxgkrnl: Fixed coding style issues
From: Eric Curtin @ 2026-03-19 20:24 UTC (permalink / raw)
To: linux-hyperv; +Cc: linux-kernel, iourit, wei.liu, decui, haiyangz
In-Reply-To: <20260319202509.63802-1-eric.curtin@docker.com>
From: Iouri Tarassov <iourit@linux.microsoft.com>
Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
[kms: forward port to 6.6 from 6.1. No code changes made.]
Signed-off-by: Kelsey Steele <kelseysteele@microsoft.com>
---
drivers/hv/dxgkrnl/dxgadapter.c | 12 ++++--------
drivers/hv/dxgkrnl/dxgkrnl.h | 6 +++---
drivers/hv/dxgkrnl/dxgvmbus.c | 2 +-
drivers/hv/dxgkrnl/ioctl.c | 20 +++++++-------------
4 files changed, 15 insertions(+), 25 deletions(-)
diff --git a/drivers/hv/dxgkrnl/dxgadapter.c b/drivers/hv/dxgkrnl/dxgadapter.c
index bcd19b7267d1..b8ae8099847b 100644
--- a/drivers/hv/dxgkrnl/dxgadapter.c
+++ b/drivers/hv/dxgkrnl/dxgadapter.c
@@ -1017,8 +1017,7 @@ struct dxgprocess_adapter *dxgprocess_adapter_create(struct dxgprocess *process,
}
return adapter_info;
cleanup:
- if (adapter_info)
- kfree(adapter_info);
+ kfree(adapter_info);
return NULL;
}
@@ -1225,10 +1224,8 @@ struct dxgsyncobject *dxgsyncobject_create(struct dxgprocess *process,
DXG_TRACE("Syncobj created: %p", syncobj);
return syncobj;
cleanup:
- if (syncobj->host_event)
- kfree(syncobj->host_event);
- if (syncobj)
- kfree(syncobj);
+ kfree(syncobj->host_event);
+ kfree(syncobj);
return NULL;
}
@@ -1308,8 +1305,7 @@ void dxgsyncobject_release(struct kref *refcount)
kref_put(&syncobj->shared_owner->ssyncobj_kref,
dxgsharedsyncobj_release);
}
- if (syncobj->host_event)
- kfree(syncobj->host_event);
+ kfree(syncobj->host_event);
kfree(syncobj);
}
diff --git a/drivers/hv/dxgkrnl/dxgkrnl.h b/drivers/hv/dxgkrnl/dxgkrnl.h
index 9599ec8e0f1d..a4d0c504668b 100644
--- a/drivers/hv/dxgkrnl/dxgkrnl.h
+++ b/drivers/hv/dxgkrnl/dxgkrnl.h
@@ -47,10 +47,10 @@ struct dxghwqueue;
* Driver private data.
* A single /dev/dxg device is created per virtual machine.
*/
-struct dxgdriver{
+struct dxgdriver {
struct dxgglobal *dxgglobal;
- struct device *dxgdev;
- struct pci_driver pci_drv;
+ struct device *dxgdev;
+ struct pci_driver pci_drv;
struct hv_driver vmbus_drv;
};
extern struct dxgdriver dxgdrv;
diff --git a/drivers/hv/dxgkrnl/dxgvmbus.c b/drivers/hv/dxgkrnl/dxgvmbus.c
index de28c6162a70..215e2f6648e2 100644
--- a/drivers/hv/dxgkrnl/dxgvmbus.c
+++ b/drivers/hv/dxgkrnl/dxgvmbus.c
@@ -246,7 +246,7 @@ int dxgvmbuschannel_init(struct dxgvmbuschannel *ch, struct hv_device *hdev)
goto cleanup;
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,15,0)
+#if KERNEL_VERSION(5, 15, 0) <= LINUX_VERSION_CODE
hdev->channel->max_pkt_size = DXG_MAX_VM_BUS_PACKET_SIZE;
#endif
ret = vmbus_open(hdev->channel, RING_BUFSIZE, RING_BUFSIZE,
diff --git a/drivers/hv/dxgkrnl/ioctl.c b/drivers/hv/dxgkrnl/ioctl.c
index f8ca79d098f3..5ac6dd1f09b9 100644
--- a/drivers/hv/dxgkrnl/ioctl.c
+++ b/drivers/hv/dxgkrnl/ioctl.c
@@ -3162,8 +3162,7 @@ dxgkio_signal_sync_object(struct dxgprocess *process, void *__user inargs)
}
if (event)
eventfd_ctx_put(event);
- if (host_event)
- kfree(host_event);
+ kfree(host_event);
}
if (adapter)
dxgadapter_release_lock_shared(adapter);
@@ -3398,8 +3397,7 @@ dxgkio_signal_sync_object_gpu2(struct dxgprocess *process, void *__user inargs)
}
if (event)
eventfd_ctx_put(event);
- if (host_event)
- kfree(host_event);
+ kfree(host_event);
}
if (adapter)
dxgadapter_release_lock_shared(adapter);
@@ -3577,8 +3575,7 @@ dxgkio_wait_sync_object_cpu(struct dxgprocess *process, void *__user inargs)
}
if (event)
eventfd_ctx_put(event);
- if (async_host_event)
- kfree(async_host_event);
+ kfree(async_host_event);
}
DXG_TRACE_IOCTL_END(ret);
@@ -4438,7 +4435,7 @@ build_test_command_buffer(struct dxgprocess *process,
if (cmd.dma_buffer_size < sizeof(u32) ||
cmd.dma_buffer_size > D3DDDI_MAXTESTBUFFERSIZE ||
cmd.dma_buffer_priv_data_size >
- D3DDDI_MAXTESTBUFFERPRIVATEDRIVERDATASIZE) {
+ D3DDDI_MAXTESTBUFFERPRIVATEDRIVERDATASIZE) {
DXG_ERR("Invalid DMA buffer or private data size");
return -EINVAL;
}
@@ -4511,8 +4508,7 @@ driver_known_escape(struct dxgprocess *process,
enum d3dkmt_escapetype escape_type;
int ret = 0;
- if (args->priv_drv_data_size < sizeof(enum d3dddi_knownescapetype))
- {
+ if (args->priv_drv_data_size < sizeof(enum d3dddi_knownescapetype)) {
DXG_ERR("Invalid private data size");
return -EINVAL;
}
@@ -5631,10 +5627,8 @@ void dxgk_validate_ioctls(void)
{
int i;
- for (i=0; i < ARRAY_SIZE(ioctls); i++)
- {
- if (ioctls[i].ioctl && _IOC_NR(ioctls[i].ioctl) != i)
- {
+ for (i = 0; i < ARRAY_SIZE(ioctls); i++) {
+ if (ioctls[i].ioctl && _IOC_NR(ioctls[i].ioctl) != i) {
DXG_ERR("Invalid ioctl");
DXGKRNL_ASSERT(0);
}
^ permalink raw reply related
* [PATCH 44/55] drivers: hv: dxgkrnl: Implement known escapes
From: Eric Curtin @ 2026-03-19 20:24 UTC (permalink / raw)
To: linux-hyperv; +Cc: linux-kernel, iourit, wei.liu, decui, haiyangz
In-Reply-To: <20260319202509.63802-1-eric.curtin@docker.com>
From: Iouri Tarassov <iourit@linux.microsoft.com>
Implement an escape to build test command buffer.
Implement other known escapes.
Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
[kms: forward port to 6.6 from 6.1. No code changes made.]
Signed-off-by: Kelsey Steele <kelseysteele@microsoft.com>
---
drivers/hv/dxgkrnl/dxgkrnl.h | 3 +-
drivers/hv/dxgkrnl/dxgvmbus.c | 40 +++++---
drivers/hv/dxgkrnl/ioctl.c | 170 +++++++++++++++++++++++++++++-----
include/uapi/misc/d3dkmthk.h | 31 +++++++
4 files changed, 205 insertions(+), 39 deletions(-)
diff --git a/drivers/hv/dxgkrnl/dxgkrnl.h b/drivers/hv/dxgkrnl/dxgkrnl.h
index ebf81cffa289..9599ec8e0f1d 100644
--- a/drivers/hv/dxgkrnl/dxgkrnl.h
+++ b/drivers/hv/dxgkrnl/dxgkrnl.h
@@ -953,7 +953,8 @@ int dxgvmb_send_query_alloc_residency(struct dxgprocess *process,
*args);
int dxgvmb_send_escape(struct dxgprocess *process,
struct dxgadapter *adapter,
- struct d3dkmt_escape *args);
+ struct d3dkmt_escape *args,
+ bool user_mode);
int dxgvmb_send_query_vidmem_info(struct dxgprocess *process,
struct dxgadapter *adapter,
struct d3dkmt_queryvideomemoryinfo *args,
diff --git a/drivers/hv/dxgkrnl/dxgvmbus.c b/drivers/hv/dxgkrnl/dxgvmbus.c
index 2436e1a7bc73..de28c6162a70 100644
--- a/drivers/hv/dxgkrnl/dxgvmbus.c
+++ b/drivers/hv/dxgkrnl/dxgvmbus.c
@@ -2174,7 +2174,8 @@ int dxgvmb_send_query_alloc_residency(struct dxgprocess *process,
int dxgvmb_send_escape(struct dxgprocess *process,
struct dxgadapter *adapter,
- struct d3dkmt_escape *args)
+ struct d3dkmt_escape *args,
+ bool user_mode)
{
int ret;
struct dxgkvmb_command_escape *command = NULL;
@@ -2203,13 +2204,18 @@ int dxgvmb_send_escape(struct dxgprocess *process,
command->priv_drv_data_size = args->priv_drv_data_size;
command->context = args->context;
if (args->priv_drv_data_size) {
- ret = copy_from_user(command->priv_drv_data,
- args->priv_drv_data,
- args->priv_drv_data_size);
- if (ret) {
- DXG_ERR("failed to copy priv data");
- ret = -EFAULT;
- goto cleanup;
+ if (user_mode) {
+ ret = copy_from_user(command->priv_drv_data,
+ args->priv_drv_data,
+ args->priv_drv_data_size);
+ if (ret) {
+ DXG_ERR("failed to copy priv data");
+ ret = -EFAULT;
+ goto cleanup;
+ }
+ } else {
+ memcpy(command->priv_drv_data, args->priv_drv_data,
+ args->priv_drv_data_size);
}
}
@@ -2220,12 +2226,18 @@ int dxgvmb_send_escape(struct dxgprocess *process,
goto cleanup;
if (args->priv_drv_data_size) {
- ret = copy_to_user(args->priv_drv_data,
- command->priv_drv_data,
- args->priv_drv_data_size);
- if (ret) {
- DXG_ERR("failed to copy priv data");
- ret = -EINVAL;
+ if (user_mode) {
+ ret = copy_to_user(args->priv_drv_data,
+ command->priv_drv_data,
+ args->priv_drv_data_size);
+ if (ret) {
+ DXG_ERR("failed to copy priv data");
+ ret = -EINVAL;
+ }
+ } else {
+ memcpy(args->priv_drv_data,
+ command->priv_drv_data,
+ args->priv_drv_data_size);
}
}
diff --git a/drivers/hv/dxgkrnl/ioctl.c b/drivers/hv/dxgkrnl/ioctl.c
index 5ff4b27af19d..f8ca79d098f3 100644
--- a/drivers/hv/dxgkrnl/ioctl.c
+++ b/drivers/hv/dxgkrnl/ioctl.c
@@ -4257,10 +4257,8 @@ dxgkio_change_vidmem_reservation(struct dxgprocess *process, void *__user inargs
}
ret = dxgadapter_acquire_lock_shared(adapter);
- if (ret < 0) {
- adapter = NULL;
+ if (ret < 0)
goto cleanup;
- }
adapter_locked = true;
args.adapter.v = 0;
ret = dxgvmb_send_change_vidmem_reservation(process, adapter,
@@ -4299,10 +4297,8 @@ dxgkio_query_clock_calibration(struct dxgprocess *process, void *__user inargs)
}
ret = dxgadapter_acquire_lock_shared(adapter);
- if (ret < 0) {
- adapter = NULL;
+ if (ret < 0)
goto cleanup;
- }
adapter_locked = true;
args.adapter = adapter->host_handle;
@@ -4349,10 +4345,8 @@ dxgkio_flush_heap_transitions(struct dxgprocess *process, void *__user inargs)
}
ret = dxgadapter_acquire_lock_shared(adapter);
- if (ret < 0) {
- adapter = NULL;
+ if (ret < 0)
goto cleanup;
- }
adapter_locked = true;
args.adapter = adapter->host_handle;
@@ -4417,6 +4411,134 @@ dxgkio_invalidate_cache(struct dxgprocess *process, void *__user inargs)
return ret;
}
+static int
+build_test_command_buffer(struct dxgprocess *process,
+ struct dxgadapter *adapter,
+ struct d3dkmt_escape *args)
+{
+ int ret;
+ struct d3dddi_buildtestcommandbuffer cmd;
+ struct d3dkmt_escape newargs = *args;
+ u32 buf_size;
+ struct d3dddi_buildtestcommandbuffer *buf = NULL;
+ struct d3dddi_buildtestcommandbuffer *__user ucmd;
+
+ ucmd = args->priv_drv_data;
+ if (args->priv_drv_data_size <
+ sizeof(struct d3dddi_buildtestcommandbuffer)) {
+ DXG_ERR("Invalid private data size");
+ return -EINVAL;
+ }
+ ret = copy_from_user(&cmd, ucmd, sizeof(cmd));
+ if (ret) {
+ DXG_ERR("Failed to copy private data");
+ return -EFAULT;
+ }
+
+ if (cmd.dma_buffer_size < sizeof(u32) ||
+ cmd.dma_buffer_size > D3DDDI_MAXTESTBUFFERSIZE ||
+ cmd.dma_buffer_priv_data_size >
+ D3DDDI_MAXTESTBUFFERPRIVATEDRIVERDATASIZE) {
+ DXG_ERR("Invalid DMA buffer or private data size");
+ return -EINVAL;
+ }
+ /* Allocate a new buffer for the escape call */
+ buf_size = sizeof(struct d3dddi_buildtestcommandbuffer) +
+ cmd.dma_buffer_size +
+ cmd.dma_buffer_priv_data_size;
+ buf = vzalloc(buf_size);
+ if (buf == NULL) {
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+ *buf = cmd;
+ buf->dma_buffer = NULL;
+ buf->dma_buffer_priv_data = NULL;
+
+ /* Replace private data in the escape arguments and call the host */
+ newargs.priv_drv_data = buf;
+ newargs.priv_drv_data_size = buf_size;
+ ret = dxgvmb_send_escape(process, adapter, &newargs, false);
+ if (ret) {
+ DXG_ERR("Host failed escape");
+ goto cleanup;
+ }
+
+ ret = copy_to_user(&ucmd->dma_buffer_size, &buf->dma_buffer_size,
+ sizeof(u32));
+ if (ret) {
+ DXG_ERR("Failed to dma size to user");
+ ret = -EFAULT;
+ goto cleanup;
+ }
+ ret = copy_to_user(&ucmd->dma_buffer_priv_data_size,
+ &buf->dma_buffer_priv_data_size,
+ sizeof(u32));
+ if (ret) {
+ DXG_ERR("Failed to dma private data size to user");
+ ret = -EFAULT;
+ goto cleanup;
+ }
+ ret = copy_to_user(cmd.dma_buffer, (char *)buf + sizeof(*buf),
+ buf->dma_buffer_size);
+ if (ret) {
+ DXG_ERR("Failed to copy dma buffer to user");
+ ret = -EFAULT;
+ goto cleanup;
+ }
+ if (buf->dma_buffer_priv_data_size) {
+ ret = copy_to_user(cmd.dma_buffer_priv_data,
+ (char *)buf + sizeof(*buf) + cmd.dma_buffer_size,
+ buf->dma_buffer_priv_data_size);
+ if (ret) {
+ DXG_ERR("Failed to copy private data to user");
+ ret = -EFAULT;
+ goto cleanup;
+ }
+ }
+
+cleanup:
+ if (buf)
+ vfree(buf);
+ return ret;
+}
+
+static int
+driver_known_escape(struct dxgprocess *process,
+ struct dxgadapter *adapter,
+ struct d3dkmt_escape *args)
+{
+ enum d3dkmt_escapetype escape_type;
+ int ret = 0;
+
+ if (args->priv_drv_data_size < sizeof(enum d3dddi_knownescapetype))
+ {
+ DXG_ERR("Invalid private data size");
+ return -EINVAL;
+ }
+ ret = copy_from_user(&escape_type, args->priv_drv_data,
+ sizeof(escape_type));
+ if (ret) {
+ DXG_ERR("Failed to read escape type");
+ return -EFAULT;
+ }
+ switch (escape_type) {
+ case _D3DDDI_DRIVERESCAPETYPE_TRANSLATEALLOCATIONHANDLE:
+ case _D3DDDI_DRIVERESCAPETYPE_TRANSLATERESOURCEHANDLE:
+ /*
+ * The host and VM handles are the same
+ */
+ break;
+ case _D3DDDI_DRIVERESCAPETYPE_BUILDTESTCOMMANDBUFFER:
+ ret = build_test_command_buffer(process, adapter, args);
+ break;
+ default:
+ ret = dxgvmb_send_escape(process, adapter, args, true);
+ break;
+ }
+ return ret;
+}
+
static int
dxgkio_escape(struct dxgprocess *process, void *__user inargs)
{
@@ -4438,14 +4560,17 @@ dxgkio_escape(struct dxgprocess *process, void *__user inargs)
}
ret = dxgadapter_acquire_lock_shared(adapter);
- if (ret < 0) {
- adapter = NULL;
+ if (ret < 0)
goto cleanup;
- }
adapter_locked = true;
args.adapter = adapter->host_handle;
- ret = dxgvmb_send_escape(process, adapter, &args);
+
+ if (args.type == _D3DKMT_ESCAPE_DRIVERPRIVATE &&
+ args.flags.driver_known_escape)
+ ret = driver_known_escape(process, adapter, &args);
+ else
+ ret = dxgvmb_send_escape(process, adapter, &args, true);
cleanup:
@@ -4485,10 +4610,8 @@ dxgkio_query_vidmem_info(struct dxgprocess *process, void *__user inargs)
}
ret = dxgadapter_acquire_lock_shared(adapter);
- if (ret < 0) {
- adapter = NULL;
+ if (ret < 0)
goto cleanup;
- }
adapter_locked = true;
args.adapter = adapter->host_handle;
@@ -5323,9 +5446,9 @@ dxgkio_is_feature_enabled(struct dxgprocess *process, void *__user inargs)
{
struct d3dkmt_isfeatureenabled args;
struct dxgadapter *adapter = NULL;
- struct dxgglobal *dxgglobal = dxggbl();
struct d3dkmt_isfeatureenabled *__user uargs = inargs;
int ret;
+ bool adapter_locked = false;
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
@@ -5340,11 +5463,10 @@ dxgkio_is_feature_enabled(struct dxgprocess *process, void *__user inargs)
goto cleanup;
}
- if (adapter) {
- ret = dxgadapter_acquire_lock_shared(adapter);
- if (ret < 0)
- goto cleanup;
- }
+ ret = dxgadapter_acquire_lock_shared(adapter);
+ if (ret < 0)
+ goto cleanup;
+ adapter_locked = true;
ret = dxgvmb_send_is_feature_enabled(adapter, &args);
if (ret)
@@ -5354,10 +5476,10 @@ dxgkio_is_feature_enabled(struct dxgprocess *process, void *__user inargs)
cleanup:
- if (adapter) {
+ if (adapter_locked)
dxgadapter_release_lock_shared(adapter);
+ if (adapter)
kref_put(&adapter->adapter_kref, dxgadapter_release);
- }
DXG_TRACE_IOCTL_END(ret);
return ret;
diff --git a/include/uapi/misc/d3dkmthk.h b/include/uapi/misc/d3dkmthk.h
index 5b345ddaf66e..db40e8ff40b0 100644
--- a/include/uapi/misc/d3dkmthk.h
+++ b/include/uapi/misc/d3dkmthk.h
@@ -237,6 +237,37 @@ struct d3dddi_destroypagingqueue {
struct d3dkmthandle paging_queue;
};
+enum d3dddi_knownescapetype {
+ _D3DDDI_DRIVERESCAPETYPE_TRANSLATEALLOCATIONHANDLE = 0,
+ _D3DDDI_DRIVERESCAPETYPE_TRANSLATERESOURCEHANDLE = 1,
+ _D3DDDI_DRIVERESCAPETYPE_CPUEVENTUSAGE = 2,
+ _D3DDDI_DRIVERESCAPETYPE_BUILDTESTCOMMANDBUFFER = 3,
+};
+
+struct d3dddi_translate_allocation_handle {
+ enum d3dddi_knownescapetype escape_type;
+ struct d3dkmthandle allocation;
+};
+
+struct d3dddi_testcommand {
+ char buffer[72];
+};
+
+#define D3DDDI_MAXTESTBUFFERSIZE 4096
+#define D3DDDI_MAXTESTBUFFERPRIVATEDRIVERDATASIZE 1024
+
+struct d3dddi_buildtestcommandbuffer {
+ enum d3dddi_knownescapetype escape_type;
+ struct d3dkmthandle device;
+ struct d3dkmthandle context;
+ __u32 flags;
+ struct d3dddi_testcommand command;
+ void *dma_buffer;
+ void *dma_buffer_priv_data;
+ __u32 dma_buffer_size;
+ __u32 dma_buffer_priv_data_size;
+};
+
enum d3dkmt_escapetype {
_D3DKMT_ESCAPE_DRIVERPRIVATE = 0,
_D3DKMT_ESCAPE_VIDMM = 1,
^ permalink raw reply related
* [PATCH 43/55] drivers: hv: dxgkrnl: Implement D3DDKMTIsFeatureEnabled API
From: Eric Curtin @ 2026-03-19 20:24 UTC (permalink / raw)
To: linux-hyperv; +Cc: linux-kernel, iourit, wei.liu, decui, haiyangz
In-Reply-To: <20260319202509.63802-1-eric.curtin@docker.com>
From: Iouri Tarassov <iourit@linux.microsoft.com>
D3DKMTIsFeatureEnabled is used to query if a particular feature is
supported by the given adapter.
Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
[kms: forward port to 6.6 from 6.1. No code changes made.]
Signed-off-by: Kelsey Steele <kelseysteele@microsoft.com>
---
drivers/hv/dxgkrnl/dxgkrnl.h | 2 ++
drivers/hv/dxgkrnl/dxgvmbus.c | 58 ++++++++++++++++++++++++++++++++---
drivers/hv/dxgkrnl/dxgvmbus.h | 31 +++++++++++++++++++
drivers/hv/dxgkrnl/ioctl.c | 46 +++++++++++++++++++++++++++
include/uapi/misc/d3dkmthk.h | 31 ++++++++++++++++++-
5 files changed, 163 insertions(+), 5 deletions(-)
diff --git a/drivers/hv/dxgkrnl/dxgkrnl.h b/drivers/hv/dxgkrnl/dxgkrnl.h
index 90bcd5377744..ebf81cffa289 100644
--- a/drivers/hv/dxgkrnl/dxgkrnl.h
+++ b/drivers/hv/dxgkrnl/dxgkrnl.h
@@ -994,6 +994,8 @@ int dxgvmb_send_share_object_with_host(struct dxgprocess *process,
int dxgvmb_send_invalidate_cache(struct dxgprocess *process,
struct dxgadapter *adapter,
struct d3dkmt_invalidatecache *args);
+int dxgvmb_send_is_feature_enabled(struct dxgadapter *adapter,
+ struct d3dkmt_isfeatureenabled *args);
void signal_host_cpu_event(struct dxghostevent *eventhdr);
int ntstatus2int(struct ntstatus status);
diff --git a/drivers/hv/dxgkrnl/dxgvmbus.c b/drivers/hv/dxgkrnl/dxgvmbus.c
index 916ed9071656..2436e1a7bc73 100644
--- a/drivers/hv/dxgkrnl/dxgvmbus.c
+++ b/drivers/hv/dxgkrnl/dxgvmbus.c
@@ -135,15 +135,16 @@ static int init_message_res(struct dxgvmbusmsgres *msg,
if (use_ext_header) {
msg->msg = (char *)&msg->hdr[1];
msg->hdr->command_offset = sizeof(msg->hdr[0]);
- msg->hdr->vgpu_luid = adapter->host_vgpu_luid;
+ if (adapter)
+ msg->hdr->vgpu_luid = adapter->host_vgpu_luid;
} else {
msg->msg = (char *)msg->hdr;
}
msg->res = (char *)msg->hdr + msg->size;
- if (dxgglobal->async_msg_enabled)
- msg->channel = &dxgglobal->channel;
- else
+ if (adapter && !dxgglobal->async_msg_enabled)
msg->channel = &adapter->channel;
+ else
+ msg->channel = &dxgglobal->channel;
return 0;
}
@@ -2049,6 +2050,55 @@ int dxgvmb_send_invalidate_cache(struct dxgprocess *process,
return ret;
}
+int dxgvmb_send_is_feature_enabled(struct dxgadapter *adapter,
+ struct d3dkmt_isfeatureenabled *args)
+{
+ int ret;
+ struct dxgkvmb_command_isfeatureenabled_return *result;
+ struct dxgvmbusmsgres msg = {.hdr = NULL};
+ int res_size = sizeof(*result);
+
+ if (adapter) {
+ struct dxgkvmb_command_isfeatureenabled *command;
+
+ ret = init_message_res(&msg, adapter, sizeof(*command),
+ res_size);
+ if (ret)
+ goto cleanup;
+ command = (void *)msg.msg;
+ command->feature_id = args->feature_id;
+ result = msg.res;
+ command_vgpu_to_host_init1(&command->hdr,
+ DXGK_VMBCOMMAND_ISFEATUREENABLED);
+ } else {
+ struct dxgkvmb_command_isfeatureenabled_gbl *command;
+
+ ret = init_message_res(&msg, adapter, sizeof(*command),
+ res_size);
+ if (ret)
+ goto cleanup;
+ command = (void *)msg.msg;
+ command->feature_id = args->feature_id;
+ result = msg.res;
+ command_vm_to_host_init1(&command->hdr,
+ DXGK_VMBCOMMAND_ISFEATUREENABLED_GLOBAL);
+ }
+ ret = dxgvmb_send_sync_msg(msg.channel, msg.hdr, msg.size,
+ result, res_size);
+ if (ret == 0) {
+ ret = ntstatus2int(result->status);
+ if (ret == 0)
+ args->result = result->result;
+ goto cleanup;
+ }
+
+cleanup:
+ free_message((struct dxgvmbusmsg *)&msg);
+ if (ret)
+ DXG_TRACE("err: %d", ret);
+ return ret;
+}
+
int dxgvmb_send_query_alloc_residency(struct dxgprocess *process,
struct dxgadapter *adapter,
struct d3dkmt_queryallocationresidency
diff --git a/drivers/hv/dxgkrnl/dxgvmbus.h b/drivers/hv/dxgkrnl/dxgvmbus.h
index 20c562b485de..a7e625b2f896 100644
--- a/drivers/hv/dxgkrnl/dxgvmbus.h
+++ b/drivers/hv/dxgkrnl/dxgvmbus.h
@@ -48,6 +48,7 @@ enum dxgkvmb_commandtype_global {
DXGK_VMBCOMMAND_SETIOSPACEREGION = 1010,
DXGK_VMBCOMMAND_COMPLETETRANSACTION = 1011,
DXGK_VMBCOMMAND_SHAREOBJECTWITHHOST = 1021,
+ DXGK_VMBCOMMAND_ISFEATUREENABLED_GLOBAL = 1022,
DXGK_VMBCOMMAND_INVALID_VM_TO_HOST
};
@@ -126,6 +127,7 @@ enum dxgkvmb_commandtype {
DXGK_VMBCOMMAND_LOGEVENT = 65,
DXGK_VMBCOMMAND_SETEXISTINGSYSMEMPAGES = 66,
DXGK_VMBCOMMAND_INVALIDATECACHE = 67,
+ DXGK_VMBCOMMAND_ISFEATUREENABLED = 68,
DXGK_VMBCOMMAND_INVALID
};
@@ -871,6 +873,35 @@ struct dxgkvmb_command_shareobjectwithhost_return {
u64 vail_nt_handle;
};
+struct dxgk_feature_desc {
+ u16 min_supported_version;
+ u16 max_supported_version;
+ struct {
+ u16 supported : 1;
+ u16 virtualization_mode : 3;
+ u16 global : 1;
+ u16 driver_feature : 1;
+ u16 internal : 1;
+ u16 reserved : 9;
+ };
+};
+
+struct dxgkvmb_command_isfeatureenabled {
+ struct dxgkvmb_command_vgpu_to_host hdr;
+ enum dxgk_feature_id feature_id;
+};
+
+struct dxgkvmb_command_isfeatureenabled_gbl {
+ struct dxgkvmb_command_vm_to_host hdr;
+ enum dxgk_feature_id feature_id;
+};
+
+struct dxgkvmb_command_isfeatureenabled_return {
+ struct ntstatus status;
+ struct dxgk_feature_desc descriptor;
+ struct dxgk_isfeatureenabled_result result;
+};
+
int
dxgvmb_send_sync_msg(struct dxgvmbuschannel *channel,
void *command, u32 command_size, void *result,
diff --git a/drivers/hv/dxgkrnl/ioctl.c b/drivers/hv/dxgkrnl/ioctl.c
index 24b84be2fb73..5ff4b27af19d 100644
--- a/drivers/hv/dxgkrnl/ioctl.c
+++ b/drivers/hv/dxgkrnl/ioctl.c
@@ -5318,6 +5318,51 @@ dxgkio_enum_processes(struct dxgprocess *process, void *__user inargs)
return ret;
}
+static int
+dxgkio_is_feature_enabled(struct dxgprocess *process, void *__user inargs)
+{
+ struct d3dkmt_isfeatureenabled args;
+ struct dxgadapter *adapter = NULL;
+ struct dxgglobal *dxgglobal = dxggbl();
+ struct d3dkmt_isfeatureenabled *__user uargs = inargs;
+ int ret;
+
+ ret = copy_from_user(&args, inargs, sizeof(args));
+ if (ret) {
+ DXG_ERR("failed to copy input args");
+ ret = -EFAULT;
+ goto cleanup;
+ }
+
+ adapter = dxgprocess_adapter_by_handle(process, args.adapter);
+ if (adapter == NULL) {
+ ret = -EINVAL;
+ goto cleanup;
+ }
+
+ if (adapter) {
+ ret = dxgadapter_acquire_lock_shared(adapter);
+ if (ret < 0)
+ goto cleanup;
+ }
+
+ ret = dxgvmb_send_is_feature_enabled(adapter, &args);
+ if (ret)
+ goto cleanup;
+
+ ret = copy_to_user(&uargs->result, &args.result, sizeof(args.result));
+
+cleanup:
+
+ if (adapter) {
+ dxgadapter_release_lock_shared(adapter);
+ kref_put(&adapter->adapter_kref, dxgadapter_release);
+ }
+
+ DXG_TRACE_IOCTL_END(ret);
+ return ret;
+}
+
static struct ioctl_desc ioctls[] = {
/* 0x00 */ {},
/* 0x01 */ {dxgkio_open_adapter_from_luid, LX_DXOPENADAPTERFROMLUID},
@@ -5406,6 +5451,7 @@ static struct ioctl_desc ioctls[] = {
/* 0x47 */ {dxgkio_open_syncobj_from_syncfile,
LX_DXOPENSYNCOBJECTFROMSYNCFILE},
/* 0x48 */ {dxgkio_enum_processes, LX_DXENUMPROCESSES},
+/* 0x49 */ {dxgkio_is_feature_enabled, LX_ISFEATUREENABLED},
};
/*
diff --git a/include/uapi/misc/d3dkmthk.h b/include/uapi/misc/d3dkmthk.h
index f9f817060fa9..5b345ddaf66e 100644
--- a/include/uapi/misc/d3dkmthk.h
+++ b/include/uapi/misc/d3dkmthk.h
@@ -1580,7 +1580,7 @@ struct d3dkmt_opensyncobjectfromsyncfile {
__u64 fence_value_gpu_va; /* out */
};
- struct d3dkmt_enumprocesses {
+struct d3dkmt_enumprocesses {
struct winluid adapter_luid;
#ifdef __KERNEL__
__u32 *buffer;
@@ -1590,6 +1590,33 @@ struct d3dkmt_opensyncobjectfromsyncfile {
__u64 buffer_count;
};
+enum dxgk_feature_id {
+ _DXGK_FEATURE_HWSCH = 0,
+ _DXGK_FEATURE_PAGE_BASED_MEMORY_MANAGER = 32,
+ _DXGK_FEATURE_KERNEL_MODE_TESTING = 33,
+ _DXGK_FEATURE_MAX
+};
+
+struct dxgk_isfeatureenabled_result {
+ __u16 version;
+ union {
+ struct {
+ __u16 enabled : 1;
+ __u16 known_feature : 1;
+ __u16 supported_by_driver : 1;
+ __u16 supported_on_config : 1;
+ __u16 reserved : 12;
+ };
+ __u16 value;
+ };
+};
+
+struct d3dkmt_isfeatureenabled {
+ struct d3dkmthandle adapter;
+ enum dxgk_feature_id feature_id;
+ struct dxgk_isfeatureenabled_result result;
+};
+
struct d3dkmt_invalidatecache {
struct d3dkmthandle device;
struct d3dkmthandle allocation;
@@ -1730,5 +1757,7 @@ struct d3dkmt_invalidatecache {
_IOWR(0x47, 0x47, struct d3dkmt_opensyncobjectfromsyncfile)
#define LX_DXENUMPROCESSES \
_IOWR(0x47, 0x48, struct d3dkmt_enumprocesses)
+#define LX_ISFEATUREENABLED \
+ _IOWR(0x47, 0x49, struct d3dkmt_isfeatureenabled)
#endif /* _D3DKMTHK_H */
^ permalink raw reply related
* [PATCH 42/55] drivers: hv: dxgkrnl: Implement the D3DKMTEnumProcesses API
From: Eric Curtin @ 2026-03-19 20:24 UTC (permalink / raw)
To: linux-hyperv; +Cc: linux-kernel, iourit, wei.liu, decui, haiyangz
In-Reply-To: <20260319202509.63802-1-eric.curtin@docker.com>
From: Iouri Tarassov <iourit@linux.microsoft.com>
D3DKMTEnumProcesses is used to enumerate PIDs for all processes,
which opened the /dev/dxg device.
Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
[kms: forward port to 6.6 from 6.1. No code changes made.]
Signed-off-by: Kelsey Steele <kelseysteele@microsoft.com>
---
drivers/hv/dxgkrnl/dxgkrnl.h | 1 +
drivers/hv/dxgkrnl/dxgprocess.c | 2 +
drivers/hv/dxgkrnl/ioctl.c | 81 +++++++++++++++++++++++++++++++++
include/uapi/misc/d3dkmthk.h | 12 +++++
4 files changed, 96 insertions(+)
diff --git a/drivers/hv/dxgkrnl/dxgkrnl.h b/drivers/hv/dxgkrnl/dxgkrnl.h
index 6af1e59b0a31..90bcd5377744 100644
--- a/drivers/hv/dxgkrnl/dxgkrnl.h
+++ b/drivers/hv/dxgkrnl/dxgkrnl.h
@@ -387,6 +387,7 @@ struct dxgprocess {
pid_t pid;
pid_t tgid;
pid_t vpid; /* pdi from the current namespace */
+ struct pid_namespace *nspid; /* namespace id */
/* how many time the process was opened */
struct kref process_kref;
/* protects the object memory */
diff --git a/drivers/hv/dxgkrnl/dxgprocess.c b/drivers/hv/dxgkrnl/dxgprocess.c
index 5a4c4cb0c2e8..9bfd53df1a54 100644
--- a/drivers/hv/dxgkrnl/dxgprocess.c
+++ b/drivers/hv/dxgkrnl/dxgprocess.c
@@ -13,6 +13,7 @@
#include "dxgkrnl.h"
#include "linux/sched.h"
+#include <linux/pid_namespace.h>
#undef dev_fmt
#define dev_fmt(fmt) "dxgk: " fmt
@@ -33,6 +34,7 @@ struct dxgprocess *dxgprocess_create(void)
process->pid = current->pid;
process->tgid = current->tgid;
process->vpid = task_pid_vnr(current);
+ process->nspid = task_active_pid_ns(current);
ret = dxgvmb_send_create_process(process);
if (ret < 0) {
DXG_TRACE("send_create_process failed");
diff --git a/drivers/hv/dxgkrnl/ioctl.c b/drivers/hv/dxgkrnl/ioctl.c
index 466bef6c14b3..24b84be2fb73 100644
--- a/drivers/hv/dxgkrnl/ioctl.c
+++ b/drivers/hv/dxgkrnl/ioctl.c
@@ -16,6 +16,7 @@
#include <linux/fs.h>
#include <linux/anon_inodes.h>
#include <linux/mman.h>
+#include <linux/pid_namespace.h>
#include "dxgkrnl.h"
#include "dxgvmbus.h"
@@ -5238,6 +5239,85 @@ dxgkio_share_object_with_host(struct dxgprocess *process, void *__user inargs)
return ret;
}
+static int
+dxgkio_enum_processes(struct dxgprocess *process, void *__user inargs)
+{
+ struct d3dkmt_enumprocesses args;
+ struct d3dkmt_enumprocesses *__user input = inargs;
+ struct dxgadapter *adapter = NULL;
+ struct dxgadapter *entry;
+ struct dxgglobal *dxgglobal = dxggbl();
+ struct dxgprocess_adapter *pentry;
+ int nump = 0; /* Current number of processes*/
+ struct ntstatus status;
+ int ret;
+
+ ret = copy_from_user(&args, inargs, sizeof(args));
+ if (ret) {
+ DXG_ERR("failed to copy input args");
+ ret = -EFAULT;
+ goto cleanup;
+ }
+
+ if (args.buffer_count == 0) {
+ DXG_ERR("Invalid buffer count");
+ ret = -EINVAL;
+ goto cleanup;
+ }
+
+ dxgglobal_acquire_adapter_list_lock(DXGLOCK_SHARED);
+ dxgglobal_acquire_process_adapter_lock();
+
+ list_for_each_entry(entry, &dxgglobal->adapter_list_head,
+ adapter_list_entry) {
+ if (*(u64 *) &entry->luid == *(u64 *) &args.adapter_luid) {
+ adapter = entry;
+ break;
+ }
+ }
+
+ if (adapter == NULL) {
+ DXG_ERR("Failed to find dxgadapter");
+ ret = -EINVAL;
+ goto cleanup_locks;
+ }
+
+ list_for_each_entry(pentry, &adapter->adapter_process_list_head,
+ adapter_process_list_entry) {
+ if (pentry->process->nspid != task_active_pid_ns(current))
+ continue;
+ if (nump == args.buffer_count) {
+ status.v = STATUS_BUFFER_TOO_SMALL;
+ ret = ntstatus2int(status);
+ goto cleanup_locks;
+ }
+ ret = copy_to_user(&args.buffer[nump], &pentry->process->vpid,
+ sizeof(u32));
+ if (ret) {
+ DXG_ERR("failed to copy data to user");
+ ret = -EFAULT;
+ goto cleanup_locks;
+ }
+ nump++;
+ }
+
+cleanup_locks:
+
+ dxgglobal_release_process_adapter_lock();
+ dxgglobal_release_adapter_list_lock(DXGLOCK_SHARED);
+
+ if (ret == 0) {
+ ret = copy_to_user(&input->buffer_count, &nump, sizeof(u32));
+ if (ret)
+ DXG_ERR("failed to copy buffer count to user");
+ }
+
+cleanup:
+
+ DXG_TRACE_IOCTL_END(ret);
+ return ret;
+}
+
static struct ioctl_desc ioctls[] = {
/* 0x00 */ {},
/* 0x01 */ {dxgkio_open_adapter_from_luid, LX_DXOPENADAPTERFROMLUID},
@@ -5325,6 +5405,7 @@ static struct ioctl_desc ioctls[] = {
/* 0x46 */ {dxgkio_wait_sync_file, LX_DXWAITSYNCFILE},
/* 0x47 */ {dxgkio_open_syncobj_from_syncfile,
LX_DXOPENSYNCOBJECTFROMSYNCFILE},
+/* 0x48 */ {dxgkio_enum_processes, LX_DXENUMPROCESSES},
};
/*
diff --git a/include/uapi/misc/d3dkmthk.h b/include/uapi/misc/d3dkmthk.h
index 84fa07a46d3c..f9f817060fa9 100644
--- a/include/uapi/misc/d3dkmthk.h
+++ b/include/uapi/misc/d3dkmthk.h
@@ -1580,6 +1580,16 @@ struct d3dkmt_opensyncobjectfromsyncfile {
__u64 fence_value_gpu_va; /* out */
};
+ struct d3dkmt_enumprocesses {
+ struct winluid adapter_luid;
+#ifdef __KERNEL__
+ __u32 *buffer;
+#else
+ __u64 buffer;
+#endif
+ __u64 buffer_count;
+};
+
struct d3dkmt_invalidatecache {
struct d3dkmthandle device;
struct d3dkmthandle allocation;
@@ -1718,5 +1728,7 @@ struct d3dkmt_invalidatecache {
_IOWR(0x47, 0x46, struct d3dkmt_waitsyncfile)
#define LX_DXOPENSYNCOBJECTFROMSYNCFILE \
_IOWR(0x47, 0x47, struct d3dkmt_opensyncobjectfromsyncfile)
+#define LX_DXENUMPROCESSES \
+ _IOWR(0x47, 0x48, struct d3dkmt_enumprocesses)
#endif /* _D3DKMTHK_H */
^ permalink raw reply related
* [PATCH 41/55] drivers: hv: dxgkrnl: Handle process ID in D3DKMTQueryStatistics
From: Eric Curtin @ 2026-03-19 20:24 UTC (permalink / raw)
To: linux-hyperv; +Cc: linux-kernel, iourit, wei.liu, decui, haiyangz
In-Reply-To: <20260319202509.63802-1-eric.curtin@docker.com>
From: Iouri Tarassov <iourit@linux.microsoft.com>
When D3DKMTQueryStatistics specifies a non-zero process ID, it needs to be
translated to the host process handle before sending a message to the host.
Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
[kms: forward port to 6.6 from 6.1. No code changes made.]
Signed-off-by: Kelsey Steele <kelseysteele@microsoft.com>
---
drivers/hv/dxgkrnl/dxgkrnl.h | 3 +-
drivers/hv/dxgkrnl/dxgprocess.c | 2 +
drivers/hv/dxgkrnl/dxgvmbus.c | 140 ++++++++++++++++----------------
drivers/hv/dxgkrnl/ioctl.c | 39 ++++++++-
4 files changed, 111 insertions(+), 73 deletions(-)
diff --git a/drivers/hv/dxgkrnl/dxgkrnl.h b/drivers/hv/dxgkrnl/dxgkrnl.h
index e7d8919b3c01..6af1e59b0a31 100644
--- a/drivers/hv/dxgkrnl/dxgkrnl.h
+++ b/drivers/hv/dxgkrnl/dxgkrnl.h
@@ -386,6 +386,7 @@ struct dxgprocess {
struct list_head plistentry;
pid_t pid;
pid_t tgid;
+ pid_t vpid; /* pdi from the current namespace */
/* how many time the process was opened */
struct kref process_kref;
/* protects the object memory */
@@ -981,7 +982,7 @@ int dxgvmb_send_get_stdalloc_data(struct dxgdevice *device,
void *prive_alloc_data,
u32 *res_priv_data_size,
void *priv_res_data);
-int dxgvmb_send_query_statistics(struct dxgprocess *process,
+int dxgvmb_send_query_statistics(struct d3dkmthandle host_process_handle,
struct dxgadapter *adapter,
struct d3dkmt_querystatistics *args);
int dxgvmb_send_async_msg(struct dxgvmbuschannel *channel,
diff --git a/drivers/hv/dxgkrnl/dxgprocess.c b/drivers/hv/dxgkrnl/dxgprocess.c
index fd51fd968049..5a4c4cb0c2e8 100644
--- a/drivers/hv/dxgkrnl/dxgprocess.c
+++ b/drivers/hv/dxgkrnl/dxgprocess.c
@@ -12,6 +12,7 @@
*/
#include "dxgkrnl.h"
+#include "linux/sched.h"
#undef dev_fmt
#define dev_fmt(fmt) "dxgk: " fmt
@@ -31,6 +32,7 @@ struct dxgprocess *dxgprocess_create(void)
DXG_TRACE("new dxgprocess created");
process->pid = current->pid;
process->tgid = current->tgid;
+ process->vpid = task_pid_vnr(current);
ret = dxgvmb_send_create_process(process);
if (ret < 0) {
DXG_TRACE("send_create_process failed");
diff --git a/drivers/hv/dxgkrnl/dxgvmbus.c b/drivers/hv/dxgkrnl/dxgvmbus.c
index 487804ca731a..916ed9071656 100644
--- a/drivers/hv/dxgkrnl/dxgvmbus.c
+++ b/drivers/hv/dxgkrnl/dxgvmbus.c
@@ -22,6 +22,8 @@
#include "dxgkrnl.h"
#include "dxgvmbus.h"
+#pragma GCC diagnostic ignored "-Warray-bounds"
+
#undef dev_fmt
#define dev_fmt(fmt) "dxgk: " fmt
@@ -113,7 +115,6 @@ static int init_message(struct dxgvmbusmsg *msg, struct dxgadapter *adapter,
static int init_message_res(struct dxgvmbusmsgres *msg,
struct dxgadapter *adapter,
- struct dxgprocess *process,
u32 size,
u32 result_size)
{
@@ -146,7 +147,7 @@ static int init_message_res(struct dxgvmbusmsgres *msg,
return 0;
}
-static void free_message(struct dxgvmbusmsg *msg, struct dxgprocess *process)
+static void free_message(struct dxgvmbusmsg *msg)
{
if (msg->hdr && (char *)msg->hdr != msg->msg_on_stack)
vfree(msg->hdr);
@@ -646,7 +647,7 @@ int dxgvmb_send_set_iospace_region(u64 start, u64 len)
dxgglobal_release_channel_lock();
cleanup:
- free_message(&msg, NULL);
+ free_message(&msg);
if (ret)
DXG_TRACE("Error: %d", ret);
return ret;
@@ -699,7 +700,7 @@ int dxgvmb_send_create_process(struct dxgprocess *process)
dxgglobal_release_channel_lock();
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -727,7 +728,7 @@ int dxgvmb_send_destroy_process(struct d3dkmthandle process)
dxgglobal_release_channel_lock();
cleanup:
- free_message(&msg, NULL);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -790,7 +791,7 @@ int dxgvmb_send_open_sync_object_nt(struct dxgprocess *process,
}
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -839,7 +840,7 @@ int dxgvmb_send_open_sync_object(struct dxgprocess *process,
*syncobj = result.sync_object;
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -881,7 +882,7 @@ int dxgvmb_send_create_nt_shared_object(struct dxgprocess *process,
}
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -912,7 +913,7 @@ int dxgvmb_send_destroy_nt_shared_object(struct d3dkmthandle shared_handle)
dxgglobal_release_channel_lock();
cleanup:
- free_message(&msg, NULL);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -945,7 +946,7 @@ int dxgvmb_send_destroy_sync_object(struct dxgprocess *process,
dxgglobal_release_channel_lock();
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -989,7 +990,7 @@ int dxgvmb_send_share_object_with_host(struct dxgprocess *process,
args->object_vail_nt_handle = result.vail_nt_handle;
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_ERR("err: %d", ret);
return ret;
@@ -1026,7 +1027,7 @@ int dxgvmb_send_open_adapter(struct dxgadapter *adapter)
adapter->host_handle = result.host_adapter_handle;
cleanup:
- free_message(&msg, NULL);
+ free_message(&msg);
if (ret)
DXG_ERR("Failed to open adapter: %d", ret);
return ret;
@@ -1048,7 +1049,7 @@ int dxgvmb_send_close_adapter(struct dxgadapter *adapter)
ret = dxgvmb_send_sync_msg(msg.channel, msg.hdr, msg.size,
NULL, 0);
- free_message(&msg, NULL);
+ free_message(&msg);
if (ret)
DXG_ERR("Failed to close adapter: %d", ret);
return ret;
@@ -1084,7 +1085,7 @@ int dxgvmb_send_get_internal_adapter_info(struct dxgadapter *adapter)
sizeof(adapter->device_instance_id) / sizeof(u16));
dxgglobal->async_msg_enabled = result.async_msg_enabled != 0;
}
- free_message(&msg, NULL);
+ free_message(&msg);
if (ret)
DXG_ERR("Failed to get adapter info: %d", ret);
return ret;
@@ -1114,7 +1115,7 @@ struct d3dkmthandle dxgvmb_send_create_device(struct dxgadapter *adapter,
&result, sizeof(result));
if (ret < 0)
result.device.v = 0;
- free_message(&msg, process);
+ free_message(&msg);
cleanup:
if (ret)
DXG_TRACE("err: %d", ret);
@@ -1140,7 +1141,7 @@ int dxgvmb_send_destroy_device(struct dxgadapter *adapter,
ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr, msg.size);
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -1167,7 +1168,7 @@ int dxgvmb_send_flush_device(struct dxgdevice *device,
ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr, msg.size);
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -1239,7 +1240,7 @@ dxgvmb_send_create_context(struct dxgadapter *adapter,
}
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return context;
@@ -1265,7 +1266,7 @@ int dxgvmb_send_destroy_context(struct dxgadapter *adapter,
ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr, msg.size);
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -1312,7 +1313,7 @@ int dxgvmb_send_create_paging_queue(struct dxgprocess *process,
pqueue->handle = args->paging_queue;
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -1339,7 +1340,7 @@ int dxgvmb_send_destroy_paging_queue(struct dxgprocess *process,
ret = dxgvmb_send_sync_msg(msg.channel, msg.hdr, msg.size, NULL, 0);
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -1550,7 +1551,7 @@ int create_existing_sysmem(struct dxgdevice *device,
cleanup:
if (kmem)
vunmap(kmem);
- free_message(&msg, device->process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -1783,7 +1784,7 @@ create_local_allocations(struct dxgprocess *process,
dxgdevice_release_alloc_list_lock(device);
}
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -1908,7 +1909,7 @@ int dxgvmb_send_create_allocation(struct dxgprocess *process,
if (result)
vfree(result);
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
@@ -1950,7 +1951,7 @@ int dxgvmb_send_destroy_allocation(struct dxgprocess *process,
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -1992,7 +1993,7 @@ int dxgvmb_send_query_clock_calibration(struct dxgprocess *process,
ret = ntstatus2int(result.status);
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -2015,7 +2016,7 @@ int dxgvmb_send_flush_heap_transitions(struct dxgprocess *process,
process->host_handle);
ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr, msg.size);
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -2042,7 +2043,7 @@ int dxgvmb_send_invalidate_cache(struct dxgprocess *process,
command->length = args->length;
ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr, msg.size);
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -2078,7 +2079,7 @@ int dxgvmb_send_query_alloc_residency(struct dxgprocess *process,
}
result_size += result_allocation_size;
- ret = init_message_res(&msg, adapter, process, cmd_size, result_size);
+ ret = init_message_res(&msg, adapter, cmd_size, result_size);
if (ret)
goto cleanup;
command = (void *)msg.msg;
@@ -2115,7 +2116,7 @@ int dxgvmb_send_query_alloc_residency(struct dxgprocess *process,
}
cleanup:
- free_message((struct dxgvmbusmsg *)&msg, process);
+ free_message((struct dxgvmbusmsg *)&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -2179,7 +2180,7 @@ int dxgvmb_send_escape(struct dxgprocess *process,
}
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -2243,7 +2244,7 @@ int dxgvmb_send_query_vidmem_info(struct dxgprocess *process,
}
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -2288,7 +2289,7 @@ int dxgvmb_send_get_device_state(struct dxgprocess *process,
args->execution_state = result.args.execution_state;
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -2312,8 +2313,7 @@ int dxgvmb_send_open_resource(struct dxgprocess *process,
sizeof(*result);
struct dxgvmbusmsgres msg = {.hdr = NULL};
- ret = init_message_res(&msg, adapter, process, sizeof(*command),
- result_size);
+ ret = init_message_res(&msg, adapter, sizeof(*command), result_size);
if (ret)
goto cleanup;
command = msg.msg;
@@ -2342,7 +2342,7 @@ int dxgvmb_send_open_resource(struct dxgprocess *process,
alloc_handles[i] = handles[i];
cleanup:
- free_message((struct dxgvmbusmsg *)&msg, process);
+ free_message((struct dxgvmbusmsg *)&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -2367,7 +2367,7 @@ int dxgvmb_send_get_stdalloc_data(struct dxgdevice *device,
result_size += *alloc_priv_driver_size;
if (priv_res_data)
result_size += *res_priv_data_size;
- ret = init_message_res(&msg, device->adapter, device->process,
+ ret = init_message_res(&msg, device->adapter,
sizeof(*command), result_size);
if (ret)
goto cleanup;
@@ -2427,7 +2427,7 @@ int dxgvmb_send_get_stdalloc_data(struct dxgdevice *device,
cleanup:
- free_message((struct dxgvmbusmsg *)&msg, device->process);
+ free_message((struct dxgvmbusmsg *)&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -2479,7 +2479,7 @@ int dxgvmb_send_make_resident(struct dxgprocess *process,
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -2525,7 +2525,7 @@ int dxgvmb_send_evict(struct dxgprocess *process,
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -2580,7 +2580,7 @@ int dxgvmb_send_submit_command(struct dxgprocess *process,
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -2617,7 +2617,7 @@ int dxgvmb_send_map_gpu_va(struct dxgprocess *process,
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -2647,7 +2647,7 @@ int dxgvmb_send_reserve_gpu_va(struct dxgprocess *process,
args->virtual_address = result.virtual_address;
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -2674,7 +2674,7 @@ int dxgvmb_send_free_gpu_va(struct dxgprocess *process,
ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr, msg.size);
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -2730,7 +2730,7 @@ int dxgvmb_send_update_gpu_va(struct dxgprocess *process,
ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr, msg.size);
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -2816,7 +2816,7 @@ dxgvmb_send_create_sync_object(struct dxgprocess *process,
}
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -2910,7 +2910,7 @@ int dxgvmb_send_signal_sync_object(struct dxgprocess *process,
}
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -2970,7 +2970,7 @@ int dxgvmb_send_wait_sync_object_cpu(struct dxgprocess *process,
ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr, msg.size);
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -3023,7 +3023,7 @@ int dxgvmb_send_wait_sync_object_gpu(struct dxgprocess *process,
}
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -3103,7 +3103,7 @@ int dxgvmb_send_lock2(struct dxgprocess *process,
hmgrtable_unlock(&process->handle_table, DXGLOCK_EXCL);
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -3130,7 +3130,7 @@ int dxgvmb_send_unlock2(struct dxgprocess *process,
ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr, msg.size);
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -3175,7 +3175,7 @@ int dxgvmb_send_update_alloc_property(struct dxgprocess *process,
}
}
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -3200,7 +3200,7 @@ int dxgvmb_send_mark_device_as_error(struct dxgprocess *process,
command->args = *args;
ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr, msg.size);
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -3270,7 +3270,7 @@ int dxgvmb_send_set_allocation_priority(struct dxgprocess *process,
ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr, msg.size);
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -3312,7 +3312,7 @@ int dxgvmb_send_get_allocation_priority(struct dxgprocess *process,
}
result_size = sizeof(*result) + priority_size;
- ret = init_message_res(&msg, adapter, process, cmd_size, result_size);
+ ret = init_message_res(&msg, adapter, cmd_size, result_size);
if (ret)
goto cleanup;
command = (void *)msg.msg;
@@ -3352,7 +3352,7 @@ int dxgvmb_send_get_allocation_priority(struct dxgprocess *process,
}
cleanup:
- free_message((struct dxgvmbusmsg *)&msg, process);
+ free_message((struct dxgvmbusmsg *)&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -3381,7 +3381,7 @@ int dxgvmb_send_set_context_sch_priority(struct dxgprocess *process,
command->in_process = in_process;
ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr, msg.size);
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -3415,7 +3415,7 @@ int dxgvmb_send_get_context_sch_priority(struct dxgprocess *process,
*priority = result.priority;
}
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -3461,7 +3461,7 @@ int dxgvmb_send_offer_allocations(struct dxgprocess *process,
ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr, msg.size);
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -3486,7 +3486,7 @@ int dxgvmb_send_reclaim_allocations(struct dxgprocess *process,
result_size += (args->allocation_count - 1) *
sizeof(enum d3dddi_reclaim_result);
- ret = init_message_res(&msg, adapter, process, cmd_size, result_size);
+ ret = init_message_res(&msg, adapter, cmd_size, result_size);
if (ret)
goto cleanup;
command = (void *)msg.msg;
@@ -3537,7 +3537,7 @@ int dxgvmb_send_reclaim_allocations(struct dxgprocess *process,
}
cleanup:
- free_message((struct dxgvmbusmsg *)&msg, process);
+ free_message((struct dxgvmbusmsg *)&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -3567,7 +3567,7 @@ int dxgvmb_send_change_vidmem_reservation(struct dxgprocess *process,
ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr, msg.size);
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -3706,7 +3706,7 @@ int dxgvmb_send_create_hwqueue(struct dxgprocess *process,
dxgvmb_send_destroy_hwqueue(process, adapter,
command->hwqueue);
}
- free_message(&msg, process);
+ free_message(&msg);
return ret;
}
@@ -3731,7 +3731,7 @@ int dxgvmb_send_destroy_hwqueue(struct dxgprocess *process,
ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr, msg.size);
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -3815,7 +3815,7 @@ int dxgvmb_send_query_adapter_info(struct dxgprocess *process,
}
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
@@ -3873,13 +3873,13 @@ int dxgvmb_send_submit_command_hwqueue(struct dxgprocess *process,
}
cleanup:
- free_message(&msg, process);
+ free_message(&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
}
-int dxgvmb_send_query_statistics(struct dxgprocess *process,
+int dxgvmb_send_query_statistics(struct d3dkmthandle host_process_handle,
struct dxgadapter *adapter,
struct d3dkmt_querystatistics *args)
{
@@ -3888,7 +3888,7 @@ int dxgvmb_send_query_statistics(struct dxgprocess *process,
int ret;
struct dxgvmbusmsgres msg = {.hdr = NULL};
- ret = init_message_res(&msg, adapter, process, sizeof(*command),
+ ret = init_message_res(&msg, adapter, sizeof(*command),
sizeof(*result));
if (ret)
goto cleanup;
@@ -3897,7 +3897,7 @@ int dxgvmb_send_query_statistics(struct dxgprocess *process,
command_vgpu_to_host_init2(&command->hdr,
DXGK_VMBCOMMAND_QUERYSTATISTICS,
- process->host_handle);
+ host_process_handle);
command->args = *args;
ret = dxgvmb_send_sync_msg(msg.channel, msg.hdr, msg.size,
@@ -3909,7 +3909,7 @@ int dxgvmb_send_query_statistics(struct dxgprocess *process,
ret = ntstatus2int(result->status);
cleanup:
- free_message((struct dxgvmbusmsg *)&msg, process);
+ free_message((struct dxgvmbusmsg *)&msg);
if (ret)
DXG_TRACE("err: %d", ret);
return ret;
diff --git a/drivers/hv/dxgkrnl/ioctl.c b/drivers/hv/dxgkrnl/ioctl.c
index 56b838a87f09..466bef6c14b3 100644
--- a/drivers/hv/dxgkrnl/ioctl.c
+++ b/drivers/hv/dxgkrnl/ioctl.c
@@ -147,6 +147,23 @@ static int dxgkio_open_adapter_from_luid(struct dxgprocess *process,
return ret;
}
+static struct d3dkmthandle find_dxgprocess_handle(u64 pid)
+{
+ struct dxgglobal *dxgglobal = dxggbl();
+ struct dxgprocess *entry;
+ struct d3dkmthandle host_handle = {};
+
+ mutex_lock(&dxgglobal->plistmutex);
+ list_for_each_entry(entry, &dxgglobal->plisthead, plistentry) {
+ if (entry->vpid == pid) {
+ host_handle.v = entry->host_handle.v;
+ break;
+ }
+ }
+ mutex_unlock(&dxgglobal->plistmutex);
+ return host_handle;
+}
+
static int dxgkio_query_statistics(struct dxgprocess *process,
void __user *inargs)
{
@@ -156,6 +173,8 @@ static int dxgkio_query_statistics(struct dxgprocess *process,
struct dxgadapter *adapter = NULL;
struct winluid tmp;
struct dxgglobal *dxgglobal = dxggbl();
+ struct d3dkmthandle host_process_handle = process->host_handle;
+ u64 pid;
args = vzalloc(sizeof(struct d3dkmt_querystatistics));
if (args == NULL) {
@@ -170,6 +189,18 @@ static int dxgkio_query_statistics(struct dxgprocess *process,
goto cleanup;
}
+ /* Find the host process handle when needed */
+ pid = args->process;
+ if (pid) {
+ host_process_handle = find_dxgprocess_handle(pid);
+ if (host_process_handle.v == 0) {
+ DXG_ERR("Invalid process ID is specified: %lld", pid);
+ ret = -EINVAL;
+ goto cleanup;
+ }
+ args->process = 0;
+ }
+
dxgglobal_acquire_adapter_list_lock(DXGLOCK_SHARED);
list_for_each_entry(entry, &dxgglobal->adapter_list_head,
adapter_list_entry) {
@@ -186,7 +217,8 @@ static int dxgkio_query_statistics(struct dxgprocess *process,
if (adapter) {
tmp = args->adapter_luid;
args->adapter_luid = adapter->host_adapter_luid;
- ret = dxgvmb_send_query_statistics(process, adapter, args);
+ ret = dxgvmb_send_query_statistics(host_process_handle, adapter,
+ args);
if (ret >= 0) {
args->adapter_luid = tmp;
ret = copy_to_user(inargs, args, sizeof(*args));
@@ -280,7 +312,10 @@ dxgkp_enum_adapters(struct dxgprocess *process,
dxgglobal_release_adapter_list_lock(DXGLOCK_SHARED);
if (adapter_count > adapter_count_max) {
- ret = STATUS_BUFFER_TOO_SMALL;
+ struct ntstatus status;
+
+ status.v = STATUS_BUFFER_TOO_SMALL;
+ ret = ntstatus2int(status);
DXG_TRACE("Too many adapters");
ret = copy_to_user(adapter_count_out,
&dxgglobal->num_adapters, sizeof(u32));
^ permalink raw reply related
* [PATCH 40/55] drivers: hv: dxgkrnl: Added implementation for D3DKMTInvalidateCache
From: Eric Curtin @ 2026-03-19 20:24 UTC (permalink / raw)
To: linux-hyperv; +Cc: linux-kernel, iourit, wei.liu, decui, haiyangz
In-Reply-To: <20260319202509.63802-1-eric.curtin@docker.com>
From: Iouri Tarassov <iourit@linux.microsoft.com>
D3DKMTInvalidateCache is called by user mode drivers when the device
doesn't support cache coherent access to compute device allocations.
It needs to be called after an allocation was accessed by CPU and now
needs to be accessed by the device. And vice versa.
Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
[kms: forward port to 6.6 from 6.1. No code changes made.]
Signed-off-by: Kelsey Steele <kelseysteele@microsoft.com>
---
drivers/hv/dxgkrnl/dxgkrnl.h | 3 +++
drivers/hv/dxgkrnl/dxgvmbus.c | 27 +++++++++++++++++++
drivers/hv/dxgkrnl/dxgvmbus.h | 11 ++++++++
drivers/hv/dxgkrnl/ioctl.c | 49 +++++++++++++++++++++++++++++++++--
include/uapi/misc/d3dkmthk.h | 9 +++++++
5 files changed, 97 insertions(+), 2 deletions(-)
diff --git a/drivers/hv/dxgkrnl/dxgkrnl.h b/drivers/hv/dxgkrnl/dxgkrnl.h
index d20489317c0b..e7d8919b3c01 100644
--- a/drivers/hv/dxgkrnl/dxgkrnl.h
+++ b/drivers/hv/dxgkrnl/dxgkrnl.h
@@ -989,6 +989,9 @@ int dxgvmb_send_async_msg(struct dxgvmbuschannel *channel,
u32 cmd_size);
int dxgvmb_send_share_object_with_host(struct dxgprocess *process,
struct d3dkmt_shareobjectwithhost *args);
+int dxgvmb_send_invalidate_cache(struct dxgprocess *process,
+ struct dxgadapter *adapter,
+ struct d3dkmt_invalidatecache *args);
void signal_host_cpu_event(struct dxghostevent *eventhdr);
int ntstatus2int(struct ntstatus status);
diff --git a/drivers/hv/dxgkrnl/dxgvmbus.c b/drivers/hv/dxgkrnl/dxgvmbus.c
index 5f17efc937c3..487804ca731a 100644
--- a/drivers/hv/dxgkrnl/dxgvmbus.c
+++ b/drivers/hv/dxgkrnl/dxgvmbus.c
@@ -2021,6 +2021,33 @@ int dxgvmb_send_flush_heap_transitions(struct dxgprocess *process,
return ret;
}
+int dxgvmb_send_invalidate_cache(struct dxgprocess *process,
+ struct dxgadapter *adapter,
+ struct d3dkmt_invalidatecache *args)
+{
+ struct dxgkvmb_command_invalidatecache *command;
+ int ret;
+ struct dxgvmbusmsg msg = {.hdr = NULL};
+
+ ret = init_message(&msg, adapter, process, sizeof(*command));
+ if (ret)
+ goto cleanup;
+ command = (void *)msg.msg;
+ command_vgpu_to_host_init2(&command->hdr,
+ DXGK_VMBCOMMAND_INVALIDATECACHE,
+ process->host_handle);
+ command->device = args->device;
+ command->allocation = args->allocation;
+ command->offset = args->offset;
+ command->length = args->length;
+ ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr, msg.size);
+cleanup:
+ free_message(&msg, process);
+ if (ret)
+ DXG_TRACE("err: %d", ret);
+ return ret;
+}
+
int dxgvmb_send_query_alloc_residency(struct dxgprocess *process,
struct dxgadapter *adapter,
struct d3dkmt_queryallocationresidency
diff --git a/drivers/hv/dxgkrnl/dxgvmbus.h b/drivers/hv/dxgkrnl/dxgvmbus.h
index b4a98f7c2522..20c562b485de 100644
--- a/drivers/hv/dxgkrnl/dxgvmbus.h
+++ b/drivers/hv/dxgkrnl/dxgvmbus.h
@@ -125,6 +125,7 @@ enum dxgkvmb_commandtype {
DXGK_VMBCOMMAND_QUERYRESOURCEINFO = 64,
DXGK_VMBCOMMAND_LOGEVENT = 65,
DXGK_VMBCOMMAND_SETEXISTINGSYSMEMPAGES = 66,
+ DXGK_VMBCOMMAND_INVALIDATECACHE = 67,
DXGK_VMBCOMMAND_INVALID
};
@@ -428,6 +429,16 @@ struct dxgkvmb_command_flushheaptransitions {
struct dxgkvmb_command_vgpu_to_host hdr;
};
+/* Returns ntstatus */
+struct dxgkvmb_command_invalidatecache {
+ struct dxgkvmb_command_vgpu_to_host hdr;
+ struct d3dkmthandle device;
+ struct d3dkmthandle allocation;
+ u64 offset;
+ u64 length;
+ u64 reserved;
+};
+
struct dxgkvmb_command_freegpuvirtualaddress {
struct dxgkvmb_command_vgpu_to_host hdr;
struct d3dkmt_freegpuvirtualaddress args;
diff --git a/drivers/hv/dxgkrnl/ioctl.c b/drivers/hv/dxgkrnl/ioctl.c
index f735b18fcc14..56b838a87f09 100644
--- a/drivers/hv/dxgkrnl/ioctl.c
+++ b/drivers/hv/dxgkrnl/ioctl.c
@@ -4286,6 +4286,8 @@ dxgkio_query_clock_calibration(struct dxgprocess *process, void *__user inargs)
dxgadapter_release_lock_shared(adapter);
if (adapter)
kref_put(&adapter->adapter_kref, dxgadapter_release);
+
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -4333,6 +4335,49 @@ dxgkio_flush_heap_transitions(struct dxgprocess *process, void *__user inargs)
dxgadapter_release_lock_shared(adapter);
if (adapter)
kref_put(&adapter->adapter_kref, dxgadapter_release);
+
+ DXG_TRACE_IOCTL_END(ret);
+ return ret;
+}
+
+static int
+dxgkio_invalidate_cache(struct dxgprocess *process, void *__user inargs)
+{
+ struct d3dkmt_invalidatecache args;
+ int ret;
+ struct dxgdevice *device = NULL;
+
+ ret = copy_from_user(&args, inargs, sizeof(args));
+ if (ret) {
+ DXG_ERR("failed to copy input args");
+ ret = -EFAULT;
+ goto cleanup;
+ }
+
+ device = dxgprocess_device_by_handle(process, args.device);
+ if (device == NULL) {
+ ret = -EINVAL;
+ goto cleanup;
+ }
+
+ ret = dxgdevice_acquire_lock_shared(device);
+ if (ret < 0) {
+ kref_put(&device->device_kref, dxgdevice_release);
+ device = NULL;
+ goto cleanup;
+ }
+
+ ret = dxgvmb_send_invalidate_cache(process, device->adapter,
+ &args);
+
+cleanup:
+
+ if (device) {
+ dxgdevice_release_lock_shared(device);
+ kref_put(&device->device_kref, dxgdevice_release);
+ }
+
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -5198,7 +5243,7 @@ static struct ioctl_desc ioctls[] = {
/* 0x22 */ {dxgkio_get_context_scheduling_priority,
LX_DXGETCONTEXTSCHEDULINGPRIORITY},
/* 0x23 */ {},
-/* 0x24 */ {},
+/* 0x24 */ {dxgkio_invalidate_cache, LX_DXINVALIDATECACHE},
/* 0x25 */ {dxgkio_lock2, LX_DXLOCK2},
/* 0x26 */ {dxgkio_mark_device_as_error, LX_DXMARKDEVICEASERROR},
/* 0x27 */ {dxgkio_offer_allocations, LX_DXOFFERALLOCATIONS},
@@ -5243,7 +5288,7 @@ static struct ioctl_desc ioctls[] = {
/* 0x44 */ {dxgkio_share_object_with_host, LX_DXSHAREOBJECTWITHHOST},
/* 0x45 */ {dxgkio_create_sync_file, LX_DXCREATESYNCFILE},
/* 0x46 */ {dxgkio_wait_sync_file, LX_DXWAITSYNCFILE},
-/* 0x46 */ {dxgkio_open_syncobj_from_syncfile,
+/* 0x47 */ {dxgkio_open_syncobj_from_syncfile,
LX_DXOPENSYNCOBJECTFROMSYNCFILE},
};
diff --git a/include/uapi/misc/d3dkmthk.h b/include/uapi/misc/d3dkmthk.h
index 1eaa3f038322..84fa07a46d3c 100644
--- a/include/uapi/misc/d3dkmthk.h
+++ b/include/uapi/misc/d3dkmthk.h
@@ -1580,6 +1580,13 @@ struct d3dkmt_opensyncobjectfromsyncfile {
__u64 fence_value_gpu_va; /* out */
};
+struct d3dkmt_invalidatecache {
+ struct d3dkmthandle device;
+ struct d3dkmthandle allocation;
+ __u64 offset;
+ __u64 length;
+};
+
/*
* Dxgkrnl Graphics Port Driver ioctl definitions
*
@@ -1647,6 +1654,8 @@ struct d3dkmt_opensyncobjectfromsyncfile {
_IOWR(0x47, 0x21, struct d3dkmt_getcontextinprocessschedulingpriority)
#define LX_DXGETCONTEXTSCHEDULINGPRIORITY \
_IOWR(0x47, 0x22, struct d3dkmt_getcontextschedulingpriority)
+#define LX_DXINVALIDATECACHE \
+ _IOWR(0x47, 0x24, struct d3dkmt_invalidatecache)
#define LX_DXLOCK2 \
_IOWR(0x47, 0x25, struct d3dkmt_lock2)
#define LX_DXMARKDEVICEASERROR \
^ permalink raw reply related
* [PATCH 39/55] drivers: hv: dxgkrnl: Added support for compute only adapters
From: Eric Curtin @ 2026-03-19 20:24 UTC (permalink / raw)
To: linux-hyperv; +Cc: linux-kernel, iourit, wei.liu, decui, haiyangz
In-Reply-To: <20260319202509.63802-1-eric.curtin@docker.com>
From: Iouri Tarassov <iourit@linux.microsoft.com>
Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
[kms: forward port to 6.6 from 6.1. No code changes made.]
Signed-off-by: Kelsey Steele <kelseysteele@microsoft.com>
---
drivers/hv/dxgkrnl/dxgkrnl.h | 1 +
drivers/hv/dxgkrnl/dxgmodule.c | 11 ++++++++++-
drivers/hv/dxgkrnl/dxgvmbus.c | 1 +
drivers/hv/dxgkrnl/ioctl.c | 4 ++++
4 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/drivers/hv/dxgkrnl/dxgkrnl.h b/drivers/hv/dxgkrnl/dxgkrnl.h
index c5ed23cb90df..d20489317c0b 100644
--- a/drivers/hv/dxgkrnl/dxgkrnl.h
+++ b/drivers/hv/dxgkrnl/dxgkrnl.h
@@ -478,6 +478,7 @@ struct dxgadapter {
struct winluid luid; /* VM bus channel luid */
u16 device_description[80];
u16 device_instance_id[WIN_MAX_PATH];
+ bool compute_only;
bool stopping_adapter;
};
diff --git a/drivers/hv/dxgkrnl/dxgmodule.c b/drivers/hv/dxgkrnl/dxgmodule.c
index f419597f711a..0fafb6167229 100644
--- a/drivers/hv/dxgkrnl/dxgmodule.c
+++ b/drivers/hv/dxgkrnl/dxgmodule.c
@@ -20,6 +20,7 @@
#define PCI_VENDOR_ID_MICROSOFT 0x1414
#define PCI_DEVICE_ID_VIRTUAL_RENDER 0x008E
+#define PCI_DEVICE_ID_COMPUTE_ACCELERATOR 0x008A
#undef pr_fmt
#define pr_fmt(fmt) "dxgk: " fmt
@@ -270,6 +271,8 @@ int dxgglobal_create_adapter(struct pci_dev *dev, guid_t *guid,
adapter->adapter_state = DXGADAPTER_STATE_WAITING_VMBUS;
adapter->host_vgpu_luid = host_vgpu_luid;
+ if (dev->device == PCI_DEVICE_ID_COMPUTE_ACCELERATOR)
+ adapter->compute_only = true;
kref_init(&adapter->adapter_kref);
init_rwsem(&adapter->core_lock);
mutex_init(&adapter->device_creation_lock);
@@ -622,6 +625,12 @@ static struct pci_device_id dxg_pci_id_table[] = {
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID
},
+ {
+ .vendor = PCI_VENDOR_ID_MICROSOFT,
+ .device = PCI_DEVICE_ID_COMPUTE_ACCELERATOR,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID
+ },
{ 0 }
};
@@ -962,4 +971,4 @@ module_exit(dxg_drv_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Microsoft Dxgkrnl virtual compute device Driver");
-MODULE_VERSION("2.0.1");
+MODULE_VERSION("2.0.2");
diff --git a/drivers/hv/dxgkrnl/dxgvmbus.c b/drivers/hv/dxgkrnl/dxgvmbus.c
index eb3f4c5153a6..5f17efc937c3 100644
--- a/drivers/hv/dxgkrnl/dxgvmbus.c
+++ b/drivers/hv/dxgkrnl/dxgvmbus.c
@@ -3774,6 +3774,7 @@ int dxgvmb_send_query_adapter_info(struct dxgprocess *process,
adapter_type->indirect_display_device = 0;
adapter_type->acg_supported = 0;
adapter_type->support_set_timings_from_vidpn = 0;
+ adapter_type->compute_only = !!adapter->compute_only;
break;
}
default:
diff --git a/drivers/hv/dxgkrnl/ioctl.c b/drivers/hv/dxgkrnl/ioctl.c
index 98350583943e..f735b18fcc14 100644
--- a/drivers/hv/dxgkrnl/ioctl.c
+++ b/drivers/hv/dxgkrnl/ioctl.c
@@ -254,6 +254,8 @@ dxgkp_enum_adapters(struct dxgprocess *process,
list_for_each_entry(entry, &dxgglobal->adapter_list_head,
adapter_list_entry) {
+ if (entry->compute_only && !filter.include_compute_only)
+ continue;
if (dxgadapter_acquire_lock_shared(entry) == 0) {
struct d3dkmt_adapterinfo *inf = &info[adapter_count];
@@ -474,6 +476,8 @@ dxgkio_enum_adapters(struct dxgprocess *process, void *__user inargs)
list_for_each_entry(entry, &dxgglobal->adapter_list_head,
adapter_list_entry) {
+ if (entry->compute_only)
+ continue;
if (dxgadapter_acquire_lock_shared(entry) == 0) {
struct d3dkmt_adapterinfo *inf = &info[adapter_count];
^ permalink raw reply related
* [PATCH 38/55] drivers: hv: dxgkrnl: Fixed dxgkrnl to build for the 6.1 kernel
From: Eric Curtin @ 2026-03-19 20:24 UTC (permalink / raw)
To: linux-hyperv; +Cc: linux-kernel, iourit, wei.liu, decui, haiyangz
In-Reply-To: <20260319202509.63802-1-eric.curtin@docker.com>
From: Iouri Tarassov <iourit@linux.microsoft.com>
Definition for GPADL was changed from u32 to struct vmbus_gpadl.
Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
[kms: forward port to 6.6 from 6.1. No code changes made.]
Signed-off-by: Kelsey Steele <kelseysteele@microsoft.com>
---
drivers/hv/dxgkrnl/dxgadapter.c | 8 --------
drivers/hv/dxgkrnl/dxgkrnl.h | 4 ----
drivers/hv/dxgkrnl/dxgvmbus.c | 8 --------
3 files changed, 20 deletions(-)
diff --git a/drivers/hv/dxgkrnl/dxgadapter.c b/drivers/hv/dxgkrnl/dxgadapter.c
index d9d45bd4a31e..bcd19b7267d1 100644
--- a/drivers/hv/dxgkrnl/dxgadapter.c
+++ b/drivers/hv/dxgkrnl/dxgadapter.c
@@ -927,19 +927,11 @@ void dxgallocation_destroy(struct dxgallocation *alloc)
alloc->owner.device,
&args, &alloc->alloc_handle);
}
-#ifdef _MAIN_KERNEL_
if (alloc->gpadl.gpadl_handle) {
DXG_TRACE("Teardown gpadl %d", alloc->gpadl.gpadl_handle);
vmbus_teardown_gpadl(dxgglobal_get_vmbus(), &alloc->gpadl);
alloc->gpadl.gpadl_handle = 0;
}
-#else
- if (alloc->gpadl) {
- DXG_TRACE("Teardown gpadl %d", alloc->gpadl);
- vmbus_teardown_gpadl(dxgglobal_get_vmbus(), alloc->gpadl);
- alloc->gpadl = 0;
- }
-#endif
if (alloc->priv_drv_data)
vfree(alloc->priv_drv_data);
if (alloc->cpu_address_mapped)
diff --git a/drivers/hv/dxgkrnl/dxgkrnl.h b/drivers/hv/dxgkrnl/dxgkrnl.h
index 1b40d6e39085..c5ed23cb90df 100644
--- a/drivers/hv/dxgkrnl/dxgkrnl.h
+++ b/drivers/hv/dxgkrnl/dxgkrnl.h
@@ -728,11 +728,7 @@ struct dxgallocation {
u32 cached:1;
u32 handle_valid:1;
/* GPADL address list for existing sysmem allocations */
-#ifdef _MAIN_KERNEL_
struct vmbus_gpadl gpadl;
-#else
- u32 gpadl;
-#endif
/* Number of pages in the 'pages' array */
u32 num_pages;
/*
diff --git a/drivers/hv/dxgkrnl/dxgvmbus.c b/drivers/hv/dxgkrnl/dxgvmbus.c
index 8c99f141482e..eb3f4c5153a6 100644
--- a/drivers/hv/dxgkrnl/dxgvmbus.c
+++ b/drivers/hv/dxgkrnl/dxgvmbus.c
@@ -1493,22 +1493,14 @@ int create_existing_sysmem(struct dxgdevice *device,
ret = -ENOMEM;
goto cleanup;
}
-#ifdef _MAIN_KERNEL_
DXG_TRACE("New gpadl %d", dxgalloc->gpadl.gpadl_handle);
-#else
- DXG_TRACE("New gpadl %d", dxgalloc->gpadl);
-#endif
command_vgpu_to_host_init2(&set_store_command->hdr,
DXGK_VMBCOMMAND_SETEXISTINGSYSMEMSTORE,
device->process->host_handle);
set_store_command->device = device->handle;
set_store_command->allocation = host_alloc->allocation;
-#ifdef _MAIN_KERNEL_
set_store_command->gpadl = dxgalloc->gpadl.gpadl_handle;
-#else
- set_store_command->gpadl = dxgalloc->gpadl;
-#endif
ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr,
msg.size);
if (ret < 0)
^ permalink raw reply related
* [PATCH 37/55] drivers: hv: dxgkrnl: Added missed NULL check for resource object
From: Eric Curtin @ 2026-03-19 20:24 UTC (permalink / raw)
To: linux-hyperv; +Cc: linux-kernel, iourit, wei.liu, decui, haiyangz
In-Reply-To: <20260319202509.63802-1-eric.curtin@docker.com>
From: Iouri Tarassov <iourit@linux.microsoft.com>
Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
[kms: forward port to 6.6 from 6.1. No code changes made.]
Signed-off-by: Kelsey Steele <kelseysteele@microsoft.com>
---
drivers/hv/dxgkrnl/ioctl.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/hv/dxgkrnl/ioctl.c b/drivers/hv/dxgkrnl/ioctl.c
index 69324510c9e2..98350583943e 100644
--- a/drivers/hv/dxgkrnl/ioctl.c
+++ b/drivers/hv/dxgkrnl/ioctl.c
@@ -1589,7 +1589,8 @@ dxgkio_create_allocation(struct dxgprocess *process, void *__user inargs)
&process->handle_table,
HMGRENTRY_TYPE_DXGRESOURCE,
args.resource);
- kref_get(&resource->resource_kref);
+ if (resource != NULL)
+ kref_get(&resource->resource_kref);
dxgprocess_ht_lock_shared_up(process);
if (resource == NULL || resource->device != device) {
@@ -1693,10 +1694,8 @@ dxgkio_create_allocation(struct dxgprocess *process, void *__user inargs)
&standard_alloc);
cleanup:
- if (resource_mutex_acquired) {
+ if (resource_mutex_acquired)
mutex_unlock(&resource->resource_mutex);
- kref_put(&resource->resource_kref, dxgresource_release);
- }
if (ret < 0) {
if (dxgalloc) {
for (i = 0; i < args.alloc_count; i++) {
@@ -1727,6 +1726,9 @@ dxgkio_create_allocation(struct dxgprocess *process, void *__user inargs)
if (adapter)
dxgadapter_release_lock_shared(adapter);
+ if (resource && !args.flags.create_resource)
+ kref_put(&resource->resource_kref, dxgresource_release);
+
if (device) {
dxgdevice_release_lock_shared(device);
kref_put(&device->device_kref, dxgdevice_release);
^ permalink raw reply related
* [PATCH 36/55] drivers: hv: dxgkrnl: Close shared file objects in case of a failure
From: Eric Curtin @ 2026-03-19 20:24 UTC (permalink / raw)
To: linux-hyperv; +Cc: linux-kernel, iourit, wei.liu, decui, haiyangz
In-Reply-To: <20260319202509.63802-1-eric.curtin@docker.com>
From: Iouri Tarassov <iourit@linux.microsoft.com>
Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
[kms: forward port to 6.6 from 6.1. No code changes made.]
Signed-off-by: Kelsey Steele <kelseysteele@microsoft.com>
---
drivers/hv/dxgkrnl/ioctl.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/drivers/hv/dxgkrnl/ioctl.c b/drivers/hv/dxgkrnl/ioctl.c
index 7c72790f917f..69324510c9e2 100644
--- a/drivers/hv/dxgkrnl/ioctl.c
+++ b/drivers/hv/dxgkrnl/ioctl.c
@@ -4536,7 +4536,7 @@ enum dxg_sharedobject_type {
};
static int get_object_fd(enum dxg_sharedobject_type type,
- void *object, int *fdout)
+ void *object, int *fdout, struct file **filp)
{
struct file *file;
int fd;
@@ -4565,8 +4565,8 @@ static int get_object_fd(enum dxg_sharedobject_type type,
return -ENOTRECOVERABLE;
}
- fd_install(fd, file);
*fdout = fd;
+ *filp = file;
return 0;
}
@@ -4581,6 +4581,7 @@ dxgkio_share_objects(struct dxgprocess *process, void *__user inargs)
struct dxgsharedresource *shared_resource = NULL;
struct d3dkmthandle *handles = NULL;
int object_fd = -1;
+ struct file *filp = NULL;
void *obj = NULL;
u32 handle_size;
int ret;
@@ -4660,7 +4661,7 @@ dxgkio_share_objects(struct dxgprocess *process, void *__user inargs)
switch (object_type) {
case HMGRENTRY_TYPE_DXGSYNCOBJECT:
ret = get_object_fd(DXG_SHARED_SYNCOBJECT, shared_syncobj,
- &object_fd);
+ &object_fd, &filp);
if (ret < 0) {
DXG_ERR("get_object_fd failed for sync object");
goto cleanup;
@@ -4675,7 +4676,7 @@ dxgkio_share_objects(struct dxgprocess *process, void *__user inargs)
break;
case HMGRENTRY_TYPE_DXGRESOURCE:
ret = get_object_fd(DXG_SHARED_RESOURCE, shared_resource,
- &object_fd);
+ &object_fd, &filp);
if (ret < 0) {
DXG_ERR("get_object_fd failed for resource");
goto cleanup;
@@ -4708,10 +4709,15 @@ dxgkio_share_objects(struct dxgprocess *process, void *__user inargs)
if (ret) {
DXG_ERR("failed to copy shared handle");
ret = -EFAULT;
+ goto cleanup;
}
+ fd_install(object_fd, filp);
+
cleanup:
if (ret < 0) {
+ if (filp)
+ fput(filp);
if (object_fd >= 0)
put_unused_fd(object_fd);
}
^ permalink raw reply related
* [PATCH 35/55] drivers: hv: dxgkrnl: Fix synchronization locks
From: Eric Curtin @ 2026-03-19 20:24 UTC (permalink / raw)
To: linux-hyperv; +Cc: linux-kernel, iourit, wei.liu, decui, haiyangz
In-Reply-To: <20260319202509.63802-1-eric.curtin@docker.com>
From: Iouri Tarassov <iourit@linux.microsoft.com>
Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
[kms: forward port to 6.6 from 6.1. No code changes made.]
Signed-off-by: Kelsey Steele <kelseysteele@microsoft.com>
---
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/dxgadapter.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;
adapter = container_of(refcount, struct dxgadapter, adapter_kref);
- DXG_TRACE("%p", adapter);
+ DXG_TRACE("Destroying adapter: %px", adapter);
kfree(adapter);
}
@@ -270,6 +270,8 @@ struct dxgdevice *dxgdevice_create(struct dxgadapter *adapter,
if (ret < 0) {
kref_put(&device->device_kref, dxgdevice_release);
device = NULL;
+ } else {
+ DXG_TRACE("dxgdevice created: %px", device);
}
}
return device;
@@ -413,11 +415,8 @@ void dxgdevice_destroy(struct dxgdevice *device)
cleanup:
- if (device->adapter) {
+ if (device->adapter)
dxgprocess_adapter_remove_device(device);
- kref_put(&device->adapter->adapter_kref, dxgadapter_release);
- device->adapter = NULL;
- }
up_write(&device->device_lock);
@@ -721,6 +720,8 @@ void dxgdevice_release(struct kref *refcount)
struct dxgdevice *device;
device = container_of(refcount, struct dxgdevice, device_kref);
+ DXG_TRACE("Destroying device: %px", device);
+ kref_put(&device->adapter->adapter_kref, dxgadapter_release);
kfree(device);
}
@@ -999,6 +1000,9 @@ void dxgpagingqueue_destroy(struct dxgpagingqueue *pqueue)
kfree(pqueue);
}
+/*
+ * Process_adapter_mutex is held.
+ */
struct dxgprocess_adapter *dxgprocess_adapter_create(struct dxgprocess *process,
struct dxgadapter *adapter)
{
@@ -1108,7 +1112,7 @@ int dxgprocess_adapter_add_device(struct dxgprocess *process,
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;
- /* List of opened adapters (dxgprocess_adapter) */
+ /*
+ * List of opened adapters (dxgprocess_adapter).
+ * Protected by process_adapter_mutex.
+ */
struct list_head process_adapter_list_head;
};
@@ -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);
#define DXG_TRACE(fmt, ...) do { \
trace_printk(dev_fmt(fmt) "\n", ##__VA_ARGS__); \
+ dev_dbg(DXGDEV, "%s: " fmt, __func__, ##__VA_ARGS__); \
} while (0)
#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 = host_vgpu_luid;
kref_init(&adapter->adapter_kref);
init_rwsem(&adapter->core_lock);
+ mutex_init(&adapter->device_creation_lock);
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);
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/dxgprocess.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 *process,
hmgrtable_unlock(&process->local_handle_table, DXGLOCK_EXCL);
if (adapter) {
+ mutex_lock(&adapter->device_creation_lock);
+ dxgglobal_acquire_process_adapter_lock();
adapter_info = 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 = -EINVAL;
- }
+ dxgglobal_release_process_adapter_lock();
+ mutex_unlock(&adapter->device_creation_lock);
} else {
DXG_ERR("Adapter not found %x", handle.v);
ret = -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 *process,
struct dxgresource *resource)
{
int ret = 0;
- int i;
+ int i = 0;
+ int k;
+ struct dxgkvmb_command_allocinfo_return *host_alloc;
+ /*
+ * 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 = res->resource;
+ for (i = 0; i < args->alloc_count; i++) {
+ host_alloc = &res->allocation_info[i];
+ dxgalloc[i]->alloc_handle = 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 = hmgrtable_assign_handle(&process->handle_table, resource,
@@ -1583,14 +1602,12 @@ process_allocation_handles(struct dxgprocess *process,
if (ret < 0) {
DXG_ERR("failed to assign resource handle %x",
res->resource.v);
+ goto cleanup;
} else {
- resource->handle = res->resource;
resource->handle_valid = 1;
}
}
for (i = 0; i < args->alloc_count; i++) {
- struct dxgkvmb_command_allocinfo_return *host_alloc;
-
host_alloc = &res->allocation_info[i];
ret = hmgrtable_assign_handle(&process->handle_table,
dxgalloc[i],
@@ -1602,9 +1619,26 @@ process_allocation_handles(struct dxgprocess *process,
args->alloc_count, i);
break;
}
- dxgalloc[i]->alloc_handle = host_alloc->allocation;
dxgalloc[i]->handle_valid = 1;
}
+ if (ret < 0) {
+ if (args->flags.create_resource) {
+ hmgrtable_free_handle(&process->handle_table,
+ HMGRENTRY_TYPE_DXGRESOURCE,
+ res->resource);
+ resource->handle_valid = 0;
+ }
+ for (k = 0; k < i; k++) {
+ host_alloc = &res->allocation_info[i];
+ hmgrtable_free_handle(&process->handle_table,
+ HMGRENTRY_TYPE_DXGALLOCATION,
+ host_alloc->allocation);
+ dxgalloc[i]->handle_valid = 0;
+ }
+ }
+
+cleanup:
+
hmgrtable_unlock(&process->handle_table, DXGLOCK_EXCL);
if (ret)
@@ -1705,18 +1739,17 @@ create_local_allocations(struct dxgprocess *process,
}
}
- ret = process_allocation_handles(process, device, args, result,
- dxgalloc, resource);
- if (ret < 0)
- goto cleanup;
-
ret = copy_to_user(&input_args->global_share, &args->global_share,
sizeof(struct d3dkmthandle));
if (ret) {
DXG_ERR("failed to copy global share");
ret = -EFAULT;
+ goto cleanup;
}
+ ret = process_allocation_handles(process, device, args, result,
+ dxgalloc, resource);
+
cleanup:
if (ret < 0) {
@@ -3576,22 +3609,6 @@ int dxgvmb_send_create_hwqueue(struct dxgprocess *process,
goto cleanup;
}
- ret = hmgrtable_assign_handle_safe(&process->handle_table, hwqueue,
- HMGRENTRY_TYPE_DXGHWQUEUE,
- command->hwqueue);
- if (ret < 0)
- goto cleanup;
-
- ret = hmgrtable_assign_handle_safe(&process->handle_table,
- NULL,
- HMGRENTRY_TYPE_MONITOREDFENCE,
- command->hwqueue_progress_fence);
- if (ret < 0)
- goto cleanup;
-
- hwqueue->handle = command->hwqueue;
- hwqueue->progress_fence_sync_object = command->hwqueue_progress_fence;
-
hwqueue->progress_fence_mapped_address =
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 *process,
}
}
+ ret = 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 = command->hwqueue_progress_fence;
+ hwqueue->handle = command->hwqueue;
+
+ ret = hmgrtable_assign_handle_safe(&process->handle_table, hwqueue,
+ HMGRENTRY_TYPE_DXGHWQUEUE,
+ command->hwqueue);
+ if (ret < 0)
+ hwqueue->handle.v = 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 = NULL;
struct d3dkmthandle host_device_handle = {};
bool adapter_locked = false;
+ bool device_creation_locked = false;
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
@@ -651,6 +652,9 @@ dxgkio_create_device(struct dxgprocess *process, void *__user inargs)
goto cleanup;
}
+ mutex_lock(&adapter->device_creation_lock);
+ device_creation_locked = true;
+
device = dxgdevice_create(adapter, process);
if (device == NULL) {
ret = -ENOMEM;
@@ -699,6 +703,9 @@ dxgkio_create_device(struct dxgprocess *process, void *__user inargs)
if (adapter_locked)
dxgadapter_release_lock_shared(adapter);
+ if (device_creation_locked)
+ mutex_unlock(&adapter->device_creation_lock);
+
if (adapter)
kref_put(&adapter->adapter_kref, dxgadapter_release);
@@ -803,22 +810,21 @@ dxgkio_create_context_virtual(struct dxgprocess *process, void *__user inargs)
host_context_handle = dxgvmb_send_create_context(adapter,
process, &args);
if (host_context_handle.v) {
- hmgrtable_lock(&process->handle_table, DXGLOCK_EXCL);
- ret = hmgrtable_assign_handle(&process->handle_table, context,
- HMGRENTRY_TYPE_DXGCONTEXT,
- host_context_handle);
- if (ret >= 0)
- context->handle = host_context_handle;
- hmgrtable_unlock(&process->handle_table, DXGLOCK_EXCL);
- if (ret < 0)
- goto cleanup;
ret = copy_to_user(&((struct d3dkmt_createcontextvirtual *)
inargs)->context, &host_context_handle,
sizeof(struct d3dkmthandle));
if (ret) {
DXG_ERR("failed to copy context handle");
ret = -EFAULT;
+ goto cleanup;
}
+ hmgrtable_lock(&process->handle_table, DXGLOCK_EXCL);
+ ret = hmgrtable_assign_handle(&process->handle_table, context,
+ HMGRENTRY_TYPE_DXGCONTEXT,
+ host_context_handle);
+ if (ret >= 0)
+ context->handle = host_context_handle;
+ hmgrtable_unlock(&process->handle_table, DXGLOCK_EXCL);
} else {
DXG_ERR("invalid host handle");
ret = -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)
*/
^ permalink raw reply related
* [PATCH 34/55] drivers: hv: dxgkrnl: Improve tracing and return values from copy from user
From: Eric Curtin @ 2026-03-19 20:24 UTC (permalink / raw)
To: linux-hyperv; +Cc: linux-kernel, iourit, wei.liu, decui, haiyangz
In-Reply-To: <20260319202509.63802-1-eric.curtin@docker.com>
From: Iouri Tarassov <iourit@linux.microsoft.com>
Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
[kms: forward port to 6.6 from 6.1. No code changes made.]
Signed-off-by: Kelsey Steele <kelseysteele@microsoft.com>
---
drivers/hv/dxgkrnl/dxgkrnl.h | 17 +-
drivers/hv/dxgkrnl/dxgmodule.c | 1 +
drivers/hv/dxgkrnl/dxgsyncfile.c | 13 +-
drivers/hv/dxgkrnl/dxgvmbus.c | 98 ++++-----
drivers/hv/dxgkrnl/ioctl.c | 327 +++++++++++++++----------------
5 files changed, 225 insertions(+), 231 deletions(-)
diff --git a/drivers/hv/dxgkrnl/dxgkrnl.h b/drivers/hv/dxgkrnl/dxgkrnl.h
index d92e1348ccfb..f63aa6f7a9dc 100644
--- a/drivers/hv/dxgkrnl/dxgkrnl.h
+++ b/drivers/hv/dxgkrnl/dxgkrnl.h
@@ -999,18 +999,25 @@ void dxgk_validate_ioctls(void);
trace_printk(dev_fmt(fmt) "\n", ##__VA_ARGS__); \
} while (0)
-#define DXG_ERR(fmt, ...) do { \
- dev_err(DXGDEV, fmt, ##__VA_ARGS__); \
- trace_printk("*** dxgkerror *** " dev_fmt(fmt) "\n", ##__VA_ARGS__); \
+#define DXG_ERR(fmt, ...) do { \
+ dev_err(DXGDEV, "%s: " fmt, __func__, ##__VA_ARGS__); \
+ trace_printk("*** dxgkerror *** " dev_fmt(fmt) "\n", ##__VA_ARGS__); \
} while (0)
#else
#define DXG_TRACE(...)
-#define DXG_ERR(fmt, ...) do { \
- dev_err(DXGDEV, fmt, ##__VA_ARGS__); \
+#define DXG_ERR(fmt, ...) do { \
+ dev_err(DXGDEV, "%s: " fmt, __func__, ##__VA_ARGS__); \
} while (0)
#endif /* DEBUG */
+#define DXG_TRACE_IOCTL_END(ret) do { \
+ if (ret < 0) \
+ DXG_ERR("Ioctl failed: %d", ret); \
+ else \
+ DXG_TRACE("Ioctl returned: %d", ret); \
+} while (0)
+
#endif
diff --git a/drivers/hv/dxgkrnl/dxgmodule.c b/drivers/hv/dxgkrnl/dxgmodule.c
index 5570f35954d4..aa27931a3447 100644
--- a/drivers/hv/dxgkrnl/dxgmodule.c
+++ b/drivers/hv/dxgkrnl/dxgmodule.c
@@ -961,3 +961,4 @@ module_exit(dxg_drv_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Microsoft Dxgkrnl virtual compute device Driver");
+MODULE_VERSION("2.0.0");
diff --git a/drivers/hv/dxgkrnl/dxgsyncfile.c b/drivers/hv/dxgkrnl/dxgsyncfile.c
index 9d5832c90ad7..f3b3e8dd4568 100644
--- a/drivers/hv/dxgkrnl/dxgsyncfile.c
+++ b/drivers/hv/dxgkrnl/dxgsyncfile.c
@@ -38,13 +38,6 @@
#undef dev_fmt
#define dev_fmt(fmt) "dxgk: " fmt
-#ifdef DEBUG
-static char *errorstr(int ret)
-{
- return ret < 0 ? "err" : "";
-}
-#endif
-
static const struct dma_fence_ops dxgdmafence_ops;
static struct dxgsyncpoint *to_syncpoint(struct dma_fence *fence)
@@ -193,7 +186,7 @@ int dxgkio_create_sync_file(struct dxgprocess *process, void *__user inargs)
if (fd >= 0)
put_unused_fd(fd);
}
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -317,7 +310,7 @@ int dxgkio_open_syncobj_from_syncfile(struct dxgprocess *process,
kref_put(&device->device_kref, dxgdevice_release);
}
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -415,7 +408,7 @@ int dxgkio_wait_sync_file(struct dxgprocess *process, void *__user inargs)
if (dmafence)
dma_fence_put(dmafence);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
diff --git a/drivers/hv/dxgkrnl/dxgvmbus.c b/drivers/hv/dxgkrnl/dxgvmbus.c
index 36f4d4e84d3e..566ccb6d01c9 100644
--- a/drivers/hv/dxgkrnl/dxgvmbus.c
+++ b/drivers/hv/dxgkrnl/dxgvmbus.c
@@ -1212,7 +1212,7 @@ dxgvmb_send_create_context(struct dxgadapter *adapter,
args->priv_drv_data_size);
if (ret) {
DXG_ERR("Faled to copy private data");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
}
@@ -1230,7 +1230,7 @@ dxgvmb_send_create_context(struct dxgadapter *adapter,
if (ret) {
DXG_ERR(
"Faled to copy private data to user");
- ret = -EINVAL;
+ ret = -EFAULT;
dxgvmb_send_destroy_context(adapter, process,
context);
context.v = 0;
@@ -1365,7 +1365,7 @@ copy_private_data(struct d3dkmt_createallocation *args,
args->private_runtime_data_size);
if (ret) {
DXG_ERR("failed to copy runtime data");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
private_data_dest += args->private_runtime_data_size;
@@ -1385,7 +1385,7 @@ copy_private_data(struct d3dkmt_createallocation *args,
args->priv_drv_data_size);
if (ret) {
DXG_ERR("failed to copy private data");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
private_data_dest += args->priv_drv_data_size;
@@ -1406,7 +1406,7 @@ copy_private_data(struct d3dkmt_createallocation *args,
input_alloc->priv_drv_data_size);
if (ret) {
DXG_ERR("failed to copy alloc data");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
private_data_dest += input_alloc->priv_drv_data_size;
@@ -1658,7 +1658,7 @@ create_local_allocations(struct dxgprocess *process,
sizeof(struct d3dkmthandle));
if (ret) {
DXG_ERR("failed to copy resource handle");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
}
@@ -1690,7 +1690,7 @@ create_local_allocations(struct dxgprocess *process,
host_alloc->priv_drv_data_size);
if (ret) {
DXG_ERR("failed to copy private data");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
alloc_private_data += host_alloc->priv_drv_data_size;
@@ -1700,7 +1700,7 @@ create_local_allocations(struct dxgprocess *process,
sizeof(struct d3dkmthandle));
if (ret) {
DXG_ERR("failed to copy alloc handle");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
}
@@ -1714,7 +1714,7 @@ create_local_allocations(struct dxgprocess *process,
sizeof(struct d3dkmthandle));
if (ret) {
DXG_ERR("failed to copy global share");
- ret = -EINVAL;
+ ret = -EFAULT;
}
cleanup:
@@ -1961,7 +1961,7 @@ int dxgvmb_send_query_clock_calibration(struct dxgprocess *process,
sizeof(result.clock_data));
if (ret) {
DXG_ERR("failed to copy clock data");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
ret = ntstatus2int(result.status);
@@ -2041,7 +2041,7 @@ int dxgvmb_send_query_alloc_residency(struct dxgprocess *process,
alloc_size);
if (ret) {
DXG_ERR("failed to copy alloc handles");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
}
@@ -2059,7 +2059,7 @@ int dxgvmb_send_query_alloc_residency(struct dxgprocess *process,
result_allocation_size);
if (ret) {
DXG_ERR("failed to copy residency status");
- ret = -EINVAL;
+ ret = -EFAULT;
}
cleanup:
@@ -2105,7 +2105,7 @@ int dxgvmb_send_escape(struct dxgprocess *process,
args->priv_drv_data_size);
if (ret) {
DXG_ERR("failed to copy priv data");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
}
@@ -2164,14 +2164,14 @@ int dxgvmb_send_query_vidmem_info(struct dxgprocess *process,
sizeof(output->budget));
if (ret) {
DXG_ERR("failed to copy budget");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
ret = copy_to_user(&output->current_usage, &result.current_usage,
sizeof(output->current_usage));
if (ret) {
DXG_ERR("failed to copy current usage");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
ret = copy_to_user(&output->current_reservation,
@@ -2179,7 +2179,7 @@ int dxgvmb_send_query_vidmem_info(struct dxgprocess *process,
sizeof(output->current_reservation));
if (ret) {
DXG_ERR("failed to copy reservation");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
ret = copy_to_user(&output->available_for_reservation,
@@ -2187,7 +2187,7 @@ int dxgvmb_send_query_vidmem_info(struct dxgprocess *process,
sizeof(output->available_for_reservation));
if (ret) {
DXG_ERR("failed to copy avail reservation");
- ret = -EINVAL;
+ ret = -EFAULT;
}
cleanup:
@@ -2229,7 +2229,7 @@ int dxgvmb_send_get_device_state(struct dxgprocess *process,
ret = copy_to_user(output, &result.args, sizeof(result.args));
if (ret) {
DXG_ERR("failed to copy output args");
- ret = -EINVAL;
+ ret = -EFAULT;
}
if (args->state_type == _D3DKMT_DEVICESTATE_EXECUTION)
@@ -2404,7 +2404,7 @@ int dxgvmb_send_make_resident(struct dxgprocess *process,
sizeof(struct d3dkmthandle));
if (ret) {
DXG_ERR("failed to copy alloc handles");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
command_vgpu_to_host_init2(&command->hdr,
@@ -2454,7 +2454,7 @@ int dxgvmb_send_evict(struct dxgprocess *process,
sizeof(struct d3dkmthandle));
if (ret) {
DXG_ERR("failed to copy alloc handles");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
command_vgpu_to_host_init2(&command->hdr,
@@ -2502,14 +2502,14 @@ int dxgvmb_send_submit_command(struct dxgprocess *process,
hbufsize);
if (ret) {
DXG_ERR(" failed to copy history buffer");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
ret = copy_from_user((u8 *) &command[1] + hbufsize,
args->priv_drv_data, args->priv_drv_data_size);
if (ret) {
DXG_ERR("failed to copy history priv data");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -2671,7 +2671,7 @@ int dxgvmb_send_update_gpu_va(struct dxgprocess *process,
op_size);
if (ret) {
DXG_ERR("failed to copy operations");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -2751,7 +2751,7 @@ dxgvmb_send_create_sync_object(struct dxgprocess *process,
sizeof(u64));
if (ret) {
DXG_ERR("failed to read fence");
- ret = -EINVAL;
+ ret = -EFAULT;
} else {
DXG_TRACE("fence value:%lx",
value);
@@ -2820,7 +2820,7 @@ int dxgvmb_send_signal_sync_object(struct dxgprocess *process,
if (ret) {
DXG_ERR("Failed to read objects %p %d",
objects, object_size);
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
current_pos += object_size;
@@ -2834,7 +2834,7 @@ int dxgvmb_send_signal_sync_object(struct dxgprocess *process,
if (ret) {
DXG_ERR("Failed to read contexts %p %d",
contexts, context_size);
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
current_pos += context_size;
@@ -2844,7 +2844,7 @@ int dxgvmb_send_signal_sync_object(struct dxgprocess *process,
if (ret) {
DXG_ERR("Failed to read fences %p %d",
fences, fence_size);
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
}
@@ -2898,7 +2898,7 @@ int dxgvmb_send_wait_sync_object_cpu(struct dxgprocess *process,
ret = copy_from_user(current_pos, args->objects, object_size);
if (ret) {
DXG_ERR("failed to copy objects");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
current_pos += object_size;
@@ -2906,7 +2906,7 @@ int dxgvmb_send_wait_sync_object_cpu(struct dxgprocess *process,
fence_size);
if (ret) {
DXG_ERR("failed to copy fences");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
} else {
@@ -3037,7 +3037,7 @@ int dxgvmb_send_lock2(struct dxgprocess *process,
sizeof(args->data));
if (ret) {
DXG_ERR("failed to copy data");
- ret = -EINVAL;
+ ret = -EFAULT;
alloc->cpu_address_refcount--;
if (alloc->cpu_address_refcount == 0) {
dxg_unmap_iospace(alloc->cpu_address,
@@ -3119,7 +3119,7 @@ int dxgvmb_send_update_alloc_property(struct dxgprocess *process,
sizeof(u64));
if (ret1) {
DXG_ERR("failed to copy paging fence");
- ret = -EINVAL;
+ ret = -EFAULT;
}
}
cleanup:
@@ -3204,14 +3204,14 @@ int dxgvmb_send_set_allocation_priority(struct dxgprocess *process,
alloc_size);
if (ret) {
DXG_ERR("failed to copy alloc handle");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
ret = copy_from_user((u8 *) allocations + alloc_size,
args->priorities, priority_size);
if (ret) {
DXG_ERR("failed to copy alloc priority");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -3277,7 +3277,7 @@ int dxgvmb_send_get_allocation_priority(struct dxgprocess *process,
alloc_size);
if (ret) {
DXG_ERR("failed to copy alloc handles");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -3296,7 +3296,7 @@ int dxgvmb_send_get_allocation_priority(struct dxgprocess *process,
priority_size);
if (ret) {
DXG_ERR("failed to copy priorities");
- ret = -EINVAL;
+ ret = -EFAULT;
}
cleanup:
@@ -3402,7 +3402,7 @@ int dxgvmb_send_offer_allocations(struct dxgprocess *process,
}
if (ret) {
DXG_ERR("failed to copy input handles");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -3457,7 +3457,7 @@ int dxgvmb_send_reclaim_allocations(struct dxgprocess *process,
}
if (ret) {
DXG_ERR("failed to copy input handles");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -3469,7 +3469,7 @@ int dxgvmb_send_reclaim_allocations(struct dxgprocess *process,
&result->paging_fence_value, sizeof(u64));
if (ret) {
DXG_ERR("failed to copy paging fence");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -3480,7 +3480,7 @@ int dxgvmb_send_reclaim_allocations(struct dxgprocess *process,
args->allocation_count);
if (ret) {
DXG_ERR("failed to copy results");
- ret = -EINVAL;
+ ret = -EFAULT;
}
}
@@ -3559,7 +3559,7 @@ int dxgvmb_send_create_hwqueue(struct dxgprocess *process,
args->priv_drv_data_size);
if (ret) {
DXG_ERR("failed to copy private data");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
}
@@ -3604,7 +3604,7 @@ int dxgvmb_send_create_hwqueue(struct dxgprocess *process,
sizeof(struct d3dkmthandle));
if (ret) {
DXG_ERR("failed to copy hwqueue handle");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
ret = copy_to_user(&inargs->queue_progress_fence,
@@ -3612,7 +3612,7 @@ int dxgvmb_send_create_hwqueue(struct dxgprocess *process,
sizeof(struct d3dkmthandle));
if (ret) {
DXG_ERR("failed to progress fence");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
ret = copy_to_user(&inargs->queue_progress_fence_cpu_va,
@@ -3620,7 +3620,7 @@ int dxgvmb_send_create_hwqueue(struct dxgprocess *process,
sizeof(inargs->queue_progress_fence_cpu_va));
if (ret) {
DXG_ERR("failed to copy fence cpu va");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
ret = copy_to_user(&inargs->queue_progress_fence_gpu_va,
@@ -3628,7 +3628,7 @@ int dxgvmb_send_create_hwqueue(struct dxgprocess *process,
sizeof(u64));
if (ret) {
DXG_ERR("failed to copy fence gpu va");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
if (args->priv_drv_data_size) {
@@ -3637,7 +3637,7 @@ int dxgvmb_send_create_hwqueue(struct dxgprocess *process,
args->priv_drv_data_size);
if (ret) {
DXG_ERR("failed to copy private data");
- ret = -EINVAL;
+ ret = -EFAULT;
}
}
@@ -3706,7 +3706,7 @@ int dxgvmb_send_query_adapter_info(struct dxgprocess *process,
args->private_data, args->private_data_size);
if (ret) {
DXG_ERR("Faled to copy private data");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -3758,7 +3758,7 @@ int dxgvmb_send_query_adapter_info(struct dxgprocess *process,
args->private_data_size);
if (ret) {
DXG_ERR("Faled to copy private data to user");
- ret = -EINVAL;
+ ret = -EFAULT;
}
cleanup:
@@ -3791,7 +3791,7 @@ int dxgvmb_send_submit_command_hwqueue(struct dxgprocess *process,
primaries_size);
if (ret) {
DXG_ERR("failed to copy primaries handles");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
}
@@ -3801,7 +3801,7 @@ int dxgvmb_send_submit_command_hwqueue(struct dxgprocess *process,
args->priv_drv_data_size);
if (ret) {
DXG_ERR("failed to copy primaries data");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
}
diff --git a/drivers/hv/dxgkrnl/ioctl.c b/drivers/hv/dxgkrnl/ioctl.c
index 622904d5c3a9..3dc9e76f4f3d 100644
--- a/drivers/hv/dxgkrnl/ioctl.c
+++ b/drivers/hv/dxgkrnl/ioctl.c
@@ -29,13 +29,6 @@ struct ioctl_desc {
u32 ioctl;
};
-#ifdef DEBUG
-static char *errorstr(int ret)
-{
- return ret < 0 ? "err" : "";
-}
-#endif
-
void dxgsharedsyncobj_put(struct dxgsharedsyncobject *syncobj)
{
DXG_TRACE("Release syncobj: %p", syncobj);
@@ -108,7 +101,7 @@ static int dxgkio_open_adapter_from_luid(struct dxgprocess *process,
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("Faled to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -129,7 +122,7 @@ static int dxgkio_open_adapter_from_luid(struct dxgprocess *process,
&args.adapter_handle,
sizeof(struct d3dkmthandle));
if (ret)
- ret = -EINVAL;
+ ret = -EFAULT;
}
adapter = entry;
}
@@ -150,7 +143,7 @@ static int dxgkio_open_adapter_from_luid(struct dxgprocess *process,
if (ret < 0)
dxgprocess_close_adapter(process, args.adapter_handle);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -173,7 +166,7 @@ static int dxgkio_query_statistics(struct dxgprocess *process,
ret = copy_from_user(args, inargs, sizeof(*args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -199,7 +192,7 @@ static int dxgkio_query_statistics(struct dxgprocess *process,
ret = copy_to_user(inargs, args, sizeof(*args));
if (ret) {
DXG_ERR("failed to copy args");
- ret = -EINVAL;
+ ret = -EFAULT;
}
}
dxgadapter_release_lock_shared(adapter);
@@ -209,7 +202,7 @@ static int dxgkio_query_statistics(struct dxgprocess *process,
if (args)
vfree(args);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -233,7 +226,7 @@ dxgkp_enum_adapters(struct dxgprocess *process,
&dxgglobal->num_adapters, sizeof(u32));
if (ret) {
DXG_ERR("copy_to_user faled");
- ret = -EINVAL;
+ ret = -EFAULT;
}
goto cleanup;
}
@@ -291,7 +284,7 @@ dxgkp_enum_adapters(struct dxgprocess *process,
&dxgglobal->num_adapters, sizeof(u32));
if (ret) {
DXG_ERR("copy_to_user failed");
- ret = -EINVAL;
+ ret = -EFAULT;
}
goto cleanup;
}
@@ -300,13 +293,13 @@ dxgkp_enum_adapters(struct dxgprocess *process,
sizeof(adapter_count));
if (ret) {
DXG_ERR("failed to copy adapter_count");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
ret = copy_to_user(info_out, info, sizeof(info[0]) * adapter_count);
if (ret) {
DXG_ERR("failed to copy adapter info");
- ret = -EINVAL;
+ ret = -EFAULT;
}
cleanup:
@@ -326,7 +319,7 @@ dxgkp_enum_adapters(struct dxgprocess *process,
if (adapters)
vfree(adapters);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -437,7 +430,7 @@ dxgkio_enum_adapters(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -447,7 +440,7 @@ dxgkio_enum_adapters(struct dxgprocess *process, void *__user inargs)
ret = copy_to_user(inargs, &args, sizeof(args));
if (ret) {
DXG_ERR("failed to copy args to user");
- ret = -EINVAL;
+ ret = -EFAULT;
}
goto cleanup;
}
@@ -508,14 +501,14 @@ dxgkio_enum_adapters(struct dxgprocess *process, void *__user inargs)
ret = copy_to_user(inargs, &args, sizeof(args));
if (ret) {
DXG_ERR("failed to copy args to user");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
ret = copy_to_user(args.adapters, info,
sizeof(info[0]) * args.num_adapters);
if (ret) {
DXG_ERR("failed to copy adapter info to user");
- ret = -EINVAL;
+ ret = -EFAULT;
}
cleanup:
@@ -536,7 +529,7 @@ dxgkio_enum_adapters(struct dxgprocess *process, void *__user inargs)
if (adapters)
vfree(adapters);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -549,7 +542,7 @@ dxgkio_enum_adapters3(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -561,7 +554,7 @@ dxgkio_enum_adapters3(struct dxgprocess *process, void *__user inargs)
cleanup:
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -574,7 +567,7 @@ dxgkio_close_adapter(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -584,7 +577,7 @@ dxgkio_close_adapter(struct dxgprocess *process, void *__user inargs)
cleanup:
- DXG_TRACE("ioctl: %s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -598,7 +591,7 @@ dxgkio_query_adapter_info(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -630,7 +623,7 @@ dxgkio_query_adapter_info(struct dxgprocess *process, void *__user inargs)
if (adapter)
kref_put(&adapter->adapter_kref, dxgadapter_release);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -647,7 +640,7 @@ dxgkio_create_device(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -677,7 +670,7 @@ dxgkio_create_device(struct dxgprocess *process, void *__user inargs)
sizeof(struct d3dkmthandle));
if (ret) {
DXG_ERR("failed to copy device handle");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -709,7 +702,7 @@ dxgkio_create_device(struct dxgprocess *process, void *__user inargs)
if (adapter)
kref_put(&adapter->adapter_kref, dxgadapter_release);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -724,7 +717,7 @@ dxgkio_destroy_device(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -756,7 +749,7 @@ dxgkio_destroy_device(struct dxgprocess *process, void *__user inargs)
cleanup:
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -774,7 +767,7 @@ dxgkio_create_context_virtual(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -824,7 +817,7 @@ dxgkio_create_context_virtual(struct dxgprocess *process, void *__user inargs)
sizeof(struct d3dkmthandle));
if (ret) {
DXG_ERR("failed to copy context handle");
- ret = -EINVAL;
+ ret = -EFAULT;
}
} else {
DXG_ERR("invalid host handle");
@@ -851,7 +844,7 @@ dxgkio_create_context_virtual(struct dxgprocess *process, void *__user inargs)
kref_put(&device->device_kref, dxgdevice_release);
}
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -868,7 +861,7 @@ dxgkio_destroy_context(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -920,7 +913,7 @@ dxgkio_destroy_context(struct dxgprocess *process, void *__user inargs)
if (device)
kref_put(&device->device_kref, dxgdevice_release);
- DXG_TRACE("ioctl:%s %s %d", errorstr(ret), __func__, ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -938,7 +931,7 @@ dxgkio_create_hwqueue(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -1002,7 +995,7 @@ dxgkio_create_hwqueue(struct dxgprocess *process, void *__user inargs)
if (device)
kref_put(&device->device_kref, dxgdevice_release);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -1019,7 +1012,7 @@ static int dxgkio_destroy_hwqueue(struct dxgprocess *process,
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -1070,7 +1063,7 @@ static int dxgkio_destroy_hwqueue(struct dxgprocess *process,
if (device)
kref_put(&device->device_kref, dxgdevice_release);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -1088,7 +1081,7 @@ dxgkio_create_paging_queue(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -1128,7 +1121,7 @@ dxgkio_create_paging_queue(struct dxgprocess *process, void *__user inargs)
ret = copy_to_user(inargs, &args, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -1169,7 +1162,7 @@ dxgkio_create_paging_queue(struct dxgprocess *process, void *__user inargs)
kref_put(&device->device_kref, dxgdevice_release);
}
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -1186,7 +1179,7 @@ dxgkio_destroy_paging_queue(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -1247,7 +1240,7 @@ dxgkio_destroy_paging_queue(struct dxgprocess *process, void *__user inargs)
kref_put(&device->device_kref, dxgdevice_release);
}
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -1351,7 +1344,7 @@ dxgkio_create_allocation(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -1373,7 +1366,7 @@ dxgkio_create_allocation(struct dxgprocess *process, void *__user inargs)
alloc_info_size);
if (ret) {
DXG_ERR("failed to copy alloc info");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -1412,7 +1405,7 @@ dxgkio_create_allocation(struct dxgprocess *process, void *__user inargs)
sizeof(standard_alloc));
if (ret) {
DXG_ERR("failed to copy std alloc data");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
if (standard_alloc.type ==
@@ -1556,7 +1549,7 @@ dxgkio_create_allocation(struct dxgprocess *process, void *__user inargs)
if (ret) {
DXG_ERR(
"failed to copy runtime data");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
}
@@ -1576,7 +1569,7 @@ dxgkio_create_allocation(struct dxgprocess *process, void *__user inargs)
if (ret) {
DXG_ERR(
"failed to copy res data");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
}
@@ -1733,7 +1726,7 @@ dxgkio_create_allocation(struct dxgprocess *process, void *__user inargs)
kref_put(&device->device_kref, dxgdevice_release);
}
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -1793,7 +1786,7 @@ dxgkio_destroy_allocation(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -1823,7 +1816,7 @@ dxgkio_destroy_allocation(struct dxgprocess *process, void *__user inargs)
handle_size);
if (ret) {
DXG_ERR("failed to copy alloc handles");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
}
@@ -1962,7 +1955,7 @@ dxgkio_destroy_allocation(struct dxgprocess *process, void *__user inargs)
if (allocs)
vfree(allocs);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -1978,7 +1971,7 @@ dxgkio_make_resident(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -2022,7 +2015,7 @@ dxgkio_make_resident(struct dxgprocess *process, void *__user inargs)
&args.paging_fence_value, sizeof(u64));
if (ret2) {
DXG_ERR("failed to copy paging fence");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -2030,7 +2023,7 @@ dxgkio_make_resident(struct dxgprocess *process, void *__user inargs)
&args.num_bytes_to_trim, sizeof(u64));
if (ret2) {
DXG_ERR("failed to copy bytes to trim");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -2041,7 +2034,7 @@ dxgkio_make_resident(struct dxgprocess *process, void *__user inargs)
if (device)
kref_put(&device->device_kref, dxgdevice_release);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -2058,7 +2051,7 @@ dxgkio_evict(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -2090,7 +2083,7 @@ dxgkio_evict(struct dxgprocess *process, void *__user inargs)
&args.num_bytes_to_trim, sizeof(u64));
if (ret) {
DXG_ERR("failed to copy bytes to trim to user");
- ret = -EINVAL;
+ ret = -EFAULT;
}
cleanup:
@@ -2099,7 +2092,7 @@ dxgkio_evict(struct dxgprocess *process, void *__user inargs)
if (device)
kref_put(&device->device_kref, dxgdevice_release);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -2114,7 +2107,7 @@ dxgkio_offer_allocations(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -2153,7 +2146,7 @@ dxgkio_offer_allocations(struct dxgprocess *process, void *__user inargs)
if (device)
kref_put(&device->device_kref, dxgdevice_release);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -2169,7 +2162,7 @@ dxgkio_reclaim_allocations(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -2212,7 +2205,7 @@ dxgkio_reclaim_allocations(struct dxgprocess *process, void *__user inargs)
if (device)
kref_put(&device->device_kref, dxgdevice_release);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -2227,7 +2220,7 @@ dxgkio_submit_command(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -2280,7 +2273,7 @@ dxgkio_submit_command(struct dxgprocess *process, void *__user inargs)
if (device)
kref_put(&device->device_kref, dxgdevice_release);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -2296,7 +2289,7 @@ dxgkio_submit_command_to_hwqueue(struct dxgprocess *process,
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -2336,7 +2329,7 @@ dxgkio_submit_command_to_hwqueue(struct dxgprocess *process,
if (device)
kref_put(&device->device_kref, dxgdevice_release);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -2352,7 +2345,7 @@ dxgkio_submit_signal_to_hwqueue(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -2376,7 +2369,7 @@ dxgkio_submit_signal_to_hwqueue(struct dxgprocess *process, void *__user inargs)
sizeof(struct d3dkmthandle));
if (ret) {
DXG_ERR("failed to copy hwqueue handle");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -2410,7 +2403,7 @@ dxgkio_submit_signal_to_hwqueue(struct dxgprocess *process, void *__user inargs)
if (device)
kref_put(&device->device_kref, dxgdevice_release);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -2428,7 +2421,7 @@ dxgkio_submit_wait_to_hwqueue(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -2447,7 +2440,7 @@ dxgkio_submit_wait_to_hwqueue(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(objects, args.objects, object_size);
if (ret) {
DXG_ERR("failed to copy objects");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -2460,7 +2453,7 @@ dxgkio_submit_wait_to_hwqueue(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(fences, args.fence_values, object_size);
if (ret) {
DXG_ERR("failed to copy fence values");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -2494,7 +2487,7 @@ dxgkio_submit_wait_to_hwqueue(struct dxgprocess *process, void *__user inargs)
if (device)
kref_put(&device->device_kref, dxgdevice_release);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -2510,7 +2503,7 @@ dxgkio_map_gpu_va(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -2542,7 +2535,7 @@ dxgkio_map_gpu_va(struct dxgprocess *process, void *__user inargs)
&args.paging_fence_value, sizeof(u64));
if (ret2) {
DXG_ERR("failed to copy paging fence to user");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -2550,7 +2543,7 @@ dxgkio_map_gpu_va(struct dxgprocess *process, void *__user inargs)
sizeof(args.virtual_address));
if (ret2) {
DXG_ERR("failed to copy va to user");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -2561,7 +2554,7 @@ dxgkio_map_gpu_va(struct dxgprocess *process, void *__user inargs)
if (device)
kref_put(&device->device_kref, dxgdevice_release);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -2577,7 +2570,7 @@ dxgkio_reserve_gpu_va(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -2614,7 +2607,7 @@ dxgkio_reserve_gpu_va(struct dxgprocess *process, void *__user inargs)
sizeof(args.virtual_address));
if (ret) {
DXG_ERR("failed to copy VA to user");
- ret = -EINVAL;
+ ret = -EFAULT;
}
cleanup:
@@ -2624,7 +2617,7 @@ dxgkio_reserve_gpu_va(struct dxgprocess *process, void *__user inargs)
kref_put(&adapter->adapter_kref, dxgadapter_release);
}
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -2638,7 +2631,7 @@ dxgkio_free_gpu_va(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -2680,7 +2673,7 @@ dxgkio_update_gpu_va(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -2705,7 +2698,7 @@ dxgkio_update_gpu_va(struct dxgprocess *process, void *__user inargs)
sizeof(args.fence_value));
if (ret) {
DXG_ERR("failed to copy fence value to user");
- ret = -EINVAL;
+ ret = -EFAULT;
}
cleanup:
@@ -2734,7 +2727,7 @@ dxgkio_create_sync_object(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -2808,7 +2801,7 @@ dxgkio_create_sync_object(struct dxgprocess *process, void *__user inargs)
ret = copy_to_user(inargs, &args, sizeof(args));
if (ret) {
DXG_ERR("failed to copy output args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -2842,7 +2835,7 @@ dxgkio_create_sync_object(struct dxgprocess *process, void *__user inargs)
if (device)
kref_put(&device->device_kref, dxgdevice_release);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -2856,7 +2849,7 @@ dxgkio_destroy_sync_object(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -2885,7 +2878,7 @@ dxgkio_destroy_sync_object(struct dxgprocess *process, void *__user inargs)
cleanup:
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -2906,7 +2899,7 @@ dxgkio_open_sync_object_nt(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -2995,7 +2988,7 @@ dxgkio_open_sync_object_nt(struct dxgprocess *process, void *__user inargs)
if (ret == 0)
goto success;
DXG_ERR("failed to copy output args");
- ret = -EINVAL;
+ ret = -EFAULT;
cleanup:
@@ -3020,7 +3013,7 @@ dxgkio_open_sync_object_nt(struct dxgprocess *process, void *__user inargs)
if (device)
kref_put(&device->device_kref, dxgdevice_release);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -3041,7 +3034,7 @@ dxgkio_signal_sync_object(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -3129,7 +3122,7 @@ dxgkio_signal_sync_object(struct dxgprocess *process, void *__user inargs)
if (device)
kref_put(&device->device_kref, dxgdevice_release);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -3144,7 +3137,7 @@ dxgkio_signal_sync_object_cpu(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
if (args.object_count == 0 ||
@@ -3181,7 +3174,7 @@ dxgkio_signal_sync_object_cpu(struct dxgprocess *process, void *__user inargs)
if (device)
kref_put(&device->device_kref, dxgdevice_release);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -3199,7 +3192,7 @@ dxgkio_signal_sync_object_gpu(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -3240,7 +3233,7 @@ dxgkio_signal_sync_object_gpu(struct dxgprocess *process, void *__user inargs)
if (device)
kref_put(&device->device_kref, dxgdevice_release);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -3262,7 +3255,7 @@ dxgkio_signal_sync_object_gpu2(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -3287,7 +3280,7 @@ dxgkio_signal_sync_object_gpu2(struct dxgprocess *process, void *__user inargs)
sizeof(struct d3dkmthandle));
if (ret) {
DXG_ERR("failed to copy context handle");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -3365,7 +3358,7 @@ dxgkio_signal_sync_object_gpu2(struct dxgprocess *process, void *__user inargs)
if (device)
kref_put(&device->device_kref, dxgdevice_release);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -3380,7 +3373,7 @@ dxgkio_wait_sync_object(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -3418,7 +3411,7 @@ dxgkio_wait_sync_object(struct dxgprocess *process, void *__user inargs)
if (device)
kref_put(&device->device_kref, dxgdevice_release);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -3439,7 +3432,7 @@ dxgkio_wait_sync_object_cpu(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -3540,7 +3533,7 @@ dxgkio_wait_sync_object_cpu(struct dxgprocess *process, void *__user inargs)
kfree(async_host_event);
}
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -3563,7 +3556,7 @@ dxgkio_wait_sync_object_gpu(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -3583,7 +3576,7 @@ dxgkio_wait_sync_object_gpu(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(objects, args.objects, object_size);
if (ret) {
DXG_ERR("failed to copy objects");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -3637,7 +3630,7 @@ dxgkio_wait_sync_object_gpu(struct dxgprocess *process, void *__user inargs)
object_size);
if (ret) {
DXG_ERR("failed to copy fences");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
} else {
@@ -3673,7 +3666,7 @@ dxgkio_wait_sync_object_gpu(struct dxgprocess *process, void *__user inargs)
if (fences && fences != &args.fence_value)
vfree(fences);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -3690,7 +3683,7 @@ dxgkio_lock2(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -3712,7 +3705,7 @@ dxgkio_lock2(struct dxgprocess *process, void *__user inargs)
alloc->cpu_address_refcount++;
} else {
DXG_ERR("Failed to copy cpu address");
- ret = -EINVAL;
+ ret = -EFAULT;
}
}
}
@@ -3749,7 +3742,7 @@ dxgkio_lock2(struct dxgprocess *process, void *__user inargs)
kref_put(&device->device_kref, dxgdevice_release);
success:
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -3766,7 +3759,7 @@ dxgkio_unlock2(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -3829,7 +3822,7 @@ dxgkio_unlock2(struct dxgprocess *process, void *__user inargs)
kref_put(&device->device_kref, dxgdevice_release);
success:
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -3844,7 +3837,7 @@ dxgkio_update_alloc_property(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -3872,7 +3865,7 @@ dxgkio_update_alloc_property(struct dxgprocess *process, void *__user inargs)
if (device)
kref_put(&device->device_kref, dxgdevice_release);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -3887,7 +3880,7 @@ dxgkio_mark_device_as_error(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
device = dxgprocess_device_by_handle(process, args.device);
@@ -3908,7 +3901,7 @@ dxgkio_mark_device_as_error(struct dxgprocess *process, void *__user inargs)
dxgadapter_release_lock_shared(adapter);
if (device)
kref_put(&device->device_kref, dxgdevice_release);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -3923,7 +3916,7 @@ dxgkio_query_alloc_residency(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -3949,7 +3942,7 @@ dxgkio_query_alloc_residency(struct dxgprocess *process, void *__user inargs)
dxgadapter_release_lock_shared(adapter);
if (device)
kref_put(&device->device_kref, dxgdevice_release);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -3964,7 +3957,7 @@ dxgkio_set_allocation_priority(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
device = dxgprocess_device_by_handle(process, args.device);
@@ -3984,7 +3977,7 @@ dxgkio_set_allocation_priority(struct dxgprocess *process, void *__user inargs)
dxgadapter_release_lock_shared(adapter);
if (device)
kref_put(&device->device_kref, dxgdevice_release);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -3999,7 +3992,7 @@ dxgkio_get_allocation_priority(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
device = dxgprocess_device_by_handle(process, args.device);
@@ -4019,7 +4012,7 @@ dxgkio_get_allocation_priority(struct dxgprocess *process, void *__user inargs)
dxgadapter_release_lock_shared(adapter);
if (device)
kref_put(&device->device_kref, dxgdevice_release);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -4069,14 +4062,14 @@ dxgkio_set_context_scheduling_priority(struct dxgprocess *process,
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
ret = set_context_scheduling_priority(process, args.context,
args.priority, false);
cleanup:
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -4111,7 +4104,7 @@ get_context_scheduling_priority(struct dxgprocess *process,
ret = copy_to_user(priority, &pri, sizeof(pri));
if (ret) {
DXG_ERR("failed to copy priority to user");
- ret = -EINVAL;
+ ret = -EFAULT;
}
cleanup:
@@ -4134,14 +4127,14 @@ dxgkio_get_context_scheduling_priority(struct dxgprocess *process,
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
ret = get_context_scheduling_priority(process, args.context,
&input->priority, false);
cleanup:
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -4155,14 +4148,14 @@ dxgkio_set_context_process_scheduling_priority(struct dxgprocess *process,
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
ret = set_context_scheduling_priority(process, args.context,
args.priority, true);
cleanup:
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -4176,7 +4169,7 @@ dxgkio_get_context_process_scheduling_priority(struct dxgprocess *process,
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -4184,7 +4177,7 @@ dxgkio_get_context_process_scheduling_priority(struct dxgprocess *process,
&((struct d3dkmt_getcontextinprocessschedulingpriority *)
inargs)->priority, true);
cleanup:
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -4199,7 +4192,7 @@ dxgkio_change_vidmem_reservation(struct dxgprocess *process, void *__user inargs
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -4232,7 +4225,7 @@ dxgkio_change_vidmem_reservation(struct dxgprocess *process, void *__user inargs
if (adapter)
kref_put(&adapter->adapter_kref, dxgadapter_release);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -4247,7 +4240,7 @@ dxgkio_query_clock_calibration(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -4272,7 +4265,7 @@ dxgkio_query_clock_calibration(struct dxgprocess *process, void *__user inargs)
ret = copy_to_user(inargs, &args, sizeof(args));
if (ret) {
DXG_ERR("failed to copy output args");
- ret = -EINVAL;
+ ret = -EFAULT;
}
cleanup:
@@ -4295,7 +4288,7 @@ dxgkio_flush_heap_transitions(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -4319,7 +4312,7 @@ dxgkio_flush_heap_transitions(struct dxgprocess *process, void *__user inargs)
ret = copy_to_user(inargs, &args, sizeof(args));
if (ret) {
DXG_ERR("failed to copy output args");
- ret = -EINVAL;
+ ret = -EFAULT;
}
cleanup:
@@ -4341,7 +4334,7 @@ dxgkio_escape(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -4367,7 +4360,7 @@ dxgkio_escape(struct dxgprocess *process, void *__user inargs)
dxgadapter_release_lock_shared(adapter);
if (adapter)
kref_put(&adapter->adapter_kref, dxgadapter_release);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -4382,7 +4375,7 @@ dxgkio_query_vidmem_info(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -4432,7 +4425,7 @@ dxgkio_get_device_state(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -4458,7 +4451,7 @@ dxgkio_get_device_state(struct dxgprocess *process, void *__user inargs)
ret = copy_to_user(inargs, &args, sizeof(args));
if (ret) {
DXG_ERR("failed to copy args to user");
- ret = -EINVAL;
+ ret = -EFAULT;
}
goto cleanup;
}
@@ -4590,7 +4583,7 @@ dxgkio_share_objects(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -4610,7 +4603,7 @@ dxgkio_share_objects(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(handles, args.objects, handle_size);
if (ret) {
DXG_ERR("failed to copy object handles");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -4708,7 +4701,7 @@ dxgkio_share_objects(struct dxgprocess *process, void *__user inargs)
ret = copy_to_user(args.shared_handle, &tmp, sizeof(u64));
if (ret) {
DXG_ERR("failed to copy shared handle");
- ret = -EINVAL;
+ ret = -EFAULT;
}
cleanup:
@@ -4726,7 +4719,7 @@ dxgkio_share_objects(struct dxgprocess *process, void *__user inargs)
if (resource)
kref_put(&resource->resource_kref, dxgresource_release);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -4742,7 +4735,7 @@ dxgkio_query_resource_info_nt(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -4795,7 +4788,7 @@ dxgkio_query_resource_info_nt(struct dxgprocess *process, void *__user inargs)
ret = copy_to_user(inargs, &args, sizeof(args));
if (ret) {
DXG_ERR("failed to copy output args");
- ret = -EINVAL;
+ ret = -EFAULT;
}
cleanup:
@@ -4807,7 +4800,7 @@ dxgkio_query_resource_info_nt(struct dxgprocess *process, void *__user inargs)
if (device)
kref_put(&device->device_kref, dxgdevice_release);
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -4859,7 +4852,7 @@ assign_resource_handles(struct dxgprocess *process,
sizeof(open_alloc_info));
if (ret) {
DXG_ERR("failed to copy alloc info");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
}
@@ -5009,7 +5002,7 @@ open_resource(struct dxgprocess *process,
shared_resource->runtime_private_data_size);
if (ret) {
DXG_ERR("failed to copy runtime data");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
}
@@ -5020,7 +5013,7 @@ open_resource(struct dxgprocess *process,
shared_resource->resource_private_data_size);
if (ret) {
DXG_ERR("failed to copy resource data");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
}
@@ -5031,7 +5024,7 @@ open_resource(struct dxgprocess *process,
shared_resource->alloc_private_data_size);
if (ret) {
DXG_ERR("failed to copy alloc data");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
}
@@ -5046,7 +5039,7 @@ open_resource(struct dxgprocess *process,
sizeof(struct d3dkmthandle));
if (ret) {
DXG_ERR("failed to copy resource handle to user");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -5054,7 +5047,7 @@ open_resource(struct dxgprocess *process,
&args->total_priv_drv_data_size, sizeof(u32));
if (ret) {
DXG_ERR("failed to copy total driver data size");
- ret = -EINVAL;
+ ret = -EFAULT;
}
cleanup:
@@ -5102,7 +5095,7 @@ dxgkio_open_resource_nt(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -5112,7 +5105,7 @@ dxgkio_open_resource_nt(struct dxgprocess *process, void *__user inargs)
cleanup:
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
@@ -5125,7 +5118,7 @@ dxgkio_share_object_with_host(struct dxgprocess *process, void *__user inargs)
ret = copy_from_user(&args, inargs, sizeof(args));
if (ret) {
DXG_ERR("failed to copy input args");
- ret = -EINVAL;
+ ret = -EFAULT;
goto cleanup;
}
@@ -5138,12 +5131,12 @@ dxgkio_share_object_with_host(struct dxgprocess *process, void *__user inargs)
ret = copy_to_user(inargs, &args, sizeof(args));
if (ret) {
DXG_ERR("failed to copy data to user");
- ret = -EINVAL;
+ ret = -EFAULT;
}
cleanup:
- DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ DXG_TRACE_IOCTL_END(ret);
return ret;
}
^ permalink raw reply related
* [PATCH 33/55] drivers: hv: dxgkrnl: Implement D3DKMTWaitSyncFile
From: Eric Curtin @ 2026-03-19 20:24 UTC (permalink / raw)
To: linux-hyperv; +Cc: linux-kernel, iourit, wei.liu, decui, haiyangz
In-Reply-To: <20260319202509.63802-1-eric.curtin@docker.com>
From: Iouri Tarassov <iourit@linux.microsoft.com>
Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
[kms: forward port to 6.6 from 6.1. No code changes made.]
Signed-off-by: Kelsey Steele <kelseysteele@microsoft.com>
---
drivers/hv/dxgkrnl/dxgkrnl.h | 11 ++
drivers/hv/dxgkrnl/dxgmodule.c | 7 +-
drivers/hv/dxgkrnl/dxgprocess.c | 12 +-
drivers/hv/dxgkrnl/dxgsyncfile.c | 291 ++++++++++++++++++++++++++++++-
drivers/hv/dxgkrnl/dxgsyncfile.h | 3 +
drivers/hv/dxgkrnl/dxgvmbus.c | 49 ++++++
drivers/hv/dxgkrnl/ioctl.c | 16 +-
include/uapi/misc/d3dkmthk.h | 23 +++
8 files changed, 396 insertions(+), 16 deletions(-)
diff --git a/drivers/hv/dxgkrnl/dxgkrnl.h b/drivers/hv/dxgkrnl/dxgkrnl.h
index 3a69e3b34e1c..d92e1348ccfb 100644
--- a/drivers/hv/dxgkrnl/dxgkrnl.h
+++ b/drivers/hv/dxgkrnl/dxgkrnl.h
@@ -254,6 +254,10 @@ void dxgsharedsyncobj_add_syncobj(struct dxgsharedsyncobject *sharedsyncobj,
struct dxgsyncobject *syncobj);
void dxgsharedsyncobj_remove_syncobj(struct dxgsharedsyncobject *sharedsyncobj,
struct dxgsyncobject *syncobj);
+int dxgsharedsyncobj_get_host_nt_handle(struct dxgsharedsyncobject *syncobj,
+ struct dxgprocess *process,
+ struct d3dkmthandle objecthandle);
+void dxgsharedsyncobj_put(struct dxgsharedsyncobject *syncobj);
struct dxgsyncobject *dxgsyncobject_create(struct dxgprocess *process,
struct dxgdevice *device,
@@ -384,6 +388,8 @@ struct dxgprocess {
pid_t tgid;
/* how many time the process was opened */
struct kref process_kref;
+ /* protects the object memory */
+ struct kref process_mem_kref;
/*
* This handle table is used for all objects except dxgadapter
* The handle table lock order is higher than the local_handle_table
@@ -405,6 +411,7 @@ struct dxgprocess {
struct dxgprocess *dxgprocess_create(void);
void dxgprocess_destroy(struct dxgprocess *process);
void dxgprocess_release(struct kref *refcount);
+void dxgprocess_mem_release(struct kref *refcount);
int dxgprocess_open_adapter(struct dxgprocess *process,
struct dxgadapter *adapter,
struct d3dkmthandle *handle);
@@ -932,6 +939,10 @@ int dxgvmb_send_open_sync_object_nt(struct dxgprocess *process,
struct d3dkmt_opensyncobjectfromnthandle2
*args,
struct dxgsyncobject *syncobj);
+int dxgvmb_send_open_sync_object(struct dxgprocess *process,
+ struct d3dkmthandle device,
+ struct d3dkmthandle host_shared_syncobj,
+ struct d3dkmthandle *syncobj);
int dxgvmb_send_query_alloc_residency(struct dxgprocess *process,
struct dxgadapter *adapter,
struct d3dkmt_queryallocationresidency
diff --git a/drivers/hv/dxgkrnl/dxgmodule.c b/drivers/hv/dxgkrnl/dxgmodule.c
index 08feae97e845..5570f35954d4 100644
--- a/drivers/hv/dxgkrnl/dxgmodule.c
+++ b/drivers/hv/dxgkrnl/dxgmodule.c
@@ -149,10 +149,11 @@ void dxgglobal_remove_host_event(struct dxghostevent *event)
spin_unlock_irq(&dxgglobal->host_event_list_mutex);
}
-static void signal_dma_fence(struct dxghostevent *eventhdr)
+static void dxg_signal_dma_fence(struct dxghostevent *eventhdr)
{
struct dxgsyncpoint *event = (struct dxgsyncpoint *)eventhdr;
+ DXG_TRACE("syncpoint: %px, fence: %lld", event, event->fence_value);
event->fence_value++;
list_del(&eventhdr->host_event_list_entry);
dma_fence_signal(&event->base);
@@ -198,7 +199,7 @@ void dxgglobal_signal_host_event(u64 event_id)
if (event->event_type == dxghostevent_cpu_event)
signal_host_cpu_event(event);
else if (event->event_type == dxghostevent_dma_fence)
- signal_dma_fence(event);
+ dxg_signal_dma_fence(event);
else
DXG_ERR("Unknown host event type");
break;
@@ -355,6 +356,7 @@ static struct dxgprocess *dxgglobal_get_current_process(void)
if (entry->tgid == current->tgid) {
if (kref_get_unless_zero(&entry->process_kref)) {
process = entry;
+ kref_get(&entry->process_mem_kref);
DXG_TRACE("found dxgprocess");
} else {
DXG_TRACE("process is destroyed");
@@ -405,6 +407,7 @@ static int dxgk_release(struct inode *n, struct file *f)
return -EINVAL;
kref_put(&process->process_kref, dxgprocess_release);
+ kref_put(&process->process_mem_kref, dxgprocess_mem_release);
f->private_data = NULL;
return 0;
diff --git a/drivers/hv/dxgkrnl/dxgprocess.c b/drivers/hv/dxgkrnl/dxgprocess.c
index afef196c0588..e77e3a4983f8 100644
--- a/drivers/hv/dxgkrnl/dxgprocess.c
+++ b/drivers/hv/dxgkrnl/dxgprocess.c
@@ -39,6 +39,7 @@ struct dxgprocess *dxgprocess_create(void)
} else {
INIT_LIST_HEAD(&process->plistentry);
kref_init(&process->process_kref);
+ kref_init(&process->process_mem_kref);
mutex_lock(&dxgglobal->plistmutex);
list_add_tail(&process->plistentry,
@@ -117,8 +118,17 @@ void dxgprocess_release(struct kref *refcount)
dxgprocess_destroy(process);
- if (process->host_handle.v)
+ if (process->host_handle.v) {
dxgvmb_send_destroy_process(process->host_handle);
+ process->host_handle.v = 0;
+ }
+}
+
+void dxgprocess_mem_release(struct kref *refcount)
+{
+ struct dxgprocess *process;
+
+ process = container_of(refcount, struct dxgprocess, process_mem_kref);
kfree(process);
}
diff --git a/drivers/hv/dxgkrnl/dxgsyncfile.c b/drivers/hv/dxgkrnl/dxgsyncfile.c
index 88fd78f08fbe..9d5832c90ad7 100644
--- a/drivers/hv/dxgkrnl/dxgsyncfile.c
+++ b/drivers/hv/dxgkrnl/dxgsyncfile.c
@@ -9,6 +9,20 @@
* Dxgkrnl Graphics Driver
* Ioctl implementation
*
+ * dxgsyncpoint:
+ * - pointer to dxgsharedsyncobject
+ * - host_shared_handle_nt_reference incremented
+ * - list of (process, local syncobj d3dkmthandle) pairs
+ * wait for sync file
+ * - get dxgsyncpoint
+ * - if process doesn't have a local syncobj
+ * - create local dxgsyncobject
+ * - send open syncobj to the host
+ * - Send wait for syncobj to the context
+ * dxgsyncpoint destruction
+ * - walk the list of (process, local syncobj)
+ * - destroy syncobj
+ * - remove reference to dxgsharedsyncobject
*/
#include <linux/eventfd.h>
@@ -45,12 +59,15 @@ int dxgkio_create_sync_file(struct dxgprocess *process, void *__user inargs)
struct d3dkmt_createsyncfile args;
struct dxgsyncpoint *pt = NULL;
int ret = 0;
- int fd = get_unused_fd_flags(O_CLOEXEC);
+ int fd;
struct sync_file *sync_file = NULL;
struct dxgdevice *device = NULL;
struct dxgadapter *adapter = NULL;
+ struct dxgsyncobject *syncobj = NULL;
struct d3dkmt_waitforsynchronizationobjectfromcpu waitargs = {};
+ bool device_lock_acquired = false;
+ fd = get_unused_fd_flags(O_CLOEXEC);
if (fd < 0) {
DXG_ERR("get_unused_fd_flags failed: %d", fd);
ret = fd;
@@ -74,9 +91,9 @@ int dxgkio_create_sync_file(struct dxgprocess *process, void *__user inargs)
ret = dxgdevice_acquire_lock_shared(device);
if (ret < 0) {
DXG_ERR("dxgdevice_acquire_lock_shared failed");
- device = NULL;
goto cleanup;
}
+ device_lock_acquired = true;
adapter = device->adapter;
ret = dxgadapter_acquire_lock_shared(adapter);
@@ -109,6 +126,30 @@ int dxgkio_create_sync_file(struct dxgprocess *process, void *__user inargs)
}
dma_fence_put(&pt->base);
+ hmgrtable_lock(&process->handle_table, DXGLOCK_SHARED);
+ syncobj = hmgrtable_get_object(&process->handle_table,
+ args.monitored_fence);
+ if (syncobj == NULL) {
+ DXG_ERR("invalid syncobj handle %x", args.monitored_fence.v);
+ ret = -EINVAL;
+ } else {
+ if (syncobj->shared) {
+ kref_get(&syncobj->syncobj_kref);
+ pt->shared_syncobj = syncobj->shared_owner;
+ }
+ }
+ hmgrtable_unlock(&process->handle_table, DXGLOCK_SHARED);
+
+ if (pt->shared_syncobj) {
+ ret = dxgsharedsyncobj_get_host_nt_handle(pt->shared_syncobj,
+ process,
+ args.monitored_fence);
+ if (ret)
+ pt->shared_syncobj = NULL;
+ }
+ if (ret)
+ goto cleanup;
+
waitargs.device = args.device;
waitargs.object_count = 1;
waitargs.objects = &args.monitored_fence;
@@ -132,10 +173,15 @@ int dxgkio_create_sync_file(struct dxgprocess *process, void *__user inargs)
fd_install(fd, sync_file->file);
cleanup:
+ if (syncobj && syncobj->shared)
+ kref_put(&syncobj->syncobj_kref, dxgsyncobject_release);
if (adapter)
dxgadapter_release_lock_shared(adapter);
- if (device)
- dxgdevice_release_lock_shared(device);
+ if (device) {
+ if (device_lock_acquired)
+ dxgdevice_release_lock_shared(device);
+ kref_put(&device->device_kref, dxgdevice_release);
+ }
if (ret) {
if (sync_file) {
fput(sync_file->file);
@@ -151,6 +197,228 @@ int dxgkio_create_sync_file(struct dxgprocess *process, void *__user inargs)
return ret;
}
+int dxgkio_open_syncobj_from_syncfile(struct dxgprocess *process,
+ void *__user inargs)
+{
+ struct d3dkmt_opensyncobjectfromsyncfile args;
+ int ret = 0;
+ struct dxgsyncpoint *pt = NULL;
+ struct dma_fence *dmafence = NULL;
+ struct dxgdevice *device = NULL;
+ struct dxgadapter *adapter = NULL;
+ struct dxgsyncobject *syncobj = NULL;
+ struct d3dddi_synchronizationobject_flags flags = { };
+ struct d3dkmt_opensyncobjectfromnthandle2 openargs = { };
+ struct dxgglobal *dxgglobal = dxggbl();
+
+ ret = copy_from_user(&args, inargs, sizeof(args));
+ if (ret) {
+ DXG_ERR("failed to copy input args");
+ ret = -EFAULT;
+ goto cleanup;
+ }
+
+ dmafence = sync_file_get_fence(args.sync_file_handle);
+ if (dmafence == NULL) {
+ DXG_ERR("failed to get dmafence from handle: %llx",
+ args.sync_file_handle);
+ ret = -EINVAL;
+ goto cleanup;
+ }
+ pt = to_syncpoint(dmafence);
+ if (pt->shared_syncobj == NULL) {
+ DXG_ERR("Sync object is not shared");
+ goto cleanup;
+ }
+
+ device = dxgprocess_device_by_handle(process, args.device);
+ if (device == NULL) {
+ DXG_ERR("dxgprocess_device_by_handle failed");
+ ret = -EINVAL;
+ goto cleanup;
+ }
+
+ ret = dxgdevice_acquire_lock_shared(device);
+ if (ret < 0) {
+ DXG_ERR("dxgdevice_acquire_lock_shared failed");
+ kref_put(&device->device_kref, dxgdevice_release);
+ device = NULL;
+ goto cleanup;
+ }
+
+ adapter = device->adapter;
+ ret = dxgadapter_acquire_lock_shared(adapter);
+ if (ret < 0) {
+ DXG_ERR("dxgadapter_acquire_lock_shared failed");
+ adapter = NULL;
+ goto cleanup;
+ }
+
+ flags.shared = 1;
+ flags.nt_security_sharing = 1;
+ syncobj = dxgsyncobject_create(process, device, adapter,
+ _D3DDDI_MONITORED_FENCE, flags);
+ if (syncobj == NULL) {
+ DXG_ERR("failed to create sync object");
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+ dxgsharedsyncobj_add_syncobj(pt->shared_syncobj, syncobj);
+
+ /* Open the shared syncobj to get a local handle */
+
+ openargs.device = device->handle;
+ openargs.flags.shared = 1;
+ openargs.flags.nt_security_sharing = 1;
+ openargs.flags.no_signal = 1;
+
+ ret = dxgvmb_send_open_sync_object_nt(process,
+ &dxgglobal->channel, &openargs, syncobj);
+ if (ret) {
+ DXG_ERR("Failed to open shared syncobj on host");
+ goto cleanup;
+ }
+
+ hmgrtable_lock(&process->handle_table, DXGLOCK_EXCL);
+ ret = hmgrtable_assign_handle(&process->handle_table,
+ syncobj,
+ HMGRENTRY_TYPE_DXGSYNCOBJECT,
+ openargs.sync_object);
+ if (ret == 0) {
+ syncobj->handle = openargs.sync_object;
+ kref_get(&syncobj->syncobj_kref);
+ }
+ hmgrtable_unlock(&process->handle_table, DXGLOCK_EXCL);
+
+ args.syncobj = openargs.sync_object;
+ args.fence_value = pt->fence_value;
+ args.fence_value_cpu_va = openargs.monitored_fence.fence_value_cpu_va;
+ args.fence_value_gpu_va = openargs.monitored_fence.fence_value_gpu_va;
+
+ ret = copy_to_user(inargs, &args, sizeof(args));
+ if (ret) {
+ DXG_ERR("failed to copy output args");
+ ret = -EFAULT;
+ }
+
+cleanup:
+ if (dmafence)
+ dma_fence_put(dmafence);
+ if (ret) {
+ if (syncobj) {
+ dxgsyncobject_destroy(process, syncobj);
+ kref_put(&syncobj->syncobj_kref, dxgsyncobject_release);
+ }
+ }
+ if (adapter)
+ dxgadapter_release_lock_shared(adapter);
+ if (device) {
+ dxgdevice_release_lock_shared(device);
+ kref_put(&device->device_kref, dxgdevice_release);
+ }
+
+ DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ return ret;
+}
+
+int dxgkio_wait_sync_file(struct dxgprocess *process, void *__user inargs)
+{
+ struct d3dkmt_waitsyncfile args;
+ struct dma_fence *dmafence = NULL;
+ int ret = 0;
+ struct dxgsyncpoint *pt = NULL;
+ struct dxgdevice *device = NULL;
+ struct dxgadapter *adapter = NULL;
+ struct d3dkmthandle syncobj_handle = {};
+ bool device_lock_acquired = false;
+
+ ret = copy_from_user(&args, inargs, sizeof(args));
+ if (ret) {
+ DXG_ERR("failed to copy input args");
+ ret = -EFAULT;
+ goto cleanup;
+ }
+
+ dmafence = sync_file_get_fence(args.sync_file_handle);
+ if (dmafence == NULL) {
+ DXG_ERR("failed to get dmafence from handle: %llx",
+ args.sync_file_handle);
+ ret = -EINVAL;
+ goto cleanup;
+ }
+ pt = to_syncpoint(dmafence);
+
+ device = dxgprocess_device_by_object_handle(process,
+ HMGRENTRY_TYPE_DXGCONTEXT,
+ args.context);
+ if (device == NULL) {
+ ret = -EINVAL;
+ goto cleanup;
+ }
+
+ ret = dxgdevice_acquire_lock_shared(device);
+ if (ret < 0) {
+ DXG_ERR("dxgdevice_acquire_lock_shared failed");
+ device = NULL;
+ goto cleanup;
+ }
+ device_lock_acquired = true;
+
+ adapter = device->adapter;
+ ret = dxgadapter_acquire_lock_shared(adapter);
+ if (ret < 0) {
+ DXG_ERR("dxgadapter_acquire_lock_shared failed");
+ adapter = NULL;
+ goto cleanup;
+ }
+
+ /* Open the shared syncobj to get a local handle */
+ if (pt->shared_syncobj == NULL) {
+ DXG_ERR("Sync object is not shared");
+ goto cleanup;
+ }
+ ret = dxgvmb_send_open_sync_object(process,
+ device->handle,
+ pt->shared_syncobj->host_shared_handle,
+ &syncobj_handle);
+ if (ret) {
+ DXG_ERR("Failed to open shared syncobj on host");
+ goto cleanup;
+ }
+
+ /* Ask the host to insert the syncobj to the context queue */
+ ret = dxgvmb_send_wait_sync_object_gpu(process, adapter,
+ args.context, 1,
+ &syncobj_handle,
+ &pt->fence_value,
+ false);
+ if (ret < 0) {
+ DXG_ERR("dxgvmb_send_wait_sync_object_cpu failed");
+ goto cleanup;
+ }
+
+ /*
+ * Destroy the local syncobject immediately. This will not unblock
+ * GPU waiters, but will unblock CPU waiter, which includes the sync
+ * file itself.
+ */
+ ret = dxgvmb_send_destroy_sync_object(process, syncobj_handle);
+
+cleanup:
+ if (adapter)
+ dxgadapter_release_lock_shared(adapter);
+ if (device) {
+ if (device_lock_acquired)
+ dxgdevice_release_lock_shared(device);
+ kref_put(&device->device_kref, dxgdevice_release);
+ }
+ if (dmafence)
+ dma_fence_put(dmafence);
+
+ DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ return ret;
+}
+
static const char *dxgdmafence_get_driver_name(struct dma_fence *fence)
{
return "dxgkrnl";
@@ -166,11 +434,16 @@ static void dxgdmafence_release(struct dma_fence *fence)
struct dxgsyncpoint *syncpoint;
syncpoint = to_syncpoint(fence);
- if (syncpoint) {
- if (syncpoint->hdr.event_id)
- dxgglobal_get_host_event(syncpoint->hdr.event_id);
- kfree(syncpoint);
- }
+ if (syncpoint == NULL)
+ return;
+
+ if (syncpoint->hdr.event_id)
+ dxgglobal_get_host_event(syncpoint->hdr.event_id);
+
+ if (syncpoint->shared_syncobj)
+ dxgsharedsyncobj_put(syncpoint->shared_syncobj);
+
+ kfree(syncpoint);
}
static bool dxgdmafence_signaled(struct dma_fence *fence)
diff --git a/drivers/hv/dxgkrnl/dxgsyncfile.h b/drivers/hv/dxgkrnl/dxgsyncfile.h
index 207ef9b30f67..292b7f718987 100644
--- a/drivers/hv/dxgkrnl/dxgsyncfile.h
+++ b/drivers/hv/dxgkrnl/dxgsyncfile.h
@@ -17,10 +17,13 @@
#include <linux/sync_file.h>
int dxgkio_create_sync_file(struct dxgprocess *process, void *__user inargs);
+int dxgkio_wait_sync_file(struct dxgprocess *process, void *__user inargs);
+int dxgkio_open_syncobj_from_syncfile(struct dxgprocess *p, void *__user args);
struct dxgsyncpoint {
struct dxghostevent hdr;
struct dma_fence base;
+ struct dxgsharedsyncobject *shared_syncobj;
u64 fence_value;
u64 context;
spinlock_t lock;
diff --git a/drivers/hv/dxgkrnl/dxgvmbus.c b/drivers/hv/dxgkrnl/dxgvmbus.c
index d53d4254be63..36f4d4e84d3e 100644
--- a/drivers/hv/dxgkrnl/dxgvmbus.c
+++ b/drivers/hv/dxgkrnl/dxgvmbus.c
@@ -796,6 +796,55 @@ int dxgvmb_send_open_sync_object_nt(struct dxgprocess *process,
return ret;
}
+int dxgvmb_send_open_sync_object(struct dxgprocess *process,
+ struct d3dkmthandle device,
+ struct d3dkmthandle host_shared_syncobj,
+ struct d3dkmthandle *syncobj)
+{
+ struct dxgkvmb_command_opensyncobject *command;
+ struct dxgkvmb_command_opensyncobject_return result = { };
+ int ret;
+ struct dxgvmbusmsg msg;
+ struct dxgglobal *dxgglobal = dxggbl();
+
+ ret = init_message(&msg, NULL, process, sizeof(*command));
+ if (ret)
+ return ret;
+ command = (void *)msg.msg;
+
+ command_vm_to_host_init2(&command->hdr, DXGK_VMBCOMMAND_OPENSYNCOBJECT,
+ process->host_handle);
+ command->device = device;
+ command->global_sync_object = host_shared_syncobj;
+ command->flags.shared = 1;
+ command->flags.nt_security_sharing = 1;
+ command->flags.no_signal = 1;
+
+ ret = dxgglobal_acquire_channel_lock();
+ if (ret < 0)
+ goto cleanup;
+
+ ret = dxgvmb_send_sync_msg(&dxgglobal->channel, msg.hdr, msg.size,
+ &result, sizeof(result));
+
+ dxgglobal_release_channel_lock();
+
+ if (ret < 0)
+ goto cleanup;
+
+ ret = ntstatus2int(result.status);
+ if (ret < 0)
+ goto cleanup;
+
+ *syncobj = result.sync_object;
+
+cleanup:
+ free_message(&msg, process);
+ if (ret)
+ DXG_TRACE("err: %d", ret);
+ return ret;
+}
+
int dxgvmb_send_create_nt_shared_object(struct dxgprocess *process,
struct d3dkmthandle object,
struct d3dkmthandle *shared_handle)
diff --git a/drivers/hv/dxgkrnl/ioctl.c b/drivers/hv/dxgkrnl/ioctl.c
index 4db23cd55b24..622904d5c3a9 100644
--- a/drivers/hv/dxgkrnl/ioctl.c
+++ b/drivers/hv/dxgkrnl/ioctl.c
@@ -36,10 +36,8 @@ static char *errorstr(int ret)
}
#endif
-static int dxgsyncobj_release(struct inode *inode, struct file *file)
+void dxgsharedsyncobj_put(struct dxgsharedsyncobject *syncobj)
{
- struct dxgsharedsyncobject *syncobj = file->private_data;
-
DXG_TRACE("Release syncobj: %p", syncobj);
mutex_lock(&syncobj->fd_mutex);
kref_get(&syncobj->ssyncobj_kref);
@@ -56,6 +54,13 @@ static int dxgsyncobj_release(struct inode *inode, struct file *file)
}
mutex_unlock(&syncobj->fd_mutex);
kref_put(&syncobj->ssyncobj_kref, dxgsharedsyncobj_release);
+}
+
+static int dxgsyncobj_release(struct inode *inode, struct file *file)
+{
+ struct dxgsharedsyncobject *syncobj = file->private_data;
+
+ dxgsharedsyncobj_put(syncobj);
return 0;
}
@@ -4478,7 +4483,7 @@ dxgkio_get_device_state(struct dxgprocess *process, void *__user inargs)
return ret;
}
-static int
+int
dxgsharedsyncobj_get_host_nt_handle(struct dxgsharedsyncobject *syncobj,
struct dxgprocess *process,
struct d3dkmthandle objecthandle)
@@ -5226,6 +5231,9 @@ static struct ioctl_desc ioctls[] = {
/* 0x43 */ {dxgkio_query_statistics, LX_DXQUERYSTATISTICS},
/* 0x44 */ {dxgkio_share_object_with_host, LX_DXSHAREOBJECTWITHHOST},
/* 0x45 */ {dxgkio_create_sync_file, LX_DXCREATESYNCFILE},
+/* 0x46 */ {dxgkio_wait_sync_file, LX_DXWAITSYNCFILE},
+/* 0x46 */ {dxgkio_open_syncobj_from_syncfile,
+ LX_DXOPENSYNCOBJECTFROMSYNCFILE},
};
/*
diff --git a/include/uapi/misc/d3dkmthk.h b/include/uapi/misc/d3dkmthk.h
index c7f168425dc7..1eaa3f038322 100644
--- a/include/uapi/misc/d3dkmthk.h
+++ b/include/uapi/misc/d3dkmthk.h
@@ -1561,6 +1561,25 @@ struct d3dkmt_createsyncfile {
__u64 sync_file_handle; /* out */
};
+struct d3dkmt_waitsyncfile {
+ __u64 sync_file_handle;
+ struct d3dkmthandle context;
+ __u32 reserved;
+};
+
+struct d3dkmt_opensyncobjectfromsyncfile {
+ __u64 sync_file_handle;
+ struct d3dkmthandle device;
+ struct d3dkmthandle syncobj; /* out */
+ __u64 fence_value; /* out */
+#ifdef __KERNEL__
+ void *fence_value_cpu_va; /* out */
+#else
+ __u64 fence_value_cpu_va; /* out */
+#endif
+ __u64 fence_value_gpu_va; /* out */
+};
+
/*
* Dxgkrnl Graphics Port Driver ioctl definitions
*
@@ -1686,5 +1705,9 @@ struct d3dkmt_createsyncfile {
_IOWR(0x47, 0x44, struct d3dkmt_shareobjectwithhost)
#define LX_DXCREATESYNCFILE \
_IOWR(0x47, 0x45, struct d3dkmt_createsyncfile)
+#define LX_DXWAITSYNCFILE \
+ _IOWR(0x47, 0x46, struct d3dkmt_waitsyncfile)
+#define LX_DXOPENSYNCOBJECTFROMSYNCFILE \
+ _IOWR(0x47, 0x47, struct d3dkmt_opensyncobjectfromsyncfile)
#endif /* _D3DKMTHK_H */
^ permalink raw reply related
* [PATCH 32/55] drivers: hv: dxgkrnl: Use tracing instead of dev_dbg
From: Eric Curtin @ 2026-03-19 20:24 UTC (permalink / raw)
To: linux-hyperv; +Cc: linux-kernel, iourit, wei.liu, decui, haiyangz
In-Reply-To: <20260319202509.63802-1-eric.curtin@docker.com>
From: Iouri Tarassov <iourit@linux.microsoft.com>
Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
[kms: forward port to 6.6 from 6.1. No code changes made.]
Signed-off-by: Kelsey Steele <kelseysteele@microsoft.com>
---
drivers/hv/dxgkrnl/dxgadapter.c | 4 ++--
drivers/hv/dxgkrnl/dxgmodule.c | 5 ++++-
drivers/hv/dxgkrnl/dxgprocess.c | 6 +++---
drivers/hv/dxgkrnl/dxgvmbus.c | 4 ++--
drivers/hv/dxgkrnl/hmgr.c | 16 ++++++++--------
drivers/hv/dxgkrnl/ioctl.c | 8 ++++----
drivers/hv/dxgkrnl/misc.c | 4 ++--
7 files changed, 25 insertions(+), 22 deletions(-)
diff --git a/drivers/hv/dxgkrnl/dxgadapter.c b/drivers/hv/dxgkrnl/dxgadapter.c
index 236febbc6fca..3d8bec295b87 100644
--- a/drivers/hv/dxgkrnl/dxgadapter.c
+++ b/drivers/hv/dxgkrnl/dxgadapter.c
@@ -18,8 +18,8 @@
#include "dxgkrnl.h"
-#undef pr_fmt
-#define pr_fmt(fmt) "dxgk: " fmt
+#undef dev_fmt
+#define dev_fmt(fmt) "dxgk: " fmt
int dxgadapter_set_vmbus(struct dxgadapter *adapter, struct hv_device *hdev)
{
diff --git a/drivers/hv/dxgkrnl/dxgmodule.c b/drivers/hv/dxgkrnl/dxgmodule.c
index af51fcd35697..08feae97e845 100644
--- a/drivers/hv/dxgkrnl/dxgmodule.c
+++ b/drivers/hv/dxgkrnl/dxgmodule.c
@@ -24,6 +24,9 @@
#undef pr_fmt
#define pr_fmt(fmt) "dxgk: " fmt
+#undef dev_fmt
+#define dev_fmt(fmt) "dxgk: " fmt
+
/*
* Interface from dxgglobal
*/
@@ -442,7 +445,7 @@ const struct file_operations dxgk_fops = {
#define DXGK_VMBUS_HOSTCAPS_OFFSET (DXGK_VMBUS_VGPU_LUID_OFFSET + \
sizeof(struct winluid))
-/* The guest writes its capavilities to this adderss */
+/* The guest writes its capabilities to this address */
#define DXGK_VMBUS_GUESTCAPS_OFFSET (DXGK_VMBUS_VERSION_OFFSET + \
sizeof(u32))
diff --git a/drivers/hv/dxgkrnl/dxgprocess.c b/drivers/hv/dxgkrnl/dxgprocess.c
index 5de3f8ccb448..afef196c0588 100644
--- a/drivers/hv/dxgkrnl/dxgprocess.c
+++ b/drivers/hv/dxgkrnl/dxgprocess.c
@@ -13,8 +13,8 @@
#include "dxgkrnl.h"
-#undef pr_fmt
-#define pr_fmt(fmt) "dxgk: " fmt
+#undef dev_fmt
+#define dev_fmt(fmt) "dxgk: " fmt
/*
* Creates a new dxgprocess object
@@ -248,7 +248,7 @@ struct dxgadapter *dxgprocess_adapter_by_handle(struct dxgprocess *process,
HMGRENTRY_TYPE_DXGADAPTER,
handle);
if (adapter == NULL)
- DXG_ERR("adapter_by_handle failed %x", handle.v);
+ DXG_TRACE("adapter_by_handle failed %x", handle.v);
else if (kref_get_unless_zero(&adapter->adapter_kref) == 0) {
DXG_ERR("failed to acquire adapter reference");
adapter = NULL;
diff --git a/drivers/hv/dxgkrnl/dxgvmbus.c b/drivers/hv/dxgkrnl/dxgvmbus.c
index 913ea3cabb31..d53d4254be63 100644
--- a/drivers/hv/dxgkrnl/dxgvmbus.c
+++ b/drivers/hv/dxgkrnl/dxgvmbus.c
@@ -22,8 +22,8 @@
#include "dxgkrnl.h"
#include "dxgvmbus.h"
-#undef pr_fmt
-#define pr_fmt(fmt) "dxgk: " fmt
+#undef dev_fmt
+#define dev_fmt(fmt) "dxgk: " fmt
#define RING_BUFSIZE (256 * 1024)
diff --git a/drivers/hv/dxgkrnl/hmgr.c b/drivers/hv/dxgkrnl/hmgr.c
index 526b50f46d96..24101d0091ab 100644
--- a/drivers/hv/dxgkrnl/hmgr.c
+++ b/drivers/hv/dxgkrnl/hmgr.c
@@ -19,8 +19,8 @@
#include "dxgkrnl.h"
#include "hmgr.h"
-#undef pr_fmt
-#define pr_fmt(fmt) "dxgk: " fmt
+#undef dev_fmt
+#define dev_fmt(fmt) "dxgk: " fmt
const struct d3dkmthandle zerohandle;
@@ -90,29 +90,29 @@ static bool is_handle_valid(struct hmgrtable *table, struct d3dkmthandle h,
struct hmgrentry *entry;
if (index >= table->table_size) {
- DXG_ERR("Invalid index %x %d", h.v, index);
+ DXG_TRACE("Invalid index %x %d", h.v, index);
return false;
}
entry = &table->entry_table[index];
if (unique != entry->unique) {
- DXG_ERR("Invalid unique %x %d %d %d %p",
+ DXG_TRACE("Invalid unique %x %d %d %d %p",
h.v, unique, entry->unique, index, entry->object);
return false;
}
if (entry->destroyed && !ignore_destroyed) {
- DXG_ERR("Invalid destroyed value");
+ DXG_TRACE("Invalid destroyed value");
return false;
}
if (entry->type == HMGRENTRY_TYPE_FREE) {
- DXG_ERR("Entry is freed %x %d", h.v, index);
+ DXG_TRACE("Entry is freed %x %d", h.v, index);
return false;
}
if (t != HMGRENTRY_TYPE_FREE && t != entry->type) {
- DXG_ERR("type mismatch %x %d %d", h.v, t, entry->type);
+ DXG_TRACE("type mismatch %x %d %d", h.v, t, entry->type);
return false;
}
@@ -500,7 +500,7 @@ void *hmgrtable_get_object_by_type(struct hmgrtable *table,
struct d3dkmthandle h)
{
if (!is_handle_valid(table, h, false, type)) {
- DXG_ERR("Invalid handle %x", h.v);
+ DXG_TRACE("Invalid handle %x", h.v);
return NULL;
}
return table->entry_table[get_index(h)].object;
diff --git a/drivers/hv/dxgkrnl/ioctl.c b/drivers/hv/dxgkrnl/ioctl.c
index 6c26aafb0619..4db23cd55b24 100644
--- a/drivers/hv/dxgkrnl/ioctl.c
+++ b/drivers/hv/dxgkrnl/ioctl.c
@@ -21,8 +21,8 @@
#include "dxgvmbus.h"
#include "dxgsyncfile.h"
-#undef pr_fmt
-#define pr_fmt(fmt) "dxgk: " fmt
+#undef dev_fmt
+#define dev_fmt(fmt) "dxgk: " fmt
struct ioctl_desc {
int (*ioctl_callback)(struct dxgprocess *p, void __user *arg);
@@ -556,7 +556,7 @@ dxgkio_enum_adapters3(struct dxgprocess *process, void *__user inargs)
cleanup:
- DXG_TRACE("ioctl: %s %d", errorstr(ret), ret);
+ DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
return ret;
}
@@ -5242,7 +5242,7 @@ static int dxgk_ioctl(struct file *f, unsigned int p1, unsigned long p2)
int status;
struct dxgprocess *process;
- if (code < 1 || code >= ARRAY_SIZE(ioctls)) {
+ if (code < 1 || code >= ARRAY_SIZE(ioctls)) {
DXG_ERR("bad ioctl %x %x %x %x",
code, _IOC_TYPE(p1), _IOC_SIZE(p1), _IOC_DIR(p1));
return -ENOTTY;
diff --git a/drivers/hv/dxgkrnl/misc.c b/drivers/hv/dxgkrnl/misc.c
index 4a1309d80ee5..4bf6fe80d22a 100644
--- a/drivers/hv/dxgkrnl/misc.c
+++ b/drivers/hv/dxgkrnl/misc.c
@@ -18,8 +18,8 @@
#include "dxgkrnl.h"
#include "misc.h"
-#undef pr_fmt
-#define pr_fmt(fmt) "dxgk: " fmt
+#undef dev_fmt
+#define dev_fmt(fmt) "dxgk: " fmt
u16 *wcsncpy(u16 *dest, const u16 *src, size_t n)
{
^ permalink raw reply related
* [PATCH 31/55] drivers: hv: dxgkrnl: Creation of dxgsyncfile objects
From: Eric Curtin @ 2026-03-19 20:24 UTC (permalink / raw)
To: linux-hyperv; +Cc: linux-kernel, iourit, wei.liu, decui, haiyangz
In-Reply-To: <20260319202509.63802-1-eric.curtin@docker.com>
From: Iouri Tarassov <iourit@linux.microsoft.com>
Implement the ioctl to create a dxgsyncfile object
(LX_DXCREATESYNCFILE). This object is a wrapper around a monitored
fence sync object and a fence value.
dxgsyncfile is built on top of the Linux sync_file object and
provides a way for the user mode to synchronize with the execution
of the device DMA packets.
The ioctl creates a dxgsyncfile object for the given GPU synchronization
object and a fence value. A file descriptor of the sync_file object
is returned to the caller. The caller could wait for the object by using
poll(). When the underlying GPU synchronization object is signaled on
the host, the host sends a message to the virtual machine and the
sync_file object is signaled.
Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
[kms: forward port to 6.6 from 6.1. No code changes made.]
Signed-off-by: Kelsey Steele <kelseysteele@microsoft.com>
---
drivers/hv/dxgkrnl/Kconfig | 2 +
drivers/hv/dxgkrnl/Makefile | 2 +-
drivers/hv/dxgkrnl/dxgkrnl.h | 2 +
drivers/hv/dxgkrnl/dxgmodule.c | 12 ++
drivers/hv/dxgkrnl/dxgsyncfile.c | 215 +++++++++++++++++++++++++++++++
drivers/hv/dxgkrnl/dxgsyncfile.h | 30 +++++
drivers/hv/dxgkrnl/dxgvmbus.c | 33 +++--
drivers/hv/dxgkrnl/ioctl.c | 5 +-
include/uapi/misc/d3dkmthk.h | 9 ++
9 files changed, 294 insertions(+), 16 deletions(-)
create mode 100644 drivers/hv/dxgkrnl/dxgsyncfile.c
create mode 100644 drivers/hv/dxgkrnl/dxgsyncfile.h
diff --git a/drivers/hv/dxgkrnl/Kconfig b/drivers/hv/dxgkrnl/Kconfig
index bcd92bbff939..782692610887 100644
--- a/drivers/hv/dxgkrnl/Kconfig
+++ b/drivers/hv/dxgkrnl/Kconfig
@@ -6,6 +6,8 @@ config DXGKRNL
tristate "Microsoft Paravirtualized GPU support"
depends on HYPERV
depends on 64BIT || COMPILE_TEST
+ select DMA_SHARED_BUFFER
+ select SYNC_FILE
help
This driver supports paravirtualized virtual compute devices, exposed
by Microsoft Hyper-V when Linux is running inside of a virtual machine
diff --git a/drivers/hv/dxgkrnl/Makefile b/drivers/hv/dxgkrnl/Makefile
index fc85a47a6ad5..89824cda670a 100644
--- a/drivers/hv/dxgkrnl/Makefile
+++ b/drivers/hv/dxgkrnl/Makefile
@@ -2,4 +2,4 @@
# Makefile for the hyper-v compute device driver (dxgkrnl).
obj-$(CONFIG_DXGKRNL) += dxgkrnl.o
-dxgkrnl-y := dxgmodule.o hmgr.o misc.o dxgadapter.o ioctl.o dxgvmbus.o dxgprocess.o
+dxgkrnl-y := dxgmodule.o hmgr.o misc.o dxgadapter.o ioctl.o dxgvmbus.o dxgprocess.o dxgsyncfile.o
diff --git a/drivers/hv/dxgkrnl/dxgkrnl.h b/drivers/hv/dxgkrnl/dxgkrnl.h
index 091dbe999d33..3a69e3b34e1c 100644
--- a/drivers/hv/dxgkrnl/dxgkrnl.h
+++ b/drivers/hv/dxgkrnl/dxgkrnl.h
@@ -120,6 +120,7 @@ struct dxgpagingqueue {
*/
enum dxghosteventtype {
dxghostevent_cpu_event = 1,
+ dxghostevent_dma_fence = 2,
};
struct dxghostevent {
@@ -858,6 +859,7 @@ int dxgvmb_send_wait_sync_object_cpu(struct dxgprocess *process,
struct
d3dkmt_waitforsynchronizationobjectfromcpu
*args,
+ bool user_address,
u64 cpu_event);
int dxgvmb_send_lock2(struct dxgprocess *process,
struct dxgadapter *adapter,
diff --git a/drivers/hv/dxgkrnl/dxgmodule.c b/drivers/hv/dxgkrnl/dxgmodule.c
index f1245a9d8826..af51fcd35697 100644
--- a/drivers/hv/dxgkrnl/dxgmodule.c
+++ b/drivers/hv/dxgkrnl/dxgmodule.c
@@ -16,6 +16,7 @@
#include <linux/hyperv.h>
#include <linux/pci.h>
#include "dxgkrnl.h"
+#include "dxgsyncfile.h"
#define PCI_VENDOR_ID_MICROSOFT 0x1414
#define PCI_DEVICE_ID_VIRTUAL_RENDER 0x008E
@@ -145,6 +146,15 @@ void dxgglobal_remove_host_event(struct dxghostevent *event)
spin_unlock_irq(&dxgglobal->host_event_list_mutex);
}
+static void signal_dma_fence(struct dxghostevent *eventhdr)
+{
+ struct dxgsyncpoint *event = (struct dxgsyncpoint *)eventhdr;
+
+ event->fence_value++;
+ list_del(&eventhdr->host_event_list_entry);
+ dma_fence_signal(&event->base);
+}
+
void signal_host_cpu_event(struct dxghostevent *eventhdr)
{
struct dxghosteventcpu *event = (struct dxghosteventcpu *)eventhdr;
@@ -184,6 +194,8 @@ void dxgglobal_signal_host_event(u64 event_id)
DXG_TRACE("found event to signal");
if (event->event_type == dxghostevent_cpu_event)
signal_host_cpu_event(event);
+ else if (event->event_type == dxghostevent_dma_fence)
+ signal_dma_fence(event);
else
DXG_ERR("Unknown host event type");
break;
diff --git a/drivers/hv/dxgkrnl/dxgsyncfile.c b/drivers/hv/dxgkrnl/dxgsyncfile.c
new file mode 100644
index 000000000000..88fd78f08fbe
--- /dev/null
+++ b/drivers/hv/dxgkrnl/dxgsyncfile.c
@@ -0,0 +1,215 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright (c) 2022, Microsoft Corporation.
+ *
+ * Author:
+ * Iouri Tarassov <iourit@linux.microsoft.com>
+ *
+ * Dxgkrnl Graphics Driver
+ * Ioctl implementation
+ *
+ */
+
+#include <linux/eventfd.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/anon_inodes.h>
+#include <linux/mman.h>
+
+#include "dxgkrnl.h"
+#include "dxgvmbus.h"
+#include "dxgsyncfile.h"
+
+#undef dev_fmt
+#define dev_fmt(fmt) "dxgk: " fmt
+
+#ifdef DEBUG
+static char *errorstr(int ret)
+{
+ return ret < 0 ? "err" : "";
+}
+#endif
+
+static const struct dma_fence_ops dxgdmafence_ops;
+
+static struct dxgsyncpoint *to_syncpoint(struct dma_fence *fence)
+{
+ if (fence->ops != &dxgdmafence_ops)
+ return NULL;
+ return container_of(fence, struct dxgsyncpoint, base);
+}
+
+int dxgkio_create_sync_file(struct dxgprocess *process, void *__user inargs)
+{
+ struct d3dkmt_createsyncfile args;
+ struct dxgsyncpoint *pt = NULL;
+ int ret = 0;
+ int fd = get_unused_fd_flags(O_CLOEXEC);
+ struct sync_file *sync_file = NULL;
+ struct dxgdevice *device = NULL;
+ struct dxgadapter *adapter = NULL;
+ struct d3dkmt_waitforsynchronizationobjectfromcpu waitargs = {};
+
+ if (fd < 0) {
+ DXG_ERR("get_unused_fd_flags failed: %d", fd);
+ ret = fd;
+ goto cleanup;
+ }
+
+ ret = copy_from_user(&args, inargs, sizeof(args));
+ if (ret) {
+ DXG_ERR("failed to copy input args");
+ ret = -EFAULT;
+ goto cleanup;
+ }
+
+ device = dxgprocess_device_by_handle(process, args.device);
+ if (device == NULL) {
+ DXG_ERR("dxgprocess_device_by_handle failed");
+ ret = -EINVAL;
+ goto cleanup;
+ }
+
+ ret = dxgdevice_acquire_lock_shared(device);
+ if (ret < 0) {
+ DXG_ERR("dxgdevice_acquire_lock_shared failed");
+ device = NULL;
+ goto cleanup;
+ }
+
+ adapter = device->adapter;
+ ret = dxgadapter_acquire_lock_shared(adapter);
+ if (ret < 0) {
+ DXG_ERR("dxgadapter_acquire_lock_shared failed");
+ adapter = NULL;
+ goto cleanup;
+ }
+
+ pt = kzalloc(sizeof(*pt), GFP_KERNEL);
+ if (!pt) {
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+ spin_lock_init(&pt->lock);
+ pt->fence_value = args.fence_value;
+ pt->context = dma_fence_context_alloc(1);
+ pt->hdr.event_id = dxgglobal_new_host_event_id();
+ pt->hdr.event_type = dxghostevent_dma_fence;
+ dxgglobal_add_host_event(&pt->hdr);
+
+ dma_fence_init(&pt->base, &dxgdmafence_ops, &pt->lock,
+ pt->context, args.fence_value);
+
+ sync_file = sync_file_create(&pt->base);
+ if (sync_file == NULL) {
+ DXG_ERR("sync_file_create failed");
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+ dma_fence_put(&pt->base);
+
+ waitargs.device = args.device;
+ waitargs.object_count = 1;
+ waitargs.objects = &args.monitored_fence;
+ waitargs.fence_values = &args.fence_value;
+ ret = dxgvmb_send_wait_sync_object_cpu(process, adapter,
+ &waitargs, false,
+ pt->hdr.event_id);
+ if (ret < 0) {
+ DXG_ERR("dxgvmb_send_wait_sync_object_cpu failed");
+ goto cleanup;
+ }
+
+ args.sync_file_handle = (u64)fd;
+ ret = copy_to_user(inargs, &args, sizeof(args));
+ if (ret) {
+ DXG_ERR("failed to copy output args");
+ ret = -EFAULT;
+ goto cleanup;
+ }
+
+ fd_install(fd, sync_file->file);
+
+cleanup:
+ if (adapter)
+ dxgadapter_release_lock_shared(adapter);
+ if (device)
+ dxgdevice_release_lock_shared(device);
+ if (ret) {
+ if (sync_file) {
+ fput(sync_file->file);
+ /* sync_file_release will destroy dma_fence */
+ pt = NULL;
+ }
+ if (pt)
+ dma_fence_put(&pt->base);
+ if (fd >= 0)
+ put_unused_fd(fd);
+ }
+ DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+ return ret;
+}
+
+static const char *dxgdmafence_get_driver_name(struct dma_fence *fence)
+{
+ return "dxgkrnl";
+}
+
+static const char *dxgdmafence_get_timeline_name(struct dma_fence *fence)
+{
+ return "no_timeline";
+}
+
+static void dxgdmafence_release(struct dma_fence *fence)
+{
+ struct dxgsyncpoint *syncpoint;
+
+ syncpoint = to_syncpoint(fence);
+ if (syncpoint) {
+ if (syncpoint->hdr.event_id)
+ dxgglobal_get_host_event(syncpoint->hdr.event_id);
+ kfree(syncpoint);
+ }
+}
+
+static bool dxgdmafence_signaled(struct dma_fence *fence)
+{
+ struct dxgsyncpoint *syncpoint;
+
+ syncpoint = to_syncpoint(fence);
+ if (syncpoint == 0)
+ return true;
+ return __dma_fence_is_later(syncpoint->fence_value, fence->seqno,
+ fence->ops);
+}
+
+static bool dxgdmafence_enable_signaling(struct dma_fence *fence)
+{
+ return true;
+}
+
+static void dxgdmafence_value_str(struct dma_fence *fence,
+ char *str, int size)
+{
+ snprintf(str, size, "%lld", fence->seqno);
+}
+
+static void dxgdmafence_timeline_value_str(struct dma_fence *fence,
+ char *str, int size)
+{
+ struct dxgsyncpoint *syncpoint;
+
+ syncpoint = to_syncpoint(fence);
+ snprintf(str, size, "%lld", syncpoint->fence_value);
+}
+
+static const struct dma_fence_ops dxgdmafence_ops = {
+ .get_driver_name = dxgdmafence_get_driver_name,
+ .get_timeline_name = dxgdmafence_get_timeline_name,
+ .enable_signaling = dxgdmafence_enable_signaling,
+ .signaled = dxgdmafence_signaled,
+ .release = dxgdmafence_release,
+ .fence_value_str = dxgdmafence_value_str,
+ .timeline_value_str = dxgdmafence_timeline_value_str,
+};
diff --git a/drivers/hv/dxgkrnl/dxgsyncfile.h b/drivers/hv/dxgkrnl/dxgsyncfile.h
new file mode 100644
index 000000000000..207ef9b30f67
--- /dev/null
+++ b/drivers/hv/dxgkrnl/dxgsyncfile.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/*
+ * Copyright (c) 2022, Microsoft Corporation.
+ *
+ * Author:
+ * Iouri Tarassov <iourit@linux.microsoft.com>
+ *
+ * Dxgkrnl Graphics Driver
+ * Headers for sync file objects
+ *
+ */
+
+#ifndef _DXGSYNCFILE_H
+#define _DXGSYNCFILE_H
+
+#include <linux/sync_file.h>
+
+int dxgkio_create_sync_file(struct dxgprocess *process, void *__user inargs);
+
+struct dxgsyncpoint {
+ struct dxghostevent hdr;
+ struct dma_fence base;
+ u64 fence_value;
+ u64 context;
+ spinlock_t lock;
+ u64 u64;
+};
+
+#endif /* _DXGSYNCFILE_H */
diff --git a/drivers/hv/dxgkrnl/dxgvmbus.c b/drivers/hv/dxgkrnl/dxgvmbus.c
index 4d7807909284..913ea3cabb31 100644
--- a/drivers/hv/dxgkrnl/dxgvmbus.c
+++ b/drivers/hv/dxgkrnl/dxgvmbus.c
@@ -2820,6 +2820,7 @@ int dxgvmb_send_wait_sync_object_cpu(struct dxgprocess *process,
struct
d3dkmt_waitforsynchronizationobjectfromcpu
*args,
+ bool user_address,
u64 cpu_event)
{
int ret = -EINVAL;
@@ -2844,19 +2845,25 @@ int dxgvmb_send_wait_sync_object_cpu(struct dxgprocess *process,
command->guest_event_pointer = (u64) cpu_event;
current_pos = (u8 *) &command[1];
- ret = copy_from_user(current_pos, args->objects, object_size);
- if (ret) {
- DXG_ERR("failed to copy objects");
- ret = -EINVAL;
- goto cleanup;
- }
- current_pos += object_size;
- ret = copy_from_user(current_pos, args->fence_values,
- fence_size);
- if (ret) {
- DXG_ERR("failed to copy fences");
- ret = -EINVAL;
- goto cleanup;
+ if (user_address) {
+ ret = copy_from_user(current_pos, args->objects, object_size);
+ if (ret) {
+ DXG_ERR("failed to copy objects");
+ ret = -EINVAL;
+ goto cleanup;
+ }
+ current_pos += object_size;
+ ret = copy_from_user(current_pos, args->fence_values,
+ fence_size);
+ if (ret) {
+ DXG_ERR("failed to copy fences");
+ ret = -EINVAL;
+ goto cleanup;
+ }
+ } else {
+ memcpy(current_pos, args->objects, object_size);
+ current_pos += object_size;
+ memcpy(current_pos, args->fence_values, fence_size);
}
ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr, msg.size);
diff --git a/drivers/hv/dxgkrnl/ioctl.c b/drivers/hv/dxgkrnl/ioctl.c
index 8732a66040a0..6c26aafb0619 100644
--- a/drivers/hv/dxgkrnl/ioctl.c
+++ b/drivers/hv/dxgkrnl/ioctl.c
@@ -19,6 +19,7 @@
#include "dxgkrnl.h"
#include "dxgvmbus.h"
+#include "dxgsyncfile.h"
#undef pr_fmt
#define pr_fmt(fmt) "dxgk: " fmt
@@ -3488,7 +3489,7 @@ dxgkio_wait_sync_object_cpu(struct dxgprocess *process, void *__user inargs)
}
ret = dxgvmb_send_wait_sync_object_cpu(process, adapter,
- &args, event_id);
+ &args, true, event_id);
if (ret < 0)
goto cleanup;
@@ -5224,7 +5225,7 @@ static struct ioctl_desc ioctls[] = {
/* 0x42 */ {dxgkio_open_resource_nt, LX_DXOPENRESOURCEFROMNTHANDLE},
/* 0x43 */ {dxgkio_query_statistics, LX_DXQUERYSTATISTICS},
/* 0x44 */ {dxgkio_share_object_with_host, LX_DXSHAREOBJECTWITHHOST},
-/* 0x45 */ {},
+/* 0x45 */ {dxgkio_create_sync_file, LX_DXCREATESYNCFILE},
};
/*
diff --git a/include/uapi/misc/d3dkmthk.h b/include/uapi/misc/d3dkmthk.h
index 1f60f5120e1d..c7f168425dc7 100644
--- a/include/uapi/misc/d3dkmthk.h
+++ b/include/uapi/misc/d3dkmthk.h
@@ -1554,6 +1554,13 @@ struct d3dkmt_shareobjectwithhost {
__u64 object_vail_nt_handle;
};
+struct d3dkmt_createsyncfile {
+ struct d3dkmthandle device;
+ struct d3dkmthandle monitored_fence;
+ __u64 fence_value;
+ __u64 sync_file_handle; /* out */
+};
+
/*
* Dxgkrnl Graphics Port Driver ioctl definitions
*
@@ -1677,5 +1684,7 @@ struct d3dkmt_shareobjectwithhost {
_IOWR(0x47, 0x43, struct d3dkmt_querystatistics)
#define LX_DXSHAREOBJECTWITHHOST \
_IOWR(0x47, 0x44, struct d3dkmt_shareobjectwithhost)
+#define LX_DXCREATESYNCFILE \
+ _IOWR(0x47, 0x45, struct d3dkmt_createsyncfile)
#endif /* _D3DKMTHK_H */
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox