mirror of https://github.com/armbian/build.git
829 lines
24 KiB
Diff
829 lines
24 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Iouri Tarassov <iourit@linux.microsoft.com>
|
|
Date: Tue, 1 Feb 2022 17:23:58 -0800
|
|
Subject: drivers: hv: dxgkrnl: Creation of dxgdevice objects
|
|
|
|
Implement ioctls for creation and destruction of dxgdevice
|
|
objects:
|
|
- the LX_DXCREATEDEVICE ioctl
|
|
- the LX_DXDESTROYDEVICE ioctl
|
|
|
|
A dxgdevice object represents a container of other virtual
|
|
compute device objects (allocations, sync objects, contexts,
|
|
etc.). It belongs to a dxgadapter object.
|
|
|
|
Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>
|
|
[kms: Forward port to v6.1]
|
|
Signed-off-by: Kelsey Steele <kelseysteele@microsoft.com>
|
|
---
|
|
drivers/hv/dxgkrnl/dxgadapter.c | 187 ++++++++++
|
|
drivers/hv/dxgkrnl/dxgkrnl.h | 58 +++
|
|
drivers/hv/dxgkrnl/dxgprocess.c | 43 +++
|
|
drivers/hv/dxgkrnl/dxgvmbus.c | 80 ++++
|
|
drivers/hv/dxgkrnl/dxgvmbus.h | 22 ++
|
|
drivers/hv/dxgkrnl/ioctl.c | 130 ++++++-
|
|
drivers/hv/dxgkrnl/misc.h | 8 +-
|
|
include/uapi/misc/d3dkmthk.h | 82 ++++
|
|
8 files changed, 604 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/drivers/hv/dxgkrnl/dxgadapter.c b/drivers/hv/dxgkrnl/dxgadapter.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/hv/dxgkrnl/dxgadapter.c
|
|
+++ b/drivers/hv/dxgkrnl/dxgadapter.c
|
|
@@ -194,6 +194,122 @@ void dxgadapter_release_lock_shared(struct dxgadapter *adapter)
|
|
up_read(&adapter->core_lock);
|
|
}
|
|
|
|
+struct dxgdevice *dxgdevice_create(struct dxgadapter *adapter,
|
|
+ struct dxgprocess *process)
|
|
+{
|
|
+ struct dxgdevice *device;
|
|
+ int ret;
|
|
+
|
|
+ device = kzalloc(sizeof(struct dxgdevice), GFP_KERNEL);
|
|
+ if (device) {
|
|
+ kref_init(&device->device_kref);
|
|
+ device->adapter = adapter;
|
|
+ device->process = process;
|
|
+ kref_get(&adapter->adapter_kref);
|
|
+ init_rwsem(&device->device_lock);
|
|
+ INIT_LIST_HEAD(&device->pqueue_list_head);
|
|
+ device->object_state = DXGOBJECTSTATE_CREATED;
|
|
+ device->execution_state = _D3DKMT_DEVICEEXECUTION_ACTIVE;
|
|
+
|
|
+ ret = dxgprocess_adapter_add_device(process, adapter, device);
|
|
+ if (ret < 0) {
|
|
+ kref_put(&device->device_kref, dxgdevice_release);
|
|
+ device = NULL;
|
|
+ }
|
|
+ }
|
|
+ return device;
|
|
+}
|
|
+
|
|
+void dxgdevice_stop(struct dxgdevice *device)
|
|
+{
|
|
+}
|
|
+
|
|
+void dxgdevice_mark_destroyed(struct dxgdevice *device)
|
|
+{
|
|
+ down_write(&device->device_lock);
|
|
+ device->object_state = DXGOBJECTSTATE_DESTROYED;
|
|
+ up_write(&device->device_lock);
|
|
+}
|
|
+
|
|
+void dxgdevice_destroy(struct dxgdevice *device)
|
|
+{
|
|
+ struct dxgprocess *process = device->process;
|
|
+ struct dxgadapter *adapter = device->adapter;
|
|
+ struct d3dkmthandle device_handle = {};
|
|
+
|
|
+ DXG_TRACE("Destroying device: %p", device);
|
|
+
|
|
+ down_write(&device->device_lock);
|
|
+
|
|
+ if (device->object_state != DXGOBJECTSTATE_ACTIVE)
|
|
+ goto cleanup;
|
|
+
|
|
+ device->object_state = DXGOBJECTSTATE_DESTROYED;
|
|
+
|
|
+ dxgdevice_stop(device);
|
|
+
|
|
+ /* Guest handles need to be released before the host handles */
|
|
+ hmgrtable_lock(&process->handle_table, DXGLOCK_EXCL);
|
|
+ if (device->handle_valid) {
|
|
+ hmgrtable_free_handle(&process->handle_table,
|
|
+ HMGRENTRY_TYPE_DXGDEVICE, device->handle);
|
|
+ device_handle = device->handle;
|
|
+ device->handle_valid = 0;
|
|
+ }
|
|
+ hmgrtable_unlock(&process->handle_table, DXGLOCK_EXCL);
|
|
+
|
|
+ if (device_handle.v) {
|
|
+ up_write(&device->device_lock);
|
|
+ if (dxgadapter_acquire_lock_shared(adapter) == 0) {
|
|
+ dxgvmb_send_destroy_device(adapter, process,
|
|
+ device_handle);
|
|
+ dxgadapter_release_lock_shared(adapter);
|
|
+ }
|
|
+ down_write(&device->device_lock);
|
|
+ }
|
|
+
|
|
+cleanup:
|
|
+
|
|
+ if (device->adapter) {
|
|
+ dxgprocess_adapter_remove_device(device);
|
|
+ kref_put(&device->adapter->adapter_kref, dxgadapter_release);
|
|
+ device->adapter = NULL;
|
|
+ }
|
|
+
|
|
+ up_write(&device->device_lock);
|
|
+
|
|
+ kref_put(&device->device_kref, dxgdevice_release);
|
|
+ DXG_TRACE("Device destroyed");
|
|
+}
|
|
+
|
|
+int dxgdevice_acquire_lock_shared(struct dxgdevice *device)
|
|
+{
|
|
+ down_read(&device->device_lock);
|
|
+ if (!dxgdevice_is_active(device)) {
|
|
+ up_read(&device->device_lock);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+void dxgdevice_release_lock_shared(struct dxgdevice *device)
|
|
+{
|
|
+ up_read(&device->device_lock);
|
|
+}
|
|
+
|
|
+bool dxgdevice_is_active(struct dxgdevice *device)
|
|
+{
|
|
+ return device->object_state == DXGOBJECTSTATE_ACTIVE;
|
|
+}
|
|
+
|
|
+void dxgdevice_release(struct kref *refcount)
|
|
+{
|
|
+ struct dxgdevice *device;
|
|
+
|
|
+ device = container_of(refcount, struct dxgdevice, device_kref);
|
|
+ kfree(device);
|
|
+}
|
|
+
|
|
struct dxgprocess_adapter *dxgprocess_adapter_create(struct dxgprocess *process,
|
|
struct dxgadapter *adapter)
|
|
{
|
|
@@ -208,6 +324,8 @@ struct dxgprocess_adapter *dxgprocess_adapter_create(struct dxgprocess *process,
|
|
adapter_info->adapter = adapter;
|
|
adapter_info->process = process;
|
|
adapter_info->refcount = 1;
|
|
+ mutex_init(&adapter_info->device_list_mutex);
|
|
+ INIT_LIST_HEAD(&adapter_info->device_list_head);
|
|
list_add_tail(&adapter_info->process_adapter_list_entry,
|
|
&process->process_adapter_list_head);
|
|
dxgadapter_add_process(adapter, adapter_info);
|
|
@@ -221,10 +339,34 @@ struct dxgprocess_adapter *dxgprocess_adapter_create(struct dxgprocess *process,
|
|
|
|
void dxgprocess_adapter_stop(struct dxgprocess_adapter *adapter_info)
|
|
{
|
|
+ struct dxgdevice *device;
|
|
+
|
|
+ mutex_lock(&adapter_info->device_list_mutex);
|
|
+ list_for_each_entry(device, &adapter_info->device_list_head,
|
|
+ device_list_entry) {
|
|
+ dxgdevice_stop(device);
|
|
+ }
|
|
+ mutex_unlock(&adapter_info->device_list_mutex);
|
|
}
|
|
|
|
void dxgprocess_adapter_destroy(struct dxgprocess_adapter *adapter_info)
|
|
{
|
|
+ struct dxgdevice *device;
|
|
+
|
|
+ mutex_lock(&adapter_info->device_list_mutex);
|
|
+ while (!list_empty(&adapter_info->device_list_head)) {
|
|
+ device = list_first_entry(&adapter_info->device_list_head,
|
|
+ struct dxgdevice, device_list_entry);
|
|
+ list_del(&device->device_list_entry);
|
|
+ device->device_list_entry.next = NULL;
|
|
+ mutex_unlock(&adapter_info->device_list_mutex);
|
|
+ dxgvmb_send_flush_device(device,
|
|
+ DXGDEVICE_FLUSHSCHEDULER_DEVICE_TERMINATE);
|
|
+ dxgdevice_destroy(device);
|
|
+ mutex_lock(&adapter_info->device_list_mutex);
|
|
+ }
|
|
+ mutex_unlock(&adapter_info->device_list_mutex);
|
|
+
|
|
dxgadapter_remove_process(adapter_info);
|
|
kref_put(&adapter_info->adapter->adapter_kref, dxgadapter_release);
|
|
list_del(&adapter_info->process_adapter_list_entry);
|
|
@@ -240,3 +382,48 @@ void dxgprocess_adapter_release(struct dxgprocess_adapter *adapter_info)
|
|
if (adapter_info->refcount == 0)
|
|
dxgprocess_adapter_destroy(adapter_info);
|
|
}
|
|
+
|
|
+int dxgprocess_adapter_add_device(struct dxgprocess *process,
|
|
+ struct dxgadapter *adapter,
|
|
+ struct dxgdevice *device)
|
|
+{
|
|
+ struct dxgprocess_adapter *entry;
|
|
+ struct dxgprocess_adapter *adapter_info = NULL;
|
|
+ int ret = 0;
|
|
+
|
|
+ dxgglobal_acquire_process_adapter_lock();
|
|
+
|
|
+ list_for_each_entry(entry, &process->process_adapter_list_head,
|
|
+ process_adapter_list_entry) {
|
|
+ if (entry->adapter == adapter) {
|
|
+ adapter_info = entry;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if (adapter_info == NULL) {
|
|
+ DXG_ERR("failed to find process adapter info");
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ mutex_lock(&adapter_info->device_list_mutex);
|
|
+ list_add_tail(&device->device_list_entry,
|
|
+ &adapter_info->device_list_head);
|
|
+ device->adapter_info = adapter_info;
|
|
+ mutex_unlock(&adapter_info->device_list_mutex);
|
|
+
|
|
+cleanup:
|
|
+
|
|
+ dxgglobal_release_process_adapter_lock();
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+void dxgprocess_adapter_remove_device(struct dxgdevice *device)
|
|
+{
|
|
+ DXG_TRACE("Removing device: %p", device);
|
|
+ mutex_lock(&device->adapter_info->device_list_mutex);
|
|
+ if (device->device_list_entry.next) {
|
|
+ list_del(&device->device_list_entry);
|
|
+ device->device_list_entry.next = NULL;
|
|
+ }
|
|
+ mutex_unlock(&device->adapter_info->device_list_mutex);
|
|
+}
|
|
diff --git a/drivers/hv/dxgkrnl/dxgkrnl.h b/drivers/hv/dxgkrnl/dxgkrnl.h
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/hv/dxgkrnl/dxgkrnl.h
|
|
+++ b/drivers/hv/dxgkrnl/dxgkrnl.h
|
|
@@ -34,6 +34,7 @@
|
|
|
|
struct dxgprocess;
|
|
struct dxgadapter;
|
|
+struct dxgdevice;
|
|
|
|
/*
|
|
* Driver private data.
|
|
@@ -71,6 +72,10 @@ struct dxgk_device_types {
|
|
u32 virtual_monitor_device:1;
|
|
};
|
|
|
|
+enum dxgdevice_flushschedulerreason {
|
|
+ DXGDEVICE_FLUSHSCHEDULER_DEVICE_TERMINATE = 4,
|
|
+};
|
|
+
|
|
enum dxgobjectstate {
|
|
DXGOBJECTSTATE_CREATED,
|
|
DXGOBJECTSTATE_ACTIVE,
|
|
@@ -166,6 +171,9 @@ struct dxgprocess_adapter {
|
|
struct list_head adapter_process_list_entry;
|
|
/* Entry in dxgprocess::process_adapter_list_head */
|
|
struct list_head process_adapter_list_entry;
|
|
+ /* List of all dxgdevice objects created for the process on adapter */
|
|
+ struct list_head device_list_head;
|
|
+ struct mutex device_list_mutex;
|
|
struct dxgadapter *adapter;
|
|
struct dxgprocess *process;
|
|
int refcount;
|
|
@@ -175,6 +183,10 @@ struct dxgprocess_adapter *dxgprocess_adapter_create(struct dxgprocess *process,
|
|
struct dxgadapter
|
|
*adapter);
|
|
void dxgprocess_adapter_release(struct dxgprocess_adapter *adapter);
|
|
+int dxgprocess_adapter_add_device(struct dxgprocess *process,
|
|
+ struct dxgadapter *adapter,
|
|
+ struct dxgdevice *device);
|
|
+void dxgprocess_adapter_remove_device(struct dxgdevice *device);
|
|
void dxgprocess_adapter_stop(struct dxgprocess_adapter *adapter_info);
|
|
void dxgprocess_adapter_destroy(struct dxgprocess_adapter *adapter_info);
|
|
|
|
@@ -222,6 +234,11 @@ struct dxgadapter *dxgprocess_get_adapter(struct dxgprocess *process,
|
|
struct d3dkmthandle handle);
|
|
struct dxgadapter *dxgprocess_adapter_by_handle(struct dxgprocess *process,
|
|
struct d3dkmthandle handle);
|
|
+struct dxgdevice *dxgprocess_device_by_handle(struct dxgprocess *process,
|
|
+ struct d3dkmthandle handle);
|
|
+struct dxgdevice *dxgprocess_device_by_object_handle(struct dxgprocess *process,
|
|
+ enum hmgrentry_type t,
|
|
+ struct d3dkmthandle h);
|
|
void dxgprocess_ht_lock_shared_down(struct dxgprocess *process);
|
|
void dxgprocess_ht_lock_shared_up(struct dxgprocess *process);
|
|
void dxgprocess_ht_lock_exclusive_down(struct dxgprocess *process);
|
|
@@ -241,6 +258,7 @@ enum dxgadapter_state {
|
|
* This object represents the grapchis adapter.
|
|
* Objects, which take reference on the adapter:
|
|
* - dxgglobal
|
|
+ * - dxgdevice
|
|
* - adapter handle (struct d3dkmthandle)
|
|
*/
|
|
struct dxgadapter {
|
|
@@ -277,6 +295,38 @@ void dxgadapter_add_process(struct dxgadapter *adapter,
|
|
struct dxgprocess_adapter *process_info);
|
|
void dxgadapter_remove_process(struct dxgprocess_adapter *process_info);
|
|
|
|
+/*
|
|
+ * The object represent the device object.
|
|
+ * The following objects take reference on the device
|
|
+ * - device handle (struct d3dkmthandle)
|
|
+ */
|
|
+struct dxgdevice {
|
|
+ enum dxgobjectstate object_state;
|
|
+ /* Device takes reference on the adapter */
|
|
+ struct dxgadapter *adapter;
|
|
+ struct dxgprocess_adapter *adapter_info;
|
|
+ struct dxgprocess *process;
|
|
+ /* Entry in the DGXPROCESS_ADAPTER device list */
|
|
+ struct list_head device_list_entry;
|
|
+ struct kref device_kref;
|
|
+ /* Protects destcruction of the device object */
|
|
+ struct rw_semaphore device_lock;
|
|
+ /* List of paging queues. Protected by process handle table lock. */
|
|
+ struct list_head pqueue_list_head;
|
|
+ struct d3dkmthandle handle;
|
|
+ enum d3dkmt_deviceexecution_state execution_state;
|
|
+ u32 handle_valid;
|
|
+};
|
|
+
|
|
+struct dxgdevice *dxgdevice_create(struct dxgadapter *a, struct dxgprocess *p);
|
|
+void dxgdevice_destroy(struct dxgdevice *device);
|
|
+void dxgdevice_stop(struct dxgdevice *device);
|
|
+void dxgdevice_mark_destroyed(struct dxgdevice *device);
|
|
+int dxgdevice_acquire_lock_shared(struct dxgdevice *dev);
|
|
+void dxgdevice_release_lock_shared(struct dxgdevice *dev);
|
|
+void dxgdevice_release(struct kref *refcount);
|
|
+bool dxgdevice_is_active(struct dxgdevice *dev);
|
|
+
|
|
long dxgk_compat_ioctl(struct file *f, unsigned int p1, unsigned long p2);
|
|
long dxgk_unlocked_ioctl(struct file *f, unsigned int p1, unsigned long p2);
|
|
|
|
@@ -313,6 +363,14 @@ int dxgvmb_send_destroy_process(struct d3dkmthandle process);
|
|
int dxgvmb_send_open_adapter(struct dxgadapter *adapter);
|
|
int dxgvmb_send_close_adapter(struct dxgadapter *adapter);
|
|
int dxgvmb_send_get_internal_adapter_info(struct dxgadapter *adapter);
|
|
+struct d3dkmthandle dxgvmb_send_create_device(struct dxgadapter *adapter,
|
|
+ struct dxgprocess *process,
|
|
+ struct d3dkmt_createdevice *args);
|
|
+int dxgvmb_send_destroy_device(struct dxgadapter *adapter,
|
|
+ struct dxgprocess *process,
|
|
+ struct d3dkmthandle h);
|
|
+int dxgvmb_send_flush_device(struct dxgdevice *device,
|
|
+ enum dxgdevice_flushschedulerreason reason);
|
|
int dxgvmb_send_query_adapter_info(struct dxgprocess *process,
|
|
struct dxgadapter *adapter,
|
|
struct d3dkmt_queryadapterinfo *args);
|
|
diff --git a/drivers/hv/dxgkrnl/dxgprocess.c b/drivers/hv/dxgkrnl/dxgprocess.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/hv/dxgkrnl/dxgprocess.c
|
|
+++ b/drivers/hv/dxgkrnl/dxgprocess.c
|
|
@@ -241,6 +241,49 @@ struct dxgadapter *dxgprocess_adapter_by_handle(struct dxgprocess *process,
|
|
return adapter;
|
|
}
|
|
|
|
+struct dxgdevice *dxgprocess_device_by_object_handle(struct dxgprocess *process,
|
|
+ enum hmgrentry_type t,
|
|
+ struct d3dkmthandle handle)
|
|
+{
|
|
+ struct dxgdevice *device = NULL;
|
|
+ void *obj;
|
|
+
|
|
+ hmgrtable_lock(&process->handle_table, DXGLOCK_SHARED);
|
|
+ obj = hmgrtable_get_object_by_type(&process->handle_table, t, handle);
|
|
+ if (obj) {
|
|
+ struct d3dkmthandle device_handle = {};
|
|
+
|
|
+ switch (t) {
|
|
+ case HMGRENTRY_TYPE_DXGDEVICE:
|
|
+ device = obj;
|
|
+ break;
|
|
+ default:
|
|
+ DXG_ERR("invalid handle type: %d", t);
|
|
+ break;
|
|
+ }
|
|
+ if (device == NULL)
|
|
+ device = hmgrtable_get_object_by_type(
|
|
+ &process->handle_table,
|
|
+ HMGRENTRY_TYPE_DXGDEVICE,
|
|
+ device_handle);
|
|
+ if (device)
|
|
+ if (kref_get_unless_zero(&device->device_kref) == 0)
|
|
+ device = NULL;
|
|
+ }
|
|
+ if (device == NULL)
|
|
+ DXG_ERR("device_by_handle failed: %d %x", t, handle.v);
|
|
+ hmgrtable_unlock(&process->handle_table, DXGLOCK_SHARED);
|
|
+ return device;
|
|
+}
|
|
+
|
|
+struct dxgdevice *dxgprocess_device_by_handle(struct dxgprocess *process,
|
|
+ struct d3dkmthandle handle)
|
|
+{
|
|
+ return dxgprocess_device_by_object_handle(process,
|
|
+ HMGRENTRY_TYPE_DXGDEVICE,
|
|
+ handle);
|
|
+}
|
|
+
|
|
void dxgprocess_ht_lock_shared_down(struct dxgprocess *process)
|
|
{
|
|
hmgrtable_lock(&process->handle_table, DXGLOCK_SHARED);
|
|
diff --git a/drivers/hv/dxgkrnl/dxgvmbus.c b/drivers/hv/dxgkrnl/dxgvmbus.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/hv/dxgkrnl/dxgvmbus.c
|
|
+++ b/drivers/hv/dxgkrnl/dxgvmbus.c
|
|
@@ -673,6 +673,86 @@ int dxgvmb_send_get_internal_adapter_info(struct dxgadapter *adapter)
|
|
return ret;
|
|
}
|
|
|
|
+struct d3dkmthandle dxgvmb_send_create_device(struct dxgadapter *adapter,
|
|
+ struct dxgprocess *process,
|
|
+ struct d3dkmt_createdevice *args)
|
|
+{
|
|
+ int ret;
|
|
+ struct dxgkvmb_command_createdevice *command;
|
|
+ struct dxgkvmb_command_createdevice_return result = { };
|
|
+ struct dxgvmbusmsg msg;
|
|
+
|
|
+ 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_CREATEDEVICE,
|
|
+ process->host_handle);
|
|
+ command->flags = args->flags;
|
|
+
|
|
+ ret = dxgvmb_send_sync_msg(msg.channel, msg.hdr, msg.size,
|
|
+ &result, sizeof(result));
|
|
+ if (ret < 0)
|
|
+ result.device.v = 0;
|
|
+ free_message(&msg, process);
|
|
+cleanup:
|
|
+ if (ret)
|
|
+ DXG_TRACE("err: %d", ret);
|
|
+ return result.device;
|
|
+}
|
|
+
|
|
+int dxgvmb_send_destroy_device(struct dxgadapter *adapter,
|
|
+ struct dxgprocess *process,
|
|
+ struct d3dkmthandle h)
|
|
+{
|
|
+ int ret;
|
|
+ struct dxgkvmb_command_destroydevice *command;
|
|
+ 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_DESTROYDEVICE,
|
|
+ process->host_handle);
|
|
+ command->device = h;
|
|
+
|
|
+ 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_flush_device(struct dxgdevice *device,
|
|
+ enum dxgdevice_flushschedulerreason reason)
|
|
+{
|
|
+ int ret;
|
|
+ struct dxgkvmb_command_flushdevice *command;
|
|
+ struct dxgvmbusmsg msg = {.hdr = NULL};
|
|
+ struct dxgprocess *process = device->process;
|
|
+
|
|
+ ret = init_message(&msg, device->adapter, process, sizeof(*command));
|
|
+ if (ret)
|
|
+ goto cleanup;
|
|
+ command = (void *)msg.msg;
|
|
+
|
|
+ command_vgpu_to_host_init2(&command->hdr, DXGK_VMBCOMMAND_FLUSHDEVICE,
|
|
+ process->host_handle);
|
|
+ command->device = device->handle;
|
|
+ command->reason = reason;
|
|
+
|
|
+ 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_query_adapter_info(struct dxgprocess *process,
|
|
struct dxgadapter *adapter,
|
|
struct d3dkmt_queryadapterinfo *args)
|
|
diff --git a/drivers/hv/dxgkrnl/dxgvmbus.h b/drivers/hv/dxgkrnl/dxgvmbus.h
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/hv/dxgkrnl/dxgvmbus.h
|
|
+++ b/drivers/hv/dxgkrnl/dxgvmbus.h
|
|
@@ -247,4 +247,26 @@ struct dxgkvmb_command_queryadapterinfo_return {
|
|
u8 private_data[1];
|
|
};
|
|
|
|
+struct dxgkvmb_command_createdevice {
|
|
+ struct dxgkvmb_command_vgpu_to_host hdr;
|
|
+ struct d3dkmt_createdeviceflags flags;
|
|
+ bool cdd_device;
|
|
+ void *error_code;
|
|
+};
|
|
+
|
|
+struct dxgkvmb_command_createdevice_return {
|
|
+ struct d3dkmthandle device;
|
|
+};
|
|
+
|
|
+struct dxgkvmb_command_destroydevice {
|
|
+ struct dxgkvmb_command_vgpu_to_host hdr;
|
|
+ struct d3dkmthandle device;
|
|
+};
|
|
+
|
|
+struct dxgkvmb_command_flushdevice {
|
|
+ struct dxgkvmb_command_vgpu_to_host hdr;
|
|
+ struct d3dkmthandle device;
|
|
+ enum dxgdevice_flushschedulerreason reason;
|
|
+};
|
|
+
|
|
#endif /* _DXGVMBUS_H */
|
|
diff --git a/drivers/hv/dxgkrnl/ioctl.c b/drivers/hv/dxgkrnl/ioctl.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/hv/dxgkrnl/ioctl.c
|
|
+++ b/drivers/hv/dxgkrnl/ioctl.c
|
|
@@ -424,10 +424,136 @@ dxgkio_query_adapter_info(struct dxgprocess *process, void *__user inargs)
|
|
return ret;
|
|
}
|
|
|
|
+static int
|
|
+dxgkio_create_device(struct dxgprocess *process, void *__user inargs)
|
|
+{
|
|
+ struct d3dkmt_createdevice args;
|
|
+ int ret;
|
|
+ struct dxgadapter *adapter = NULL;
|
|
+ struct dxgdevice *device = NULL;
|
|
+ struct d3dkmthandle host_device_handle = {};
|
|
+ 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;
|
|
+ }
|
|
+
|
|
+ /* The call acquires reference on the adapter */
|
|
+ adapter = dxgprocess_adapter_by_handle(process, args.adapter);
|
|
+ if (adapter == NULL) {
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ device = dxgdevice_create(adapter, process);
|
|
+ if (device == NULL) {
|
|
+ ret = -ENOMEM;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ ret = dxgadapter_acquire_lock_shared(adapter);
|
|
+ if (ret < 0)
|
|
+ goto cleanup;
|
|
+
|
|
+ adapter_locked = true;
|
|
+
|
|
+ host_device_handle = dxgvmb_send_create_device(adapter, process, &args);
|
|
+ if (host_device_handle.v) {
|
|
+ ret = copy_to_user(&((struct d3dkmt_createdevice *)inargs)->
|
|
+ device, &host_device_handle,
|
|
+ sizeof(struct d3dkmthandle));
|
|
+ if (ret) {
|
|
+ DXG_ERR("failed to copy device handle");
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ hmgrtable_lock(&process->handle_table, DXGLOCK_EXCL);
|
|
+ ret = hmgrtable_assign_handle(&process->handle_table, device,
|
|
+ HMGRENTRY_TYPE_DXGDEVICE,
|
|
+ host_device_handle);
|
|
+ if (ret >= 0) {
|
|
+ device->handle = host_device_handle;
|
|
+ device->handle_valid = 1;
|
|
+ device->object_state = DXGOBJECTSTATE_ACTIVE;
|
|
+ }
|
|
+ hmgrtable_unlock(&process->handle_table, DXGLOCK_EXCL);
|
|
+ }
|
|
+
|
|
+cleanup:
|
|
+
|
|
+ if (ret < 0) {
|
|
+ if (host_device_handle.v)
|
|
+ dxgvmb_send_destroy_device(adapter, process,
|
|
+ host_device_handle);
|
|
+ if (device)
|
|
+ dxgdevice_destroy(device);
|
|
+ }
|
|
+
|
|
+ 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;
|
|
+}
|
|
+
|
|
+static int
|
|
+dxgkio_destroy_device(struct dxgprocess *process, void *__user inargs)
|
|
+{
|
|
+ struct d3dkmt_destroydevice 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;
|
|
+ }
|
|
+
|
|
+ hmgrtable_lock(&process->handle_table, DXGLOCK_EXCL);
|
|
+ device = hmgrtable_get_object_by_type(&process->handle_table,
|
|
+ HMGRENTRY_TYPE_DXGDEVICE,
|
|
+ args.device);
|
|
+ if (device) {
|
|
+ hmgrtable_free_handle(&process->handle_table,
|
|
+ HMGRENTRY_TYPE_DXGDEVICE, args.device);
|
|
+ device->handle_valid = 0;
|
|
+ }
|
|
+ hmgrtable_unlock(&process->handle_table, DXGLOCK_EXCL);
|
|
+
|
|
+ if (device == NULL) {
|
|
+ DXG_ERR("invalid device handle: %x", args.device.v);
|
|
+ ret = -EINVAL;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ adapter = device->adapter;
|
|
+
|
|
+ dxgdevice_destroy(device);
|
|
+
|
|
+ if (dxgadapter_acquire_lock_shared(adapter) == 0) {
|
|
+ dxgvmb_send_destroy_device(adapter, process, args.device);
|
|
+ dxgadapter_release_lock_shared(adapter);
|
|
+ }
|
|
+
|
|
+cleanup:
|
|
+
|
|
+ DXG_TRACE("ioctl:%s %d", errorstr(ret), ret);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
static struct ioctl_desc ioctls[] = {
|
|
/* 0x00 */ {},
|
|
/* 0x01 */ {dxgkio_open_adapter_from_luid, LX_DXOPENADAPTERFROMLUID},
|
|
-/* 0x02 */ {},
|
|
+/* 0x02 */ {dxgkio_create_device, LX_DXCREATEDEVICE},
|
|
/* 0x03 */ {},
|
|
/* 0x04 */ {},
|
|
/* 0x05 */ {},
|
|
@@ -450,7 +576,7 @@ static struct ioctl_desc ioctls[] = {
|
|
/* 0x16 */ {},
|
|
/* 0x17 */ {},
|
|
/* 0x18 */ {},
|
|
-/* 0x19 */ {},
|
|
+/* 0x19 */ {dxgkio_destroy_device, LX_DXDESTROYDEVICE},
|
|
/* 0x1a */ {},
|
|
/* 0x1b */ {},
|
|
/* 0x1c */ {},
|
|
diff --git a/drivers/hv/dxgkrnl/misc.h b/drivers/hv/dxgkrnl/misc.h
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/hv/dxgkrnl/misc.h
|
|
+++ b/drivers/hv/dxgkrnl/misc.h
|
|
@@ -27,10 +27,10 @@ extern const struct d3dkmthandle zerohandle;
|
|
*
|
|
* channel_lock (VMBus channel lock)
|
|
* fd_mutex
|
|
- * plistmutex
|
|
- * table_lock
|
|
- * core_lock
|
|
- * device_lock
|
|
+ * plistmutex (process list mutex)
|
|
+ * table_lock (handle table lock)
|
|
+ * core_lock (dxgadapter lock)
|
|
+ * device_lock (dxgdevice lock)
|
|
* process_adapter_mutex
|
|
* adapter_list_lock
|
|
* device_mutex (dxgglobal mutex)
|
|
diff --git a/include/uapi/misc/d3dkmthk.h b/include/uapi/misc/d3dkmthk.h
|
|
index 111111111111..222222222222 100644
|
|
--- a/include/uapi/misc/d3dkmthk.h
|
|
+++ b/include/uapi/misc/d3dkmthk.h
|
|
@@ -86,6 +86,74 @@ struct d3dkmt_openadapterfromluid {
|
|
struct d3dkmthandle adapter_handle;
|
|
};
|
|
|
|
+struct d3dddi_allocationlist {
|
|
+ struct d3dkmthandle allocation;
|
|
+ union {
|
|
+ struct {
|
|
+ __u32 write_operation :1;
|
|
+ __u32 do_not_retire_instance :1;
|
|
+ __u32 offer_priority :3;
|
|
+ __u32 reserved :27;
|
|
+ };
|
|
+ __u32 value;
|
|
+ };
|
|
+};
|
|
+
|
|
+struct d3dddi_patchlocationlist {
|
|
+ __u32 allocation_index;
|
|
+ union {
|
|
+ struct {
|
|
+ __u32 slot_id:24;
|
|
+ __u32 reserved:8;
|
|
+ };
|
|
+ __u32 value;
|
|
+ };
|
|
+ __u32 driver_id;
|
|
+ __u32 allocation_offset;
|
|
+ __u32 patch_offset;
|
|
+ __u32 split_offset;
|
|
+};
|
|
+
|
|
+struct d3dkmt_createdeviceflags {
|
|
+ __u32 legacy_mode:1;
|
|
+ __u32 request_vSync:1;
|
|
+ __u32 disable_gpu_timeout:1;
|
|
+ __u32 gdi_device:1;
|
|
+ __u32 reserved:28;
|
|
+};
|
|
+
|
|
+struct d3dkmt_createdevice {
|
|
+ struct d3dkmthandle adapter;
|
|
+ __u32 reserved3;
|
|
+ struct d3dkmt_createdeviceflags flags;
|
|
+ struct d3dkmthandle device;
|
|
+#ifdef __KERNEL__
|
|
+ void *command_buffer;
|
|
+#else
|
|
+ __u64 command_buffer;
|
|
+#endif
|
|
+ __u32 command_buffer_size;
|
|
+ __u32 reserved;
|
|
+#ifdef __KERNEL__
|
|
+ struct d3dddi_allocationlist *allocation_list;
|
|
+#else
|
|
+ __u64 allocation_list;
|
|
+#endif
|
|
+ __u32 allocation_list_size;
|
|
+ __u32 reserved1;
|
|
+#ifdef __KERNEL__
|
|
+ struct d3dddi_patchlocationlist *patch_location_list;
|
|
+#else
|
|
+ __u64 patch_location_list;
|
|
+#endif
|
|
+ __u32 patch_location_list_size;
|
|
+ __u32 reserved2;
|
|
+};
|
|
+
|
|
+struct d3dkmt_destroydevice {
|
|
+ struct d3dkmthandle device;
|
|
+};
|
|
+
|
|
struct d3dkmt_adaptertype {
|
|
union {
|
|
struct {
|
|
@@ -125,6 +193,16 @@ struct d3dkmt_queryadapterinfo {
|
|
__u32 private_data_size;
|
|
};
|
|
|
|
+enum d3dkmt_deviceexecution_state {
|
|
+ _D3DKMT_DEVICEEXECUTION_ACTIVE = 1,
|
|
+ _D3DKMT_DEVICEEXECUTION_RESET = 2,
|
|
+ _D3DKMT_DEVICEEXECUTION_HUNG = 3,
|
|
+ _D3DKMT_DEVICEEXECUTION_STOPPED = 4,
|
|
+ _D3DKMT_DEVICEEXECUTION_ERROR_OUTOFMEMORY = 5,
|
|
+ _D3DKMT_DEVICEEXECUTION_ERROR_DMAFAULT = 6,
|
|
+ _D3DKMT_DEVICEEXECUTION_ERROR_DMAPAGEFAULT = 7,
|
|
+};
|
|
+
|
|
union d3dkmt_enumadapters_filter {
|
|
struct {
|
|
__u64 include_compute_only:1;
|
|
@@ -152,12 +230,16 @@ struct d3dkmt_enumadapters3 {
|
|
|
|
#define LX_DXOPENADAPTERFROMLUID \
|
|
_IOWR(0x47, 0x01, struct d3dkmt_openadapterfromluid)
|
|
+#define LX_DXCREATEDEVICE \
|
|
+ _IOWR(0x47, 0x02, struct d3dkmt_createdevice)
|
|
#define LX_DXQUERYADAPTERINFO \
|
|
_IOWR(0x47, 0x09, struct d3dkmt_queryadapterinfo)
|
|
#define LX_DXENUMADAPTERS2 \
|
|
_IOWR(0x47, 0x14, struct d3dkmt_enumadapters2)
|
|
#define LX_DXCLOSEADAPTER \
|
|
_IOWR(0x47, 0x15, struct d3dkmt_closeadapter)
|
|
+#define LX_DXDESTROYDEVICE \
|
|
+ _IOWR(0x47, 0x19, struct d3dkmt_destroydevice)
|
|
#define LX_DXENUMADAPTERS3 \
|
|
_IOWR(0x47, 0x3e, struct d3dkmt_enumadapters3)
|
|
|
|
--
|
|
Armbian
|
|
|