Skip to content

Commit 899af4b

Browse files
Iouri Tarassovchessturo
authored andcommitted
drivers: hv: dxgkrnl: Query the dxgdevice state
Implement the ioctl to query the dxgdevice state - LX_DXGETDEVICESTATE. The IOCTL is used to query the state of the given dxgdevice object (active, error, etc.). A call to the dxgdevice execution state could be high frequency. The following method is used to avoid sending a synchronous VM bus message to the host for every call: - When a dxgdevice is created, a pointer to dxgglobal->device_state_counter is sent to the host - Every time the device state on the host is changed, the host will send an asynchronous message to the guest (DXGK_VMBCOMMAND_SETGUESTDATA) and the guest will increment the device_state_counter value. - the dxgdevice object has execution_state_counter member, which is equal to dxgglobal->device_state_counter value at the time when LX_DXGETDEVICESTATE was last processed.. - if execution_state_counter is different from device_state_counter, the dxgk_vmbcommand_getdevicestate VM bus message is sent to the host. Otherwise, the cached value is returned to the caller. 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 89cbe4c commit 899af4b

6 files changed

Lines changed: 261 additions & 12 deletions

File tree

drivers/hv/dxgkrnl/dxgkrnl.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,12 +268,18 @@ void dxgsyncobject_destroy(struct dxgprocess *process,
268268
void dxgsyncobject_stop(struct dxgsyncobject *syncobj);
269269
void dxgsyncobject_release(struct kref *refcount);
270270

271+
/*
272+
* device_state_counter - incremented every time the execition state of
273+
* a DXGDEVICE is changed in the host. Used to optimize access to the
274+
* device execution state.
275+
*/
271276
struct dxgglobal {
272277
struct dxgdriver *drvdata;
273278
struct dxgvmbuschannel channel;
274279
struct hv_device *hdev;
275280
u32 num_adapters;
276281
u32 vmbus_ver; /* Interface version */
282+
atomic_t device_state_counter;
277283
struct resource *mem;
278284
u64 mmiospace_base;
279285
u64 mmiospace_size;
@@ -512,6 +518,7 @@ struct dxgdevice {
512518
struct list_head syncobj_list_head;
513519
struct d3dkmthandle handle;
514520
enum d3dkmt_deviceexecution_state execution_state;
521+
int execution_state_counter;
515522
u32 handle_valid;
516523
};
517524

@@ -849,6 +856,10 @@ int dxgvmb_send_open_sync_object_nt(struct dxgprocess *process,
849856
struct d3dkmt_opensyncobjectfromnthandle2
850857
*args,
851858
struct dxgsyncobject *syncobj);
859+
int dxgvmb_send_get_device_state(struct dxgprocess *process,
860+
struct dxgadapter *adapter,
861+
struct d3dkmt_getdevicestate *args,
862+
struct d3dkmt_getdevicestate *__user inargs);
852863
int dxgvmb_send_create_nt_shared_object(struct dxgprocess *process,
853864
struct d3dkmthandle object,
854865
struct d3dkmthandle *shared_handle);

drivers/hv/dxgkrnl/dxgmodule.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -827,7 +827,6 @@ static struct dxgglobal *dxgglobal_create(void)
827827
#ifdef DEBUG
828828
dxgk_validate_ioctls();
829829
#endif
830-
831830
return dxgglobal;
832831
}
833832

drivers/hv/dxgkrnl/dxgvmbus.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,24 @@ static void command_vm_to_host_init1(struct dxgkvmb_command_vm_to_host *command,
281281
command->channel_type = DXGKVMB_VM_TO_HOST;
282282
}
283283

284+
static void set_guest_data(struct dxgkvmb_command_host_to_vm *packet,
285+
u32 packet_length)
286+
{
287+
struct dxgkvmb_command_setguestdata *command = (void *)packet;
288+
struct dxgglobal *dxgglobal = dxggbl();
289+
290+
DXG_TRACE("Setting guest data: %d %d %p %p",
291+
command->data_type,
292+
command->data32,
293+
command->guest_pointer,
294+
&dxgglobal->device_state_counter);
295+
if (command->data_type == SETGUESTDATA_DATATYPE_DWORD &&
296+
command->guest_pointer == &dxgglobal->device_state_counter &&
297+
command->data32 != 0) {
298+
atomic_inc(&dxgglobal->device_state_counter);
299+
}
300+
}
301+
284302
static void signal_guest_event(struct dxgkvmb_command_host_to_vm *packet,
285303
u32 packet_length)
286304
{
@@ -311,6 +329,9 @@ static void process_inband_packet(struct dxgvmbuschannel *channel,
311329
DXG_TRACE("global packet %d",
312330
packet->command_type);
313331
switch (packet->command_type) {
332+
case DXGK_VMBCOMMAND_SETGUESTDATA:
333+
set_guest_data(packet, packet_length);
334+
break;
314335
case DXGK_VMBCOMMAND_SIGNALGUESTEVENT:
315336
case DXGK_VMBCOMMAND_SIGNALGUESTEVENTPASSIVE:
316337
signal_guest_event(packet, packet_length);
@@ -1028,6 +1049,7 @@ struct d3dkmthandle dxgvmb_send_create_device(struct dxgadapter *adapter,
10281049
struct dxgkvmb_command_createdevice *command;
10291050
struct dxgkvmb_command_createdevice_return result = { };
10301051
struct dxgvmbusmsg msg;
1052+
struct dxgglobal *dxgglobal = dxggbl();
10311053

10321054
ret = init_message(&msg, adapter, process, sizeof(*command));
10331055
if (ret)
@@ -1037,6 +1059,7 @@ struct d3dkmthandle dxgvmb_send_create_device(struct dxgadapter *adapter,
10371059
command_vgpu_to_host_init2(&command->hdr, DXGK_VMBCOMMAND_CREATEDEVICE,
10381060
process->host_handle);
10391061
command->flags = args->flags;
1062+
command->error_code = &dxgglobal->device_state_counter;
10401063

10411064
ret = dxgvmb_send_sync_msg(msg.channel, msg.hdr, msg.size,
10421065
&result, sizeof(result));
@@ -1806,6 +1829,51 @@ int dxgvmb_send_destroy_allocation(struct dxgprocess *process,
18061829
return ret;
18071830
}
18081831

1832+
int dxgvmb_send_get_device_state(struct dxgprocess *process,
1833+
struct dxgadapter *adapter,
1834+
struct d3dkmt_getdevicestate *args,
1835+
struct d3dkmt_getdevicestate *__user output)
1836+
{
1837+
int ret;
1838+
struct dxgkvmb_command_getdevicestate *command;
1839+
struct dxgkvmb_command_getdevicestate_return result = { };
1840+
struct dxgvmbusmsg msg = {.hdr = NULL};
1841+
1842+
ret = init_message(&msg, adapter, process, sizeof(*command));
1843+
if (ret)
1844+
goto cleanup;
1845+
command = (void *)msg.msg;
1846+
1847+
command_vgpu_to_host_init2(&command->hdr,
1848+
DXGK_VMBCOMMAND_GETDEVICESTATE,
1849+
process->host_handle);
1850+
command->args = *args;
1851+
1852+
ret = dxgvmb_send_sync_msg(msg.channel, msg.hdr, msg.size,
1853+
&result, sizeof(result));
1854+
if (ret < 0)
1855+
goto cleanup;
1856+
1857+
ret = ntstatus2int(result.status);
1858+
if (ret < 0)
1859+
goto cleanup;
1860+
1861+
ret = copy_to_user(output, &result.args, sizeof(result.args));
1862+
if (ret) {
1863+
DXG_ERR("failed to copy output args");
1864+
ret = -EINVAL;
1865+
}
1866+
1867+
if (args->state_type == _D3DKMT_DEVICESTATE_EXECUTION)
1868+
args->execution_state = result.args.execution_state;
1869+
1870+
cleanup:
1871+
free_message(&msg, process);
1872+
if (ret)
1873+
DXG_TRACE("err: %d", ret);
1874+
return ret;
1875+
}
1876+
18091877
int dxgvmb_send_open_resource(struct dxgprocess *process,
18101878
struct dxgadapter *adapter,
18111879
struct d3dkmthandle device,

drivers/hv/dxgkrnl/dxgvmbus.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,22 @@ struct dxgkvmb_command_signalguestevent {
172172
bool dereference_event;
173173
};
174174

175+
enum set_guestdata_type {
176+
SETGUESTDATA_DATATYPE_DWORD = 0,
177+
SETGUESTDATA_DATATYPE_UINT64 = 1
178+
};
179+
180+
struct dxgkvmb_command_setguestdata {
181+
struct dxgkvmb_command_host_to_vm hdr;
182+
void *guest_pointer;
183+
union {
184+
u64 data64;
185+
u32 data32;
186+
};
187+
u32 dereference : 1;
188+
u32 data_type : 4;
189+
};
190+
175191
struct dxgkvmb_command_opensyncobject {
176192
struct dxgkvmb_command_vm_to_host hdr;
177193
struct d3dkmthandle device;
@@ -574,6 +590,16 @@ struct dxgkvmb_command_destroyhwqueue {
574590
struct d3dkmthandle hwqueue;
575591
};
576592

593+
struct dxgkvmb_command_getdevicestate {
594+
struct dxgkvmb_command_vgpu_to_host hdr;
595+
struct d3dkmt_getdevicestate args;
596+
};
597+
598+
struct dxgkvmb_command_getdevicestate_return {
599+
struct d3dkmt_getdevicestate args;
600+
struct ntstatus status;
601+
};
602+
577603
struct dxgkvmb_command_shareobjectwithhost {
578604
struct dxgkvmb_command_vm_to_host hdr;
579605
struct d3dkmthandle device_handle;

drivers/hv/dxgkrnl/ioctl.c

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3142,6 +3142,70 @@ dxgkio_wait_sync_object_gpu(struct dxgprocess *process, void *__user inargs)
31423142
return ret;
31433143
}
31443144

3145+
static int
3146+
dxgkio_get_device_state(struct dxgprocess *process, void *__user inargs)
3147+
{
3148+
int ret;
3149+
struct d3dkmt_getdevicestate args;
3150+
struct dxgdevice *device = NULL;
3151+
struct dxgadapter *adapter = NULL;
3152+
int global_device_state_counter = 0;
3153+
struct dxgglobal *dxgglobal = dxggbl();
3154+
3155+
ret = copy_from_user(&args, inargs, sizeof(args));
3156+
if (ret) {
3157+
DXG_ERR("failed to copy input args");
3158+
ret = -EINVAL;
3159+
goto cleanup;
3160+
}
3161+
3162+
device = dxgprocess_device_by_handle(process, args.device);
3163+
if (device == NULL) {
3164+
ret = -EINVAL;
3165+
goto cleanup;
3166+
}
3167+
3168+
adapter = device->adapter;
3169+
ret = dxgadapter_acquire_lock_shared(adapter);
3170+
if (ret < 0) {
3171+
adapter = NULL;
3172+
goto cleanup;
3173+
}
3174+
3175+
if (args.state_type == _D3DKMT_DEVICESTATE_EXECUTION) {
3176+
global_device_state_counter =
3177+
atomic_read(&dxgglobal->device_state_counter);
3178+
if (device->execution_state_counter ==
3179+
global_device_state_counter) {
3180+
args.execution_state = device->execution_state;
3181+
ret = copy_to_user(inargs, &args, sizeof(args));
3182+
if (ret) {
3183+
DXG_ERR("failed to copy args to user");
3184+
ret = -EINVAL;
3185+
}
3186+
goto cleanup;
3187+
}
3188+
}
3189+
3190+
ret = dxgvmb_send_get_device_state(process, adapter, &args, inargs);
3191+
3192+
if (ret == 0 && args.state_type == _D3DKMT_DEVICESTATE_EXECUTION) {
3193+
device->execution_state = args.execution_state;
3194+
device->execution_state_counter = global_device_state_counter;
3195+
}
3196+
3197+
cleanup:
3198+
3199+
if (adapter)
3200+
dxgadapter_release_lock_shared(adapter);
3201+
if (device)
3202+
kref_put(&device->device_kref, dxgdevice_release);
3203+
if (ret < 0)
3204+
DXG_ERR("Failed to get device state %x", ret);
3205+
3206+
return ret;
3207+
}
3208+
31453209
static int
31463210
dxgsharedsyncobj_get_host_nt_handle(struct dxgsharedsyncobject *syncobj,
31473211
struct dxgprocess *process,
@@ -3822,7 +3886,7 @@ static struct ioctl_desc ioctls[] = {
38223886
/* 0x0b */ {},
38233887
/* 0x0c */ {},
38243888
/* 0x0d */ {},
3825-
/* 0x0e */ {},
3889+
/* 0x0e */ {dxgkio_get_device_state, LX_DXGETDEVICESTATE},
38263890
/* 0x0f */ {dxgkio_submit_command, LX_DXSUBMITCOMMAND},
38273891
/* 0x10 */ {dxgkio_create_sync_object, LX_DXCREATESYNCHRONIZATIONOBJECT},
38283892
/* 0x11 */ {dxgkio_signal_sync_object, LX_DXSIGNALSYNCHRONIZATIONOBJECT},

include/uapi/misc/d3dkmthk.h

Lines changed: 91 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,95 @@ struct d3dddi_destroypagingqueue {
236236
struct d3dkmthandle paging_queue;
237237
};
238238

239+
enum dxgk_render_pipeline_stage {
240+
_DXGK_RENDER_PIPELINE_STAGE_UNKNOWN = 0,
241+
_DXGK_RENDER_PIPELINE_STAGE_INPUT_ASSEMBLER = 1,
242+
_DXGK_RENDER_PIPELINE_STAGE_VERTEX_SHADER = 2,
243+
_DXGK_RENDER_PIPELINE_STAGE_GEOMETRY_SHADER = 3,
244+
_DXGK_RENDER_PIPELINE_STAGE_STREAM_OUTPUT = 4,
245+
_DXGK_RENDER_PIPELINE_STAGE_RASTERIZER = 5,
246+
_DXGK_RENDER_PIPELINE_STAGE_PIXEL_SHADER = 6,
247+
_DXGK_RENDER_PIPELINE_STAGE_OUTPUT_MERGER = 7,
248+
};
249+
250+
enum dxgk_page_fault_flags {
251+
_DXGK_PAGE_FAULT_WRITE = 0x1,
252+
_DXGK_PAGE_FAULT_FENCE_INVALID = 0x2,
253+
_DXGK_PAGE_FAULT_ADAPTER_RESET_REQUIRED = 0x4,
254+
_DXGK_PAGE_FAULT_ENGINE_RESET_REQUIRED = 0x8,
255+
_DXGK_PAGE_FAULT_FATAL_HARDWARE_ERROR = 0x10,
256+
_DXGK_PAGE_FAULT_IOMMU = 0x20,
257+
_DXGK_PAGE_FAULT_HW_CONTEXT_VALID = 0x40,
258+
_DXGK_PAGE_FAULT_PROCESS_HANDLE_VALID = 0x80,
259+
};
260+
261+
enum dxgk_general_error_code {
262+
_DXGK_GENERAL_ERROR_PAGE_FAULT = 0,
263+
_DXGK_GENERAL_ERROR_INVALID_INSTRUCTION = 1,
264+
};
265+
266+
struct dxgk_fault_error_code {
267+
union {
268+
struct {
269+
__u32 is_device_specific_code:1;
270+
enum dxgk_general_error_code general_error_code:31;
271+
};
272+
struct {
273+
__u32 is_device_specific_code_reserved_bit:1;
274+
__u32 device_specific_code:31;
275+
};
276+
};
277+
};
278+
279+
struct d3dkmt_devicereset_state {
280+
union {
281+
struct {
282+
__u32 desktop_switched:1;
283+
__u32 reserved:31;
284+
};
285+
__u32 value;
286+
};
287+
};
288+
289+
struct d3dkmt_devicepagefault_state {
290+
__u64 faulted_primitive_api_sequence_number;
291+
enum dxgk_render_pipeline_stage faulted_pipeline_stage;
292+
__u32 faulted_bind_table_entry;
293+
enum dxgk_page_fault_flags page_fault_flags;
294+
struct dxgk_fault_error_code fault_error_code;
295+
__u64 faulted_virtual_address;
296+
};
297+
298+
enum d3dkmt_deviceexecution_state {
299+
_D3DKMT_DEVICEEXECUTION_ACTIVE = 1,
300+
_D3DKMT_DEVICEEXECUTION_RESET = 2,
301+
_D3DKMT_DEVICEEXECUTION_HUNG = 3,
302+
_D3DKMT_DEVICEEXECUTION_STOPPED = 4,
303+
_D3DKMT_DEVICEEXECUTION_ERROR_OUTOFMEMORY = 5,
304+
_D3DKMT_DEVICEEXECUTION_ERROR_DMAFAULT = 6,
305+
_D3DKMT_DEVICEEXECUTION_ERROR_DMAPAGEFAULT = 7,
306+
};
307+
308+
enum d3dkmt_devicestate_type {
309+
_D3DKMT_DEVICESTATE_EXECUTION = 1,
310+
_D3DKMT_DEVICESTATE_PRESENT = 2,
311+
_D3DKMT_DEVICESTATE_RESET = 3,
312+
_D3DKMT_DEVICESTATE_PRESENT_DWM = 4,
313+
_D3DKMT_DEVICESTATE_PAGE_FAULT = 5,
314+
_D3DKMT_DEVICESTATE_PRESENT_QUEUE = 6,
315+
};
316+
317+
struct d3dkmt_getdevicestate {
318+
struct d3dkmthandle device;
319+
enum d3dkmt_devicestate_type state_type;
320+
union {
321+
enum d3dkmt_deviceexecution_state execution_state;
322+
struct d3dkmt_devicereset_state reset_state;
323+
struct d3dkmt_devicepagefault_state page_fault_state;
324+
char alignment[48];
325+
};
326+
};
327+
239328
enum d3dkmdt_gdisurfacetype {
240329
_D3DKMDT_GDISURFACE_INVALID = 0,
241330
_D3DKMDT_GDISURFACE_TEXTURE = 1,
@@ -759,16 +848,6 @@ struct d3dkmt_queryadapterinfo {
759848
__u32 private_data_size;
760849
};
761850

762-
enum d3dkmt_deviceexecution_state {
763-
_D3DKMT_DEVICEEXECUTION_ACTIVE = 1,
764-
_D3DKMT_DEVICEEXECUTION_RESET = 2,
765-
_D3DKMT_DEVICEEXECUTION_HUNG = 3,
766-
_D3DKMT_DEVICEEXECUTION_STOPPED = 4,
767-
_D3DKMT_DEVICEEXECUTION_ERROR_OUTOFMEMORY = 5,
768-
_D3DKMT_DEVICEEXECUTION_ERROR_DMAFAULT = 6,
769-
_D3DKMT_DEVICEEXECUTION_ERROR_DMAPAGEFAULT = 7,
770-
};
771-
772851
struct d3dddi_openallocationinfo2 {
773852
struct d3dkmthandle allocation;
774853
#ifdef __KERNEL__
@@ -978,6 +1057,8 @@ struct d3dkmt_shareobjectwithhost {
9781057
_IOWR(0x47, 0x07, struct d3dkmt_createpagingqueue)
9791058
#define LX_DXQUERYADAPTERINFO \
9801059
_IOWR(0x47, 0x09, struct d3dkmt_queryadapterinfo)
1060+
#define LX_DXGETDEVICESTATE \
1061+
_IOWR(0x47, 0x0e, struct d3dkmt_getdevicestate)
9811062
#define LX_DXSUBMITCOMMAND \
9821063
_IOWR(0x47, 0x0f, struct d3dkmt_submitcommand)
9831064
#define LX_DXCREATESYNCHRONIZATIONOBJECT \

0 commit comments

Comments
 (0)