mirror of
https://github.com/armbian/build
synced 2025-09-24 19:47:06 +07:00
424 lines
13 KiB
Diff
424 lines
13 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Iouri Tarassov <iourit@linux.microsoft.com>
|
|
Date: Wed, 9 Feb 2022 11:01:57 -0800
|
|
Subject: drivers: hv: dxgkrnl: Ioctls to query statistics and clock
|
|
calibration
|
|
|
|
Implement ioctls to query statistics from the VGPU device
|
|
(LX_DXQUERYSTATISTICS) and to query clock calibration
|
|
(LX_DXQUERYCLOCKCALIBRATION).
|
|
|
|
The LX_DXQUERYSTATISTICS ioctl is used to query various statistics from
|
|
the compute device on the host.
|
|
|
|
The LX_DXQUERYCLOCKCALIBRATION ioctl queries the compute device clock
|
|
and is used for performance monitoring.
|
|
|
|
Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
|
|
[kms: Forward port to v6.1]
|
|
Signed-off-by: Kelsey Steele <kelseysteele@microsoft.com>
|
|
---
|
|
drivers/hv/dxgkrnl/dxgkrnl.h | 8 +
|
|
drivers/hv/dxgkrnl/dxgvmbus.c | 77 +++++++
|
|
drivers/hv/dxgkrnl/dxgvmbus.h | 21 ++
|
|
drivers/hv/dxgkrnl/ioctl.c | 111 +++++++++-
|
|
include/uapi/misc/d3dkmthk.h | 62 ++++++
|
|
5 files changed, 277 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/drivers/hv/dxgkrnl/dxgkrnl.h b/drivers/hv/dxgkrnl/dxgkrnl.h
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/hv/dxgkrnl/dxgkrnl.h
|
|
+++ b/drivers/hv/dxgkrnl/dxgkrnl.h
|
|
@@ -885,6 +885,11 @@ int dxgvmb_send_query_adapter_info(struct dxgprocess *process,
|
|
int dxgvmb_send_submit_command_hwqueue(struct dxgprocess *process,
|
|
struct dxgadapter *adapter,
|
|
struct d3dkmt_submitcommandtohwqueue *a);
|
|
+int dxgvmb_send_query_clock_calibration(struct dxgprocess *process,
|
|
+ struct dxgadapter *adapter,
|
|
+ struct d3dkmt_queryclockcalibration *a,
|
|
+ struct d3dkmt_queryclockcalibration
|
|
+ *__user inargs);
|
|
int dxgvmb_send_flush_heap_transitions(struct dxgprocess *process,
|
|
struct dxgadapter *adapter,
|
|
struct d3dkmt_flushheaptransitions *arg);
|
|
@@ -929,6 +934,9 @@ 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,
|
|
+ struct dxgadapter *adapter,
|
|
+ struct d3dkmt_querystatistics *args);
|
|
int dxgvmb_send_async_msg(struct dxgvmbuschannel *channel,
|
|
void *command,
|
|
u32 cmd_size);
|
|
diff --git a/drivers/hv/dxgkrnl/dxgvmbus.c b/drivers/hv/dxgkrnl/dxgvmbus.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/hv/dxgkrnl/dxgvmbus.c
|
|
+++ b/drivers/hv/dxgkrnl/dxgvmbus.c
|
|
@@ -1829,6 +1829,48 @@ int dxgvmb_send_destroy_allocation(struct dxgprocess *process,
|
|
return ret;
|
|
}
|
|
|
|
+int dxgvmb_send_query_clock_calibration(struct dxgprocess *process,
|
|
+ struct dxgadapter *adapter,
|
|
+ struct d3dkmt_queryclockcalibration
|
|
+ *args,
|
|
+ struct d3dkmt_queryclockcalibration
|
|
+ *__user inargs)
|
|
+{
|
|
+ struct dxgkvmb_command_queryclockcalibration *command;
|
|
+ struct dxgkvmb_command_queryclockcalibration_return result;
|
|
+ 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_QUERYCLOCKCALIBRATION,
|
|
+ process->host_handle);
|
|
+ command->args = *args;
|
|
+
|
|
+ ret = dxgvmb_send_sync_msg(msg.channel, msg.hdr, msg.size,
|
|
+ &result, sizeof(result));
|
|
+ if (ret < 0)
|
|
+ goto cleanup;
|
|
+ ret = copy_to_user(&inargs->clock_data, &result.clock_data,
|
|
+ sizeof(result.clock_data));
|
|
+ if (ret) {
|
|
+ pr_err("%s failed to copy clock data", __func__);
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ ret = ntstatus2int(result.status);
|
|
+
|
|
+cleanup:
|
|
+ free_message(&msg, process);
|
|
+ if (ret)
|
|
+ DXG_TRACE("err: %d", ret);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
int dxgvmb_send_flush_heap_transitions(struct dxgprocess *process,
|
|
struct dxgadapter *adapter,
|
|
struct d3dkmt_flushheaptransitions *args)
|
|
@@ -3242,3 +3284,38 @@ int dxgvmb_send_submit_command_hwqueue(struct dxgprocess *process,
|
|
return ret;
|
|
}
|
|
|
|
+int dxgvmb_send_query_statistics(struct dxgprocess *process,
|
|
+ struct dxgadapter *adapter,
|
|
+ struct d3dkmt_querystatistics *args)
|
|
+{
|
|
+ struct dxgkvmb_command_querystatistics *command;
|
|
+ struct dxgkvmb_command_querystatistics_return *result;
|
|
+ int ret;
|
|
+ struct dxgvmbusmsgres msg = {.hdr = NULL};
|
|
+
|
|
+ ret = init_message_res(&msg, adapter, process, sizeof(*command),
|
|
+ sizeof(*result));
|
|
+ if (ret)
|
|
+ goto cleanup;
|
|
+ command = msg.msg;
|
|
+ result = msg.res;
|
|
+
|
|
+ command_vgpu_to_host_init2(&command->hdr,
|
|
+ DXGK_VMBCOMMAND_QUERYSTATISTICS,
|
|
+ process->host_handle);
|
|
+ command->args = *args;
|
|
+
|
|
+ ret = dxgvmb_send_sync_msg(msg.channel, msg.hdr, msg.size,
|
|
+ result, msg.res_size);
|
|
+ if (ret < 0)
|
|
+ goto cleanup;
|
|
+
|
|
+ args->result = result->result;
|
|
+ ret = ntstatus2int(result->status);
|
|
+
|
|
+cleanup:
|
|
+ free_message((struct dxgvmbusmsg *)&msg, process);
|
|
+ if (ret)
|
|
+ DXG_TRACE("err: %d", ret);
|
|
+ return ret;
|
|
+}
|
|
diff --git a/drivers/hv/dxgkrnl/dxgvmbus.h b/drivers/hv/dxgkrnl/dxgvmbus.h
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/hv/dxgkrnl/dxgvmbus.h
|
|
+++ b/drivers/hv/dxgkrnl/dxgvmbus.h
|
|
@@ -372,6 +372,16 @@ struct dxgkvmb_command_flushheaptransitions {
|
|
struct dxgkvmb_command_vgpu_to_host hdr;
|
|
};
|
|
|
|
+struct dxgkvmb_command_queryclockcalibration {
|
|
+ struct dxgkvmb_command_vgpu_to_host hdr;
|
|
+ struct d3dkmt_queryclockcalibration args;
|
|
+};
|
|
+
|
|
+struct dxgkvmb_command_queryclockcalibration_return {
|
|
+ struct ntstatus status;
|
|
+ struct dxgk_gpuclockdata clock_data;
|
|
+};
|
|
+
|
|
struct dxgkvmb_command_createallocation_allocinfo {
|
|
u32 flags;
|
|
u32 priv_drv_data_size;
|
|
@@ -408,6 +418,17 @@ struct dxgkvmb_command_openresource_return {
|
|
/* struct d3dkmthandle allocation[allocation_count]; */
|
|
};
|
|
|
|
+struct dxgkvmb_command_querystatistics {
|
|
+ struct dxgkvmb_command_vgpu_to_host hdr;
|
|
+ struct d3dkmt_querystatistics args;
|
|
+};
|
|
+
|
|
+struct dxgkvmb_command_querystatistics_return {
|
|
+ struct ntstatus status;
|
|
+ u32 reserved;
|
|
+ struct d3dkmt_querystatistics_result result;
|
|
+};
|
|
+
|
|
struct dxgkvmb_command_getstandardallocprivdata {
|
|
struct dxgkvmb_command_vgpu_to_host hdr;
|
|
enum d3dkmdt_standardallocationtype alloc_type;
|
|
diff --git a/drivers/hv/dxgkrnl/ioctl.c b/drivers/hv/dxgkrnl/ioctl.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/hv/dxgkrnl/ioctl.c
|
|
+++ b/drivers/hv/dxgkrnl/ioctl.c
|
|
@@ -149,6 +149,65 @@ static int dxgkio_open_adapter_from_luid(struct dxgprocess *process,
|
|
return ret;
|
|
}
|
|
|
|
+static int dxgkio_query_statistics(struct dxgprocess *process,
|
|
+ void __user *inargs)
|
|
+{
|
|
+ struct d3dkmt_querystatistics *args;
|
|
+ int ret;
|
|
+ struct dxgadapter *entry;
|
|
+ struct dxgadapter *adapter = NULL;
|
|
+ struct winluid tmp;
|
|
+ struct dxgglobal *dxgglobal = dxggbl();
|
|
+
|
|
+ args = vzalloc(sizeof(struct d3dkmt_querystatistics));
|
|
+ if (args == NULL) {
|
|
+ ret = -ENOMEM;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ ret = copy_from_user(args, inargs, sizeof(*args));
|
|
+ if (ret) {
|
|
+ DXG_ERR("failed to copy input args");
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ dxgglobal_acquire_adapter_list_lock(DXGLOCK_SHARED);
|
|
+ list_for_each_entry(entry, &dxgglobal->adapter_list_head,
|
|
+ adapter_list_entry) {
|
|
+ if (dxgadapter_acquire_lock_shared(entry) == 0) {
|
|
+ if (*(u64 *) &entry->luid ==
|
|
+ *(u64 *) &args->adapter_luid) {
|
|
+ adapter = entry;
|
|
+ break;
|
|
+ }
|
|
+ dxgadapter_release_lock_shared(entry);
|
|
+ }
|
|
+ }
|
|
+ dxgglobal_release_adapter_list_lock(DXGLOCK_SHARED);
|
|
+ if (adapter) {
|
|
+ tmp = args->adapter_luid;
|
|
+ args->adapter_luid = adapter->host_adapter_luid;
|
|
+ ret = dxgvmb_send_query_statistics(process, adapter, args);
|
|
+ if (ret >= 0) {
|
|
+ args->adapter_luid = tmp;
|
|
+ ret = copy_to_user(inargs, args, sizeof(*args));
|
|
+ if (ret) {
|
|
+ DXG_ERR("failed to copy args");
|
|
+ ret = -EINVAL;
|
|
+ }
|
|
+ }
|
|
+ dxgadapter_release_lock_shared(adapter);
|
|
+ }
|
|
+
|
|
+cleanup:
|
|
+ if (args)
|
|
+ vfree(args);
|
|
+
|
|
+ DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
static int
|
|
dxgkp_enum_adapters(struct dxgprocess *process,
|
|
union d3dkmt_enumadapters_filter filter,
|
|
@@ -3536,6 +3595,54 @@ dxgkio_change_vidmem_reservation(struct dxgprocess *process, void *__user inargs
|
|
return ret;
|
|
}
|
|
|
|
+static int
|
|
+dxgkio_query_clock_calibration(struct dxgprocess *process, void *__user inargs)
|
|
+{
|
|
+ struct d3dkmt_queryclockcalibration args;
|
|
+ int ret;
|
|
+ struct dxgadapter *adapter = NULL;
|
|
+ bool adapter_locked = false;
|
|
+
|
|
+ ret = copy_from_user(&args, inargs, sizeof(args));
|
|
+ if (ret) {
|
|
+ DXG_ERR("failed to copy input args");
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ adapter = dxgprocess_adapter_by_handle(process, args.adapter);
|
|
+ if (adapter == NULL) {
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ ret = dxgadapter_acquire_lock_shared(adapter);
|
|
+ if (ret < 0) {
|
|
+ adapter = NULL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ adapter_locked = true;
|
|
+
|
|
+ args.adapter = adapter->host_handle;
|
|
+ ret = dxgvmb_send_query_clock_calibration(process, adapter,
|
|
+ &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 = -EINVAL;
|
|
+ }
|
|
+
|
|
+cleanup:
|
|
+
|
|
+ if (adapter_locked)
|
|
+ dxgadapter_release_lock_shared(adapter);
|
|
+ if (adapter)
|
|
+ kref_put(&adapter->adapter_kref, dxgadapter_release);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
static int
|
|
dxgkio_flush_heap_transitions(struct dxgprocess *process, void *__user inargs)
|
|
{
|
|
@@ -4470,14 +4577,14 @@ static struct ioctl_desc ioctls[] = {
|
|
/* 0x3b */ {dxgkio_wait_sync_object_gpu,
|
|
LX_DXWAITFORSYNCHRONIZATIONOBJECTFROMGPU},
|
|
/* 0x3c */ {dxgkio_get_allocation_priority, LX_DXGETALLOCATIONPRIORITY},
|
|
-/* 0x3d */ {},
|
|
+/* 0x3d */ {dxgkio_query_clock_calibration, LX_DXQUERYCLOCKCALIBRATION},
|
|
/* 0x3e */ {dxgkio_enum_adapters3, LX_DXENUMADAPTERS3},
|
|
/* 0x3f */ {dxgkio_share_objects, LX_DXSHAREOBJECTS},
|
|
/* 0x40 */ {dxgkio_open_sync_object_nt, LX_DXOPENSYNCOBJECTFROMNTHANDLE2},
|
|
/* 0x41 */ {dxgkio_query_resource_info_nt,
|
|
LX_DXQUERYRESOURCEINFOFROMNTHANDLE},
|
|
/* 0x42 */ {dxgkio_open_resource_nt, LX_DXOPENRESOURCEFROMNTHANDLE},
|
|
-/* 0x43 */ {},
|
|
+/* 0x43 */ {dxgkio_query_statistics, LX_DXQUERYSTATISTICS},
|
|
/* 0x44 */ {dxgkio_share_object_with_host, LX_DXSHAREOBJECTWITHHOST},
|
|
/* 0x45 */ {},
|
|
};
|
|
diff --git a/include/uapi/misc/d3dkmthk.h b/include/uapi/misc/d3dkmthk.h
|
|
index 111111111111..222222222222 100644
|
|
--- a/include/uapi/misc/d3dkmthk.h
|
|
+++ b/include/uapi/misc/d3dkmthk.h
|
|
@@ -996,6 +996,34 @@ struct d3dkmt_queryadapterinfo {
|
|
__u32 private_data_size;
|
|
};
|
|
|
|
+#pragma pack(push, 1)
|
|
+
|
|
+struct dxgk_gpuclockdata_flags {
|
|
+ union {
|
|
+ struct {
|
|
+ __u32 context_management_processor:1;
|
|
+ __u32 reserved:31;
|
|
+ };
|
|
+ __u32 value;
|
|
+ };
|
|
+};
|
|
+
|
|
+struct dxgk_gpuclockdata {
|
|
+ __u64 gpu_frequency;
|
|
+ __u64 gpu_clock_counter;
|
|
+ __u64 cpu_clock_counter;
|
|
+ struct dxgk_gpuclockdata_flags flags;
|
|
+} __packed;
|
|
+
|
|
+struct d3dkmt_queryclockcalibration {
|
|
+ struct d3dkmthandle adapter;
|
|
+ __u32 node_ordinal;
|
|
+ __u32 physical_adapter_index;
|
|
+ struct dxgk_gpuclockdata clock_data;
|
|
+};
|
|
+
|
|
+#pragma pack(pop)
|
|
+
|
|
struct d3dkmt_flushheaptransitions {
|
|
struct d3dkmthandle adapter;
|
|
};
|
|
@@ -1238,6 +1266,36 @@ struct d3dkmt_enumadapters3 {
|
|
#endif
|
|
};
|
|
|
|
+enum d3dkmt_querystatistics_type {
|
|
+ _D3DKMT_QUERYSTATISTICS_ADAPTER = 0,
|
|
+ _D3DKMT_QUERYSTATISTICS_PROCESS = 1,
|
|
+ _D3DKMT_QUERYSTATISTICS_PROCESS_ADAPTER = 2,
|
|
+ _D3DKMT_QUERYSTATISTICS_SEGMENT = 3,
|
|
+ _D3DKMT_QUERYSTATISTICS_PROCESS_SEGMENT = 4,
|
|
+ _D3DKMT_QUERYSTATISTICS_NODE = 5,
|
|
+ _D3DKMT_QUERYSTATISTICS_PROCESS_NODE = 6,
|
|
+ _D3DKMT_QUERYSTATISTICS_VIDPNSOURCE = 7,
|
|
+ _D3DKMT_QUERYSTATISTICS_PROCESS_VIDPNSOURCE = 8,
|
|
+ _D3DKMT_QUERYSTATISTICS_PROCESS_SEGMENT_GROUP = 9,
|
|
+ _D3DKMT_QUERYSTATISTICS_PHYSICAL_ADAPTER = 10,
|
|
+};
|
|
+
|
|
+struct d3dkmt_querystatistics_result {
|
|
+ char size[0x308];
|
|
+};
|
|
+
|
|
+struct d3dkmt_querystatistics {
|
|
+ union {
|
|
+ struct {
|
|
+ enum d3dkmt_querystatistics_type type;
|
|
+ struct winluid adapter_luid;
|
|
+ __u64 process;
|
|
+ struct d3dkmt_querystatistics_result result;
|
|
+ };
|
|
+ char size[0x328];
|
|
+ };
|
|
+};
|
|
+
|
|
struct d3dkmt_shareobjectwithhost {
|
|
struct d3dkmthandle device_handle;
|
|
struct d3dkmthandle object_handle;
|
|
@@ -1328,6 +1386,8 @@ struct d3dkmt_shareobjectwithhost {
|
|
_IOWR(0x47, 0x3b, struct d3dkmt_waitforsynchronizationobjectfromgpu)
|
|
#define LX_DXGETALLOCATIONPRIORITY \
|
|
_IOWR(0x47, 0x3c, struct d3dkmt_getallocationpriority)
|
|
+#define LX_DXQUERYCLOCKCALIBRATION \
|
|
+ _IOWR(0x47, 0x3d, struct d3dkmt_queryclockcalibration)
|
|
#define LX_DXENUMADAPTERS3 \
|
|
_IOWR(0x47, 0x3e, struct d3dkmt_enumadapters3)
|
|
#define LX_DXSHAREOBJECTS \
|
|
@@ -1338,6 +1398,8 @@ struct d3dkmt_shareobjectwithhost {
|
|
_IOWR(0x47, 0x41, struct d3dkmt_queryresourceinfofromnthandle)
|
|
#define LX_DXOPENRESOURCEFROMNTHANDLE \
|
|
_IOWR(0x47, 0x42, struct d3dkmt_openresourcefromnthandle)
|
|
+#define LX_DXQUERYSTATISTICS \
|
|
+ _IOWR(0x47, 0x43, struct d3dkmt_querystatistics)
|
|
#define LX_DXSHAREOBJECTWITHHOST \
|
|
_IOWR(0x47, 0x44, struct d3dkmt_shareobjectwithhost)
|
|
|
|
--
|
|
Armbian
|
|
|