[PATCH] drm/xen-front: Replace NULL with error value in xen_drm_front_gem_get_sg_table
From: Oleksandr Andrushchenko Dan Carpenter has reported that there is the following static checker warning: drivers/gpu/drm/drm_prime.c:317 drm_gem_map_dma_buf() warn: 'sgt' can also be NULL 314 sgt = obj->dev->driver->gem_prime_get_sg_table(obj); 315 316 if (!IS_ERR(sgt)) { 317 if (!dma_map_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir, And one of the problematic functions is xen_drm_front_gem_get_sg_table. Fix this by replacing NULL with error value. Signed-off-by: Oleksandr Andrushchenko Reported-by: Dan Carpenter --- drivers/gpu/drm/xen/xen_drm_front_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xen/xen_drm_front_gem.c b/drivers/gpu/drm/xen/xen_drm_front_gem.c index c85bfe7571cb..47ff019d3aef 100644 --- a/drivers/gpu/drm/xen/xen_drm_front_gem.c +++ b/drivers/gpu/drm/xen/xen_drm_front_gem.c @@ -179,7 +179,7 @@ struct sg_table *xen_drm_front_gem_get_sg_table(struct drm_gem_object *gem_obj) struct xen_gem_object *xen_obj = to_xen_gem_obj(gem_obj); if (!xen_obj->pages) - return NULL; + return ERR_PTR(-ENOMEM); return drm_prime_pages_to_sg(xen_obj->pages, xen_obj->num_pages); } -- 2.17.1
[PATCH v4 3/9] xen/balloon: Share common memory reservation routines
From: Oleksandr Andrushchenko Memory {increase|decrease}_reservation and VA mappings update/reset code used in balloon driver can be made common, so other drivers can also re-use the same functionality without open-coding. Create a dedicated file for the shared code and export corresponding symbols for other kernel modules. Signed-off-by: Oleksandr Andrushchenko --- drivers/xen/Makefile | 1 + drivers/xen/balloon.c | 75 ++--- drivers/xen/mem-reservation.c | 118 ++ include/xen/mem-reservation.h | 59 + 4 files changed, 184 insertions(+), 69 deletions(-) create mode 100644 drivers/xen/mem-reservation.c create mode 100644 include/xen/mem-reservation.h diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile index 451e833f5931..3c87b0c3aca6 100644 --- a/drivers/xen/Makefile +++ b/drivers/xen/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o obj-$(CONFIG_X86) += fallback.o obj-y += grant-table.o features.o balloon.o manage.o preempt.o time.o +obj-y += mem-reservation.o obj-y += events/ obj-y += xenbus/ diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index 065f0b607373..e12bb256036f 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -71,6 +71,7 @@ #include #include #include +#include static int xen_hotplug_unpopulated; @@ -157,13 +158,6 @@ static DECLARE_DELAYED_WORK(balloon_worker, balloon_process); #define GFP_BALLOON \ (GFP_HIGHUSER | __GFP_NOWARN | __GFP_NORETRY | __GFP_NOMEMALLOC) -static void scrub_page(struct page *page) -{ -#ifdef CONFIG_XEN_SCRUB_PAGES - clear_highpage(page); -#endif -} - /* balloon_append: add the given page to the balloon. */ static void __balloon_append(struct page *page) { @@ -463,11 +457,6 @@ static enum bp_state increase_reservation(unsigned long nr_pages) int rc; unsigned long i; struct page *page; - struct xen_memory_reservation reservation = { - .address_bits = 0, - .extent_order = EXTENT_ORDER, - .domid= DOMID_SELF - }; if (nr_pages > ARRAY_SIZE(frame_list)) nr_pages = ARRAY_SIZE(frame_list); @@ -479,16 +468,11 @@ static enum bp_state increase_reservation(unsigned long nr_pages) break; } - /* XENMEM_populate_physmap requires a PFN based on Xen -* granularity. -*/ frame_list[i] = page_to_xen_pfn(page); page = balloon_next_page(page); } - set_xen_guest_handle(reservation.extent_start, frame_list); - reservation.nr_extents = nr_pages; - rc = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation); + rc = xenmem_reservation_increase(nr_pages, frame_list); if (rc <= 0) return BP_EAGAIN; @@ -496,29 +480,7 @@ static enum bp_state increase_reservation(unsigned long nr_pages) page = balloon_retrieve(false); BUG_ON(page == NULL); -#ifdef CONFIG_XEN_HAVE_PVMMU - /* -* We don't support PV MMU when Linux and Xen is using -* different page granularity. -*/ - BUILD_BUG_ON(XEN_PAGE_SIZE != PAGE_SIZE); - - if (!xen_feature(XENFEAT_auto_translated_physmap)) { - unsigned long pfn = page_to_pfn(page); - - set_phys_to_machine(pfn, frame_list[i]); - - /* Link back into the page tables if not highmem. */ - if (!PageHighMem(page)) { - int ret; - ret = HYPERVISOR_update_va_mapping( - (unsigned long)__va(pfn << PAGE_SHIFT), - mfn_pte(frame_list[i], PAGE_KERNEL), - 0); - BUG_ON(ret); - } - } -#endif + xenmem_reservation_va_mapping_update(1, &page, &frame_list[i]); /* Relinquish the page back to the allocator. */ free_reserved_page(page); @@ -535,11 +497,6 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) unsigned long i; struct page *page, *tmp; int ret; - struct xen_memory_reservation reservation = { - .address_bits = 0, - .extent_order = EXTENT_ORDER, - .domid= DOMID_SELF - }; LIST_HEAD(pages); if (nr_pages > ARRAY_SIZE(frame_list)) @@ -553,7 +510,7 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) break; } ad
[PATCH v4 1/9] xen/grant-table: Export gnttab_{alloc|free}_pages as GPL
From: Oleksandr Andrushchenko Only gnttab_{alloc|free}_pages are exported as EXPORT_SYMBOL while all the rest are exported as EXPORT_SYMBOL_GPL, thus effectively making it not possible for non-GPL driver modules to use grant table module. Export gnttab_{alloc|free}_pages as EXPORT_SYMBOL_GPL so all the exports are aligned. Signed-off-by: Oleksandr Andrushchenko Reviewed-by: Juergen Gross --- drivers/xen/grant-table.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index 27be107d6480..ba36ff3e4903 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -799,7 +799,7 @@ int gnttab_alloc_pages(int nr_pages, struct page **pages) return 0; } -EXPORT_SYMBOL(gnttab_alloc_pages); +EXPORT_SYMBOL_GPL(gnttab_alloc_pages); /** * gnttab_free_pages - free pages allocated by gnttab_alloc_pages() @@ -820,7 +820,7 @@ void gnttab_free_pages(int nr_pages, struct page **pages) } free_xenballooned_pages(nr_pages, pages); } -EXPORT_SYMBOL(gnttab_free_pages); +EXPORT_SYMBOL_GPL(gnttab_free_pages); /* Handling of paged out grant targets (GNTST_eagain) */ #define MAX_DELAY 256 -- 2.17.1
Re: [PATCH v5 1/3] xen: Sync up with the canonical protocol definitions in Xen
On 06/13/2018 09:40 AM, Juergen Gross wrote: On 13/06/18 08:13, Oleksandr Andrushchenko wrote: On 06/13/2018 09:11 AM, Dmitry Torokhov wrote: On June 12, 2018 10:49:31 PM PDT, Oleksandr Andrushchenko wrote: On 06/13/2018 02:40 AM, Dmitry Torokhov wrote: On Tue, Jun 12, 2018 at 03:46:10PM +0200, Juergen Gross wrote: On 12/06/18 09:48, Oleksandr Andrushchenko wrote: From: Oleksandr Andrushchenko This is the sync up with the canonical definitions of the input, sound and display protocols in Xen. Changes to kbdif: 1. Add missing string constants for {feature|request}-raw-pointer to align with the rest of the interface file. 2. Add new XenStore feature fields, so it is possible to individually control set of exposed virtual devices for each guest OS: - set feature-disable-keyboard to 1 if no keyboard device needs to be created - set feature-disable-pointer to 1 if no pointer device needs to be created 3. Move multi-touch device parameters to backend nodes: these are described as a part of frontend's XenBus configuration nodes while they belong to backend's configuration. Fix this by moving the parameters to the proper section. Unique-id field: 1. Add unique-id XenBus entry for virtual input and display. 2. Change type of unique-id field to string for sndif to align with display and input protocols. Signed-off-by: Oleksandr Andrushchenko Cc: Konrad Rzeszutek Wilk Reviewed-by: Juergen Gross I'm fine with this patch being added via the input tree with the other patches. In case I should take it via the Xen tree, please send me a note. Juergen, I created an immutable branch off v4.17 with these 3 patches in case you would want to merge them into your tree without waiting for them to appear in mainline: git pull git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git ib/4.17-xen-kbdfront-runtime-config Thanks. Thank you, I would prefer the fastest path of course It will be part of 4.19 pull request; the immutable branch is for Juergen if he does not want to wait till 4.19 merge window to get the changes. Ah, I see. Juergen, can we please merge this via Xen tree then which I assume will be faster? As Dmitry has it already queued in the input tree I think this is fine. I trust him to take the right decision for which kernel version those patches are to be queued. They belong to the input tree after all. Of course, no doubt here Juergen Thank you, Oleksandr
Re: [Xen-devel] [PATCH v2 5/9] xen/gntdev: Allow mappings for DMA buffers
On 06/08/2018 10:21 PM, Boris Ostrovsky wrote: On 06/08/2018 01:59 PM, Stefano Stabellini wrote: @@ -325,6 +401,14 @@ static int map_grant_pages(struct grant_map *map) map->unmap_ops[i].handle = map->map_ops[i].handle; if (use_ptemod) map->kunmap_ops[i].handle = map->kmap_ops[i].handle; +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC + else if (map->dma_vaddr) { + unsigned long mfn; + + mfn = __pfn_to_mfn(page_to_pfn(map->pages[i])); Not pfn_to_mfn()? I'd love to, but pfn_to_mfn is only defined for x86, not ARM: [1] and [2] Thus, drivers/xen/gntdev.c:408:10: error: implicit declaration of function ‘pfn_to_mfn’ [-Werror=implicit-function-declaration] mfn = pfn_to_mfn(page_to_pfn(map->pages[i])); So, I'll keep __pfn_to_mfn How will this work on non-PV x86? So, you mean I need: #ifdef CONFIG_X86 mfn = pfn_to_mfn(page_to_pfn(map->pages[i])); #else mfn = __pfn_to_mfn(page_to_pfn(map->pages[i])); #endif I'd rather fix it in ARM code. Stefano, why does ARM uses the underscored version? Do you want me to add one more patch for ARM to wrap __pfn_to_mfn with static inline for ARM? e.g. static inline ...pfn_to_mfn(...) { __pfn_to_mfn(); } A Xen on ARM guest doesn't actually know the mfns behind its own pseudo-physical pages. This is why we stopped using pfn_to_mfn and started using pfn_to_bfn instead, which will generally return "pfn", unless the page is a foreign grant. See include/xen/arm/page.h. pfn_to_bfn was also introduced on x86. For example, see the usage of pfn_to_bfn in drivers/xen/swiotlb-xen.c. Otherwise, if you don't care about other mapped grants, you can just use pfn_to_gfn, that always returns pfn. I think then this code needs to use pfn_to_bfn(). Ok Also, for your information, we support different page granularities in Linux as a Xen guest, see the comment at include/xen/arm/page.h: /* * The pseudo-physical frame (pfn) used in all the helpers is always based * on Xen page granularity (i.e 4KB). * * A Linux page may be split across multiple non-contiguous Xen page so we * have to keep track with frame based on 4KB page granularity. * * PV drivers should never make a direct usage of those helpers (particularly * pfn_to_gfn and gfn_to_pfn). */ A Linux page could be 64K, but a Xen page is always 4K. A granted page is also 4K. We have helpers to take into account the offsets to map multiple Xen grants in a single Linux page, see for example drivers/xen/grant-table.c:gnttab_foreach_grant. Most PV drivers have been converted to be able to work with 64K pages correctly, but if I remember correctly gntdev.c is the only remaining driver that doesn't support 64K pages yet, so you don't have to deal with it if you don't want to. I believe somewhere in this series there is a test for PAGE_SIZE vs. XEN_PAGE_SIZE. Right, Oleksandr? Not in gntdev. You might have seen this in xen-drmfront/xen-sndfront, but I didn't touch gntdev for that. Do you want me to add yet another patch in the series to check for that? Thanks for the explanation. -boris Thank you, Oleksandr
Re: [PATCH 2/8] xen/balloon: Move common memory reservation routines to a module
On 05/29/2018 09:04 PM, Boris Ostrovsky wrote: On 05/25/2018 11:33 AM, Oleksandr Andrushchenko wrote: From: Oleksandr Andrushchenko Memory {increase|decrease}_reservation and VA mappings update/reset code used in balloon driver can be made common, so other drivers can also re-use the same functionality without open-coding. Create a dedicated module IIUIC this is not really a module, it's a common file. Sure, will put "file" here for the shared code and export corresponding symbols for other kernel modules. Signed-off-by: Oleksandr Andrushchenko --- drivers/xen/Makefile | 1 + drivers/xen/balloon.c | 71 ++ drivers/xen/mem-reservation.c | 134 ++ include/xen/mem_reservation.h | 29 4 files changed, 170 insertions(+), 65 deletions(-) create mode 100644 drivers/xen/mem-reservation.c create mode 100644 include/xen/mem_reservation.h diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile index 451e833f5931..3c87b0c3aca6 100644 --- a/drivers/xen/Makefile +++ b/drivers/xen/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o obj-$(CONFIG_X86) += fallback.o obj-y += grant-table.o features.o balloon.o manage.o preempt.o time.o +obj-y += mem-reservation.o obj-y += events/ obj-y += xenbus/ diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index 065f0b607373..57b482d67a3a 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -71,6 +71,7 @@ #include #include #include +#include static int xen_hotplug_unpopulated; @@ -157,13 +158,6 @@ static DECLARE_DELAYED_WORK(balloon_worker, balloon_process); #define GFP_BALLOON \ (GFP_HIGHUSER | __GFP_NOWARN | __GFP_NORETRY | __GFP_NOMEMALLOC) -static void scrub_page(struct page *page) -{ -#ifdef CONFIG_XEN_SCRUB_PAGES - clear_highpage(page); -#endif -} - /* balloon_append: add the given page to the balloon. */ static void __balloon_append(struct page *page) { @@ -463,11 +457,6 @@ static enum bp_state increase_reservation(unsigned long nr_pages) int rc; unsigned long i; struct page *page; - struct xen_memory_reservation reservation = { - .address_bits = 0, - .extent_order = EXTENT_ORDER, - .domid= DOMID_SELF - }; if (nr_pages > ARRAY_SIZE(frame_list)) nr_pages = ARRAY_SIZE(frame_list); @@ -486,9 +475,7 @@ static enum bp_state increase_reservation(unsigned long nr_pages) page = balloon_next_page(page); } - set_xen_guest_handle(reservation.extent_start, frame_list); - reservation.nr_extents = nr_pages; - rc = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation); + rc = xenmem_reservation_increase(nr_pages, frame_list); if (rc <= 0) return BP_EAGAIN; @@ -496,29 +483,7 @@ static enum bp_state increase_reservation(unsigned long nr_pages) page = balloon_retrieve(false); BUG_ON(page == NULL); -#ifdef CONFIG_XEN_HAVE_PVMMU - /* -* We don't support PV MMU when Linux and Xen is using -* different page granularity. -*/ - BUILD_BUG_ON(XEN_PAGE_SIZE != PAGE_SIZE); - - if (!xen_feature(XENFEAT_auto_translated_physmap)) { - unsigned long pfn = page_to_pfn(page); - - set_phys_to_machine(pfn, frame_list[i]); - - /* Link back into the page tables if not highmem. */ - if (!PageHighMem(page)) { - int ret; - ret = HYPERVISOR_update_va_mapping( - (unsigned long)__va(pfn << PAGE_SHIFT), - mfn_pte(frame_list[i], PAGE_KERNEL), - 0); - BUG_ON(ret); - } - } -#endif + xenmem_reservation_va_mapping_update(1, &page, &frame_list[i]); Can you make a single call to xenmem_reservation_va_mapping_update(rc, ...)? You need to keep track of pages but presumable they can be put into an array (or a list). In fact, perhaps we can have balloon_retrieve() return a set of pages. This is actually how it is used later on for dma-buf, but I just didn't want to alter original balloon code too much, but this can be done, in order of simplicity: 1. Similar to frame_list, e.g. static array of struct page* of size ARRAY_SIZE(frame_list): more static memory is used, but no allocations 2. Allocated at run-time with kcalloc: allocation can fail 3. Make balloon_retrieve() return a set of pages: will require list/array allocation and handling, allocation may fail, balloon_retri
Re: [PATCH] drm: Fix possible race conditions while unplugging DRM device
ping On 05/22/2018 05:13 PM, Oleksandr Andrushchenko wrote: From: Oleksandr Andrushchenko When unplugging a hotpluggable DRM device we first unregister it with drm_dev_unregister and then set drm_device.unplugged flag which is used to mark device critical sections with drm_dev_enter()/ drm_dev_exit() preventing access to device resources that are not available after the device is gone. But drm_dev_unregister may lead to hotplug uevent(s) fired to user-space on card and/or connector removal, thus making it possible for user-space to try accessing a disconnected device. Fix this by first making sure device is properly marked as disconnected and only then unregister it. Fixes: bee330f3d672 ("drm: Use srcu to protect drm_device.unplugged") Signed-off-by: Oleksandr Andrushchenko Reported-by: Andrii Chepurnyi Cc: "Noralf Trønnes" --- drivers/gpu/drm/drm_drv.c | 14 +++--- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index b553a6f2ff0e..7af748ed1c58 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -369,13 +369,6 @@ EXPORT_SYMBOL(drm_dev_exit); */ void drm_dev_unplug(struct drm_device *dev) { - drm_dev_unregister(dev); - - mutex_lock(&drm_global_mutex); - if (dev->open_count == 0) - drm_dev_put(dev); - mutex_unlock(&drm_global_mutex); - /* * After synchronizing any critical read section is guaranteed to see * the new value of ->unplugged, and any critical section which might @@ -384,6 +377,13 @@ void drm_dev_unplug(struct drm_device *dev) */ dev->unplugged = true; synchronize_srcu(&drm_unplug_srcu); + + drm_dev_unregister(dev); + + mutex_lock(&drm_global_mutex); + if (dev->open_count == 0) + drm_dev_put(dev); + mutex_unlock(&drm_global_mutex); } EXPORT_SYMBOL(drm_dev_unplug);
Re: [Xen-devel] [PATCH 3/8] drm/xen-front: fix 32-bit build warning
Hi, On 05/25/2018 06:50 PM, Arnd Bergmann wrote: In 32-bit kernel builds, we cannot cast between a pointer and a 64-bit type: In file included from drivers/gpu/drm/xen/xen_drm_front_cfg.c:18: drivers/gpu/drm/xen/xen_drm_front.h: In function 'xen_drm_front_fb_to_cookie': drivers/gpu/drm/xen/xen_drm_front.h:129:9: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast] return (u64)fb; drivers/gpu/drm/xen/xen_drm_front.h: In function 'xen_drm_front_dbuf_to_cookie': drivers/gpu/drm/xen/xen_drm_front.h:134:9: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast] return (u64)gem_obj; drivers/gpu/drm/xen/xen_drm_front_shbuf.c: In function 'backend_unmap': drivers/gpu/drm/xen/xen_drm_front_shbuf.c:125:4: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast] ((phys_addr_t)pfn_to_kaddr(page_to_xen_pfn(page))) Using uintptr_t instead probably does what we want here, although it's not clear to me why we assign a virtual address pointer to a phys_addr_t in backend_unmap(). Fixes: c575b7eeb89f ("drm/xen-front: Add support for Xen PV display frontend") Signed-off-by: Arnd Bergmann --- drivers/gpu/drm/xen/xen_drm_front.h | 4 ++-- drivers/gpu/drm/xen/xen_drm_front_shbuf.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/xen/xen_drm_front.h b/drivers/gpu/drm/xen/xen_drm_front.h index 2c2479b571ae..5693b4a4b02b 100644 --- a/drivers/gpu/drm/xen/xen_drm_front.h +++ b/drivers/gpu/drm/xen/xen_drm_front.h @@ -126,12 +126,12 @@ struct xen_drm_front_drm_info { static inline u64 xen_drm_front_fb_to_cookie(struct drm_framebuffer *fb) { - return (u64)fb; + return (uintptr_t)fb; } static inline u64 xen_drm_front_dbuf_to_cookie(struct drm_gem_object *gem_obj) { - return (u64)gem_obj; + return (uintptr_t)gem_obj; } int xen_drm_front_mode_set(struct xen_drm_front_drm_pipeline *pipeline, diff --git a/drivers/gpu/drm/xen/xen_drm_front_shbuf.c b/drivers/gpu/drm/xen/xen_drm_front_shbuf.c index 8099cb343ae3..d333b67cc1a0 100644 --- a/drivers/gpu/drm/xen/xen_drm_front_shbuf.c +++ b/drivers/gpu/drm/xen/xen_drm_front_shbuf.c @@ -122,7 +122,7 @@ static void guest_calc_num_grefs(struct xen_drm_front_shbuf *buf) } #define xen_page_to_vaddr(page) \ - ((phys_addr_t)pfn_to_kaddr(page_to_xen_pfn(page))) + ((uintptr_t)pfn_to_kaddr(page_to_xen_pfn(page))) static int backend_unmap(struct xen_drm_front_shbuf *buf) { Thank you for your patch: this issue was already discussed [1] and applied [2] to drm-misc-next. Thank you, Oleksandr [1] https://patchwork.freedesktop.org/patch/224359/ [2] https://patchwork.freedesktop.org/patch/224920/
Re: [alsa-devel] [PATCH] ALSA: xen: ensure nul-terminated device name
On 05/28/2018 06:59 PM, Arnd Bergmann wrote: gcc-8 warns that pcm_instance->name is not necessarily terminated correctly if the input is more than 80 characters long or lacks a termination byte itself: In function 'strncpy', inlined from 'cfg_device' at sound/xen/xen_snd_front_cfg.c:399:3, inlined from 'xen_snd_front_cfg_card' at sound/xen/xen_snd_front_cfg.c:509:9: include/linux/string.h:254:9: error: '__builtin_strncpy' specified bound 80 equals destination size [-Werror=stringop-truncation] return __builtin_strncpy(p, q, size); Using strlcpy() instead of strncpy() makes this a bit safer. Fixes: fd3b36045c2c ("ALSA: xen-front: Read sound driver configuration from Xen store") Signed-off-by: Arnd Bergmann --- sound/xen/xen_snd_front_cfg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/xen/xen_snd_front_cfg.c b/sound/xen/xen_snd_front_cfg.c index 38c7e1eefbb9..684b5f1d51ac 100644 --- a/sound/xen/xen_snd_front_cfg.c +++ b/sound/xen/xen_snd_front_cfg.c @@ -396,7 +396,7 @@ static int cfg_device(struct xen_snd_front_info *front_info, str = xenbus_read(XBT_NIL, device_path, XENSND_FIELD_DEVICE_NAME, NULL); if (!IS_ERR(str)) { - strncpy(pcm_instance->name, str, sizeof(pcm_instance->name)); + strlcpy(pcm_instance->name, str, sizeof(pcm_instance->name)); kfree(str); } Thank you for your patch, Reviewed-by: Oleksandr Andrushchenko
[PATCH 3/8] xen/grant-table: Allow allocating buffers suitable for DMA
From: Oleksandr Andrushchenko Extend grant table module API to allow allocating buffers that can be used for DMA operations and mapping foreign grant references on top of those. The resulting buffer is similar to the one allocated by the balloon driver in terms that proper memory reservation is made ({increase|decrease}_reservation and VA mappings updated if needed). This is useful for sharing foreign buffers with HW drivers which cannot work with scattered buffers provided by the balloon driver, but require DMAable memory instead. Signed-off-by: Oleksandr Andrushchenko --- drivers/xen/Kconfig | 13 drivers/xen/grant-table.c | 124 ++ include/xen/grant_table.h | 25 3 files changed, 162 insertions(+) diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index e5d0c28372ea..3431fe210624 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig @@ -161,6 +161,19 @@ config XEN_GRANT_DEV_ALLOC to other domains. This can be used to implement frontend drivers or as part of an inter-domain shared memory channel. +config XEN_GRANT_DMA_ALLOC + bool "Allow allocating DMA capable buffers with grant reference module" + depends on XEN + help + Extends grant table module API to allow allocating DMA capable + buffers and mapping foreign grant references on top of it. + The resulting buffer is similar to one allocated by the balloon + driver in terms that proper memory reservation is made + ({increase|decrease}_reservation and VA mappings updated if needed). + This is useful for sharing foreign buffers with HW drivers which + cannot work with scattered buffers provided by the balloon driver, + but require DMAable memory instead. + config SWIOTLB_XEN def_bool y select SWIOTLB diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index d7488226e1f2..06fe6e7f639c 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -45,6 +45,9 @@ #include #include #include +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC +#include +#endif #include #include @@ -57,6 +60,7 @@ #ifdef CONFIG_X86 #include #endif +#include #include #include @@ -811,6 +815,82 @@ int gnttab_alloc_pages(int nr_pages, struct page **pages) } EXPORT_SYMBOL(gnttab_alloc_pages); +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC +/** + * gnttab_dma_alloc_pages - alloc DMAable pages suitable for grant mapping into + * @args: arguments to the function + */ +int gnttab_dma_alloc_pages(struct gnttab_dma_alloc_args *args) +{ + unsigned long pfn, start_pfn; + xen_pfn_t *frames; + size_t size; + int i, ret; + + frames = kcalloc(args->nr_pages, sizeof(*frames), GFP_KERNEL); + if (!frames) + return -ENOMEM; + + size = args->nr_pages << PAGE_SHIFT; + if (args->coherent) + args->vaddr = dma_alloc_coherent(args->dev, size, +&args->dev_bus_addr, +GFP_KERNEL | __GFP_NOWARN); + else + args->vaddr = dma_alloc_wc(args->dev, size, + &args->dev_bus_addr, + GFP_KERNEL | __GFP_NOWARN); + if (!args->vaddr) { + pr_err("Failed to allocate DMA buffer of size %zu\n", size); + ret = -ENOMEM; + goto fail_free_frames; + } + + start_pfn = __phys_to_pfn(args->dev_bus_addr); + for (pfn = start_pfn, i = 0; pfn < start_pfn + args->nr_pages; + pfn++, i++) { + struct page *page = pfn_to_page(pfn); + + args->pages[i] = page; + frames[i] = xen_page_to_gfn(page); + xenmem_reservation_scrub_page(page); + } + + xenmem_reservation_va_mapping_reset(args->nr_pages, args->pages); + + ret = xenmem_reservation_decrease(args->nr_pages, frames); + if (ret != args->nr_pages) { + pr_err("Failed to decrease reservation for DMA buffer\n"); + xenmem_reservation_increase(ret, frames); + ret = -EFAULT; + goto fail_free_dma; + } + + ret = gnttab_pages_set_private(args->nr_pages, args->pages); + if (ret < 0) + goto fail_clear_private; + + kfree(frames); + return 0; + +fail_clear_private: + gnttab_pages_clear_private(args->nr_pages, args->pages); +fail_free_dma: + xenmem_reservation_va_mapping_update(args->nr_pages, args->pages, +frames); + if (args->coherent) + dma_free_coherent(args->dev, size, + args->vaddr, args->dev_bus_addr); +
[PATCH 1/8] xen/grant-table: Make set/clear page private code shared
From: Oleksandr Andrushchenko Make set/clear page private code shared and accessible to other kernel modules which can re-use these instead of open-coding. Signed-off-by: Oleksandr Andrushchenko --- drivers/xen/grant-table.c | 54 +-- include/xen/grant_table.h | 3 +++ 2 files changed, 38 insertions(+), 19 deletions(-) diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index 27be107d6480..d7488226e1f2 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -769,29 +769,18 @@ void gnttab_free_auto_xlat_frames(void) } EXPORT_SYMBOL_GPL(gnttab_free_auto_xlat_frames); -/** - * gnttab_alloc_pages - alloc pages suitable for grant mapping into - * @nr_pages: number of pages to alloc - * @pages: returns the pages - */ -int gnttab_alloc_pages(int nr_pages, struct page **pages) +int gnttab_pages_set_private(int nr_pages, struct page **pages) { int i; - int ret; - - ret = alloc_xenballooned_pages(nr_pages, pages); - if (ret < 0) - return ret; for (i = 0; i < nr_pages; i++) { #if BITS_PER_LONG < 64 struct xen_page_foreign *foreign; foreign = kzalloc(sizeof(*foreign), GFP_KERNEL); - if (!foreign) { - gnttab_free_pages(nr_pages, pages); + if (!foreign) return -ENOMEM; - } + set_page_private(pages[i], (unsigned long)foreign); #endif SetPagePrivate(pages[i]); @@ -799,14 +788,30 @@ int gnttab_alloc_pages(int nr_pages, struct page **pages) return 0; } -EXPORT_SYMBOL(gnttab_alloc_pages); +EXPORT_SYMBOL(gnttab_pages_set_private); /** - * gnttab_free_pages - free pages allocated by gnttab_alloc_pages() - * @nr_pages; number of pages to free - * @pages: the pages + * gnttab_alloc_pages - alloc pages suitable for grant mapping into + * @nr_pages: number of pages to alloc + * @pages: returns the pages */ -void gnttab_free_pages(int nr_pages, struct page **pages) +int gnttab_alloc_pages(int nr_pages, struct page **pages) +{ + int ret; + + ret = alloc_xenballooned_pages(nr_pages, pages); + if (ret < 0) + return ret; + + ret = gnttab_pages_set_private(nr_pages, pages); + if (ret < 0) + gnttab_free_pages(nr_pages, pages); + + return ret; +} +EXPORT_SYMBOL(gnttab_alloc_pages); + +void gnttab_pages_clear_private(int nr_pages, struct page **pages) { int i; @@ -818,6 +823,17 @@ void gnttab_free_pages(int nr_pages, struct page **pages) ClearPagePrivate(pages[i]); } } +} +EXPORT_SYMBOL(gnttab_pages_clear_private); + +/** + * gnttab_free_pages - free pages allocated by gnttab_alloc_pages() + * @nr_pages; number of pages to free + * @pages: the pages + */ +void gnttab_free_pages(int nr_pages, struct page **pages) +{ + gnttab_pages_clear_private(nr_pages, pages); free_xenballooned_pages(nr_pages, pages); } EXPORT_SYMBOL(gnttab_free_pages); diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h index 2e37741f6b8d..de03f2542bb7 100644 --- a/include/xen/grant_table.h +++ b/include/xen/grant_table.h @@ -198,6 +198,9 @@ void gnttab_free_auto_xlat_frames(void); int gnttab_alloc_pages(int nr_pages, struct page **pages); void gnttab_free_pages(int nr_pages, struct page **pages); +int gnttab_pages_set_private(int nr_pages, struct page **pages); +void gnttab_pages_clear_private(int nr_pages, struct page **pages); + int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, struct gnttab_map_grant_ref *kmap_ops, struct page **pages, unsigned int count); -- 2.17.0
[PATCH 4/8] xen/gntdev: Allow mappings for DMA buffers
From: Oleksandr Andrushchenko Allow mappings for DMA backed buffers if grant table module supports such: this extends grant device to not only map buffers made of balloon pages, but also from buffers allocated with dma_alloc_xxx. Signed-off-by: Oleksandr Andrushchenko --- drivers/xen/gntdev.c | 100 +- include/uapi/xen/gntdev.h | 15 ++ 2 files changed, 113 insertions(+), 2 deletions(-) diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index bd56653b9bbc..640a579f42ea 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -37,6 +37,9 @@ #include #include #include +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC +#include +#endif #include #include @@ -72,6 +75,11 @@ struct gntdev_priv { struct mutex lock; struct mm_struct *mm; struct mmu_notifier mn; + +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC + /* Device for which DMA memory is allocated. */ + struct device *dma_dev; +#endif }; struct unmap_notify { @@ -96,10 +104,28 @@ struct grant_map { struct gnttab_unmap_grant_ref *kunmap_ops; struct page **pages; unsigned long pages_vm_start; + +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC + /* +* If dmabuf_vaddr is not NULL then this mapping is backed by DMA +* capable memory. +*/ + + /* Device for which DMA memory is allocated. */ + struct device *dma_dev; + /* Flags used to create this DMA buffer: GNTDEV_DMABUF_FLAG_XXX. */ + bool dma_flags; + /* Virtual/CPU address of the DMA buffer. */ + void *dma_vaddr; + /* Bus address of the DMA buffer. */ + dma_addr_t dma_bus_addr; +#endif }; static int unmap_grant_pages(struct grant_map *map, int offset, int pages); +static struct miscdevice gntdev_miscdev; + /* -- */ static void gntdev_print_maps(struct gntdev_priv *priv, @@ -121,8 +147,26 @@ static void gntdev_free_map(struct grant_map *map) if (map == NULL) return; +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC + if (map->dma_vaddr) { + struct gnttab_dma_alloc_args args; + + args.dev = map->dma_dev; + args.coherent = map->dma_flags & GNTDEV_DMA_FLAG_COHERENT; + args.nr_pages = map->count; + args.pages = map->pages; + args.vaddr = map->dma_vaddr; + args.dev_bus_addr = map->dma_bus_addr; + + gnttab_dma_free_pages(&args); + } else if (map->pages) { + gnttab_free_pages(map->count, map->pages); + } +#else if (map->pages) gnttab_free_pages(map->count, map->pages); +#endif + kfree(map->pages); kfree(map->grants); kfree(map->map_ops); @@ -132,7 +176,8 @@ static void gntdev_free_map(struct grant_map *map) kfree(map); } -static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count) +static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count, + int dma_flags) { struct grant_map *add; int i; @@ -155,8 +200,37 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count) NULL == add->pages) goto err; +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC + add->dma_flags = dma_flags; + + /* +* Check if this mapping is requested to be backed +* by a DMA buffer. +*/ + if (dma_flags & (GNTDEV_DMA_FLAG_WC | GNTDEV_DMA_FLAG_COHERENT)) { + struct gnttab_dma_alloc_args args; + + /* Remember the device, so we can free DMA memory. */ + add->dma_dev = priv->dma_dev; + + args.dev = priv->dma_dev; + args.coherent = dma_flags & GNTDEV_DMA_FLAG_COHERENT; + args.nr_pages = count; + args.pages = add->pages; + + if (gnttab_dma_alloc_pages(&args)) + goto err; + + add->dma_vaddr = args.vaddr; + add->dma_bus_addr = args.dev_bus_addr; + } else { + if (gnttab_alloc_pages(count, add->pages)) + goto err; + } +#else if (gnttab_alloc_pages(count, add->pages)) goto err; +#endif for (i = 0; i < count; i++) { add->map_ops[i].handle = -1; @@ -323,8 +397,19 @@ static int map_grant_pages(struct grant_map *map) } map->unmap_ops[i].handle = map->map_ops[i].handle; +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC + if (use_ptemod) { + map->kunmap_ops[i].handle = map->kmap_ops[i].handle; + } else if (map->dma_vaddr) { + unsigned long mfn; + + mfn
[PATCH 2/8] xen/balloon: Move common memory reservation routines to a module
From: Oleksandr Andrushchenko Memory {increase|decrease}_reservation and VA mappings update/reset code used in balloon driver can be made common, so other drivers can also re-use the same functionality without open-coding. Create a dedicated module for the shared code and export corresponding symbols for other kernel modules. Signed-off-by: Oleksandr Andrushchenko --- drivers/xen/Makefile | 1 + drivers/xen/balloon.c | 71 ++ drivers/xen/mem-reservation.c | 134 ++ include/xen/mem_reservation.h | 29 4 files changed, 170 insertions(+), 65 deletions(-) create mode 100644 drivers/xen/mem-reservation.c create mode 100644 include/xen/mem_reservation.h diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile index 451e833f5931..3c87b0c3aca6 100644 --- a/drivers/xen/Makefile +++ b/drivers/xen/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o obj-$(CONFIG_X86) += fallback.o obj-y += grant-table.o features.o balloon.o manage.o preempt.o time.o +obj-y += mem-reservation.o obj-y += events/ obj-y += xenbus/ diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index 065f0b607373..57b482d67a3a 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -71,6 +71,7 @@ #include #include #include +#include static int xen_hotplug_unpopulated; @@ -157,13 +158,6 @@ static DECLARE_DELAYED_WORK(balloon_worker, balloon_process); #define GFP_BALLOON \ (GFP_HIGHUSER | __GFP_NOWARN | __GFP_NORETRY | __GFP_NOMEMALLOC) -static void scrub_page(struct page *page) -{ -#ifdef CONFIG_XEN_SCRUB_PAGES - clear_highpage(page); -#endif -} - /* balloon_append: add the given page to the balloon. */ static void __balloon_append(struct page *page) { @@ -463,11 +457,6 @@ static enum bp_state increase_reservation(unsigned long nr_pages) int rc; unsigned long i; struct page *page; - struct xen_memory_reservation reservation = { - .address_bits = 0, - .extent_order = EXTENT_ORDER, - .domid= DOMID_SELF - }; if (nr_pages > ARRAY_SIZE(frame_list)) nr_pages = ARRAY_SIZE(frame_list); @@ -486,9 +475,7 @@ static enum bp_state increase_reservation(unsigned long nr_pages) page = balloon_next_page(page); } - set_xen_guest_handle(reservation.extent_start, frame_list); - reservation.nr_extents = nr_pages; - rc = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation); + rc = xenmem_reservation_increase(nr_pages, frame_list); if (rc <= 0) return BP_EAGAIN; @@ -496,29 +483,7 @@ static enum bp_state increase_reservation(unsigned long nr_pages) page = balloon_retrieve(false); BUG_ON(page == NULL); -#ifdef CONFIG_XEN_HAVE_PVMMU - /* -* We don't support PV MMU when Linux and Xen is using -* different page granularity. -*/ - BUILD_BUG_ON(XEN_PAGE_SIZE != PAGE_SIZE); - - if (!xen_feature(XENFEAT_auto_translated_physmap)) { - unsigned long pfn = page_to_pfn(page); - - set_phys_to_machine(pfn, frame_list[i]); - - /* Link back into the page tables if not highmem. */ - if (!PageHighMem(page)) { - int ret; - ret = HYPERVISOR_update_va_mapping( - (unsigned long)__va(pfn << PAGE_SHIFT), - mfn_pte(frame_list[i], PAGE_KERNEL), - 0); - BUG_ON(ret); - } - } -#endif + xenmem_reservation_va_mapping_update(1, &page, &frame_list[i]); /* Relinquish the page back to the allocator. */ free_reserved_page(page); @@ -535,11 +500,6 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) unsigned long i; struct page *page, *tmp; int ret; - struct xen_memory_reservation reservation = { - .address_bits = 0, - .extent_order = EXTENT_ORDER, - .domid= DOMID_SELF - }; LIST_HEAD(pages); if (nr_pages > ARRAY_SIZE(frame_list)) @@ -553,7 +513,7 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) break; } adjust_managed_page_count(page, -1); - scrub_page(page); + xenmem_reservation_scrub_page(page); list_add(&page->lru, &pages); } @@ -575,25 +535,8 @@ static enum bp_state decrease_res
[PATCH 6/8] xen/gntdev: Implement dma-buf export functionality
From: Oleksandr Andrushchenko 1. Create a dma-buf from grant references provided by the foreign domain. By default dma-buf is backed by system memory pages, but by providing GNTDEV_DMA_FLAG_XXX flags it can also be created as a DMA write-combine/coherent buffer, e.g. allocated with corresponding dma_alloc_xxx API. Export the resulting buffer as a new dma-buf. 2. Implement waiting for the dma-buf to be released: block until the dma-buf with the file descriptor provided is released. If within the time-out provided the buffer is not released then -ETIMEDOUT error is returned. If the buffer with the file descriptor does not exist or has already been released, then -ENOENT is returned. For valid file descriptors this must not be treated as error. Signed-off-by: Oleksandr Andrushchenko --- drivers/xen/gntdev.c | 478 ++- 1 file changed, 476 insertions(+), 2 deletions(-) diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 9e450622af1a..52abc6cd5846 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -4,6 +4,8 @@ * Device for accessing (in user-space) pages that have been granted by other * domains. * + * DMA buffer implementation is based on drivers/gpu/drm/drm_prime.c. + * * Copyright (c) 2006-2007, D G Murray. * (c) 2009 Gerd Hoffmann * (c) 2018 Oleksandr Andrushchenko, EPAM Systems Inc. @@ -41,6 +43,9 @@ #ifdef CONFIG_XEN_GRANT_DMA_ALLOC #include #endif +#ifdef CONFIG_XEN_GNTDEV_DMABUF +#include +#endif #include #include @@ -81,6 +86,17 @@ struct gntdev_priv { /* Device for which DMA memory is allocated. */ struct device *dma_dev; #endif + +#ifdef CONFIG_XEN_GNTDEV_DMABUF + /* Private data of the hyper DMA buffers. */ + + /* List of exported DMA buffers. */ + struct list_head dmabuf_exp_list; + /* List of wait objects. */ + struct list_head dmabuf_exp_wait_list; + /* This is the lock which protects dma_buf_xxx lists. */ + struct mutex dmabuf_lock; +#endif }; struct unmap_notify { @@ -125,12 +141,38 @@ struct grant_map { #ifdef CONFIG_XEN_GNTDEV_DMABUF struct xen_dmabuf { + struct gntdev_priv *priv; + struct dma_buf *dmabuf; + struct list_head next; + int fd; + union { + struct { + /* Exported buffers are reference counted. */ + struct kref refcount; + struct grant_map *map; + } exp; struct { /* Granted references of the imported buffer. */ grant_ref_t *refs; } imp; } u; + + /* Number of pages this buffer has. */ + int nr_pages; + /* Pages of this buffer. */ + struct page **pages; +}; + +struct xen_dmabuf_wait_obj { + struct list_head next; + struct xen_dmabuf *xen_dmabuf; + struct completion completion; +}; + +struct xen_dmabuf_attachment { + struct sg_table *sgt; + enum dma_data_direction dir; }; #endif @@ -320,6 +362,16 @@ static void gntdev_put_map(struct gntdev_priv *priv, struct grant_map *map) gntdev_free_map(map); } +#ifdef CONFIG_XEN_GNTDEV_DMABUF +static void gntdev_remove_map(struct gntdev_priv *priv, struct grant_map *map) +{ + mutex_lock(&priv->lock); + list_del(&map->next); + gntdev_put_map(NULL /* already removed */, map); + mutex_unlock(&priv->lock); +} +#endif + /* -- */ static int find_grant_ptes(pte_t *pte, pgtable_t token, @@ -628,6 +680,12 @@ static int gntdev_open(struct inode *inode, struct file *flip) INIT_LIST_HEAD(&priv->freeable_maps); mutex_init(&priv->lock); +#ifdef CONFIG_XEN_GNTDEV_DMABUF + mutex_init(&priv->dmabuf_lock); + INIT_LIST_HEAD(&priv->dmabuf_exp_list); + INIT_LIST_HEAD(&priv->dmabuf_exp_wait_list); +#endif + if (use_ptemod) { priv->mm = get_task_mm(current); if (!priv->mm) { @@ -1053,17 +,433 @@ static long gntdev_ioctl_grant_copy(struct gntdev_priv *priv, void __user *u) /* DMA buffer export support. */ /* -- */ +/* -- */ +/* Implementation of wait for exported DMA buffer to be released. */ +/* -- */ + +static void dmabuf_exp_release(struct kref *kref); + +static struct xen_dmabuf_wait_obj * +dmabuf_exp_wait_obj_new(struct gntdev_priv *priv, + struct xen_dmabuf *xen_dmabuf) +{ + struct xen_dmabuf_wait_obj *obj; + + obj = kzalloc(sizeof(*obj), GFP_KERNEL); + if (!obj) +
[PATCH 8/8] xen/gntdev: Expose gntdev's dma-buf API for in-kernel use
From: Oleksandr Andrushchenko Allow creating grant device context for use by kernel modules which require functionality, provided by gntdev. Export symbols for dma-buf API provided by the module. Signed-off-by: Oleksandr Andrushchenko --- drivers/xen/gntdev.c| 116 ++-- include/xen/grant_dev.h | 37 + 2 files changed, 113 insertions(+), 40 deletions(-) create mode 100644 include/xen/grant_dev.h diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index d8b6168f2cd9..912056f3e909 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -684,14 +684,33 @@ static const struct mmu_notifier_ops gntdev_mmu_ops = { /* -- */ -static int gntdev_open(struct inode *inode, struct file *flip) +void gntdev_free_context(struct gntdev_priv *priv) +{ + struct grant_map *map; + + pr_debug("priv %p\n", priv); + + mutex_lock(&priv->lock); + while (!list_empty(&priv->maps)) { + map = list_entry(priv->maps.next, struct grant_map, next); + list_del(&map->next); + gntdev_put_map(NULL /* already removed */, map); + } + WARN_ON(!list_empty(&priv->freeable_maps)); + + mutex_unlock(&priv->lock); + + kfree(priv); +} +EXPORT_SYMBOL(gntdev_free_context); + +struct gntdev_priv *gntdev_alloc_context(struct device *dev) { struct gntdev_priv *priv; - int ret = 0; priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) - return -ENOMEM; + return ERR_PTR(-ENOMEM); INIT_LIST_HEAD(&priv->maps); INIT_LIST_HEAD(&priv->freeable_maps); @@ -704,6 +723,32 @@ static int gntdev_open(struct inode *inode, struct file *flip) INIT_LIST_HEAD(&priv->dmabuf_imp_list); #endif +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC + priv->dma_dev = dev; + + /* +* The device is not spawn from a device tree, so arch_setup_dma_ops +* is not called, thus leaving the device with dummy DMA ops. +* Fix this call of_dma_configure() with a NULL node to set +* default DMA ops. +*/ + of_dma_configure(priv->dma_dev, NULL); +#endif + pr_debug("priv %p\n", priv); + + return priv; +} +EXPORT_SYMBOL(gntdev_alloc_context); + +static int gntdev_open(struct inode *inode, struct file *flip) +{ + struct gntdev_priv *priv; + int ret = 0; + + priv = gntdev_alloc_context(gntdev_miscdev.this_device); + if (IS_ERR(priv)) + return PTR_ERR(priv); + if (use_ptemod) { priv->mm = get_task_mm(current); if (!priv->mm) { @@ -716,23 +761,11 @@ static int gntdev_open(struct inode *inode, struct file *flip) } if (ret) { - kfree(priv); + gntdev_free_context(priv); return ret; } flip->private_data = priv; -#ifdef CONFIG_XEN_GRANT_DMA_ALLOC - priv->dma_dev = gntdev_miscdev.this_device; - - /* -* The device is not spawn from a device tree, so arch_setup_dma_ops -* is not called, thus leaving the device with dummy DMA ops. -* Fix this call of_dma_configure() with a NULL node to set -* default DMA ops. -*/ - of_dma_configure(priv->dma_dev, NULL); -#endif - pr_debug("priv %p\n", priv); return 0; } @@ -740,22 +773,11 @@ static int gntdev_open(struct inode *inode, struct file *flip) static int gntdev_release(struct inode *inode, struct file *flip) { struct gntdev_priv *priv = flip->private_data; - struct grant_map *map; - - pr_debug("priv %p\n", priv); - - mutex_lock(&priv->lock); - while (!list_empty(&priv->maps)) { - map = list_entry(priv->maps.next, struct grant_map, next); - list_del(&map->next); - gntdev_put_map(NULL /* already removed */, map); - } - WARN_ON(!list_empty(&priv->freeable_maps)); - mutex_unlock(&priv->lock); if (use_ptemod) mmu_notifier_unregister(&priv->mn, priv->mm); - kfree(priv); + + gntdev_free_context(priv); return 0; } @@ -1210,7 +1232,7 @@ dmabuf_exp_wait_obj_get_by_fd(struct gntdev_priv *priv, int fd) return ret; } -static int dmabuf_exp_wait_released(struct gntdev_priv *priv, int fd, +int gntdev_dmabuf_exp_wait_released(struct gntdev_priv *priv, int fd, int wait_to_ms) { struct xen_dmabuf *xen_dmabuf; @@ -1242,6 +1264,7 @@ static int dmabuf_exp_wait_released(struct gntdev_priv *priv, int fd, dmabuf_exp_wait_obj_free(priv, obj); return ret; } +EXPORT_SYMBOL(gntdev_dmabuf_exp_wait_released
[PATCH 5/8] xen/gntdev: Add initial support for dma-buf UAPI
From: Oleksandr Andrushchenko Add UAPI and IOCTLs for dma-buf grant device driver extension: the extension allows userspace processes and kernel modules to use Xen backed dma-buf implementation. With this extension grant references to the pages of an imported dma-buf can be exported for other domain use and grant references coming from a foreign domain can be converted into a local dma-buf for local export. Implement basic initialization and stubs for Xen DMA buffers' support. Signed-off-by: Oleksandr Andrushchenko --- drivers/xen/Kconfig | 10 +++ drivers/xen/gntdev.c | 148 ++ include/uapi/xen/gntdev.h | 91 +++ 3 files changed, 249 insertions(+) diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index 3431fe210624..eaf63a2c7ae6 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig @@ -152,6 +152,16 @@ config XEN_GNTDEV help Allows userspace processes to use grants. +config XEN_GNTDEV_DMABUF + bool "Add support for dma-buf grant access device driver extension" + depends on XEN_GNTDEV && XEN_GRANT_DMA_ALLOC + help + Allows userspace processes and kernel modules to use Xen backed + dma-buf implementation. With this extension grant references to + the pages of an imported dma-buf can be exported for other domain + use and grant references coming from a foreign domain can be + converted into a local dma-buf for local export. + config XEN_GRANT_DEV_ALLOC tristate "User-space grant reference allocator driver" depends on XEN diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 640a579f42ea..9e450622af1a 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -6,6 +6,7 @@ * * Copyright (c) 2006-2007, D G Murray. * (c) 2009 Gerd Hoffmann + * (c) 2018 Oleksandr Andrushchenko, EPAM Systems Inc. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -122,6 +123,17 @@ struct grant_map { #endif }; +#ifdef CONFIG_XEN_GNTDEV_DMABUF +struct xen_dmabuf { + union { + struct { + /* Granted references of the imported buffer. */ + grant_ref_t *refs; + } imp; + } u; +}; +#endif + static int unmap_grant_pages(struct grant_map *map, int offset, int pages); static struct miscdevice gntdev_miscdev; @@ -1036,6 +1048,128 @@ static long gntdev_ioctl_grant_copy(struct gntdev_priv *priv, void __user *u) return ret; } +#ifdef CONFIG_XEN_GNTDEV_DMABUF +/* -- */ +/* DMA buffer export support. */ +/* -- */ + +static int dmabuf_exp_wait_released(struct gntdev_priv *priv, int fd, + int wait_to_ms) +{ + return -ETIMEDOUT; +} + +static int dmabuf_exp_from_refs(struct gntdev_priv *priv, int flags, + int count, u32 domid, u32 *refs, u32 *fd) +{ + *fd = -1; + return -EINVAL; +} + +/* -- */ +/* DMA buffer import support. */ +/* -- */ + +static int dmabuf_imp_release(struct gntdev_priv *priv, u32 fd) +{ + return 0; +} + +static struct xen_dmabuf * +dmabuf_imp_to_refs(struct gntdev_priv *priv, int fd, int count, int domid) +{ + return ERR_PTR(-ENOMEM); +} + +/* -- */ +/* DMA buffer IOCTL support. */ +/* -- */ + +static long +gntdev_ioctl_dmabuf_exp_from_refs(struct gntdev_priv *priv, + struct ioctl_gntdev_dmabuf_exp_from_refs __user *u) +{ + struct ioctl_gntdev_dmabuf_exp_from_refs op; + u32 *refs; + long ret; + + if (copy_from_user(&op, u, sizeof(op)) != 0) + return -EFAULT; + + refs = kcalloc(op.count, sizeof(*refs), GFP_KERNEL); + if (!refs) + return -ENOMEM; + + if (copy_from_user(refs, u->refs, sizeof(*refs) * op.count) != 0) { + ret = -EFAULT; + goto out; + } + + ret = dmabuf_exp_from_refs(priv, op.flags, op.count, + op.domid, refs, &op.fd); + if (ret) + goto out; + + if (copy_to_user(u, &op, sizeof(op)) != 0) + ret = -EFAULT; + +out: + kfree(refs); + return ret; +} + +static long +gntdev_ioctl_dmabuf_exp_wait_released(struct gntdev_priv *pr
[PATCH 7/8] xen/gntdev: Implement dma-buf import functionality
From: Oleksandr Andrushchenko 1. Import a dma-buf with the file descriptor provided and export granted references to the pages of that dma-buf into the array of grant references. 2. Add API to close all references to an imported buffer, so it can be released by the owner. This is only valid for buffers created with IOCTL_GNTDEV_DMABUF_IMP_TO_REFS. Signed-off-by: Oleksandr Andrushchenko --- drivers/xen/gntdev.c | 237 ++- 1 file changed, 234 insertions(+), 3 deletions(-) diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 52abc6cd5846..d8b6168f2cd9 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -71,6 +71,17 @@ static atomic_t pages_mapped = ATOMIC_INIT(0); static int use_ptemod; #define populate_freeable_maps use_ptemod +#ifdef CONFIG_XEN_GNTDEV_DMABUF +#ifndef GRANT_INVALID_REF +/* + * Note on usage of grant reference 0 as invalid grant reference: + * grant reference 0 is valid, but never exposed to a driver, + * because of the fact it is already in use/reserved by the PV console. + */ +#define GRANT_INVALID_REF 0 +#endif +#endif + struct gntdev_priv { /* maps with visible offsets in the file descriptor */ struct list_head maps; @@ -94,6 +105,8 @@ struct gntdev_priv { struct list_head dmabuf_exp_list; /* List of wait objects. */ struct list_head dmabuf_exp_wait_list; + /* List of imported DMA buffers. */ + struct list_head dmabuf_imp_list; /* This is the lock which protects dma_buf_xxx lists. */ struct mutex dmabuf_lock; #endif @@ -155,6 +168,10 @@ struct xen_dmabuf { struct { /* Granted references of the imported buffer. */ grant_ref_t *refs; + /* Scatter-gather table of the imported buffer. */ + struct sg_table *sgt; + /* dma-buf attachment of the imported buffer. */ + struct dma_buf_attachment *attach; } imp; } u; @@ -684,6 +701,7 @@ static int gntdev_open(struct inode *inode, struct file *flip) mutex_init(&priv->dmabuf_lock); INIT_LIST_HEAD(&priv->dmabuf_exp_list); INIT_LIST_HEAD(&priv->dmabuf_exp_wait_list); + INIT_LIST_HEAD(&priv->dmabuf_imp_list); #endif if (use_ptemod) { @@ -1544,15 +1562,228 @@ static int dmabuf_exp_from_refs(struct gntdev_priv *priv, int flags, /* DMA buffer import support. */ /* -- */ -static int dmabuf_imp_release(struct gntdev_priv *priv, u32 fd) +static int +dmabuf_imp_grant_foreign_access(struct page **pages, u32 *refs, + int count, int domid) { - return 0; + grant_ref_t priv_gref_head; + int i, ret; + + ret = gnttab_alloc_grant_references(count, &priv_gref_head); + if (ret < 0) { + pr_err("Cannot allocate grant references, ret %d\n", ret); + return ret; + } + + for (i = 0; i < count; i++) { + int cur_ref; + + cur_ref = gnttab_claim_grant_reference(&priv_gref_head); + if (cur_ref < 0) { + ret = cur_ref; + pr_err("Cannot claim grant reference, ret %d\n", ret); + goto out; + } + + gnttab_grant_foreign_access_ref(cur_ref, domid, + xen_page_to_gfn(pages[i]), 0); + refs[i] = cur_ref; + } + + ret = 0; + +out: + gnttab_free_grant_references(priv_gref_head); + return ret; +} + +static void dmabuf_imp_end_foreign_access(u32 *refs, int count) +{ + int i; + + for (i = 0; i < count; i++) + if (refs[i] != GRANT_INVALID_REF) + gnttab_end_foreign_access(refs[i], 0, 0UL); +} + +static void dmabuf_imp_free_storage(struct xen_dmabuf *xen_dmabuf) +{ + kfree(xen_dmabuf->pages); + kfree(xen_dmabuf->u.imp.refs); + kfree(xen_dmabuf); +} + +static struct xen_dmabuf *dmabuf_imp_alloc_storage(int count) +{ + struct xen_dmabuf *xen_dmabuf; + int i; + + xen_dmabuf = kzalloc(sizeof(*xen_dmabuf), GFP_KERNEL); + if (!xen_dmabuf) + goto fail; + + xen_dmabuf->u.imp.refs = kcalloc(count, +sizeof(xen_dmabuf->u.imp.refs[0]), +GFP_KERNEL); + if (!xen_dmabuf->u.imp.refs) + goto fail; + + xen_dmabuf->pages = kcalloc(count, + sizeof(xen_dmabuf->pages[0]), + GFP_KERNEL); + if (!xen_dmabuf->pages) + goto fail; + + xe
[PATCH 0/8] xen: dma-buf support for grant device
From: Oleksandr Andrushchenko This work is in response to my previous attempt to introduce Xen/DRM zero-copy driver [1] to enable Linux dma-buf API [2] for Xen based frontends/backends. There is also an existing hyper_dmabuf approach available [3] which, if reworked to utilize the proposed solution, can greatly benefit as well. RFC for this series was published and discussed [9], comments addressed. The original rationale behind this work was to enable zero-copying use-cases while working with Xen para-virtual display driver [4]: when using Xen PV DRM frontend driver then on backend side one will need to do copying of display buffers' contents (filled by the frontend's user-space) into buffers allocated at the backend side. Taking into account the size of display buffers and frames per second it may result in unneeded huge data bus occupation and performance loss. The helper driver [4] allows implementing zero-copying use-cases when using Xen para-virtualized frontend display driver by implementing a DRM/KMS helper driver running on backend's side. It utilizes PRIME buffers API (implemented on top of Linux dma-buf) to share frontend's buffers with physical device drivers on backend's side: - a dumb buffer created on backend's side can be shared with the Xen PV frontend driver, so it directly writes into backend's domain memory (into the buffer exported from DRM/KMS driver of a physical display device) - a dumb buffer allocated by the frontend can be imported into physical device DRM/KMS driver, thus allowing to achieve no copying as well Finally, it was discussed and decided ([1], [5]) that it is worth implementing such use-cases via extension of the existing Xen gntdev driver instead of introducing new DRM specific driver. Please note, that the support of dma-buf is Linux only, as dma-buf is a Linux only thing. Now to the proposed solution. The changes to the existing Xen drivers in the Linux kernel fall into 2 categories: 1. DMA-able memory buffer allocation and increasing/decreasing memory reservation of the pages of such a buffer. This is required if we are about to share dma-buf with the hardware that does require those to be allocated with dma_alloc_xxx API. (It is still possible to allocate a dma-buf from any system memory, e.g. system pages). 2. Extension of the gntdev driver to enable it to import/export dma-buf’s. The first four patches are in preparation for Xen dma-buf support, but I consider those usable regardless of the dma-buf use-case, e.g. other frontend/backend kernel modules may also benefit from these for better code reuse: 0001-xen-grant-table-Make-set-clear-page-private-code-sha.patch 0002-xen-balloon-Move-common-memory-reservation-routines-.patch 0003-xen-grant-table-Allow-allocating-buffers-suitable-fo.patch 0004-xen-gntdev-Allow-mappings-for-DMA-buffers.patch The next three patches are Xen implementation of dma-buf as part of the grant device: 0005-xen-gntdev-Add-initial-support-for-dma-buf-UAPI.patch 0006-xen-gntdev-Implement-dma-buf-export-functionality.patch 0007-xen-gntdev-Implement-dma-buf-import-functionality.patch The last patch makes it possible for in-kernel use of Xen dma-buf API: 0008-xen-gntdev-Expose-gntdev-s-dma-buf-API-for-in-kernel.patch The corresponding libxengnttab changes are available at [6]. All the above was tested with display backend [7] and its accompanying helper library [8] on Renesas ARM64 based board. *To all the communities*: I would like to ask you to review the proposed solution and give feedback on it, so I can improve and send final patches for review (this is still work in progress, but enough to start discussing the implementation). Thank you in advance, Oleksandr Andrushchenko [1] https://lists.freedesktop.org/archives/dri-devel/2018-April/173163.html [2] https://elixir.bootlin.com/linux/v4.17-rc5/source/Documentation/driver-api/dma-buf.rst [3] https://lists.xenproject.org/archives/html/xen-devel/2018-02/msg01202.html [4] https://cgit.freedesktop.org/drm/drm-misc/tree/drivers/gpu/drm/xen [5] https://patchwork.kernel.org/patch/10279681/ [6] https://github.com/andr2000/xen/tree/xen_dma_buf_v1 [7] https://github.com/andr2000/displ_be/tree/xen_dma_buf_v1 [8] https://github.com/andr2000/libxenbe/tree/xen_dma_buf_v1 [9] https://lkml.org/lkml/2018/5/17/215 Oleksandr Andrushchenko (8): xen/grant-table: Make set/clear page private code shared xen/balloon: Move common memory reservation routines to a module xen/grant-table: Allow allocating buffers suitable for DMA xen/gntdev: Allow mappings for DMA buffers xen/gntdev: Add initial support for dma-buf UAPI xen/gntdev: Implement dma-buf export functionality xen/gntdev: Implement dma-buf import functionality xen/gntdev: Expose gntdev's dma-buf API for in-kernel use drivers/xen/Kconfig | 23 + drivers/xen/Makefile |1 + drivers/xen/balloon.c
Re: [PATCH v2] drm/xen-front: fix pointer casts
On 05/23/2018 02:46 PM, Juergen Gross wrote: On 23/05/18 13:36, Oleksandr Andrushchenko wrote: From: Oleksandr Andrushchenko Building for a 32-bit target results in warnings from casting between a 32-bit pointer and a 64-bit integer. Fix the warnings by casting those pointers to uintptr_t first. Signed-off-by: Oleksandr Andrushchenko Reviewed-by: Juergen Gross Thank you, applied to drm-misc-next Juergen
[PATCH v2] drm/xen-front: fix pointer casts
From: Oleksandr Andrushchenko Building for a 32-bit target results in warnings from casting between a 32-bit pointer and a 64-bit integer. Fix the warnings by casting those pointers to uintptr_t first. Signed-off-by: Oleksandr Andrushchenko --- Changes since v1: - remove unneeded u64 and phys_addr_t casts (Juergen) drivers/gpu/drm/xen/xen_drm_front.h | 4 ++-- drivers/gpu/drm/xen/xen_drm_front_shbuf.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/xen/xen_drm_front.h b/drivers/gpu/drm/xen/xen_drm_front.h index 2c2479b571ae..5693b4a4b02b 100644 --- a/drivers/gpu/drm/xen/xen_drm_front.h +++ b/drivers/gpu/drm/xen/xen_drm_front.h @@ -126,12 +126,12 @@ struct xen_drm_front_drm_info { static inline u64 xen_drm_front_fb_to_cookie(struct drm_framebuffer *fb) { - return (u64)fb; + return (uintptr_t)fb; } static inline u64 xen_drm_front_dbuf_to_cookie(struct drm_gem_object *gem_obj) { - return (u64)gem_obj; + return (uintptr_t)gem_obj; } int xen_drm_front_mode_set(struct xen_drm_front_drm_pipeline *pipeline, diff --git a/drivers/gpu/drm/xen/xen_drm_front_shbuf.c b/drivers/gpu/drm/xen/xen_drm_front_shbuf.c index 8099cb343ae3..d333b67cc1a0 100644 --- a/drivers/gpu/drm/xen/xen_drm_front_shbuf.c +++ b/drivers/gpu/drm/xen/xen_drm_front_shbuf.c @@ -122,7 +122,7 @@ static void guest_calc_num_grefs(struct xen_drm_front_shbuf *buf) } #define xen_page_to_vaddr(page) \ - ((phys_addr_t)pfn_to_kaddr(page_to_xen_pfn(page))) + ((uintptr_t)pfn_to_kaddr(page_to_xen_pfn(page))) static int backend_unmap(struct xen_drm_front_shbuf *buf) { -- 2.17.0
Re: [PATCH] drm/xen-front: fix pointer casts
On 05/23/2018 02:06 PM, Juergen Gross wrote: On 23/05/18 12:00, Oleksandr Andrushchenko wrote: On 05/23/2018 12:19 PM, Juergen Gross wrote: On 21/05/18 09:39, Oleksandr Andrushchenko wrote: From: Oleksandr Andrushchenko Building for a 32-bit target results in warnings from casting between a 32-bit pointer and a 64-bit integer. Fix the warnings by casting those pointers to uintptr_t first. Signed-off-by: Oleksandr Andrushchenko --- drivers/gpu/drm/xen/xen_drm_front.h | 4 ++-- drivers/gpu/drm/xen/xen_drm_front_shbuf.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/xen/xen_drm_front.h b/drivers/gpu/drm/xen/xen_drm_front.h index 2c2479b571ae..8e15dbebc4ba 100644 --- a/drivers/gpu/drm/xen/xen_drm_front.h +++ b/drivers/gpu/drm/xen/xen_drm_front.h @@ -126,12 +126,12 @@ struct xen_drm_front_drm_info { static inline u64 xen_drm_front_fb_to_cookie(struct drm_framebuffer *fb) { - return (u64)fb; + return (u64)(uintptr_t)fb; Do you really still need the cast to u64? Indeed, I can remove (u64) now, thank you } static inline u64 xen_drm_front_dbuf_to_cookie(struct drm_gem_object *gem_obj) { - return (u64)gem_obj; + return (u64)(uintptr_t)gem_obj; } int xen_drm_front_mode_set(struct xen_drm_front_drm_pipeline *pipeline, diff --git a/drivers/gpu/drm/xen/xen_drm_front_shbuf.c b/drivers/gpu/drm/xen/xen_drm_front_shbuf.c index 8099cb343ae3..47fc93847765 100644 --- a/drivers/gpu/drm/xen/xen_drm_front_shbuf.c +++ b/drivers/gpu/drm/xen/xen_drm_front_shbuf.c @@ -122,7 +122,7 @@ static void guest_calc_num_grefs(struct xen_drm_front_shbuf *buf) } #define xen_page_to_vaddr(page) \ - ((phys_addr_t)pfn_to_kaddr(page_to_xen_pfn(page))) + ((phys_addr_t)(uintptr_t)pfn_to_kaddr(page_to_xen_pfn(page))) phys_addr_t for a virtual address? This is because the resulting value is then passed to gnttab_set_map_op/ gnttab_set_unmap_op which expects host address to be passed as phys_addr_t addr :( Okay, but this means the compiler should do the necessary cast when you drop the cast to phys_addr_t in xen_page_to_vaddr(), as the cast to uintptr_t is already producing an unsigned integer value which can easily be promoted to more bits, right? Right, so I can safely use: #define xen_page_to_vaddr(page) \ - ((phys_addr_t)(uintptr_t)pfn_to_kaddr(page_to_xen_pfn(page))) + ((uintptr_t)pfn_to_kaddr(page_to_xen_pfn(page))) Juergen Thank you for your time and comments, Oleksandr
Re: [PATCH] drm/xen-front: fix pointer casts
On 05/23/2018 12:19 PM, Juergen Gross wrote: On 21/05/18 09:39, Oleksandr Andrushchenko wrote: From: Oleksandr Andrushchenko Building for a 32-bit target results in warnings from casting between a 32-bit pointer and a 64-bit integer. Fix the warnings by casting those pointers to uintptr_t first. Signed-off-by: Oleksandr Andrushchenko --- drivers/gpu/drm/xen/xen_drm_front.h | 4 ++-- drivers/gpu/drm/xen/xen_drm_front_shbuf.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/xen/xen_drm_front.h b/drivers/gpu/drm/xen/xen_drm_front.h index 2c2479b571ae..8e15dbebc4ba 100644 --- a/drivers/gpu/drm/xen/xen_drm_front.h +++ b/drivers/gpu/drm/xen/xen_drm_front.h @@ -126,12 +126,12 @@ struct xen_drm_front_drm_info { static inline u64 xen_drm_front_fb_to_cookie(struct drm_framebuffer *fb) { - return (u64)fb; + return (u64)(uintptr_t)fb; Do you really still need the cast to u64? Indeed, I can remove (u64) now, thank you } static inline u64 xen_drm_front_dbuf_to_cookie(struct drm_gem_object *gem_obj) { - return (u64)gem_obj; + return (u64)(uintptr_t)gem_obj; } int xen_drm_front_mode_set(struct xen_drm_front_drm_pipeline *pipeline, diff --git a/drivers/gpu/drm/xen/xen_drm_front_shbuf.c b/drivers/gpu/drm/xen/xen_drm_front_shbuf.c index 8099cb343ae3..47fc93847765 100644 --- a/drivers/gpu/drm/xen/xen_drm_front_shbuf.c +++ b/drivers/gpu/drm/xen/xen_drm_front_shbuf.c @@ -122,7 +122,7 @@ static void guest_calc_num_grefs(struct xen_drm_front_shbuf *buf) } #define xen_page_to_vaddr(page) \ - ((phys_addr_t)pfn_to_kaddr(page_to_xen_pfn(page))) + ((phys_addr_t)(uintptr_t)pfn_to_kaddr(page_to_xen_pfn(page))) phys_addr_t for a virtual address? This is because the resulting value is then passed to gnttab_set_map_op/ gnttab_set_unmap_op which expects host address to be passed as phys_addr_t addr :( Please see [1], [2]: regardless of the fact that xen_page_to_vaddr does produce host address I have to convert it to phys_addr_t then to pass to [1] and [2]. Please also see [3], [4], [5] which either cast to phys_addr_t or unsigned long or u64. Juergen [1] https://elixir.bootlin.com/linux/v4.17-rc6/source/include/xen/grant_table.h#L147 [2] https://elixir.bootlin.com/linux/v4.17-rc6/source/include/xen/grant_table.h#L163 [3] https://elixir.bootlin.com/linux/v4.17-rc6/source/drivers/block/xen-blkback/blkback.c#L845 [4] https://elixir.bootlin.com/linux/v4.17-rc6/source/drivers/net/xen-netback/netback.c#L334 [5] https://elixir.bootlin.com/linux/v4.17-rc6/source/drivers/xen/xenbus/xenbus_client.c#L478
Re: [PATCH v3 5/6] ALSA: xen-front: Implement ALSA virtual sound driver
On 05/23/2018 07:00 AM, Takashi Sakamoto wrote: Hi, On May 14 2018 15:27, Oleksandr Andrushchenko wrote: > diff --git a/sound/xen/xen_snd_front_alsa.c b/sound/xen/xen_snd_front_alsa.c > new file mode 100644 > index ..5041f83e98d2 > --- /dev/null > +++ b/sound/xen/xen_snd_front_alsa.c > ... > +/* > + * FIXME: The mmaped data transfer is asynchronous and there is no > + * ack signal from user-space when it is done. This is the > + * reason it is not implemented in the PV driver as we do need > + * to know when the buffer can be transferred to the backend. > + */ > ... In ALSA PCM interface v2.0.14 or later, SNDRV_PCM_INFO_SYNC_APPLPTR is available. This flag express that userspace applications are expected to call ioctl(2) with 'SNDRV_PCM_IOCTL_SYNC_PTR' even if they oprate to memory mapped page frames for PCM samples. For detail, please refer to a commit 42f945970af9 ('ALSA: pcm: Add the explicit appl_ptr sync support')[1]. As a supplement, please refer to below commits: * 4b671f577474 ('ALSA: pcm: Add an ioctl to specify the supported protocol version')[2] * b602aa8eb1a0 ('ALSA: pcm: Disable only control mmap for explicit appl_ptr sync')[3] Alsa-lib v1.1.5 or later supports this flag and existent applications can run transparently. For developers, a tracepoint may be useful: * fccf53881e9b ('ALSA: pcm: add 'applptr' event of tracepoint')[4] For your information. [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=42f945970af9 [2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4b671f577474 [3] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b602aa8eb1a0 [4] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=fccf53881e9b Oh, this is very useful, thank you so much for such a detailed description. I'll take a close look at the above and see if Xen sound driver can benefit from this. Regards Takashi Sakamoto Thank you very much, Oleksandr
Re: [Xen-devel] [RFC 1/3] xen/balloon: Allow allocating DMA buffers
On 05/22/2018 09:02 PM, Boris Ostrovsky wrote: On 05/22/2018 11:00 AM, Oleksandr Andrushchenko wrote: On 05/22/2018 05:33 PM, Boris Ostrovsky wrote: On 05/22/2018 01:55 AM, Oleksandr Andrushchenko wrote: On 05/21/2018 11:36 PM, Boris Ostrovsky wrote: On 05/21/2018 03:13 PM, Oleksandr Andrushchenko wrote: On 05/21/2018 09:53 PM, Boris Ostrovsky wrote: On 05/21/2018 01:32 PM, Oleksandr Andrushchenko wrote: On 05/21/2018 07:35 PM, Boris Ostrovsky wrote: On 05/21/2018 01:40 AM, Oleksandr Andrushchenko wrote: On 05/19/2018 01:04 AM, Boris Ostrovsky wrote: On 05/17/2018 04:26 AM, Oleksandr Andrushchenko wrote: From: Oleksandr Andrushchenko A commit message would be useful. Sure, v1 will have it Signed-off-by: Oleksandr Andrushchenko for (i = 0; i < nr_pages; i++) { - page = alloc_page(gfp); - if (page == NULL) { - nr_pages = i; - state = BP_EAGAIN; - break; + if (ext_pages) { + page = ext_pages[i]; + } else { + page = alloc_page(gfp); + if (page == NULL) { + nr_pages = i; + state = BP_EAGAIN; + break; + } } scrub_page(page); list_add(&page->lru, &pages); @@ -529,7 +565,7 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) i = 0; list_for_each_entry_safe(page, tmp, &pages, lru) { /* XENMEM_decrease_reservation requires a GFN */ - frame_list[i++] = xen_page_to_gfn(page); + frames[i++] = xen_page_to_gfn(page); #ifdef CONFIG_XEN_HAVE_PVMMU /* @@ -552,18 +588,22 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) #endif list_del(&page->lru); - balloon_append(page); + if (!ext_pages) + balloon_append(page); So what you are proposing is not really ballooning. You are just piggybacking on existing interfaces, aren't you? Sort of. Basically I need to {increase|decrease}_reservation, not actually allocating ballooned pages. Do you think I can simply EXPORT_SYMBOL for {increase|decrease}_reservation? Any other suggestion? I am actually wondering how much of that code you end up reusing. You pretty much create new code paths in both routines and common code ends up being essentially the hypercall. Well, I hoped that it would be easier to maintain if I modify existing code to support both use-cases, but I am also ok to create new routines if this seems to be reasonable - please let me know So the question is --- would it make sense to do all of this separately from the balloon driver? This can be done, but which driver will host this code then? If we move from the balloon driver, then this could go to either gntdev or grant-table. What's your preference? A separate module? Is there any use for this feature outside of your zero-copy DRM driver? Intel's hyper dma-buf (Dongwon/Matt CC'ed), V4L/GPU at least. At the time I tried to upstream zcopy driver it was discussed and decided that it would be better if I remove all DRM specific code and move it to Xen drivers. Thus, this RFC. But it can also be implemented as a dedicated Xen dma-buf driver which will have all the code from this RFC + a bit more (char/misc device handling at least). This will also require a dedicated user-space library, just like libxengnttab.so for gntdev (now I have all new IOCTLs covered there). If the idea of a dedicated Xen dma-buf driver seems to be more attractive we can work toward this solution. BTW, I do support this idea, but was not sure if Xen community accepts yet another driver which duplicates quite some code of the existing gntdev/balloon/grant-table. And now after this RFC I hope that all cons and pros of both dedicated driver and gntdev/balloon/grant-table extension are clearly seen and we can make a decision. IIRC the objection for a separate module was in the context of gntdev was discussion, because (among other things) people didn't want to have yet another file in /dev/xen/ Here we are talking about (a new) balloon-like module which doesn't create any new user-visible interfaces. And as for duplicating code --- as I said, I am not convinced there is much of duplication. I might even argue that we should add a new config option for this module. I am not quite sure I am fully following you here: so, you suggest that we have balloon.c unchanged, but instead create a new module (namely a file under the same folder as balloon.c, e.g. dma-buf-reservation.c) and move those {increase|decrease}_reservation routines (specific to dma-buf) to that new file? And make it selectable via Kconfig? If so, then how about the changes to grant-table and gntdev? Those will look inconsistent then. Inconsistent with what? The changes to grant code will also be under the new
Re: [Xen-devel] [RFC 1/3] xen/balloon: Allow allocating DMA buffers
On 05/22/2018 05:33 PM, Boris Ostrovsky wrote: On 05/22/2018 01:55 AM, Oleksandr Andrushchenko wrote: On 05/21/2018 11:36 PM, Boris Ostrovsky wrote: On 05/21/2018 03:13 PM, Oleksandr Andrushchenko wrote: On 05/21/2018 09:53 PM, Boris Ostrovsky wrote: On 05/21/2018 01:32 PM, Oleksandr Andrushchenko wrote: On 05/21/2018 07:35 PM, Boris Ostrovsky wrote: On 05/21/2018 01:40 AM, Oleksandr Andrushchenko wrote: On 05/19/2018 01:04 AM, Boris Ostrovsky wrote: On 05/17/2018 04:26 AM, Oleksandr Andrushchenko wrote: From: Oleksandr Andrushchenko A commit message would be useful. Sure, v1 will have it Signed-off-by: Oleksandr Andrushchenko for (i = 0; i < nr_pages; i++) { - page = alloc_page(gfp); - if (page == NULL) { - nr_pages = i; - state = BP_EAGAIN; - break; + if (ext_pages) { + page = ext_pages[i]; + } else { + page = alloc_page(gfp); + if (page == NULL) { + nr_pages = i; + state = BP_EAGAIN; + break; + } } scrub_page(page); list_add(&page->lru, &pages); @@ -529,7 +565,7 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) i = 0; list_for_each_entry_safe(page, tmp, &pages, lru) { /* XENMEM_decrease_reservation requires a GFN */ - frame_list[i++] = xen_page_to_gfn(page); + frames[i++] = xen_page_to_gfn(page); #ifdef CONFIG_XEN_HAVE_PVMMU /* @@ -552,18 +588,22 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) #endif list_del(&page->lru); - balloon_append(page); + if (!ext_pages) + balloon_append(page); So what you are proposing is not really ballooning. You are just piggybacking on existing interfaces, aren't you? Sort of. Basically I need to {increase|decrease}_reservation, not actually allocating ballooned pages. Do you think I can simply EXPORT_SYMBOL for {increase|decrease}_reservation? Any other suggestion? I am actually wondering how much of that code you end up reusing. You pretty much create new code paths in both routines and common code ends up being essentially the hypercall. Well, I hoped that it would be easier to maintain if I modify existing code to support both use-cases, but I am also ok to create new routines if this seems to be reasonable - please let me know So the question is --- would it make sense to do all of this separately from the balloon driver? This can be done, but which driver will host this code then? If we move from the balloon driver, then this could go to either gntdev or grant-table. What's your preference? A separate module? Is there any use for this feature outside of your zero-copy DRM driver? Intel's hyper dma-buf (Dongwon/Matt CC'ed), V4L/GPU at least. At the time I tried to upstream zcopy driver it was discussed and decided that it would be better if I remove all DRM specific code and move it to Xen drivers. Thus, this RFC. But it can also be implemented as a dedicated Xen dma-buf driver which will have all the code from this RFC + a bit more (char/misc device handling at least). This will also require a dedicated user-space library, just like libxengnttab.so for gntdev (now I have all new IOCTLs covered there). If the idea of a dedicated Xen dma-buf driver seems to be more attractive we can work toward this solution. BTW, I do support this idea, but was not sure if Xen community accepts yet another driver which duplicates quite some code of the existing gntdev/balloon/grant-table. And now after this RFC I hope that all cons and pros of both dedicated driver and gntdev/balloon/grant-table extension are clearly seen and we can make a decision. IIRC the objection for a separate module was in the context of gntdev was discussion, because (among other things) people didn't want to have yet another file in /dev/xen/ Here we are talking about (a new) balloon-like module which doesn't create any new user-visible interfaces. And as for duplicating code --- as I said, I am not convinced there is much of duplication. I might even argue that we should add a new config option for this module. I am not quite sure I am fully following you here: so, you suggest that we have balloon.c unchanged, but instead create a new module (namely a file under the same folder as balloon.c, e.g. dma-buf-reservation.c) and move those {increase|decrease}_reservation routines (specific to dma-buf) to that new file? And make it selectable via Kconfig? If so, then how about the changes to grant-table and gntdev? Those will look inconsistent then. Inconsistent with what? The changes to grant code will also be under the new config option. Ah, ok. Option 1. We will have Kconfig option which will cover dma-buf changes in balloon, grant-
[PATCH] drm: Fix possible race conditions while unplugging DRM device
From: Oleksandr Andrushchenko When unplugging a hotpluggable DRM device we first unregister it with drm_dev_unregister and then set drm_device.unplugged flag which is used to mark device critical sections with drm_dev_enter()/ drm_dev_exit() preventing access to device resources that are not available after the device is gone. But drm_dev_unregister may lead to hotplug uevent(s) fired to user-space on card and/or connector removal, thus making it possible for user-space to try accessing a disconnected device. Fix this by first making sure device is properly marked as disconnected and only then unregister it. Fixes: bee330f3d672 ("drm: Use srcu to protect drm_device.unplugged") Signed-off-by: Oleksandr Andrushchenko Reported-by: Andrii Chepurnyi Cc: "Noralf Trønnes" --- drivers/gpu/drm/drm_drv.c | 14 +++--- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index b553a6f2ff0e..7af748ed1c58 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -369,13 +369,6 @@ EXPORT_SYMBOL(drm_dev_exit); */ void drm_dev_unplug(struct drm_device *dev) { - drm_dev_unregister(dev); - - mutex_lock(&drm_global_mutex); - if (dev->open_count == 0) - drm_dev_put(dev); - mutex_unlock(&drm_global_mutex); - /* * After synchronizing any critical read section is guaranteed to see * the new value of ->unplugged, and any critical section which might @@ -384,6 +377,13 @@ void drm_dev_unplug(struct drm_device *dev) */ dev->unplugged = true; synchronize_srcu(&drm_unplug_srcu); + + drm_dev_unregister(dev); + + mutex_lock(&drm_global_mutex); + if (dev->open_count == 0) + drm_dev_put(dev); + mutex_unlock(&drm_global_mutex); } EXPORT_SYMBOL(drm_dev_unplug); -- 2.17.0
Re: [Xen-devel][RFC 3/3] xen/gntdev: Add support for Linux dma buffers
On 05/22/2018 12:31 AM, Dongwon Kim wrote: Still need more time to review the whole code changes Take your time, I just wanted to make sure that all interested parties are in the discussion, so we all finally have what we all want, not a thing covering only my use-cases but I noticed one thing. We've been using the term "hyper_dmabuf" for hypervisor-agnostic linux dmabuf solution and we are planning to call any of our future solution for other hypervisors the same name. So having same name for this xen-specific structure or functions you implemented is confusing. Would you change it to something else like... "xen_"? Np, will rename On Thu, May 17, 2018 at 11:26:04AM +0300, Oleksandr Andrushchenko wrote: From: Oleksandr Andrushchenko Signed-off-by: Oleksandr Andrushchenko --- drivers/xen/gntdev.c | 954 +- include/uapi/xen/gntdev.h | 101 include/xen/gntdev_exp.h | 23 + 3 files changed, 1066 insertions(+), 12 deletions(-) create mode 100644 include/xen/gntdev_exp.h diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 9510f228efe9..0ee88e193362 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -4,6 +4,8 @@ * Device for accessing (in user-space) pages that have been granted by other * domains. * + * DMA buffer implementation is based on drivers/gpu/drm/drm_prime.c. + * * Copyright (c) 2006-2007, D G Murray. * (c) 2009 Gerd Hoffmann * @@ -37,6 +39,9 @@ #include #include +#include +#include + #include #include #include @@ -61,16 +66,39 @@ static atomic_t pages_mapped = ATOMIC_INIT(0); static int use_ptemod; #define populate_freeable_maps use_ptemod +#ifndef GRANT_INVALID_REF +/* + * Note on usage of grant reference 0 as invalid grant reference: + * grant reference 0 is valid, but never exposed to a driver, + * because of the fact it is already in use/reserved by the PV console. + */ +#define GRANT_INVALID_REF 0 +#endif + struct gntdev_priv { /* maps with visible offsets in the file descriptor */ struct list_head maps; /* maps that are not visible; will be freed on munmap. * Only populated if populate_freeable_maps == 1 */ struct list_head freeable_maps; + /* List of dma-bufs. */ + struct list_head dma_bufs; /* lock protects maps and freeable_maps */ struct mutex lock; struct mm_struct *mm; struct mmu_notifier mn; + + /* Private data of the hyper DMA buffers. */ + + struct device *dev; + /* List of exported DMA buffers. */ + struct list_head dmabuf_exp_list; + /* List of wait objects. */ + struct list_head dmabuf_exp_wait_list; + /* List of imported DMA buffers. */ + struct list_head dmabuf_imp_list; + /* This is the lock which protects dma_buf_xxx lists. */ + struct mutex dmabuf_lock; }; struct unmap_notify { @@ -95,10 +123,65 @@ struct grant_map { struct gnttab_unmap_grant_ref *kunmap_ops; struct page **pages; unsigned long pages_vm_start; + + /* +* All the fields starting with dmabuf_ are only valid if this +* mapping is used for exporting a DMA buffer. +* If dmabuf_vaddr is not NULL then this mapping is backed by DMA +* capable memory. +*/ + + /* Flags used to create this DMA buffer: GNTDEV_DMABUF_FLAG_XXX. */ + bool dmabuf_flags; + /* Virtual/CPU address of the DMA buffer. */ + void *dmabuf_vaddr; + /* Bus address of the DMA buffer. */ + dma_addr_t dmabuf_bus_addr; +}; + +struct hyper_dmabuf { + struct gntdev_priv *priv; + struct dma_buf *dmabuf; + struct list_head next; + int fd; + + union { + struct { + /* Exported buffers are reference counted. */ + struct kref refcount; + struct grant_map *map; + } exp; + struct { + /* Granted references of the imported buffer. */ + grant_ref_t *refs; + /* Scatter-gather table of the imported buffer. */ + struct sg_table *sgt; + /* dma-buf attachment of the imported buffer. */ + struct dma_buf_attachment *attach; + } imp; + } u; + + /* Number of pages this buffer has. */ + int nr_pages; + /* Pages of this buffer. */ + struct page **pages; +}; + +struct hyper_dmabuf_wait_obj { + struct list_head next; + struct hyper_dmabuf *hyper_dmabuf; + struct completion completion; +}; + +struct hyper_dambuf_attachment { minor typo: dam->dma (same thing in other places as well.) sure, thanks + struct sg_table *sgt; + enum dma_data_direction dir; }; static int unmap_grant_pages(struct gra
Re: [Xen-devel] [RFC 1/3] xen/balloon: Allow allocating DMA buffers
On 05/21/2018 11:36 PM, Boris Ostrovsky wrote: On 05/21/2018 03:13 PM, Oleksandr Andrushchenko wrote: On 05/21/2018 09:53 PM, Boris Ostrovsky wrote: On 05/21/2018 01:32 PM, Oleksandr Andrushchenko wrote: On 05/21/2018 07:35 PM, Boris Ostrovsky wrote: On 05/21/2018 01:40 AM, Oleksandr Andrushchenko wrote: On 05/19/2018 01:04 AM, Boris Ostrovsky wrote: On 05/17/2018 04:26 AM, Oleksandr Andrushchenko wrote: From: Oleksandr Andrushchenko A commit message would be useful. Sure, v1 will have it Signed-off-by: Oleksandr Andrushchenko for (i = 0; i < nr_pages; i++) { - page = alloc_page(gfp); - if (page == NULL) { - nr_pages = i; - state = BP_EAGAIN; - break; + if (ext_pages) { + page = ext_pages[i]; + } else { + page = alloc_page(gfp); + if (page == NULL) { + nr_pages = i; + state = BP_EAGAIN; + break; + } } scrub_page(page); list_add(&page->lru, &pages); @@ -529,7 +565,7 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) i = 0; list_for_each_entry_safe(page, tmp, &pages, lru) { /* XENMEM_decrease_reservation requires a GFN */ - frame_list[i++] = xen_page_to_gfn(page); + frames[i++] = xen_page_to_gfn(page); #ifdef CONFIG_XEN_HAVE_PVMMU /* @@ -552,18 +588,22 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) #endif list_del(&page->lru); - balloon_append(page); + if (!ext_pages) + balloon_append(page); So what you are proposing is not really ballooning. You are just piggybacking on existing interfaces, aren't you? Sort of. Basically I need to {increase|decrease}_reservation, not actually allocating ballooned pages. Do you think I can simply EXPORT_SYMBOL for {increase|decrease}_reservation? Any other suggestion? I am actually wondering how much of that code you end up reusing. You pretty much create new code paths in both routines and common code ends up being essentially the hypercall. Well, I hoped that it would be easier to maintain if I modify existing code to support both use-cases, but I am also ok to create new routines if this seems to be reasonable - please let me know So the question is --- would it make sense to do all of this separately from the balloon driver? This can be done, but which driver will host this code then? If we move from the balloon driver, then this could go to either gntdev or grant-table. What's your preference? A separate module? Is there any use for this feature outside of your zero-copy DRM driver? Intel's hyper dma-buf (Dongwon/Matt CC'ed), V4L/GPU at least. At the time I tried to upstream zcopy driver it was discussed and decided that it would be better if I remove all DRM specific code and move it to Xen drivers. Thus, this RFC. But it can also be implemented as a dedicated Xen dma-buf driver which will have all the code from this RFC + a bit more (char/misc device handling at least). This will also require a dedicated user-space library, just like libxengnttab.so for gntdev (now I have all new IOCTLs covered there). If the idea of a dedicated Xen dma-buf driver seems to be more attractive we can work toward this solution. BTW, I do support this idea, but was not sure if Xen community accepts yet another driver which duplicates quite some code of the existing gntdev/balloon/grant-table. And now after this RFC I hope that all cons and pros of both dedicated driver and gntdev/balloon/grant-table extension are clearly seen and we can make a decision. IIRC the objection for a separate module was in the context of gntdev was discussion, because (among other things) people didn't want to have yet another file in /dev/xen/ Here we are talking about (a new) balloon-like module which doesn't create any new user-visible interfaces. And as for duplicating code --- as I said, I am not convinced there is much of duplication. I might even argue that we should add a new config option for this module. I am not quite sure I am fully following you here: so, you suggest that we have balloon.c unchanged, but instead create a new module (namely a file under the same folder as balloon.c, e.g. dma-buf-reservation.c) and move those {increase|decrease}_reservation routines (specific to dma-buf) to that new file? And make it selectable via Kconfig? If so, then how about the changes to grant-table and gntdev? Those will look inconsistent then. If you suggest a new kernel driver module: IMO, there is nothing bad if we create a dedicated kernel module (driver) for Xen dma-buf handling selectable under Kconfig option. Yes, this will create a yet another device under /dev/xen, but most people will never see it if we set Kconfig to default to "n&quo
Re: [PATCH v3 4/6] ALSA: xen-front: Implement handling of shared buffers
On 05/21/2018 11:26 PM, Takashi Iwai wrote: On Thu, 17 May 2018 08:26:16 +0200, Takashi Iwai wrote: On Tue, 15 May 2018 08:02:08 +0200, Oleksandr Andrushchenko wrote: On 05/15/2018 09:01 AM, Takashi Iwai wrote: On Tue, 15 May 2018 07:46:38 +0200, Oleksandr Andrushchenko wrote: On 05/14/2018 11:28 PM, Takashi Iwai wrote: On Mon, 14 May 2018 08:27:40 +0200, Oleksandr Andrushchenko wrote: --- /dev/null +++ b/sound/xen/xen_snd_front_shbuf.c @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT + +/* + * Xen para-virtual sound device + * + * Copyright (C) 2016-2018 EPAM Systems Inc. + * + * Author: Oleksandr Andrushchenko + */ + +#include +#include + +#include "xen_snd_front_shbuf.h" Hm, with the local build test, I get the following error: CC [M] sound/xen/xen_snd_front_shbuf.o In file included from sound/xen/xen_snd_front_shbuf.c:11:0: ./include/xen/xen.h:18:8: error: unknown type name ‘bool’ extern bool xen_pvh; ^~~~ In file included from ./include/xen/interface/xen.h:30:0, from ./include/xen/xen.h:29, from sound/xen/xen_snd_front_shbuf.c:11: ./arch/x86/include/asm/xen/interface.h:92:21: error: unknown type name ‘uint64_t’ DEFINE_GUEST_HANDLE(uint64_t); ^ Adding #include fixed the issue. Did you really test your patches with the latest Linus tree? My bad, it does build for ARM (which is my target), but also does need "#include " for x86 which I didn't build this time. Sorry about that. Do you want me to resend this single patch or you can make the change while applying? Yes, it's fine. Thank you FWIW, the patches are in topic/xen branch in sound.git tree, and I'll keep boiling for a while to see if any issues are caught by 0day bot. ... and now the topic/xen branch got merged to for-next, targeted for 4.18. Thanks for your patient works! Takashi Great news, thank you, Oleksandr
Re: [Xen-devel] [RFC 1/3] xen/balloon: Allow allocating DMA buffers
On 05/21/2018 09:53 PM, Boris Ostrovsky wrote: On 05/21/2018 01:32 PM, Oleksandr Andrushchenko wrote: On 05/21/2018 07:35 PM, Boris Ostrovsky wrote: On 05/21/2018 01:40 AM, Oleksandr Andrushchenko wrote: On 05/19/2018 01:04 AM, Boris Ostrovsky wrote: On 05/17/2018 04:26 AM, Oleksandr Andrushchenko wrote: From: Oleksandr Andrushchenko A commit message would be useful. Sure, v1 will have it Signed-off-by: Oleksandr Andrushchenko for (i = 0; i < nr_pages; i++) { - page = alloc_page(gfp); - if (page == NULL) { - nr_pages = i; - state = BP_EAGAIN; - break; + if (ext_pages) { + page = ext_pages[i]; + } else { + page = alloc_page(gfp); + if (page == NULL) { + nr_pages = i; + state = BP_EAGAIN; + break; + } } scrub_page(page); list_add(&page->lru, &pages); @@ -529,7 +565,7 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) i = 0; list_for_each_entry_safe(page, tmp, &pages, lru) { /* XENMEM_decrease_reservation requires a GFN */ - frame_list[i++] = xen_page_to_gfn(page); + frames[i++] = xen_page_to_gfn(page); #ifdef CONFIG_XEN_HAVE_PVMMU /* @@ -552,18 +588,22 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) #endif list_del(&page->lru); - balloon_append(page); + if (!ext_pages) + balloon_append(page); So what you are proposing is not really ballooning. You are just piggybacking on existing interfaces, aren't you? Sort of. Basically I need to {increase|decrease}_reservation, not actually allocating ballooned pages. Do you think I can simply EXPORT_SYMBOL for {increase|decrease}_reservation? Any other suggestion? I am actually wondering how much of that code you end up reusing. You pretty much create new code paths in both routines and common code ends up being essentially the hypercall. Well, I hoped that it would be easier to maintain if I modify existing code to support both use-cases, but I am also ok to create new routines if this seems to be reasonable - please let me know So the question is --- would it make sense to do all of this separately from the balloon driver? This can be done, but which driver will host this code then? If we move from the balloon driver, then this could go to either gntdev or grant-table. What's your preference? A separate module? Is there any use for this feature outside of your zero-copy DRM driver? Intel's hyper dma-buf (Dongwon/Matt CC'ed), V4L/GPU at least. At the time I tried to upstream zcopy driver it was discussed and decided that it would be better if I remove all DRM specific code and move it to Xen drivers. Thus, this RFC. But it can also be implemented as a dedicated Xen dma-buf driver which will have all the code from this RFC + a bit more (char/misc device handling at least). This will also require a dedicated user-space library, just like libxengnttab.so for gntdev (now I have all new IOCTLs covered there). If the idea of a dedicated Xen dma-buf driver seems to be more attractive we can work toward this solution. BTW, I do support this idea, but was not sure if Xen community accepts yet another driver which duplicates quite some code of the existing gntdev/balloon/grant-table. And now after this RFC I hope that all cons and pros of both dedicated driver and gntdev/balloon/grant-table extension are clearly seen and we can make a decision. -boris Thank you, Oleksandr [1] https://lists.freedesktop.org/archives/dri-devel/2018-April/173163.html
Re: [Xen-devel] [RFC 1/3] xen/balloon: Allow allocating DMA buffers
On 05/21/2018 07:35 PM, Boris Ostrovsky wrote: On 05/21/2018 01:40 AM, Oleksandr Andrushchenko wrote: On 05/19/2018 01:04 AM, Boris Ostrovsky wrote: On 05/17/2018 04:26 AM, Oleksandr Andrushchenko wrote: From: Oleksandr Andrushchenko A commit message would be useful. Sure, v1 will have it Signed-off-by: Oleksandr Andrushchenko for (i = 0; i < nr_pages; i++) { - page = alloc_page(gfp); - if (page == NULL) { - nr_pages = i; - state = BP_EAGAIN; - break; + if (ext_pages) { + page = ext_pages[i]; + } else { + page = alloc_page(gfp); + if (page == NULL) { + nr_pages = i; + state = BP_EAGAIN; + break; + } } scrub_page(page); list_add(&page->lru, &pages); @@ -529,7 +565,7 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) i = 0; list_for_each_entry_safe(page, tmp, &pages, lru) { /* XENMEM_decrease_reservation requires a GFN */ - frame_list[i++] = xen_page_to_gfn(page); + frames[i++] = xen_page_to_gfn(page); #ifdef CONFIG_XEN_HAVE_PVMMU /* @@ -552,18 +588,22 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) #endif list_del(&page->lru); - balloon_append(page); + if (!ext_pages) + balloon_append(page); So what you are proposing is not really ballooning. You are just piggybacking on existing interfaces, aren't you? Sort of. Basically I need to {increase|decrease}_reservation, not actually allocating ballooned pages. Do you think I can simply EXPORT_SYMBOL for {increase|decrease}_reservation? Any other suggestion? I am actually wondering how much of that code you end up reusing. You pretty much create new code paths in both routines and common code ends up being essentially the hypercall. Well, I hoped that it would be easier to maintain if I modify existing code to support both use-cases, but I am also ok to create new routines if this seems to be reasonable - please let me know So the question is --- would it make sense to do all of this separately from the balloon driver? This can be done, but which driver will host this code then? If we move from the balloon driver, then this could go to either gntdev or grant-table. What's your preference? -boris Thank you, Oleksandr
[PATCH] drm/xen-front: fix pointer casts
From: Oleksandr Andrushchenko Building for a 32-bit target results in warnings from casting between a 32-bit pointer and a 64-bit integer. Fix the warnings by casting those pointers to uintptr_t first. Signed-off-by: Oleksandr Andrushchenko --- drivers/gpu/drm/xen/xen_drm_front.h | 4 ++-- drivers/gpu/drm/xen/xen_drm_front_shbuf.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/xen/xen_drm_front.h b/drivers/gpu/drm/xen/xen_drm_front.h index 2c2479b571ae..8e15dbebc4ba 100644 --- a/drivers/gpu/drm/xen/xen_drm_front.h +++ b/drivers/gpu/drm/xen/xen_drm_front.h @@ -126,12 +126,12 @@ struct xen_drm_front_drm_info { static inline u64 xen_drm_front_fb_to_cookie(struct drm_framebuffer *fb) { - return (u64)fb; + return (u64)(uintptr_t)fb; } static inline u64 xen_drm_front_dbuf_to_cookie(struct drm_gem_object *gem_obj) { - return (u64)gem_obj; + return (u64)(uintptr_t)gem_obj; } int xen_drm_front_mode_set(struct xen_drm_front_drm_pipeline *pipeline, diff --git a/drivers/gpu/drm/xen/xen_drm_front_shbuf.c b/drivers/gpu/drm/xen/xen_drm_front_shbuf.c index 8099cb343ae3..47fc93847765 100644 --- a/drivers/gpu/drm/xen/xen_drm_front_shbuf.c +++ b/drivers/gpu/drm/xen/xen_drm_front_shbuf.c @@ -122,7 +122,7 @@ static void guest_calc_num_grefs(struct xen_drm_front_shbuf *buf) } #define xen_page_to_vaddr(page) \ - ((phys_addr_t)pfn_to_kaddr(page_to_xen_pfn(page))) + ((phys_addr_t)(uintptr_t)pfn_to_kaddr(page_to_xen_pfn(page))) static int backend_unmap(struct xen_drm_front_shbuf *buf) { -- 2.17.0
Re: [Xen-devel][RFC 2/3] xen/grant-table: Extend API to work with DMA buffers
On 05/19/2018 01:19 AM, Boris Ostrovsky wrote: On 05/17/2018 04:26 AM, Oleksandr Andrushchenko wrote: From: Oleksandr Andrushchenko Signed-off-by: Oleksandr Andrushchenko --- drivers/xen/grant-table.c | 49 +++ include/xen/grant_table.h | 7 ++ 2 files changed, 56 insertions(+) diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index bb36b1e1dbcc..c27bcc420575 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -729,6 +729,55 @@ void gnttab_free_pages(int nr_pages, struct page **pages) } EXPORT_SYMBOL(gnttab_free_pages); +int gnttab_dma_alloc_pages(struct device *dev, bool coherent, + int nr_pages, struct page **pages, + void **vaddr, dma_addr_t *dev_bus_addr) +{ + int i; + int ret; + + ret = alloc_dma_xenballooned_pages(dev, coherent, nr_pages, pages, + vaddr, dev_bus_addr); + if (ret < 0) + return ret; + + for (i = 0; i < nr_pages; i++) { +#if BITS_PER_LONG < 64 + struct xen_page_foreign *foreign; + + foreign = kzalloc(sizeof(*foreign), GFP_KERNEL); + if (!foreign) { + gnttab_dma_free_pages(dev, flags, nr_pages, pages, + *vaddr, *dev_bus_addr); + return -ENOMEM; + } + set_page_private(pages[i], (unsigned long)foreign); +#endif + SetPagePrivate(pages[i]); + } + return 0; +} +EXPORT_SYMBOL(gnttab_dma_alloc_pages); + +void gnttab_dma_free_pages(struct device *dev, bool coherent, + int nr_pages, struct page **pages, + void *vaddr, dma_addr_t dev_bus_addr) +{ + int i; + + for (i = 0; i < nr_pages; i++) { + if (PagePrivate(pages[i])) { +#if BITS_PER_LONG < 64 + kfree((void *)page_private(pages[i])); +#endif + ClearPagePrivate(pages[i]); + } + } + free_dma_xenballooned_pages(dev, coherent, nr_pages, pages, + vaddr, dev_bus_addr); +} +EXPORT_SYMBOL(gnttab_dma_free_pages); Given that these routines look almost exactly like their non-dma counterparts I wonder whether common code could be factored out. Yes, this can be done -boris + /* Handling of paged out grant targets (GNTST_eagain) */ #define MAX_DELAY 256 static inline void diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h index 34b1379f9777..20ee2b5ba965 100644 --- a/include/xen/grant_table.h +++ b/include/xen/grant_table.h @@ -195,6 +195,13 @@ void gnttab_free_auto_xlat_frames(void); int gnttab_alloc_pages(int nr_pages, struct page **pages); void gnttab_free_pages(int nr_pages, struct page **pages); +int gnttab_dma_alloc_pages(struct device *dev, bool coherent, + int nr_pages, struct page **pages, + void **vaddr, dma_addr_t *dev_bus_addr); +void gnttab_dma_free_pages(struct device *dev, bool coherent, + int nr_pages, struct page **pages, + void *vaddr, dma_addr_t dev_bus_addr); + int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, struct gnttab_map_grant_ref *kmap_ops, struct page **pages, unsigned int count);
Re: [Xen-devel] [RFC 1/3] xen/balloon: Allow allocating DMA buffers
On 05/19/2018 01:04 AM, Boris Ostrovsky wrote: On 05/17/2018 04:26 AM, Oleksandr Andrushchenko wrote: From: Oleksandr Andrushchenko A commit message would be useful. Sure, v1 will have it Signed-off-by: Oleksandr Andrushchenko for (i = 0; i < nr_pages; i++) { - page = alloc_page(gfp); - if (page == NULL) { - nr_pages = i; - state = BP_EAGAIN; - break; + if (ext_pages) { + page = ext_pages[i]; + } else { + page = alloc_page(gfp); + if (page == NULL) { + nr_pages = i; + state = BP_EAGAIN; + break; + } } scrub_page(page); list_add(&page->lru, &pages); @@ -529,7 +565,7 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) i = 0; list_for_each_entry_safe(page, tmp, &pages, lru) { /* XENMEM_decrease_reservation requires a GFN */ - frame_list[i++] = xen_page_to_gfn(page); + frames[i++] = xen_page_to_gfn(page); #ifdef CONFIG_XEN_HAVE_PVMMU /* @@ -552,18 +588,22 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) #endif list_del(&page->lru); - balloon_append(page); + if (!ext_pages) + balloon_append(page); So what you are proposing is not really ballooning. You are just piggybacking on existing interfaces, aren't you? Sort of. Basically I need to {increase|decrease}_reservation, not actually allocating ballooned pages. Do you think I can simply EXPORT_SYMBOL for {increase|decrease}_reservation? Any other suggestion? -boris Thank you, Oleksandr
Re: [PATCH v4 2/2] Input: xen-kbdfront - allow better run-time configuration
Sorry for top posting. Due to a bug in the test used to verify this patch I need to make two more changes, please see inline. Please ignore this patch for now, I will send v5 soon. Sorry for inconvenience, Oleksandr On 05/18/2018 12:59 PM, Oleksandr Andrushchenko wrote: From: Oleksandr Andrushchenko It is now only possible to control if multi-touch virtual device is created or not (via the corresponding XenStore entries), but keyboard and pointer devices are always created. In some cases this is not desirable. For example, if virtual keyboard device is exposed to Android then the latter won't automatically show on-screen keyboard as it expects that a physical keyboard device can be used for typing. Utilize keyboard and pointer device XenStore feature fields to configure which virtual devices are created: - set "feature-disable-keyboard" to 1 if no keyboard device needs to be created - set "feature-disable-pointer" to 1 if no pointer device needs to be created Keep old behavior by default. Signed-off-by: Oleksandr Andrushchenko Suggested-by: Andrii Chepurnyi Tested-by: Andrii Chepurnyi --- Changes since v3: - do not connect backend if all virtual devices are disabled (Dmitry) Changes since v2: - based on XenStore kbdif features to control which devices are exposed instead of module parameters. drivers/input/misc/xen-kbdfront.c | 177 ++ 1 file changed, 106 insertions(+), 71 deletions(-) diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index d91f3b1c5375..0e8926c75559 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c @@ -63,6 +63,9 @@ static void xenkbd_disconnect_backend(struct xenkbd_info *); static void xenkbd_handle_motion_event(struct xenkbd_info *info, struct xenkbd_motion *motion) { + if (unlikely(!info->ptr)) + return; + input_report_rel(info->ptr, REL_X, motion->rel_x); input_report_rel(info->ptr, REL_Y, motion->rel_y); if (motion->rel_z) @@ -73,6 +76,9 @@ static void xenkbd_handle_motion_event(struct xenkbd_info *info, static void xenkbd_handle_position_event(struct xenkbd_info *info, struct xenkbd_position *pos) { + if (unlikely(!info->ptr)) + return; + input_report_abs(info->ptr, ABS_X, pos->abs_x); input_report_abs(info->ptr, ABS_Y, pos->abs_y); if (pos->rel_z) @@ -97,6 +103,9 @@ static void xenkbd_handle_key_event(struct xenkbd_info *info, return; } + if (unlikely(!dev)) + return; + input_event(dev, EV_KEY, key->keycode, value); input_sync(dev); } @@ -192,7 +201,7 @@ static int xenkbd_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { int ret, i; - unsigned int abs, touch; + bool with_mtouch, with_kbd, with_ptr; struct xenkbd_info *info; struct input_dev *kbd, *ptr, *mtouch; @@ -211,93 +220,114 @@ static int xenkbd_probe(struct xenbus_device *dev, if (!info->page) goto error_nomem; - /* Set input abs params to match backend screen res */ - abs = xenbus_read_unsigned(dev->otherend, - XENKBD_FIELD_FEAT_ABS_POINTER, 0); - ptr_size[KPARAM_X] = xenbus_read_unsigned(dev->otherend, - XENKBD_FIELD_WIDTH, - ptr_size[KPARAM_X]); - ptr_size[KPARAM_Y] = xenbus_read_unsigned(dev->otherend, - XENKBD_FIELD_HEIGHT, - ptr_size[KPARAM_Y]); - if (abs) { - ret = xenbus_write(XBT_NIL, dev->nodename, - XENKBD_FIELD_REQ_ABS_POINTER, "1"); - if (ret) { - pr_warn("xenkbd: can't request abs-pointer\n"); - abs = 0; - } - } + /* +* The below are reverse logic, e.g. if the feature is set, then +* do not expose the corresponding virtual device. +*/ + with_kbd = !xenbus_read_unsigned(dev->nodename, According to the kbdif protocol this must be "dev->otherend" +XENKBD_FIELD_FEAT_DSBL_KEYBRD, 0); + + with_ptr = !xenbus_read_unsigned(dev->nodename, According to the kbdif protocol this must be "dev->otherend" +XENKBD_FIELD_FEAT_DSBL_POINTER, 0); - touch = xenbus_read_unsigned(dev->nodename, -XENKBD_FIELD_FEAT_MTOUCH, 0); - if (touch) { + /* Direct logic: if set, then
[PATCH v4 2/2] Input: xen-kbdfront - allow better run-time configuration
From: Oleksandr Andrushchenko It is now only possible to control if multi-touch virtual device is created or not (via the corresponding XenStore entries), but keyboard and pointer devices are always created. In some cases this is not desirable. For example, if virtual keyboard device is exposed to Android then the latter won't automatically show on-screen keyboard as it expects that a physical keyboard device can be used for typing. Utilize keyboard and pointer device XenStore feature fields to configure which virtual devices are created: - set "feature-disable-keyboard" to 1 if no keyboard device needs to be created - set "feature-disable-pointer" to 1 if no pointer device needs to be created Keep old behavior by default. Signed-off-by: Oleksandr Andrushchenko Suggested-by: Andrii Chepurnyi Tested-by: Andrii Chepurnyi --- Changes since v3: - do not connect backend if all virtual devices are disabled (Dmitry) Changes since v2: - based on XenStore kbdif features to control which devices are exposed instead of module parameters. drivers/input/misc/xen-kbdfront.c | 177 ++ 1 file changed, 106 insertions(+), 71 deletions(-) diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index d91f3b1c5375..0e8926c75559 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c @@ -63,6 +63,9 @@ static void xenkbd_disconnect_backend(struct xenkbd_info *); static void xenkbd_handle_motion_event(struct xenkbd_info *info, struct xenkbd_motion *motion) { + if (unlikely(!info->ptr)) + return; + input_report_rel(info->ptr, REL_X, motion->rel_x); input_report_rel(info->ptr, REL_Y, motion->rel_y); if (motion->rel_z) @@ -73,6 +76,9 @@ static void xenkbd_handle_motion_event(struct xenkbd_info *info, static void xenkbd_handle_position_event(struct xenkbd_info *info, struct xenkbd_position *pos) { + if (unlikely(!info->ptr)) + return; + input_report_abs(info->ptr, ABS_X, pos->abs_x); input_report_abs(info->ptr, ABS_Y, pos->abs_y); if (pos->rel_z) @@ -97,6 +103,9 @@ static void xenkbd_handle_key_event(struct xenkbd_info *info, return; } + if (unlikely(!dev)) + return; + input_event(dev, EV_KEY, key->keycode, value); input_sync(dev); } @@ -192,7 +201,7 @@ static int xenkbd_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { int ret, i; - unsigned int abs, touch; + bool with_mtouch, with_kbd, with_ptr; struct xenkbd_info *info; struct input_dev *kbd, *ptr, *mtouch; @@ -211,93 +220,114 @@ static int xenkbd_probe(struct xenbus_device *dev, if (!info->page) goto error_nomem; - /* Set input abs params to match backend screen res */ - abs = xenbus_read_unsigned(dev->otherend, - XENKBD_FIELD_FEAT_ABS_POINTER, 0); - ptr_size[KPARAM_X] = xenbus_read_unsigned(dev->otherend, - XENKBD_FIELD_WIDTH, - ptr_size[KPARAM_X]); - ptr_size[KPARAM_Y] = xenbus_read_unsigned(dev->otherend, - XENKBD_FIELD_HEIGHT, - ptr_size[KPARAM_Y]); - if (abs) { - ret = xenbus_write(XBT_NIL, dev->nodename, - XENKBD_FIELD_REQ_ABS_POINTER, "1"); - if (ret) { - pr_warn("xenkbd: can't request abs-pointer\n"); - abs = 0; - } - } + /* +* The below are reverse logic, e.g. if the feature is set, then +* do not expose the corresponding virtual device. +*/ + with_kbd = !xenbus_read_unsigned(dev->nodename, +XENKBD_FIELD_FEAT_DSBL_KEYBRD, 0); + + with_ptr = !xenbus_read_unsigned(dev->nodename, +XENKBD_FIELD_FEAT_DSBL_POINTER, 0); - touch = xenbus_read_unsigned(dev->nodename, -XENKBD_FIELD_FEAT_MTOUCH, 0); - if (touch) { + /* Direct logic: if set, then create multi-touch device. */ + with_mtouch = xenbus_read_unsigned(dev->nodename, + XENKBD_FIELD_FEAT_MTOUCH, 0); + if (with_mtouch) { ret = xenbus_write(XBT_NIL, dev->nodename, XENKBD_FIELD_REQ_MTOUCH, "1"); if (ret) { pr_warn("xenkbd: can't request m
[PATCH v4 1/2] xen/kbdif: Sync up with the canonical definition in Xen
From: Oleksandr Andrushchenko This is the sync up with the canonical definition of the keyboard protocol in Xen: 1. Add missing string constants for {feature|request}-raw-pointer to align with the rest of the interface file. 2. Add new XenStore feature fields, so it is possible to individually control set of exposed virtual devices for each guest OS: - set feature-disable-keyboard to 1 if no keyboard device needs to be created - set feature-disable-pointer to 1 if no pointer device needs to be created Signed-off-by: Oleksandr Andrushchenko Cc: Konrad Rzeszutek Wilk --- include/xen/interface/io/kbdif.h | 30 ++ 1 file changed, 30 insertions(+) diff --git a/include/xen/interface/io/kbdif.h b/include/xen/interface/io/kbdif.h index 2a9510ade701..808ef7d02a65 100644 --- a/include/xen/interface/io/kbdif.h +++ b/include/xen/interface/io/kbdif.h @@ -51,6 +51,18 @@ * corresponding entries in XenStore and puts 1 as the value of the entry. * If a feature is not supported then 0 must be set or feature entry omitted. * + * feature-disable-keyboard + * Values: + * + * If there is no need to expose a virtual keyboard device by the + * frontend then this must be set to 1. + * + * feature-disable-pointer + * Values: + * + * If there is no need to expose a virtual pointer device by the + * frontend then this must be set to 1. + * * feature-abs-pointer * Values: * @@ -63,6 +75,13 @@ * Backends, which support reporting of multi-touch events * should set this to 1. * + * feature-raw-pointer + * Values: + * + * Backends, which support reporting raw (unscaled) absolute coordinates + * for pointer devices should set this to 1. Raw (unscaled) values have + * a range of [0, 0x7fff]. + * *- Pointer Device Parameters * * width @@ -98,6 +117,13 @@ * * Request backend to report multi-touch events. * + * request-raw-pointer + * Values: + * + * Request backend to report raw unscaled absolute pointer coordinates. + * This option is only valid if request-abs-pointer is also set. + * Raw unscaled coordinates have the range [0, 0x7fff] + * *--- Request Transport Parameters --- * * event-channel @@ -163,9 +189,13 @@ #define XENKBD_DRIVER_NAME "vkbd" +#define XENKBD_FIELD_FEAT_DSBL_KEYBRD "feature-disable-keyboard" +#define XENKBD_FIELD_FEAT_DSBL_POINTER "feature-disable-pointer" #define XENKBD_FIELD_FEAT_ABS_POINTER "feature-abs-pointer" +#define XENKBD_FIELD_FEAT_RAW_POINTER "feature-raw-pointer" #define XENKBD_FIELD_FEAT_MTOUCH "feature-multi-touch" #define XENKBD_FIELD_REQ_ABS_POINTER "request-abs-pointer" +#define XENKBD_FIELD_REQ_RAW_POINTER "request-raw-pointer" #define XENKBD_FIELD_REQ_MTOUCH"request-multi-touch" #define XENKBD_FIELD_RING_GREF "page-gref" #define XENKBD_FIELD_EVT_CHANNEL "event-channel" -- 2.17.0
Re: [PATCH v3 2/2] Input: xen-kbdfront - allow better run-time configuration
On 05/17/2018 04:08 PM, Boris Ostrovsky wrote: On 05/17/2018 01:31 AM, Oleksandr Andrushchenko wrote: I will go with the change you suggested and I'll send v4 tomorrow then. Please make sure your changes to kbdif.h are in Xen first. I believe you submitted a patch there but I don't see it in the staging tree yet. Sure, I already have Release ack for the one which is not in Xen tree yet, hope Konrad can apply it today, so tomorrow Xen and Linux are both ok (or by the time I send v4). -boris Thank you, Oleksandr
[Xen-devel][RFC 3/3] xen/gntdev: Add support for Linux dma buffers
From: Oleksandr Andrushchenko Signed-off-by: Oleksandr Andrushchenko --- drivers/xen/gntdev.c | 954 +- include/uapi/xen/gntdev.h | 101 include/xen/gntdev_exp.h | 23 + 3 files changed, 1066 insertions(+), 12 deletions(-) create mode 100644 include/xen/gntdev_exp.h diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 9510f228efe9..0ee88e193362 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -4,6 +4,8 @@ * Device for accessing (in user-space) pages that have been granted by other * domains. * + * DMA buffer implementation is based on drivers/gpu/drm/drm_prime.c. + * * Copyright (c) 2006-2007, D G Murray. * (c) 2009 Gerd Hoffmann * @@ -37,6 +39,9 @@ #include #include +#include +#include + #include #include #include @@ -61,16 +66,39 @@ static atomic_t pages_mapped = ATOMIC_INIT(0); static int use_ptemod; #define populate_freeable_maps use_ptemod +#ifndef GRANT_INVALID_REF +/* + * Note on usage of grant reference 0 as invalid grant reference: + * grant reference 0 is valid, but never exposed to a driver, + * because of the fact it is already in use/reserved by the PV console. + */ +#define GRANT_INVALID_REF 0 +#endif + struct gntdev_priv { /* maps with visible offsets in the file descriptor */ struct list_head maps; /* maps that are not visible; will be freed on munmap. * Only populated if populate_freeable_maps == 1 */ struct list_head freeable_maps; + /* List of dma-bufs. */ + struct list_head dma_bufs; /* lock protects maps and freeable_maps */ struct mutex lock; struct mm_struct *mm; struct mmu_notifier mn; + + /* Private data of the hyper DMA buffers. */ + + struct device *dev; + /* List of exported DMA buffers. */ + struct list_head dmabuf_exp_list; + /* List of wait objects. */ + struct list_head dmabuf_exp_wait_list; + /* List of imported DMA buffers. */ + struct list_head dmabuf_imp_list; + /* This is the lock which protects dma_buf_xxx lists. */ + struct mutex dmabuf_lock; }; struct unmap_notify { @@ -95,10 +123,65 @@ struct grant_map { struct gnttab_unmap_grant_ref *kunmap_ops; struct page **pages; unsigned long pages_vm_start; + + /* +* All the fields starting with dmabuf_ are only valid if this +* mapping is used for exporting a DMA buffer. +* If dmabuf_vaddr is not NULL then this mapping is backed by DMA +* capable memory. +*/ + + /* Flags used to create this DMA buffer: GNTDEV_DMABUF_FLAG_XXX. */ + bool dmabuf_flags; + /* Virtual/CPU address of the DMA buffer. */ + void *dmabuf_vaddr; + /* Bus address of the DMA buffer. */ + dma_addr_t dmabuf_bus_addr; +}; + +struct hyper_dmabuf { + struct gntdev_priv *priv; + struct dma_buf *dmabuf; + struct list_head next; + int fd; + + union { + struct { + /* Exported buffers are reference counted. */ + struct kref refcount; + struct grant_map *map; + } exp; + struct { + /* Granted references of the imported buffer. */ + grant_ref_t *refs; + /* Scatter-gather table of the imported buffer. */ + struct sg_table *sgt; + /* dma-buf attachment of the imported buffer. */ + struct dma_buf_attachment *attach; + } imp; + } u; + + /* Number of pages this buffer has. */ + int nr_pages; + /* Pages of this buffer. */ + struct page **pages; +}; + +struct hyper_dmabuf_wait_obj { + struct list_head next; + struct hyper_dmabuf *hyper_dmabuf; + struct completion completion; +}; + +struct hyper_dambuf_attachment { + struct sg_table *sgt; + enum dma_data_direction dir; }; static int unmap_grant_pages(struct grant_map *map, int offset, int pages); +static struct miscdevice gntdev_miscdev; + /* -- */ static void gntdev_print_maps(struct gntdev_priv *priv, @@ -120,8 +203,17 @@ static void gntdev_free_map(struct grant_map *map) if (map == NULL) return; - if (map->pages) + if (map->dmabuf_vaddr) { + bool coherent = map->dmabuf_flags & + GNTDEV_DMABUF_FLAG_DMA_COHERENT; + + gnttab_dma_free_pages(gntdev_miscdev.this_device, + coherent, map->count, map->pages, + map->dmabuf_vaddr, map->dmabuf_bus_addr); + } else if (map->pages) { gnttab_free_pages(map->count, map->pages); +
[Xen-devel][RFC 2/3] xen/grant-table: Extend API to work with DMA buffers
From: Oleksandr Andrushchenko Signed-off-by: Oleksandr Andrushchenko --- drivers/xen/grant-table.c | 49 +++ include/xen/grant_table.h | 7 ++ 2 files changed, 56 insertions(+) diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index bb36b1e1dbcc..c27bcc420575 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -729,6 +729,55 @@ void gnttab_free_pages(int nr_pages, struct page **pages) } EXPORT_SYMBOL(gnttab_free_pages); +int gnttab_dma_alloc_pages(struct device *dev, bool coherent, + int nr_pages, struct page **pages, + void **vaddr, dma_addr_t *dev_bus_addr) +{ + int i; + int ret; + + ret = alloc_dma_xenballooned_pages(dev, coherent, nr_pages, pages, + vaddr, dev_bus_addr); + if (ret < 0) + return ret; + + for (i = 0; i < nr_pages; i++) { +#if BITS_PER_LONG < 64 + struct xen_page_foreign *foreign; + + foreign = kzalloc(sizeof(*foreign), GFP_KERNEL); + if (!foreign) { + gnttab_dma_free_pages(dev, flags, nr_pages, pages, + *vaddr, *dev_bus_addr); + return -ENOMEM; + } + set_page_private(pages[i], (unsigned long)foreign); +#endif + SetPagePrivate(pages[i]); + } + return 0; +} +EXPORT_SYMBOL(gnttab_dma_alloc_pages); + +void gnttab_dma_free_pages(struct device *dev, bool coherent, + int nr_pages, struct page **pages, + void *vaddr, dma_addr_t dev_bus_addr) +{ + int i; + + for (i = 0; i < nr_pages; i++) { + if (PagePrivate(pages[i])) { +#if BITS_PER_LONG < 64 + kfree((void *)page_private(pages[i])); +#endif + ClearPagePrivate(pages[i]); + } + } + free_dma_xenballooned_pages(dev, coherent, nr_pages, pages, + vaddr, dev_bus_addr); +} +EXPORT_SYMBOL(gnttab_dma_free_pages); + /* Handling of paged out grant targets (GNTST_eagain) */ #define MAX_DELAY 256 static inline void diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h index 34b1379f9777..20ee2b5ba965 100644 --- a/include/xen/grant_table.h +++ b/include/xen/grant_table.h @@ -195,6 +195,13 @@ void gnttab_free_auto_xlat_frames(void); int gnttab_alloc_pages(int nr_pages, struct page **pages); void gnttab_free_pages(int nr_pages, struct page **pages); +int gnttab_dma_alloc_pages(struct device *dev, bool coherent, + int nr_pages, struct page **pages, + void **vaddr, dma_addr_t *dev_bus_addr); +void gnttab_dma_free_pages(struct device *dev, bool coherent, + int nr_pages, struct page **pages, + void *vaddr, dma_addr_t dev_bus_addr); + int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, struct gnttab_map_grant_ref *kmap_ops, struct page **pages, unsigned int count); -- 2.17.0
[Xen-devel][RFC 1/3] xen/balloon: Allow allocating DMA buffers
From: Oleksandr Andrushchenko Signed-off-by: Oleksandr Andrushchenko --- drivers/xen/balloon.c | 214 +++--- drivers/xen/xen-balloon.c | 2 + include/xen/balloon.h | 11 +- 3 files changed, 188 insertions(+), 39 deletions(-) diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index e4db19e88ab1..e3a145aa9f29 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -415,8 +415,10 @@ static bool balloon_is_inflated(void) return balloon_stats.balloon_low || balloon_stats.balloon_high; } -static enum bp_state increase_reservation(unsigned long nr_pages) +static enum bp_state increase_reservation(unsigned long nr_pages, + struct page **ext_pages) { + enum bp_state ret = BP_DONE; int rc; unsigned long i; struct page *page; @@ -425,32 +427,49 @@ static enum bp_state increase_reservation(unsigned long nr_pages) .extent_order = EXTENT_ORDER, .domid= DOMID_SELF }; + xen_pfn_t *frames; - if (nr_pages > ARRAY_SIZE(frame_list)) - nr_pages = ARRAY_SIZE(frame_list); + if (nr_pages > ARRAY_SIZE(frame_list)) { + frames = kcalloc(nr_pages, sizeof(xen_pfn_t), GFP_KERNEL); + if (!frames) + return BP_ECANCELED; + } else { + frames = frame_list; + } - page = list_first_entry_or_null(&ballooned_pages, struct page, lru); - for (i = 0; i < nr_pages; i++) { - if (!page) { - nr_pages = i; - break; - } + /* XENMEM_populate_physmap requires a PFN based on Xen +* granularity. +*/ + if (ext_pages) { + for (i = 0; i < nr_pages; i++) + frames[i] = page_to_xen_pfn(ext_pages[i]); + } else { + page = list_first_entry_or_null(&ballooned_pages, + struct page, lru); + for (i = 0; i < nr_pages; i++) { + if (!page) { + nr_pages = i; + break; + } - /* XENMEM_populate_physmap requires a PFN based on Xen -* granularity. -*/ - frame_list[i] = page_to_xen_pfn(page); - page = balloon_next_page(page); + frames[i] = page_to_xen_pfn(page); + page = balloon_next_page(page); + } } - set_xen_guest_handle(reservation.extent_start, frame_list); + set_xen_guest_handle(reservation.extent_start, frames); reservation.nr_extents = nr_pages; rc = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation); - if (rc <= 0) - return BP_EAGAIN; + if (rc <= 0) { + ret = BP_EAGAIN; + goto out; + } for (i = 0; i < rc; i++) { - page = balloon_retrieve(false); + if (ext_pages) + page = ext_pages[i]; + else + page = balloon_retrieve(false); BUG_ON(page == NULL); #ifdef CONFIG_XEN_HAVE_PVMMU @@ -463,14 +482,14 @@ static enum bp_state increase_reservation(unsigned long nr_pages) if (!xen_feature(XENFEAT_auto_translated_physmap)) { unsigned long pfn = page_to_pfn(page); - set_phys_to_machine(pfn, frame_list[i]); + set_phys_to_machine(pfn, frames[i]); /* Link back into the page tables if not highmem. */ if (!PageHighMem(page)) { int ret; ret = HYPERVISOR_update_va_mapping( (unsigned long)__va(pfn << PAGE_SHIFT), - mfn_pte(frame_list[i], PAGE_KERNEL), + mfn_pte(frames[i], PAGE_KERNEL), 0); BUG_ON(ret); } @@ -478,15 +497,22 @@ static enum bp_state increase_reservation(unsigned long nr_pages) #endif /* Relinquish the page back to the allocator. */ - __free_reserved_page(page); + if (!ext_pages) + __free_reserved_page(page); } - balloon_stats.current_pages += rc; + if (!ext_pages) + balloon_stats.current_pages += rc; - return BP_DONE; +out: + if (frames != frame_list) + kfree(frames); + + return ret; } -static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) +static enum b
[Xen-devel][RFC 0/3] dma-buf support for gntdev
From: Oleksandr Andrushchenko This work is in response to my previous attempt to introduce Xen/DRM zero-copy driver [1] to enable Linux dma-buf API [2] for Xen based frontends/backends. There is also an existing hyper_dmabuf approach available [3] which, if reworked to utilize the proposed solution, can greatly benefit as well. The original rationale behind this work was to enable zero-copying use-cases while working with Xen para-virtual display driver [4]: when using Xen PV DRM frontend driver then on backend side one will need to do copying of display buffers' contents (filled by the frontend's user-space) into buffers allocated at the backend side. Taking into account the size of display buffers and frames per second it may result in unneeded huge data bus occupation and performance loss. The helper driver [4] allows implementing zero-copying use-cases when using Xen para-virtualized frontend display driver by implementing a DRM/KMS helper driver running on backend's side. It utilizes PRIME buffers API (implemented on top of Linux dma-buf) to share frontend's buffers with physical device drivers on backend's side: - a dumb buffer created on backend's side can be shared with the Xen PV frontend driver, so it directly writes into backend's domain memory (into the buffer exported from DRM/KMS driver of a physical display device) - a dumb buffer allocated by the frontend can be imported into physical device DRM/KMS driver, thus allowing to achieve no copying as well Finally, it was discussed and decided ([1], [5]) that it is worth implementing such use-cases via extension of the existing Xen gntdev driver instead of introducing new DRM specific driver. Please note, that the support of dma-buf is Linux only, as dma-buf is a Linux only thing. Now to the proposed solution. The changes to the existing Xen drivers in the Linux kernel fall into 2 categories: 1. DMA-able memory buffer allocation and ballooning in/out the pages of such a buffer. This is required if we are about to share dma-buf with the hardware that does require those to be allocated with dma_alloc_xxx API. (It is still possible to allocate a dma-buf from any other memory, e.g. system pages). 2. Extension of the gntdev driver to enable it to import/export dma-buf’s. The first two patches in this series solve #1 and the last one is for #2. The corresponding libxengnttab changes are available at [6]. All the above was tested with display backend [7] and its accompanying helper library [8] on Renesas ARM64 based board. *To all the communities*: I would like to ask you to review the proposed solution and give feedback on it, so I can improve and send final patches for review (this is still work in progress, but enough to start discussing the implementation). Thank you in advance, Oleksandr Andrushchenko [1] https://lists.freedesktop.org/archives/dri-devel/2018-April/173163.html [2] https://elixir.bootlin.com/linux/v4.17-rc5/source/Documentation/driver-api/dma-buf.rst [3] https://lists.xenproject.org/archives/html/xen-devel/2018-02/msg01202.html [4] https://cgit.freedesktop.org/drm/drm-misc/tree/drivers/gpu/drm/xen [5] https://patchwork.kernel.org/patch/10279681/ [6] https://github.com/andr2000/xen/tree/xen_dma_buf_v1 [7] https://github.com/andr2000/displ_be/tree/xen_dma_buf_v1 [8] https://github.com/andr2000/libxenbe/tree/xen_dma_buf_v1 Oleksandr Andrushchenko (3): xen/balloon: Allow allocating DMA buffers xen/grant-table: Extend API to work with DMA buffers xen/gntdev: Add support for Linux dma buffers drivers/xen/balloon.c | 214 +++-- drivers/xen/gntdev.c | 954 +- drivers/xen/grant-table.c | 49 ++ drivers/xen/xen-balloon.c | 2 + include/uapi/xen/gntdev.h | 101 include/xen/balloon.h | 11 +- include/xen/gntdev_exp.h | 23 + include/xen/grant_table.h | 7 + 8 files changed, 1310 insertions(+), 51 deletions(-) create mode 100644 include/xen/gntdev_exp.h -- 2.17.0
Re: [PATCH v3 4/6] ALSA: xen-front: Implement handling of shared buffers
On 05/17/2018 09:26 AM, Takashi Iwai wrote: On Tue, 15 May 2018 08:02:08 +0200, Oleksandr Andrushchenko wrote: On 05/15/2018 09:01 AM, Takashi Iwai wrote: On Tue, 15 May 2018 07:46:38 +0200, Oleksandr Andrushchenko wrote: On 05/14/2018 11:28 PM, Takashi Iwai wrote: On Mon, 14 May 2018 08:27:40 +0200, Oleksandr Andrushchenko wrote: --- /dev/null +++ b/sound/xen/xen_snd_front_shbuf.c @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT + +/* + * Xen para-virtual sound device + * + * Copyright (C) 2016-2018 EPAM Systems Inc. + * + * Author: Oleksandr Andrushchenko + */ + +#include +#include + +#include "xen_snd_front_shbuf.h" Hm, with the local build test, I get the following error: CC [M] sound/xen/xen_snd_front_shbuf.o In file included from sound/xen/xen_snd_front_shbuf.c:11:0: ./include/xen/xen.h:18:8: error: unknown type name ‘bool’ extern bool xen_pvh; ^~~~ In file included from ./include/xen/interface/xen.h:30:0, from ./include/xen/xen.h:29, from sound/xen/xen_snd_front_shbuf.c:11: ./arch/x86/include/asm/xen/interface.h:92:21: error: unknown type name ‘uint64_t’ DEFINE_GUEST_HANDLE(uint64_t); ^ Adding #include fixed the issue. Did you really test your patches with the latest Linus tree? My bad, it does build for ARM (which is my target), but also does need "#include " for x86 which I didn't build this time. Sorry about that. Do you want me to resend this single patch or you can make the change while applying? Yes, it's fine. Thank you FWIW, the patches are in topic/xen branch in sound.git tree, and I'll keep boiling for a while to see if any issues are caught by 0day bot. Thank you, hope everything goes well Takashi Thank you, Oleksandr
Re: [PATCH v3 2/2] Input: xen-kbdfront - allow better run-time configuration
On 05/17/2018 12:08 AM, Dmitry Torokhov wrote: On Wed, May 16, 2018 at 08:47:30PM +0300, Oleksandr Andrushchenko wrote: On 05/16/2018 08:15 PM, Dmitry Torokhov wrote: Hi Oleksandr, On Mon, May 14, 2018 at 05:40:29PM +0300, Oleksandr Andrushchenko wrote: @@ -211,93 +220,114 @@ static int xenkbd_probe(struct xenbus_device *dev, if (!info->page) goto error_nomem; - /* Set input abs params to match backend screen res */ - abs = xenbus_read_unsigned(dev->otherend, - XENKBD_FIELD_FEAT_ABS_POINTER, 0); - ptr_size[KPARAM_X] = xenbus_read_unsigned(dev->otherend, - XENKBD_FIELD_WIDTH, - ptr_size[KPARAM_X]); - ptr_size[KPARAM_Y] = xenbus_read_unsigned(dev->otherend, - XENKBD_FIELD_HEIGHT, - ptr_size[KPARAM_Y]); - if (abs) { - ret = xenbus_write(XBT_NIL, dev->nodename, - XENKBD_FIELD_REQ_ABS_POINTER, "1"); - if (ret) { - pr_warn("xenkbd: can't request abs-pointer\n"); - abs = 0; - } - } + /* +* The below are reverse logic, e.g. if the feature is set, then +* do not expose the corresponding virtual device. +*/ + with_kbd = !xenbus_read_unsigned(dev->nodename, +XENKBD_FIELD_FEAT_DSBL_KEYBRD, 0); - touch = xenbus_read_unsigned(dev->nodename, -XENKBD_FIELD_FEAT_MTOUCH, 0); - if (touch) { + with_ptr = !xenbus_read_unsigned(dev->nodename, +XENKBD_FIELD_FEAT_DSBL_POINTER, 0); + + /* Direct logic: if set, then create multi-touch device. */ + with_mtouch = xenbus_read_unsigned(dev->nodename, + XENKBD_FIELD_FEAT_MTOUCH, 0); + if (with_mtouch) { ret = xenbus_write(XBT_NIL, dev->nodename, XENKBD_FIELD_REQ_MTOUCH, "1"); if (ret) { pr_warn("xenkbd: can't request multi-touch"); - touch = 0; + with_mtouch = 0; } } Does it make sense to still end up calling xenkbd_connect_backend() when all interfaces (keyboard, pointer, and multitouch) are disabled? Should we do: if (!(with_kbd || || with_ptr || with_mtouch)) return -ENXIO; ? It does make sense. Then we probably need to move all xenbus_read_unsigned calls to the very beginning of the .probe, so no memory allocations are made which will be useless if we return -ENXIO, e.g. something like static int xenkbd_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { int ret, i; bool with_mtouch, with_kbd, with_ptr; struct xenkbd_info *info; struct input_dev *kbd, *ptr, *mtouch; if (!(with_kbd | with_ptr | with_mtouch)) return -ENXIO; Does the above looks ok? Yes. Another option is to keep the check where I suggested and do if (...) { ret = -ENXIO; goto error; } Whichever you prefer is fine with me. I will go with the change you suggested and I'll send v4 tomorrow then. Thanks. Thank you, Oleksandr
Re: [PATCH v3 2/2] Input: xen-kbdfront - allow better run-time configuration
On 05/16/2018 08:15 PM, Dmitry Torokhov wrote: Hi Oleksandr, On Mon, May 14, 2018 at 05:40:29PM +0300, Oleksandr Andrushchenko wrote: @@ -211,93 +220,114 @@ static int xenkbd_probe(struct xenbus_device *dev, if (!info->page) goto error_nomem; - /* Set input abs params to match backend screen res */ - abs = xenbus_read_unsigned(dev->otherend, - XENKBD_FIELD_FEAT_ABS_POINTER, 0); - ptr_size[KPARAM_X] = xenbus_read_unsigned(dev->otherend, - XENKBD_FIELD_WIDTH, - ptr_size[KPARAM_X]); - ptr_size[KPARAM_Y] = xenbus_read_unsigned(dev->otherend, - XENKBD_FIELD_HEIGHT, - ptr_size[KPARAM_Y]); - if (abs) { - ret = xenbus_write(XBT_NIL, dev->nodename, - XENKBD_FIELD_REQ_ABS_POINTER, "1"); - if (ret) { - pr_warn("xenkbd: can't request abs-pointer\n"); - abs = 0; - } - } + /* +* The below are reverse logic, e.g. if the feature is set, then +* do not expose the corresponding virtual device. +*/ + with_kbd = !xenbus_read_unsigned(dev->nodename, +XENKBD_FIELD_FEAT_DSBL_KEYBRD, 0); - touch = xenbus_read_unsigned(dev->nodename, -XENKBD_FIELD_FEAT_MTOUCH, 0); - if (touch) { + with_ptr = !xenbus_read_unsigned(dev->nodename, +XENKBD_FIELD_FEAT_DSBL_POINTER, 0); + + /* Direct logic: if set, then create multi-touch device. */ + with_mtouch = xenbus_read_unsigned(dev->nodename, + XENKBD_FIELD_FEAT_MTOUCH, 0); + if (with_mtouch) { ret = xenbus_write(XBT_NIL, dev->nodename, XENKBD_FIELD_REQ_MTOUCH, "1"); if (ret) { pr_warn("xenkbd: can't request multi-touch"); - touch = 0; + with_mtouch = 0; } } Does it make sense to still end up calling xenkbd_connect_backend() when all interfaces (keyboard, pointer, and multitouch) are disabled? Should we do: if (!(with_kbd || || with_ptr || with_mtouch)) return -ENXIO; ? It does make sense. Then we probably need to move all xenbus_read_unsigned calls to the very beginning of the .probe, so no memory allocations are made which will be useless if we return -ENXIO, e.g. something like static int xenkbd_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { int ret, i; bool with_mtouch, with_kbd, with_ptr; struct xenkbd_info *info; struct input_dev *kbd, *ptr, *mtouch; if (!(with_kbd | with_ptr | with_mtouch)) return -ENXIO; Does the above looks ok? Thanks. Thank you, Oleksandr
Re: [PATCH][next] drm/xen-front: fix spelling mistake: "conector" -> "connector"
On 05/15/2018 11:54 AM, Colin King wrote: From: Colin Ian King Trivial fix to spelling mistake in DRM_INFO message. Signed-off-by: Colin Ian King Thank you, Reviewed-by: Oleksandr Andrushchenko Will apply to drm-misc-next --- drivers/gpu/drm/xen/xen_drm_front.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xen/xen_drm_front.c b/drivers/gpu/drm/xen/xen_drm_front.c index 0e486cb1c10c..3725de4c4da8 100644 --- a/drivers/gpu/drm/xen/xen_drm_front.c +++ b/drivers/gpu/drm/xen/xen_drm_front.c @@ -623,7 +623,7 @@ static int displback_initwait(struct xen_drm_front_info *front_info) if (ret < 0) return ret; - DRM_INFO("Have %d conector(s)\n", cfg->num_connectors); + DRM_INFO("Have %d connector(s)\n", cfg->num_connectors); /* Create event channels for all connectors and publish */ ret = xen_drm_front_evtchnl_create_all(front_info); if (ret < 0)
Re: [PATCH v3 4/6] ALSA: xen-front: Implement handling of shared buffers
On 05/15/2018 09:01 AM, Takashi Iwai wrote: On Tue, 15 May 2018 07:46:38 +0200, Oleksandr Andrushchenko wrote: On 05/14/2018 11:28 PM, Takashi Iwai wrote: On Mon, 14 May 2018 08:27:40 +0200, Oleksandr Andrushchenko wrote: --- /dev/null +++ b/sound/xen/xen_snd_front_shbuf.c @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT + +/* + * Xen para-virtual sound device + * + * Copyright (C) 2016-2018 EPAM Systems Inc. + * + * Author: Oleksandr Andrushchenko + */ + +#include +#include + +#include "xen_snd_front_shbuf.h" Hm, with the local build test, I get the following error: CC [M] sound/xen/xen_snd_front_shbuf.o In file included from sound/xen/xen_snd_front_shbuf.c:11:0: ./include/xen/xen.h:18:8: error: unknown type name ‘bool’ extern bool xen_pvh; ^~~~ In file included from ./include/xen/interface/xen.h:30:0, from ./include/xen/xen.h:29, from sound/xen/xen_snd_front_shbuf.c:11: ./arch/x86/include/asm/xen/interface.h:92:21: error: unknown type name ‘uint64_t’ DEFINE_GUEST_HANDLE(uint64_t); ^ Adding #include fixed the issue. Did you really test your patches with the latest Linus tree? My bad, it does build for ARM (which is my target), but also does need "#include " for x86 which I didn't build this time. Sorry about that. Do you want me to resend this single patch or you can make the change while applying? Yes, it's fine. Thank you thanks, Takashi
Re: [PATCH v3 4/6] ALSA: xen-front: Implement handling of shared buffers
On 05/14/2018 11:28 PM, Takashi Iwai wrote: On Mon, 14 May 2018 08:27:40 +0200, Oleksandr Andrushchenko wrote: --- /dev/null +++ b/sound/xen/xen_snd_front_shbuf.c @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT + +/* + * Xen para-virtual sound device + * + * Copyright (C) 2016-2018 EPAM Systems Inc. + * + * Author: Oleksandr Andrushchenko + */ + +#include +#include + +#include "xen_snd_front_shbuf.h" Hm, with the local build test, I get the following error: CC [M] sound/xen/xen_snd_front_shbuf.o In file included from sound/xen/xen_snd_front_shbuf.c:11:0: ./include/xen/xen.h:18:8: error: unknown type name ‘bool’ extern bool xen_pvh; ^~~~ In file included from ./include/xen/interface/xen.h:30:0, from ./include/xen/xen.h:29, from sound/xen/xen_snd_front_shbuf.c:11: ./arch/x86/include/asm/xen/interface.h:92:21: error: unknown type name ‘uint64_t’ DEFINE_GUEST_HANDLE(uint64_t); ^ Adding #include fixed the issue. Did you really test your patches with the latest Linus tree? My bad, it does build for ARM (which is my target), but also does need "#include " for x86 which I didn't build this time. Sorry about that. Do you want me to resend this single patch or you can make the change while applying? thanks, Takashi Thank you, Oleksandr
Re: [alsa-devel] [PATCH v3 0/6] ALSA: xen-front: Add Xen para-virtualized frontend driver
On 05/14/2018 06:52 PM, Takashi Iwai wrote: On Mon, 14 May 2018 08:27:36 +0200, Oleksandr Andrushchenko wrote: From: Oleksandr Andrushchenko Please note: this patch series depends on [3]. This patch series adds support for Xen [1] para-virtualized sound frontend driver. It implements the protocol from include/xen/interface/io/sndif.h with the following limitations: - mute/unmute is not supported - get/set volume is not supported Volume control is not supported for the reason that most of the use-cases (at the moment) are based on scenarious where unprivileged OS (e.g. Android, AGL etc) use software mixers. Both capture and playback are supported. Corresponding backend, implemented as a user-space application, can be found at [2]. Through a quick glance, all look OK for merge (assuming that they really work on your systems :) Well, we have tested this at EPAM on Android/Linux, so this is it for now Of course, it'd be great if anyone else can review, test and give reviewed-by or tested-by tags. I hope Juergen and Boris can review, at least Juergen had some comments that I have addressed in v3 So I'll keep this floating for a couple of days and merge to for-next branch after that. Oh, this is great news! Thank you thanks, Takashi
[PATCH v3 2/2] Input: xen-kbdfront - allow better run-time configuration
From: Oleksandr Andrushchenko It is now only possible to control if multi-touch virtual device is created or not (via the corresponding XenStore entries), but keyboard and pointer devices are always created. In some cases this is not desirable. For example, if virtual keyboard device is exposed to Android then the latter won't automatically show on-screen keyboard as it expects that a physical keyboard device can be used for typing. Utilize keyboard and pointer device XenStore feature fields to configure which virtual devices are created: - set "feature-disable-keyboard" to 1 if no keyboard device needs to be created - set "feature-disable-pointer" to 1 if no pointer device needs to be created Keep old behavior by default. Signed-off-by: Oleksandr Andrushchenko Suggested-by: Andrii Chepurnyi Tested-by: Andrii Chepurnyi --- Changes since v2: - based on XenStore kbdif features to control which devices are exposed instead of module parameters. drivers/input/misc/xen-kbdfront.c | 172 ++ 1 file changed, 101 insertions(+), 71 deletions(-) diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index d91f3b1c5375..0f166e11c421 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c @@ -63,6 +63,9 @@ static void xenkbd_disconnect_backend(struct xenkbd_info *); static void xenkbd_handle_motion_event(struct xenkbd_info *info, struct xenkbd_motion *motion) { + if (unlikely(!info->ptr)) + return; + input_report_rel(info->ptr, REL_X, motion->rel_x); input_report_rel(info->ptr, REL_Y, motion->rel_y); if (motion->rel_z) @@ -73,6 +76,9 @@ static void xenkbd_handle_motion_event(struct xenkbd_info *info, static void xenkbd_handle_position_event(struct xenkbd_info *info, struct xenkbd_position *pos) { + if (unlikely(!info->ptr)) + return; + input_report_abs(info->ptr, ABS_X, pos->abs_x); input_report_abs(info->ptr, ABS_Y, pos->abs_y); if (pos->rel_z) @@ -97,6 +103,9 @@ static void xenkbd_handle_key_event(struct xenkbd_info *info, return; } + if (unlikely(!dev)) + return; + input_event(dev, EV_KEY, key->keycode, value); input_sync(dev); } @@ -192,7 +201,7 @@ static int xenkbd_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { int ret, i; - unsigned int abs, touch; + bool with_mtouch, with_kbd, with_ptr; struct xenkbd_info *info; struct input_dev *kbd, *ptr, *mtouch; @@ -211,93 +220,114 @@ static int xenkbd_probe(struct xenbus_device *dev, if (!info->page) goto error_nomem; - /* Set input abs params to match backend screen res */ - abs = xenbus_read_unsigned(dev->otherend, - XENKBD_FIELD_FEAT_ABS_POINTER, 0); - ptr_size[KPARAM_X] = xenbus_read_unsigned(dev->otherend, - XENKBD_FIELD_WIDTH, - ptr_size[KPARAM_X]); - ptr_size[KPARAM_Y] = xenbus_read_unsigned(dev->otherend, - XENKBD_FIELD_HEIGHT, - ptr_size[KPARAM_Y]); - if (abs) { - ret = xenbus_write(XBT_NIL, dev->nodename, - XENKBD_FIELD_REQ_ABS_POINTER, "1"); - if (ret) { - pr_warn("xenkbd: can't request abs-pointer\n"); - abs = 0; - } - } + /* +* The below are reverse logic, e.g. if the feature is set, then +* do not expose the corresponding virtual device. +*/ + with_kbd = !xenbus_read_unsigned(dev->nodename, +XENKBD_FIELD_FEAT_DSBL_KEYBRD, 0); - touch = xenbus_read_unsigned(dev->nodename, -XENKBD_FIELD_FEAT_MTOUCH, 0); - if (touch) { + with_ptr = !xenbus_read_unsigned(dev->nodename, +XENKBD_FIELD_FEAT_DSBL_POINTER, 0); + + /* Direct logic: if set, then create multi-touch device. */ + with_mtouch = xenbus_read_unsigned(dev->nodename, + XENKBD_FIELD_FEAT_MTOUCH, 0); + if (with_mtouch) { ret = xenbus_write(XBT_NIL, dev->nodename, XENKBD_FIELD_REQ_MTOUCH, "1"); if (ret) { pr_warn("xenkbd: can't request multi-touch"); - touch = 0; + with_mtouch = 0
[PATCH v3 1/2] xen/kbdif: Sync up with the canonical definition in Xen
From: Oleksandr Andrushchenko This is the sync up with the canonical definition of the keyboard protocol in Xen: 1. Add missing string constants for {feature|request}-raw-pointer to align with the rest of the interface file. 2. Add new XenStore feature fields, so it is possible to individually control set of exposed virtual devices for each guest OS: - set feature-disable-keyboard to 1 if no keyboard device needs to be created - set feature-disable-pointer to 1 if no pointer device needs to be created Signed-off-by: Oleksandr Andrushchenko Cc: Konrad Rzeszutek Wilk --- include/xen/interface/io/kbdif.h | 30 ++ 1 file changed, 30 insertions(+) diff --git a/include/xen/interface/io/kbdif.h b/include/xen/interface/io/kbdif.h index 2a9510ade701..808ef7d02a65 100644 --- a/include/xen/interface/io/kbdif.h +++ b/include/xen/interface/io/kbdif.h @@ -51,6 +51,18 @@ * corresponding entries in XenStore and puts 1 as the value of the entry. * If a feature is not supported then 0 must be set or feature entry omitted. * + * feature-disable-keyboard + * Values: + * + * If there is no need to expose a virtual keyboard device by the + * frontend then this must be set to 1. + * + * feature-disable-pointer + * Values: + * + * If there is no need to expose a virtual pointer device by the + * frontend then this must be set to 1. + * * feature-abs-pointer * Values: * @@ -63,6 +75,13 @@ * Backends, which support reporting of multi-touch events * should set this to 1. * + * feature-raw-pointer + * Values: + * + * Backends, which support reporting raw (unscaled) absolute coordinates + * for pointer devices should set this to 1. Raw (unscaled) values have + * a range of [0, 0x7fff]. + * *- Pointer Device Parameters * * width @@ -98,6 +117,13 @@ * * Request backend to report multi-touch events. * + * request-raw-pointer + * Values: + * + * Request backend to report raw unscaled absolute pointer coordinates. + * This option is only valid if request-abs-pointer is also set. + * Raw unscaled coordinates have the range [0, 0x7fff] + * *--- Request Transport Parameters --- * * event-channel @@ -163,9 +189,13 @@ #define XENKBD_DRIVER_NAME "vkbd" +#define XENKBD_FIELD_FEAT_DSBL_KEYBRD "feature-disable-keyboard" +#define XENKBD_FIELD_FEAT_DSBL_POINTER "feature-disable-pointer" #define XENKBD_FIELD_FEAT_ABS_POINTER "feature-abs-pointer" +#define XENKBD_FIELD_FEAT_RAW_POINTER "feature-raw-pointer" #define XENKBD_FIELD_FEAT_MTOUCH "feature-multi-touch" #define XENKBD_FIELD_REQ_ABS_POINTER "request-abs-pointer" +#define XENKBD_FIELD_REQ_RAW_POINTER "request-raw-pointer" #define XENKBD_FIELD_REQ_MTOUCH"request-multi-touch" #define XENKBD_FIELD_RING_GREF "page-gref" #define XENKBD_FIELD_EVT_CHANNEL "event-channel" -- 2.17.0
[PATCH v3 3/6] ALSA: xen-front: Implement Xen event channel handling
From: Oleksandr Andrushchenko Handle Xen event channels: - create for all configured streams and publish corresponding ring references and event channels in Xen store, so backend can connect - implement event channels interrupt handlers - create and destroy event channels with respect to Xen bus state Signed-off-by: Oleksandr Andrushchenko --- sound/xen/Makefile| 3 +- sound/xen/xen_snd_front.c | 9 +- sound/xen/xen_snd_front.h | 5 + sound/xen/xen_snd_front_evtchnl.c | 494 ++ sound/xen/xen_snd_front_evtchnl.h | 95 ++ 5 files changed, 604 insertions(+), 2 deletions(-) create mode 100644 sound/xen/xen_snd_front_evtchnl.c create mode 100644 sound/xen/xen_snd_front_evtchnl.h diff --git a/sound/xen/Makefile b/sound/xen/Makefile index 06705bef61fa..03c669984000 100644 --- a/sound/xen/Makefile +++ b/sound/xen/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 OR MIT snd_xen_front-objs := xen_snd_front.o \ - xen_snd_front_cfg.o + xen_snd_front_cfg.o \ + xen_snd_front_evtchnl.o obj-$(CONFIG_SND_XEN_FRONTEND) += snd_xen_front.o diff --git a/sound/xen/xen_snd_front.c b/sound/xen/xen_snd_front.c index 70fa91683c71..277214d4fd0a 100644 --- a/sound/xen/xen_snd_front.c +++ b/sound/xen/xen_snd_front.c @@ -18,9 +18,11 @@ #include #include "xen_snd_front.h" +#include "xen_snd_front_evtchnl.h" static void xen_snd_drv_fini(struct xen_snd_front_info *front_info) { + xen_snd_front_evtchnl_free_all(front_info); } static int sndback_initwait(struct xen_snd_front_info *front_info) @@ -32,7 +34,12 @@ static int sndback_initwait(struct xen_snd_front_info *front_info) if (ret < 0) return ret; - return 0; + /* create event channels for all streams and publish */ + ret = xen_snd_front_evtchnl_create_all(front_info, num_streams); + if (ret < 0) + return ret; + + return xen_snd_front_evtchnl_publish_all(front_info); } static int sndback_connect(struct xen_snd_front_info *front_info) diff --git a/sound/xen/xen_snd_front.h b/sound/xen/xen_snd_front.h index b52226cb30bc..9d0c92100c7b 100644 --- a/sound/xen/xen_snd_front.h +++ b/sound/xen/xen_snd_front.h @@ -13,9 +13,14 @@ #include "xen_snd_front_cfg.h" +struct xen_snd_front_evtchnl_pair; + struct xen_snd_front_info { struct xenbus_device *xb_dev; + int num_evt_pairs; + struct xen_snd_front_evtchnl_pair *evt_pairs; + struct xen_front_cfg_card cfg; }; diff --git a/sound/xen/xen_snd_front_evtchnl.c b/sound/xen/xen_snd_front_evtchnl.c new file mode 100644 index ..1faafff08807 --- /dev/null +++ b/sound/xen/xen_snd_front_evtchnl.c @@ -0,0 +1,494 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT + +/* + * Xen para-virtual sound device + * + * Copyright (C) 2016-2018 EPAM Systems Inc. + * + * Author: Oleksandr Andrushchenko + */ + +#include +#include +#include +#include + +#include "xen_snd_front.h" +#include "xen_snd_front_cfg.h" +#include "xen_snd_front_evtchnl.h" + +static irqreturn_t evtchnl_interrupt_req(int irq, void *dev_id) +{ + struct xen_snd_front_evtchnl *channel = dev_id; + struct xen_snd_front_info *front_info = channel->front_info; + struct xensnd_resp *resp; + RING_IDX i, rp; + + if (unlikely(channel->state != EVTCHNL_STATE_CONNECTED)) + return IRQ_HANDLED; + + mutex_lock(&channel->ring_io_lock); + +again: + rp = channel->u.req.ring.sring->rsp_prod; + /* Ensure we see queued responses up to rp. */ + rmb(); + + /* +* Assume that the backend is trusted to always write sane values +* to the ring counters, so no overflow checks on frontend side +* are required. +*/ + for (i = channel->u.req.ring.rsp_cons; i != rp; i++) { + resp = RING_GET_RESPONSE(&channel->u.req.ring, i); + if (resp->id != channel->evt_id) + continue; + switch (resp->operation) { + case XENSND_OP_OPEN: + /* fall through */ + case XENSND_OP_CLOSE: + /* fall through */ + case XENSND_OP_READ: + /* fall through */ + case XENSND_OP_WRITE: + /* fall through */ + case XENSND_OP_TRIGGER: + channel->u.req.resp_status = resp->status; + complete(&channel->u.req.completion); + break; + case XENSND_OP_HW_PARAM_QUERY: + channel->u.req.resp_status = resp->status; + channel->u.req.resp.hw_param = +
[PATCH v3 1/6] ALSA: xen-front: Introduce Xen para-virtualized sound frontend driver
From: Oleksandr Andrushchenko Introduce skeleton of the para-virtualized Xen sound frontend driver. Initial handling for Xen bus states: implement Xen bus state machine for the frontend driver according to the state diagram and recovery flow from sound para-virtualized protocol: xen/interface/io/sndif.h. Signed-off-by: Oleksandr Andrushchenko Reviewed-by: Juergen Gross --- sound/Kconfig | 2 + sound/Makefile| 2 +- sound/xen/Kconfig | 10 ++ sound/xen/Makefile| 5 + sound/xen/xen_snd_front.c | 196 ++ sound/xen/xen_snd_front.h | 18 6 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 sound/xen/Kconfig create mode 100644 sound/xen/Makefile create mode 100644 sound/xen/xen_snd_front.c create mode 100644 sound/xen/xen_snd_front.h diff --git a/sound/Kconfig b/sound/Kconfig index 6833db9002ec..1140e9988fc5 100644 --- a/sound/Kconfig +++ b/sound/Kconfig @@ -96,6 +96,8 @@ source "sound/x86/Kconfig" source "sound/synth/Kconfig" +source "sound/xen/Kconfig" + endif # SND endif # !UML diff --git a/sound/Makefile b/sound/Makefile index 99d8c31262c8..797ecdcd35e2 100644 --- a/sound/Makefile +++ b/sound/Makefile @@ -5,7 +5,7 @@ obj-$(CONFIG_SOUND) += soundcore.o obj-$(CONFIG_DMASOUND) += oss/dmasound/ obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \ - firewire/ sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/ hda/ x86/ + firewire/ sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/ hda/ x86/ xen/ obj-$(CONFIG_SND_AOA) += aoa/ # This one must be compilable even if sound is configured out diff --git a/sound/xen/Kconfig b/sound/xen/Kconfig new file mode 100644 index ..4f1fceea82d2 --- /dev/null +++ b/sound/xen/Kconfig @@ -0,0 +1,10 @@ +# ALSA Xen drivers + +config SND_XEN_FRONTEND + tristate "Xen para-virtualized sound frontend driver" + depends on XEN + select SND_PCM + select XEN_XENBUS_FRONTEND + help + Choose this option if you want to enable a para-virtualized + frontend sound driver for Xen guest OSes. diff --git a/sound/xen/Makefile b/sound/xen/Makefile new file mode 100644 index ..4507ef3c27fd --- /dev/null +++ b/sound/xen/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 OR MIT + +snd_xen_front-objs := xen_snd_front.o + +obj-$(CONFIG_SND_XEN_FRONTEND) += snd_xen_front.o diff --git a/sound/xen/xen_snd_front.c b/sound/xen/xen_snd_front.c new file mode 100644 index ..bbbe2767b565 --- /dev/null +++ b/sound/xen/xen_snd_front.c @@ -0,0 +1,196 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT + +/* + * Xen para-virtual sound device + * + * Copyright (C) 2016-2018 EPAM Systems Inc. + * + * Author: Oleksandr Andrushchenko + */ + +#include +#include + +#include +#include +#include + +#include + +#include "xen_snd_front.h" + +static void xen_snd_drv_fini(struct xen_snd_front_info *front_info) +{ +} + +static int sndback_initwait(struct xen_snd_front_info *front_info) +{ + return 0; +} + +static int sndback_connect(struct xen_snd_front_info *front_info) +{ + return 0; +} + +static void sndback_disconnect(struct xen_snd_front_info *front_info) +{ + xen_snd_drv_fini(front_info); + xenbus_switch_state(front_info->xb_dev, XenbusStateInitialising); +} + +static void sndback_changed(struct xenbus_device *xb_dev, + enum xenbus_state backend_state) +{ + struct xen_snd_front_info *front_info = dev_get_drvdata(&xb_dev->dev); + int ret; + + dev_dbg(&xb_dev->dev, "Backend state is %s, front is %s\n", + xenbus_strstate(backend_state), + xenbus_strstate(xb_dev->state)); + + switch (backend_state) { + case XenbusStateReconfiguring: + /* fall through */ + case XenbusStateReconfigured: + /* fall through */ + case XenbusStateInitialised: + /* fall through */ + break; + + case XenbusStateInitialising: + /* Recovering after backend unexpected closure. */ + sndback_disconnect(front_info); + break; + + case XenbusStateInitWait: + /* Recovering after backend unexpected closure. */ + sndback_disconnect(front_info); + + ret = sndback_initwait(front_info); + if (ret < 0) + xenbus_dev_fatal(xb_dev, ret, "initializing frontend"); + else + xenbus_switch_state(xb_dev, XenbusStateInitialised); + break; + + case XenbusStateConnected: + if (xb_dev->state != XenbusStateInitialised) + break; + + ret = sndback_connect(front_info); + if (ret < 0) +
[PATCH v3 5/6] ALSA: xen-front: Implement ALSA virtual sound driver
From: Oleksandr Andrushchenko Implement essential initialization of the sound driver: - introduce required data structures - handle driver registration - handle sound card registration - register sound driver on backend connection - remove sound driver on backend disconnect Initialize virtual sound card with streams according to the Xen store configuration. Implement ALSA driver operations including: - manage frontend/backend shared buffers - manage Xen bus event channel states Implement requests from front to back for ALSA PCM operations. - report ALSA period elapsed event: handle XENSND_EVT_CUR_POS notifications from the backend when stream position advances during playback/capture. The event carries a value of how many octets were played/captured at the time of the event. - implement explicit stream parameter negotiation between backend and frontend: handle XENSND_OP_HW_PARAM_QUERY request to read/update configuration space for the parameter given: request passes desired parameter interval and the response to this request returns min/max interval for the parameter to be used. Signed-off-by: Oleksandr Andrushchenko --- sound/xen/Makefile| 3 +- sound/xen/xen_snd_front.c | 181 ++- sound/xen/xen_snd_front.h | 27 + sound/xen/xen_snd_front_alsa.c| 821 ++ sound/xen/xen_snd_front_alsa.h| 23 + sound/xen/xen_snd_front_evtchnl.c | 4 +- 6 files changed, 1056 insertions(+), 3 deletions(-) create mode 100644 sound/xen/xen_snd_front_alsa.c create mode 100644 sound/xen/xen_snd_front_alsa.h diff --git a/sound/xen/Makefile b/sound/xen/Makefile index f028bc30af5d..1e6470ecc2f2 100644 --- a/sound/xen/Makefile +++ b/sound/xen/Makefile @@ -3,6 +3,7 @@ snd_xen_front-objs := xen_snd_front.o \ xen_snd_front_cfg.o \ xen_snd_front_evtchnl.o \ - xen_snd_front_shbuf.o + xen_snd_front_shbuf.o \ + xen_snd_front_alsa.o obj-$(CONFIG_SND_XEN_FRONTEND) += snd_xen_front.o diff --git a/sound/xen/xen_snd_front.c b/sound/xen/xen_snd_front.c index cdf66ea516c4..c18973a9bc9b 100644 --- a/sound/xen/xen_snd_front.c +++ b/sound/xen/xen_snd_front.c @@ -19,10 +19,189 @@ #include #include "xen_snd_front.h" +#include "xen_snd_front_alsa.h" #include "xen_snd_front_evtchnl.h" +#include "xen_snd_front_shbuf.h" + +static struct xensnd_req * +be_stream_prepare_req(struct xen_snd_front_evtchnl *evtchnl, u8 operation) +{ + struct xensnd_req *req; + + req = RING_GET_REQUEST(&evtchnl->u.req.ring, + evtchnl->u.req.ring.req_prod_pvt); + req->operation = operation; + req->id = evtchnl->evt_next_id++; + evtchnl->evt_id = req->id; + return req; +} + +static int be_stream_do_io(struct xen_snd_front_evtchnl *evtchnl) +{ + if (unlikely(evtchnl->state != EVTCHNL_STATE_CONNECTED)) + return -EIO; + + reinit_completion(&evtchnl->u.req.completion); + xen_snd_front_evtchnl_flush(evtchnl); + return 0; +} + +static int be_stream_wait_io(struct xen_snd_front_evtchnl *evtchnl) +{ + if (wait_for_completion_timeout(&evtchnl->u.req.completion, + msecs_to_jiffies(VSND_WAIT_BACK_MS)) <= 0) + return -ETIMEDOUT; + + return evtchnl->u.req.resp_status; +} + +int xen_snd_front_stream_query_hw_param(struct xen_snd_front_evtchnl *evtchnl, + struct xensnd_query_hw_param *hw_param_req, + struct xensnd_query_hw_param *hw_param_resp) +{ + struct xensnd_req *req; + int ret; + + mutex_lock(&evtchnl->u.req.req_io_lock); + + mutex_lock(&evtchnl->ring_io_lock); + req = be_stream_prepare_req(evtchnl, XENSND_OP_HW_PARAM_QUERY); + req->op.hw_param = *hw_param_req; + mutex_unlock(&evtchnl->ring_io_lock); + + ret = be_stream_do_io(evtchnl); + + if (ret == 0) + ret = be_stream_wait_io(evtchnl); + + if (ret == 0) + *hw_param_resp = evtchnl->u.req.resp.hw_param; + + mutex_unlock(&evtchnl->u.req.req_io_lock); + return ret; +} + +int xen_snd_front_stream_prepare(struct xen_snd_front_evtchnl *evtchnl, +struct xen_snd_front_shbuf *sh_buf, +u8 format, unsigned int channels, +unsigned int rate, u32 buffer_sz, +u32 period_sz) +{ + struct xensnd_req *req; + int ret; + + mutex_lock(&evtchnl->u.req.req_io_lock); + + mutex_lock(&evtchnl->ring_io_lock); + req = be_stream_prepare_req(evtchnl, XENSND_OP_OPEN); + req->op.open.pcm_format = format;
[PATCH v3 2/6] ALSA: xen-front: Read sound driver configuration from Xen store
From: Oleksandr Andrushchenko Read configuration values from Xen store according to xen/interface/io/sndif.h protocol: - introduce configuration structures for different components, e.g. sound card, device, stream - read PCM HW parameters, e.g rate, format etc. - detect stream type (capture/playback) - read device and card parameters Signed-off-by: Oleksandr Andrushchenko --- sound/xen/Makefile| 3 +- sound/xen/xen_snd_front.c | 7 + sound/xen/xen_snd_front.h | 4 + sound/xen/xen_snd_front_cfg.c | 517 ++ sound/xen/xen_snd_front_cfg.h | 46 +++ 5 files changed, 576 insertions(+), 1 deletion(-) create mode 100644 sound/xen/xen_snd_front_cfg.c create mode 100644 sound/xen/xen_snd_front_cfg.h diff --git a/sound/xen/Makefile b/sound/xen/Makefile index 4507ef3c27fd..06705bef61fa 100644 --- a/sound/xen/Makefile +++ b/sound/xen/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 OR MIT -snd_xen_front-objs := xen_snd_front.o +snd_xen_front-objs := xen_snd_front.o \ + xen_snd_front_cfg.o obj-$(CONFIG_SND_XEN_FRONTEND) += snd_xen_front.o diff --git a/sound/xen/xen_snd_front.c b/sound/xen/xen_snd_front.c index bbbe2767b565..70fa91683c71 100644 --- a/sound/xen/xen_snd_front.c +++ b/sound/xen/xen_snd_front.c @@ -25,6 +25,13 @@ static void xen_snd_drv_fini(struct xen_snd_front_info *front_info) static int sndback_initwait(struct xen_snd_front_info *front_info) { + int num_streams; + int ret; + + ret = xen_snd_front_cfg_card(front_info, &num_streams); + if (ret < 0) + return ret; + return 0; } diff --git a/sound/xen/xen_snd_front.h b/sound/xen/xen_snd_front.h index 4ae204b23d32..b52226cb30bc 100644 --- a/sound/xen/xen_snd_front.h +++ b/sound/xen/xen_snd_front.h @@ -11,8 +11,12 @@ #ifndef __XEN_SND_FRONT_H #define __XEN_SND_FRONT_H +#include "xen_snd_front_cfg.h" + struct xen_snd_front_info { struct xenbus_device *xb_dev; + + struct xen_front_cfg_card cfg; }; #endif /* __XEN_SND_FRONT_H */ diff --git a/sound/xen/xen_snd_front_cfg.c b/sound/xen/xen_snd_front_cfg.c new file mode 100644 index ..38c7e1eefbb9 --- /dev/null +++ b/sound/xen/xen_snd_front_cfg.c @@ -0,0 +1,517 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT + +/* + * Xen para-virtual sound device + * + * Copyright (C) 2016-2018 EPAM Systems Inc. + * + * Author: Oleksandr Andrushchenko + */ + +#include + +#include + +#include "xen_snd_front.h" +#include "xen_snd_front_cfg.h" + +/* Maximum number of supported streams. */ +#define VSND_MAX_STREAM8 + +struct cfg_hw_sample_rate { + const char *name; + unsigned int mask; + unsigned int value; +}; + +static const struct cfg_hw_sample_rate CFG_HW_SUPPORTED_RATES[] = { + { .name = "5512", .mask = SNDRV_PCM_RATE_5512, .value = 5512 }, + { .name = "8000", .mask = SNDRV_PCM_RATE_8000, .value = 8000 }, + { .name = "11025", .mask = SNDRV_PCM_RATE_11025, .value = 11025 }, + { .name = "16000", .mask = SNDRV_PCM_RATE_16000, .value = 16000 }, + { .name = "22050", .mask = SNDRV_PCM_RATE_22050, .value = 22050 }, + { .name = "32000", .mask = SNDRV_PCM_RATE_32000, .value = 32000 }, + { .name = "44100", .mask = SNDRV_PCM_RATE_44100, .value = 44100 }, + { .name = "48000", .mask = SNDRV_PCM_RATE_48000, .value = 48000 }, + { .name = "64000", .mask = SNDRV_PCM_RATE_64000, .value = 64000 }, + { .name = "96000", .mask = SNDRV_PCM_RATE_96000, .value = 96000 }, + { .name = "176400", .mask = SNDRV_PCM_RATE_176400, .value = 176400 }, + { .name = "192000", .mask = SNDRV_PCM_RATE_192000, .value = 192000 }, +}; + +struct cfg_hw_sample_format { + const char *name; + u64 mask; +}; + +static const struct cfg_hw_sample_format CFG_HW_SUPPORTED_FORMATS[] = { + { + .name = XENSND_PCM_FORMAT_U8_STR, + .mask = SNDRV_PCM_FMTBIT_U8 + }, + { + .name = XENSND_PCM_FORMAT_S8_STR, + .mask = SNDRV_PCM_FMTBIT_S8 + }, + { + .name = XENSND_PCM_FORMAT_U16_LE_STR, + .mask = SNDRV_PCM_FMTBIT_U16_LE + }, + { + .name = XENSND_PCM_FORMAT_U16_BE_STR, + .mask = SNDRV_PCM_FMTBIT_U16_BE + }, + { + .name = XENSND_PCM_FORMAT_S16_LE_STR, + .mask = SNDRV_PCM_FMTBIT_S16_LE + }, + { + .name = XENSND_PCM_FORMAT_S16_BE_STR, + .mask = SNDRV_PCM_FMTBIT_S16_BE + }, + { + .name = XENSND_PCM_FORMAT_U24_LE_STR, + .mask = SNDRV_PCM_FMTBIT_U24_LE + }, + { + .name = XENSND_PCM_FORMAT
[PATCH v3 6/6] MAINTAINERS: Add ALSA: xen-front: maintainer entry
From: Oleksandr Andrushchenko Add myself as sound/xen maintainer. Signed-off-by: Oleksandr Andrushchenko --- MAINTAINERS | 7 +++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 92be777d060a..bd214e061359 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15494,6 +15494,13 @@ S: Supported F: arch/x86/xen/*swiotlb* F: drivers/xen/*swiotlb* +XEN SOUND FRONTEND DRIVER +M: Oleksandr Andrushchenko +L: xen-de...@lists.xenproject.org (moderated for non-subscribers) +L: alsa-de...@alsa-project.org (moderated for non-subscribers) +S: Supported +F: sound/xen/* + XFS FILESYSTEM M: Darrick J. Wong M: linux-...@vger.kernel.org -- 2.17.0
[PATCH v3 4/6] ALSA: xen-front: Implement handling of shared buffers
From: Oleksandr Andrushchenko Implement shared buffer handling according to the para-virtualized sound device protocol at xen/interface/io/sndif.h: - manage buffer memory - handle granted references - handle page directories Signed-off-by: Oleksandr Andrushchenko --- sound/xen/Makefile | 3 +- sound/xen/xen_snd_front.c | 8 ++ sound/xen/xen_snd_front_shbuf.c | 193 sound/xen/xen_snd_front_shbuf.h | 36 ++ 4 files changed, 239 insertions(+), 1 deletion(-) create mode 100644 sound/xen/xen_snd_front_shbuf.c create mode 100644 sound/xen/xen_snd_front_shbuf.h diff --git a/sound/xen/Makefile b/sound/xen/Makefile index 03c669984000..f028bc30af5d 100644 --- a/sound/xen/Makefile +++ b/sound/xen/Makefile @@ -2,6 +2,7 @@ snd_xen_front-objs := xen_snd_front.o \ xen_snd_front_cfg.o \ - xen_snd_front_evtchnl.o + xen_snd_front_evtchnl.o \ + xen_snd_front_shbuf.o obj-$(CONFIG_SND_XEN_FRONTEND) += snd_xen_front.o diff --git a/sound/xen/xen_snd_front.c b/sound/xen/xen_snd_front.c index 277214d4fd0a..cdf66ea516c4 100644 --- a/sound/xen/xen_snd_front.c +++ b/sound/xen/xen_snd_front.c @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -191,6 +192,13 @@ static int __init xen_drv_init(void) if (!xen_has_pv_devices()) return -ENODEV; + /* At the moment we only support case with XEN_PAGE_SIZE == PAGE_SIZE */ + if (XEN_PAGE_SIZE != PAGE_SIZE) { + pr_err(XENSND_DRIVER_NAME ": different kernel and Xen page sizes are not supported: XEN_PAGE_SIZE (%lu) != PAGE_SIZE (%lu)\n", + XEN_PAGE_SIZE, PAGE_SIZE); + return -ENODEV; + } + pr_info("Initialising Xen " XENSND_DRIVER_NAME " frontend driver\n"); return xenbus_register_frontend(&xen_driver); } diff --git a/sound/xen/xen_snd_front_shbuf.c b/sound/xen/xen_snd_front_shbuf.c new file mode 100644 index ..6845dbc7fdf5 --- /dev/null +++ b/sound/xen/xen_snd_front_shbuf.c @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT + +/* + * Xen para-virtual sound device + * + * Copyright (C) 2016-2018 EPAM Systems Inc. + * + * Author: Oleksandr Andrushchenko + */ + +#include +#include + +#include "xen_snd_front_shbuf.h" + +grant_ref_t xen_snd_front_shbuf_get_dir_start(struct xen_snd_front_shbuf *buf) +{ + if (!buf->grefs) + return GRANT_INVALID_REF; + + return buf->grefs[0]; +} + +void xen_snd_front_shbuf_clear(struct xen_snd_front_shbuf *buf) +{ + memset(buf, 0, sizeof(*buf)); +} + +void xen_snd_front_shbuf_free(struct xen_snd_front_shbuf *buf) +{ + int i; + + if (buf->grefs) { + for (i = 0; i < buf->num_grefs; i++) + if (buf->grefs[i] != GRANT_INVALID_REF) + gnttab_end_foreign_access(buf->grefs[i], + 0, 0UL); + kfree(buf->grefs); + } + kfree(buf->directory); + free_pages_exact(buf->buffer, buf->buffer_sz); + xen_snd_front_shbuf_clear(buf); +} + +/* + * number of grant references a page can hold with respect to the + * xensnd_page_directory header + */ +#define XENSND_NUM_GREFS_PER_PAGE ((XEN_PAGE_SIZE - \ + offsetof(struct xensnd_page_directory, gref)) / \ + sizeof(grant_ref_t)) + +static void fill_page_dir(struct xen_snd_front_shbuf *buf, + int num_pages_dir) +{ + struct xensnd_page_directory *page_dir; + unsigned char *ptr; + int i, cur_gref, grefs_left, to_copy; + + ptr = buf->directory; + grefs_left = buf->num_grefs - num_pages_dir; + /* +* skip grant references at the beginning, they are for pages granted +* for the page directory itself +*/ + cur_gref = num_pages_dir; + for (i = 0; i < num_pages_dir; i++) { + page_dir = (struct xensnd_page_directory *)ptr; + if (grefs_left <= XENSND_NUM_GREFS_PER_PAGE) { + to_copy = grefs_left; + page_dir->gref_dir_next_page = GRANT_INVALID_REF; + } else { + to_copy = XENSND_NUM_GREFS_PER_PAGE; + page_dir->gref_dir_next_page = buf->grefs[i + 1]; + } + + memcpy(&page_dir->gref, &buf->grefs[cur_gref], + to_copy * sizeof(grant_ref_t)); + + ptr += XEN_PAGE_SIZE; + grefs_left -= to_copy; + cur_gref += to_copy; + } +} + +static int grant_references(struct xenbus_device *xb_dev, + struct xen_snd_front_shbuf *buf, + int num_p
[PATCH v3 0/6] ALSA: xen-front: Add Xen para-virtualized frontend driver
From: Oleksandr Andrushchenko Please note: this patch series depends on [3]. This patch series adds support for Xen [1] para-virtualized sound frontend driver. It implements the protocol from include/xen/interface/io/sndif.h with the following limitations: - mute/unmute is not supported - get/set volume is not supported Volume control is not supported for the reason that most of the use-cases (at the moment) are based on scenarious where unprivileged OS (e.g. Android, AGL etc) use software mixers. Both capture and playback are supported. Corresponding backend, implemented as a user-space application, can be found at [2]. Thank you, Oleksandr Changes since v2: * 1. Kconfig: select SND_PCM instead of depends 2. Changed spinlock to mutex for protecting the rings since all the interrupts are threaded. Make those per event channel, not a single global one. This also addresses Juergen's comment on calling xen_snd_front_alsa_handle_cur_pos. 3. Fixed page leak on error while allocating an event channel 4. Fixed comments to start from a capital letter 5. Performed XEN_PAGE_SIZE != PAGE_SIZE check after xen_domain and xen_has_pv_devices checks 6. Changed driver specific structures names not to mislead with ALSA structs 7. Added comments on ring counters and overflows 8. Added MAINTAINERS entry Changes since v1: * 1. Moved driver from sound/drivers to sound/xen 2. Coding style changes to better meet Linux Kernel 3. Added explicit back and front synchronization In order to provide explicit synchronization between backend and frontend the following changes are introduced in the protocol: - add new ring buffer for sending asynchronous events from backend to frontend to report number of bytes played by the frontend (XENSND_EVT_CUR_POS) - introduce trigger events for playback control: start/stop/pause/resume - add "req-" prefix to event-channel and ring-ref to unify naming of the Xen event channels for requests and events 4. Added explicit back and front parameter negotiation In order to provide explicit stream parameter negotiation between backend and frontend the following changes are introduced in the protocol: add XENSND_OP_HW_PARAM_QUERY request to read/update configuration space for the parameters given: request passes desired parameter's intervals/masks and the response to this request returns allowed min/max intervals/masks to be used. [1] https://xenproject.org/ [2] https://github.com/xen-troops/snd_be [3] https://lkml.org/lkml/2018/4/12/522 Oleksandr Andrushchenko (6): ALSA: xen-front: Introduce Xen para-virtualized sound frontend driver ALSA: xen-front: Read sound driver configuration from Xen store ALSA: xen-front: Implement Xen event channel handling ALSA: xen-front: Implement handling of shared buffers ALSA: xen-front: Implement ALSA virtual sound driver MAINTAINERS: Add ALSA: xen-front: maintainer entry MAINTAINERS | 7 + sound/Kconfig | 2 + sound/Makefile| 2 +- sound/xen/Kconfig | 10 + sound/xen/Makefile| 9 + sound/xen/xen_snd_front.c | 397 +++ sound/xen/xen_snd_front.h | 54 ++ sound/xen/xen_snd_front_alsa.c| 821 ++ sound/xen/xen_snd_front_alsa.h| 23 + sound/xen/xen_snd_front_cfg.c | 517 +++ sound/xen/xen_snd_front_cfg.h | 46 ++ sound/xen/xen_snd_front_evtchnl.c | 496 ++ sound/xen/xen_snd_front_evtchnl.h | 95 sound/xen/xen_snd_front_shbuf.c | 193 +++ sound/xen/xen_snd_front_shbuf.h | 36 ++ 15 files changed, 2707 insertions(+), 1 deletion(-) create mode 100644 sound/xen/Kconfig create mode 100644 sound/xen/Makefile create mode 100644 sound/xen/xen_snd_front.c create mode 100644 sound/xen/xen_snd_front.h create mode 100644 sound/xen/xen_snd_front_alsa.c create mode 100644 sound/xen/xen_snd_front_alsa.h create mode 100644 sound/xen/xen_snd_front_cfg.c create mode 100644 sound/xen/xen_snd_front_cfg.h create mode 100644 sound/xen/xen_snd_front_evtchnl.c create mode 100644 sound/xen/xen_snd_front_evtchnl.h create mode 100644 sound/xen/xen_snd_front_shbuf.c create mode 100644 sound/xen/xen_snd_front_shbuf.h -- 2.17.0
Re: linux-next: build failure after merge of the drm-intel tree
On 05/08/2018 04:07 AM, Stephen Rothwell wrote: Hi all, After merging the drm-intel tree, today's linux-next build (x86_64 allmodconfig) failed like this: drivers/gpu/drm/xen/xen_drm_front.c: In function 'xen_drv_probe': drivers/gpu/drm/xen/xen_drm_front.c:740:10: error: 'struct bus_type' has no member named 'force_dma' dev->bus->force_dma = true; ^~ drivers/gpu/drm/xen/xen_drm_front.c:742:8: error: too few arguments to function 'of_dma_configure' ret = of_dma_configure(dev, NULL); ^~~~ In file included from drivers/gpu/drm/xen/xen_drm_front.c:16:0: include/linux/of_device.h:58:5: note: declared here int of_dma_configure(struct device *dev, ^~~~ Caused by commit c575b7eeb89f ("drm/xen-front: Add support for Xen PV display frontend") interacting with commit 3d6ce86ee794 ("drivers: remove force dma flag from buses") from the dma-mapping tree. I have added the following merge fix patch: From: Stephen Rothwell Date: Tue, 8 May 2018 11:02:24 +1000 Subject: [PATCH] drm/xen-front: merge fix for "drivers: remove force dma flag from buses" Signed-off-by: Stephen Rothwell Thank you, Reviewed-by: Oleksandr Andrushchenko --- drivers/gpu/drm/xen/xen_drm_front.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xen/xen_drm_front.c b/drivers/gpu/drm/xen/xen_drm_front.c index 1b0ea9ac330e..0e486cb1c10c 100644 --- a/drivers/gpu/drm/xen/xen_drm_front.c +++ b/drivers/gpu/drm/xen/xen_drm_front.c @@ -737,9 +737,8 @@ static int xen_drv_probe(struct xenbus_device *xb_dev, * is not correct: to fix this call of_dma_configure() with a NULL * node to set default DMA ops. */ - dev->bus->force_dma = true; dev->coherent_dma_mask = DMA_BIT_MASK(32); - ret = of_dma_configure(dev, NULL); + ret = of_dma_configure(dev, NULL, true); if (ret < 0) { DRM_ERROR("Cannot setup DMA ops, ret %d", ret); return ret; ___ dri-devel mailing list dri-de...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2 0/5] ALSA: xen-front: Add Xen para-virtualized frontend driver
Gentle reminder... I think that Xen side comments are already there and still I miss some input from ALSA community on patch #5. Thank you, Oleksandr On 04/16/2018 09:24 AM, Oleksandr Andrushchenko wrote: From: Oleksandr Andrushchenko Please note: this patch series depends on [3]. This patch series adds support for Xen [1] para-virtualized sound frontend driver. It implements the protocol from include/xen/interface/io/sndif.h with the following limitations: - mute/unmute is not supported - get/set volume is not supported Volume control is not supported for the reason that most of the use-cases (at the moment) are based on scenarious where unprivileged OS (e.g. Android, AGL etc) use software mixers. Both capture and playback are supported. Corresponding backend, implemented as a user-space application, can be found at [2]. Thank you, Oleksandr Changes since v1: * 1. Moved driver from sound/drivers to sound/xen 2. Coding style changes to better meet Linux Kernel 3. Added explicit back and front synchronization In order to provide explicit synchronization between backend and frontend the following changes are introduced in the protocol: - add new ring buffer for sending asynchronous events from backend to frontend to report number of bytes played by the frontend (XENSND_EVT_CUR_POS) - introduce trigger events for playback control: start/stop/pause/resume - add "req-" prefix to event-channel and ring-ref to unify naming of the Xen event channels for requests and events 4. Added explicit back and front parameter negotiation In order to provide explicit stream parameter negotiation between backend and frontend the following changes are introduced in the protocol: add XENSND_OP_HW_PARAM_QUERY request to read/update configuration space for the parameters given: request passes desired parameter's intervals/masks and the response to this request returns allowed min/max intervals/masks to be used. [1] https://xenproject.org/ [2] https://github.com/xen-troops/snd_be [3] https://lkml.org/lkml/2018/4/12/522 Oleksandr Andrushchenko (5): ALSA: xen-front: Introduce Xen para-virtualized sound frontend driver ALSA: xen-front: Read sound driver configuration from Xen store ALSA: xen-front: Implement Xen event channel handling ALSA: xen-front: Implement handling of shared buffers ALSA: xen-front: Implement ALSA virtual sound driver sound/Kconfig | 2 + sound/Makefile| 2 +- sound/xen/Kconfig | 10 + sound/xen/Makefile| 9 + sound/xen/xen_snd_front.c | 410 +++ sound/xen/xen_snd_front.h | 57 +++ sound/xen/xen_snd_front_alsa.c| 830 ++ sound/xen/xen_snd_front_alsa.h| 23 ++ sound/xen/xen_snd_front_cfg.c | 517 sound/xen/xen_snd_front_cfg.h | 46 +++ sound/xen/xen_snd_front_evtchnl.c | 478 ++ sound/xen/xen_snd_front_evtchnl.h | 92 + sound/xen/xen_snd_front_shbuf.c | 193 + sound/xen/xen_snd_front_shbuf.h | 36 ++ 14 files changed, 2704 insertions(+), 1 deletion(-) create mode 100644 sound/xen/Kconfig create mode 100644 sound/xen/Makefile create mode 100644 sound/xen/xen_snd_front.c create mode 100644 sound/xen/xen_snd_front.h create mode 100644 sound/xen/xen_snd_front_alsa.c create mode 100644 sound/xen/xen_snd_front_alsa.h create mode 100644 sound/xen/xen_snd_front_cfg.c create mode 100644 sound/xen/xen_snd_front_cfg.h create mode 100644 sound/xen/xen_snd_front_evtchnl.c create mode 100644 sound/xen/xen_snd_front_evtchnl.h create mode 100644 sound/xen/xen_snd_front_shbuf.c create mode 100644 sound/xen/xen_snd_front_shbuf.h
Re: [Xen-devel] [PATCH 2/6] xen-netfront: copy response out of shared buffer before accessing it
On 05/01/2018 12:01 AM, Marek Marczykowski-Górecki wrote: Make local copy of the response, otherwise backend might modify it while frontend is already processing it - leading to time of check / time of use issue. This is complementary to XSA155. Cc: sta...@vger.kernel.org Signed-off-by: Marek Marczykowski-Górecki --- drivers/net/xen-netfront.c | 51 +++ 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 4dd0668..dc99763 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -387,13 +387,13 @@ static void xennet_tx_buf_gc(struct netfront_queue *queue) rmb(); /* Ensure we see responses up to 'rp'. */ for (cons = queue->tx.rsp_cons; cons != prod; cons++) { Side comment: the original concern was expressed on the above counters, will those be addressed as a dedicated series? - struct xen_netif_tx_response *txrsp; + struct xen_netif_tx_response txrsp; - txrsp = RING_GET_RESPONSE(&queue->tx, cons); - if (txrsp->status == XEN_NETIF_RSP_NULL) + RING_COPY_RESPONSE(&queue->tx, cons, &txrsp); + if (txrsp.status == XEN_NETIF_RSP_NULL) continue; IMO, there is still no guarantee you access consistent data after this change. What if part of the response was ok when you started copying and then, in the middle, backend poisons the end of the response? This seems to be just like minimizing(?) chances to work with inconsistent data rather than removing the possibility of such completely - id = txrsp->id; + id = txrsp.id; skb = queue->tx_skbs[id].skb; if (unlikely(gnttab_query_foreign_access( queue->grant_tx_ref[id]) != 0)) { @@ -741,7 +741,7 @@ static int xennet_get_extras(struct netfront_queue *queue, RING_IDX rp) { - struct xen_netif_extra_info *extra; + struct xen_netif_extra_info extra; struct device *dev = &queue->info->netdev->dev; RING_IDX cons = queue->rx.rsp_cons; int err = 0; @@ -757,24 +757,23 @@ static int xennet_get_extras(struct netfront_queue *queue, break; } - extra = (struct xen_netif_extra_info *) - RING_GET_RESPONSE(&queue->rx, ++cons); + RING_COPY_RESPONSE(&queue->rx, ++cons, &extra); - if (unlikely(!extra->type || -extra->type >= XEN_NETIF_EXTRA_TYPE_MAX)) { + if (unlikely(!extra.type || +extra.type >= XEN_NETIF_EXTRA_TYPE_MAX)) { if (net_ratelimit()) dev_warn(dev, "Invalid extra type: %d\n", - extra->type); + extra.type); err = -EINVAL; } else { - memcpy(&extras[extra->type - 1], extra, - sizeof(*extra)); + memcpy(&extras[extra.type - 1], &extra, + sizeof(extra)); } skb = xennet_get_rx_skb(queue, cons); ref = xennet_get_rx_ref(queue, cons); xennet_move_rx_slot(queue, skb, ref); - } while (extra->flags & XEN_NETIF_EXTRA_FLAG_MORE); + } while (extra.flags & XEN_NETIF_EXTRA_FLAG_MORE); queue->rx.rsp_cons = cons; return err; @@ -784,28 +783,28 @@ static int xennet_get_responses(struct netfront_queue *queue, struct netfront_rx_info *rinfo, RING_IDX rp, struct sk_buff_head *list) { - struct xen_netif_rx_response *rx = &rinfo->rx; + struct xen_netif_rx_response rx = rinfo->rx; struct xen_netif_extra_info *extras = rinfo->extras; struct device *dev = &queue->info->netdev->dev; RING_IDX cons = queue->rx.rsp_cons; struct sk_buff *skb = xennet_get_rx_skb(queue, cons); grant_ref_t ref = xennet_get_rx_ref(queue, cons); - int max = MAX_SKB_FRAGS + (rx->status <= RX_COPY_THRESHOLD); + int max = MAX_SKB_FRAGS + (rx.status <= RX_COPY_THRESHOLD); int slots = 1; int err = 0; unsigned long ret; - if (rx->flags & XEN_NETRXF_extra_info) { + if (rx.flags & XEN_NETRXF_extra_info) { err = xennet_get_extras(queue, extras, rp); cons = queue->rx.rsp_cons; } for (;;) { - if (unlikely(rx->status < 0 || -rx->offset + rx->status > XEN_PAGE_SIZE)) { + if (unlikely(rx.status < 0 || +rx.offset + rx.status > XEN_PAGE_SIZE)) {
Re: [Xen-devel] [PATCH 0/1] drm/xen-zcopy: Add Xen zero-copy helper DRM driver
On 04/25/2018 08:16 PM, Dongwon Kim wrote: On Wed, Apr 25, 2018 at 08:34:55AM +0200, Daniel Vetter wrote: On Wed, Apr 25, 2018 at 09:07:07AM +0300, Oleksandr Andrushchenko wrote: On 04/24/2018 11:35 PM, Dongwon Kim wrote: Had a meeting with Daniel and talked about bringing out generic part of hyper-dmabuf to the userspace, which means we most likely reuse IOCTLs defined in xen-zcopy for our use-case if we follow his suggestion. I will still have kernel side API, so backends/frontends implemented in the kernel can access that functionality as well. So assuming we use these IOCTLs as they are, Several things I would like you to double-check.. 1. returning gref as is to the user space is still unsafe because it is a constant, easy to guess and any process that hijacks it can easily exploit the buffer. So I am wondering if it's possible to keep dmabuf-to -gref or gref-to-dmabuf in kernel space and add other layers on top of those in actual IOCTLs to add some safety.. We introduced flink like hyper_dmabuf_id including random number but many says even that is still not safe. Yes, it is generally unsafe. But even if we have implemented the approach you have in hyper-dmabuf or similar, what stops malicious software from doing the same with the existing gntdev UAPI? No need to brute force new UAPI if there is a simpler one. That being said, I'll put security aside at the first stage, but of course we can start investigating ways to improve (I assume you already have use-cases where security issues must be considered, so, probably you can tell more on what was investigated so far). Yeah, although we think we lowered the chance of guessing the right id by adding random number to it, the security hole is still there as far as we use a constant id across VMs. We understood this from the beginning but couldn't find a better way. So what we proposed is to make sure our customer understand this and prepare very secure way to handle this id in the userspace (mattrope however recently proposed a "hyper-pipe" which FD-type id can be converted and exchanged safely through. So we are looking into this now.) And another approach we have proposed is to use event-polling, that lets the privileged userapp in importing guest to know about a new exported DMABUF so that it can retrieve it from the queue then redistribute to other applications. This method is not very flexible however, is one way to hide ID from userspace completely. Anyway, yes, we can continue to investigate the possible way to make it more secure. Great, if you come up with something then you'll be able to plumb this in Maybe a bit more context here: So in graphics we have this old flink approach for buffer sharing with processes, and it's unsafe because way too easy to guess the buffer handles. And anyone with access to the graphics driver can then import that buffer object. We switched to file descriptor passing to make sure only the intended recipient can import a buffer. So at the vm->vm level it sounds like grefs are safe, because they're only for a specific other guest (or sets of guests, not sure about). That means security is only within the OS. For that you need to make sure that unpriviledge userspace simply can't ever access a gref. If that doesn't work out, then I guess we should improve the xen gref stuff to have a more secure cookie. 2. maybe we could take hypervisor-independent process (e.g. SGT<->page) out of xen-zcopy and put those in a new helper library. I believe this can be done, but at the first stage I would go without that helper library, so it is clearly seen what can be moved to it later (I know that you want to run ACRN as well, but can I run it on ARM? ;) There's already helpers for walking sgtables and adding pages/enumerating pages. I don't think we need more. ok, where would that helpers be located? If we consider we will use these with other hypervisor drivers, maybe it's better to place those in some common area? I am not quite sure what and if those helpers be really needed. Let's try to prototype the thing and then see what can be moved to a helper library and where it should live 3. please consider the case where original DMA-BUF's first offset and last length are not 0 and PAGE_SIZE respectively. I assume current xen-zcopy only supports page-aligned buffer with PAGE_SIZE x n big. Hm, what is the use-case for that? Just in general use-case.. I was just considering the case (might be corner case..) where sg->offset != 0 or sg->length != PAGE_SIZE. Hyper dmabuf sends this information (first offset and last length) together with references for pages. So I was wondering if we should so similar thing in zcopy since your goal is now to cover general dma-buf use-cases (however, danvet mentioned hard constaint of dma-buf below.. so if this can't happen according to the spec, then we can ignore it..) I won't be
Re: [PATCH] Input: xen-kbdfront - allow better run-time configuration
On 04/26/2018 10:16 PM, Dmitry Torokhov wrote: On Tue, Apr 24, 2018 at 08:55:19AM +0300, Oleksandr Andrushchenko wrote: On 04/23/2018 09:53 PM, Dmitry Torokhov wrote: On Thu, Apr 19, 2018 at 02:44:19PM +0300, Oleksandr Andrushchenko wrote: On 04/19/2018 02:25 PM, Juergen Gross wrote: On 18/04/18 17:04, Oleksandr Andrushchenko wrote: From: Oleksandr Andrushchenko It is now only possible to control if multi-touch virtual device is created or not (via the corresponding XenStore entries), but keyboard and pointer devices are always created. Why don't you want to go that route for keyboard and mouse, too? Or does this really make no sense? Well, I would prefer not to touch anything outside Linux and this driver. And these settings seem to be implementation specific. So, this is why introduce Linux module parameters and don't extend the kbdif protocol. Why do you consider this implementation specific? How other guests decide to forego creation of relative pointer device or keyboard-like device? You already have "features" for absolute pointing device and multitouch, so please extend the protocol properly so you indeed do not code something implementation-specific (i.e. module parameters). Ok, but in order to preserve the default behavior, e.g. pointer and keyboard devices are always created now, I'll have to have reverse features in the protocol: - feature-no-pointer - feature-no-keyboard The above may be set as a part of frontend's configuration and if missed are considered to be set to false. I think you can have them as "feature-pointer" and "feature-keyboard" (no negation), but assume not present considered enabled. I.e. kbd = xenbus_read_unsigned(..., XENKBD_FIELD_FEAT_KEYBOARD, 1); if (kbd) { ... Thank you for your comments, could you please take a look at the patch [1] where I am trying to change the corresponding Xen protocol to fit the requirements? As we agreed I have to change the protocol first, so this patch is no longer valid } Thanks. Thank you, Oleksandr [1] https://www.spinics.net/lists/linux-input/msg56094.html
Re: [PATCH v2 3/5] ALSA: xen-front: Implement Xen event channel handling
On 04/25/2018 12:02 PM, Takashi Iwai wrote: On Wed, 25 Apr 2018 10:26:34 +0200, Oleksandr Andrushchenko wrote: On 04/24/2018 07:23 PM, Oleksandr Andrushchenko wrote: On 04/24/2018 06:02 PM, Takashi Iwai wrote: On Tue, 24 Apr 2018 16:58:43 +0200, Oleksandr Andrushchenko wrote: On 04/24/2018 05:35 PM, Takashi Iwai wrote: On Tue, 24 Apr 2018 16:29:15 +0200, Oleksandr Andrushchenko wrote: On 04/24/2018 05:20 PM, Takashi Iwai wrote: On Mon, 16 Apr 2018 08:24:51 +0200, Oleksandr Andrushchenko wrote: +static irqreturn_t evtchnl_interrupt_req(int irq, void *dev_id) +{ + struct xen_snd_front_evtchnl *channel = dev_id; + struct xen_snd_front_info *front_info = channel->front_info; + struct xensnd_resp *resp; + RING_IDX i, rp; + unsigned long flags; + + if (unlikely(channel->state != EVTCHNL_STATE_CONNECTED)) + return IRQ_HANDLED; + + spin_lock_irqsave(&front_info->io_lock, flags); + +again: + rp = channel->u.req.ring.sring->rsp_prod; + /* ensure we see queued responses up to rp */ + rmb(); + + for (i = channel->u.req.ring.rsp_cons; i != rp; i++) { I'm not familiar with Xen stuff in general, but through a quick glance, this kind of code worries me a bit. If channel->u.req.ring.rsp_cons has a bogus number, this may lead to a very long loop, no? Better to have a sanity check of the ring buffer size. In this loop I have: resp = RING_GET_RESPONSE(&channel->u.req.ring, i); and the RING_GET_RESPONSE macro is designed in the way that it wraps around when *i* in the question gets bigger than the ring size: #define RING_GET_REQUEST(_r, _idx) \ (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].req)) So, even if the counter has a bogus number it will not last long Hm, this prevents from accessing outside the ring buffer, but does it change the loop behavior? no, it doesn't Suppose channel->u.req.ring_rsp_cons = 1, and rp = 0, the loop below would still consume the whole 32bit counts, no? for (i = channel->u.req.ring.rsp_cons; i != rp; i++) { resp = RING_GET_RESPONSE(&channel->u.req.ring, i); ... } You are right here and the comment is totally valid. I'll put an additional check like here [1] and here [2] Will this address your comment? Yep, this kind of sanity checks should work. Great, will implement the checks this way then Well, after thinking a bit more on that and chatting on #xendevel IRC with Juergen (he is on CC list), it seems that the way the code is now it is all fine without the checks: the assumption here is that the backend is trusted to always write sane values to the ring counters, thus no overflow checks on frontend side are required. Even if I implement the checks then I have no means to recover, but just print an error message and bail out not handling any responses. This is probably why the checks [1] and [2] are only implemented for the backend side and there are no such macros for the frontend side. Takashi, please let me know if the above sounds reasonable and addresses your comments. If it's guaranteed to work, that's OK. But maybe it's worth to comment for readers. ok, will put a comment on that thanks, Takashi Thank you, Oleksandr
Re: [PATCH v2 3/5] ALSA: xen-front: Implement Xen event channel handling
On 04/24/2018 07:23 PM, Oleksandr Andrushchenko wrote: On 04/24/2018 06:02 PM, Takashi Iwai wrote: On Tue, 24 Apr 2018 16:58:43 +0200, Oleksandr Andrushchenko wrote: On 04/24/2018 05:35 PM, Takashi Iwai wrote: On Tue, 24 Apr 2018 16:29:15 +0200, Oleksandr Andrushchenko wrote: On 04/24/2018 05:20 PM, Takashi Iwai wrote: On Mon, 16 Apr 2018 08:24:51 +0200, Oleksandr Andrushchenko wrote: +static irqreturn_t evtchnl_interrupt_req(int irq, void *dev_id) +{ + struct xen_snd_front_evtchnl *channel = dev_id; + struct xen_snd_front_info *front_info = channel->front_info; + struct xensnd_resp *resp; + RING_IDX i, rp; + unsigned long flags; + + if (unlikely(channel->state != EVTCHNL_STATE_CONNECTED)) + return IRQ_HANDLED; + + spin_lock_irqsave(&front_info->io_lock, flags); + +again: + rp = channel->u.req.ring.sring->rsp_prod; + /* ensure we see queued responses up to rp */ + rmb(); + + for (i = channel->u.req.ring.rsp_cons; i != rp; i++) { I'm not familiar with Xen stuff in general, but through a quick glance, this kind of code worries me a bit. If channel->u.req.ring.rsp_cons has a bogus number, this may lead to a very long loop, no? Better to have a sanity check of the ring buffer size. In this loop I have: resp = RING_GET_RESPONSE(&channel->u.req.ring, i); and the RING_GET_RESPONSE macro is designed in the way that it wraps around when *i* in the question gets bigger than the ring size: #define RING_GET_REQUEST(_r, _idx) \ (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].req)) So, even if the counter has a bogus number it will not last long Hm, this prevents from accessing outside the ring buffer, but does it change the loop behavior? no, it doesn't Suppose channel->u.req.ring_rsp_cons = 1, and rp = 0, the loop below would still consume the whole 32bit counts, no? for (i = channel->u.req.ring.rsp_cons; i != rp; i++) { resp = RING_GET_RESPONSE(&channel->u.req.ring, i); ... } You are right here and the comment is totally valid. I'll put an additional check like here [1] and here [2] Will this address your comment? Yep, this kind of sanity checks should work. Great, will implement the checks this way then Well, after thinking a bit more on that and chatting on #xendevel IRC with Juergen (he is on CC list), it seems that the way the code is now it is all fine without the checks: the assumption here is that the backend is trusted to always write sane values to the ring counters, thus no overflow checks on frontend side are required. Even if I implement the checks then I have no means to recover, but just print an error message and bail out not handling any responses. This is probably why the checks [1] and [2] are only implemented for the backend side and there are no such macros for the frontend side. Takashi, please let me know if the above sounds reasonable and addresses your comments. thanks, Takashi Thank you, Oleksandr Takashi Thank you, Oleksandr [1] https://elixir.bootlin.com/linux/v4.17-rc2/source/drivers/block/xen-blkback/blkback.c#L1127 [2] https://elixir.bootlin.com/linux/v4.17-rc2/source/drivers/block/xen-blkback/blkback.c#L1135
Re: [Xen-devel] [PATCH 0/1] drm/xen-zcopy: Add Xen zero-copy helper DRM driver
On 04/24/2018 11:35 PM, Dongwon Kim wrote: Had a meeting with Daniel and talked about bringing out generic part of hyper-dmabuf to the userspace, which means we most likely reuse IOCTLs defined in xen-zcopy for our use-case if we follow his suggestion. I will still have kernel side API, so backends/frontends implemented in the kernel can access that functionality as well. So assuming we use these IOCTLs as they are, Several things I would like you to double-check.. 1. returning gref as is to the user space is still unsafe because it is a constant, easy to guess and any process that hijacks it can easily exploit the buffer. So I am wondering if it's possible to keep dmabuf-to -gref or gref-to-dmabuf in kernel space and add other layers on top of those in actual IOCTLs to add some safety.. We introduced flink like hyper_dmabuf_id including random number but many says even that is still not safe. Yes, it is generally unsafe. But even if we have implemented the approach you have in hyper-dmabuf or similar, what stops malicious software from doing the same with the existing gntdev UAPI? No need to brute force new UAPI if there is a simpler one. That being said, I'll put security aside at the first stage, but of course we can start investigating ways to improve (I assume you already have use-cases where security issues must be considered, so, probably you can tell more on what was investigated so far). 2. maybe we could take hypervisor-independent process (e.g. SGT<->page) out of xen-zcopy and put those in a new helper library. I believe this can be done, but at the first stage I would go without that helper library, so it is clearly seen what can be moved to it later (I know that you want to run ACRN as well, but can I run it on ARM? ;) 3. please consider the case where original DMA-BUF's first offset and last length are not 0 and PAGE_SIZE respectively. I assume current xen-zcopy only supports page-aligned buffer with PAGE_SIZE x n big. Hm, what is the use-case for that? thanks, DW Thank you, Oleksandr On Tue, Apr 24, 2018 at 02:59:39PM +0300, Oleksandr Andrushchenko wrote: On 04/24/2018 02:54 PM, Daniel Vetter wrote: On Mon, Apr 23, 2018 at 03:10:35PM +0300, Oleksandr Andrushchenko wrote: On 04/23/2018 02:52 PM, Wei Liu wrote: On Fri, Apr 20, 2018 at 02:25:20PM +0300, Oleksandr Andrushchenko wrote: the gntdev. I think this is generic enough that it could be implemented by a device not tied to Xen. AFAICT the hyper_dma guys also wanted something similar to this. You can't just wrap random userspace memory into a dma-buf. We've just had this discussion with kvm/qemu folks, who proposed just that, and after a bit of discussion they'll now try to have a driver which just wraps a memfd into a dma-buf. So, we have to decide either we introduce a new driver (say, under drivers/xen/xen-dma-buf) or extend the existing gntdev/balloon to support dma-buf use-cases. Can anybody from Xen community express their preference here? Oleksandr talked to me on IRC about this, he said a few IOCTLs need to be added to either existing drivers or a new driver. I went through this thread twice and skimmed through the relevant documents, but I couldn't see any obvious pros and cons for either approach. So I don't really have an opinion on this. But, assuming if implemented in existing drivers, those IOCTLs need to be added to different drivers, which means userspace program needs to write more code and get more handles, it would be slightly better to implement a new driver from that perspective. If gntdev/balloon extension is still considered: All the IOCTLs will be in gntdev driver (in current xen-zcopy terminology): I was lazy to change dumb to dma-buf, so put this notice ;) - DRM_ICOTL_XEN_ZCOPY_DUMB_FROM_REFS - DRM_IOCTL_XEN_ZCOPY_DUMB_TO_REFS - DRM_IOCTL_XEN_ZCOPY_DUMB_WAIT_FREE s/DUMB/DMA_BUF/ please. This is generic dma-buf, it has nothing to do with the dumb scanout buffer support in the drm/gfx subsystem. This here can be used for any zcopy sharing among guests (as long as your endpoints understands dma-buf, which most relevant drivers do). Of course, please see above -Daniel Balloon driver extension, which is needed for contiguous/DMA buffers, will be to provide new *kernel API*, no UAPI is needed. Wei. Thank you, Oleksandr ___ dri-devel mailing list dri-de...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2 3/5] ALSA: xen-front: Implement Xen event channel handling
On 04/24/2018 06:02 PM, Takashi Iwai wrote: On Tue, 24 Apr 2018 16:58:43 +0200, Oleksandr Andrushchenko wrote: On 04/24/2018 05:35 PM, Takashi Iwai wrote: On Tue, 24 Apr 2018 16:29:15 +0200, Oleksandr Andrushchenko wrote: On 04/24/2018 05:20 PM, Takashi Iwai wrote: On Mon, 16 Apr 2018 08:24:51 +0200, Oleksandr Andrushchenko wrote: +static irqreturn_t evtchnl_interrupt_req(int irq, void *dev_id) +{ + struct xen_snd_front_evtchnl *channel = dev_id; + struct xen_snd_front_info *front_info = channel->front_info; + struct xensnd_resp *resp; + RING_IDX i, rp; + unsigned long flags; + + if (unlikely(channel->state != EVTCHNL_STATE_CONNECTED)) + return IRQ_HANDLED; + + spin_lock_irqsave(&front_info->io_lock, flags); + +again: + rp = channel->u.req.ring.sring->rsp_prod; + /* ensure we see queued responses up to rp */ + rmb(); + + for (i = channel->u.req.ring.rsp_cons; i != rp; i++) { I'm not familiar with Xen stuff in general, but through a quick glance, this kind of code worries me a bit. If channel->u.req.ring.rsp_cons has a bogus number, this may lead to a very long loop, no? Better to have a sanity check of the ring buffer size. In this loop I have: resp = RING_GET_RESPONSE(&channel->u.req.ring, i); and the RING_GET_RESPONSE macro is designed in the way that it wraps around when *i* in the question gets bigger than the ring size: #define RING_GET_REQUEST(_r, _idx) \ (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].req)) So, even if the counter has a bogus number it will not last long Hm, this prevents from accessing outside the ring buffer, but does it change the loop behavior? no, it doesn't Suppose channel->u.req.ring_rsp_cons = 1, and rp = 0, the loop below would still consume the whole 32bit counts, no? for (i = channel->u.req.ring.rsp_cons; i != rp; i++) { resp = RING_GET_RESPONSE(&channel->u.req.ring, i); ... } You are right here and the comment is totally valid. I'll put an additional check like here [1] and here [2] Will this address your comment? Yep, this kind of sanity checks should work. Great, will implement the checks this way then thanks, Takashi Thank you, Oleksandr Takashi Thank you, Oleksandr [1] https://elixir.bootlin.com/linux/v4.17-rc2/source/drivers/block/xen-blkback/blkback.c#L1127 [2] https://elixir.bootlin.com/linux/v4.17-rc2/source/drivers/block/xen-blkback/blkback.c#L1135
Re: [PATCH v2 3/5] ALSA: xen-front: Implement Xen event channel handling
On 04/24/2018 05:35 PM, Takashi Iwai wrote: On Tue, 24 Apr 2018 16:29:15 +0200, Oleksandr Andrushchenko wrote: On 04/24/2018 05:20 PM, Takashi Iwai wrote: On Mon, 16 Apr 2018 08:24:51 +0200, Oleksandr Andrushchenko wrote: +static irqreturn_t evtchnl_interrupt_req(int irq, void *dev_id) +{ + struct xen_snd_front_evtchnl *channel = dev_id; + struct xen_snd_front_info *front_info = channel->front_info; + struct xensnd_resp *resp; + RING_IDX i, rp; + unsigned long flags; + + if (unlikely(channel->state != EVTCHNL_STATE_CONNECTED)) + return IRQ_HANDLED; + + spin_lock_irqsave(&front_info->io_lock, flags); + +again: + rp = channel->u.req.ring.sring->rsp_prod; + /* ensure we see queued responses up to rp */ + rmb(); + + for (i = channel->u.req.ring.rsp_cons; i != rp; i++) { I'm not familiar with Xen stuff in general, but through a quick glance, this kind of code worries me a bit. If channel->u.req.ring.rsp_cons has a bogus number, this may lead to a very long loop, no? Better to have a sanity check of the ring buffer size. In this loop I have: resp = RING_GET_RESPONSE(&channel->u.req.ring, i); and the RING_GET_RESPONSE macro is designed in the way that it wraps around when *i* in the question gets bigger than the ring size: #define RING_GET_REQUEST(_r, _idx) \ (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].req)) So, even if the counter has a bogus number it will not last long Hm, this prevents from accessing outside the ring buffer, but does it change the loop behavior? no, it doesn't Suppose channel->u.req.ring_rsp_cons = 1, and rp = 0, the loop below would still consume the whole 32bit counts, no? for (i = channel->u.req.ring.rsp_cons; i != rp; i++) { resp = RING_GET_RESPONSE(&channel->u.req.ring, i); ... } You are right here and the comment is totally valid. I'll put an additional check like here [1] and here [2] Will this address your comment? Takashi Thank you, Oleksandr [1] https://elixir.bootlin.com/linux/v4.17-rc2/source/drivers/block/xen-blkback/blkback.c#L1127 [2] https://elixir.bootlin.com/linux/v4.17-rc2/source/drivers/block/xen-blkback/blkback.c#L1135
Re: [PATCH v2 3/5] ALSA: xen-front: Implement Xen event channel handling
On 04/24/2018 05:20 PM, Takashi Iwai wrote: On Mon, 16 Apr 2018 08:24:51 +0200, Oleksandr Andrushchenko wrote: +static irqreturn_t evtchnl_interrupt_req(int irq, void *dev_id) +{ + struct xen_snd_front_evtchnl *channel = dev_id; + struct xen_snd_front_info *front_info = channel->front_info; + struct xensnd_resp *resp; + RING_IDX i, rp; + unsigned long flags; + + if (unlikely(channel->state != EVTCHNL_STATE_CONNECTED)) + return IRQ_HANDLED; + + spin_lock_irqsave(&front_info->io_lock, flags); + +again: + rp = channel->u.req.ring.sring->rsp_prod; + /* ensure we see queued responses up to rp */ + rmb(); + + for (i = channel->u.req.ring.rsp_cons; i != rp; i++) { I'm not familiar with Xen stuff in general, but through a quick glance, this kind of code worries me a bit. If channel->u.req.ring.rsp_cons has a bogus number, this may lead to a very long loop, no? Better to have a sanity check of the ring buffer size. In this loop I have: resp = RING_GET_RESPONSE(&channel->u.req.ring, i); and the RING_GET_RESPONSE macro is designed in the way that it wraps around when *i* in the question gets bigger than the ring size: #define RING_GET_REQUEST(_r, _idx) \ (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].req)) So, even if the counter has a bogus number it will not last long +static irqreturn_t evtchnl_interrupt_evt(int irq, void *dev_id) +{ + struct xen_snd_front_evtchnl *channel = dev_id; + struct xen_snd_front_info *front_info = channel->front_info; + struct xensnd_event_page *page = channel->u.evt.page; + u32 cons, prod; + unsigned long flags; + + if (unlikely(channel->state != EVTCHNL_STATE_CONNECTED)) + return IRQ_HANDLED; + + spin_lock_irqsave(&front_info->io_lock, flags); + + prod = page->in_prod; + /* ensure we see ring contents up to prod */ + virt_rmb(); + if (prod == page->in_cons) + goto out; + + for (cons = page->in_cons; cons != prod; cons++) { Ditto. Same as above thanks, Takashi Thank you, Oleksandr
Re: [PATCH v2 1/5] ALSA: xen-front: Introduce Xen para-virtualized sound frontend driver
On 04/24/2018 04:55 PM, Takashi Iwai wrote: On Mon, 16 Apr 2018 08:24:49 +0200, Oleksandr Andrushchenko wrote: --- /dev/null +++ b/sound/xen/Kconfig @@ -0,0 +1,10 @@ +# ALSA Xen drivers + +config SND_XEN_FRONTEND + tristate "Xen para-virtualized sound frontend driver" + depends on XEN && SND_PCM Please do select SND_PCM instead of depends. will do + select XEN_XENBUS_FRONTEND + default n "default n" is superfluous, drop it. will drop thanks, Takashi Thank you, Oleksandr
Re: [Xen-devel] [PATCH 0/1] drm/xen-zcopy: Add Xen zero-copy helper DRM driver
On 04/24/2018 02:54 PM, Daniel Vetter wrote: On Mon, Apr 23, 2018 at 03:10:35PM +0300, Oleksandr Andrushchenko wrote: On 04/23/2018 02:52 PM, Wei Liu wrote: On Fri, Apr 20, 2018 at 02:25:20PM +0300, Oleksandr Andrushchenko wrote: the gntdev. I think this is generic enough that it could be implemented by a device not tied to Xen. AFAICT the hyper_dma guys also wanted something similar to this. You can't just wrap random userspace memory into a dma-buf. We've just had this discussion with kvm/qemu folks, who proposed just that, and after a bit of discussion they'll now try to have a driver which just wraps a memfd into a dma-buf. So, we have to decide either we introduce a new driver (say, under drivers/xen/xen-dma-buf) or extend the existing gntdev/balloon to support dma-buf use-cases. Can anybody from Xen community express their preference here? Oleksandr talked to me on IRC about this, he said a few IOCTLs need to be added to either existing drivers or a new driver. I went through this thread twice and skimmed through the relevant documents, but I couldn't see any obvious pros and cons for either approach. So I don't really have an opinion on this. But, assuming if implemented in existing drivers, those IOCTLs need to be added to different drivers, which means userspace program needs to write more code and get more handles, it would be slightly better to implement a new driver from that perspective. If gntdev/balloon extension is still considered: All the IOCTLs will be in gntdev driver (in current xen-zcopy terminology): I was lazy to change dumb to dma-buf, so put this notice ;) - DRM_ICOTL_XEN_ZCOPY_DUMB_FROM_REFS - DRM_IOCTL_XEN_ZCOPY_DUMB_TO_REFS - DRM_IOCTL_XEN_ZCOPY_DUMB_WAIT_FREE s/DUMB/DMA_BUF/ please. This is generic dma-buf, it has nothing to do with the dumb scanout buffer support in the drm/gfx subsystem. This here can be used for any zcopy sharing among guests (as long as your endpoints understands dma-buf, which most relevant drivers do). Of course, please see above -Daniel Balloon driver extension, which is needed for contiguous/DMA buffers, will be to provide new *kernel API*, no UAPI is needed. Wei. Thank you, Oleksandr ___ dri-devel mailing list dri-de...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Xen-devel] [PATCH 0/1] drm/xen-zcopy: Add Xen zero-copy helper DRM driver
On 04/24/2018 01:01 PM, Wei Liu wrote: On Tue, Apr 24, 2018 at 11:08:41AM +0200, Juergen Gross wrote: On 24/04/18 11:03, Oleksandr Andrushchenko wrote: On 04/24/2018 11:40 AM, Juergen Gross wrote: On 24/04/18 10:07, Oleksandr Andrushchenko wrote: On 04/24/2018 10:51 AM, Juergen Gross wrote: On 24/04/18 07:43, Oleksandr Andrushchenko wrote: On 04/24/2018 01:41 AM, Boris Ostrovsky wrote: On 04/23/2018 08:10 AM, Oleksandr Andrushchenko wrote: On 04/23/2018 02:52 PM, Wei Liu wrote: On Fri, Apr 20, 2018 at 02:25:20PM +0300, Oleksandr Andrushchenko wrote: the gntdev. I think this is generic enough that it could be implemented by a device not tied to Xen. AFAICT the hyper_dma guys also wanted something similar to this. You can't just wrap random userspace memory into a dma-buf. We've just had this discussion with kvm/qemu folks, who proposed just that, and after a bit of discussion they'll now try to have a driver which just wraps a memfd into a dma-buf. So, we have to decide either we introduce a new driver (say, under drivers/xen/xen-dma-buf) or extend the existing gntdev/balloon to support dma-buf use-cases. Can anybody from Xen community express their preference here? Oleksandr talked to me on IRC about this, he said a few IOCTLs need to be added to either existing drivers or a new driver. I went through this thread twice and skimmed through the relevant documents, but I couldn't see any obvious pros and cons for either approach. So I don't really have an opinion on this. But, assuming if implemented in existing drivers, those IOCTLs need to be added to different drivers, which means userspace program needs to write more code and get more handles, it would be slightly better to implement a new driver from that perspective. If gntdev/balloon extension is still considered: All the IOCTLs will be in gntdev driver (in current xen-zcopy terminology): - DRM_ICOTL_XEN_ZCOPY_DUMB_FROM_REFS - DRM_IOCTL_XEN_ZCOPY_DUMB_TO_REFS - DRM_IOCTL_XEN_ZCOPY_DUMB_WAIT_FREE Balloon driver extension, which is needed for contiguous/DMA buffers, will be to provide new *kernel API*, no UAPI is needed. So I am obviously a bit late to this thread, but why do you need to add new ioctls to gntdev and balloon? Doesn't this driver manage to do what you want without any extensions? 1. I only (may) need to add IOCTLs to gntdev 2. balloon driver needs to be extended, so it can allocate contiguous (DMA) memory, not IOCTLs/UAPI here, all lives in the kernel. 3. The reason I need to extend gnttab with new IOCTLs is to provide new functionality to create a dma-buf from grant references and to produce grant references for a dma-buf. This is what I have as UAPI description for xen-zcopy driver: 1. DRM_IOCTL_XEN_ZCOPY_DUMB_FROM_REFS This will create a DRM dumb buffer from grant references provided by the frontend. The intended usage is: - Frontend - creates a dumb/display buffer and allocates memory - grants foreign access to the buffer pages - passes granted references to the backend - Backend - issues DRM_XEN_ZCOPY_DUMB_FROM_REFS ioctl to map granted references and create a dumb buffer - requests handle to fd conversion via DRM_IOCTL_PRIME_HANDLE_TO_FD - requests real HW driver/consumer to import the PRIME buffer with DRM_IOCTL_PRIME_FD_TO_HANDLE - uses handle returned by the real HW driver - at the end: o closes real HW driver's handle with DRM_IOCTL_GEM_CLOSE o closes zero-copy driver's handle with DRM_IOCTL_GEM_CLOSE o closes file descriptor of the exported buffer 2. DRM_IOCTL_XEN_ZCOPY_DUMB_TO_REFS This will grant references to a dumb/display buffer's memory provided by the backend. The intended usage is: - Frontend - requests backend to allocate dumb/display buffer and grant references to its pages - Backend - requests real HW driver to create a dumb with DRM_IOCTL_MODE_CREATE_DUMB - requests handle to fd conversion via DRM_IOCTL_PRIME_HANDLE_TO_FD - requests zero-copy driver to import the PRIME buffer with DRM_IOCTL_PRIME_FD_TO_HANDLE - issues DRM_XEN_ZCOPY_DUMB_TO_REFS ioctl to grant references to the buffer's memory. - passes grant references to the frontend - at the end: - closes zero-copy driver's handle with DRM_IOCTL_GEM_CLOSE - closes real HW driver's handle with DRM_IOCTL_GEM_CLOSE - closes file descriptor of the imported buffer 3. DRM_XEN_ZCOPY_DUMB_WAIT_FREE This will block until the dumb buffer with the wait handle provided be freed: this is needed for synchronization between frontend and backend in case frontend provides grant references of the buffer via DRM_XEN_ZCOPY_DUMB_FROM_REFS IOCTL and which must be released before backend replies with XENDISPL_OP_DBUF_DESTROY response. wait_handle must be the same value re
Re: [Xen-devel] [PATCH 0/1] drm/xen-zcopy: Add Xen zero-copy helper DRM driver
On 04/24/2018 12:08 PM, Juergen Gross wrote: On 24/04/18 11:03, Oleksandr Andrushchenko wrote: On 04/24/2018 11:40 AM, Juergen Gross wrote: On 24/04/18 10:07, Oleksandr Andrushchenko wrote: On 04/24/2018 10:51 AM, Juergen Gross wrote: On 24/04/18 07:43, Oleksandr Andrushchenko wrote: On 04/24/2018 01:41 AM, Boris Ostrovsky wrote: On 04/23/2018 08:10 AM, Oleksandr Andrushchenko wrote: On 04/23/2018 02:52 PM, Wei Liu wrote: On Fri, Apr 20, 2018 at 02:25:20PM +0300, Oleksandr Andrushchenko wrote: the gntdev. I think this is generic enough that it could be implemented by a device not tied to Xen. AFAICT the hyper_dma guys also wanted something similar to this. You can't just wrap random userspace memory into a dma-buf. We've just had this discussion with kvm/qemu folks, who proposed just that, and after a bit of discussion they'll now try to have a driver which just wraps a memfd into a dma-buf. So, we have to decide either we introduce a new driver (say, under drivers/xen/xen-dma-buf) or extend the existing gntdev/balloon to support dma-buf use-cases. Can anybody from Xen community express their preference here? Oleksandr talked to me on IRC about this, he said a few IOCTLs need to be added to either existing drivers or a new driver. I went through this thread twice and skimmed through the relevant documents, but I couldn't see any obvious pros and cons for either approach. So I don't really have an opinion on this. But, assuming if implemented in existing drivers, those IOCTLs need to be added to different drivers, which means userspace program needs to write more code and get more handles, it would be slightly better to implement a new driver from that perspective. If gntdev/balloon extension is still considered: All the IOCTLs will be in gntdev driver (in current xen-zcopy terminology): - DRM_ICOTL_XEN_ZCOPY_DUMB_FROM_REFS - DRM_IOCTL_XEN_ZCOPY_DUMB_TO_REFS - DRM_IOCTL_XEN_ZCOPY_DUMB_WAIT_FREE Balloon driver extension, which is needed for contiguous/DMA buffers, will be to provide new *kernel API*, no UAPI is needed. So I am obviously a bit late to this thread, but why do you need to add new ioctls to gntdev and balloon? Doesn't this driver manage to do what you want without any extensions? 1. I only (may) need to add IOCTLs to gntdev 2. balloon driver needs to be extended, so it can allocate contiguous (DMA) memory, not IOCTLs/UAPI here, all lives in the kernel. 3. The reason I need to extend gnttab with new IOCTLs is to provide new functionality to create a dma-buf from grant references and to produce grant references for a dma-buf. This is what I have as UAPI description for xen-zcopy driver: 1. DRM_IOCTL_XEN_ZCOPY_DUMB_FROM_REFS This will create a DRM dumb buffer from grant references provided by the frontend. The intended usage is: - Frontend - creates a dumb/display buffer and allocates memory - grants foreign access to the buffer pages - passes granted references to the backend - Backend - issues DRM_XEN_ZCOPY_DUMB_FROM_REFS ioctl to map granted references and create a dumb buffer - requests handle to fd conversion via DRM_IOCTL_PRIME_HANDLE_TO_FD - requests real HW driver/consumer to import the PRIME buffer with DRM_IOCTL_PRIME_FD_TO_HANDLE - uses handle returned by the real HW driver - at the end: o closes real HW driver's handle with DRM_IOCTL_GEM_CLOSE o closes zero-copy driver's handle with DRM_IOCTL_GEM_CLOSE o closes file descriptor of the exported buffer 2. DRM_IOCTL_XEN_ZCOPY_DUMB_TO_REFS This will grant references to a dumb/display buffer's memory provided by the backend. The intended usage is: - Frontend - requests backend to allocate dumb/display buffer and grant references to its pages - Backend - requests real HW driver to create a dumb with DRM_IOCTL_MODE_CREATE_DUMB - requests handle to fd conversion via DRM_IOCTL_PRIME_HANDLE_TO_FD - requests zero-copy driver to import the PRIME buffer with DRM_IOCTL_PRIME_FD_TO_HANDLE - issues DRM_XEN_ZCOPY_DUMB_TO_REFS ioctl to grant references to the buffer's memory. - passes grant references to the frontend - at the end: - closes zero-copy driver's handle with DRM_IOCTL_GEM_CLOSE - closes real HW driver's handle with DRM_IOCTL_GEM_CLOSE - closes file descriptor of the imported buffer 3. DRM_XEN_ZCOPY_DUMB_WAIT_FREE This will block until the dumb buffer with the wait handle provided be freed: this is needed for synchronization between frontend and backend in case frontend provides grant references of the buffer via DRM_XEN_ZCOPY_DUMB_FROM_REFS IOCTL and which must be released before backend replies with XENDISPL_OP_DBUF_DESTROY response. wait_handle must be the same value returned while calling DRM_XEN_ZCOPY_DUMB_FROM_REFS IOCTL.
Re: [Xen-devel] [PATCH 0/1] drm/xen-zcopy: Add Xen zero-copy helper DRM driver
On 04/24/2018 11:40 AM, Juergen Gross wrote: On 24/04/18 10:07, Oleksandr Andrushchenko wrote: On 04/24/2018 10:51 AM, Juergen Gross wrote: On 24/04/18 07:43, Oleksandr Andrushchenko wrote: On 04/24/2018 01:41 AM, Boris Ostrovsky wrote: On 04/23/2018 08:10 AM, Oleksandr Andrushchenko wrote: On 04/23/2018 02:52 PM, Wei Liu wrote: On Fri, Apr 20, 2018 at 02:25:20PM +0300, Oleksandr Andrushchenko wrote: the gntdev. I think this is generic enough that it could be implemented by a device not tied to Xen. AFAICT the hyper_dma guys also wanted something similar to this. You can't just wrap random userspace memory into a dma-buf. We've just had this discussion with kvm/qemu folks, who proposed just that, and after a bit of discussion they'll now try to have a driver which just wraps a memfd into a dma-buf. So, we have to decide either we introduce a new driver (say, under drivers/xen/xen-dma-buf) or extend the existing gntdev/balloon to support dma-buf use-cases. Can anybody from Xen community express their preference here? Oleksandr talked to me on IRC about this, he said a few IOCTLs need to be added to either existing drivers or a new driver. I went through this thread twice and skimmed through the relevant documents, but I couldn't see any obvious pros and cons for either approach. So I don't really have an opinion on this. But, assuming if implemented in existing drivers, those IOCTLs need to be added to different drivers, which means userspace program needs to write more code and get more handles, it would be slightly better to implement a new driver from that perspective. If gntdev/balloon extension is still considered: All the IOCTLs will be in gntdev driver (in current xen-zcopy terminology): - DRM_ICOTL_XEN_ZCOPY_DUMB_FROM_REFS - DRM_IOCTL_XEN_ZCOPY_DUMB_TO_REFS - DRM_IOCTL_XEN_ZCOPY_DUMB_WAIT_FREE Balloon driver extension, which is needed for contiguous/DMA buffers, will be to provide new *kernel API*, no UAPI is needed. So I am obviously a bit late to this thread, but why do you need to add new ioctls to gntdev and balloon? Doesn't this driver manage to do what you want without any extensions? 1. I only (may) need to add IOCTLs to gntdev 2. balloon driver needs to be extended, so it can allocate contiguous (DMA) memory, not IOCTLs/UAPI here, all lives in the kernel. 3. The reason I need to extend gnttab with new IOCTLs is to provide new functionality to create a dma-buf from grant references and to produce grant references for a dma-buf. This is what I have as UAPI description for xen-zcopy driver: 1. DRM_IOCTL_XEN_ZCOPY_DUMB_FROM_REFS This will create a DRM dumb buffer from grant references provided by the frontend. The intended usage is: - Frontend - creates a dumb/display buffer and allocates memory - grants foreign access to the buffer pages - passes granted references to the backend - Backend - issues DRM_XEN_ZCOPY_DUMB_FROM_REFS ioctl to map granted references and create a dumb buffer - requests handle to fd conversion via DRM_IOCTL_PRIME_HANDLE_TO_FD - requests real HW driver/consumer to import the PRIME buffer with DRM_IOCTL_PRIME_FD_TO_HANDLE - uses handle returned by the real HW driver - at the end: o closes real HW driver's handle with DRM_IOCTL_GEM_CLOSE o closes zero-copy driver's handle with DRM_IOCTL_GEM_CLOSE o closes file descriptor of the exported buffer 2. DRM_IOCTL_XEN_ZCOPY_DUMB_TO_REFS This will grant references to a dumb/display buffer's memory provided by the backend. The intended usage is: - Frontend - requests backend to allocate dumb/display buffer and grant references to its pages - Backend - requests real HW driver to create a dumb with DRM_IOCTL_MODE_CREATE_DUMB - requests handle to fd conversion via DRM_IOCTL_PRIME_HANDLE_TO_FD - requests zero-copy driver to import the PRIME buffer with DRM_IOCTL_PRIME_FD_TO_HANDLE - issues DRM_XEN_ZCOPY_DUMB_TO_REFS ioctl to grant references to the buffer's memory. - passes grant references to the frontend - at the end: - closes zero-copy driver's handle with DRM_IOCTL_GEM_CLOSE - closes real HW driver's handle with DRM_IOCTL_GEM_CLOSE - closes file descriptor of the imported buffer 3. DRM_XEN_ZCOPY_DUMB_WAIT_FREE This will block until the dumb buffer with the wait handle provided be freed: this is needed for synchronization between frontend and backend in case frontend provides grant references of the buffer via DRM_XEN_ZCOPY_DUMB_FROM_REFS IOCTL and which must be released before backend replies with XENDISPL_OP_DBUF_DESTROY response. wait_handle must be the same value returned while calling DRM_XEN_ZCOPY_DUMB_FROM_REFS IOCTL. So, as you can see the above functionality is not covered by the existing UAPI of the gntdev driver. Now, if we change dumb -> d
Re: [Xen-devel] [PATCH 0/1] drm/xen-zcopy: Add Xen zero-copy helper DRM driver
On 04/24/2018 10:51 AM, Juergen Gross wrote: On 24/04/18 07:43, Oleksandr Andrushchenko wrote: On 04/24/2018 01:41 AM, Boris Ostrovsky wrote: On 04/23/2018 08:10 AM, Oleksandr Andrushchenko wrote: On 04/23/2018 02:52 PM, Wei Liu wrote: On Fri, Apr 20, 2018 at 02:25:20PM +0300, Oleksandr Andrushchenko wrote: the gntdev. I think this is generic enough that it could be implemented by a device not tied to Xen. AFAICT the hyper_dma guys also wanted something similar to this. You can't just wrap random userspace memory into a dma-buf. We've just had this discussion with kvm/qemu folks, who proposed just that, and after a bit of discussion they'll now try to have a driver which just wraps a memfd into a dma-buf. So, we have to decide either we introduce a new driver (say, under drivers/xen/xen-dma-buf) or extend the existing gntdev/balloon to support dma-buf use-cases. Can anybody from Xen community express their preference here? Oleksandr talked to me on IRC about this, he said a few IOCTLs need to be added to either existing drivers or a new driver. I went through this thread twice and skimmed through the relevant documents, but I couldn't see any obvious pros and cons for either approach. So I don't really have an opinion on this. But, assuming if implemented in existing drivers, those IOCTLs need to be added to different drivers, which means userspace program needs to write more code and get more handles, it would be slightly better to implement a new driver from that perspective. If gntdev/balloon extension is still considered: All the IOCTLs will be in gntdev driver (in current xen-zcopy terminology): - DRM_ICOTL_XEN_ZCOPY_DUMB_FROM_REFS - DRM_IOCTL_XEN_ZCOPY_DUMB_TO_REFS - DRM_IOCTL_XEN_ZCOPY_DUMB_WAIT_FREE Balloon driver extension, which is needed for contiguous/DMA buffers, will be to provide new *kernel API*, no UAPI is needed. So I am obviously a bit late to this thread, but why do you need to add new ioctls to gntdev and balloon? Doesn't this driver manage to do what you want without any extensions? 1. I only (may) need to add IOCTLs to gntdev 2. balloon driver needs to be extended, so it can allocate contiguous (DMA) memory, not IOCTLs/UAPI here, all lives in the kernel. 3. The reason I need to extend gnttab with new IOCTLs is to provide new functionality to create a dma-buf from grant references and to produce grant references for a dma-buf. This is what I have as UAPI description for xen-zcopy driver: 1. DRM_IOCTL_XEN_ZCOPY_DUMB_FROM_REFS This will create a DRM dumb buffer from grant references provided by the frontend. The intended usage is: - Frontend - creates a dumb/display buffer and allocates memory - grants foreign access to the buffer pages - passes granted references to the backend - Backend - issues DRM_XEN_ZCOPY_DUMB_FROM_REFS ioctl to map granted references and create a dumb buffer - requests handle to fd conversion via DRM_IOCTL_PRIME_HANDLE_TO_FD - requests real HW driver/consumer to import the PRIME buffer with DRM_IOCTL_PRIME_FD_TO_HANDLE - uses handle returned by the real HW driver - at the end: o closes real HW driver's handle with DRM_IOCTL_GEM_CLOSE o closes zero-copy driver's handle with DRM_IOCTL_GEM_CLOSE o closes file descriptor of the exported buffer 2. DRM_IOCTL_XEN_ZCOPY_DUMB_TO_REFS This will grant references to a dumb/display buffer's memory provided by the backend. The intended usage is: - Frontend - requests backend to allocate dumb/display buffer and grant references to its pages - Backend - requests real HW driver to create a dumb with DRM_IOCTL_MODE_CREATE_DUMB - requests handle to fd conversion via DRM_IOCTL_PRIME_HANDLE_TO_FD - requests zero-copy driver to import the PRIME buffer with DRM_IOCTL_PRIME_FD_TO_HANDLE - issues DRM_XEN_ZCOPY_DUMB_TO_REFS ioctl to grant references to the buffer's memory. - passes grant references to the frontend - at the end: - closes zero-copy driver's handle with DRM_IOCTL_GEM_CLOSE - closes real HW driver's handle with DRM_IOCTL_GEM_CLOSE - closes file descriptor of the imported buffer 3. DRM_XEN_ZCOPY_DUMB_WAIT_FREE This will block until the dumb buffer with the wait handle provided be freed: this is needed for synchronization between frontend and backend in case frontend provides grant references of the buffer via DRM_XEN_ZCOPY_DUMB_FROM_REFS IOCTL and which must be released before backend replies with XENDISPL_OP_DBUF_DESTROY response. wait_handle must be the same value returned while calling DRM_XEN_ZCOPY_DUMB_FROM_REFS IOCTL. So, as you can see the above functionality is not covered by the existing UAPI of the gntdev driver. Now, if we change dumb -> dma-buf and remove DRM code (which is only a wrapper here on top of dma-buf) we get new driver for dma-buf for Xen. This is why I
Re: [PATCH v2] Input: xen-kbdfront - allow better run-time configuration
On 04/23/2018 09:55 PM, Dmitry Torokhov wrote: On Mon, Apr 23, 2018 at 11:29:45AM +0300, Oleksandr Andrushchenko wrote: On 04/23/2018 11:23 AM, Juergen Gross wrote: On 23/04/18 10:02, Oleksandr Andrushchenko wrote: Juergen, Jason, Dmitry any comment on this? Oleksandr, please give us some time. I can't speak for others, but I am not sitting here idling and hoping that some work (e.g. patches to review) might appear. I have a lot of other stuff to do and will respond when I find some time to look at your patches. Pinging others on Monday when having sent out the patch only on Thursday is rather unfriendly. Really sorry about this, my bad. I had an impression that the only change we need to discuss was uint -> bool change which seemed rather trivial I am sorry I did not respond to the previous version until today, but I do not think that we should be extending module parameters for this. Protocol features are already there for absolute pointers and multi-touch, keyboard and relative pointers should use the same mechanism. Ok, then I'll start from extending the protocol Thanks.
Re: [PATCH] Input: xen-kbdfront - allow better run-time configuration
On 04/23/2018 09:53 PM, Dmitry Torokhov wrote: On Thu, Apr 19, 2018 at 02:44:19PM +0300, Oleksandr Andrushchenko wrote: On 04/19/2018 02:25 PM, Juergen Gross wrote: On 18/04/18 17:04, Oleksandr Andrushchenko wrote: From: Oleksandr Andrushchenko It is now only possible to control if multi-touch virtual device is created or not (via the corresponding XenStore entries), but keyboard and pointer devices are always created. Why don't you want to go that route for keyboard and mouse, too? Or does this really make no sense? Well, I would prefer not to touch anything outside Linux and this driver. And these settings seem to be implementation specific. So, this is why introduce Linux module parameters and don't extend the kbdif protocol. Why do you consider this implementation specific? How other guests decide to forego creation of relative pointer device or keyboard-like device? You already have "features" for absolute pointing device and multitouch, so please extend the protocol properly so you indeed do not code something implementation-specific (i.e. module parameters). Ok, but in order to preserve the default behavior, e.g. pointer and keyboard devices are always created now, I'll have to have reverse features in the protocol: - feature-no-pointer - feature-no-keyboard The above may be set as a part of frontend's configuration and if missed are considered to be set to false. Thanks.
Re: [Xen-devel] [PATCH 0/1] drm/xen-zcopy: Add Xen zero-copy helper DRM driver
On 04/24/2018 01:41 AM, Boris Ostrovsky wrote: On 04/23/2018 08:10 AM, Oleksandr Andrushchenko wrote: On 04/23/2018 02:52 PM, Wei Liu wrote: On Fri, Apr 20, 2018 at 02:25:20PM +0300, Oleksandr Andrushchenko wrote: the gntdev. I think this is generic enough that it could be implemented by a device not tied to Xen. AFAICT the hyper_dma guys also wanted something similar to this. You can't just wrap random userspace memory into a dma-buf. We've just had this discussion with kvm/qemu folks, who proposed just that, and after a bit of discussion they'll now try to have a driver which just wraps a memfd into a dma-buf. So, we have to decide either we introduce a new driver (say, under drivers/xen/xen-dma-buf) or extend the existing gntdev/balloon to support dma-buf use-cases. Can anybody from Xen community express their preference here? Oleksandr talked to me on IRC about this, he said a few IOCTLs need to be added to either existing drivers or a new driver. I went through this thread twice and skimmed through the relevant documents, but I couldn't see any obvious pros and cons for either approach. So I don't really have an opinion on this. But, assuming if implemented in existing drivers, those IOCTLs need to be added to different drivers, which means userspace program needs to write more code and get more handles, it would be slightly better to implement a new driver from that perspective. If gntdev/balloon extension is still considered: All the IOCTLs will be in gntdev driver (in current xen-zcopy terminology): - DRM_ICOTL_XEN_ZCOPY_DUMB_FROM_REFS - DRM_IOCTL_XEN_ZCOPY_DUMB_TO_REFS - DRM_IOCTL_XEN_ZCOPY_DUMB_WAIT_FREE Balloon driver extension, which is needed for contiguous/DMA buffers, will be to provide new *kernel API*, no UAPI is needed. So I am obviously a bit late to this thread, but why do you need to add new ioctls to gntdev and balloon? Doesn't this driver manage to do what you want without any extensions? 1. I only (may) need to add IOCTLs to gntdev 2. balloon driver needs to be extended, so it can allocate contiguous (DMA) memory, not IOCTLs/UAPI here, all lives in the kernel. 3. The reason I need to extend gnttab with new IOCTLs is to provide new functionality to create a dma-buf from grant references and to produce grant references for a dma-buf. This is what I have as UAPI description for xen-zcopy driver: 1. DRM_IOCTL_XEN_ZCOPY_DUMB_FROM_REFS This will create a DRM dumb buffer from grant references provided by the frontend. The intended usage is: - Frontend - creates a dumb/display buffer and allocates memory - grants foreign access to the buffer pages - passes granted references to the backend - Backend - issues DRM_XEN_ZCOPY_DUMB_FROM_REFS ioctl to map granted references and create a dumb buffer - requests handle to fd conversion via DRM_IOCTL_PRIME_HANDLE_TO_FD - requests real HW driver/consumer to import the PRIME buffer with DRM_IOCTL_PRIME_FD_TO_HANDLE - uses handle returned by the real HW driver - at the end: o closes real HW driver's handle with DRM_IOCTL_GEM_CLOSE o closes zero-copy driver's handle with DRM_IOCTL_GEM_CLOSE o closes file descriptor of the exported buffer 2. DRM_IOCTL_XEN_ZCOPY_DUMB_TO_REFS This will grant references to a dumb/display buffer's memory provided by the backend. The intended usage is: - Frontend - requests backend to allocate dumb/display buffer and grant references to its pages - Backend - requests real HW driver to create a dumb with DRM_IOCTL_MODE_CREATE_DUMB - requests handle to fd conversion via DRM_IOCTL_PRIME_HANDLE_TO_FD - requests zero-copy driver to import the PRIME buffer with DRM_IOCTL_PRIME_FD_TO_HANDLE - issues DRM_XEN_ZCOPY_DUMB_TO_REFS ioctl to grant references to the buffer's memory. - passes grant references to the frontend - at the end: - closes zero-copy driver's handle with DRM_IOCTL_GEM_CLOSE - closes real HW driver's handle with DRM_IOCTL_GEM_CLOSE - closes file descriptor of the imported buffer 3. DRM_XEN_ZCOPY_DUMB_WAIT_FREE This will block until the dumb buffer with the wait handle provided be freed: this is needed for synchronization between frontend and backend in case frontend provides grant references of the buffer via DRM_XEN_ZCOPY_DUMB_FROM_REFS IOCTL and which must be released before backend replies with XENDISPL_OP_DBUF_DESTROY response. wait_handle must be the same value returned while calling DRM_XEN_ZCOPY_DUMB_FROM_REFS IOCTL. So, as you can see the above functionality is not covered by the existing UAPI of the gntdev driver. Now, if we change dumb -> dma-buf and remove DRM code (which is only a wrapper here on top of dma-buf) we get new driver for dma-buf for Xen. This is why I have 2 options here: either create a dedicated driver for this (e.g. re-work xen-zcopy to be DRM independent and put it und
Re: [Xen-devel] [PATCH 0/1] drm/xen-zcopy: Add Xen zero-copy helper DRM driver
On 04/23/2018 02:52 PM, Wei Liu wrote: On Fri, Apr 20, 2018 at 02:25:20PM +0300, Oleksandr Andrushchenko wrote: the gntdev. I think this is generic enough that it could be implemented by a device not tied to Xen. AFAICT the hyper_dma guys also wanted something similar to this. You can't just wrap random userspace memory into a dma-buf. We've just had this discussion with kvm/qemu folks, who proposed just that, and after a bit of discussion they'll now try to have a driver which just wraps a memfd into a dma-buf. So, we have to decide either we introduce a new driver (say, under drivers/xen/xen-dma-buf) or extend the existing gntdev/balloon to support dma-buf use-cases. Can anybody from Xen community express their preference here? Oleksandr talked to me on IRC about this, he said a few IOCTLs need to be added to either existing drivers or a new driver. I went through this thread twice and skimmed through the relevant documents, but I couldn't see any obvious pros and cons for either approach. So I don't really have an opinion on this. But, assuming if implemented in existing drivers, those IOCTLs need to be added to different drivers, which means userspace program needs to write more code and get more handles, it would be slightly better to implement a new driver from that perspective. If gntdev/balloon extension is still considered: All the IOCTLs will be in gntdev driver (in current xen-zcopy terminology): - DRM_ICOTL_XEN_ZCOPY_DUMB_FROM_REFS - DRM_IOCTL_XEN_ZCOPY_DUMB_TO_REFS - DRM_IOCTL_XEN_ZCOPY_DUMB_WAIT_FREE Balloon driver extension, which is needed for contiguous/DMA buffers, will be to provide new *kernel API*, no UAPI is needed. Wei. Thank you, Oleksandr
Re: [PATCH v2] Input: xen-kbdfront - allow better run-time configuration
On 04/23/2018 11:23 AM, Juergen Gross wrote: On 23/04/18 10:02, Oleksandr Andrushchenko wrote: Juergen, Jason, Dmitry any comment on this? Oleksandr, please give us some time. I can't speak for others, but I am not sitting here idling and hoping that some work (e.g. patches to review) might appear. I have a lot of other stuff to do and will respond when I find some time to look at your patches. Pinging others on Monday when having sent out the patch only on Thursday is rather unfriendly. Really sorry about this, my bad. I had an impression that the only change we need to discuss was uint -> bool change which seemed rather trivial Juergen
Re: [PATCH v2] Input: xen-kbdfront - allow better run-time configuration
Juergen, Jason, Dmitry any comment on this? Thank you, Oleksandr On 04/19/2018 04:39 PM, Oleksandr Andrushchenko wrote: From: Oleksandr Andrushchenko It is now only possible to control if multi-touch virtual device is created or not (via the corresponding XenStore entries), but keyboard and pointer devices are always created. In some cases this is not desirable. For example, if virtual keyboard device is exposed to Android then the latter won't automatically show on-screen keyboard as it expects that a physical keyboard device can be used for typing. Make it possible to configure which virtual devices are created with module parameters: - provide no_ptr_dev if no pointer device needs to be created - provide no_kbd_dev if no keyboard device needs to be created Keep old behavior by default. Signed-off-by: Oleksandr Andrushchenko Suggested-by: Andrii Chepurnyi Tested-by: Andrii Chepurnyi --- Changes since v1: - changed module parameters from uint to bool drivers/input/misc/xen-kbdfront.c | 159 +- 1 file changed, 92 insertions(+), 67 deletions(-) diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index d91f3b1c5375..d8cca212f737 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c @@ -51,6 +51,16 @@ module_param_array(ptr_size, int, NULL, 0444); MODULE_PARM_DESC(ptr_size, "Pointing device width, height in pixels (default 800,600)"); +static bool no_ptr_dev; +module_param(no_ptr_dev, bool, 0); +MODULE_PARM_DESC(no_ptr_dev, + "If set then no virtual pointing device exposed to the guest"); + +static bool no_kbd_dev; +module_param(no_kbd_dev, bool, 0); +MODULE_PARM_DESC(no_kbd_dev, + "If set then no virtual keyboard device exposed to the guest"); + static int xenkbd_remove(struct xenbus_device *); static int xenkbd_connect_backend(struct xenbus_device *, struct xenkbd_info *); static void xenkbd_disconnect_backend(struct xenkbd_info *); @@ -63,6 +73,9 @@ static void xenkbd_disconnect_backend(struct xenkbd_info *); static void xenkbd_handle_motion_event(struct xenkbd_info *info, struct xenkbd_motion *motion) { + if (unlikely(!info->ptr)) + return; + input_report_rel(info->ptr, REL_X, motion->rel_x); input_report_rel(info->ptr, REL_Y, motion->rel_y); if (motion->rel_z) @@ -73,6 +86,9 @@ static void xenkbd_handle_motion_event(struct xenkbd_info *info, static void xenkbd_handle_position_event(struct xenkbd_info *info, struct xenkbd_position *pos) { + if (unlikely(!info->ptr)) + return; + input_report_abs(info->ptr, ABS_X, pos->abs_x); input_report_abs(info->ptr, ABS_Y, pos->abs_y); if (pos->rel_z) @@ -97,6 +113,9 @@ static void xenkbd_handle_key_event(struct xenkbd_info *info, return; } + if (unlikely(!dev)) + return; + input_event(dev, EV_KEY, key->keycode, value); input_sync(dev); } @@ -192,7 +211,7 @@ static int xenkbd_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { int ret, i; - unsigned int abs, touch; + unsigned int touch; struct xenkbd_info *info; struct input_dev *kbd, *ptr, *mtouch; @@ -211,24 +230,6 @@ static int xenkbd_probe(struct xenbus_device *dev, if (!info->page) goto error_nomem; - /* Set input abs params to match backend screen res */ - abs = xenbus_read_unsigned(dev->otherend, - XENKBD_FIELD_FEAT_ABS_POINTER, 0); - ptr_size[KPARAM_X] = xenbus_read_unsigned(dev->otherend, - XENKBD_FIELD_WIDTH, - ptr_size[KPARAM_X]); - ptr_size[KPARAM_Y] = xenbus_read_unsigned(dev->otherend, - XENKBD_FIELD_HEIGHT, - ptr_size[KPARAM_Y]); - if (abs) { - ret = xenbus_write(XBT_NIL, dev->nodename, - XENKBD_FIELD_REQ_ABS_POINTER, "1"); - if (ret) { - pr_warn("xenkbd: can't request abs-pointer\n"); - abs = 0; - } - } - touch = xenbus_read_unsigned(dev->nodename, XENKBD_FIELD_FEAT_MTOUCH, 0); if (touch) { @@ -241,60 +242,84 @@ static int xenkbd_probe(struct xenbus_device *dev, } /* keyboard */ - kbd = input_allocate_device(); - if (!kbd) - goto error_nomem; - kbd->name = "Xen Virtual Keyboard"; - kbd->phys = info-&g
Re: [PATCH v2 0/5] ALSA: xen-front: Add Xen para-virtualized frontend driver
On 04/18/2018 06:15 PM, Oleksandr Andrushchenko wrote: On 04/16/2018 09:24 AM, Oleksandr Andrushchenko wrote: From: Oleksandr Andrushchenko Please note: this patch series depends on [3]. The dependency is now merged into Xen kernel tree [4] for-linus-4.17 The dependency is now pulled into Linus tree [5] This patch series adds support for Xen [1] para-virtualized sound frontend driver. It implements the protocol from include/xen/interface/io/sndif.h with the following limitations: - mute/unmute is not supported - get/set volume is not supported Volume control is not supported for the reason that most of the use-cases (at the moment) are based on scenarious where unprivileged OS (e.g. Android, AGL etc) use software mixers. Both capture and playback are supported. Corresponding backend, implemented as a user-space application, can be found at [2]. Thank you, Oleksandr Changes since v1: * 1. Moved driver from sound/drivers to sound/xen 2. Coding style changes to better meet Linux Kernel 3. Added explicit back and front synchronization In order to provide explicit synchronization between backend and frontend the following changes are introduced in the protocol: - add new ring buffer for sending asynchronous events from backend to frontend to report number of bytes played by the frontend (XENSND_EVT_CUR_POS) - introduce trigger events for playback control: start/stop/pause/resume - add "req-" prefix to event-channel and ring-ref to unify naming of the Xen event channels for requests and events 4. Added explicit back and front parameter negotiation In order to provide explicit stream parameter negotiation between backend and frontend the following changes are introduced in the protocol: add XENSND_OP_HW_PARAM_QUERY request to read/update configuration space for the parameters given: request passes desired parameter's intervals/masks and the response to this request returns allowed min/max intervals/masks to be used. [1] https://xenproject.org/ [2] https://github.com/xen-troops/snd_be [3] https://lkml.org/lkml/2018/4/12/522 Oleksandr Andrushchenko (5): ALSA: xen-front: Introduce Xen para-virtualized sound frontend driver ALSA: xen-front: Read sound driver configuration from Xen store ALSA: xen-front: Implement Xen event channel handling ALSA: xen-front: Implement handling of shared buffers ALSA: xen-front: Implement ALSA virtual sound driver sound/Kconfig | 2 + sound/Makefile | 2 +- sound/xen/Kconfig | 10 + sound/xen/Makefile | 9 + sound/xen/xen_snd_front.c | 410 +++ sound/xen/xen_snd_front.h | 57 +++ sound/xen/xen_snd_front_alsa.c | 830 ++ sound/xen/xen_snd_front_alsa.h | 23 ++ sound/xen/xen_snd_front_cfg.c | 517 sound/xen/xen_snd_front_cfg.h | 46 +++ sound/xen/xen_snd_front_evtchnl.c | 478 ++ sound/xen/xen_snd_front_evtchnl.h | 92 + sound/xen/xen_snd_front_shbuf.c | 193 + sound/xen/xen_snd_front_shbuf.h | 36 ++ 14 files changed, 2704 insertions(+), 1 deletion(-) create mode 100644 sound/xen/Kconfig create mode 100644 sound/xen/Makefile create mode 100644 sound/xen/xen_snd_front.c create mode 100644 sound/xen/xen_snd_front.h create mode 100644 sound/xen/xen_snd_front_alsa.c create mode 100644 sound/xen/xen_snd_front_alsa.h create mode 100644 sound/xen/xen_snd_front_cfg.c create mode 100644 sound/xen/xen_snd_front_cfg.h create mode 100644 sound/xen/xen_snd_front_evtchnl.c create mode 100644 sound/xen/xen_snd_front_evtchnl.h create mode 100644 sound/xen/xen_snd_front_shbuf.c create mode 100644 sound/xen/xen_snd_front_shbuf.h [4] https://git.kernel.org/pub/scm/linux/kernel/git/xen/tip.git/commit/?h=for-linus-4.17&id=cd6e992b3aab072cc90839508aaf5573c8f7e066 [5] https://elixir.bootlin.com/linux/v4.17-rc2/source/include/xen/interface/io/sndif.h
Re: [Xen-devel] [PATCH 0/1] drm/xen-zcopy: Add Xen zero-copy helper DRM driver
On 04/20/2018 10:19 AM, Daniel Vetter wrote: On Wed, Apr 18, 2018 at 11:10:58AM +0100, Roger Pau Monné wrote: On Wed, Apr 18, 2018 at 11:01:12AM +0300, Oleksandr Andrushchenko wrote: On 04/18/2018 10:35 AM, Roger Pau Monné wrote: On Wed, Apr 18, 2018 at 09:38:39AM +0300, Oleksandr Andrushchenko wrote: On 04/17/2018 11:57 PM, Dongwon Kim wrote: On Tue, Apr 17, 2018 at 09:59:28AM +0200, Daniel Vetter wrote: On Mon, Apr 16, 2018 at 12:29:05PM -0700, Dongwon Kim wrote: 3.2 Backend exports dma-buf to xen-front In this case Dom0 pages are shared with DomU. As before, DomU can only write to these pages, not any other page from Dom0, so it can be still considered safe. But, the following must be considered (highlighted in xen-front's Kernel documentation): - If guest domain dies then pages/grants received from the backend cannot be claimed back - think of it as memory lost to Dom0 (won't be used for any other guest) - Misbehaving guest may send too many requests to the backend exhausting its grant references and memory (consider this from security POV). As the backend runs in the trusted domain we also assume that it is trusted as well, e.g. must take measures to prevent DDoS attacks. I cannot parse the above sentence: "As the backend runs in the trusted domain we also assume that it is trusted as well, e.g. must take measures to prevent DDoS attacks." What's the relation between being trusted and protecting from DoS attacks? I mean that we trust the backend that it can prevent Dom0 from crashing in case DomU's frontend misbehaves, e.g. if the frontend sends too many memory requests etc. In any case, all? PV protocols are implemented with the frontend sharing pages to the backend, and I think there's a reason why this model is used, and it should continue to be used. This is the first use-case above. But there are real-world use-cases (embedded in my case) when physically contiguous memory needs to be shared, one of the possible ways to achieve this is to share contiguous memory from Dom0 to DomU (the second use-case above) Having to add logic in the backend to prevent such attacks means that: - We need more code in the backend, which increases complexity and chances of bugs. - Such code/logic could be wrong, thus allowing DoS. You can live without this code at all, but this is then up to backend which may make Dom0 down because of DomU's frontend doing evil things IMO we should design protocols that do not allow such attacks instead of having to defend against them. 4. xen-front/backend/xen-zcopy synchronization 4.1. As I already said in 2) all the inter VM communication happens between xen-front and the backend, xen-zcopy is NOT involved in that. When xen-front wants to destroy a display buffer (dumb/dma-buf) it issues a XENDISPL_OP_DBUF_DESTROY command (opposite to XENDISPL_OP_DBUF_CREATE). This call is synchronous, so xen-front expects that backend does free the buffer pages on return. 4.2. Backend, on XENDISPL_OP_DBUF_DESTROY: - closes all dumb handles/fd's of the buffer according to [3] - issues DRM_IOCTL_XEN_ZCOPY_DUMB_WAIT_FREE IOCTL to xen-zcopy to make sure the buffer is freed (think of it as it waits for dma-buf->release callback) So this zcopy thing keeps some kind of track of the memory usage? Why can't the user-space backend keep track of the buffer usage? Because there is no dma-buf UAPI which allows to track the buffer life cycle (e.g. wait until dma-buf's .release callback is called) - replies to xen-front that the buffer can be destroyed. This way deletion of the buffer happens synchronously on both Dom0 and DomU sides. In case if DRM_IOCTL_XEN_ZCOPY_DUMB_WAIT_FREE returns with time-out error (BTW, wait time is a parameter of this IOCTL), Xen will defer grant reference removal and will retry later until those are free. Hope this helps understand how buffers are synchronously deleted in case of xen-zcopy with a single protocol command. I think the above logic can also be re-used by the hyper-dmabuf driver with some additional work: 1. xen-zcopy can be split into 2 parts and extend: 1.1. Xen gntdev driver [4], [5] to allow creating dma-buf from grefs and vise versa, I don't know much about the dma-buf implementation in Linux, but gntdev is a user-space device, and AFAICT user-space applications don't have any notion of dma buffers. How are such buffers useful for user-space? Why can't this just be called memory? A dma-buf is seen by user-space as a file descriptor and you can pass it to different drivers then. For example, you can share a buffer used by a display driver for scanout with a GPU, to compose a picture into it: 1. User-space (US) allocates a display buffer from display driver 2. US asks display driver to export the dma-buf which backs up that buffer, US gets buffer's fd: dma_buf_fd 3. US asks GPU driver to import
[PATCH v2] Input: xen-kbdfront - allow better run-time configuration
From: Oleksandr Andrushchenko It is now only possible to control if multi-touch virtual device is created or not (via the corresponding XenStore entries), but keyboard and pointer devices are always created. In some cases this is not desirable. For example, if virtual keyboard device is exposed to Android then the latter won't automatically show on-screen keyboard as it expects that a physical keyboard device can be used for typing. Make it possible to configure which virtual devices are created with module parameters: - provide no_ptr_dev if no pointer device needs to be created - provide no_kbd_dev if no keyboard device needs to be created Keep old behavior by default. Signed-off-by: Oleksandr Andrushchenko Suggested-by: Andrii Chepurnyi Tested-by: Andrii Chepurnyi --- Changes since v1: - changed module parameters from uint to bool drivers/input/misc/xen-kbdfront.c | 159 +- 1 file changed, 92 insertions(+), 67 deletions(-) diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index d91f3b1c5375..d8cca212f737 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c @@ -51,6 +51,16 @@ module_param_array(ptr_size, int, NULL, 0444); MODULE_PARM_DESC(ptr_size, "Pointing device width, height in pixels (default 800,600)"); +static bool no_ptr_dev; +module_param(no_ptr_dev, bool, 0); +MODULE_PARM_DESC(no_ptr_dev, + "If set then no virtual pointing device exposed to the guest"); + +static bool no_kbd_dev; +module_param(no_kbd_dev, bool, 0); +MODULE_PARM_DESC(no_kbd_dev, + "If set then no virtual keyboard device exposed to the guest"); + static int xenkbd_remove(struct xenbus_device *); static int xenkbd_connect_backend(struct xenbus_device *, struct xenkbd_info *); static void xenkbd_disconnect_backend(struct xenkbd_info *); @@ -63,6 +73,9 @@ static void xenkbd_disconnect_backend(struct xenkbd_info *); static void xenkbd_handle_motion_event(struct xenkbd_info *info, struct xenkbd_motion *motion) { + if (unlikely(!info->ptr)) + return; + input_report_rel(info->ptr, REL_X, motion->rel_x); input_report_rel(info->ptr, REL_Y, motion->rel_y); if (motion->rel_z) @@ -73,6 +86,9 @@ static void xenkbd_handle_motion_event(struct xenkbd_info *info, static void xenkbd_handle_position_event(struct xenkbd_info *info, struct xenkbd_position *pos) { + if (unlikely(!info->ptr)) + return; + input_report_abs(info->ptr, ABS_X, pos->abs_x); input_report_abs(info->ptr, ABS_Y, pos->abs_y); if (pos->rel_z) @@ -97,6 +113,9 @@ static void xenkbd_handle_key_event(struct xenkbd_info *info, return; } + if (unlikely(!dev)) + return; + input_event(dev, EV_KEY, key->keycode, value); input_sync(dev); } @@ -192,7 +211,7 @@ static int xenkbd_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { int ret, i; - unsigned int abs, touch; + unsigned int touch; struct xenkbd_info *info; struct input_dev *kbd, *ptr, *mtouch; @@ -211,24 +230,6 @@ static int xenkbd_probe(struct xenbus_device *dev, if (!info->page) goto error_nomem; - /* Set input abs params to match backend screen res */ - abs = xenbus_read_unsigned(dev->otherend, - XENKBD_FIELD_FEAT_ABS_POINTER, 0); - ptr_size[KPARAM_X] = xenbus_read_unsigned(dev->otherend, - XENKBD_FIELD_WIDTH, - ptr_size[KPARAM_X]); - ptr_size[KPARAM_Y] = xenbus_read_unsigned(dev->otherend, - XENKBD_FIELD_HEIGHT, - ptr_size[KPARAM_Y]); - if (abs) { - ret = xenbus_write(XBT_NIL, dev->nodename, - XENKBD_FIELD_REQ_ABS_POINTER, "1"); - if (ret) { - pr_warn("xenkbd: can't request abs-pointer\n"); - abs = 0; - } - } - touch = xenbus_read_unsigned(dev->nodename, XENKBD_FIELD_FEAT_MTOUCH, 0); if (touch) { @@ -241,60 +242,84 @@ static int xenkbd_probe(struct xenbus_device *dev, } /* keyboard */ - kbd = input_allocate_device(); - if (!kbd) - goto error_nomem; - kbd->name = "Xen Virtual Keyboard"; - kbd->phys = info->phys; - kbd->id.bustype = BUS_PCI; - kbd->id.vendor = 0x5853; - kbd->id.product = 0x; - - __s
Re: [Xen-devel] [PATCH] Input: xen-kbdfront - allow better run-time configuration
On 04/19/2018 04:19 PM, Juergen Gross wrote: On 19/04/18 15:12, Oleksandr Andrushchenko wrote: On 04/19/2018 04:10 PM, Jason Andryuk wrote: On Thu, Apr 19, 2018 at 9:01 AM, Oleksandr Andrushchenko wrote: Ok, so I'll send v2 with the following changes: diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index a3306aad40b0..d8cca212f737 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c @@ -51,13 +51,13 @@ module_param_array(ptr_size, int, NULL, 0444); MODULE_PARM_DESC(ptr_size, "Pointing device width, height in pixels (default 800,600)"); -static unsigned int no_ptr_dev; -module_param(no_ptr_dev, uint, 0); +static bool no_ptr_dev; +module_param(no_ptr_dev, bool, 0); MODULE_PARM_DESC(no_ptr_dev, "If set then no virtual pointing device exposed to the guest"); -static unsigned int no_kbd_dev; -module_param(no_kbd_dev, uint, 0); +static bool no_kbd_dev; +module_param(no_kbd_dev, bool, 0); MODULE_PARM_DESC(no_kbd_dev, "If set then no virtual keyboard device exposed to the guest"); I prefer direct logic over inverse logic. Maybe just use kbd_dev, default to true, but allow it to be set off? static bool kbd_dev = true; module_param(kbd_dev, bool, 0); I have no preference here, either way works for me Juergen, what do you think about the above? I really have no preference here. What should be taken into account is that boolean parameters don't need a value, meaning "true" in that case. This would make no sense for "kbd_dev" as it wouldn't change the default. Then I'll go with the diff above, e.g. boolean no_{kbd|ptr})dev Juergen
Re: [Xen-devel] [PATCH] Input: xen-kbdfront - allow better run-time configuration
On 04/19/2018 04:10 PM, Jason Andryuk wrote: On Thu, Apr 19, 2018 at 9:01 AM, Oleksandr Andrushchenko wrote: Ok, so I'll send v2 with the following changes: diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index a3306aad40b0..d8cca212f737 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c @@ -51,13 +51,13 @@ module_param_array(ptr_size, int, NULL, 0444); MODULE_PARM_DESC(ptr_size, "Pointing device width, height in pixels (default 800,600)"); -static unsigned int no_ptr_dev; -module_param(no_ptr_dev, uint, 0); +static bool no_ptr_dev; +module_param(no_ptr_dev, bool, 0); MODULE_PARM_DESC(no_ptr_dev, "If set then no virtual pointing device exposed to the guest"); -static unsigned int no_kbd_dev; -module_param(no_kbd_dev, uint, 0); +static bool no_kbd_dev; +module_param(no_kbd_dev, bool, 0); MODULE_PARM_DESC(no_kbd_dev, "If set then no virtual keyboard device exposed to the guest"); I prefer direct logic over inverse logic. Maybe just use kbd_dev, default to true, but allow it to be set off? static bool kbd_dev = true; module_param(kbd_dev, bool, 0); I have no preference here, either way works for me Juergen, what do you think about the above? Regards, Jason
Re: [PATCH] Input: xen-kbdfront - allow better run-time configuration
On 04/19/2018 03:52 PM, Juergen Gross wrote: On 19/04/18 13:44, Oleksandr Andrushchenko wrote: On 04/19/2018 02:25 PM, Juergen Gross wrote: On 18/04/18 17:04, Oleksandr Andrushchenko wrote: From: Oleksandr Andrushchenko It is now only possible to control if multi-touch virtual device is created or not (via the corresponding XenStore entries), but keyboard and pointer devices are always created. Why don't you want to go that route for keyboard and mouse, too? Or does this really make no sense? Well, I would prefer not to touch anything outside Linux and this driver. And these settings seem to be implementation specific. So, this is why introduce Linux module parameters and don't extend the kbdif protocol. In some cases this is not desirable. For example, if virtual keyboard device is exposed to Android then the latter won't automatically show on-screen keyboard as it expects that a physical keyboard device can be used for typing. Make it possible to configure which virtual devices are created with module parameters: - no_ptr_dev=1 if no pointer device needs to be created - no_kbd_dev=1 if no keyboard device needs to be created Keep old behavior by default. Signed-off-by: Oleksandr Andrushchenko Suggested-by: Andrii Chepurnyi Tested-by: Andrii Chepurnyi --- drivers/input/misc/xen-kbdfront.c | 159 +- 1 file changed, 92 insertions(+), 67 deletions(-) diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index d91f3b1c5375..a3306aad40b0 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c @@ -51,6 +51,16 @@ module_param_array(ptr_size, int, NULL, 0444); MODULE_PARM_DESC(ptr_size, "Pointing device width, height in pixels (default 800,600)"); +static unsigned int no_ptr_dev; +module_param(no_ptr_dev, uint, 0); Use type invbool instead? Hm, better bool then? invbool will require parameter name change to something like "with_ptr_dev" which might confuse, e.g. default was to go with pointer device, now we have with_ptr_dev module parameter: do I now need to set it to preserve the old behavior? The answer is no (because of invbool), but you have to dig for it. Will bool work for you? As long as the default won't change from today: yes. Ok, so I'll send v2 with the following changes: diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index a3306aad40b0..d8cca212f737 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c @@ -51,13 +51,13 @@ module_param_array(ptr_size, int, NULL, 0444); MODULE_PARM_DESC(ptr_size, "Pointing device width, height in pixels (default 800,600)"); -static unsigned int no_ptr_dev; -module_param(no_ptr_dev, uint, 0); +static bool no_ptr_dev; +module_param(no_ptr_dev, bool, 0); MODULE_PARM_DESC(no_ptr_dev, "If set then no virtual pointing device exposed to the guest"); -static unsigned int no_kbd_dev; -module_param(no_kbd_dev, uint, 0); +static bool no_kbd_dev; +module_param(no_kbd_dev, bool, 0); MODULE_PARM_DESC(no_kbd_dev, "If set then no virtual keyboard device exposed to the guest"); Juergen
Re: [PATCH] Input: xen-kbdfront - allow better run-time configuration
On 04/19/2018 02:25 PM, Juergen Gross wrote: On 18/04/18 17:04, Oleksandr Andrushchenko wrote: From: Oleksandr Andrushchenko It is now only possible to control if multi-touch virtual device is created or not (via the corresponding XenStore entries), but keyboard and pointer devices are always created. Why don't you want to go that route for keyboard and mouse, too? Or does this really make no sense? Well, I would prefer not to touch anything outside Linux and this driver. And these settings seem to be implementation specific. So, this is why introduce Linux module parameters and don't extend the kbdif protocol. In some cases this is not desirable. For example, if virtual keyboard device is exposed to Android then the latter won't automatically show on-screen keyboard as it expects that a physical keyboard device can be used for typing. Make it possible to configure which virtual devices are created with module parameters: - no_ptr_dev=1 if no pointer device needs to be created - no_kbd_dev=1 if no keyboard device needs to be created Keep old behavior by default. Signed-off-by: Oleksandr Andrushchenko Suggested-by: Andrii Chepurnyi Tested-by: Andrii Chepurnyi --- drivers/input/misc/xen-kbdfront.c | 159 +- 1 file changed, 92 insertions(+), 67 deletions(-) diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index d91f3b1c5375..a3306aad40b0 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c @@ -51,6 +51,16 @@ module_param_array(ptr_size, int, NULL, 0444); MODULE_PARM_DESC(ptr_size, "Pointing device width, height in pixels (default 800,600)"); +static unsigned int no_ptr_dev; +module_param(no_ptr_dev, uint, 0); Use type invbool instead? Hm, better bool then? invbool will require parameter name change to something like "with_ptr_dev" which might confuse, e.g. default was to go with pointer device, now we have with_ptr_dev module parameter: do I now need to set it to preserve the old behavior? The answer is no (because of invbool), but you have to dig for it. Will bool work for you? +MODULE_PARM_DESC(no_ptr_dev, + "If set then no virtual pointing device exposed to the guest"); + +static unsigned int no_kbd_dev; +module_param(no_kbd_dev, uint, 0); invbool? Juergen
Re: [Xen-devel] [PATCH 0/1] drm/xen-zcopy: Add Xen zero-copy helper DRM driver
On 04/18/2018 07:01 PM, Dongwon Kim wrote: On Wed, Apr 18, 2018 at 03:42:29PM +0300, Oleksandr Andrushchenko wrote: On 04/18/2018 01:55 PM, Roger Pau Monné wrote: On Wed, Apr 18, 2018 at 01:39:35PM +0300, Oleksandr Andrushchenko wrote: On 04/18/2018 01:18 PM, Paul Durrant wrote: -Original Message- From: Xen-devel [mailto:xen-devel-boun...@lists.xenproject.org] On Behalf Of Roger Pau Monné Sent: 18 April 2018 11:11 To: Oleksandr Andrushchenko Cc: jgr...@suse.com; Artem Mygaiev ; Dongwon Kim ; airl...@linux.ie; oleksandr_andrushche...@epam.com; linux-kernel@vger.kernel.org; dri- de...@lists.freedesktop.org; Potrola, MateuszX ; xen-de...@lists.xenproject.org; daniel.vet...@intel.com; boris.ostrov...@oracle.com; Matt Roper Subject: Re: [Xen-devel] [PATCH 0/1] drm/xen-zcopy: Add Xen zero-copy helper DRM driver On Wed, Apr 18, 2018 at 11:01:12AM +0300, Oleksandr Andrushchenko wrote: On 04/18/2018 10:35 AM, Roger Pau Monné wrote: After speaking with Oleksandr on IRC, I think the main usage of the gntdev extension is to: 1. Create a dma-buf from a set of grant references. 2. Share dma-buf and get a list of grant references. I think this set of operations could be broken into: 1.1 Map grant references into user-space using the gntdev. 1.2 Create a dma-buf out of a set of user-space virtual addresses. 2.1 Map a dma-buf into user-space. 2.2 Get grefs out of the user-space addresses where the dma-buf is mapped. So it seems like what's actually missing is a way to: - Create a dma-buf from a list of user-space virtual addresses. - Allow to map a dma-buf into user-space, so it can then be used with the gntdev. I think this is generic enough that it could be implemented by a device not tied to Xen. AFAICT the hyper_dma guys also wanted something similar to this. Ok, so just to summarize, xen-zcopy/hyper-dmabuf as they are now, are no go from your POV? FYI, our use-case is "surface sharing" or "graphic obj sharing" where a client application in one guest renders and export this render target(e.g. EGL surface) as dma-buf. This dma-buf is then exported to another guest/host via hyper_dmabuf drv where a compositor is running. This importing domain creates a dmabuf with shared reference then it is imported as EGL image that later can be used as texture object via EGL api. Mapping dmabuf to the userspace or vice versa might be possible with modifying user space drivers/applications but it is an unnecessary extra step from our perspective. +1. I also feel like if it is implemented in the kernel space it will be *much* more easier then inventing workarounds with gntdev, user-space and helper dma-buf driver (which obviously can be implemented). Of course, this approach is easier for Xen as we do not touch its kernel code ;) But there is a demand for changes as number of embedded/multimedia use-cases is constantly growing and we have to react. Also, we want to keep all objects in the kernel level. My opinion is that there seems to be a more generic way to implement this, and thus I would prefer that one. Instead, we have to make all that fancy stuff with VAs <-> device-X and have that device-X driver live out of drivers/xen as it is not a Xen specific driver? That would be my preference if feasible, simply because it can be reused by other use-cases that need to create dma-bufs in user-space. There is a use-case I have: a display unit on my target has a DMA controller which can't do scatter-gather, e.g. it only expects a single starting address of the buffer. In order to create a dma-buf from grefs in this case I allocate memory with dma_alloc_xxx and then balloon pages of the buffer and finally map grefs onto this DMA buffer. This way I can give this shared buffer to the display unit as its bus addresses are contiguous. With the proposed solution (gntdev + device-X) I won't be able to achieve this, as I have no control over from where gntdev/balloon drivers get the pages (even more, those can easily be out of DMA address space of the display unit). Thus, even if implemented, I can't use this approach. In any case I just knew about dma-bufs this morning, there might be things that I'm missing. Roger.
Re: [PATCH 0/1] drm/xen-zcopy: Add Xen zero-copy helper DRM driver
On 04/18/2018 08:01 PM, Dongwon Kim wrote: On Wed, Apr 18, 2018 at 09:38:39AM +0300, Oleksandr Andrushchenko wrote: On 04/17/2018 11:57 PM, Dongwon Kim wrote: On Tue, Apr 17, 2018 at 09:59:28AM +0200, Daniel Vetter wrote: On Mon, Apr 16, 2018 at 12:29:05PM -0700, Dongwon Kim wrote: Yeah, I definitely agree on the idea of expanding the use case to the general domain where dmabuf sharing is used. However, what you are targetting with proposed changes is identical to the core design of hyper_dmabuf. On top of this basic functionalities, hyper_dmabuf has driver level inter-domain communication, that is needed for dma-buf remote tracking (no fence forwarding though), event triggering and event handling, extra meta data exchange and hyper_dmabuf_id that represents grefs (grefs are shared implicitly on driver level) This really isn't a positive design aspect of hyperdmabuf imo. The core code in xen-zcopy (ignoring the ioctl side, which will be cleaned up) is very simple & clean. If there's a clear need later on we can extend that. But for now xen-zcopy seems to cover the basic use-case needs, so gets the job done. Also it is designed with frontend (common core framework) + backend (hyper visor specific comm and memory sharing) structure for portability. We just can't limit this feature to Xen because we want to use the same uapis not only for Xen but also other applicable hypervisor, like ACORN. See the discussion around udmabuf and the needs for kvm. I think trying to make an ioctl/uapi that works for multiple hypervisors is misguided - it likely won't work. On top of that the 2nd hypervisor you're aiming to support is ACRN. That's not even upstream yet, nor have I seen any patches proposing to land linux support for ACRN. Since it's not upstream, it doesn't really matter for upstream consideration. I'm doubting that ACRN will use the same grant references as xen, so the same uapi won't work on ACRN as on Xen anyway. Yeah, ACRN doesn't have grant-table. Only Xen supports it. But that is why hyper_dmabuf has been architectured with the concept of backend. If you look at the structure of backend, you will find that backend is just a set of standard function calls as shown here: struct hyper_dmabuf_bknd_ops { /* backend initialization routine (optional) */ int (*init)(void); /* backend cleanup routine (optional) */ int (*cleanup)(void); /* retreiving id of current virtual machine */ int (*get_vm_id)(void); /* get pages shared via hypervisor-specific method */ int (*share_pages)(struct page **pages, int vm_id, int nents, void **refs_info); /* make shared pages unshared via hypervisor specific method */ int (*unshare_pages)(void **refs_info, int nents); /* map remotely shared pages on importer's side via * hypervisor-specific method */ struct page ** (*map_shared_pages)(unsigned long ref, int vm_id, int nents, void **refs_info); /* unmap and free shared pages on importer's side via * hypervisor-specific method */ int (*unmap_shared_pages)(void **refs_info, int nents); /* initialize communication environment */ int (*init_comm_env)(void); void (*destroy_comm)(void); /* upstream ch setup (receiving and responding) */ int (*init_rx_ch)(int vm_id); /* downstream ch setup (transmitting and parsing responses) */ int (*init_tx_ch)(int vm_id); int (*send_req)(int vm_id, struct hyper_dmabuf_req *req, int wait); }; All of these can be mapped with any hypervisor specific implementation. We designed backend implementation for Xen using grant-table, Xen event and ring buffer communication. For ACRN, we have another backend using Virt-IO for both memory sharing and communication. We tried to define this structure of backend to make it general enough (or it can be even modified or extended to support more cases.) so that it can fit to other hypervisor cases. Only requirements/expectation on the hypervisor are page-level memory sharing and inter-domain communication, which I think are standard features of modern hypervisor. And please review common UAPIs that hyper_dmabuf and xen-zcopy supports. They are very general. One is getting FD (dmabuf) and get those shared. The other is generating dmabuf from global handle (secure handle hiding gref behind it). On top of this, hyper_dmabuf has "unshare" and "query" which are also useful for any cases. So I don't know why we wouldn't want to try to make these standard in most of hypervisor cases instead of limiting it to certain hypervisor like Xen. Frontend-backend structre is optimal for this I think. So I am wondering we can start with this hyper_dmabuf t
Re: [PATCH v2 0/5] ALSA: xen-front: Add Xen para-virtualized frontend driver
On 04/16/2018 09:24 AM, Oleksandr Andrushchenko wrote: From: Oleksandr Andrushchenko Please note: this patch series depends on [3]. The dependency is now merged into Xen kernel tree [4] for-linus-4.17 This patch series adds support for Xen [1] para-virtualized sound frontend driver. It implements the protocol from include/xen/interface/io/sndif.h with the following limitations: - mute/unmute is not supported - get/set volume is not supported Volume control is not supported for the reason that most of the use-cases (at the moment) are based on scenarious where unprivileged OS (e.g. Android, AGL etc) use software mixers. Both capture and playback are supported. Corresponding backend, implemented as a user-space application, can be found at [2]. Thank you, Oleksandr Changes since v1: * 1. Moved driver from sound/drivers to sound/xen 2. Coding style changes to better meet Linux Kernel 3. Added explicit back and front synchronization In order to provide explicit synchronization between backend and frontend the following changes are introduced in the protocol: - add new ring buffer for sending asynchronous events from backend to frontend to report number of bytes played by the frontend (XENSND_EVT_CUR_POS) - introduce trigger events for playback control: start/stop/pause/resume - add "req-" prefix to event-channel and ring-ref to unify naming of the Xen event channels for requests and events 4. Added explicit back and front parameter negotiation In order to provide explicit stream parameter negotiation between backend and frontend the following changes are introduced in the protocol: add XENSND_OP_HW_PARAM_QUERY request to read/update configuration space for the parameters given: request passes desired parameter's intervals/masks and the response to this request returns allowed min/max intervals/masks to be used. [1] https://xenproject.org/ [2] https://github.com/xen-troops/snd_be [3] https://lkml.org/lkml/2018/4/12/522 Oleksandr Andrushchenko (5): ALSA: xen-front: Introduce Xen para-virtualized sound frontend driver ALSA: xen-front: Read sound driver configuration from Xen store ALSA: xen-front: Implement Xen event channel handling ALSA: xen-front: Implement handling of shared buffers ALSA: xen-front: Implement ALSA virtual sound driver sound/Kconfig | 2 + sound/Makefile| 2 +- sound/xen/Kconfig | 10 + sound/xen/Makefile| 9 + sound/xen/xen_snd_front.c | 410 +++ sound/xen/xen_snd_front.h | 57 +++ sound/xen/xen_snd_front_alsa.c| 830 ++ sound/xen/xen_snd_front_alsa.h| 23 ++ sound/xen/xen_snd_front_cfg.c | 517 sound/xen/xen_snd_front_cfg.h | 46 +++ sound/xen/xen_snd_front_evtchnl.c | 478 ++ sound/xen/xen_snd_front_evtchnl.h | 92 + sound/xen/xen_snd_front_shbuf.c | 193 + sound/xen/xen_snd_front_shbuf.h | 36 ++ 14 files changed, 2704 insertions(+), 1 deletion(-) create mode 100644 sound/xen/Kconfig create mode 100644 sound/xen/Makefile create mode 100644 sound/xen/xen_snd_front.c create mode 100644 sound/xen/xen_snd_front.h create mode 100644 sound/xen/xen_snd_front_alsa.c create mode 100644 sound/xen/xen_snd_front_alsa.h create mode 100644 sound/xen/xen_snd_front_cfg.c create mode 100644 sound/xen/xen_snd_front_cfg.h create mode 100644 sound/xen/xen_snd_front_evtchnl.c create mode 100644 sound/xen/xen_snd_front_evtchnl.h create mode 100644 sound/xen/xen_snd_front_shbuf.c create mode 100644 sound/xen/xen_snd_front_shbuf.h [4] https://git.kernel.org/pub/scm/linux/kernel/git/xen/tip.git/commit/?h=for-linus-4.17&id=cd6e992b3aab072cc90839508aaf5573c8f7e066
[PATCH] Input: xen-kbdfront - allow better run-time configuration
From: Oleksandr Andrushchenko It is now only possible to control if multi-touch virtual device is created or not (via the corresponding XenStore entries), but keyboard and pointer devices are always created. In some cases this is not desirable. For example, if virtual keyboard device is exposed to Android then the latter won't automatically show on-screen keyboard as it expects that a physical keyboard device can be used for typing. Make it possible to configure which virtual devices are created with module parameters: - no_ptr_dev=1 if no pointer device needs to be created - no_kbd_dev=1 if no keyboard device needs to be created Keep old behavior by default. Signed-off-by: Oleksandr Andrushchenko Suggested-by: Andrii Chepurnyi Tested-by: Andrii Chepurnyi --- drivers/input/misc/xen-kbdfront.c | 159 +- 1 file changed, 92 insertions(+), 67 deletions(-) diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index d91f3b1c5375..a3306aad40b0 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c @@ -51,6 +51,16 @@ module_param_array(ptr_size, int, NULL, 0444); MODULE_PARM_DESC(ptr_size, "Pointing device width, height in pixels (default 800,600)"); +static unsigned int no_ptr_dev; +module_param(no_ptr_dev, uint, 0); +MODULE_PARM_DESC(no_ptr_dev, + "If set then no virtual pointing device exposed to the guest"); + +static unsigned int no_kbd_dev; +module_param(no_kbd_dev, uint, 0); +MODULE_PARM_DESC(no_kbd_dev, + "If set then no virtual keyboard device exposed to the guest"); + static int xenkbd_remove(struct xenbus_device *); static int xenkbd_connect_backend(struct xenbus_device *, struct xenkbd_info *); static void xenkbd_disconnect_backend(struct xenkbd_info *); @@ -63,6 +73,9 @@ static void xenkbd_disconnect_backend(struct xenkbd_info *); static void xenkbd_handle_motion_event(struct xenkbd_info *info, struct xenkbd_motion *motion) { + if (unlikely(!info->ptr)) + return; + input_report_rel(info->ptr, REL_X, motion->rel_x); input_report_rel(info->ptr, REL_Y, motion->rel_y); if (motion->rel_z) @@ -73,6 +86,9 @@ static void xenkbd_handle_motion_event(struct xenkbd_info *info, static void xenkbd_handle_position_event(struct xenkbd_info *info, struct xenkbd_position *pos) { + if (unlikely(!info->ptr)) + return; + input_report_abs(info->ptr, ABS_X, pos->abs_x); input_report_abs(info->ptr, ABS_Y, pos->abs_y); if (pos->rel_z) @@ -97,6 +113,9 @@ static void xenkbd_handle_key_event(struct xenkbd_info *info, return; } + if (unlikely(!dev)) + return; + input_event(dev, EV_KEY, key->keycode, value); input_sync(dev); } @@ -192,7 +211,7 @@ static int xenkbd_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { int ret, i; - unsigned int abs, touch; + unsigned int touch; struct xenkbd_info *info; struct input_dev *kbd, *ptr, *mtouch; @@ -211,24 +230,6 @@ static int xenkbd_probe(struct xenbus_device *dev, if (!info->page) goto error_nomem; - /* Set input abs params to match backend screen res */ - abs = xenbus_read_unsigned(dev->otherend, - XENKBD_FIELD_FEAT_ABS_POINTER, 0); - ptr_size[KPARAM_X] = xenbus_read_unsigned(dev->otherend, - XENKBD_FIELD_WIDTH, - ptr_size[KPARAM_X]); - ptr_size[KPARAM_Y] = xenbus_read_unsigned(dev->otherend, - XENKBD_FIELD_HEIGHT, - ptr_size[KPARAM_Y]); - if (abs) { - ret = xenbus_write(XBT_NIL, dev->nodename, - XENKBD_FIELD_REQ_ABS_POINTER, "1"); - if (ret) { - pr_warn("xenkbd: can't request abs-pointer\n"); - abs = 0; - } - } - touch = xenbus_read_unsigned(dev->nodename, XENKBD_FIELD_FEAT_MTOUCH, 0); if (touch) { @@ -241,60 +242,84 @@ static int xenkbd_probe(struct xenbus_device *dev, } /* keyboard */ - kbd = input_allocate_device(); - if (!kbd) - goto error_nomem; - kbd->name = "Xen Virtual Keyboard"; - kbd->phys = info->phys; - kbd->id.bustype = BUS_PCI; - kbd->id.vendor = 0x5853; - kbd->id.product = 0x; - - __set_bit(EV_KEY, kbd->evbit); - for (i = KEY_ESC;
Re: [Xen-devel] [PATCH 0/1] drm/xen-zcopy: Add Xen zero-copy helper DRM driver
On 04/18/2018 01:55 PM, Roger Pau Monné wrote: On Wed, Apr 18, 2018 at 01:39:35PM +0300, Oleksandr Andrushchenko wrote: On 04/18/2018 01:18 PM, Paul Durrant wrote: -Original Message- From: Xen-devel [mailto:xen-devel-boun...@lists.xenproject.org] On Behalf Of Roger Pau Monné Sent: 18 April 2018 11:11 To: Oleksandr Andrushchenko Cc: jgr...@suse.com; Artem Mygaiev ; Dongwon Kim ; airl...@linux.ie; oleksandr_andrushche...@epam.com; linux-kernel@vger.kernel.org; dri- de...@lists.freedesktop.org; Potrola, MateuszX ; xen-de...@lists.xenproject.org; daniel.vet...@intel.com; boris.ostrov...@oracle.com; Matt Roper Subject: Re: [Xen-devel] [PATCH 0/1] drm/xen-zcopy: Add Xen zero-copy helper DRM driver On Wed, Apr 18, 2018 at 11:01:12AM +0300, Oleksandr Andrushchenko wrote: On 04/18/2018 10:35 AM, Roger Pau Monné wrote: After speaking with Oleksandr on IRC, I think the main usage of the gntdev extension is to: 1. Create a dma-buf from a set of grant references. 2. Share dma-buf and get a list of grant references. I think this set of operations could be broken into: 1.1 Map grant references into user-space using the gntdev. 1.2 Create a dma-buf out of a set of user-space virtual addresses. 2.1 Map a dma-buf into user-space. 2.2 Get grefs out of the user-space addresses where the dma-buf is mapped. So it seems like what's actually missing is a way to: - Create a dma-buf from a list of user-space virtual addresses. - Allow to map a dma-buf into user-space, so it can then be used with the gntdev. I think this is generic enough that it could be implemented by a device not tied to Xen. AFAICT the hyper_dma guys also wanted something similar to this. Ok, so just to summarize, xen-zcopy/hyper-dmabuf as they are now, are no go from your POV? My opinion is that there seems to be a more generic way to implement this, and thus I would prefer that one. Instead, we have to make all that fancy stuff with VAs <-> device-X and have that device-X driver live out of drivers/xen as it is not a Xen specific driver? That would be my preference if feasible, simply because it can be reused by other use-cases that need to create dma-bufs in user-space. There is a use-case I have: a display unit on my target has a DMA controller which can't do scatter-gather, e.g. it only expects a single starting address of the buffer. In order to create a dma-buf from grefs in this case I allocate memory with dma_alloc_xxx and then balloon pages of the buffer and finally map grefs onto this DMA buffer. This way I can give this shared buffer to the display unit as its bus addresses are contiguous. With the proposed solution (gntdev + device-X) I won't be able to achieve this, as I have no control over from where gntdev/balloon drivers get the pages (even more, those can easily be out of DMA address space of the display unit). Thus, even if implemented, I can't use this approach. In any case I just knew about dma-bufs this morning, there might be things that I'm missing. Roger.
Re: [Xen-devel] [PATCH 0/1] drm/xen-zcopy: Add Xen zero-copy helper DRM driver
On 04/18/2018 01:18 PM, Paul Durrant wrote: -Original Message- From: Xen-devel [mailto:xen-devel-boun...@lists.xenproject.org] On Behalf Of Roger Pau Monné Sent: 18 April 2018 11:11 To: Oleksandr Andrushchenko Cc: jgr...@suse.com; Artem Mygaiev ; Dongwon Kim ; airl...@linux.ie; oleksandr_andrushche...@epam.com; linux-kernel@vger.kernel.org; dri- de...@lists.freedesktop.org; Potrola, MateuszX ; xen-de...@lists.xenproject.org; daniel.vet...@intel.com; boris.ostrov...@oracle.com; Matt Roper Subject: Re: [Xen-devel] [PATCH 0/1] drm/xen-zcopy: Add Xen zero-copy helper DRM driver On Wed, Apr 18, 2018 at 11:01:12AM +0300, Oleksandr Andrushchenko wrote: On 04/18/2018 10:35 AM, Roger Pau Monné wrote: On Wed, Apr 18, 2018 at 09:38:39AM +0300, Oleksandr Andrushchenko wrote: On 04/17/2018 11:57 PM, Dongwon Kim wrote: On Tue, Apr 17, 2018 at 09:59:28AM +0200, Daniel Vetter wrote: On Mon, Apr 16, 2018 at 12:29:05PM -0700, Dongwon Kim wrote: 3.2 Backend exports dma-buf to xen-front In this case Dom0 pages are shared with DomU. As before, DomU can only write to these pages, not any other page from Dom0, so it can be still considered safe. But, the following must be considered (highlighted in xen-front's Kernel documentation): - If guest domain dies then pages/grants received from the backend cannot be claimed back - think of it as memory lost to Dom0 (won't be used for any other guest) - Misbehaving guest may send too many requests to the backend exhausting its grant references and memory (consider this from security POV). As the backend runs in the trusted domain we also assume that it is trusted as well, e.g. must take measures to prevent DDoS attacks. I cannot parse the above sentence: "As the backend runs in the trusted domain we also assume that it is trusted as well, e.g. must take measures to prevent DDoS attacks." What's the relation between being trusted and protecting from DoS attacks? I mean that we trust the backend that it can prevent Dom0 from crashing in case DomU's frontend misbehaves, e.g. if the frontend sends too many memory requests etc. In any case, all? PV protocols are implemented with the frontend sharing pages to the backend, and I think there's a reason why this model is used, and it should continue to be used. This is the first use-case above. But there are real-world use-cases (embedded in my case) when physically contiguous memory needs to be shared, one of the possible ways to achieve this is to share contiguous memory from Dom0 to DomU (the second use-case above) Having to add logic in the backend to prevent such attacks means that: - We need more code in the backend, which increases complexity and chances of bugs. - Such code/logic could be wrong, thus allowing DoS. You can live without this code at all, but this is then up to backend which may make Dom0 down because of DomU's frontend doing evil things IMO we should design protocols that do not allow such attacks instead of having to defend against them. 4. xen-front/backend/xen-zcopy synchronization 4.1. As I already said in 2) all the inter VM communication happens between xen-front and the backend, xen-zcopy is NOT involved in that. When xen-front wants to destroy a display buffer (dumb/dma-buf) it issues a XENDISPL_OP_DBUF_DESTROY command (opposite to XENDISPL_OP_DBUF_CREATE). This call is synchronous, so xen-front expects that backend does free the buffer pages on return. 4.2. Backend, on XENDISPL_OP_DBUF_DESTROY: - closes all dumb handles/fd's of the buffer according to [3] - issues DRM_IOCTL_XEN_ZCOPY_DUMB_WAIT_FREE IOCTL to xen- zcopy to make sure the buffer is freed (think of it as it waits for dma-buf->release callback) So this zcopy thing keeps some kind of track of the memory usage? Why can't the user-space backend keep track of the buffer usage? Because there is no dma-buf UAPI which allows to track the buffer life cycle (e.g. wait until dma-buf's .release callback is called) - replies to xen-front that the buffer can be destroyed. This way deletion of the buffer happens synchronously on both Dom0 and DomU sides. In case if DRM_IOCTL_XEN_ZCOPY_DUMB_WAIT_FREE returns with time-out error (BTW, wait time is a parameter of this IOCTL), Xen will defer grant reference removal and will retry later until those are free. Hope this helps understand how buffers are synchronously deleted in case of xen-zcopy with a single protocol command. I think the above logic can also be re-used by the hyper-dmabuf driver with some additional work: 1. xen-zcopy can be split into 2 parts and extend: 1.1. Xen gntdev driver [4], [5] to allow creating dma-buf from grefs and vise versa, I don't know much about the dma-buf implementation in Linux, but gntdev is a user-space device, and AFAICT user-space applications don't have any notion of dma buffers
Re: [Xen-devel] [PATCH 0/1] drm/xen-zcopy: Add Xen zero-copy helper DRM driver
On 04/18/2018 01:23 PM, Paul Durrant wrote: -Original Message- From: Oleksandr Andrushchenko [mailto:andr2...@gmail.com] Sent: 18 April 2018 11:21 To: Paul Durrant ; Roger Pau Monne Cc: jgr...@suse.com; Artem Mygaiev ; Dongwon Kim ; airl...@linux.ie; oleksandr_andrushche...@epam.com; linux-kernel@vger.kernel.org; dri- de...@lists.freedesktop.org; Potrola, MateuszX ; xen-de...@lists.xenproject.org; daniel.vet...@intel.com; boris.ostrov...@oracle.com; Matt Roper Subject: Re: [Xen-devel] [PATCH 0/1] drm/xen-zcopy: Add Xen zero-copy helper DRM driver On 04/18/2018 01:18 PM, Paul Durrant wrote: -Original Message- From: Xen-devel [mailto:xen-devel-boun...@lists.xenproject.org] On Behalf Of Roger Pau Monné Sent: 18 April 2018 11:11 To: Oleksandr Andrushchenko Cc: jgr...@suse.com; Artem Mygaiev ; Dongwon Kim ; airl...@linux.ie; oleksandr_andrushche...@epam.com; linux-kernel@vger.kernel.org; dri- de...@lists.freedesktop.org; Potrola, MateuszX ; xen-de...@lists.xenproject.org; daniel.vet...@intel.com; boris.ostrov...@oracle.com; Matt Roper Subject: Re: [Xen-devel] [PATCH 0/1] drm/xen-zcopy: Add Xen zero-copy helper DRM driver On Wed, Apr 18, 2018 at 11:01:12AM +0300, Oleksandr Andrushchenko wrote: On 04/18/2018 10:35 AM, Roger Pau Monné wrote: On Wed, Apr 18, 2018 at 09:38:39AM +0300, Oleksandr Andrushchenko wrote: On 04/17/2018 11:57 PM, Dongwon Kim wrote: On Tue, Apr 17, 2018 at 09:59:28AM +0200, Daniel Vetter wrote: On Mon, Apr 16, 2018 at 12:29:05PM -0700, Dongwon Kim wrote: 3.2 Backend exports dma-buf to xen-front In this case Dom0 pages are shared with DomU. As before, DomU can only write to these pages, not any other page from Dom0, so it can be still considered safe. But, the following must be considered (highlighted in xen-front's Kernel documentation): - If guest domain dies then pages/grants received from the backend cannot be claimed back - think of it as memory lost to Dom0 (won't be used for any other guest) - Misbehaving guest may send too many requests to the backend exhausting its grant references and memory (consider this from security POV). As the backend runs in the trusted domain we also assume that it is trusted as well, e.g. must take measures to prevent DDoS attacks. I cannot parse the above sentence: "As the backend runs in the trusted domain we also assume that it is trusted as well, e.g. must take measures to prevent DDoS attacks." What's the relation between being trusted and protecting from DoS attacks? I mean that we trust the backend that it can prevent Dom0 from crashing in case DomU's frontend misbehaves, e.g. if the frontend sends too many memory requests etc. In any case, all? PV protocols are implemented with the frontend sharing pages to the backend, and I think there's a reason why this model is used, and it should continue to be used. This is the first use-case above. But there are real-world use-cases (embedded in my case) when physically contiguous memory needs to be shared, one of the possible ways to achieve this is to share contiguous memory from Dom0 to DomU (the second use-case above) Having to add logic in the backend to prevent such attacks means that: - We need more code in the backend, which increases complexity and chances of bugs. - Such code/logic could be wrong, thus allowing DoS. You can live without this code at all, but this is then up to backend which may make Dom0 down because of DomU's frontend doing evil things IMO we should design protocols that do not allow such attacks instead of having to defend against them. 4. xen-front/backend/xen-zcopy synchronization 4.1. As I already said in 2) all the inter VM communication happens between xen-front and the backend, xen-zcopy is NOT involved in that. When xen-front wants to destroy a display buffer (dumb/dma-buf) it issues a XENDISPL_OP_DBUF_DESTROY command (opposite to XENDISPL_OP_DBUF_CREATE). This call is synchronous, so xen-front expects that backend does free the buffer pages on return. 4.2. Backend, on XENDISPL_OP_DBUF_DESTROY: - closes all dumb handles/fd's of the buffer according to [3] - issues DRM_IOCTL_XEN_ZCOPY_DUMB_WAIT_FREE IOCTL to xen- zcopy to make sure the buffer is freed (think of it as it waits for dma-buf->release callback) So this zcopy thing keeps some kind of track of the memory usage? Why can't the user-space backend keep track of the buffer usage? Because there is no dma-buf UAPI which allows to track the buffer life cycle (e.g. wait until dma-buf's .release callback is called) - replies to xen-front that the buffer can be destroyed. This way deletion of the buffer happens synchronously on both Dom0 and DomU sides. In case if DRM_IOCTL_XEN_ZCOPY_DUMB_WAIT_FREE returns with time-out error (BTW, wait time is a parameter of this IOCTL), Xen will defer grant referenc
Re: [Xen-devel] [PATCH 0/1] drm/xen-zcopy: Add Xen zero-copy helper DRM driver
On 04/18/2018 01:18 PM, Paul Durrant wrote: -Original Message- From: Xen-devel [mailto:xen-devel-boun...@lists.xenproject.org] On Behalf Of Roger Pau Monné Sent: 18 April 2018 11:11 To: Oleksandr Andrushchenko Cc: jgr...@suse.com; Artem Mygaiev ; Dongwon Kim ; airl...@linux.ie; oleksandr_andrushche...@epam.com; linux-kernel@vger.kernel.org; dri- de...@lists.freedesktop.org; Potrola, MateuszX ; xen-de...@lists.xenproject.org; daniel.vet...@intel.com; boris.ostrov...@oracle.com; Matt Roper Subject: Re: [Xen-devel] [PATCH 0/1] drm/xen-zcopy: Add Xen zero-copy helper DRM driver On Wed, Apr 18, 2018 at 11:01:12AM +0300, Oleksandr Andrushchenko wrote: On 04/18/2018 10:35 AM, Roger Pau Monné wrote: On Wed, Apr 18, 2018 at 09:38:39AM +0300, Oleksandr Andrushchenko wrote: On 04/17/2018 11:57 PM, Dongwon Kim wrote: On Tue, Apr 17, 2018 at 09:59:28AM +0200, Daniel Vetter wrote: On Mon, Apr 16, 2018 at 12:29:05PM -0700, Dongwon Kim wrote: 3.2 Backend exports dma-buf to xen-front In this case Dom0 pages are shared with DomU. As before, DomU can only write to these pages, not any other page from Dom0, so it can be still considered safe. But, the following must be considered (highlighted in xen-front's Kernel documentation): - If guest domain dies then pages/grants received from the backend cannot be claimed back - think of it as memory lost to Dom0 (won't be used for any other guest) - Misbehaving guest may send too many requests to the backend exhausting its grant references and memory (consider this from security POV). As the backend runs in the trusted domain we also assume that it is trusted as well, e.g. must take measures to prevent DDoS attacks. I cannot parse the above sentence: "As the backend runs in the trusted domain we also assume that it is trusted as well, e.g. must take measures to prevent DDoS attacks." What's the relation between being trusted and protecting from DoS attacks? I mean that we trust the backend that it can prevent Dom0 from crashing in case DomU's frontend misbehaves, e.g. if the frontend sends too many memory requests etc. In any case, all? PV protocols are implemented with the frontend sharing pages to the backend, and I think there's a reason why this model is used, and it should continue to be used. This is the first use-case above. But there are real-world use-cases (embedded in my case) when physically contiguous memory needs to be shared, one of the possible ways to achieve this is to share contiguous memory from Dom0 to DomU (the second use-case above) Having to add logic in the backend to prevent such attacks means that: - We need more code in the backend, which increases complexity and chances of bugs. - Such code/logic could be wrong, thus allowing DoS. You can live without this code at all, but this is then up to backend which may make Dom0 down because of DomU's frontend doing evil things IMO we should design protocols that do not allow such attacks instead of having to defend against them. 4. xen-front/backend/xen-zcopy synchronization 4.1. As I already said in 2) all the inter VM communication happens between xen-front and the backend, xen-zcopy is NOT involved in that. When xen-front wants to destroy a display buffer (dumb/dma-buf) it issues a XENDISPL_OP_DBUF_DESTROY command (opposite to XENDISPL_OP_DBUF_CREATE). This call is synchronous, so xen-front expects that backend does free the buffer pages on return. 4.2. Backend, on XENDISPL_OP_DBUF_DESTROY: - closes all dumb handles/fd's of the buffer according to [3] - issues DRM_IOCTL_XEN_ZCOPY_DUMB_WAIT_FREE IOCTL to xen- zcopy to make sure the buffer is freed (think of it as it waits for dma-buf->release callback) So this zcopy thing keeps some kind of track of the memory usage? Why can't the user-space backend keep track of the buffer usage? Because there is no dma-buf UAPI which allows to track the buffer life cycle (e.g. wait until dma-buf's .release callback is called) - replies to xen-front that the buffer can be destroyed. This way deletion of the buffer happens synchronously on both Dom0 and DomU sides. In case if DRM_IOCTL_XEN_ZCOPY_DUMB_WAIT_FREE returns with time-out error (BTW, wait time is a parameter of this IOCTL), Xen will defer grant reference removal and will retry later until those are free. Hope this helps understand how buffers are synchronously deleted in case of xen-zcopy with a single protocol command. I think the above logic can also be re-used by the hyper-dmabuf driver with some additional work: 1. xen-zcopy can be split into 2 parts and extend: 1.1. Xen gntdev driver [4], [5] to allow creating dma-buf from grefs and vise versa, I don't know much about the dma-buf implementation in Linux, but gntdev is a user-space device, and AFAICT user-space applications don't have any notion of dma buffers
Re: [Xen-devel] [PATCH 0/1] drm/xen-zcopy: Add Xen zero-copy helper DRM driver
On 04/18/2018 10:35 AM, Roger Pau Monné wrote: On Wed, Apr 18, 2018 at 09:38:39AM +0300, Oleksandr Andrushchenko wrote: On 04/17/2018 11:57 PM, Dongwon Kim wrote: On Tue, Apr 17, 2018 at 09:59:28AM +0200, Daniel Vetter wrote: On Mon, Apr 16, 2018 at 12:29:05PM -0700, Dongwon Kim wrote: 3.2 Backend exports dma-buf to xen-front In this case Dom0 pages are shared with DomU. As before, DomU can only write to these pages, not any other page from Dom0, so it can be still considered safe. But, the following must be considered (highlighted in xen-front's Kernel documentation): - If guest domain dies then pages/grants received from the backend cannot be claimed back - think of it as memory lost to Dom0 (won't be used for any other guest) - Misbehaving guest may send too many requests to the backend exhausting its grant references and memory (consider this from security POV). As the backend runs in the trusted domain we also assume that it is trusted as well, e.g. must take measures to prevent DDoS attacks. I cannot parse the above sentence: "As the backend runs in the trusted domain we also assume that it is trusted as well, e.g. must take measures to prevent DDoS attacks." What's the relation between being trusted and protecting from DoS attacks? I mean that we trust the backend that it can prevent Dom0 from crashing in case DomU's frontend misbehaves, e.g. if the frontend sends too many memory requests etc. In any case, all? PV protocols are implemented with the frontend sharing pages to the backend, and I think there's a reason why this model is used, and it should continue to be used. This is the first use-case above. But there are real-world use-cases (embedded in my case) when physically contiguous memory needs to be shared, one of the possible ways to achieve this is to share contiguous memory from Dom0 to DomU (the second use-case above) Having to add logic in the backend to prevent such attacks means that: - We need more code in the backend, which increases complexity and chances of bugs. - Such code/logic could be wrong, thus allowing DoS. You can live without this code at all, but this is then up to backend which may make Dom0 down because of DomU's frontend doing evil things 4. xen-front/backend/xen-zcopy synchronization 4.1. As I already said in 2) all the inter VM communication happens between xen-front and the backend, xen-zcopy is NOT involved in that. When xen-front wants to destroy a display buffer (dumb/dma-buf) it issues a XENDISPL_OP_DBUF_DESTROY command (opposite to XENDISPL_OP_DBUF_CREATE). This call is synchronous, so xen-front expects that backend does free the buffer pages on return. 4.2. Backend, on XENDISPL_OP_DBUF_DESTROY: - closes all dumb handles/fd's of the buffer according to [3] - issues DRM_IOCTL_XEN_ZCOPY_DUMB_WAIT_FREE IOCTL to xen-zcopy to make sure the buffer is freed (think of it as it waits for dma-buf->release callback) So this zcopy thing keeps some kind of track of the memory usage? Why can't the user-space backend keep track of the buffer usage? Because there is no dma-buf UAPI which allows to track the buffer life cycle (e.g. wait until dma-buf's .release callback is called) - replies to xen-front that the buffer can be destroyed. This way deletion of the buffer happens synchronously on both Dom0 and DomU sides. In case if DRM_IOCTL_XEN_ZCOPY_DUMB_WAIT_FREE returns with time-out error (BTW, wait time is a parameter of this IOCTL), Xen will defer grant reference removal and will retry later until those are free. Hope this helps understand how buffers are synchronously deleted in case of xen-zcopy with a single protocol command. I think the above logic can also be re-used by the hyper-dmabuf driver with some additional work: 1. xen-zcopy can be split into 2 parts and extend: 1.1. Xen gntdev driver [4], [5] to allow creating dma-buf from grefs and vise versa, I don't know much about the dma-buf implementation in Linux, but gntdev is a user-space device, and AFAICT user-space applications don't have any notion of dma buffers. How are such buffers useful for user-space? Why can't this just be called memory? A dma-buf is seen by user-space as a file descriptor and you can pass it to different drivers then. For example, you can share a buffer used by a display driver for scanout with a GPU, to compose a picture into it: 1. User-space (US) allocates a display buffer from display driver 2. US asks display driver to export the dma-buf which backs up that buffer, US gets buffer's fd: dma_buf_fd 3. US asks GPU driver to import a buffer and provides it with dma_buf_fd 4. GPU renders contents into display buffer (dma_buf_fd) Finally, this is indeed some memory, but a bit more [1] Also, (with my FreeBSD maintainer hat) how is this going to translate to other OSes? So far the operations performed by the gntdev device are mostly OS
Re: [PATCH] drm/xen-front: Remove CMA support
On 04/17/2018 12:08 PM, Oleksandr Andrushchenko wrote: On 04/17/2018 12:04 PM, Daniel Vetter wrote: On Tue, Apr 17, 2018 at 10:40:12AM +0300, Oleksandr Andrushchenko wrote: From: Oleksandr Andrushchenko Even if xen-front allocates its buffers from contiguous memory those are still not contiguous in PA space, e.g. the buffer is only contiguous in IPA space. The only use-case for this mode was if xen-front is used to allocate dumb buffers which later be used by some other driver requiring contiguous memory, but there is no currently such a use-case or it can be worked around with xen-front. Please also mention the nents confusion here, and the patch that fixes it. Or just outright take the commit message from my patch with all the details: ok, if you don't mind then I'll use your commit message entirely drm/xen: Dissable CMA support It turns out this was only needed to paper over a bug in the CMA helpers, which was addressed in commit 998fb1a0f478b83492220ff79583bf9ad538bdd8 Author: Liviu Dudau Date: Fri Nov 10 13:33:10 2017 + drm: gem_cma_helper.c: Allow importing of contiguous scatterlists with nents > 1 Without this the following pipeline didn't work: domU: 1. xen-front allocates a non-contig buffer 2. creates grants out of it dom0: 3. converts the grants into a dma-buf. Since they're non-contig, the scatter-list is huge. 4. imports it into rcar-du, which requires dma-contig memory for scanout. -> On this given platform there's an IOMMU, so in theory this should work. But in practice this failed, because of the huge number of sg entries, even though the IOMMU driver mapped it all into a dma-contig range. With a guest-contig buffer allocated in step 1, this problem doesn't exist. But there's technically no reason to require guest-contig memory for xen buffer sharing using grants. With the commit message improved: Acked-by: Daniel Vetter Thank you, I'll wait for a day and apply to drm-misc-next if this is ok applied to drm-misc-next Signed-off-by: Oleksandr Andrushchenko Suggested-by: Daniel Vetter --- Documentation/gpu/xen-front.rst | 12 drivers/gpu/drm/xen/Kconfig | 13 drivers/gpu/drm/xen/Makefile | 9 +-- drivers/gpu/drm/xen/xen_drm_front.c | 62 +++- drivers/gpu/drm/xen/xen_drm_front.h | 42 ++- drivers/gpu/drm/xen/xen_drm_front_gem.c | 12 +--- drivers/gpu/drm/xen/xen_drm_front_gem.h | 3 - drivers/gpu/drm/xen/xen_drm_front_gem_cma.c | 79 - drivers/gpu/drm/xen/xen_drm_front_shbuf.c | 22 -- drivers/gpu/drm/xen/xen_drm_front_shbuf.h | 8 --- 10 files changed, 21 insertions(+), 241 deletions(-) delete mode 100644 drivers/gpu/drm/xen/xen_drm_front_gem_cma.c diff --git a/Documentation/gpu/xen-front.rst b/Documentation/gpu/xen-front.rst index 009d942386c5..d988da7d1983 100644 --- a/Documentation/gpu/xen-front.rst +++ b/Documentation/gpu/xen-front.rst @@ -18,18 +18,6 @@ Buffers allocated by the frontend driver .. kernel-doc:: drivers/gpu/drm/xen/xen_drm_front.h :doc: Buffers allocated by the frontend driver -With GEM CMA helpers - - -.. kernel-doc:: drivers/gpu/drm/xen/xen_drm_front.h - :doc: With GEM CMA helpers - -Without GEM CMA helpers -~~~ - -.. kernel-doc:: drivers/gpu/drm/xen/xen_drm_front.h - :doc: Without GEM CMA helpers - Buffers allocated by the backend diff --git a/drivers/gpu/drm/xen/Kconfig b/drivers/gpu/drm/xen/Kconfig index 4f4abc91f3b6..4cca160782ab 100644 --- a/drivers/gpu/drm/xen/Kconfig +++ b/drivers/gpu/drm/xen/Kconfig @@ -15,16 +15,3 @@ config DRM_XEN_FRONTEND help Choose this option if you want to enable a para-virtualized frontend DRM/KMS driver for Xen guest OSes. - -config DRM_XEN_FRONTEND_CMA - bool "Use DRM CMA to allocate dumb buffers" - depends on DRM_XEN_FRONTEND - select DRM_KMS_CMA_HELPER - select DRM_GEM_CMA_HELPER - help - Use DRM CMA helpers to allocate display buffers. - This is useful for the use-cases when guest driver needs to - share or export buffers to other drivers which only expect - contiguous buffers. - Note: in this mode driver cannot use buffers allocated - by the backend. diff --git a/drivers/gpu/drm/xen/Makefile b/drivers/gpu/drm/xen/Makefile index 352730dc6c13..712afff5ffc3 100644 --- a/drivers/gpu/drm/xen/Makefile +++ b/drivers/gpu/drm/xen/Makefile @@ -5,12 +5,7 @@ drm_xen_front-objs := xen_drm_front.o \ xen_drm_front_conn.o \ xen_drm_front_evtchnl.o \ xen_drm_front_shbuf.o \ - xen_drm_front_cfg.o - -ifeq ($(CONFIG_DRM_XEN_FRONTEND_CM
Re: [PATCH 0/1] drm/xen-zcopy: Add Xen zero-copy helper DRM driver
_REFS, DRM_XEN_ZCOPY_DUMB_TO_REFS and DRM_XEN_ZCOPY_DUMB_WAIT_FREE 1.2. Xen balloon driver [6] to allow allocating contiguous buffers (not needed by current hyper-dmabuf, but is a must for xen-zcopy use-cases) 2. Then hyper-dmabuf uses Xen gntdev driver for Xen specific dma-buf alloc/free/wait 3. hyper-dmabuf uses its own protocol between VMs to communicate buffer creation/deletion and whatever else is needed (fences?). To Xen community: please think of dma-buf here as of a buffer representation mechanism, e.g. at the end of the day it's just a set of pages. Thank you, Oleksandr -Daniel Regards, DW On Mon, Apr 16, 2018 at 05:33:46PM +0300, Oleksandr Andrushchenko wrote: Hello, all! After discussing xen-zcopy and hyper-dmabuf [1] approaches it seems that xen-zcopy can be made not depend on DRM core any more and be dma-buf centric (which it in fact is). The DRM code was mostly there for dma-buf's FD import/export with DRM PRIME UAPI and with DRM use-cases in mind, but it comes out that if the proposed 2 IOCTLs (DRM_XEN_ZCOPY_DUMB_FROM_REFS and DRM_XEN_ZCOPY_DUMB_TO_REFS) are extended to also provide a file descriptor of the corresponding dma-buf, then PRIME stuff in the driver is not needed anymore. That being said, xen-zcopy can safely be detached from DRM and moved from drivers/gpu/drm/xen into drivers/xen/dma-buf-backend(?). This driver then becomes a universal way to turn any shared buffer between Dom0/DomD and DomU(s) into a dma-buf, e.g. one can create a dma-buf from any grant references or represent a dma-buf as grant-references for export. This way the driver can be used not only for DRM use-cases, but also for other use-cases which may require zero copying between domains. For example, the use-cases we are about to work in the nearest future will use V4L, e.g. we plan to support cameras, codecs etc. and all these will benefit from zero copying much. Potentially, even block/net devices may benefit, but this needs some evaluation. I would love to hear comments for authors of the hyper-dmabuf and Xen community, as well as DRI-Devel and other interested parties. Thank you, Oleksandr On 03/29/2018 04:19 PM, Oleksandr Andrushchenko wrote: From: Oleksandr Andrushchenko Hello! When using Xen PV DRM frontend driver then on backend side one will need to do copying of display buffers' contents (filled by the frontend's user-space) into buffers allocated at the backend side. Taking into account the size of display buffers and frames per seconds it may result in unneeded huge data bus occupation and performance loss. This helper driver allows implementing zero-copying use-cases when using Xen para-virtualized frontend display driver by implementing a DRM/KMS helper driver running on backend's side. It utilizes PRIME buffers API to share frontend's buffers with physical device drivers on backend's side: - a dumb buffer created on backend's side can be shared with the Xen PV frontend driver, so it directly writes into backend's domain memory (into the buffer exported from DRM/KMS driver of a physical display device) - a dumb buffer allocated by the frontend can be imported into physical device DRM/KMS driver, thus allowing to achieve no copying as well For that reason number of IOCTLs are introduced: - DRM_XEN_ZCOPY_DUMB_FROM_REFS This will create a DRM dumb buffer from grant references provided by the frontend - DRM_XEN_ZCOPY_DUMB_TO_REFS This will grant references to a dumb/display buffer's memory provided by the backend - DRM_XEN_ZCOPY_DUMB_WAIT_FREE This will block until the dumb buffer with the wait handle provided be freed With this helper driver I was able to drop CPU usage from 17% to 3% on Renesas R-Car M3 board. This was tested with Renesas' Wayland-KMS and backend running as DRM master. Thank you, Oleksandr Oleksandr Andrushchenko (1): drm/xen-zcopy: Add Xen zero-copy helper DRM driver Documentation/gpu/drivers.rst | 1 + Documentation/gpu/xen-zcopy.rst | 32 + drivers/gpu/drm/xen/Kconfig | 25 + drivers/gpu/drm/xen/Makefile| 5 + drivers/gpu/drm/xen/xen_drm_zcopy.c | 880 drivers/gpu/drm/xen/xen_drm_zcopy_balloon.c | 154 + drivers/gpu/drm/xen/xen_drm_zcopy_balloon.h | 38 ++ include/uapi/drm/xen_zcopy_drm.h| 129 8 files changed, 1264 insertions(+) create mode 100644 Documentation/gpu/xen-zcopy.rst create mode 100644 drivers/gpu/drm/xen/xen_drm_zcopy.c create mode 100644 drivers/gpu/drm/xen/xen_drm_zcopy_balloon.c create mode 100644 drivers/gpu/drm/xen/xen_drm_zcopy_balloon.h create mode 100644 include/uapi/drm/xen_zcopy_drm.h [1] https://lists.xenproject.org/archives/html/xen-devel/2018-02/msg01202.html ___ dri-devel mailing list dri-de.
Re: [PATCH v2 0/5] ALSA: xen-front: Add Xen para-virtualized frontend driver
Hello, Juergen! Thank you very much for reviewing the driver and providing valuable comments! I will send v3 of the driver once I have more reviews, especially I hope ALSA community can also take a look Also, as you suggested on IRC, I will add a patch for adding myself as sound/xen maintainer. Thank you, Oleksandr On 04/16/2018 09:24 AM, Oleksandr Andrushchenko wrote: From: Oleksandr Andrushchenko Please note: this patch series depends on [3]. This patch series adds support for Xen [1] para-virtualized sound frontend driver. It implements the protocol from include/xen/interface/io/sndif.h with the following limitations: - mute/unmute is not supported - get/set volume is not supported Volume control is not supported for the reason that most of the use-cases (at the moment) are based on scenarious where unprivileged OS (e.g. Android, AGL etc) use software mixers. Both capture and playback are supported. Corresponding backend, implemented as a user-space application, can be found at [2]. Thank you, Oleksandr Changes since v1: * 1. Moved driver from sound/drivers to sound/xen 2. Coding style changes to better meet Linux Kernel 3. Added explicit back and front synchronization In order to provide explicit synchronization between backend and frontend the following changes are introduced in the protocol: - add new ring buffer for sending asynchronous events from backend to frontend to report number of bytes played by the frontend (XENSND_EVT_CUR_POS) - introduce trigger events for playback control: start/stop/pause/resume - add "req-" prefix to event-channel and ring-ref to unify naming of the Xen event channels for requests and events 4. Added explicit back and front parameter negotiation In order to provide explicit stream parameter negotiation between backend and frontend the following changes are introduced in the protocol: add XENSND_OP_HW_PARAM_QUERY request to read/update configuration space for the parameters given: request passes desired parameter's intervals/masks and the response to this request returns allowed min/max intervals/masks to be used. [1] https://xenproject.org/ [2] https://github.com/xen-troops/snd_be [3] https://lkml.org/lkml/2018/4/12/522 Oleksandr Andrushchenko (5): ALSA: xen-front: Introduce Xen para-virtualized sound frontend driver ALSA: xen-front: Read sound driver configuration from Xen store ALSA: xen-front: Implement Xen event channel handling ALSA: xen-front: Implement handling of shared buffers ALSA: xen-front: Implement ALSA virtual sound driver sound/Kconfig | 2 + sound/Makefile| 2 +- sound/xen/Kconfig | 10 + sound/xen/Makefile| 9 + sound/xen/xen_snd_front.c | 410 +++ sound/xen/xen_snd_front.h | 57 +++ sound/xen/xen_snd_front_alsa.c| 830 ++ sound/xen/xen_snd_front_alsa.h| 23 ++ sound/xen/xen_snd_front_cfg.c | 517 sound/xen/xen_snd_front_cfg.h | 46 +++ sound/xen/xen_snd_front_evtchnl.c | 478 ++ sound/xen/xen_snd_front_evtchnl.h | 92 + sound/xen/xen_snd_front_shbuf.c | 193 + sound/xen/xen_snd_front_shbuf.h | 36 ++ 14 files changed, 2704 insertions(+), 1 deletion(-) create mode 100644 sound/xen/Kconfig create mode 100644 sound/xen/Makefile create mode 100644 sound/xen/xen_snd_front.c create mode 100644 sound/xen/xen_snd_front.h create mode 100644 sound/xen/xen_snd_front_alsa.c create mode 100644 sound/xen/xen_snd_front_alsa.h create mode 100644 sound/xen/xen_snd_front_cfg.c create mode 100644 sound/xen/xen_snd_front_cfg.h create mode 100644 sound/xen/xen_snd_front_evtchnl.c create mode 100644 sound/xen/xen_snd_front_evtchnl.h create mode 100644 sound/xen/xen_snd_front_shbuf.c create mode 100644 sound/xen/xen_snd_front_shbuf.h