Skip to content

Commit 6ddd3ce

Browse files
Iouri Tarassovchessturo
authored andcommitted
drivers: hv: dxgkrnl: Manage residency of allocations
Implement ioctls to manage residency of compute device allocations: - LX_DXMAKERESIDENT, - LX_DXEVICT. An allocation is "resident" when the compute devoce is setup to access it. It means that the allocation is in the local device memory or in non-pageable system memory. The current design does not support on demand compute device page faulting. An allocation must be resident before the compute device is allowed to access it. The LX_DXMAKERESIDENT ioctl instructs the video memory manager to make the given allocations resident. The operation is submitted to a paging queue (dxgpagingqueue). When the ioctl returns a "pending" status, a monitored fence sync object can be used to synchronize with the completion of the operation. The LX_DXEVICT ioctl istructs the video memory manager to evict the given allocations from device accessible memory. 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 9d333d6 commit 6ddd3ce

5 files changed

Lines changed: 322 additions & 2 deletions

File tree

drivers/hv/dxgkrnl/dxgkrnl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -810,6 +810,10 @@ int dxgvmb_send_create_allocation(struct dxgprocess *pr, struct dxgdevice *dev,
810810
int dxgvmb_send_destroy_allocation(struct dxgprocess *pr, struct dxgdevice *dev,
811811
struct d3dkmt_destroyallocation2 *args,
812812
struct d3dkmthandle *alloc_handles);
813+
int dxgvmb_send_make_resident(struct dxgprocess *pr, struct dxgadapter *adapter,
814+
struct d3dddi_makeresident *args);
815+
int dxgvmb_send_evict(struct dxgprocess *pr, struct dxgadapter *adapter,
816+
struct d3dkmt_evict *args);
813817
int dxgvmb_send_submit_command(struct dxgprocess *pr,
814818
struct dxgadapter *adapter,
815819
struct d3dkmt_submitcommand *args);

drivers/hv/dxgkrnl/dxgvmbus.c

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2279,6 +2279,104 @@ int dxgvmb_send_get_stdalloc_data(struct dxgdevice *device,
22792279
return ret;
22802280
}
22812281

2282+
int dxgvmb_send_make_resident(struct dxgprocess *process,
2283+
struct dxgadapter *adapter,
2284+
struct d3dddi_makeresident *args)
2285+
{
2286+
int ret;
2287+
u32 cmd_size;
2288+
struct dxgkvmb_command_makeresident_return result = { };
2289+
struct dxgkvmb_command_makeresident *command = NULL;
2290+
struct dxgvmbusmsg msg = {.hdr = NULL};
2291+
2292+
cmd_size = (args->alloc_count - 1) * sizeof(struct d3dkmthandle) +
2293+
sizeof(struct dxgkvmb_command_makeresident);
2294+
2295+
ret = init_message(&msg, adapter, process, cmd_size);
2296+
if (ret)
2297+
goto cleanup;
2298+
command = (void *)msg.msg;
2299+
2300+
ret = copy_from_user(command->allocations, args->allocation_list,
2301+
args->alloc_count *
2302+
sizeof(struct d3dkmthandle));
2303+
if (ret) {
2304+
DXG_ERR("failed to copy alloc handles");
2305+
ret = -EINVAL;
2306+
goto cleanup;
2307+
}
2308+
command_vgpu_to_host_init2(&command->hdr,
2309+
DXGK_VMBCOMMAND_MAKERESIDENT,
2310+
process->host_handle);
2311+
command->alloc_count = args->alloc_count;
2312+
command->paging_queue = args->paging_queue;
2313+
command->flags = args->flags;
2314+
2315+
ret = dxgvmb_send_sync_msg(msg.channel, msg.hdr, msg.size,
2316+
&result, sizeof(result));
2317+
if (ret < 0) {
2318+
DXG_ERR("send_make_resident failed %x", ret);
2319+
goto cleanup;
2320+
}
2321+
2322+
args->paging_fence_value = result.paging_fence_value;
2323+
args->num_bytes_to_trim = result.num_bytes_to_trim;
2324+
ret = ntstatus2int(result.status);
2325+
2326+
cleanup:
2327+
2328+
free_message(&msg, process);
2329+
if (ret)
2330+
DXG_TRACE("err: %d", ret);
2331+
return ret;
2332+
}
2333+
2334+
int dxgvmb_send_evict(struct dxgprocess *process,
2335+
struct dxgadapter *adapter,
2336+
struct d3dkmt_evict *args)
2337+
{
2338+
int ret;
2339+
u32 cmd_size;
2340+
struct dxgkvmb_command_evict_return result = { };
2341+
struct dxgkvmb_command_evict *command = NULL;
2342+
struct dxgvmbusmsg msg = {.hdr = NULL};
2343+
2344+
cmd_size = (args->alloc_count - 1) * sizeof(struct d3dkmthandle) +
2345+
sizeof(struct dxgkvmb_command_evict);
2346+
ret = init_message(&msg, adapter, process, cmd_size);
2347+
if (ret)
2348+
goto cleanup;
2349+
command = (void *)msg.msg;
2350+
ret = copy_from_user(command->allocations, args->allocations,
2351+
args->alloc_count *
2352+
sizeof(struct d3dkmthandle));
2353+
if (ret) {
2354+
DXG_ERR("failed to copy alloc handles");
2355+
ret = -EINVAL;
2356+
goto cleanup;
2357+
}
2358+
command_vgpu_to_host_init2(&command->hdr,
2359+
DXGK_VMBCOMMAND_EVICT, process->host_handle);
2360+
command->alloc_count = args->alloc_count;
2361+
command->device = args->device;
2362+
command->flags = args->flags;
2363+
2364+
ret = dxgvmb_send_sync_msg(msg.channel, msg.hdr, msg.size,
2365+
&result, sizeof(result));
2366+
if (ret < 0) {
2367+
DXG_ERR("send_evict failed %x", ret);
2368+
goto cleanup;
2369+
}
2370+
args->num_bytes_to_trim = result.num_bytes_to_trim;
2371+
2372+
cleanup:
2373+
2374+
free_message(&msg, process);
2375+
if (ret)
2376+
DXG_TRACE("err: %d", ret);
2377+
return ret;
2378+
}
2379+
22822380
int dxgvmb_send_submit_command(struct dxgprocess *process,
22832381
struct dxgadapter *adapter,
22842382
struct d3dkmt_submitcommand *args)

drivers/hv/dxgkrnl/dxgvmbus.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,33 @@ struct dxgkvmb_command_flushdevice {
372372
enum dxgdevice_flushschedulerreason reason;
373373
};
374374

375+
struct dxgkvmb_command_makeresident {
376+
struct dxgkvmb_command_vgpu_to_host hdr;
377+
struct d3dkmthandle device;
378+
struct d3dkmthandle paging_queue;
379+
struct d3dddi_makeresident_flags flags;
380+
u32 alloc_count;
381+
struct d3dkmthandle allocations[1];
382+
};
383+
384+
struct dxgkvmb_command_makeresident_return {
385+
u64 paging_fence_value;
386+
u64 num_bytes_to_trim;
387+
struct ntstatus status;
388+
};
389+
390+
struct dxgkvmb_command_evict {
391+
struct dxgkvmb_command_vgpu_to_host hdr;
392+
struct d3dkmthandle device;
393+
struct d3dddi_evict_flags flags;
394+
u32 alloc_count;
395+
struct d3dkmthandle allocations[1];
396+
};
397+
398+
struct dxgkvmb_command_evict_return {
399+
u64 num_bytes_to_trim;
400+
};
401+
375402
struct dxgkvmb_command_submitcommand {
376403
struct dxgkvmb_command_vgpu_to_host hdr;
377404
struct d3dkmt_submitcommand args;

drivers/hv/dxgkrnl/ioctl.c

Lines changed: 139 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1961,6 +1961,143 @@ dxgkio_destroy_allocation(struct dxgprocess *process, void *__user inargs)
19611961
return ret;
19621962
}
19631963

1964+
static int
1965+
dxgkio_make_resident(struct dxgprocess *process, void *__user inargs)
1966+
{
1967+
int ret, ret2;
1968+
struct d3dddi_makeresident args;
1969+
struct d3dddi_makeresident *input = inargs;
1970+
struct dxgdevice *device = NULL;
1971+
struct dxgadapter *adapter = NULL;
1972+
1973+
ret = copy_from_user(&args, inargs, sizeof(args));
1974+
if (ret) {
1975+
DXG_ERR("failed to copy input args");
1976+
ret = -EINVAL;
1977+
goto cleanup;
1978+
}
1979+
1980+
if (args.alloc_count > D3DKMT_MAKERESIDENT_ALLOC_MAX ||
1981+
args.alloc_count == 0) {
1982+
DXG_ERR("invalid number of allocations");
1983+
ret = -EINVAL;
1984+
goto cleanup;
1985+
}
1986+
if (args.paging_queue.v == 0) {
1987+
DXG_ERR("paging queue is missing");
1988+
ret = -EINVAL;
1989+
goto cleanup;
1990+
}
1991+
1992+
device = dxgprocess_device_by_object_handle(process,
1993+
HMGRENTRY_TYPE_DXGPAGINGQUEUE,
1994+
args.paging_queue);
1995+
if (device == NULL) {
1996+
ret = -EINVAL;
1997+
goto cleanup;
1998+
}
1999+
2000+
adapter = device->adapter;
2001+
ret = dxgadapter_acquire_lock_shared(adapter);
2002+
if (ret < 0) {
2003+
adapter = NULL;
2004+
goto cleanup;
2005+
}
2006+
2007+
ret = dxgvmb_send_make_resident(process, adapter, &args);
2008+
if (ret < 0)
2009+
goto cleanup;
2010+
/* STATUS_PENING is a success code > 0. It is returned to user mode */
2011+
if (!(ret == STATUS_PENDING || ret == 0)) {
2012+
DXG_ERR("Unexpected error %x", ret);
2013+
goto cleanup;
2014+
}
2015+
2016+
ret2 = copy_to_user(&input->paging_fence_value,
2017+
&args.paging_fence_value, sizeof(u64));
2018+
if (ret2) {
2019+
DXG_ERR("failed to copy paging fence");
2020+
ret = -EINVAL;
2021+
goto cleanup;
2022+
}
2023+
2024+
ret2 = copy_to_user(&input->num_bytes_to_trim,
2025+
&args.num_bytes_to_trim, sizeof(u64));
2026+
if (ret2) {
2027+
DXG_ERR("failed to copy bytes to trim");
2028+
ret = -EINVAL;
2029+
goto cleanup;
2030+
}
2031+
2032+
cleanup:
2033+
2034+
if (adapter)
2035+
dxgadapter_release_lock_shared(adapter);
2036+
if (device)
2037+
kref_put(&device->device_kref, dxgdevice_release);
2038+
2039+
DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
2040+
2041+
return ret;
2042+
}
2043+
2044+
static int
2045+
dxgkio_evict(struct dxgprocess *process, void *__user inargs)
2046+
{
2047+
int ret;
2048+
struct d3dkmt_evict args;
2049+
struct d3dkmt_evict *input = inargs;
2050+
struct dxgdevice *device = NULL;
2051+
struct dxgadapter *adapter = NULL;
2052+
2053+
ret = copy_from_user(&args, inargs, sizeof(args));
2054+
if (ret) {
2055+
DXG_ERR("failed to copy input args");
2056+
ret = -EINVAL;
2057+
goto cleanup;
2058+
}
2059+
2060+
if (args.alloc_count > D3DKMT_MAKERESIDENT_ALLOC_MAX ||
2061+
args.alloc_count == 0) {
2062+
DXG_ERR("invalid number of allocations");
2063+
ret = -EINVAL;
2064+
goto cleanup;
2065+
}
2066+
2067+
device = dxgprocess_device_by_handle(process, args.device);
2068+
if (device == NULL) {
2069+
ret = -EINVAL;
2070+
goto cleanup;
2071+
}
2072+
2073+
adapter = device->adapter;
2074+
ret = dxgadapter_acquire_lock_shared(adapter);
2075+
if (ret < 0) {
2076+
adapter = NULL;
2077+
goto cleanup;
2078+
}
2079+
2080+
ret = dxgvmb_send_evict(process, adapter, &args);
2081+
if (ret < 0)
2082+
goto cleanup;
2083+
2084+
ret = copy_to_user(&input->num_bytes_to_trim,
2085+
&args.num_bytes_to_trim, sizeof(u64));
2086+
if (ret) {
2087+
DXG_ERR("failed to copy bytes to trim to user");
2088+
ret = -EINVAL;
2089+
}
2090+
cleanup:
2091+
2092+
if (adapter)
2093+
dxgadapter_release_lock_shared(adapter);
2094+
if (device)
2095+
kref_put(&device->device_kref, dxgdevice_release);
2096+
2097+
DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
2098+
return ret;
2099+
}
2100+
19642101
static int
19652102
dxgkio_offer_allocations(struct dxgprocess *process, void *__user inargs)
19662103
{
@@ -4797,7 +4934,7 @@ static struct ioctl_desc ioctls[] = {
47974934
/* 0x08 */ {},
47984935
/* 0x09 */ {dxgkio_query_adapter_info, LX_DXQUERYADAPTERINFO},
47994936
/* 0x0a */ {dxgkio_query_vidmem_info, LX_DXQUERYVIDEOMEMORYINFO},
4800-
/* 0x0b */ {},
4937+
/* 0x0b */ {dxgkio_make_resident, LX_DXMAKERESIDENT},
48014938
/* 0x0c */ {},
48024939
/* 0x0d */ {dxgkio_escape, LX_DXESCAPE},
48034940
/* 0x0e */ {dxgkio_get_device_state, LX_DXGETDEVICESTATE},
@@ -4817,7 +4954,7 @@ static struct ioctl_desc ioctls[] = {
48174954
/* 0x1b */ {dxgkio_destroy_hwqueue, LX_DXDESTROYHWQUEUE},
48184955
/* 0x1c */ {dxgkio_destroy_paging_queue, LX_DXDESTROYPAGINGQUEUE},
48194956
/* 0x1d */ {dxgkio_destroy_sync_object, LX_DXDESTROYSYNCHRONIZATIONOBJECT},
4820-
/* 0x1e */ {},
4957+
/* 0x1e */ {dxgkio_evict, LX_DXEVICT},
48214958
/* 0x1f */ {dxgkio_flush_heap_transitions, LX_DXFLUSHHEAPTRANSITIONS},
48224959
/* 0x20 */ {},
48234960
/* 0x21 */ {dxgkio_get_context_process_scheduling_priority,

include/uapi/misc/d3dkmthk.h

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -962,6 +962,56 @@ struct d3dkmt_destroyallocation2 {
962962
struct d3dddicb_destroyallocation2flags flags;
963963
};
964964

965+
struct d3dddi_makeresident_flags {
966+
union {
967+
struct {
968+
__u32 cant_trim_further:1;
969+
__u32 must_succeed:1;
970+
__u32 reserved:30;
971+
};
972+
__u32 value;
973+
};
974+
};
975+
976+
struct d3dddi_makeresident {
977+
struct d3dkmthandle paging_queue;
978+
__u32 alloc_count;
979+
#ifdef __KERNEL__
980+
const struct d3dkmthandle *allocation_list;
981+
const __u32 *priority_list;
982+
#else
983+
__u64 allocation_list;
984+
__u64 priority_list;
985+
#endif
986+
struct d3dddi_makeresident_flags flags;
987+
__u64 paging_fence_value;
988+
__u64 num_bytes_to_trim;
989+
};
990+
991+
struct d3dddi_evict_flags {
992+
union {
993+
struct {
994+
__u32 evict_only_if_necessary:1;
995+
__u32 not_written_to:1;
996+
__u32 reserved:30;
997+
};
998+
__u32 value;
999+
};
1000+
};
1001+
1002+
struct d3dkmt_evict {
1003+
struct d3dkmthandle device;
1004+
__u32 alloc_count;
1005+
#ifdef __KERNEL__
1006+
const struct d3dkmthandle *allocations;
1007+
#else
1008+
__u64 allocations;
1009+
#endif
1010+
struct d3dddi_evict_flags flags;
1011+
__u32 reserved;
1012+
__u64 num_bytes_to_trim;
1013+
};
1014+
9651015
enum d3dkmt_memory_segment_group {
9661016
_D3DKMT_MEMORY_SEGMENT_GROUP_LOCAL = 0,
9671017
_D3DKMT_MEMORY_SEGMENT_GROUP_NON_LOCAL = 1
@@ -1407,6 +1457,8 @@ struct d3dkmt_shareobjectwithhost {
14071457
_IOWR(0x47, 0x09, struct d3dkmt_queryadapterinfo)
14081458
#define LX_DXQUERYVIDEOMEMORYINFO \
14091459
_IOWR(0x47, 0x0a, struct d3dkmt_queryvideomemoryinfo)
1460+
#define LX_DXMAKERESIDENT \
1461+
_IOWR(0x47, 0x0b, struct d3dddi_makeresident)
14101462
#define LX_DXESCAPE \
14111463
_IOWR(0x47, 0x0d, struct d3dkmt_escape)
14121464
#define LX_DXGETDEVICESTATE \
@@ -1437,6 +1489,8 @@ struct d3dkmt_shareobjectwithhost {
14371489
_IOWR(0x47, 0x19, struct d3dkmt_destroydevice)
14381490
#define LX_DXDESTROYSYNCHRONIZATIONOBJECT \
14391491
_IOWR(0x47, 0x1d, struct d3dkmt_destroysynchronizationobject)
1492+
#define LX_DXEVICT \
1493+
_IOWR(0x47, 0x1e, struct d3dkmt_evict)
14401494
#define LX_DXFLUSHHEAPTRANSITIONS \
14411495
_IOWR(0x47, 0x1f, struct d3dkmt_flushheaptransitions)
14421496
#define LX_DXGETCONTEXTINPROCESSSCHEDULINGPRIORITY \

0 commit comments

Comments
 (0)