Skip to content

Commit 1418968

Browse files
Iouri Tarassovchessturo
authored andcommitted
drivers: hv: dxgkrnl: Offer and reclaim allocations
Implement ioctls to offer and reclaim compute device allocations: - LX_DXOFFERALLOCATIONS, - LX_DXRECLAIMALLOCATIONS2 When a user mode driver (UMD) does not need to access an allocation, it can "offer" it by issuing the LX_DXOFFERALLOCATIONS ioctl. This means that the allocation is not in use and its local device memory could be evicted. The freed space could be given to another allocation. When the allocation is again needed, the UMD can attempt to"reclaim" the allocation by issuing the LX_DXRECLAIMALLOCATIONS2 ioctl. If the allocation is still not evicted, the reclaim operation succeeds and no other action is required. If the reclaim operation fails, the caller must restore the content of the allocation before it can be used by the device. 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 7deec1c commit 1418968

5 files changed

Lines changed: 340 additions & 3 deletions

File tree

drivers/hv/dxgkrnl/dxgkrnl.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -865,6 +865,14 @@ int dxgvmb_send_set_allocation_priority(struct dxgprocess *process,
865865
int dxgvmb_send_get_allocation_priority(struct dxgprocess *process,
866866
struct dxgadapter *adapter,
867867
struct d3dkmt_getallocationpriority *a);
868+
int dxgvmb_send_offer_allocations(struct dxgprocess *process,
869+
struct dxgadapter *adapter,
870+
struct d3dkmt_offerallocations *args);
871+
int dxgvmb_send_reclaim_allocations(struct dxgprocess *process,
872+
struct dxgadapter *adapter,
873+
struct d3dkmthandle device,
874+
struct d3dkmt_reclaimallocations2 *args,
875+
u64 __user *paging_fence_value);
868876
int dxgvmb_send_change_vidmem_reservation(struct dxgprocess *process,
869877
struct dxgadapter *adapter,
870878
struct d3dkmthandle other_process,

drivers/hv/dxgkrnl/dxgvmbus.c

Lines changed: 123 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1858,7 +1858,7 @@ int dxgvmb_send_query_clock_calibration(struct dxgprocess *process,
18581858
ret = copy_to_user(&inargs->clock_data, &result.clock_data,
18591859
sizeof(result.clock_data));
18601860
if (ret) {
1861-
pr_err("%s failed to copy clock data", __func__);
1861+
DXG_ERR("failed to copy clock data");
18621862
ret = -EINVAL;
18631863
goto cleanup;
18641864
}
@@ -2949,6 +2949,128 @@ int dxgvmb_send_get_allocation_priority(struct dxgprocess *process,
29492949
return ret;
29502950
}
29512951

2952+
int dxgvmb_send_offer_allocations(struct dxgprocess *process,
2953+
struct dxgadapter *adapter,
2954+
struct d3dkmt_offerallocations *args)
2955+
{
2956+
struct dxgkvmb_command_offerallocations *command;
2957+
int ret = -EINVAL;
2958+
u32 alloc_size = sizeof(struct d3dkmthandle) * args->allocation_count;
2959+
u32 cmd_size = sizeof(struct dxgkvmb_command_offerallocations) +
2960+
alloc_size - sizeof(struct d3dkmthandle);
2961+
struct dxgvmbusmsg msg = {.hdr = NULL};
2962+
2963+
ret = init_message(&msg, adapter, process, cmd_size);
2964+
if (ret)
2965+
goto cleanup;
2966+
command = (void *)msg.msg;
2967+
2968+
command_vgpu_to_host_init2(&command->hdr,
2969+
DXGK_VMBCOMMAND_OFFERALLOCATIONS,
2970+
process->host_handle);
2971+
command->flags = args->flags;
2972+
command->priority = args->priority;
2973+
command->device = args->device;
2974+
command->allocation_count = args->allocation_count;
2975+
if (args->resources) {
2976+
command->resources = true;
2977+
ret = copy_from_user(command->allocations, args->resources,
2978+
alloc_size);
2979+
} else {
2980+
ret = copy_from_user(command->allocations,
2981+
args->allocations, alloc_size);
2982+
}
2983+
if (ret) {
2984+
DXG_ERR("failed to copy input handles");
2985+
ret = -EINVAL;
2986+
goto cleanup;
2987+
}
2988+
2989+
ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr, msg.size);
2990+
2991+
cleanup:
2992+
free_message(&msg, process);
2993+
if (ret)
2994+
pr_debug("err: %s %d", __func__, ret);
2995+
return ret;
2996+
}
2997+
2998+
int dxgvmb_send_reclaim_allocations(struct dxgprocess *process,
2999+
struct dxgadapter *adapter,
3000+
struct d3dkmthandle device,
3001+
struct d3dkmt_reclaimallocations2 *args,
3002+
u64 __user *paging_fence_value)
3003+
{
3004+
struct dxgkvmb_command_reclaimallocations *command;
3005+
struct dxgkvmb_command_reclaimallocations_return *result;
3006+
int ret;
3007+
u32 alloc_size = sizeof(struct d3dkmthandle) * args->allocation_count;
3008+
u32 cmd_size = sizeof(struct dxgkvmb_command_reclaimallocations) +
3009+
alloc_size - sizeof(struct d3dkmthandle);
3010+
u32 result_size = sizeof(*result);
3011+
struct dxgvmbusmsgres msg = {.hdr = NULL};
3012+
3013+
if (args->results)
3014+
result_size += (args->allocation_count - 1) *
3015+
sizeof(enum d3dddi_reclaim_result);
3016+
3017+
ret = init_message_res(&msg, adapter, process, cmd_size, result_size);
3018+
if (ret)
3019+
goto cleanup;
3020+
command = (void *)msg.msg;
3021+
result = msg.res;
3022+
3023+
command_vgpu_to_host_init2(&command->hdr,
3024+
DXGK_VMBCOMMAND_RECLAIMALLOCATIONS,
3025+
process->host_handle);
3026+
command->device = device;
3027+
command->paging_queue = args->paging_queue;
3028+
command->allocation_count = args->allocation_count;
3029+
command->write_results = args->results != NULL;
3030+
if (args->resources) {
3031+
command->resources = true;
3032+
ret = copy_from_user(command->allocations, args->resources,
3033+
alloc_size);
3034+
} else {
3035+
ret = copy_from_user(command->allocations,
3036+
args->allocations, alloc_size);
3037+
}
3038+
if (ret) {
3039+
DXG_ERR("failed to copy input handles");
3040+
ret = -EINVAL;
3041+
goto cleanup;
3042+
}
3043+
3044+
ret = dxgvmb_send_sync_msg(msg.channel, msg.hdr, msg.size,
3045+
result, msg.res_size);
3046+
if (ret < 0)
3047+
goto cleanup;
3048+
ret = copy_to_user(paging_fence_value,
3049+
&result->paging_fence_value, sizeof(u64));
3050+
if (ret) {
3051+
DXG_ERR("failed to copy paging fence");
3052+
ret = -EINVAL;
3053+
goto cleanup;
3054+
}
3055+
3056+
ret = ntstatus2int(result->status);
3057+
if (NT_SUCCESS(result->status) && args->results) {
3058+
ret = copy_to_user(args->results, result->discarded,
3059+
sizeof(result->discarded[0]) *
3060+
args->allocation_count);
3061+
if (ret) {
3062+
DXG_ERR("failed to copy results");
3063+
ret = -EINVAL;
3064+
}
3065+
}
3066+
3067+
cleanup:
3068+
free_message((struct dxgvmbusmsg *)&msg, process);
3069+
if (ret)
3070+
pr_debug("err: %s %d", __func__, ret);
3071+
return ret;
3072+
}
3073+
29523074
int dxgvmb_send_change_vidmem_reservation(struct dxgprocess *process,
29533075
struct dxgadapter *adapter,
29543076
struct d3dkmthandle other_process,

drivers/hv/dxgkrnl/dxgvmbus.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,33 @@ struct dxgkvmb_command_markdeviceaserror {
653653
struct d3dkmt_markdeviceaserror args;
654654
};
655655

656+
/* Returns ntstatus */
657+
struct dxgkvmb_command_offerallocations {
658+
struct dxgkvmb_command_vgpu_to_host hdr;
659+
struct d3dkmthandle device;
660+
u32 allocation_count;
661+
enum d3dkmt_offer_priority priority;
662+
struct d3dkmt_offer_flags flags;
663+
bool resources;
664+
struct d3dkmthandle allocations[1];
665+
};
666+
667+
struct dxgkvmb_command_reclaimallocations {
668+
struct dxgkvmb_command_vgpu_to_host hdr;
669+
struct d3dkmthandle device;
670+
struct d3dkmthandle paging_queue;
671+
u32 allocation_count;
672+
bool resources;
673+
bool write_results;
674+
struct d3dkmthandle allocations[1];
675+
};
676+
677+
struct dxgkvmb_command_reclaimallocations_return {
678+
u64 paging_fence_value;
679+
struct ntstatus status;
680+
enum d3dddi_reclaim_result discarded[1];
681+
};
682+
656683
/* Returns ntstatus */
657684
struct dxgkvmb_command_changevideomemoryreservation {
658685
struct dxgkvmb_command_vgpu_to_host hdr;

drivers/hv/dxgkrnl/ioctl.c

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

1964+
static int
1965+
dxgkio_offer_allocations(struct dxgprocess *process, void *__user inargs)
1966+
{
1967+
int ret;
1968+
struct d3dkmt_offerallocations args;
1969+
struct dxgdevice *device = NULL;
1970+
struct dxgadapter *adapter = NULL;
1971+
1972+
ret = copy_from_user(&args, inargs, sizeof(args));
1973+
if (ret) {
1974+
DXG_ERR("failed to copy input args");
1975+
ret = -EINVAL;
1976+
goto cleanup;
1977+
}
1978+
1979+
if (args.allocation_count > D3DKMT_MAKERESIDENT_ALLOC_MAX ||
1980+
args.allocation_count == 0) {
1981+
DXG_ERR("invalid number of allocations");
1982+
ret = -EINVAL;
1983+
goto cleanup;
1984+
}
1985+
1986+
if ((args.resources == NULL) == (args.allocations == NULL)) {
1987+
DXG_ERR("invalid pointer to resources/allocations");
1988+
ret = -EINVAL;
1989+
goto cleanup;
1990+
}
1991+
1992+
device = dxgprocess_device_by_handle(process, args.device);
1993+
if (device == NULL) {
1994+
ret = -EINVAL;
1995+
goto cleanup;
1996+
}
1997+
1998+
adapter = device->adapter;
1999+
ret = dxgadapter_acquire_lock_shared(adapter);
2000+
if (ret < 0) {
2001+
adapter = NULL;
2002+
goto cleanup;
2003+
}
2004+
2005+
ret = dxgvmb_send_offer_allocations(process, adapter, &args);
2006+
2007+
cleanup:
2008+
2009+
if (adapter)
2010+
dxgadapter_release_lock_shared(adapter);
2011+
if (device)
2012+
kref_put(&device->device_kref, dxgdevice_release);
2013+
2014+
DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
2015+
return ret;
2016+
}
2017+
2018+
static int
2019+
dxgkio_reclaim_allocations(struct dxgprocess *process, void *__user inargs)
2020+
{
2021+
int ret;
2022+
struct d3dkmt_reclaimallocations2 args;
2023+
struct dxgdevice *device = NULL;
2024+
struct dxgadapter *adapter = NULL;
2025+
struct d3dkmt_reclaimallocations2 * __user in_args = inargs;
2026+
2027+
ret = copy_from_user(&args, inargs, sizeof(args));
2028+
if (ret) {
2029+
DXG_ERR("failed to copy input args");
2030+
ret = -EINVAL;
2031+
goto cleanup;
2032+
}
2033+
2034+
if (args.allocation_count > D3DKMT_MAKERESIDENT_ALLOC_MAX ||
2035+
args.allocation_count == 0) {
2036+
DXG_ERR("invalid number of allocations");
2037+
ret = -EINVAL;
2038+
goto cleanup;
2039+
}
2040+
2041+
if ((args.resources == NULL) == (args.allocations == NULL)) {
2042+
DXG_ERR("invalid pointer to resources/allocations");
2043+
ret = -EINVAL;
2044+
goto cleanup;
2045+
}
2046+
2047+
device = dxgprocess_device_by_object_handle(process,
2048+
HMGRENTRY_TYPE_DXGPAGINGQUEUE,
2049+
args.paging_queue);
2050+
if (device == NULL) {
2051+
ret = -EINVAL;
2052+
goto cleanup;
2053+
}
2054+
2055+
adapter = device->adapter;
2056+
ret = dxgadapter_acquire_lock_shared(adapter);
2057+
if (ret < 0) {
2058+
adapter = NULL;
2059+
goto cleanup;
2060+
}
2061+
2062+
ret = dxgvmb_send_reclaim_allocations(process, adapter,
2063+
device->handle, &args,
2064+
&in_args->paging_fence_value);
2065+
2066+
cleanup:
2067+
2068+
if (adapter)
2069+
dxgadapter_release_lock_shared(adapter);
2070+
if (device)
2071+
kref_put(&device->device_kref, dxgdevice_release);
2072+
2073+
DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
2074+
return ret;
2075+
}
2076+
19642077
static int
19652078
dxgkio_submit_command(struct dxgprocess *process, void *__user inargs)
19662079
{
@@ -4548,12 +4661,12 @@ static struct ioctl_desc ioctls[] = {
45484661
/* 0x24 */ {},
45494662
/* 0x25 */ {dxgkio_lock2, LX_DXLOCK2},
45504663
/* 0x26 */ {dxgkio_mark_device_as_error, LX_DXMARKDEVICEASERROR},
4551-
/* 0x27 */ {},
4664+
/* 0x27 */ {dxgkio_offer_allocations, LX_DXOFFERALLOCATIONS},
45524665
/* 0x28 */ {},
45534666
/* 0x29 */ {},
45544667
/* 0x2a */ {dxgkio_query_alloc_residency, LX_DXQUERYALLOCATIONRESIDENCY},
45554668
/* 0x2b */ {},
4556-
/* 0x2c */ {},
4669+
/* 0x2c */ {dxgkio_reclaim_allocations, LX_DXRECLAIMALLOCATIONS2},
45574670
/* 0x2d */ {},
45584671
/* 0x2e */ {dxgkio_set_allocation_priority, LX_DXSETALLOCATIONPRIORITY},
45594672
/* 0x2f */ {},

0 commit comments

Comments
 (0)