From: Iouri Tarassov <[email protected]>

Implement ioctls to manage properties of a compute device allocation:
  - LX_DXUPDATEALLOCPROPERTY,
  - LX_DXSETALLOCATIONPRIORITY,
  - LX_DXGETALLOCATIONPRIORITY,
  - LX_DXQUERYALLOCATIONRESIDENCY.
  - LX_DXCHANGEVIDEOMEMORYRESERVATION,

The LX_DXUPDATEALLOCPROPERTY ioctl requests the host to update
various properties of a compute devoce allocation.

The LX_DXSETALLOCATIONPRIORITY and LX_DXGETALLOCATIONPRIORITY ioctls
are used to set/get allocation priority, which defines the
importance of the allocation to be in the local device memory.

The LX_DXQUERYALLOCATIONRESIDENCY ioctl queries if the allocation
is located in the compute device accessible memory.

The LX_DXCHANGEVIDEOMEMORYRESERVATION ioctl changes compute device
memory reservation of an allocation.

Signed-off-by: Iouri Tarassov <[email protected]>
[kms: forward port to 6.6 from 6.1. No code changes made.]
Signed-off-by: Kelsey Steele <[email protected]>
---
 drivers/hv/dxgkrnl/dxgkrnl.h  |  21 +++
 drivers/hv/dxgkrnl/dxgvmbus.c | 300 ++++++++++++++++++++++++++++++++++
 drivers/hv/dxgkrnl/dxgvmbus.h |  50 ++++++
 drivers/hv/dxgkrnl/ioctl.c    | 217 +++++++++++++++++++++++-
 include/uapi/misc/d3dkmthk.h  | 127 ++++++++++++++
 5 files changed, 708 insertions(+), 7 deletions(-)

diff --git a/drivers/hv/dxgkrnl/dxgkrnl.h b/drivers/hv/dxgkrnl/dxgkrnl.h
index 1d6b552f1c1a..7fefe4617488 100644
--- a/drivers/hv/dxgkrnl/dxgkrnl.h
+++ b/drivers/hv/dxgkrnl/dxgkrnl.h
@@ -851,6 +851,23 @@ int dxgvmb_send_lock2(struct dxgprocess *process,
 int dxgvmb_send_unlock2(struct dxgprocess *process,
                        struct dxgadapter *adapter,
                        struct d3dkmt_unlock2 *args);
+int dxgvmb_send_update_alloc_property(struct dxgprocess *process,
+                                     struct dxgadapter *adapter,
+                                     struct d3dddi_updateallocproperty *args,
+                                     struct d3dddi_updateallocproperty *__user
+                                     inargs);
+int dxgvmb_send_set_allocation_priority(struct dxgprocess *process,
+                                       struct dxgadapter *adapter,
+                                       struct d3dkmt_setallocationpriority *a);
+int dxgvmb_send_get_allocation_priority(struct dxgprocess *process,
+                                       struct dxgadapter *adapter,
+                                       struct d3dkmt_getallocationpriority *a);
+int dxgvmb_send_change_vidmem_reservation(struct dxgprocess *process,
+                                         struct dxgadapter *adapter,
+                                         struct d3dkmthandle other_process,
+                                         struct
+                                         d3dkmt_changevideomemoryreservation
+                                         *args);
 int dxgvmb_send_create_hwqueue(struct dxgprocess *process,
                               struct dxgadapter *adapter,
                               struct d3dkmt_createhwqueue *args,
@@ -870,6 +887,10 @@ int dxgvmb_send_open_sync_object_nt(struct dxgprocess 
*process,
                                    struct d3dkmt_opensyncobjectfromnthandle2
                                    *args,
                                    struct dxgsyncobject *syncobj);
+int dxgvmb_send_query_alloc_residency(struct dxgprocess *process,
+                                     struct dxgadapter *adapter,
+                                     struct d3dkmt_queryallocationresidency
+                                     *args);
 int dxgvmb_send_get_device_state(struct dxgprocess *process,
                                 struct dxgadapter *adapter,
                                 struct d3dkmt_getdevicestate *args,
diff --git a/drivers/hv/dxgkrnl/dxgvmbus.c b/drivers/hv/dxgkrnl/dxgvmbus.c
index a80f84d9065a..dd2c97fee27b 100644
--- a/drivers/hv/dxgkrnl/dxgvmbus.c
+++ b/drivers/hv/dxgkrnl/dxgvmbus.c
@@ -1829,6 +1829,79 @@ int dxgvmb_send_destroy_allocation(struct dxgprocess 
*process,
        return ret;
 }
 
+int dxgvmb_send_query_alloc_residency(struct dxgprocess *process,
+                                     struct dxgadapter *adapter,
+                                     struct d3dkmt_queryallocationresidency
+                                     *args)
+{
+       int ret = -EINVAL;
+       struct dxgkvmb_command_queryallocationresidency *command = NULL;
+       u32 cmd_size = sizeof(*command);
+       u32 alloc_size = 0;
+       u32 result_allocation_size = 0;
+       struct dxgkvmb_command_queryallocationresidency_return *result = NULL;
+       u32 result_size = sizeof(*result);
+       struct dxgvmbusmsgres msg = {.hdr = NULL};
+
+       if (args->allocation_count > DXG_MAX_VM_BUS_PACKET_SIZE) {
+               ret = -EINVAL;
+               goto cleanup;
+       }
+
+       if (args->allocation_count) {
+               alloc_size = args->allocation_count *
+                            sizeof(struct d3dkmthandle);
+               cmd_size += alloc_size;
+               result_allocation_size = args->allocation_count *
+                   sizeof(args->residency_status[0]);
+       } else {
+               result_allocation_size = sizeof(args->residency_status[0]);
+       }
+       result_size += result_allocation_size;
+
+       ret = init_message_res(&msg, adapter, process, cmd_size, result_size);
+       if (ret)
+               goto cleanup;
+       command = (void *)msg.msg;
+       result = msg.res;
+
+       command_vgpu_to_host_init2(&command->hdr,
+                                  DXGK_VMBCOMMAND_QUERYALLOCATIONRESIDENCY,
+                                  process->host_handle);
+       command->args = *args;
+       if (alloc_size) {
+               ret = copy_from_user(&command[1], args->allocations,
+                                    alloc_size);
+               if (ret) {
+                       DXG_ERR("failed to copy alloc handles");
+                       ret = -EINVAL;
+                       goto cleanup;
+               }
+       }
+
+       ret = dxgvmb_send_sync_msg(msg.channel, msg.hdr, msg.size,
+                                  result, msg.res_size);
+       if (ret < 0)
+               goto cleanup;
+
+       ret = ntstatus2int(result->status);
+       if (ret < 0)
+               goto cleanup;
+
+       ret = copy_to_user(args->residency_status, &result[1],
+                          result_allocation_size);
+       if (ret) {
+               DXG_ERR("failed to copy residency status");
+               ret = -EINVAL;
+       }
+
+cleanup:
+       free_message((struct dxgvmbusmsg *)&msg, process);
+       if (ret)
+               DXG_TRACE("err: %d", ret);
+       return ret;
+}
+
 int dxgvmb_send_get_device_state(struct dxgprocess *process,
                                 struct dxgadapter *adapter,
                                 struct d3dkmt_getdevicestate *args,
@@ -2461,6 +2534,233 @@ int dxgvmb_send_unlock2(struct dxgprocess *process,
        return ret;
 }
 
+int dxgvmb_send_update_alloc_property(struct dxgprocess *process,
+                                     struct dxgadapter *adapter,
+                                     struct d3dddi_updateallocproperty *args,
+                                     struct d3dddi_updateallocproperty *__user
+                                     inargs)
+{
+       int ret;
+       int ret1;
+       struct dxgkvmb_command_updateallocationproperty *command;
+       struct dxgkvmb_command_updateallocationproperty_return result = { };
+       struct dxgvmbusmsg msg = {.hdr = NULL};
+
+       ret = init_message(&msg, adapter, process, sizeof(*command));
+       if (ret)
+               goto cleanup;
+       command = (void *)msg.msg;
+
+       command_vgpu_to_host_init2(&command->hdr,
+                                  DXGK_VMBCOMMAND_UPDATEALLOCATIONPROPERTY,
+                                  process->host_handle);
+       command->args = *args;
+
+       ret = dxgvmb_send_sync_msg(msg.channel, msg.hdr, msg.size,
+                                  &result, sizeof(result));
+
+       if (ret < 0)
+               goto cleanup;
+       ret = ntstatus2int(result.status);
+       /* STATUS_PENING is a success code > 0 */
+       if (ret == STATUS_PENDING) {
+               ret1 = copy_to_user(&inargs->paging_fence_value,
+                                   &result.paging_fence_value,
+                                   sizeof(u64));
+               if (ret1) {
+                       DXG_ERR("failed to copy paging fence");
+                       ret = -EINVAL;
+               }
+       }
+cleanup:
+       free_message(&msg, process);
+       if (ret)
+               DXG_TRACE("err: %d", ret);
+       return ret;
+}
+
+int dxgvmb_send_set_allocation_priority(struct dxgprocess *process,
+                               struct dxgadapter *adapter,
+                               struct d3dkmt_setallocationpriority *args)
+{
+       u32 cmd_size = sizeof(struct dxgkvmb_command_setallocationpriority);
+       u32 alloc_size = 0;
+       u32 priority_size = 0;
+       struct dxgkvmb_command_setallocationpriority *command;
+       int ret;
+       struct d3dkmthandle *allocations;
+       struct dxgvmbusmsg msg = {.hdr = NULL};
+
+       if (args->allocation_count > DXG_MAX_VM_BUS_PACKET_SIZE) {
+               ret = -EINVAL;
+               goto cleanup;
+       }
+       if (args->resource.v) {
+               priority_size = sizeof(u32);
+               if (args->allocation_count != 0) {
+                       ret = -EINVAL;
+                       goto cleanup;
+               }
+       } else {
+               if (args->allocation_count == 0) {
+                       ret = -EINVAL;
+                       goto cleanup;
+               }
+               alloc_size = args->allocation_count *
+                            sizeof(struct d3dkmthandle);
+               cmd_size += alloc_size;
+               priority_size = sizeof(u32) * args->allocation_count;
+       }
+       cmd_size += priority_size;
+
+       ret = init_message(&msg, adapter, process, cmd_size);
+       if (ret)
+               goto cleanup;
+       command = (void *)msg.msg;
+
+       command_vgpu_to_host_init2(&command->hdr,
+                                  DXGK_VMBCOMMAND_SETALLOCATIONPRIORITY,
+                                  process->host_handle);
+       command->device = args->device;
+       command->allocation_count = args->allocation_count;
+       command->resource = args->resource;
+       allocations = (struct d3dkmthandle *) &command[1];
+       ret = copy_from_user(allocations, args->allocation_list,
+                            alloc_size);
+       if (ret) {
+               DXG_ERR("failed to copy alloc handle");
+               ret = -EINVAL;
+               goto cleanup;
+       }
+       ret = copy_from_user((u8 *) allocations + alloc_size,
+                               args->priorities, priority_size);
+       if (ret) {
+               DXG_ERR("failed to copy alloc priority");
+               ret = -EINVAL;
+               goto cleanup;
+       }
+
+       ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr, msg.size);
+
+cleanup:
+       free_message(&msg, process);
+       if (ret)
+               DXG_TRACE("err: %d", ret);
+       return ret;
+}
+
+int dxgvmb_send_get_allocation_priority(struct dxgprocess *process,
+                               struct dxgadapter *adapter,
+                               struct d3dkmt_getallocationpriority *args)
+{
+       u32 cmd_size = sizeof(struct dxgkvmb_command_getallocationpriority);
+       u32 result_size;
+       u32 alloc_size = 0;
+       u32 priority_size = 0;
+       struct dxgkvmb_command_getallocationpriority *command;
+       struct dxgkvmb_command_getallocationpriority_return *result;
+       int ret;
+       struct d3dkmthandle *allocations;
+       struct dxgvmbusmsgres msg = {.hdr = NULL};
+
+       if (args->allocation_count > DXG_MAX_VM_BUS_PACKET_SIZE) {
+               ret = -EINVAL;
+               goto cleanup;
+       }
+       if (args->resource.v) {
+               priority_size = sizeof(u32);
+               if (args->allocation_count != 0) {
+                       ret = -EINVAL;
+                       goto cleanup;
+               }
+       } else {
+               if (args->allocation_count == 0) {
+                       ret = -EINVAL;
+                       goto cleanup;
+               }
+               alloc_size = args->allocation_count *
+                       sizeof(struct d3dkmthandle);
+               cmd_size += alloc_size;
+               priority_size = sizeof(u32) * args->allocation_count;
+       }
+       result_size = sizeof(*result) + priority_size;
+
+       ret = init_message_res(&msg, adapter, process, cmd_size, result_size);
+       if (ret)
+               goto cleanup;
+       command = (void *)msg.msg;
+       result = msg.res;
+
+       command_vgpu_to_host_init2(&command->hdr,
+                                  DXGK_VMBCOMMAND_GETALLOCATIONPRIORITY,
+                                  process->host_handle);
+       command->device = args->device;
+       command->allocation_count = args->allocation_count;
+       command->resource = args->resource;
+       allocations = (struct d3dkmthandle *) &command[1];
+       ret = copy_from_user(allocations, args->allocation_list,
+                            alloc_size);
+       if (ret) {
+               DXG_ERR("failed to copy alloc handles");
+               ret = -EINVAL;
+               goto cleanup;
+       }
+
+       ret = dxgvmb_send_sync_msg(msg.channel, msg.hdr,
+                                  msg.size + msg.res_size,
+                                  result, msg.res_size);
+       if (ret < 0)
+               goto cleanup;
+
+       ret = ntstatus2int(result->status);
+       if (ret < 0)
+               goto cleanup;
+
+       ret = copy_to_user(args->priorities,
+                          (u8 *) result + sizeof(*result),
+                          priority_size);
+       if (ret) {
+               DXG_ERR("failed to copy priorities");
+               ret = -EINVAL;
+       }
+
+cleanup:
+       free_message((struct dxgvmbusmsg *)&msg, process);
+       if (ret)
+               DXG_TRACE("err: %d", ret);
+       return ret;
+}
+
+int dxgvmb_send_change_vidmem_reservation(struct dxgprocess *process,
+                                         struct dxgadapter *adapter,
+                                         struct d3dkmthandle other_process,
+                                         struct
+                                         d3dkmt_changevideomemoryreservation
+                                         *args)
+{
+       struct dxgkvmb_command_changevideomemoryreservation *command;
+       int ret;
+       struct dxgvmbusmsg msg = {.hdr = NULL};
+
+       ret = init_message(&msg, adapter, process, sizeof(*command));
+       if (ret)
+               goto cleanup;
+       command = (void *)msg.msg;
+
+       command_vgpu_to_host_init2(&command->hdr,
+                                  DXGK_VMBCOMMAND_CHANGEVIDEOMEMORYRESERVATION,
+                                  process->host_handle);
+       command->args = *args;
+       command->args.process = other_process.v;
+
+       ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr, msg.size);
+cleanup:
+       free_message(&msg, process);
+       if (ret)
+               DXG_TRACE("err: %d", ret);
+       return ret;
+}
+
 int dxgvmb_send_create_hwqueue(struct dxgprocess *process,
                               struct dxgadapter *adapter,
                               struct d3dkmt_createhwqueue *args,
diff --git a/drivers/hv/dxgkrnl/dxgvmbus.h b/drivers/hv/dxgkrnl/dxgvmbus.h
index 447bb1ba391b..dbb01b9ab066 100644
--- a/drivers/hv/dxgkrnl/dxgvmbus.h
+++ b/drivers/hv/dxgkrnl/dxgvmbus.h
@@ -308,6 +308,29 @@ struct dxgkvmb_command_queryadapterinfo_return {
        u8                              private_data[1];
 };
 
+/* Returns ntstatus */
+struct dxgkvmb_command_setallocationpriority {
+       struct dxgkvmb_command_vgpu_to_host hdr;
+       struct d3dkmthandle             device;
+       struct d3dkmthandle             resource;
+       u32                             allocation_count;
+       /* struct d3dkmthandle    allocations[allocation_count or 0]; */
+       /* u32 priorities[allocation_count or 1]; */
+};
+
+struct dxgkvmb_command_getallocationpriority {
+       struct dxgkvmb_command_vgpu_to_host hdr;
+       struct d3dkmthandle             device;
+       struct d3dkmthandle             resource;
+       u32                             allocation_count;
+       /* struct d3dkmthandle allocations[allocation_count or 0]; */
+};
+
+struct dxgkvmb_command_getallocationpriority_return {
+       struct ntstatus                 status;
+       /* u32 priorities[allocation_count or 1]; */
+};
+
 struct dxgkvmb_command_createdevice {
        struct dxgkvmb_command_vgpu_to_host hdr;
        struct d3dkmt_createdeviceflags flags;
@@ -589,6 +612,22 @@ struct dxgkvmb_command_unlock2 {
        bool                            use_legacy_unlock;
 };
 
+struct dxgkvmb_command_updateallocationproperty {
+       struct dxgkvmb_command_vgpu_to_host hdr;
+       struct d3dddi_updateallocproperty args;
+};
+
+struct dxgkvmb_command_updateallocationproperty_return {
+       u64                             paging_fence_value;
+       struct ntstatus                 status;
+};
+
+/* Returns ntstatus */
+struct dxgkvmb_command_changevideomemoryreservation {
+       struct dxgkvmb_command_vgpu_to_host hdr;
+       struct d3dkmt_changevideomemoryreservation args;
+};
+
 /* Returns the same structure */
 struct dxgkvmb_command_createhwqueue {
        struct dxgkvmb_command_vgpu_to_host hdr;
@@ -609,6 +648,17 @@ struct dxgkvmb_command_destroyhwqueue {
        struct d3dkmthandle             hwqueue;
 };
 
+struct dxgkvmb_command_queryallocationresidency {
+       struct dxgkvmb_command_vgpu_to_host hdr;
+       struct d3dkmt_queryallocationresidency args;
+       /* struct d3dkmthandle allocations[0 or number of allocations] */
+};
+
+struct dxgkvmb_command_queryallocationresidency_return {
+       struct ntstatus                 status;
+       /* d3dkmt_allocationresidencystatus[NumAllocations] */
+};
+
 struct dxgkvmb_command_getdevicestate {
        struct dxgkvmb_command_vgpu_to_host hdr;
        struct d3dkmt_getdevicestate    args;
diff --git a/drivers/hv/dxgkrnl/ioctl.c b/drivers/hv/dxgkrnl/ioctl.c
index 37e218443310..b626e2518ff2 100644
--- a/drivers/hv/dxgkrnl/ioctl.c
+++ b/drivers/hv/dxgkrnl/ioctl.c
@@ -3214,7 +3214,7 @@ dxgkio_lock2(struct dxgprocess *process, void *__user 
inargs)
                kref_put(&device->device_kref, dxgdevice_release);
 
 success:
-       DXG_TRACE("ioctl:%s %s %d", errorstr(ret), __func__, ret);
+       DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
        return ret;
 }
 
@@ -3294,7 +3294,209 @@ dxgkio_unlock2(struct dxgprocess *process, void *__user 
inargs)
                kref_put(&device->device_kref, dxgdevice_release);
 
 success:
-       DXG_TRACE("ioctl:%s %s %d", errorstr(ret), __func__, ret);
+       DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+       return ret;
+}
+
+static int
+dxgkio_update_alloc_property(struct dxgprocess *process, void *__user inargs)
+{
+       struct d3dddi_updateallocproperty args;
+       int ret;
+       struct dxgadapter *adapter = NULL;
+       struct dxgdevice *device = NULL;
+
+       ret = copy_from_user(&args, inargs, sizeof(args));
+       if (ret) {
+               DXG_ERR("failed to copy input args");
+               ret = -EINVAL;
+               goto cleanup;
+       }
+
+       device = dxgprocess_device_by_object_handle(process,
+                                               HMGRENTRY_TYPE_DXGPAGINGQUEUE,
+                                               args.paging_queue);
+       if (device == NULL) {
+               ret = -EINVAL;
+               goto cleanup;
+       }
+       adapter = device->adapter;
+       ret = dxgadapter_acquire_lock_shared(adapter);
+       if (ret < 0) {
+               adapter = NULL;
+               goto cleanup;
+       }
+
+       ret = dxgvmb_send_update_alloc_property(process, adapter,
+                                               &args, inargs);
+
+cleanup:
+       if (adapter)
+               dxgadapter_release_lock_shared(adapter);
+
+       if (device)
+               kref_put(&device->device_kref, dxgdevice_release);
+
+       DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+       return ret;
+}
+
+static int
+dxgkio_query_alloc_residency(struct dxgprocess *process, void *__user inargs)
+{
+       struct d3dkmt_queryallocationresidency args;
+       struct dxgadapter *adapter = NULL;
+       struct dxgdevice *device = NULL;
+       int ret;
+
+       ret = copy_from_user(&args, inargs, sizeof(args));
+       if (ret) {
+               DXG_ERR("failed to copy input args");
+               ret = -EINVAL;
+               goto cleanup;
+       }
+
+       if ((args.allocation_count == 0) == (args.resource.v == 0)) {
+               ret = -EINVAL;
+               goto cleanup;
+       }
+
+       device = dxgprocess_device_by_handle(process, args.device);
+       if (device == NULL) {
+               ret = -EINVAL;
+               goto cleanup;
+       }
+       adapter = device->adapter;
+       ret = dxgadapter_acquire_lock_shared(adapter);
+       if (ret < 0) {
+               adapter = NULL;
+               goto cleanup;
+       }
+       ret = dxgvmb_send_query_alloc_residency(process, adapter, &args);
+cleanup:
+       if (adapter)
+               dxgadapter_release_lock_shared(adapter);
+       if (device)
+               kref_put(&device->device_kref, dxgdevice_release);
+       DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+       return ret;
+}
+
+static int
+dxgkio_set_allocation_priority(struct dxgprocess *process, void *__user inargs)
+{
+       struct d3dkmt_setallocationpriority args;
+       struct dxgadapter *adapter = NULL;
+       struct dxgdevice *device = NULL;
+       int ret;
+
+       ret = copy_from_user(&args, inargs, sizeof(args));
+       if (ret) {
+               DXG_ERR("failed to copy input args");
+               ret = -EINVAL;
+               goto cleanup;
+       }
+       device = dxgprocess_device_by_handle(process, args.device);
+       if (device == NULL) {
+               ret = -EINVAL;
+               goto cleanup;
+       }
+       adapter = device->adapter;
+       ret = dxgadapter_acquire_lock_shared(adapter);
+       if (ret < 0) {
+               adapter = NULL;
+               goto cleanup;
+       }
+       ret = dxgvmb_send_set_allocation_priority(process, adapter, &args);
+cleanup:
+       if (adapter)
+               dxgadapter_release_lock_shared(adapter);
+       if (device)
+               kref_put(&device->device_kref, dxgdevice_release);
+       DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+       return ret;
+}
+
+static int
+dxgkio_get_allocation_priority(struct dxgprocess *process, void *__user inargs)
+{
+       struct d3dkmt_getallocationpriority args;
+       struct dxgadapter *adapter = NULL;
+       struct dxgdevice *device = NULL;
+       int ret;
+
+       ret = copy_from_user(&args, inargs, sizeof(args));
+       if (ret) {
+               DXG_ERR("failed to copy input args");
+               ret = -EINVAL;
+               goto cleanup;
+       }
+       device = dxgprocess_device_by_handle(process, args.device);
+       if (device == NULL) {
+               ret = -EINVAL;
+               goto cleanup;
+       }
+       adapter = device->adapter;
+       ret = dxgadapter_acquire_lock_shared(adapter);
+       if (ret < 0) {
+               adapter = NULL;
+               goto cleanup;
+       }
+       ret = dxgvmb_send_get_allocation_priority(process, adapter, &args);
+cleanup:
+       if (adapter)
+               dxgadapter_release_lock_shared(adapter);
+       if (device)
+               kref_put(&device->device_kref, dxgdevice_release);
+       DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
+       return ret;
+}
+
+static int
+dxgkio_change_vidmem_reservation(struct dxgprocess *process, void *__user 
inargs)
+{
+       struct d3dkmt_changevideomemoryreservation args;
+       int ret;
+       struct dxgadapter *adapter = NULL;
+       bool adapter_locked = false;
+
+       ret = copy_from_user(&args, inargs, sizeof(args));
+       if (ret) {
+               DXG_ERR("failed to copy input args");
+               ret = -EINVAL;
+               goto cleanup;
+       }
+
+       if (args.process != 0) {
+               DXG_ERR("setting memory reservation for other process");
+               ret = -EINVAL;
+               goto cleanup;
+       }
+
+       adapter = dxgprocess_adapter_by_handle(process, args.adapter);
+       if (adapter == NULL) {
+               ret = -EINVAL;
+               goto cleanup;
+       }
+
+       ret = dxgadapter_acquire_lock_shared(adapter);
+       if (ret < 0) {
+               adapter = NULL;
+               goto cleanup;
+       }
+       adapter_locked = true;
+       args.adapter.v = 0;
+       ret = dxgvmb_send_change_vidmem_reservation(process, adapter,
+                                                   zerohandle, &args);
+
+cleanup:
+
+       if (adapter_locked)
+               dxgadapter_release_lock_shared(adapter);
+       if (adapter)
+               kref_put(&adapter->adapter_kref, dxgadapter_release);
+
+       DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
        return ret;
 }
 
@@ -4050,7 +4252,8 @@ static struct ioctl_desc ioctls[] = {
 /* 0x13 */     {dxgkio_destroy_allocation, LX_DXDESTROYALLOCATION2},
 /* 0x14 */     {dxgkio_enum_adapters, LX_DXENUMADAPTERS2},
 /* 0x15 */     {dxgkio_close_adapter, LX_DXCLOSEADAPTER},
-/* 0x16 */     {},
+/* 0x16 */     {dxgkio_change_vidmem_reservation,
+                 LX_DXCHANGEVIDEOMEMORYRESERVATION},
 /* 0x17 */     {},
 /* 0x18 */     {dxgkio_create_hwqueue, LX_DXCREATEHWQUEUE},
 /* 0x19 */     {dxgkio_destroy_device, LX_DXDESTROYDEVICE},
@@ -4070,11 +4273,11 @@ static struct ioctl_desc ioctls[] = {
 /* 0x27 */     {},
 /* 0x28 */     {},
 /* 0x29 */     {},
-/* 0x2a */     {},
+/* 0x2a */     {dxgkio_query_alloc_residency, LX_DXQUERYALLOCATIONRESIDENCY},
 /* 0x2b */     {},
 /* 0x2c */     {},
 /* 0x2d */     {},
-/* 0x2e */     {},
+/* 0x2e */     {dxgkio_set_allocation_priority, LX_DXSETALLOCATIONPRIORITY},
 /* 0x2f */     {},
 /* 0x30 */     {},
 /* 0x31 */     {dxgkio_signal_sync_object_cpu,
@@ -4089,13 +4292,13 @@ static struct ioctl_desc ioctls[] = {
 /* 0x36 */     {dxgkio_submit_wait_to_hwqueue,
                 LX_DXSUBMITWAITFORSYNCOBJECTSTOHWQUEUE},
 /* 0x37 */     {dxgkio_unlock2, LX_DXUNLOCK2},
-/* 0x38 */     {},
+/* 0x38 */     {dxgkio_update_alloc_property, LX_DXUPDATEALLOCPROPERTY},
 /* 0x39 */     {},
 /* 0x3a */     {dxgkio_wait_sync_object_cpu,
                 LX_DXWAITFORSYNCHRONIZATIONOBJECTFROMCPU},
 /* 0x3b */     {dxgkio_wait_sync_object_gpu,
                 LX_DXWAITFORSYNCHRONIZATIONOBJECTFROMGPU},
-/* 0x3c */     {},
+/* 0x3c */     {dxgkio_get_allocation_priority, LX_DXGETALLOCATIONPRIORITY},
 /* 0x3d */     {},
 /* 0x3e */     {dxgkio_enum_adapters3, LX_DXENUMADAPTERS3},
 /* 0x3f */     {dxgkio_share_objects, LX_DXSHAREOBJECTS},
diff --git a/include/uapi/misc/d3dkmthk.h b/include/uapi/misc/d3dkmthk.h
index b498f09e694d..af381101fd90 100644
--- a/include/uapi/misc/d3dkmthk.h
+++ b/include/uapi/misc/d3dkmthk.h
@@ -668,6 +668,63 @@ struct d3dkmt_submitcommandtohwqueue {
 #endif
 };
 
+struct d3dkmt_setallocationpriority {
+       struct d3dkmthandle             device;
+       struct d3dkmthandle             resource;
+#ifdef __KERNEL__
+       const struct d3dkmthandle       *allocation_list;
+#else
+       __u64                           allocation_list;
+#endif
+       __u32                           allocation_count;
+       __u32                           reserved;
+#ifdef __KERNEL__
+       const __u32                     *priorities;
+#else
+       __u64                           priorities;
+#endif
+};
+
+struct d3dkmt_getallocationpriority {
+       struct d3dkmthandle             device;
+       struct d3dkmthandle             resource;
+#ifdef __KERNEL__
+       const struct d3dkmthandle       *allocation_list;
+#else
+       __u64                           allocation_list;
+#endif
+       __u32                           allocation_count;
+       __u32                           reserved;
+#ifdef __KERNEL__
+       __u32                           *priorities;
+#else
+       __u64                           priorities;
+#endif
+};
+
+enum d3dkmt_allocationresidencystatus {
+       _D3DKMT_ALLOCATIONRESIDENCYSTATUS_RESIDENTINGPUMEMORY           = 1,
+       _D3DKMT_ALLOCATIONRESIDENCYSTATUS_RESIDENTINSHAREDMEMORY        = 2,
+       _D3DKMT_ALLOCATIONRESIDENCYSTATUS_NOTRESIDENT                   = 3,
+};
+
+struct d3dkmt_queryallocationresidency {
+       struct d3dkmthandle                     device;
+       struct d3dkmthandle                     resource;
+#ifdef __KERNEL__
+       struct d3dkmthandle                     *allocations;
+#else
+       __u64                                   allocations;
+#endif
+       __u32                                   allocation_count;
+       __u32                                   reserved;
+#ifdef __KERNEL__
+       enum d3dkmt_allocationresidencystatus   *residency_status;
+#else
+       __u64                                   residency_status;
+#endif
+};
+
 struct d3dddicb_lock2flags {
        union {
                struct {
@@ -835,6 +892,11 @@ struct d3dkmt_destroyallocation2 {
        struct d3dddicb_destroyallocation2flags flags;
 };
 
+enum d3dkmt_memory_segment_group {
+       _D3DKMT_MEMORY_SEGMENT_GROUP_LOCAL      = 0,
+       _D3DKMT_MEMORY_SEGMENT_GROUP_NON_LOCAL  = 1
+};
+
 struct d3dkmt_adaptertype {
        union {
                struct {
@@ -886,6 +948,61 @@ struct d3dddi_openallocationinfo2 {
        __u64                   reserved[6];
 };
 
+struct d3dddi_updateallocproperty_flags {
+       union {
+               struct {
+                       __u32                   accessed_physically:1;
+                       __u32                   reserved:31;
+               };
+               __u32                           value;
+       };
+};
+
+struct d3dddi_segmentpreference {
+       union {
+               struct {
+                       __u32                   segment_id0:5;
+                       __u32                   direction0:1;
+                       __u32                   segment_id1:5;
+                       __u32                   direction1:1;
+                       __u32                   segment_id2:5;
+                       __u32                   direction2:1;
+                       __u32                   segment_id3:5;
+                       __u32                   direction3:1;
+                       __u32                   segment_id4:5;
+                       __u32                   direction4:1;
+                       __u32                   reserved:2;
+               };
+               __u32                           value;
+       };
+};
+
+struct d3dddi_updateallocproperty {
+       struct d3dkmthandle                     paging_queue;
+       struct d3dkmthandle                     allocation;
+       __u32                                   supported_segment_set;
+       struct d3dddi_segmentpreference         preferred_segment;
+       struct d3dddi_updateallocproperty_flags flags;
+       __u64                                   paging_fence_value;
+       union {
+               struct {
+                       __u32                   set_accessed_physically:1;
+                       __u32                   set_supported_segmentSet:1;
+                       __u32                   set_preferred_segment:1;
+                       __u32                   reserved:29;
+               };
+               __u32                           property_mask_value;
+       };
+};
+
+struct d3dkmt_changevideomemoryreservation {
+       __u64                   process;
+       struct d3dkmthandle     adapter;
+       enum d3dkmt_memory_segment_group memory_segment_group;
+       __u64                   reservation;
+       __u32                   physical_adapter_index;
+};
+
 struct d3dkmt_createhwqueue {
        struct d3dkmthandle     context;
        struct d3dddi_createhwqueueflags flags;
@@ -1099,6 +1216,8 @@ struct d3dkmt_shareobjectwithhost {
        _IOWR(0x47, 0x14, struct d3dkmt_enumadapters2)
 #define LX_DXCLOSEADAPTER              \
        _IOWR(0x47, 0x15, struct d3dkmt_closeadapter)
+#define LX_DXCHANGEVIDEOMEMORYRESERVATION \
+       _IOWR(0x47, 0x16, struct d3dkmt_changevideomemoryreservation)
 #define LX_DXCREATEHWQUEUE             \
        _IOWR(0x47, 0x18, struct d3dkmt_createhwqueue)
 #define LX_DXDESTROYHWQUEUE            \
@@ -1111,6 +1230,10 @@ struct d3dkmt_shareobjectwithhost {
        _IOWR(0x47, 0x1d, struct d3dkmt_destroysynchronizationobject)
 #define LX_DXLOCK2                     \
        _IOWR(0x47, 0x25, struct d3dkmt_lock2)
+#define LX_DXQUERYALLOCATIONRESIDENCY  \
+       _IOWR(0x47, 0x2a, struct d3dkmt_queryallocationresidency)
+#define LX_DXSETALLOCATIONPRIORITY     \
+       _IOWR(0x47, 0x2e, struct d3dkmt_setallocationpriority)
 #define LX_DXSIGNALSYNCHRONIZATIONOBJECTFROMCPU \
        _IOWR(0x47, 0x31, struct d3dkmt_signalsynchronizationobjectfromcpu)
 #define LX_DXSIGNALSYNCHRONIZATIONOBJECTFROMGPU \
@@ -1125,10 +1248,14 @@ struct d3dkmt_shareobjectwithhost {
        _IOWR(0x47, 0x36, struct d3dkmt_submitwaitforsyncobjectstohwqueue)
 #define LX_DXUNLOCK2                   \
        _IOWR(0x47, 0x37, struct d3dkmt_unlock2)
+#define LX_DXUPDATEALLOCPROPERTY       \
+       _IOWR(0x47, 0x38, struct d3dddi_updateallocproperty)
 #define LX_DXWAITFORSYNCHRONIZATIONOBJECTFROMCPU \
        _IOWR(0x47, 0x3a, struct d3dkmt_waitforsynchronizationobjectfromcpu)
 #define LX_DXWAITFORSYNCHRONIZATIONOBJECTFROMGPU \
        _IOWR(0x47, 0x3b, struct d3dkmt_waitforsynchronizationobjectfromgpu)
+#define LX_DXGETALLOCATIONPRIORITY     \
+       _IOWR(0x47, 0x3c, struct d3dkmt_getallocationpriority)
 #define LX_DXENUMADAPTERS3             \
        _IOWR(0x47, 0x3e, struct d3dkmt_enumadapters3)
 #define LX_DXSHAREOBJECTS              \

Reply via email to