[PATCH 41/55] drivers: hv: dxgkrnl: Handle process ID in D3DKMTQueryStatistics

From: Eric Curtin

Date: Thu Mar 19 2026 - 16:41:30 EST


From: Iouri Tarassov <iourit@xxxxxxxxxxxxxxxxxxx>

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@xxxxxxxxxxxxxxxxxxx>
[kms: forward port to 6.6 from 6.1. No code changes made.]
Signed-off-by: Kelsey Steele <kelseysteele@xxxxxxxxxxxxx>
---
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));