All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel Vetter <daniel@ffwll.ch>
To: Iouri Tarassov <iourit@linux.microsoft.com>
Cc: kys@microsoft.com, haiyangz@microsoft.com,
	sthemmin@microsoft.com, wei.liu@kernel.org,
	linux-hyperv@vger.kernel.org, linux-kernel@vger.kernel.org,
	spronovo@microsoft.com, gregkh@linuxfoundation.org,
	DRI Development <dri-devel@lists.freedesktop.org>,
	jenatali@microsoft.com
Subject: Re: [PATCH v1 9/9] drivers: hv: dxgkrnl: Implement DXGSYNCFILE
Date: Fri, 14 Jan 2022 19:03:36 +0100	[thread overview]
Message-ID: <YeG6+Crv/Bg4h3u1@phenom.ffwll.local> (raw)
In-Reply-To: <e04c8e820bc166d9d4fe8e388aace731bb3255b0.1641937420.git.iourit@linux.microsoft.com>

Hi all,

On Wed, Jan 12, 2022 at 11:55:14AM -0800, Iouri Tarassov wrote:
> Implement the LX_DXCREATESYNCFILE IOCTL (D3DKMTCreateSyncFile).
> 
> dxgsyncfile is built on top of the Linux sync_file object and
> provides a way for the user mode to synchronize with the execution
> of the device DMA packets.
> 
> The IOCTL creates a dxgsyncfile object for the given GPU synchronization
> object and a fence value. A sync_object file descriptor is returned to
> the caller. The caller could wait for the object by using poll().
> When the GPU synchronization object is signaled on the host, the host
> sends a message to the virtual machine and the sync_file object is
> signaled.
> 
> Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>

Adding dri-devel, which get_maintainers.pl should have done automatically
with the dma_fence wildcard match. Not sure why that didn't happen.

> +struct dxgsyncpoint {
> +	struct dxghostevent	hdr;
> +	struct dma_fence	base;

This doesn't work unfortuntately. For better or worse memory fences like
monitored fences from wddm have completely different semantics from
dma_fence. You could probably hack this to be self-consistent for hyper-v,
but the problem is that then hv would have incompatible locking/nesting
rules compared to everything else, and dma_fence matter for memory
management so this includes whether you're allowed to kmalloc(GFP_KERNEL)
or not, and that's just a bit too much.

I discussed this quickly with Jesse on irc and it sounds like the reason
you want the dma_fence is just to emulate the sync_file interface for
android. I think the correct solution here is to create a hv_dxg_sync_file
fd, which emulates the exact ioctls that Android needs, but with a wddm
monitored fence underneath instead of a dma_fence underneath.

This way we guarantee that no one ever accidentally mixes these
incompatible concepts up in the kernel, and Android should still be able
to happily run under hyperv.

Thoughts?

Also pls cc me on this sync work since even if you drop dma_fence use
completely I'd like to follow this a bit.

Cheers, Daniel

> +	u64			fence_value;
> +	u64			context;
> +	spinlock_t		lock;
> +	u64			u64;
> +};
> +
> +#endif	 /* _DXGSYNCFILE_H */
> diff --git a/drivers/hv/dxgkrnl/dxgvmbus.c b/drivers/hv/dxgkrnl/dxgvmbus.c
> index 773d8f364b34..185fb7e38c21 100644
> --- a/drivers/hv/dxgkrnl/dxgvmbus.c
> +++ b/drivers/hv/dxgkrnl/dxgvmbus.c
> @@ -1311,15 +1311,18 @@ int create_existing_sysmem(struct dxgdevice *device,
>  	void *kmem = NULL;
>  	int ret = 0;
>  	struct dxgkvmb_command_setexistingsysmemstore *set_store_command;
> +	struct dxgkvmb_command_setexistingsysmempages *set_pages_command;
>  	u64 alloc_size = host_alloc->allocation_size;
>  	u32 npages = alloc_size >> PAGE_SHIFT;
>  	struct dxgvmbusmsg msg = {.hdr = NULL};
> -
> -	ret = init_message(&msg, device->adapter, device->process,
> -			   sizeof(*set_store_command));
> -	if (ret)
> -		goto cleanup;
> -	set_store_command = (void *)msg.msg;
> +	const u32 max_pfns_in_message =
> +		(DXG_MAX_VM_BUS_PACKET_SIZE - sizeof(*set_pages_command) -
> +		PAGE_SIZE) / sizeof(__u64);
> +	u32 alloc_offset_in_pages = 0;
> +	struct page **page_in;
> +	u64 *pfn;
> +	u32 pages_to_send;
> +	u32 i;
>  
>  	/*
>  	 * Create a guest physical address list and set it as the allocation
> @@ -1330,6 +1333,7 @@ int create_existing_sysmem(struct dxgdevice *device,
>  	dev_dbg(dxgglobaldev, "   Alloc size: %lld", alloc_size);
>  
>  	dxgalloc->cpu_address = (void *)sysmem;
> +
>  	dxgalloc->pages = vzalloc(npages * sizeof(void *));
>  	if (dxgalloc->pages == NULL) {
>  		pr_err("failed to allocate pages");
> @@ -1347,31 +1351,80 @@ int create_existing_sysmem(struct dxgdevice *device,
>  		ret = -ENOMEM;
>  		goto cleanup;
>  	}
> -	kmem = vmap(dxgalloc->pages, npages, VM_MAP, PAGE_KERNEL);
> -	if (kmem == NULL) {
> -		pr_err("vmap failed");
> -		ret = -ENOMEM;
> -		goto cleanup;
> -	}
> -	ret1 = vmbus_establish_gpadl(dxgglobal_get_vmbus(), kmem,
> -				     alloc_size, &dxgalloc->gpadl);
> -	if (ret1) {
> -		pr_err("establish_gpadl failed: %d", ret1);
> -		ret = -ENOMEM;
> -		goto cleanup;
> -	}
> -	dev_dbg(dxgglobaldev, "New gpadl %d", dxgalloc->gpadl.gpadl_handle);
> +	if (!dxgglobal->map_guest_pages_enabled) {
> +		ret = init_message(&msg, device->adapter, device->process,
> +				sizeof(*set_store_command));
> +		if (ret)
> +			goto cleanup;
> +		set_store_command = (void *)msg.msg;
>  
> -	command_vgpu_to_host_init2(&set_store_command->hdr,
> -				   DXGK_VMBCOMMAND_SETEXISTINGSYSMEMSTORE,
> -				   device->process->host_handle);
> -	set_store_command->device = device->handle;
> -	set_store_command->device = device->handle;
> -	set_store_command->allocation = host_alloc->allocation;
> -	set_store_command->gpadl = dxgalloc->gpadl.gpadl_handle;
> -	ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr, msg.size);
> -	if (ret < 0)
> -		pr_err("failed to set existing store: %x", ret);
> +		kmem = vmap(dxgalloc->pages, npages, VM_MAP, PAGE_KERNEL);
> +		if (kmem == NULL) {
> +			pr_err("vmap failed");
> +			ret = -ENOMEM;
> +			goto cleanup;
> +		}
> +		ret1 = vmbus_establish_gpadl(dxgglobal_get_vmbus(), kmem,
> +					alloc_size, &dxgalloc->gpadl);
> +		if (ret1) {
> +			pr_err("establish_gpadl failed: %d", ret1);
> +			ret = -ENOMEM;
> +			goto cleanup;
> +		}
> +		dev_dbg(dxgglobaldev, "New gpadl %d",
> +			dxgalloc->gpadl.gpadl_handle);
> +
> +		command_vgpu_to_host_init2(&set_store_command->hdr,
> +					DXGK_VMBCOMMAND_SETEXISTINGSYSMEMSTORE,
> +					device->process->host_handle);
> +		set_store_command->device = device->handle;
> +		set_store_command->allocation = host_alloc->allocation;
> +		set_store_command->gpadl = dxgalloc->gpadl.gpadl_handle;
> +		ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr,
> +						    msg.size);
> +		if (ret < 0)
> +			pr_err("failed to set existing store: %x", ret);
> +	} else {
> +		/*
> +		 * Send the list of the allocation PFNs to the host. The host
> +		 * will map the pages for GPU access.
> +		 */
> +
> +		ret = init_message(&msg, device->adapter, device->process,
> +				sizeof(*set_pages_command) +
> +				max_pfns_in_message * sizeof(u64));
> +		if (ret)
> +			goto cleanup;
> +		set_pages_command = (void *)msg.msg;
> +		command_vgpu_to_host_init2(&set_pages_command->hdr,
> +					DXGK_VMBCOMMAND_SETEXISTINGSYSMEMPAGES,
> +					device->process->host_handle);
> +		set_pages_command->device = device->handle;
> +		set_pages_command->allocation = host_alloc->allocation;
> +
> +		page_in = dxgalloc->pages;
> +		while (alloc_offset_in_pages < npages) {
> +			pfn = (u64 *)((char *)msg.msg +
> +				sizeof(*set_pages_command));
> +			pages_to_send = min(npages - alloc_offset_in_pages,
> +					    max_pfns_in_message);
> +			set_pages_command->num_pages = pages_to_send;
> +			set_pages_command->alloc_offset_in_pages =
> +				alloc_offset_in_pages;
> +
> +			for (i = 0; i < pages_to_send; i++)
> +				*pfn++ = page_to_pfn(*page_in++);
> +
> +			ret = dxgvmb_send_sync_msg_ntstatus(msg.channel,
> +							    msg.hdr,
> +							    msg.size);
> +			if (ret < 0) {
> +				pr_err("failed to set existing pages: %x", ret);
> +				break;
> +			}
> +			alloc_offset_in_pages += pages_to_send;
> +		}
> +	}
>  
>  cleanup:
>  	if (kmem)
> @@ -2685,6 +2738,7 @@ int dxgvmb_send_wait_sync_object_cpu(struct dxgprocess *process,
>  				     struct
>  				     d3dkmt_waitforsynchronizationobjectfromcpu
>  				     *args,
> +				     bool user_address,
>  				     u64 cpu_event)
>  {
>  	int ret = -EINVAL;
> @@ -2708,18 +2762,25 @@ int dxgvmb_send_wait_sync_object_cpu(struct dxgprocess *process,
>  	command->object_count = args->object_count;
>  	command->guest_event_pointer = (u64) cpu_event;
>  	current_pos = (u8 *) &command[1];
> -	ret = copy_from_user(current_pos, args->objects, object_size);
> -	if (ret) {
> -		pr_err("%s failed to copy objects", __func__);
> -		ret = -EINVAL;
> -		goto cleanup;
> -	}
> -	current_pos += object_size;
> -	ret = copy_from_user(current_pos, args->fence_values, fence_size);
> -	if (ret) {
> -		pr_err("%s failed to copy fences", __func__);
> -		ret = -EINVAL;
> -		goto cleanup;
> +	if (user_address) {
> +		ret = copy_from_user(current_pos, args->objects, object_size);
> +		if (ret) {
> +			pr_err("%s failed to copy objects", __func__);
> +			ret = -EINVAL;
> +			goto cleanup;
> +		}
> +		current_pos += object_size;
> +		ret = copy_from_user(current_pos, args->fence_values,
> +				     fence_size);
> +		if (ret) {
> +			pr_err("%s failed to copy fences", __func__);
> +			ret = -EINVAL;
> +			goto cleanup;
> +		}
> +	} else {
> +		memcpy(current_pos, args->objects, object_size);
> +		current_pos += object_size;
> +		memcpy(current_pos, args->fence_values, fence_size);
>  	}
>  
>  	ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr, msg.size);
> diff --git a/drivers/hv/dxgkrnl/dxgvmbus.h b/drivers/hv/dxgkrnl/dxgvmbus.h
> index a19ac804a320..dc766d95a0c4 100644
> --- a/drivers/hv/dxgkrnl/dxgvmbus.h
> +++ b/drivers/hv/dxgkrnl/dxgvmbus.h
> @@ -139,6 +139,8 @@ enum dxgkvmb_commandtype {
>  	DXGK_VMBCOMMAND_GETCONTEXTSCHEDULINGPRIORITY = 61,
>  	DXGK_VMBCOMMAND_QUERYCLOCKCALIBRATION	= 62,
>  	DXGK_VMBCOMMAND_QUERYRESOURCEINFO	= 64,
> +	DXGK_VMBCOMMAND_LOGEVENT		= 65,
> +	DXGK_VMBCOMMAND_SETEXISTINGSYSMEMPAGES	= 66,
>  	DXGK_VMBCOMMAND_INVALID
>  };
>  
> @@ -245,6 +247,16 @@ struct dxgkvmb_command_setexistingsysmemstore {
>  	u32				gpadl;
>  };
>  
> +/* Returns ntstatus */
> +struct dxgkvmb_command_setexistingsysmempages {
> +	struct dxgkvmb_command_vgpu_to_host hdr;
> +	struct d3dkmthandle		device;
> +	struct d3dkmthandle		allocation;
> +	u32				num_pages;
> +	u32				alloc_offset_in_pages;
> +	/* u64 pfn_array[num_pages] */
> +};
> +
>  struct dxgkvmb_command_createprocess {
>  	struct dxgkvmb_command_vm_to_host hdr;
>  	void			*process;
> diff --git a/drivers/hv/dxgkrnl/ioctl.c b/drivers/hv/dxgkrnl/ioctl.c
> index 9770fabf163e..9236b6b95973 100644
> --- a/drivers/hv/dxgkrnl/ioctl.c
> +++ b/drivers/hv/dxgkrnl/ioctl.c
> @@ -19,6 +19,7 @@
>  
>  #include "dxgkrnl.h"
>  #include "dxgvmbus.h"
> +#include "dxgsyncfile.h"
>  
>  #undef pr_fmt
>  #define pr_fmt(fmt)	"dxgk:err: " fmt
> @@ -32,11 +33,6 @@ struct ioctl_desc {
>  };
>  static struct ioctl_desc ioctls[LX_IO_MAX + 1];
>  
> -static char *errorstr(int ret)
> -{
> -	return ret < 0 ? "err" : "";
> -}
> -
>  static int dxgsyncobj_release(struct inode *inode, struct file *file)
>  {
>  	struct dxgsharedsyncobject *syncobj = file->private_data;
> @@ -3561,7 +3557,7 @@ dxgk_wait_sync_object_cpu(struct dxgprocess *process, void *__user inargs)
>  	}
>  
>  	ret = dxgvmb_send_wait_sync_object_cpu(process, adapter,
> -					       &args, event_id);
> +					       &args, true, event_id);
>  	if (ret < 0)
>  		goto cleanup;
>  
> @@ -5457,4 +5453,6 @@ void init_ioctls(void)
>  		  LX_DXQUERYSTATISTICS);
>  	SET_IOCTL(/*0x44 */ dxgk_share_object_with_host,
>  		  LX_DXSHAREOBJECTWITHHOST);
> +	SET_IOCTL(/*0x45 */ dxgk_create_sync_file,
> +		  LX_DXCREATESYNCFILE);
>  }
> diff --git a/drivers/hv/dxgkrnl/misc.c b/drivers/hv/dxgkrnl/misc.c
> index ffb491641836..1b152c269265 100644
> --- a/drivers/hv/dxgkrnl/misc.c
> +++ b/drivers/hv/dxgkrnl/misc.c
> @@ -35,3 +35,9 @@ u16 *wcsncpy(u16 *dest, const u16 *src, size_t n)
>  	dest[i - 1] = 0;
>  	return dest;
>  }
> +
> +char *errorstr(int ret)
> +{
> +	return ret < 0 ? "err" : "";
> +}
> +
> diff --git a/drivers/hv/dxgkrnl/misc.h b/drivers/hv/dxgkrnl/misc.h
> index 7fe3fc45b67c..3079dd55c7a4 100644
> --- a/drivers/hv/dxgkrnl/misc.h
> +++ b/drivers/hv/dxgkrnl/misc.h
> @@ -44,6 +44,7 @@ extern const struct d3dkmthandle zerohandle;
>   */
>  
>  u16 *wcsncpy(u16 *dest, const u16 *src, size_t n);
> +char *errorstr(int ret);
>  
>  enum dxglockstate {
>  	DXGLOCK_SHARED,
> -- 
> 2.32.0
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

WARNING: multiple messages have this Message-ID (diff)
From: Daniel Vetter <daniel@ffwll.ch>
To: Iouri Tarassov <iourit@linux.microsoft.com>
Cc: wei.liu@kernel.org, sthemmin@microsoft.com,
	gregkh@linuxfoundation.org, haiyangz@microsoft.com,
	linux-hyperv@vger.kernel.org,
	DRI Development <dri-devel@lists.freedesktop.org>,
	linux-kernel@vger.kernel.org, spronovo@microsoft.com,
	jenatali@microsoft.com, kys@microsoft.com
Subject: Re: [PATCH v1 9/9] drivers: hv: dxgkrnl: Implement DXGSYNCFILE
Date: Fri, 14 Jan 2022 19:03:36 +0100	[thread overview]
Message-ID: <YeG6+Crv/Bg4h3u1@phenom.ffwll.local> (raw)
In-Reply-To: <e04c8e820bc166d9d4fe8e388aace731bb3255b0.1641937420.git.iourit@linux.microsoft.com>

Hi all,

On Wed, Jan 12, 2022 at 11:55:14AM -0800, Iouri Tarassov wrote:
> Implement the LX_DXCREATESYNCFILE IOCTL (D3DKMTCreateSyncFile).
> 
> dxgsyncfile is built on top of the Linux sync_file object and
> provides a way for the user mode to synchronize with the execution
> of the device DMA packets.
> 
> The IOCTL creates a dxgsyncfile object for the given GPU synchronization
> object and a fence value. A sync_object file descriptor is returned to
> the caller. The caller could wait for the object by using poll().
> When the GPU synchronization object is signaled on the host, the host
> sends a message to the virtual machine and the sync_file object is
> signaled.
> 
> Signed-off-by: Iouri Tarassov <iourit@linux.microsoft.com>

Adding dri-devel, which get_maintainers.pl should have done automatically
with the dma_fence wildcard match. Not sure why that didn't happen.

> +struct dxgsyncpoint {
> +	struct dxghostevent	hdr;
> +	struct dma_fence	base;

This doesn't work unfortuntately. For better or worse memory fences like
monitored fences from wddm have completely different semantics from
dma_fence. You could probably hack this to be self-consistent for hyper-v,
but the problem is that then hv would have incompatible locking/nesting
rules compared to everything else, and dma_fence matter for memory
management so this includes whether you're allowed to kmalloc(GFP_KERNEL)
or not, and that's just a bit too much.

I discussed this quickly with Jesse on irc and it sounds like the reason
you want the dma_fence is just to emulate the sync_file interface for
android. I think the correct solution here is to create a hv_dxg_sync_file
fd, which emulates the exact ioctls that Android needs, but with a wddm
monitored fence underneath instead of a dma_fence underneath.

This way we guarantee that no one ever accidentally mixes these
incompatible concepts up in the kernel, and Android should still be able
to happily run under hyperv.

Thoughts?

Also pls cc me on this sync work since even if you drop dma_fence use
completely I'd like to follow this a bit.

Cheers, Daniel

> +	u64			fence_value;
> +	u64			context;
> +	spinlock_t		lock;
> +	u64			u64;
> +};
> +
> +#endif	 /* _DXGSYNCFILE_H */
> diff --git a/drivers/hv/dxgkrnl/dxgvmbus.c b/drivers/hv/dxgkrnl/dxgvmbus.c
> index 773d8f364b34..185fb7e38c21 100644
> --- a/drivers/hv/dxgkrnl/dxgvmbus.c
> +++ b/drivers/hv/dxgkrnl/dxgvmbus.c
> @@ -1311,15 +1311,18 @@ int create_existing_sysmem(struct dxgdevice *device,
>  	void *kmem = NULL;
>  	int ret = 0;
>  	struct dxgkvmb_command_setexistingsysmemstore *set_store_command;
> +	struct dxgkvmb_command_setexistingsysmempages *set_pages_command;
>  	u64 alloc_size = host_alloc->allocation_size;
>  	u32 npages = alloc_size >> PAGE_SHIFT;
>  	struct dxgvmbusmsg msg = {.hdr = NULL};
> -
> -	ret = init_message(&msg, device->adapter, device->process,
> -			   sizeof(*set_store_command));
> -	if (ret)
> -		goto cleanup;
> -	set_store_command = (void *)msg.msg;
> +	const u32 max_pfns_in_message =
> +		(DXG_MAX_VM_BUS_PACKET_SIZE - sizeof(*set_pages_command) -
> +		PAGE_SIZE) / sizeof(__u64);
> +	u32 alloc_offset_in_pages = 0;
> +	struct page **page_in;
> +	u64 *pfn;
> +	u32 pages_to_send;
> +	u32 i;
>  
>  	/*
>  	 * Create a guest physical address list and set it as the allocation
> @@ -1330,6 +1333,7 @@ int create_existing_sysmem(struct dxgdevice *device,
>  	dev_dbg(dxgglobaldev, "   Alloc size: %lld", alloc_size);
>  
>  	dxgalloc->cpu_address = (void *)sysmem;
> +
>  	dxgalloc->pages = vzalloc(npages * sizeof(void *));
>  	if (dxgalloc->pages == NULL) {
>  		pr_err("failed to allocate pages");
> @@ -1347,31 +1351,80 @@ int create_existing_sysmem(struct dxgdevice *device,
>  		ret = -ENOMEM;
>  		goto cleanup;
>  	}
> -	kmem = vmap(dxgalloc->pages, npages, VM_MAP, PAGE_KERNEL);
> -	if (kmem == NULL) {
> -		pr_err("vmap failed");
> -		ret = -ENOMEM;
> -		goto cleanup;
> -	}
> -	ret1 = vmbus_establish_gpadl(dxgglobal_get_vmbus(), kmem,
> -				     alloc_size, &dxgalloc->gpadl);
> -	if (ret1) {
> -		pr_err("establish_gpadl failed: %d", ret1);
> -		ret = -ENOMEM;
> -		goto cleanup;
> -	}
> -	dev_dbg(dxgglobaldev, "New gpadl %d", dxgalloc->gpadl.gpadl_handle);
> +	if (!dxgglobal->map_guest_pages_enabled) {
> +		ret = init_message(&msg, device->adapter, device->process,
> +				sizeof(*set_store_command));
> +		if (ret)
> +			goto cleanup;
> +		set_store_command = (void *)msg.msg;
>  
> -	command_vgpu_to_host_init2(&set_store_command->hdr,
> -				   DXGK_VMBCOMMAND_SETEXISTINGSYSMEMSTORE,
> -				   device->process->host_handle);
> -	set_store_command->device = device->handle;
> -	set_store_command->device = device->handle;
> -	set_store_command->allocation = host_alloc->allocation;
> -	set_store_command->gpadl = dxgalloc->gpadl.gpadl_handle;
> -	ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr, msg.size);
> -	if (ret < 0)
> -		pr_err("failed to set existing store: %x", ret);
> +		kmem = vmap(dxgalloc->pages, npages, VM_MAP, PAGE_KERNEL);
> +		if (kmem == NULL) {
> +			pr_err("vmap failed");
> +			ret = -ENOMEM;
> +			goto cleanup;
> +		}
> +		ret1 = vmbus_establish_gpadl(dxgglobal_get_vmbus(), kmem,
> +					alloc_size, &dxgalloc->gpadl);
> +		if (ret1) {
> +			pr_err("establish_gpadl failed: %d", ret1);
> +			ret = -ENOMEM;
> +			goto cleanup;
> +		}
> +		dev_dbg(dxgglobaldev, "New gpadl %d",
> +			dxgalloc->gpadl.gpadl_handle);
> +
> +		command_vgpu_to_host_init2(&set_store_command->hdr,
> +					DXGK_VMBCOMMAND_SETEXISTINGSYSMEMSTORE,
> +					device->process->host_handle);
> +		set_store_command->device = device->handle;
> +		set_store_command->allocation = host_alloc->allocation;
> +		set_store_command->gpadl = dxgalloc->gpadl.gpadl_handle;
> +		ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr,
> +						    msg.size);
> +		if (ret < 0)
> +			pr_err("failed to set existing store: %x", ret);
> +	} else {
> +		/*
> +		 * Send the list of the allocation PFNs to the host. The host
> +		 * will map the pages for GPU access.
> +		 */
> +
> +		ret = init_message(&msg, device->adapter, device->process,
> +				sizeof(*set_pages_command) +
> +				max_pfns_in_message * sizeof(u64));
> +		if (ret)
> +			goto cleanup;
> +		set_pages_command = (void *)msg.msg;
> +		command_vgpu_to_host_init2(&set_pages_command->hdr,
> +					DXGK_VMBCOMMAND_SETEXISTINGSYSMEMPAGES,
> +					device->process->host_handle);
> +		set_pages_command->device = device->handle;
> +		set_pages_command->allocation = host_alloc->allocation;
> +
> +		page_in = dxgalloc->pages;
> +		while (alloc_offset_in_pages < npages) {
> +			pfn = (u64 *)((char *)msg.msg +
> +				sizeof(*set_pages_command));
> +			pages_to_send = min(npages - alloc_offset_in_pages,
> +					    max_pfns_in_message);
> +			set_pages_command->num_pages = pages_to_send;
> +			set_pages_command->alloc_offset_in_pages =
> +				alloc_offset_in_pages;
> +
> +			for (i = 0; i < pages_to_send; i++)
> +				*pfn++ = page_to_pfn(*page_in++);
> +
> +			ret = dxgvmb_send_sync_msg_ntstatus(msg.channel,
> +							    msg.hdr,
> +							    msg.size);
> +			if (ret < 0) {
> +				pr_err("failed to set existing pages: %x", ret);
> +				break;
> +			}
> +			alloc_offset_in_pages += pages_to_send;
> +		}
> +	}
>  
>  cleanup:
>  	if (kmem)
> @@ -2685,6 +2738,7 @@ int dxgvmb_send_wait_sync_object_cpu(struct dxgprocess *process,
>  				     struct
>  				     d3dkmt_waitforsynchronizationobjectfromcpu
>  				     *args,
> +				     bool user_address,
>  				     u64 cpu_event)
>  {
>  	int ret = -EINVAL;
> @@ -2708,18 +2762,25 @@ int dxgvmb_send_wait_sync_object_cpu(struct dxgprocess *process,
>  	command->object_count = args->object_count;
>  	command->guest_event_pointer = (u64) cpu_event;
>  	current_pos = (u8 *) &command[1];
> -	ret = copy_from_user(current_pos, args->objects, object_size);
> -	if (ret) {
> -		pr_err("%s failed to copy objects", __func__);
> -		ret = -EINVAL;
> -		goto cleanup;
> -	}
> -	current_pos += object_size;
> -	ret = copy_from_user(current_pos, args->fence_values, fence_size);
> -	if (ret) {
> -		pr_err("%s failed to copy fences", __func__);
> -		ret = -EINVAL;
> -		goto cleanup;
> +	if (user_address) {
> +		ret = copy_from_user(current_pos, args->objects, object_size);
> +		if (ret) {
> +			pr_err("%s failed to copy objects", __func__);
> +			ret = -EINVAL;
> +			goto cleanup;
> +		}
> +		current_pos += object_size;
> +		ret = copy_from_user(current_pos, args->fence_values,
> +				     fence_size);
> +		if (ret) {
> +			pr_err("%s failed to copy fences", __func__);
> +			ret = -EINVAL;
> +			goto cleanup;
> +		}
> +	} else {
> +		memcpy(current_pos, args->objects, object_size);
> +		current_pos += object_size;
> +		memcpy(current_pos, args->fence_values, fence_size);
>  	}
>  
>  	ret = dxgvmb_send_sync_msg_ntstatus(msg.channel, msg.hdr, msg.size);
> diff --git a/drivers/hv/dxgkrnl/dxgvmbus.h b/drivers/hv/dxgkrnl/dxgvmbus.h
> index a19ac804a320..dc766d95a0c4 100644
> --- a/drivers/hv/dxgkrnl/dxgvmbus.h
> +++ b/drivers/hv/dxgkrnl/dxgvmbus.h
> @@ -139,6 +139,8 @@ enum dxgkvmb_commandtype {
>  	DXGK_VMBCOMMAND_GETCONTEXTSCHEDULINGPRIORITY = 61,
>  	DXGK_VMBCOMMAND_QUERYCLOCKCALIBRATION	= 62,
>  	DXGK_VMBCOMMAND_QUERYRESOURCEINFO	= 64,
> +	DXGK_VMBCOMMAND_LOGEVENT		= 65,
> +	DXGK_VMBCOMMAND_SETEXISTINGSYSMEMPAGES	= 66,
>  	DXGK_VMBCOMMAND_INVALID
>  };
>  
> @@ -245,6 +247,16 @@ struct dxgkvmb_command_setexistingsysmemstore {
>  	u32				gpadl;
>  };
>  
> +/* Returns ntstatus */
> +struct dxgkvmb_command_setexistingsysmempages {
> +	struct dxgkvmb_command_vgpu_to_host hdr;
> +	struct d3dkmthandle		device;
> +	struct d3dkmthandle		allocation;
> +	u32				num_pages;
> +	u32				alloc_offset_in_pages;
> +	/* u64 pfn_array[num_pages] */
> +};
> +
>  struct dxgkvmb_command_createprocess {
>  	struct dxgkvmb_command_vm_to_host hdr;
>  	void			*process;
> diff --git a/drivers/hv/dxgkrnl/ioctl.c b/drivers/hv/dxgkrnl/ioctl.c
> index 9770fabf163e..9236b6b95973 100644
> --- a/drivers/hv/dxgkrnl/ioctl.c
> +++ b/drivers/hv/dxgkrnl/ioctl.c
> @@ -19,6 +19,7 @@
>  
>  #include "dxgkrnl.h"
>  #include "dxgvmbus.h"
> +#include "dxgsyncfile.h"
>  
>  #undef pr_fmt
>  #define pr_fmt(fmt)	"dxgk:err: " fmt
> @@ -32,11 +33,6 @@ struct ioctl_desc {
>  };
>  static struct ioctl_desc ioctls[LX_IO_MAX + 1];
>  
> -static char *errorstr(int ret)
> -{
> -	return ret < 0 ? "err" : "";
> -}
> -
>  static int dxgsyncobj_release(struct inode *inode, struct file *file)
>  {
>  	struct dxgsharedsyncobject *syncobj = file->private_data;
> @@ -3561,7 +3557,7 @@ dxgk_wait_sync_object_cpu(struct dxgprocess *process, void *__user inargs)
>  	}
>  
>  	ret = dxgvmb_send_wait_sync_object_cpu(process, adapter,
> -					       &args, event_id);
> +					       &args, true, event_id);
>  	if (ret < 0)
>  		goto cleanup;
>  
> @@ -5457,4 +5453,6 @@ void init_ioctls(void)
>  		  LX_DXQUERYSTATISTICS);
>  	SET_IOCTL(/*0x44 */ dxgk_share_object_with_host,
>  		  LX_DXSHAREOBJECTWITHHOST);
> +	SET_IOCTL(/*0x45 */ dxgk_create_sync_file,
> +		  LX_DXCREATESYNCFILE);
>  }
> diff --git a/drivers/hv/dxgkrnl/misc.c b/drivers/hv/dxgkrnl/misc.c
> index ffb491641836..1b152c269265 100644
> --- a/drivers/hv/dxgkrnl/misc.c
> +++ b/drivers/hv/dxgkrnl/misc.c
> @@ -35,3 +35,9 @@ u16 *wcsncpy(u16 *dest, const u16 *src, size_t n)
>  	dest[i - 1] = 0;
>  	return dest;
>  }
> +
> +char *errorstr(int ret)
> +{
> +	return ret < 0 ? "err" : "";
> +}
> +
> diff --git a/drivers/hv/dxgkrnl/misc.h b/drivers/hv/dxgkrnl/misc.h
> index 7fe3fc45b67c..3079dd55c7a4 100644
> --- a/drivers/hv/dxgkrnl/misc.h
> +++ b/drivers/hv/dxgkrnl/misc.h
> @@ -44,6 +44,7 @@ extern const struct d3dkmthandle zerohandle;
>   */
>  
>  u16 *wcsncpy(u16 *dest, const u16 *src, size_t n);
> +char *errorstr(int ret);
>  
>  enum dxglockstate {
>  	DXGLOCK_SHARED,
> -- 
> 2.32.0
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

  parent reply	other threads:[~2022-01-14 18:03 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-12 19:55 [PATCH v1 0/9] drivers: hv: dxgkrnl: Driver overview Iouri Tarassov
2022-01-12 19:55 ` [PATCH v1 1/9] drivers: hv: dxgkrnl: Driver initialization and creation of dxgadapter Iouri Tarassov
2022-01-13  1:49   ` kernel test robot
2022-01-13  1:49     ` kernel test robot
2022-01-13  6:42   ` kernel test robot
2022-01-13  6:42     ` kernel test robot
2022-01-13  7:43   ` Greg KH
2022-01-13  7:46   ` Greg KH
2022-01-14  0:08     ` Iouri Tarassov
2022-01-14  5:40       ` Greg KH
2022-01-12 19:55 ` [PATCH v1 2/9] drivers: hv: dxgkrnl: Open device object, adapter enumeration, dxgdevice, dxgcontext creation Iouri Tarassov
2022-01-13  7:41   ` Greg KH
2022-01-13  7:44   ` kernel test robot
2022-01-13  7:44     ` kernel test robot
2022-01-12 19:55 ` [PATCH v1 3/9] drivers: hv: dxgkrnl: Implement creation/destruction of GPU allocations/resources Iouri Tarassov
2022-01-13  8:56   ` kernel test robot
2022-01-13  8:56     ` kernel test robot
2022-01-12 19:55 ` [PATCH v1 4/9] drivers: hv: dxgkrnl: Implement operations with GPU sync objects Iouri Tarassov
2022-01-12 19:55 ` [PATCH v1 5/9] drivers: hv: dxgkrnl: Implement sharing resources and " Iouri Tarassov
2022-01-12 19:55 ` [PATCH v1 6/9] drivers: hv: dxgkrnl: Seal the shared resource object when dxgk_share_objects is called Iouri Tarassov
2022-01-12 19:55 ` [PATCH v1 7/9] drivers: hv: dxgkrnl: Implementation of submit command, paging and hardware queue Iouri Tarassov
2022-01-12 19:55 ` [PATCH v1 8/9] drivers: hv: dxgkrnl: Implement various WDDM ioctls Iouri Tarassov
2022-01-13  7:47   ` Greg KH
2022-01-14  0:19     ` Iouri Tarassov
2022-01-14  5:38       ` Greg KH
2022-01-15  2:16         ` Iouri Tarassov
2022-01-12 19:55 ` [PATCH v1 9/9] drivers: hv: dxgkrnl: Implement DXGSYNCFILE Iouri Tarassov
2022-01-13  7:41   ` Greg KH
2022-01-14 22:26     ` Iouri Tarassov
2022-01-14 18:03   ` Daniel Vetter [this message]
2022-01-14 18:03     ` Daniel Vetter
2022-01-14 18:52     ` Iouri Tarassov
2022-01-17  9:35       ` Daniel Vetter
2022-01-17  9:35         ` Daniel Vetter
2022-02-05  0:35         ` Iouri Tarassov
2022-02-05  0:35           ` Iouri Tarassov
2022-02-08 12:28           ` Daniel Vetter
2022-02-08 12:28             ` Daniel Vetter
2022-01-12 22:12 ` [PATCH v1 0/9] drivers: hv: dxgkrnl: Driver overview Nathan Chancellor
2022-01-12 23:39   ` Iouri Tarassov
2022-01-26  0:27     ` Nathan Chancellor
2022-02-05  0:31       ` Iouri Tarassov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=YeG6+Crv/Bg4h3u1@phenom.ffwll.local \
    --to=daniel@ffwll.ch \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=haiyangz@microsoft.com \
    --cc=iourit@linux.microsoft.com \
    --cc=jenatali@microsoft.com \
    --cc=kys@microsoft.com \
    --cc=linux-hyperv@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=spronovo@microsoft.com \
    --cc=sthemmin@microsoft.com \
    --cc=wei.liu@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.