Skip to content

Commit 7deec1c

Browse files
Iouri Tarassovchessturo
authored andcommitted
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 6.6 from 6.1. No code changes made.] Signed-off-by: Kelsey Steele <kelseysteele@microsoft.com>
1 parent 63adb4c commit 7deec1c

5 files changed

Lines changed: 277 additions & 2 deletions

File tree

drivers/hv/dxgkrnl/dxgkrnl.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -885,6 +885,11 @@ int dxgvmb_send_query_adapter_info(struct dxgprocess *process,
885885
int dxgvmb_send_submit_command_hwqueue(struct dxgprocess *process,
886886
struct dxgadapter *adapter,
887887
struct d3dkmt_submitcommandtohwqueue *a);
888+
int dxgvmb_send_query_clock_calibration(struct dxgprocess *process,
889+
struct dxgadapter *adapter,
890+
struct d3dkmt_queryclockcalibration *a,
891+
struct d3dkmt_queryclockcalibration
892+
*__user inargs);
888893
int dxgvmb_send_flush_heap_transitions(struct dxgprocess *process,
889894
struct dxgadapter *adapter,
890895
struct d3dkmt_flushheaptransitions *arg);
@@ -929,6 +934,9 @@ int dxgvmb_send_get_stdalloc_data(struct dxgdevice *device,
929934
void *prive_alloc_data,
930935
u32 *res_priv_data_size,
931936
void *priv_res_data);
937+
int dxgvmb_send_query_statistics(struct dxgprocess *process,
938+
struct dxgadapter *adapter,
939+
struct d3dkmt_querystatistics *args);
932940
int dxgvmb_send_async_msg(struct dxgvmbuschannel *channel,
933941
void *command,
934942
u32 cmd_size);

drivers/hv/dxgkrnl/dxgvmbus.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1829,6 +1829,48 @@ int dxgvmb_send_destroy_allocation(struct dxgprocess *process,
18291829
return ret;
18301830
}
18311831

1832+
int dxgvmb_send_query_clock_calibration(struct dxgprocess *process,
1833+
struct dxgadapter *adapter,
1834+
struct d3dkmt_queryclockcalibration
1835+
*args,
1836+
struct d3dkmt_queryclockcalibration
1837+
*__user inargs)
1838+
{
1839+
struct dxgkvmb_command_queryclockcalibration *command;
1840+
struct dxgkvmb_command_queryclockcalibration_return result;
1841+
int ret;
1842+
struct dxgvmbusmsg msg = {.hdr = NULL};
1843+
1844+
ret = init_message(&msg, adapter, process, sizeof(*command));
1845+
if (ret)
1846+
goto cleanup;
1847+
command = (void *)msg.msg;
1848+
1849+
command_vgpu_to_host_init2(&command->hdr,
1850+
DXGK_VMBCOMMAND_QUERYCLOCKCALIBRATION,
1851+
process->host_handle);
1852+
command->args = *args;
1853+
1854+
ret = dxgvmb_send_sync_msg(msg.channel, msg.hdr, msg.size,
1855+
&result, sizeof(result));
1856+
if (ret < 0)
1857+
goto cleanup;
1858+
ret = copy_to_user(&inargs->clock_data, &result.clock_data,
1859+
sizeof(result.clock_data));
1860+
if (ret) {
1861+
pr_err("%s failed to copy clock data", __func__);
1862+
ret = -EINVAL;
1863+
goto cleanup;
1864+
}
1865+
ret = ntstatus2int(result.status);
1866+
1867+
cleanup:
1868+
free_message(&msg, process);
1869+
if (ret)
1870+
DXG_TRACE("err: %d", ret);
1871+
return ret;
1872+
}
1873+
18321874
int dxgvmb_send_flush_heap_transitions(struct dxgprocess *process,
18331875
struct dxgadapter *adapter,
18341876
struct d3dkmt_flushheaptransitions *args)
@@ -3242,3 +3284,38 @@ int dxgvmb_send_submit_command_hwqueue(struct dxgprocess *process,
32423284
return ret;
32433285
}
32443286

3287+
int dxgvmb_send_query_statistics(struct dxgprocess *process,
3288+
struct dxgadapter *adapter,
3289+
struct d3dkmt_querystatistics *args)
3290+
{
3291+
struct dxgkvmb_command_querystatistics *command;
3292+
struct dxgkvmb_command_querystatistics_return *result;
3293+
int ret;
3294+
struct dxgvmbusmsgres msg = {.hdr = NULL};
3295+
3296+
ret = init_message_res(&msg, adapter, process, sizeof(*command),
3297+
sizeof(*result));
3298+
if (ret)
3299+
goto cleanup;
3300+
command = msg.msg;
3301+
result = msg.res;
3302+
3303+
command_vgpu_to_host_init2(&command->hdr,
3304+
DXGK_VMBCOMMAND_QUERYSTATISTICS,
3305+
process->host_handle);
3306+
command->args = *args;
3307+
3308+
ret = dxgvmb_send_sync_msg(msg.channel, msg.hdr, msg.size,
3309+
result, msg.res_size);
3310+
if (ret < 0)
3311+
goto cleanup;
3312+
3313+
args->result = result->result;
3314+
ret = ntstatus2int(result->status);
3315+
3316+
cleanup:
3317+
free_message((struct dxgvmbusmsg *)&msg, process);
3318+
if (ret)
3319+
DXG_TRACE("err: %d", ret);
3320+
return ret;
3321+
}

drivers/hv/dxgkrnl/dxgvmbus.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,16 @@ struct dxgkvmb_command_flushheaptransitions {
372372
struct dxgkvmb_command_vgpu_to_host hdr;
373373
};
374374

375+
struct dxgkvmb_command_queryclockcalibration {
376+
struct dxgkvmb_command_vgpu_to_host hdr;
377+
struct d3dkmt_queryclockcalibration args;
378+
};
379+
380+
struct dxgkvmb_command_queryclockcalibration_return {
381+
struct ntstatus status;
382+
struct dxgk_gpuclockdata clock_data;
383+
};
384+
375385
struct dxgkvmb_command_createallocation_allocinfo {
376386
u32 flags;
377387
u32 priv_drv_data_size;
@@ -408,6 +418,17 @@ struct dxgkvmb_command_openresource_return {
408418
/* struct d3dkmthandle allocation[allocation_count]; */
409419
};
410420

421+
struct dxgkvmb_command_querystatistics {
422+
struct dxgkvmb_command_vgpu_to_host hdr;
423+
struct d3dkmt_querystatistics args;
424+
};
425+
426+
struct dxgkvmb_command_querystatistics_return {
427+
struct ntstatus status;
428+
u32 reserved;
429+
struct d3dkmt_querystatistics_result result;
430+
};
431+
411432
struct dxgkvmb_command_getstandardallocprivdata {
412433
struct dxgkvmb_command_vgpu_to_host hdr;
413434
enum d3dkmdt_standardallocationtype alloc_type;

drivers/hv/dxgkrnl/ioctl.c

Lines changed: 109 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,65 @@ static int dxgkio_open_adapter_from_luid(struct dxgprocess *process,
149149
return ret;
150150
}
151151

152+
static int dxgkio_query_statistics(struct dxgprocess *process,
153+
void __user *inargs)
154+
{
155+
struct d3dkmt_querystatistics *args;
156+
int ret;
157+
struct dxgadapter *entry;
158+
struct dxgadapter *adapter = NULL;
159+
struct winluid tmp;
160+
struct dxgglobal *dxgglobal = dxggbl();
161+
162+
args = vzalloc(sizeof(struct d3dkmt_querystatistics));
163+
if (args == NULL) {
164+
ret = -ENOMEM;
165+
goto cleanup;
166+
}
167+
168+
ret = copy_from_user(args, inargs, sizeof(*args));
169+
if (ret) {
170+
DXG_ERR("failed to copy input args");
171+
ret = -EINVAL;
172+
goto cleanup;
173+
}
174+
175+
dxgglobal_acquire_adapter_list_lock(DXGLOCK_SHARED);
176+
list_for_each_entry(entry, &dxgglobal->adapter_list_head,
177+
adapter_list_entry) {
178+
if (dxgadapter_acquire_lock_shared(entry) == 0) {
179+
if (*(u64 *) &entry->luid ==
180+
*(u64 *) &args->adapter_luid) {
181+
adapter = entry;
182+
break;
183+
}
184+
dxgadapter_release_lock_shared(entry);
185+
}
186+
}
187+
dxgglobal_release_adapter_list_lock(DXGLOCK_SHARED);
188+
if (adapter) {
189+
tmp = args->adapter_luid;
190+
args->adapter_luid = adapter->host_adapter_luid;
191+
ret = dxgvmb_send_query_statistics(process, adapter, args);
192+
if (ret >= 0) {
193+
args->adapter_luid = tmp;
194+
ret = copy_to_user(inargs, args, sizeof(*args));
195+
if (ret) {
196+
DXG_ERR("failed to copy args");
197+
ret = -EINVAL;
198+
}
199+
}
200+
dxgadapter_release_lock_shared(adapter);
201+
}
202+
203+
cleanup:
204+
if (args)
205+
vfree(args);
206+
207+
DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
208+
return ret;
209+
}
210+
152211
static int
153212
dxgkp_enum_adapters(struct dxgprocess *process,
154213
union d3dkmt_enumadapters_filter filter,
@@ -3536,6 +3595,54 @@ dxgkio_change_vidmem_reservation(struct dxgprocess *process, void *__user inargs
35363595
return ret;
35373596
}
35383597

3598+
static int
3599+
dxgkio_query_clock_calibration(struct dxgprocess *process, void *__user inargs)
3600+
{
3601+
struct d3dkmt_queryclockcalibration args;
3602+
int ret;
3603+
struct dxgadapter *adapter = NULL;
3604+
bool adapter_locked = false;
3605+
3606+
ret = copy_from_user(&args, inargs, sizeof(args));
3607+
if (ret) {
3608+
DXG_ERR("failed to copy input args");
3609+
ret = -EINVAL;
3610+
goto cleanup;
3611+
}
3612+
3613+
adapter = dxgprocess_adapter_by_handle(process, args.adapter);
3614+
if (adapter == NULL) {
3615+
ret = -EINVAL;
3616+
goto cleanup;
3617+
}
3618+
3619+
ret = dxgadapter_acquire_lock_shared(adapter);
3620+
if (ret < 0) {
3621+
adapter = NULL;
3622+
goto cleanup;
3623+
}
3624+
adapter_locked = true;
3625+
3626+
args.adapter = adapter->host_handle;
3627+
ret = dxgvmb_send_query_clock_calibration(process, adapter,
3628+
&args, inargs);
3629+
if (ret < 0)
3630+
goto cleanup;
3631+
ret = copy_to_user(inargs, &args, sizeof(args));
3632+
if (ret) {
3633+
DXG_ERR("failed to copy output args");
3634+
ret = -EINVAL;
3635+
}
3636+
3637+
cleanup:
3638+
3639+
if (adapter_locked)
3640+
dxgadapter_release_lock_shared(adapter);
3641+
if (adapter)
3642+
kref_put(&adapter->adapter_kref, dxgadapter_release);
3643+
return ret;
3644+
}
3645+
35393646
static int
35403647
dxgkio_flush_heap_transitions(struct dxgprocess *process, void *__user inargs)
35413648
{
@@ -4470,14 +4577,14 @@ static struct ioctl_desc ioctls[] = {
44704577
/* 0x3b */ {dxgkio_wait_sync_object_gpu,
44714578
LX_DXWAITFORSYNCHRONIZATIONOBJECTFROMGPU},
44724579
/* 0x3c */ {dxgkio_get_allocation_priority, LX_DXGETALLOCATIONPRIORITY},
4473-
/* 0x3d */ {},
4580+
/* 0x3d */ {dxgkio_query_clock_calibration, LX_DXQUERYCLOCKCALIBRATION},
44744581
/* 0x3e */ {dxgkio_enum_adapters3, LX_DXENUMADAPTERS3},
44754582
/* 0x3f */ {dxgkio_share_objects, LX_DXSHAREOBJECTS},
44764583
/* 0x40 */ {dxgkio_open_sync_object_nt, LX_DXOPENSYNCOBJECTFROMNTHANDLE2},
44774584
/* 0x41 */ {dxgkio_query_resource_info_nt,
44784585
LX_DXQUERYRESOURCEINFOFROMNTHANDLE},
44794586
/* 0x42 */ {dxgkio_open_resource_nt, LX_DXOPENRESOURCEFROMNTHANDLE},
4480-
/* 0x43 */ {},
4587+
/* 0x43 */ {dxgkio_query_statistics, LX_DXQUERYSTATISTICS},
44814588
/* 0x44 */ {dxgkio_share_object_with_host, LX_DXSHAREOBJECTWITHHOST},
44824589
/* 0x45 */ {},
44834590
};

include/uapi/misc/d3dkmthk.h

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -996,6 +996,34 @@ struct d3dkmt_queryadapterinfo {
996996
__u32 private_data_size;
997997
};
998998

999+
#pragma pack(push, 1)
1000+
1001+
struct dxgk_gpuclockdata_flags {
1002+
union {
1003+
struct {
1004+
__u32 context_management_processor:1;
1005+
__u32 reserved:31;
1006+
};
1007+
__u32 value;
1008+
};
1009+
};
1010+
1011+
struct dxgk_gpuclockdata {
1012+
__u64 gpu_frequency;
1013+
__u64 gpu_clock_counter;
1014+
__u64 cpu_clock_counter;
1015+
struct dxgk_gpuclockdata_flags flags;
1016+
} __packed;
1017+
1018+
struct d3dkmt_queryclockcalibration {
1019+
struct d3dkmthandle adapter;
1020+
__u32 node_ordinal;
1021+
__u32 physical_adapter_index;
1022+
struct dxgk_gpuclockdata clock_data;
1023+
};
1024+
1025+
#pragma pack(pop)
1026+
9991027
struct d3dkmt_flushheaptransitions {
10001028
struct d3dkmthandle adapter;
10011029
};
@@ -1238,6 +1266,36 @@ struct d3dkmt_enumadapters3 {
12381266
#endif
12391267
};
12401268

1269+
enum d3dkmt_querystatistics_type {
1270+
_D3DKMT_QUERYSTATISTICS_ADAPTER = 0,
1271+
_D3DKMT_QUERYSTATISTICS_PROCESS = 1,
1272+
_D3DKMT_QUERYSTATISTICS_PROCESS_ADAPTER = 2,
1273+
_D3DKMT_QUERYSTATISTICS_SEGMENT = 3,
1274+
_D3DKMT_QUERYSTATISTICS_PROCESS_SEGMENT = 4,
1275+
_D3DKMT_QUERYSTATISTICS_NODE = 5,
1276+
_D3DKMT_QUERYSTATISTICS_PROCESS_NODE = 6,
1277+
_D3DKMT_QUERYSTATISTICS_VIDPNSOURCE = 7,
1278+
_D3DKMT_QUERYSTATISTICS_PROCESS_VIDPNSOURCE = 8,
1279+
_D3DKMT_QUERYSTATISTICS_PROCESS_SEGMENT_GROUP = 9,
1280+
_D3DKMT_QUERYSTATISTICS_PHYSICAL_ADAPTER = 10,
1281+
};
1282+
1283+
struct d3dkmt_querystatistics_result {
1284+
char size[0x308];
1285+
};
1286+
1287+
struct d3dkmt_querystatistics {
1288+
union {
1289+
struct {
1290+
enum d3dkmt_querystatistics_type type;
1291+
struct winluid adapter_luid;
1292+
__u64 process;
1293+
struct d3dkmt_querystatistics_result result;
1294+
};
1295+
char size[0x328];
1296+
};
1297+
};
1298+
12411299
struct d3dkmt_shareobjectwithhost {
12421300
struct d3dkmthandle device_handle;
12431301
struct d3dkmthandle object_handle;
@@ -1328,6 +1386,8 @@ struct d3dkmt_shareobjectwithhost {
13281386
_IOWR(0x47, 0x3b, struct d3dkmt_waitforsynchronizationobjectfromgpu)
13291387
#define LX_DXGETALLOCATIONPRIORITY \
13301388
_IOWR(0x47, 0x3c, struct d3dkmt_getallocationpriority)
1389+
#define LX_DXQUERYCLOCKCALIBRATION \
1390+
_IOWR(0x47, 0x3d, struct d3dkmt_queryclockcalibration)
13311391
#define LX_DXENUMADAPTERS3 \
13321392
_IOWR(0x47, 0x3e, struct d3dkmt_enumadapters3)
13331393
#define LX_DXSHAREOBJECTS \
@@ -1338,6 +1398,8 @@ struct d3dkmt_shareobjectwithhost {
13381398
_IOWR(0x47, 0x41, struct d3dkmt_queryresourceinfofromnthandle)
13391399
#define LX_DXOPENRESOURCEFROMNTHANDLE \
13401400
_IOWR(0x47, 0x42, struct d3dkmt_openresourcefromnthandle)
1401+
#define LX_DXQUERYSTATISTICS \
1402+
_IOWR(0x47, 0x43, struct d3dkmt_querystatistics)
13411403
#define LX_DXSHAREOBJECTWITHHOST \
13421404
_IOWR(0x47, 0x44, struct d3dkmt_shareobjectwithhost)
13431405

0 commit comments

Comments
 (0)