Skip to content

Commit 2dd1d57

Browse files
Iouri Tarassovchessturo
authored andcommitted
drivers: hv: dxgkrnl: Creation of compute device allocations and resources
Implemented ioctls to create and destroy virtual compute device allocations (dxgallocation) and resources (dxgresource): - the LX_DXCREATEALLOCATION ioctl, - the LX_DXDESTROYALLOCATION2 ioctl. Compute device allocations (dxgallocation objects) represent memory allocation, which could be accessible by the device. Allocations can be created around existing system memory (provided by an application) or memory, allocated by dxgkrnl on the host. Compute device resources (dxgresource objects) represent containers of compute device allocations. Allocations could be dynamically added, removed from a resource. Each allocation/resource has associated driver private data, which is provided during creation. Each created resource or allocation have a handle (d3dkmthandle), which is used to reference the corresponding object in other ioctls. A dxgallocation can be resident (meaning that it is accessible by the compute device) or evicted. When an allocation is evicted, its content is stored in the backing store in system 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 d1b768b commit 2dd1d57

8 files changed

Lines changed: 2004 additions & 2 deletions

File tree

drivers/hv/dxgkrnl/dxgadapter.c

Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,11 @@ struct dxgdevice *dxgdevice_create(struct dxgadapter *adapter,
207207
device->process = process;
208208
kref_get(&adapter->adapter_kref);
209209
INIT_LIST_HEAD(&device->context_list_head);
210+
INIT_LIST_HEAD(&device->alloc_list_head);
211+
INIT_LIST_HEAD(&device->resource_list_head);
210212
init_rwsem(&device->device_lock);
211213
init_rwsem(&device->context_list_lock);
214+
init_rwsem(&device->alloc_list_lock);
212215
INIT_LIST_HEAD(&device->pqueue_list_head);
213216
device->object_state = DXGOBJECTSTATE_CREATED;
214217
device->execution_state = _D3DKMT_DEVICEEXECUTION_ACTIVE;
@@ -224,6 +227,14 @@ struct dxgdevice *dxgdevice_create(struct dxgadapter *adapter,
224227

225228
void dxgdevice_stop(struct dxgdevice *device)
226229
{
230+
struct dxgallocation *alloc;
231+
232+
DXG_TRACE("Destroying device: %p", device);
233+
dxgdevice_acquire_alloc_list_lock(device);
234+
list_for_each_entry(alloc, &device->alloc_list_head, alloc_list_entry) {
235+
dxgallocation_stop(alloc);
236+
}
237+
dxgdevice_release_alloc_list_lock(device);
227238
}
228239

229240
void dxgdevice_mark_destroyed(struct dxgdevice *device)
@@ -250,6 +261,33 @@ void dxgdevice_destroy(struct dxgdevice *device)
250261

251262
dxgdevice_stop(device);
252263

264+
dxgdevice_acquire_alloc_list_lock(device);
265+
266+
{
267+
struct dxgallocation *alloc;
268+
struct dxgallocation *tmp;
269+
270+
DXG_TRACE("destroying allocations");
271+
list_for_each_entry_safe(alloc, tmp, &device->alloc_list_head,
272+
alloc_list_entry) {
273+
dxgallocation_destroy(alloc);
274+
}
275+
}
276+
277+
{
278+
struct dxgresource *resource;
279+
struct dxgresource *tmp;
280+
281+
DXG_TRACE("destroying resources");
282+
list_for_each_entry_safe(resource, tmp,
283+
&device->resource_list_head,
284+
resource_list_entry) {
285+
dxgresource_destroy(resource);
286+
}
287+
}
288+
289+
dxgdevice_release_alloc_list_lock(device);
290+
253291
{
254292
struct dxgcontext *context;
255293
struct dxgcontext *tmp;
@@ -328,6 +366,26 @@ void dxgdevice_release_context_list_lock(struct dxgdevice *device)
328366
up_write(&device->context_list_lock);
329367
}
330368

369+
void dxgdevice_acquire_alloc_list_lock(struct dxgdevice *device)
370+
{
371+
down_write(&device->alloc_list_lock);
372+
}
373+
374+
void dxgdevice_release_alloc_list_lock(struct dxgdevice *device)
375+
{
376+
up_write(&device->alloc_list_lock);
377+
}
378+
379+
void dxgdevice_acquire_alloc_list_lock_shared(struct dxgdevice *device)
380+
{
381+
down_read(&device->alloc_list_lock);
382+
}
383+
384+
void dxgdevice_release_alloc_list_lock_shared(struct dxgdevice *device)
385+
{
386+
up_read(&device->alloc_list_lock);
387+
}
388+
331389
void dxgdevice_add_context(struct dxgdevice *device, struct dxgcontext *context)
332390
{
333391
down_write(&device->context_list_lock);
@@ -344,6 +402,161 @@ void dxgdevice_remove_context(struct dxgdevice *device,
344402
}
345403
}
346404

405+
void dxgdevice_add_alloc(struct dxgdevice *device, struct dxgallocation *alloc)
406+
{
407+
dxgdevice_acquire_alloc_list_lock(device);
408+
list_add_tail(&alloc->alloc_list_entry, &device->alloc_list_head);
409+
kref_get(&device->device_kref);
410+
alloc->owner.device = device;
411+
dxgdevice_release_alloc_list_lock(device);
412+
}
413+
414+
void dxgdevice_remove_alloc(struct dxgdevice *device,
415+
struct dxgallocation *alloc)
416+
{
417+
if (alloc->alloc_list_entry.next) {
418+
list_del(&alloc->alloc_list_entry);
419+
alloc->alloc_list_entry.next = NULL;
420+
kref_put(&device->device_kref, dxgdevice_release);
421+
}
422+
}
423+
424+
void dxgdevice_remove_alloc_safe(struct dxgdevice *device,
425+
struct dxgallocation *alloc)
426+
{
427+
dxgdevice_acquire_alloc_list_lock(device);
428+
dxgdevice_remove_alloc(device, alloc);
429+
dxgdevice_release_alloc_list_lock(device);
430+
}
431+
432+
void dxgdevice_add_resource(struct dxgdevice *device, struct dxgresource *res)
433+
{
434+
dxgdevice_acquire_alloc_list_lock(device);
435+
list_add_tail(&res->resource_list_entry, &device->resource_list_head);
436+
kref_get(&device->device_kref);
437+
dxgdevice_release_alloc_list_lock(device);
438+
}
439+
440+
void dxgdevice_remove_resource(struct dxgdevice *device,
441+
struct dxgresource *res)
442+
{
443+
if (res->resource_list_entry.next) {
444+
list_del(&res->resource_list_entry);
445+
res->resource_list_entry.next = NULL;
446+
kref_put(&device->device_kref, dxgdevice_release);
447+
}
448+
}
449+
450+
struct dxgresource *dxgresource_create(struct dxgdevice *device)
451+
{
452+
struct dxgresource *resource;
453+
454+
resource = kzalloc(sizeof(struct dxgresource), GFP_KERNEL);
455+
if (resource) {
456+
kref_init(&resource->resource_kref);
457+
resource->device = device;
458+
resource->process = device->process;
459+
resource->object_state = DXGOBJECTSTATE_ACTIVE;
460+
mutex_init(&resource->resource_mutex);
461+
INIT_LIST_HEAD(&resource->alloc_list_head);
462+
dxgdevice_add_resource(device, resource);
463+
}
464+
return resource;
465+
}
466+
467+
void dxgresource_free_handle(struct dxgresource *resource)
468+
{
469+
struct dxgallocation *alloc;
470+
struct dxgprocess *process;
471+
472+
if (resource->handle_valid) {
473+
process = resource->device->process;
474+
hmgrtable_free_handle_safe(&process->handle_table,
475+
HMGRENTRY_TYPE_DXGRESOURCE,
476+
resource->handle);
477+
resource->handle_valid = 0;
478+
}
479+
list_for_each_entry(alloc, &resource->alloc_list_head,
480+
alloc_list_entry) {
481+
dxgallocation_free_handle(alloc);
482+
}
483+
}
484+
485+
void dxgresource_destroy(struct dxgresource *resource)
486+
{
487+
/* device->alloc_list_lock is held */
488+
struct dxgallocation *alloc;
489+
struct dxgallocation *tmp;
490+
struct d3dkmt_destroyallocation2 args = { };
491+
int destroyed = test_and_set_bit(0, &resource->flags);
492+
struct dxgdevice *device = resource->device;
493+
494+
if (!destroyed) {
495+
dxgresource_free_handle(resource);
496+
if (resource->handle.v) {
497+
args.device = device->handle;
498+
args.resource = resource->handle;
499+
dxgvmb_send_destroy_allocation(device->process,
500+
device, &args, NULL);
501+
resource->handle.v = 0;
502+
}
503+
list_for_each_entry_safe(alloc, tmp, &resource->alloc_list_head,
504+
alloc_list_entry) {
505+
dxgallocation_destroy(alloc);
506+
}
507+
dxgdevice_remove_resource(device, resource);
508+
}
509+
kref_put(&resource->resource_kref, dxgresource_release);
510+
}
511+
512+
void dxgresource_release(struct kref *refcount)
513+
{
514+
struct dxgresource *resource;
515+
516+
resource = container_of(refcount, struct dxgresource, resource_kref);
517+
kfree(resource);
518+
}
519+
520+
bool dxgresource_is_active(struct dxgresource *resource)
521+
{
522+
return resource->object_state == DXGOBJECTSTATE_ACTIVE;
523+
}
524+
525+
int dxgresource_add_alloc(struct dxgresource *resource,
526+
struct dxgallocation *alloc)
527+
{
528+
int ret = -ENODEV;
529+
struct dxgdevice *device = resource->device;
530+
531+
dxgdevice_acquire_alloc_list_lock(device);
532+
if (dxgresource_is_active(resource)) {
533+
list_add_tail(&alloc->alloc_list_entry,
534+
&resource->alloc_list_head);
535+
alloc->owner.resource = resource;
536+
ret = 0;
537+
}
538+
alloc->resource_owner = 1;
539+
dxgdevice_release_alloc_list_lock(device);
540+
return ret;
541+
}
542+
543+
void dxgresource_remove_alloc(struct dxgresource *resource,
544+
struct dxgallocation *alloc)
545+
{
546+
if (alloc->alloc_list_entry.next) {
547+
list_del(&alloc->alloc_list_entry);
548+
alloc->alloc_list_entry.next = NULL;
549+
}
550+
}
551+
552+
void dxgresource_remove_alloc_safe(struct dxgresource *resource,
553+
struct dxgallocation *alloc)
554+
{
555+
dxgdevice_acquire_alloc_list_lock(resource->device);
556+
dxgresource_remove_alloc(resource, alloc);
557+
dxgdevice_release_alloc_list_lock(resource->device);
558+
}
559+
347560
void dxgdevice_release(struct kref *refcount)
348561
{
349562
struct dxgdevice *device;
@@ -413,6 +626,75 @@ void dxgcontext_release(struct kref *refcount)
413626
kfree(context);
414627
}
415628

629+
struct dxgallocation *dxgallocation_create(struct dxgprocess *process)
630+
{
631+
struct dxgallocation *alloc;
632+
633+
alloc = kzalloc(sizeof(struct dxgallocation), GFP_KERNEL);
634+
if (alloc)
635+
alloc->process = process;
636+
return alloc;
637+
}
638+
639+
void dxgallocation_stop(struct dxgallocation *alloc)
640+
{
641+
if (alloc->pages) {
642+
release_pages(alloc->pages, alloc->num_pages);
643+
vfree(alloc->pages);
644+
alloc->pages = NULL;
645+
}
646+
}
647+
648+
void dxgallocation_free_handle(struct dxgallocation *alloc)
649+
{
650+
dxgprocess_ht_lock_exclusive_down(alloc->process);
651+
if (alloc->handle_valid) {
652+
hmgrtable_free_handle(&alloc->process->handle_table,
653+
HMGRENTRY_TYPE_DXGALLOCATION,
654+
alloc->alloc_handle);
655+
alloc->handle_valid = 0;
656+
}
657+
dxgprocess_ht_lock_exclusive_up(alloc->process);
658+
}
659+
660+
void dxgallocation_destroy(struct dxgallocation *alloc)
661+
{
662+
struct dxgprocess *process = alloc->process;
663+
struct d3dkmt_destroyallocation2 args = { };
664+
665+
dxgallocation_stop(alloc);
666+
if (alloc->resource_owner)
667+
dxgresource_remove_alloc(alloc->owner.resource, alloc);
668+
else if (alloc->owner.device)
669+
dxgdevice_remove_alloc(alloc->owner.device, alloc);
670+
dxgallocation_free_handle(alloc);
671+
if (alloc->alloc_handle.v && !alloc->resource_owner) {
672+
args.device = alloc->owner.device->handle;
673+
args.alloc_count = 1;
674+
dxgvmb_send_destroy_allocation(process,
675+
alloc->owner.device,
676+
&args, &alloc->alloc_handle);
677+
}
678+
#ifdef _MAIN_KERNEL_
679+
if (alloc->gpadl.gpadl_handle) {
680+
DXG_TRACE("Teardown gpadl %d",
681+
alloc->gpadl.gpadl_handle);
682+
vmbus_teardown_gpadl(dxgglobal_get_vmbus(), &alloc->gpadl);
683+
alloc->gpadl.gpadl_handle = 0;
684+
}
685+
else
686+
if (alloc->gpadl) {
687+
DXG_TRACE("Teardown gpadl %d",
688+
alloc->gpadl);
689+
vmbus_teardown_gpadl(dxgglobal_get_vmbus(), alloc->gpadl);
690+
alloc->gpadl = 0;
691+
}
692+
#endif
693+
if (alloc->priv_drv_data)
694+
vfree(alloc->priv_drv_data);
695+
kfree(alloc);
696+
}
697+
416698
struct dxgprocess_adapter *dxgprocess_adapter_create(struct dxgprocess *process,
417699
struct dxgadapter *adapter)
418700
{

0 commit comments

Comments
 (0)