Skip to content

Commit 11188a6

Browse files
Iouri Tarassovchessturo
authored andcommitted
drivers: hv: dxgkrnl: Implement known escapes
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>
1 parent 5e6876c commit 11188a6

4 files changed

Lines changed: 205 additions & 39 deletions

File tree

drivers/hv/dxgkrnl/dxgkrnl.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -953,7 +953,8 @@ int dxgvmb_send_query_alloc_residency(struct dxgprocess *process,
953953
*args);
954954
int dxgvmb_send_escape(struct dxgprocess *process,
955955
struct dxgadapter *adapter,
956-
struct d3dkmt_escape *args);
956+
struct d3dkmt_escape *args,
957+
bool user_mode);
957958
int dxgvmb_send_query_vidmem_info(struct dxgprocess *process,
958959
struct dxgadapter *adapter,
959960
struct d3dkmt_queryvideomemoryinfo *args,

drivers/hv/dxgkrnl/dxgvmbus.c

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2174,7 +2174,8 @@ int dxgvmb_send_query_alloc_residency(struct dxgprocess *process,
21742174

21752175
int dxgvmb_send_escape(struct dxgprocess *process,
21762176
struct dxgadapter *adapter,
2177-
struct d3dkmt_escape *args)
2177+
struct d3dkmt_escape *args,
2178+
bool user_mode)
21782179
{
21792180
int ret;
21802181
struct dxgkvmb_command_escape *command = NULL;
@@ -2203,13 +2204,18 @@ int dxgvmb_send_escape(struct dxgprocess *process,
22032204
command->priv_drv_data_size = args->priv_drv_data_size;
22042205
command->context = args->context;
22052206
if (args->priv_drv_data_size) {
2206-
ret = copy_from_user(command->priv_drv_data,
2207-
args->priv_drv_data,
2208-
args->priv_drv_data_size);
2209-
if (ret) {
2210-
DXG_ERR("failed to copy priv data");
2211-
ret = -EFAULT;
2212-
goto cleanup;
2207+
if (user_mode) {
2208+
ret = copy_from_user(command->priv_drv_data,
2209+
args->priv_drv_data,
2210+
args->priv_drv_data_size);
2211+
if (ret) {
2212+
DXG_ERR("failed to copy priv data");
2213+
ret = -EFAULT;
2214+
goto cleanup;
2215+
}
2216+
} else {
2217+
memcpy(command->priv_drv_data, args->priv_drv_data,
2218+
args->priv_drv_data_size);
22132219
}
22142220
}
22152221

@@ -2220,12 +2226,18 @@ int dxgvmb_send_escape(struct dxgprocess *process,
22202226
goto cleanup;
22212227

22222228
if (args->priv_drv_data_size) {
2223-
ret = copy_to_user(args->priv_drv_data,
2224-
command->priv_drv_data,
2225-
args->priv_drv_data_size);
2226-
if (ret) {
2227-
DXG_ERR("failed to copy priv data");
2228-
ret = -EINVAL;
2229+
if (user_mode) {
2230+
ret = copy_to_user(args->priv_drv_data,
2231+
command->priv_drv_data,
2232+
args->priv_drv_data_size);
2233+
if (ret) {
2234+
DXG_ERR("failed to copy priv data");
2235+
ret = -EINVAL;
2236+
}
2237+
} else {
2238+
memcpy(args->priv_drv_data,
2239+
command->priv_drv_data,
2240+
args->priv_drv_data_size);
22292241
}
22302242
}
22312243

drivers/hv/dxgkrnl/ioctl.c

Lines changed: 146 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4257,10 +4257,8 @@ dxgkio_change_vidmem_reservation(struct dxgprocess *process, void *__user inargs
42574257
}
42584258

42594259
ret = dxgadapter_acquire_lock_shared(adapter);
4260-
if (ret < 0) {
4261-
adapter = NULL;
4260+
if (ret < 0)
42624261
goto cleanup;
4263-
}
42644262
adapter_locked = true;
42654263
args.adapter.v = 0;
42664264
ret = dxgvmb_send_change_vidmem_reservation(process, adapter,
@@ -4299,10 +4297,8 @@ dxgkio_query_clock_calibration(struct dxgprocess *process, void *__user inargs)
42994297
}
43004298

43014299
ret = dxgadapter_acquire_lock_shared(adapter);
4302-
if (ret < 0) {
4303-
adapter = NULL;
4300+
if (ret < 0)
43044301
goto cleanup;
4305-
}
43064302
adapter_locked = true;
43074303

43084304
args.adapter = adapter->host_handle;
@@ -4349,10 +4345,8 @@ dxgkio_flush_heap_transitions(struct dxgprocess *process, void *__user inargs)
43494345
}
43504346

43514347
ret = dxgadapter_acquire_lock_shared(adapter);
4352-
if (ret < 0) {
4353-
adapter = NULL;
4348+
if (ret < 0)
43544349
goto cleanup;
4355-
}
43564350
adapter_locked = true;
43574351

43584352
args.adapter = adapter->host_handle;
@@ -4417,6 +4411,134 @@ dxgkio_invalidate_cache(struct dxgprocess *process, void *__user inargs)
44174411
return ret;
44184412
}
44194413

4414+
static int
4415+
build_test_command_buffer(struct dxgprocess *process,
4416+
struct dxgadapter *adapter,
4417+
struct d3dkmt_escape *args)
4418+
{
4419+
int ret;
4420+
struct d3dddi_buildtestcommandbuffer cmd;
4421+
struct d3dkmt_escape newargs = *args;
4422+
u32 buf_size;
4423+
struct d3dddi_buildtestcommandbuffer *buf = NULL;
4424+
struct d3dddi_buildtestcommandbuffer *__user ucmd;
4425+
4426+
ucmd = args->priv_drv_data;
4427+
if (args->priv_drv_data_size <
4428+
sizeof(struct d3dddi_buildtestcommandbuffer)) {
4429+
DXG_ERR("Invalid private data size");
4430+
return -EINVAL;
4431+
}
4432+
ret = copy_from_user(&cmd, ucmd, sizeof(cmd));
4433+
if (ret) {
4434+
DXG_ERR("Failed to copy private data");
4435+
return -EFAULT;
4436+
}
4437+
4438+
if (cmd.dma_buffer_size < sizeof(u32) ||
4439+
cmd.dma_buffer_size > D3DDDI_MAXTESTBUFFERSIZE ||
4440+
cmd.dma_buffer_priv_data_size >
4441+
D3DDDI_MAXTESTBUFFERPRIVATEDRIVERDATASIZE) {
4442+
DXG_ERR("Invalid DMA buffer or private data size");
4443+
return -EINVAL;
4444+
}
4445+
/* Allocate a new buffer for the escape call */
4446+
buf_size = sizeof(struct d3dddi_buildtestcommandbuffer) +
4447+
cmd.dma_buffer_size +
4448+
cmd.dma_buffer_priv_data_size;
4449+
buf = vzalloc(buf_size);
4450+
if (buf == NULL) {
4451+
ret = -ENOMEM;
4452+
goto cleanup;
4453+
}
4454+
*buf = cmd;
4455+
buf->dma_buffer = NULL;
4456+
buf->dma_buffer_priv_data = NULL;
4457+
4458+
/* Replace private data in the escape arguments and call the host */
4459+
newargs.priv_drv_data = buf;
4460+
newargs.priv_drv_data_size = buf_size;
4461+
ret = dxgvmb_send_escape(process, adapter, &newargs, false);
4462+
if (ret) {
4463+
DXG_ERR("Host failed escape");
4464+
goto cleanup;
4465+
}
4466+
4467+
ret = copy_to_user(&ucmd->dma_buffer_size, &buf->dma_buffer_size,
4468+
sizeof(u32));
4469+
if (ret) {
4470+
DXG_ERR("Failed to dma size to user");
4471+
ret = -EFAULT;
4472+
goto cleanup;
4473+
}
4474+
ret = copy_to_user(&ucmd->dma_buffer_priv_data_size,
4475+
&buf->dma_buffer_priv_data_size,
4476+
sizeof(u32));
4477+
if (ret) {
4478+
DXG_ERR("Failed to dma private data size to user");
4479+
ret = -EFAULT;
4480+
goto cleanup;
4481+
}
4482+
ret = copy_to_user(cmd.dma_buffer, (char *)buf + sizeof(*buf),
4483+
buf->dma_buffer_size);
4484+
if (ret) {
4485+
DXG_ERR("Failed to copy dma buffer to user");
4486+
ret = -EFAULT;
4487+
goto cleanup;
4488+
}
4489+
if (buf->dma_buffer_priv_data_size) {
4490+
ret = copy_to_user(cmd.dma_buffer_priv_data,
4491+
(char *)buf + sizeof(*buf) + cmd.dma_buffer_size,
4492+
buf->dma_buffer_priv_data_size);
4493+
if (ret) {
4494+
DXG_ERR("Failed to copy private data to user");
4495+
ret = -EFAULT;
4496+
goto cleanup;
4497+
}
4498+
}
4499+
4500+
cleanup:
4501+
if (buf)
4502+
vfree(buf);
4503+
return ret;
4504+
}
4505+
4506+
static int
4507+
driver_known_escape(struct dxgprocess *process,
4508+
struct dxgadapter *adapter,
4509+
struct d3dkmt_escape *args)
4510+
{
4511+
enum d3dkmt_escapetype escape_type;
4512+
int ret = 0;
4513+
4514+
if (args->priv_drv_data_size < sizeof(enum d3dddi_knownescapetype))
4515+
{
4516+
DXG_ERR("Invalid private data size");
4517+
return -EINVAL;
4518+
}
4519+
ret = copy_from_user(&escape_type, args->priv_drv_data,
4520+
sizeof(escape_type));
4521+
if (ret) {
4522+
DXG_ERR("Failed to read escape type");
4523+
return -EFAULT;
4524+
}
4525+
switch (escape_type) {
4526+
case _D3DDDI_DRIVERESCAPETYPE_TRANSLATEALLOCATIONHANDLE:
4527+
case _D3DDDI_DRIVERESCAPETYPE_TRANSLATERESOURCEHANDLE:
4528+
/*
4529+
* The host and VM handles are the same
4530+
*/
4531+
break;
4532+
case _D3DDDI_DRIVERESCAPETYPE_BUILDTESTCOMMANDBUFFER:
4533+
ret = build_test_command_buffer(process, adapter, args);
4534+
break;
4535+
default:
4536+
ret = dxgvmb_send_escape(process, adapter, args, true);
4537+
break;
4538+
}
4539+
return ret;
4540+
}
4541+
44204542
static int
44214543
dxgkio_escape(struct dxgprocess *process, void *__user inargs)
44224544
{
@@ -4438,14 +4560,17 @@ dxgkio_escape(struct dxgprocess *process, void *__user inargs)
44384560
}
44394561

44404562
ret = dxgadapter_acquire_lock_shared(adapter);
4441-
if (ret < 0) {
4442-
adapter = NULL;
4563+
if (ret < 0)
44434564
goto cleanup;
4444-
}
44454565
adapter_locked = true;
44464566

44474567
args.adapter = adapter->host_handle;
4448-
ret = dxgvmb_send_escape(process, adapter, &args);
4568+
4569+
if (args.type == _D3DKMT_ESCAPE_DRIVERPRIVATE &&
4570+
args.flags.driver_known_escape)
4571+
ret = driver_known_escape(process, adapter, &args);
4572+
else
4573+
ret = dxgvmb_send_escape(process, adapter, &args, true);
44494574

44504575
cleanup:
44514576

@@ -4485,10 +4610,8 @@ dxgkio_query_vidmem_info(struct dxgprocess *process, void *__user inargs)
44854610
}
44864611

44874612
ret = dxgadapter_acquire_lock_shared(adapter);
4488-
if (ret < 0) {
4489-
adapter = NULL;
4613+
if (ret < 0)
44904614
goto cleanup;
4491-
}
44924615
adapter_locked = true;
44934616

44944617
args.adapter = adapter->host_handle;
@@ -5323,9 +5446,9 @@ dxgkio_is_feature_enabled(struct dxgprocess *process, void *__user inargs)
53235446
{
53245447
struct d3dkmt_isfeatureenabled args;
53255448
struct dxgadapter *adapter = NULL;
5326-
struct dxgglobal *dxgglobal = dxggbl();
53275449
struct d3dkmt_isfeatureenabled *__user uargs = inargs;
53285450
int ret;
5451+
bool adapter_locked = false;
53295452

53305453
ret = copy_from_user(&args, inargs, sizeof(args));
53315454
if (ret) {
@@ -5340,11 +5463,10 @@ dxgkio_is_feature_enabled(struct dxgprocess *process, void *__user inargs)
53405463
goto cleanup;
53415464
}
53425465

5343-
if (adapter) {
5344-
ret = dxgadapter_acquire_lock_shared(adapter);
5345-
if (ret < 0)
5346-
goto cleanup;
5347-
}
5466+
ret = dxgadapter_acquire_lock_shared(adapter);
5467+
if (ret < 0)
5468+
goto cleanup;
5469+
adapter_locked = true;
53485470

53495471
ret = dxgvmb_send_is_feature_enabled(adapter, &args);
53505472
if (ret)
@@ -5354,10 +5476,10 @@ dxgkio_is_feature_enabled(struct dxgprocess *process, void *__user inargs)
53545476

53555477
cleanup:
53565478

5357-
if (adapter) {
5479+
if (adapter_locked)
53585480
dxgadapter_release_lock_shared(adapter);
5481+
if (adapter)
53595482
kref_put(&adapter->adapter_kref, dxgadapter_release);
5360-
}
53615483

53625484
DXG_TRACE_IOCTL_END(ret);
53635485
return ret;

include/uapi/misc/d3dkmthk.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,37 @@ struct d3dddi_destroypagingqueue {
237237
struct d3dkmthandle paging_queue;
238238
};
239239

240+
enum d3dddi_knownescapetype {
241+
_D3DDDI_DRIVERESCAPETYPE_TRANSLATEALLOCATIONHANDLE = 0,
242+
_D3DDDI_DRIVERESCAPETYPE_TRANSLATERESOURCEHANDLE = 1,
243+
_D3DDDI_DRIVERESCAPETYPE_CPUEVENTUSAGE = 2,
244+
_D3DDDI_DRIVERESCAPETYPE_BUILDTESTCOMMANDBUFFER = 3,
245+
};
246+
247+
struct d3dddi_translate_allocation_handle {
248+
enum d3dddi_knownescapetype escape_type;
249+
struct d3dkmthandle allocation;
250+
};
251+
252+
struct d3dddi_testcommand {
253+
char buffer[72];
254+
};
255+
256+
#define D3DDDI_MAXTESTBUFFERSIZE 4096
257+
#define D3DDDI_MAXTESTBUFFERPRIVATEDRIVERDATASIZE 1024
258+
259+
struct d3dddi_buildtestcommandbuffer {
260+
enum d3dddi_knownescapetype escape_type;
261+
struct d3dkmthandle device;
262+
struct d3dkmthandle context;
263+
__u32 flags;
264+
struct d3dddi_testcommand command;
265+
void *dma_buffer;
266+
void *dma_buffer_priv_data;
267+
__u32 dma_buffer_size;
268+
__u32 dma_buffer_priv_data_size;
269+
};
270+
240271
enum d3dkmt_escapetype {
241272
_D3DKMT_ESCAPE_DRIVERPRIVATE = 0,
242273
_D3DKMT_ESCAPE_VIDMM = 1,

0 commit comments

Comments
 (0)