[PATCH 2/2] vhost: convert get_user_pages() --> pin_user_pages()
This code was using get_user_pages*(), in approximately a "Case 5" scenario (accessing the data within a page), using the categorization from [1]. That means that it's time to convert the get_user_pages*() + put_page() calls to pin_user_pages*() + unpin_user_pages() calls. There is some helpful background in [2]: basically, this is a small part of fixing a long-standing disconnect between pinning pages, and file systems' use of those pages. [1] Documentation/core-api/pin_user_pages.rst [2] "Explicit pinning of user-space pages": https://lwn.net/Articles/807108/ Cc: Michael S. Tsirkin Cc: Jason Wang Cc: k...@vger.kernel.org Cc: virtualization@lists.linux-foundation.org Cc: net...@vger.kernel.org Signed-off-by: John Hubbard --- drivers/vhost/vhost.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 21a59b598ed8..596132a96cd5 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -1762,15 +1762,14 @@ static int set_bit_to_user(int nr, void __user *addr) int bit = nr + (log % PAGE_SIZE) * 8; int r; - r = get_user_pages_fast(log, 1, FOLL_WRITE, ); + r = pin_user_pages_fast(log, 1, FOLL_WRITE, ); if (r < 0) return r; BUG_ON(r != 1); base = kmap_atomic(page); set_bit(bit, base); kunmap_atomic(base); - set_page_dirty_lock(page); - put_page(page); + unpin_user_pages_dirty_lock(, 1, true); return 0; } -- 2.26.2 ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH 1/2] docs: mm/gup: pin_user_pages.rst: add a "case 5"
There are four cases listed in pin_user_pages.rst. These are intended to help developers figure out whether to use get_user_pages*(), or pin_user_pages*(). However, the four cases do not cover all the situations. For example, drivers/vhost/vhost.c has a "pin, write to page, set page dirty, unpin" case. Add a fifth case, to help explain that there is a general pattern that requires pin_user_pages*() API calls. Cc: Vlastimil Babka Cc: Jan Kara Cc: Jérôme Glisse Cc: Dave Chinner Cc: Jonathan Corbet Cc: linux-...@vger.kernel.org Cc: linux-fsde...@vger.kernel.org Signed-off-by: John Hubbard --- Documentation/core-api/pin_user_pages.rst | 20 1 file changed, 20 insertions(+) diff --git a/Documentation/core-api/pin_user_pages.rst b/Documentation/core-api/pin_user_pages.rst index 4675b04e8829..b9f2688a2c67 100644 --- a/Documentation/core-api/pin_user_pages.rst +++ b/Documentation/core-api/pin_user_pages.rst @@ -171,6 +171,26 @@ If only struct page data (as opposed to the actual memory contents that a page is tracking) is affected, then normal GUP calls are sufficient, and neither flag needs to be set. +CASE 5: Pinning in order to write to the data within the page +- +Even though neither DMA nor Direct IO is involved, just a simple case of "pin, +access page's data, unpin" can cause a problem. Case 5 may be considered a +superset of Case 1, plus Case 2, plus anything that invokes that pattern. In +other words, if the code is neither Case 1 nor Case 2, it may still require +FOLL_PIN, for patterns like this: + +Correct (uses FOLL_PIN calls): +pin_user_pages() +access the data within the pages +set_page_dirty_lock() +unpin_user_pages() + +INCORRECT (uses FOLL_GET calls): +get_user_pages() +access the data within the pages +set_page_dirty_lock() +put_page() + page_maybe_dma_pinned(): the whole point of pinning === -- 2.26.2 ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH 0/2] vhost, docs: convert to pin_user_pages(), new "case 5"
Hi, It recently became clear to me that there are some get_user_pages*() callers that don't fit neatly into any of the four cases that are so far listed in pin_user_pages.rst. vhost.c is one of those. Add a Case 5 to the documentation, and refer to that when converting vhost.c. Thanks to Jan Kara for helping me (again) in understanding the interaction between get_user_pages() and page writeback [1]. This is based on today's mmotm, which has a nearby patch to pin_user_pages.rst that rewords cases 3 and 4. Note that I have only compile-tested the vhost.c patch, although that does also include cross-compiling for a few other arches. Any run-time testing would be greatly appreciated. [1] https://lore.kernel.org/r/20200529070343.gl14...@quack2.suse.cz John Hubbard (2): docs: mm/gup: pin_user_pages.rst: add a "case 5" vhost: convert get_user_pages() --> pin_user_pages() Documentation/core-api/pin_user_pages.rst | 20 drivers/vhost/vhost.c | 5 ++--- 2 files changed, 22 insertions(+), 3 deletions(-) -- 2.26.2 ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Re: [PATCH 4/6] vhost_vdpa: support doorbell mapping via mmap
Given the need for 4K doorbell such that QEMU can easily map, ect, and assuming that I have a HW device which exposes 2 VQ's, with a notification area off of BAR3, offset=whatever, notifier_multiplier=4, we don't need to have 2 x 4K pages mapped into the VM for both doorbells do we? The guest driver would ring DB0 at BAR4+offset, and DB1 at BAR4+offset+(4*1). The 4K per DB is useful how? This allows for QEMU trapping of individual DBs, that can then be used to do what, just forward the DBs via some other scheme - this makes sense for non-HW related Virtio devices I guess. Is this why there is a qemu option? Rob Miller rob.mil...@broadcom.com (919)721-3339 On Fri, May 29, 2020 at 4:03 AM Jason Wang wrote: > Currently the doorbell is relayed via eventfd which may have > significant overhead because of the cost of vmexits or syscall. This > patch introduces mmap() based doorbell mapping which can eliminate the > overhead caused by vmexit or syscall. > > To ease the userspace modeling of the doorbell layout (usually > virtio-pci), this patch starts from a doorbell per page > model. Vhost-vdpa only support the hardware doorbell that sit at the > boundary of a page and does not share the page with other registers. > > Doorbell of each virtqueue must be mapped separately, pgoff is the > index of the virtqueue. This allows userspace to map a subset of the > doorbell which may be useful for the implementation of software > assisted virtqueue (control vq) in the future. > > Signed-off-by: Jason Wang > --- > drivers/vhost/vdpa.c | 59 > 1 file changed, 59 insertions(+) > > diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c > index 6ff72289f488..bbe23cea139a 100644 > --- a/drivers/vhost/vdpa.c > +++ b/drivers/vhost/vdpa.c > @@ -15,6 +15,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -741,12 +742,70 @@ static int vhost_vdpa_release(struct inode *inode, > struct file *filep) > return 0; > } > > +static vm_fault_t vhost_vdpa_fault(struct vm_fault *vmf) > +{ > + struct vhost_vdpa *v = vmf->vma->vm_file->private_data; > + struct vdpa_device *vdpa = v->vdpa; > + const struct vdpa_config_ops *ops = vdpa->config; > + struct vdpa_notification_area notify; > + struct vm_area_struct *vma = vmf->vma; > + u16 index = vma->vm_pgoff; > + > + notify = ops->get_vq_notification(vdpa, index); > + > + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); > + if (remap_pfn_range(vma, vmf->address & PAGE_MASK, > + notify.addr >> PAGE_SHIFT, PAGE_SIZE, > + vma->vm_page_prot)) > + return VM_FAULT_SIGBUS; > + > + return VM_FAULT_NOPAGE; > +} > + > +static const struct vm_operations_struct vhost_vdpa_vm_ops = { > + .fault = vhost_vdpa_fault, > +}; > + > +static int vhost_vdpa_mmap(struct file *file, struct vm_area_struct *vma) > +{ > + struct vhost_vdpa *v = vma->vm_file->private_data; > + struct vdpa_device *vdpa = v->vdpa; > + const struct vdpa_config_ops *ops = vdpa->config; > + struct vdpa_notification_area notify; > + int index = vma->vm_pgoff; > + > + if (vma->vm_end - vma->vm_start != PAGE_SIZE) > + return -EINVAL; > + if ((vma->vm_flags & VM_SHARED) == 0) > + return -EINVAL; > + if (vma->vm_flags & VM_READ) > + return -EINVAL; > + if (index > 65535) > + return -EINVAL; > + if (!ops->get_vq_notification) > + return -ENOTSUPP; > + > + /* To be safe and easily modelled by userspace, We only > +* support the doorbell which sits on the page boundary and > +* does not share the page with other registers. > +*/ > + notify = ops->get_vq_notification(vdpa, index); > + if (notify.addr & (PAGE_SIZE - 1)) > + return -EINVAL; > + if (vma->vm_end - vma->vm_start != notify.size) > + return -ENOTSUPP; > + > + vma->vm_ops = _vdpa_vm_ops; > + return 0; > +} > + > static const struct file_operations vhost_vdpa_fops = { > .owner = THIS_MODULE, > .open = vhost_vdpa_open, > .release= vhost_vdpa_release, > .write_iter = vhost_vdpa_chr_write_iter, > .unlocked_ioctl = vhost_vdpa_unlocked_ioctl, > + .mmap = vhost_vdpa_mmap, > .compat_ioctl = compat_ptr_ioctl, > }; > > -- > 2.20.1 > > ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Re: [PATCH v2] virtio_vsock: Fix race condition in virtio_transport_recv_pkt
On Fri, May 29, 2020 at 11:21:02PM +0800, Jia He wrote: > When client tries to connect(SOCK_STREAM) the server in the guest with > NONBLOCK mode, there will be a panic on a ThunderX2 (armv8a server): > [ 463.718844][ T5040] Unable to handle kernel NULL pointer dereference at > virtual address > [ 463.718848][ T5040] Mem abort info: > [ 463.718849][ T5040] ESR = 0x9644 > [ 463.718852][ T5040] EC = 0x25: DABT (current EL), IL = 32 bits > [ 463.718853][ T5040] SET = 0, FnV = 0 > [ 463.718854][ T5040] EA = 0, S1PTW = 0 > [ 463.718855][ T5040] Data abort info: > [ 463.718856][ T5040] ISV = 0, ISS = 0x0044 > [ 463.718857][ T5040] CM = 0, WnR = 1 > [ 463.718859][ T5040] user pgtable: 4k pages, 48-bit VAs, > pgdp=008f6f6e9000 > [ 463.718861][ T5040] [] pgd= > [ 463.718866][ T5040] Internal error: Oops: 9644 [#1] SMP > [...] > [ 463.718977][ T5040] CPU: 213 PID: 5040 Comm: vhost-5032 Tainted: G > O 5.7.0-rc7+ #139 > [ 463.718980][ T5040] Hardware name: GIGABYTE R281-T91-00/MT91-FS1-00, BIOS > F06 09/25/2018 > [ 463.718982][ T5040] pstate: 6049 (nZCv daif +PAN -UAO) > [ 463.718995][ T5040] pc : virtio_transport_recv_pkt+0x4c8/0xd40 > [vmw_vsock_virtio_transport_common] > [ 463.718999][ T5040] lr : virtio_transport_recv_pkt+0x1fc/0xd40 > [vmw_vsock_virtio_transport_common] > [ 463.719000][ T5040] sp : 80002dbe3c40 > [...] > [ 463.719025][ T5040] Call trace: > [ 463.719030][ T5040] virtio_transport_recv_pkt+0x4c8/0xd40 > [vmw_vsock_virtio_transport_common] > [ 463.719034][ T5040] vhost_vsock_handle_tx_kick+0x360/0x408 [vhost_vsock] > [ 463.719041][ T5040] vhost_worker+0x100/0x1a0 [vhost] > [ 463.719048][ T5040] kthread+0x128/0x130 > [ 463.719052][ T5040] ret_from_fork+0x10/0x18 ^ ^ Maybe we can remove these two columns from the commit message. > > The race condition as follows: > Task1Task2 > == > __sock_release virtio_transport_recv_pkt > __vsock_release vsock_find_bound_socket (found) > lock_sock_nested > vsock_remove_sock > sock_orphan > sk_set_socket(sk, NULL) Here we can add: sk->sk_shutdown = SHUTDOWN_MASK; > ... > release_sock > lock_sock >virtio_transport_recv_connecting > sk->sk_socket->state (panic) > > The root cause is that vsock_find_bound_socket can't hold the lock_sock, > so there is a small race window between vsock_find_bound_socket() and > lock_sock(). If there is __vsock_release() in another task, sk->sk_socket > will be set to NULL inadvertently. > > This fixes it by checking sk->sk_shutdown. > > Signed-off-by: Jia He > Cc: sta...@vger.kernel.org > Cc: Stefano Garzarella > --- > v2: use lightweight checking suggested by Stefano Garzarella > > net/vmw_vsock/virtio_transport_common.c | 8 > 1 file changed, 8 insertions(+) > > diff --git a/net/vmw_vsock/virtio_transport_common.c > b/net/vmw_vsock/virtio_transport_common.c > index 69efc891885f..0edda1edf988 100644 > --- a/net/vmw_vsock/virtio_transport_common.c > +++ b/net/vmw_vsock/virtio_transport_common.c > @@ -1132,6 +1132,14 @@ void virtio_transport_recv_pkt(struct virtio_transport > *t, > > lock_sock(sk); > > + /* Check if sk has been released before lock_sock */ > + if (sk->sk_shutdown == SHUTDOWN_MASK) { > + (void)virtio_transport_reset_no_sock(t, pkt); > + release_sock(sk); > + sock_put(sk); > + goto free_pkt; > + } > + > /* Update CID in case it has changed after a transport reset event */ > vsk->local_addr.svm_cid = dst.svm_cid; > > -- > 2.17.1 > Anyway, the patch LGTM, let see what David and other say. Reviewed-by: Stefano Garzarella Thanks, Stefano ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Re: [PATCH v3 69/75] x86/realmode: Setup AP jump table
On 5/29/20 4:02 AM, Borislav Petkov wrote: On Tue, Apr 28, 2020 at 05:17:19PM +0200, Joerg Roedel wrote: From: Tom Lendacky Setup the AP jump table to point to the SEV-ES trampoline code so that the APs can boot. Tom, in his laconic way, doesn't want to explain to us why is this even needed... :) Looks like some of the detail was lost during the patch shuffling. Originally (on GitHub) this was the text: As part of the GHCB specification, the booting of APs under SEV-ES requires an AP jump table when transitioning from one layer of code to another (e.g. when going from UEFI to the OS). As a result, each layer that parks an AP must provide the physical address of an AP jump table to the next layer using the GHCB MSR. Upon booting of the kernel, read the GHCB MSR and save the address of the AP jump table. Under SEV-ES, APs are started using the INIT-SIPI-SIPI sequence. Before issuing the first SIPI request for an AP, the start eip is programmed into the AP jump table. Upon issuing the SIPI request, the AP will awaken and jump to the start eip address programmed into the AP jump table. It needs to change "GHCB MSR" to "VMGEXIT MSR protocol", but should cover what you're looking for. Thanks, Tom /me reads the code /me reads the GHCB spec aha, it gets it from the HV. And it can be set by the guest too... So how about expanding that commit message as to why this is done, why needed, etc? Thx. diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c index 262f83cad355..1c5cbfd102d5 100644 --- a/arch/x86/realmode/init.c +++ b/arch/x86/realmode/init.c @@ -9,6 +9,7 @@ #include #include #include +#include struct real_mode_header *real_mode_header; u32 *trampoline_cr4_features; @@ -107,6 +108,11 @@ static void __init setup_real_mode(void) if (sme_active()) trampoline_header->flags |= TH_FLAGS_SME_ACTIVE; + if (sev_es_active()) { + if (sev_es_setup_ap_jump_table(real_mode_header)) + panic("Failed to update SEV-ES AP Jump Table"); + } + So this function gets slowly sprinkled with if (sev-something) bla Please wrap at least those last two into a sev_setup_real_mode() or so. ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Re: [PATCH] virtio_vsock: Fix race condition in virtio_transport_recv_pkt
Hi Jia, thanks for the patch! I have some comments. On Fri, May 29, 2020 at 09:31:23PM +0800, Jia He wrote: > When client tries to connect(SOCK_STREAM) the server in the guest with > NONBLOCK > mode, there will be a panic on a ThunderX2 (armv8a server): > [ 463.718844][ T5040] Unable to handle kernel NULL pointer dereference at > virtual address > [ 463.718848][ T5040] Mem abort info: > [ 463.718849][ T5040] ESR = 0x9644 > [ 463.718852][ T5040] EC = 0x25: DABT (current EL), IL = 32 bits > [ 463.718853][ T5040] SET = 0, FnV = 0 > [ 463.718854][ T5040] EA = 0, S1PTW = 0 > [ 463.718855][ T5040] Data abort info: > [ 463.718856][ T5040] ISV = 0, ISS = 0x0044 > [ 463.718857][ T5040] CM = 0, WnR = 1 > [ 463.718859][ T5040] user pgtable: 4k pages, 48-bit VAs, > pgdp=008f6f6e9000 > [ 463.718861][ T5040] [] pgd= > [ 463.718866][ T5040] Internal error: Oops: 9644 [#1] SMP > [...] > [ 463.718977][ T5040] CPU: 213 PID: 5040 Comm: vhost-5032 Tainted: G > O 5.7.0-rc7+ #139 > [ 463.718980][ T5040] Hardware name: GIGABYTE R281-T91-00/MT91-FS1-00, BIOS > F06 09/25/2018 > [ 463.718982][ T5040] pstate: 6049 (nZCv daif +PAN -UAO) > [ 463.718995][ T5040] pc : virtio_transport_recv_pkt+0x4c8/0xd40 > [vmw_vsock_virtio_transport_common] > [ 463.718999][ T5040] lr : virtio_transport_recv_pkt+0x1fc/0xd40 > [vmw_vsock_virtio_transport_common] > [ 463.719000][ T5040] sp : 80002dbe3c40 > [...] > [ 463.719025][ T5040] Call trace: > [ 463.719030][ T5040] virtio_transport_recv_pkt+0x4c8/0xd40 > [vmw_vsock_virtio_transport_common] > [ 463.719034][ T5040] vhost_vsock_handle_tx_kick+0x360/0x408 [vhost_vsock] > [ 463.719041][ T5040] vhost_worker+0x100/0x1a0 [vhost] > [ 463.719048][ T5040] kthread+0x128/0x130 > [ 463.719052][ T5040] ret_from_fork+0x10/0x18 > > The race condition as follows: > Task1Task2 > == > __sock_release virtio_transport_recv_pkt > __vsock_release vsock_find_bound_socket (found) > lock_sock_nested > vsock_remove_sock > sock_orphan > sk_set_socket(sk, NULL) > ... > release_sock > lock_sock >virtio_transport_recv_connecting > sk->sk_socket->state (panic) > > This fixes it by checking vsk again whether it is in bound/connected table. > > Signed-off-by: Jia He > Cc: sta...@vger.kernel.org > --- > net/vmw_vsock/virtio_transport_common.c | 11 +++ > 1 file changed, 11 insertions(+) > > diff --git a/net/vmw_vsock/virtio_transport_common.c > b/net/vmw_vsock/virtio_transport_common.c > index 69efc891885f..0dbd6a45f0ed 100644 > --- a/net/vmw_vsock/virtio_transport_common.c > +++ b/net/vmw_vsock/virtio_transport_common.c > @@ -1132,6 +1132,17 @@ void virtio_transport_recv_pkt(struct virtio_transport > *t, > > lock_sock(sk); > > + /* Check it again if vsk is removed by vsock_remove_sock */ > + spin_lock_bh(_table_lock); > + if (!__vsock_in_bound_table(vsk) && !__vsock_in_connected_table(vsk)) { > + spin_unlock_bh(_table_lock); > + (void)virtio_transport_reset_no_sock(t, pkt); > + release_sock(sk); > + sock_put(sk); > + goto free_pkt; > + } > + spin_unlock_bh(_table_lock); > + As an a simpler alternative, can we check the sk_shutdown or the socket state without check again both bound and connected tables? This is a data path, so we should take it faster. I mean something like this: if (sk->sk_shutdown == SHUTDOWN_MASK) { ... } or if (sock_flag(sk, SOCK_DEAD)) { ... } I prefer the first option, but I think also the second option should work. Thanks, Stefano > /* Update CID in case it has changed after a transport reset event */ > vsk->local_addr.svm_cid = dst.svm_cid; > > -- > 2.17.1 > ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Re: [PATCH 0/8] Convert the intel iommu driver to the dma-iommu api
On Thu, May 28, 2020 at 06:00:44PM -0600, Logan Gunthorpe wrote: > > This issue is most likely in the i915 driver and is most likely caused by > > the driver not respecting the return value of the dma_map_ops::map_sg > > function. You can see the driver ignoring the return value here: > > https://github.com/torvalds/linux/blob/7e0165b2f1a912a06e381e91f0f4e495f4ac3736/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c#L51 > > > > Previously this didn’t cause issues because the intel map_sg always > > returned the same number of elements as the input scatter gather list but > > with the change to this dma-iommu api this is no longer the case. I wasn’t > > able to track the bug down to a specific line of code unfortunately. Mark did a big audit into the map_sg API abuse and initially had some i915 patches, but then gave up on them with this comment: "The biggest TODO is DRM/i915 driver and I don't feel brave enough to fix it fully. The driver creatively uses sg_table->orig_nents to store the size of the allocate scatterlist and ignores the number of the entries returned by dma_map_sg function. In this patchset I only fixed the sg_table objects exported by dmabuf related functions. I hope that I didn't break anything there." it would be really nice if the i915 maintainers could help with sorting that API abuse out. ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Re: [PATCH 4/6] vhost_vdpa: support doorbell mapping via mmap
On 2020/5/29 下午5:16, Mika Penttilä wrote: Hi, On 29.5.2020 11.03, Jason Wang wrote: Currently the doorbell is relayed via eventfd which may have significant overhead because of the cost of vmexits or syscall. This patch introduces mmap() based doorbell mapping which can eliminate the overhead caused by vmexit or syscall. Just wondering. I know very little about vdpa. But how is such a "sw doorbell" monitored or observed, if no fault or wmexit etc. Is there some kind of polling used? Hi Mika: It's not a software doorbell. It just allow userspace to map page of hardware doorbell directly into userspace. Without this, for KVM, it needs to trap the MMIO access of the guest and write to eventfd, for other userspace driver, it needs to write to eventfd. vhost-vDPA's eventfd wakeup function may let the driver to do touch the doorbell. With this, since the doorbell page is mapped into userspace address space, guest or other userspace driver may write directly to the hardware doorbell register. Thanks To ease the userspace modeling of the doorbell layout (usually virtio-pci), this patch starts from a doorbell per page model. Vhost-vdpa only support the hardware doorbell that sit at the boundary of a page and does not share the page with other registers. Doorbell of each virtqueue must be mapped separately, pgoff is the index of the virtqueue. This allows userspace to map a subset of the doorbell which may be useful for the implementation of software assisted virtqueue (control vq) in the future. Signed-off-by: Jason Wang --- drivers/vhost/vdpa.c | 59 1 file changed, 59 insertions(+) diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c index 6ff72289f488..bbe23cea139a 100644 --- a/drivers/vhost/vdpa.c +++ b/drivers/vhost/vdpa.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -741,12 +742,70 @@ static int vhost_vdpa_release(struct inode *inode, struct file *filep) return 0; } +static vm_fault_t vhost_vdpa_fault(struct vm_fault *vmf) +{ + struct vhost_vdpa *v = vmf->vma->vm_file->private_data; + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + struct vdpa_notification_area notify; + struct vm_area_struct *vma = vmf->vma; + u16 index = vma->vm_pgoff; + + notify = ops->get_vq_notification(vdpa, index); + + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + if (remap_pfn_range(vma, vmf->address & PAGE_MASK, + notify.addr >> PAGE_SHIFT, PAGE_SIZE, + vma->vm_page_prot)) + return VM_FAULT_SIGBUS; + + return VM_FAULT_NOPAGE; +} + +static const struct vm_operations_struct vhost_vdpa_vm_ops = { + .fault = vhost_vdpa_fault, +}; + +static int vhost_vdpa_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct vhost_vdpa *v = vma->vm_file->private_data; + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + struct vdpa_notification_area notify; + int index = vma->vm_pgoff; + + if (vma->vm_end - vma->vm_start != PAGE_SIZE) + return -EINVAL; + if ((vma->vm_flags & VM_SHARED) == 0) + return -EINVAL; + if (vma->vm_flags & VM_READ) + return -EINVAL; + if (index > 65535) + return -EINVAL; + if (!ops->get_vq_notification) + return -ENOTSUPP; + + /* To be safe and easily modelled by userspace, We only + * support the doorbell which sits on the page boundary and + * does not share the page with other registers. + */ + notify = ops->get_vq_notification(vdpa, index); + if (notify.addr & (PAGE_SIZE - 1)) + return -EINVAL; + if (vma->vm_end - vma->vm_start != notify.size) + return -ENOTSUPP; + + vma->vm_ops = _vdpa_vm_ops; + return 0; +} + static const struct file_operations vhost_vdpa_fops = { .owner = THIS_MODULE, .open = vhost_vdpa_open, .release = vhost_vdpa_release, .write_iter = vhost_vdpa_chr_write_iter, .unlocked_ioctl = vhost_vdpa_unlocked_ioctl, + .mmap = vhost_vdpa_mmap, .compat_ioctl = compat_ptr_ioctl, }; ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Re: [PATCH v3 69/75] x86/realmode: Setup AP jump table
On Tue, Apr 28, 2020 at 05:17:19PM +0200, Joerg Roedel wrote: > From: Tom Lendacky > > Setup the AP jump table to point to the SEV-ES trampoline code so that > the APs can boot. Tom, in his laconic way, doesn't want to explain to us why is this even needed... :) /me reads the code /me reads the GHCB spec aha, it gets it from the HV. And it can be set by the guest too... So how about expanding that commit message as to why this is done, why needed, etc? Thx. > diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c > index 262f83cad355..1c5cbfd102d5 100644 > --- a/arch/x86/realmode/init.c > +++ b/arch/x86/realmode/init.c > @@ -9,6 +9,7 @@ > #include > #include > #include > +#include > > struct real_mode_header *real_mode_header; > u32 *trampoline_cr4_features; > @@ -107,6 +108,11 @@ static void __init setup_real_mode(void) > if (sme_active()) > trampoline_header->flags |= TH_FLAGS_SME_ACTIVE; > > + if (sev_es_active()) { > + if (sev_es_setup_ap_jump_table(real_mode_header)) > + panic("Failed to update SEV-ES AP Jump Table"); > + } > + So this function gets slowly sprinkled with if (sev-something) bla Please wrap at least those last two into a sev_setup_real_mode() or so. -- Regards/Gruss, Boris. https://people.kernel.org/tglx/notes-about-netiquette ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH 6/6] vdpa: vp_vdpa: report doorbell location
This patch adds support for reporting doorbell location in vp_vdpa driver. The doorbell mapping could be then enabled by e.g launching qemu's virtio-net-pci device with page-per-vq enabled. Signed-off-by: Jason Wang --- drivers/vdpa/vp_vdpa/vp_vdpa.c | 29 + 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/drivers/vdpa/vp_vdpa/vp_vdpa.c b/drivers/vdpa/vp_vdpa/vp_vdpa.c index e59c310e2156..a5ca49533138 100644 --- a/drivers/vdpa/vp_vdpa/vp_vdpa.c +++ b/drivers/vdpa/vp_vdpa/vp_vdpa.c @@ -30,6 +30,7 @@ struct vp_vring { void __iomem *notify; char msix_name[256]; + resource_size_t notify_pa; struct vdpa_callback cb; int irq; }; @@ -136,7 +137,8 @@ static int find_capability(struct pci_dev *dev, u8 cfg_type, return 0; } -static void __iomem *map_capability(struct vp_vdpa *vp_vdpa, int off) +static void __iomem *map_capability(struct vp_vdpa *vp_vdpa, int off, + resource_size_t *pa) { struct pci_dev *pdev = vp_vdpa->pdev; u32 offset; @@ -149,6 +151,9 @@ static void __iomem *map_capability(struct vp_vdpa *vp_vdpa, int off) off + offsetof(struct virtio_pci_cap, offset), ); + if (pa) + *pa = pci_resource_start(pdev, bar) + offset; + return vp_vdpa->base[bar] + offset; } @@ -283,6 +288,18 @@ static u64 vp_vdpa_get_vq_state(struct vdpa_device *vdpa, u16 qid) return 0; } +static struct vdpa_notification_area +vp_vdpa_get_vq_notification(struct vdpa_device *vdpa, u16 qid) +{ + struct vp_vdpa *vp_vdpa = vdpa_to_vp(vdpa); + struct vdpa_notification_area notify; + + notify.addr = vp_vdpa->vring[qid].notify_pa; + notify.size = vp_vdpa->notify_off_multiplier; + + return notify; +} + static int vp_vdpa_set_vq_state(struct vdpa_device *vdpa, u16 qid, u64 num) { @@ -423,6 +440,7 @@ static const struct vdpa_config_ops vp_vdpa_ops = { .set_status = vp_vdpa_set_status, .get_vq_num_max = vp_vdpa_get_vq_num_max, .get_vq_state = vp_vdpa_get_vq_state, + .get_vq_notification = vp_vdpa_get_vq_notification, .set_vq_state = vp_vdpa_set_vq_state, .set_vq_cb = vp_vdpa_set_vq_cb, .set_vq_ready = vp_vdpa_set_vq_ready, @@ -445,6 +463,7 @@ static int vp_vdpa_probe(struct pci_dev *pdev, const struct pci_device_id *id) struct vp_vdpa *vp_vdpa; int common, notify, device, ret, i; struct virtio_device_id virtio_id; + resource_size_t notify_pa; u16 notify_off; /* We only own devices >= 0x1000 and <= 0x107f: leave the rest. */ @@ -525,9 +544,9 @@ static int vp_vdpa_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (ret) dev_warn(>dev, "Failed to enable 64-bit or 32-bit DMA. Trying to continue, but this might not work.\n"); - vp_vdpa->device = map_capability(vp_vdpa, device); - vp_vdpa->notify = map_capability(vp_vdpa, notify); - vp_vdpa->common = map_capability(vp_vdpa, common); + vp_vdpa->device = map_capability(vp_vdpa, device, NULL); + vp_vdpa->notify = map_capability(vp_vdpa, notify, _pa); + vp_vdpa->common = map_capability(vp_vdpa, common, NULL); vp_vdpa->id = virtio_id; ret = vdpa_register_device(_vdpa->vdpa); @@ -545,6 +564,8 @@ static int vp_vdpa_probe(struct pci_dev *pdev, const struct pci_device_id *id) vp_vdpa->vring[i].irq = -1; vp_vdpa->vring[i].notify = vp_vdpa->notify + notify_off * vp_vdpa->notify_off_multiplier; + vp_vdpa->vring[i].notify_pa = notify_pa + + notify_off * vp_vdpa->notify_off_multiplier; } return 0; -- 2.20.1 ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH 4/6] vhost_vdpa: support doorbell mapping via mmap
Currently the doorbell is relayed via eventfd which may have significant overhead because of the cost of vmexits or syscall. This patch introduces mmap() based doorbell mapping which can eliminate the overhead caused by vmexit or syscall. To ease the userspace modeling of the doorbell layout (usually virtio-pci), this patch starts from a doorbell per page model. Vhost-vdpa only support the hardware doorbell that sit at the boundary of a page and does not share the page with other registers. Doorbell of each virtqueue must be mapped separately, pgoff is the index of the virtqueue. This allows userspace to map a subset of the doorbell which may be useful for the implementation of software assisted virtqueue (control vq) in the future. Signed-off-by: Jason Wang --- drivers/vhost/vdpa.c | 59 1 file changed, 59 insertions(+) diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c index 6ff72289f488..bbe23cea139a 100644 --- a/drivers/vhost/vdpa.c +++ b/drivers/vhost/vdpa.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -741,12 +742,70 @@ static int vhost_vdpa_release(struct inode *inode, struct file *filep) return 0; } +static vm_fault_t vhost_vdpa_fault(struct vm_fault *vmf) +{ + struct vhost_vdpa *v = vmf->vma->vm_file->private_data; + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + struct vdpa_notification_area notify; + struct vm_area_struct *vma = vmf->vma; + u16 index = vma->vm_pgoff; + + notify = ops->get_vq_notification(vdpa, index); + + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + if (remap_pfn_range(vma, vmf->address & PAGE_MASK, + notify.addr >> PAGE_SHIFT, PAGE_SIZE, + vma->vm_page_prot)) + return VM_FAULT_SIGBUS; + + return VM_FAULT_NOPAGE; +} + +static const struct vm_operations_struct vhost_vdpa_vm_ops = { + .fault = vhost_vdpa_fault, +}; + +static int vhost_vdpa_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct vhost_vdpa *v = vma->vm_file->private_data; + struct vdpa_device *vdpa = v->vdpa; + const struct vdpa_config_ops *ops = vdpa->config; + struct vdpa_notification_area notify; + int index = vma->vm_pgoff; + + if (vma->vm_end - vma->vm_start != PAGE_SIZE) + return -EINVAL; + if ((vma->vm_flags & VM_SHARED) == 0) + return -EINVAL; + if (vma->vm_flags & VM_READ) + return -EINVAL; + if (index > 65535) + return -EINVAL; + if (!ops->get_vq_notification) + return -ENOTSUPP; + + /* To be safe and easily modelled by userspace, We only +* support the doorbell which sits on the page boundary and +* does not share the page with other registers. +*/ + notify = ops->get_vq_notification(vdpa, index); + if (notify.addr & (PAGE_SIZE - 1)) + return -EINVAL; + if (vma->vm_end - vma->vm_start != notify.size) + return -ENOTSUPP; + + vma->vm_ops = _vdpa_vm_ops; + return 0; +} + static const struct file_operations vhost_vdpa_fops = { .owner = THIS_MODULE, .open = vhost_vdpa_open, .release= vhost_vdpa_release, .write_iter = vhost_vdpa_chr_write_iter, .unlocked_ioctl = vhost_vdpa_unlocked_ioctl, + .mmap = vhost_vdpa_mmap, .compat_ioctl = compat_ptr_ioctl, }; -- 2.20.1 ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH 0/6] vDPA: doorbell mapping
Hi all: This series introduce basic functionality of doorbell mapping support for vhost-vDPA. Userspace program may use mmap() to map a the doorbell of a specific virtqueue into its address space. This is help to reudce the syscall or vmexit overhead. A new vdpa_config_ops was introduced to report the location of the doorbell, vhost_vdpa may then choose to map the doorbell when: - The doorbell register is localted at page boundary - The doorbell register does not share page with non doorbell registers. With these two requriements, doorbells layout could be modelled more easily from guest (e.g Qemu's page-per-vq model) and it would be more safe to avoid exposing other registers to userspace directly. IFCVF was reported to support this feature but unfortuantely the one I used does not meet those requirements. So a new virtio-pci driver for vDPA bus is introduced, and I verify this with page-per-vq=on with a userspace vhost-vdpa driver in guest. Please review. Thanks Jason Wang (6): vhost: allow device that does not depend on vhost worker vhost: use mmgrab() instead of mmget() for non worker device vdpa: introduce get_vq_notification method vhost_vdpa: support doorbell mapping via mmap vdpa: introduce virtio pci driver vdpa: vp_vdpa: report doorbell location drivers/vdpa/Kconfig | 6 + drivers/vdpa/Makefile | 1 + drivers/vdpa/vp_vdpa/Makefile | 2 + drivers/vdpa/vp_vdpa/vp_vdpa.c | 604 + drivers/vhost/net.c| 2 +- drivers/vhost/scsi.c | 2 +- drivers/vhost/vdpa.c | 61 +++- drivers/vhost/vhost.c | 80 +++-- drivers/vhost/vhost.h | 2 + drivers/vhost/vsock.c | 2 +- include/linux/vdpa.h | 16 + 11 files changed, 753 insertions(+), 25 deletions(-) create mode 100644 drivers/vdpa/vp_vdpa/Makefile create mode 100644 drivers/vdpa/vp_vdpa/vp_vdpa.c -- 2.20.1 ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH 5/6] vdpa: introduce virtio pci driver
This patch introduce a vDPA driver for virtio-pci device. It bridges the virtio-pci control command to the vDPA bus. This will be used for developing new features for both software vDPA framework and hardware vDPA feature. Compared to vdpa_sim, it has several advantages: - it's a real device driver which allow us to play with real hardware features - type independent instead of networking specific Note that since virtio specification does not support get/restore virtqueue state. So we can not use this driver for VM. This can be addressed by extending the virtio specification. Signed-off-by: Jason Wang --- drivers/vdpa/Kconfig | 6 + drivers/vdpa/Makefile | 1 + drivers/vdpa/vp_vdpa/Makefile | 2 + drivers/vdpa/vp_vdpa/vp_vdpa.c | 583 + 4 files changed, 592 insertions(+) create mode 100644 drivers/vdpa/vp_vdpa/Makefile create mode 100644 drivers/vdpa/vp_vdpa/vp_vdpa.c diff --git a/drivers/vdpa/Kconfig b/drivers/vdpa/Kconfig index e8140065c8a5..3f1bf8b6723d 100644 --- a/drivers/vdpa/Kconfig +++ b/drivers/vdpa/Kconfig @@ -28,4 +28,10 @@ config IFCVF To compile this driver as a module, choose M here: the module will be called ifcvf. +config VP_VDPA + tristate "Virtio PCI bridge vDPA driver" + depends on PCI_MSI + help + This kernel module that bridges virtio PCI device to vDPA bus. + endif # VDPA diff --git a/drivers/vdpa/Makefile b/drivers/vdpa/Makefile index 8bbb686ca7a2..37d00f49b3bf 100644 --- a/drivers/vdpa/Makefile +++ b/drivers/vdpa/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_VDPA) += vdpa.o obj-$(CONFIG_VDPA_SIM) += vdpa_sim/ obj-$(CONFIG_IFCVF)+= ifcvf/ +obj-$(CONFIG_VP_VDPA)+= vp_vdpa/ diff --git a/drivers/vdpa/vp_vdpa/Makefile b/drivers/vdpa/vp_vdpa/Makefile new file mode 100644 index ..231088d3af7d --- /dev/null +++ b/drivers/vdpa/vp_vdpa/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_VP_VDPA) += vp_vdpa.o diff --git a/drivers/vdpa/vp_vdpa/vp_vdpa.c b/drivers/vdpa/vp_vdpa/vp_vdpa.c new file mode 100644 index ..e59c310e2156 --- /dev/null +++ b/drivers/vdpa/vp_vdpa/vp_vdpa.c @@ -0,0 +1,583 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * vDPA bridge driver for modern virtio-pci device + * + * Copyright (c) 2020, Red Hat Inc. All rights reserved. + * Author: Jason Wang + * + * Based on virtio_pci_modern.c. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* TBD: read from config space */ +#define VP_VDPA_MAX_QUEUE 2 +#define VP_VDPA_DRIVER_NAME "vp_vdpa" + +#define VP_VDPA_FEATURES \ +(1ULL << VIRTIO_F_ANY_LAYOUT) | \ +(1ULL << VIRTIO_F_VERSION_1) | \ +(1ULL << VIRTIO_F_ORDER_PLATFORM) | \ +(1ULL << VIRTIO_F_IOMMU_PLATFORM) + +struct vp_vring { + void __iomem *notify; + char msix_name[256]; + struct vdpa_callback cb; + int irq; +}; + +struct vp_vdpa { + struct vdpa_device vdpa; + struct pci_dev *pdev; + + struct virtio_device_id id; + + struct vp_vring vring[VP_VDPA_MAX_QUEUE]; + + /* The IO mapping for the PCI config space */ + void __iomem * const *base; + struct virtio_pci_common_cfg __iomem *common; + void __iomem *device; + /* Base of vq notifications */ + void __iomem *notify; + + /* Multiplier for queue_notify_off. */ + u32 notify_off_multiplier; + + int modern_bars; + int vectors; +}; + +static struct vp_vdpa *vdpa_to_vp(struct vdpa_device *vdpa) +{ + return container_of(vdpa, struct vp_vdpa, vdpa); +} + +/* + * Type-safe wrappers for io accesses. + * Use these to enforce at compile time the following spec requirement: + * + * The driver MUST access each field using the “natural” access + * method, i.e. 32-bit accesses for 32-bit fields, 16-bit accesses + * for 16-bit fields and 8-bit accesses for 8-bit fields. + */ +static inline u8 vp_ioread8(u8 __iomem *addr) +{ + return ioread8(addr); +} +static inline u16 vp_ioread16 (__le16 __iomem *addr) +{ + return ioread16(addr); +} + +static inline u32 vp_ioread32(__le32 __iomem *addr) +{ + return ioread32(addr); +} + +static inline void vp_iowrite8(u8 value, u8 __iomem *addr) +{ + iowrite8(value, addr); +} + +static inline void vp_iowrite16(u16 value, __le16 __iomem *addr) +{ + iowrite16(value, addr); +} + +static inline void vp_iowrite32(u32 value, __le32 __iomem *addr) +{ + iowrite32(value, addr); +} + +static void vp_iowrite64_twopart(u64 val, +__le32 __iomem *lo, __le32 __iomem *hi) +{ + vp_iowrite32((u32)val, lo); + vp_iowrite32(val >> 32, hi); +} + +static int find_capability(struct pci_dev *dev, u8 cfg_type, + u32 ioresource_types, int *bars) +{ + int pos; + + for (pos = pci_find_capability(dev,
[PATCH 3/6] vdpa: introduce get_vq_notification method
This patch introduces a new method in the vdpa_config_ops which reports the physical address and the size of the doorbell for a specific virtqueue. This will be used by the future patches that maps doorbell to userspace. Signed-off-by: Jason Wang --- include/linux/vdpa.h | 16 1 file changed, 16 insertions(+) diff --git a/include/linux/vdpa.h b/include/linux/vdpa.h index 5453af87a33e..239db794357c 100644 --- a/include/linux/vdpa.h +++ b/include/linux/vdpa.h @@ -17,6 +17,16 @@ struct vdpa_callback { void *private; }; +/** + * vDPA notification area + * @addr: base address of the notification area + * @size: size of the notification area + */ +struct vdpa_notification_area { + resource_size_t addr; + resource_size_t size; +}; + /** * vDPA device - representation of a vDPA device * @dev: underlying device @@ -73,6 +83,10 @@ struct vdpa_device { * @vdev: vdpa device * @idx: virtqueue index * Returns virtqueue state (last_avail_idx) + * @get_vq_notification: Get the notification area for a virtqueue + * @vdev: vdpa device + * @idx: virtqueue index + * Returns the notifcation area * @get_vq_align: Get the virtqueue align requirement * for the device * @vdev: vdpa device @@ -162,6 +176,8 @@ struct vdpa_config_ops { bool (*get_vq_ready)(struct vdpa_device *vdev, u16 idx); int (*set_vq_state)(struct vdpa_device *vdev, u16 idx, u64 state); u64 (*get_vq_state)(struct vdpa_device *vdev, u16 idx); + struct vdpa_notification_area + (*get_vq_notification)(struct vdpa_device *vdev, u16 idx); /* Device ops */ u32 (*get_vq_align)(struct vdpa_device *vdev); -- 2.20.1 ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH 2/6] vhost: use mmgrab() instead of mmget() for non worker device
For the device that doesn't use vhost worker and use_mm(), mmget() is too heavy weight and it may brings troubles for implementing mmap() support for vDPA device. This is because, an reference to the address space was held via mm_get() in vhost_dev_set_owner() and an reference to the file was held in mmap(). This means when process exits, the mm can not be released thus we can not release the file. This patch tries to use mmgrab() instead of mmget(), which allows the address space to be destroy in process exit without releasing the mm structure itself. This is sufficient for vDPA device which pin user pages and does not depend on the address space to work. Signed-off-by: Jason Wang --- drivers/vhost/vhost.c | 42 ++ 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 70105e045768..9642938a7e7c 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -541,6 +541,36 @@ bool vhost_dev_has_owner(struct vhost_dev *dev) } EXPORT_SYMBOL_GPL(vhost_dev_has_owner); +static void vhost_attach_mm(struct vhost_dev *dev) +{ + /* No owner, become one */ + if (dev->use_worker) { + dev->mm = get_task_mm(current); + } else { + /* vDPA device does not use worker thead, so there's +* no need to hold the address space for mm. This help +* to avoid deadlock in the case of mmap() which may +* held the refcnt of the file and depends on release +* method to remove vma. +*/ + dev->mm = current->mm; + mmgrab(dev->mm); + } +} + +static void vhost_detach_mm(struct vhost_dev *dev) +{ + if (!dev->mm) + return; + + if (dev->use_worker) + mmput(dev->mm); + else + mmdrop(dev->mm); + + dev->mm = NULL; +} + /* Caller should have device mutex */ long vhost_dev_set_owner(struct vhost_dev *dev) { @@ -553,8 +583,8 @@ long vhost_dev_set_owner(struct vhost_dev *dev) goto err_mm; } - /* No owner, become one */ - dev->mm = get_task_mm(current); + vhost_attach_mm(dev); + dev->kcov_handle = kcov_common_handle(); if (dev->use_worker) { worker = kthread_create(vhost_worker, dev, @@ -583,9 +613,7 @@ long vhost_dev_set_owner(struct vhost_dev *dev) dev->worker = NULL; } err_worker: - if (dev->mm) - mmput(dev->mm); - dev->mm = NULL; + vhost_detach_mm(dev); dev->kcov_handle = 0; err_mm: return err; @@ -682,9 +710,7 @@ void vhost_dev_cleanup(struct vhost_dev *dev) dev->worker = NULL; dev->kcov_handle = 0; } - if (dev->mm) - mmput(dev->mm); - dev->mm = NULL; + vhost_detach_mm(dev); } EXPORT_SYMBOL_GPL(vhost_dev_cleanup); -- 2.20.1 ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH 1/6] vhost: allow device that does not depend on vhost worker
vDPA device currently relays the eventfd via vhost worker. This is inefficient due the latency of wakeup and scheduling, so this patch tries to introduce a use_worker attribute for the vhost device. When use_worker is not set with vhost_dev_init(), vhost won't try to allocate a worker thread and the vhost_poll will be processed directly in the wakeup function. This help for vDPA since it reduces the latency caused by vhost worker. In my testing, it saves 0.2 ms in pings between VMs on a mutual host. Signed-off-by: Zhu Lingshan Signed-off-by: Jason Wang --- drivers/vhost/net.c | 2 +- drivers/vhost/scsi.c | 2 +- drivers/vhost/vdpa.c | 2 +- drivers/vhost/vhost.c | 38 +- drivers/vhost/vhost.h | 2 ++ drivers/vhost/vsock.c | 2 +- 6 files changed, 31 insertions(+), 17 deletions(-) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 2927f02cc7e1..bf5e1d81ae25 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -1326,7 +1326,7 @@ static int vhost_net_open(struct inode *inode, struct file *f) } vhost_dev_init(dev, vqs, VHOST_NET_VQ_MAX, UIO_MAXIOV + VHOST_NET_BATCH, - VHOST_NET_PKT_WEIGHT, VHOST_NET_WEIGHT, + VHOST_NET_PKT_WEIGHT, VHOST_NET_WEIGHT, true, NULL); vhost_poll_init(n->poll + VHOST_NET_VQ_TX, handle_tx_net, EPOLLOUT, dev); diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index c39952243fd3..0cbaa0b3893d 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -1628,7 +1628,7 @@ static int vhost_scsi_open(struct inode *inode, struct file *f) vs->vqs[i].vq.handle_kick = vhost_scsi_handle_kick; } vhost_dev_init(>dev, vqs, VHOST_SCSI_MAX_VQ, UIO_MAXIOV, - VHOST_SCSI_WEIGHT, 0, NULL); + VHOST_SCSI_WEIGHT, 0, true, NULL); vhost_scsi_init_inflight(vs, NULL); diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c index 20476b505d99..6ff72289f488 100644 --- a/drivers/vhost/vdpa.c +++ b/drivers/vhost/vdpa.c @@ -696,7 +696,7 @@ static int vhost_vdpa_open(struct inode *inode, struct file *filep) vqs[i] = >vqs[i]; vqs[i]->handle_kick = handle_vq_kick; } - vhost_dev_init(dev, vqs, nvqs, 0, 0, 0, + vhost_dev_init(dev, vqs, nvqs, 0, 0, 0, false, vhost_vdpa_process_iotlb_msg); dev->iotlb = vhost_iotlb_alloc(0, 0); diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index d450e16c5c25..70105e045768 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -166,11 +166,16 @@ static int vhost_poll_wakeup(wait_queue_entry_t *wait, unsigned mode, int sync, void *key) { struct vhost_poll *poll = container_of(wait, struct vhost_poll, wait); + struct vhost_work *work = >work; if (!(key_to_poll(key) & poll->mask)) return 0; - vhost_poll_queue(poll); + if (!poll->dev->use_worker) + work->fn(work); + else + vhost_poll_queue(poll); + return 0; } @@ -454,6 +459,7 @@ static size_t vhost_get_desc_size(struct vhost_virtqueue *vq, void vhost_dev_init(struct vhost_dev *dev, struct vhost_virtqueue **vqs, int nvqs, int iov_limit, int weight, int byte_weight, + bool use_worker, int (*msg_handler)(struct vhost_dev *dev, struct vhost_iotlb_msg *msg)) { @@ -471,6 +477,7 @@ void vhost_dev_init(struct vhost_dev *dev, dev->iov_limit = iov_limit; dev->weight = weight; dev->byte_weight = byte_weight; + dev->use_worker = use_worker; dev->msg_handler = msg_handler; init_llist_head(>work_list); init_waitqueue_head(>wait); @@ -549,18 +556,21 @@ long vhost_dev_set_owner(struct vhost_dev *dev) /* No owner, become one */ dev->mm = get_task_mm(current); dev->kcov_handle = kcov_common_handle(); - worker = kthread_create(vhost_worker, dev, "vhost-%d", current->pid); - if (IS_ERR(worker)) { - err = PTR_ERR(worker); - goto err_worker; - } + if (dev->use_worker) { + worker = kthread_create(vhost_worker, dev, + "vhost-%d", current->pid); + if (IS_ERR(worker)) { + err = PTR_ERR(worker); + goto err_worker; + } - dev->worker = worker; - wake_up_process(worker);/* avoid contributing to loadavg */ + dev->worker = worker; + wake_up_process(worker); /* avoid contributing to loadavg */ - err = vhost_attach_cgroups(dev); - if (err) - goto err_cgroup; + err = vhost_attach_cgroups(dev); +
[RFC 11/12] rpmsg: increase buffer size and reduce buffer number
It is hard to imagine use-cases where 512 buffers would really be needed, whereas 512 bytes per buffer might be too little. Change this to use 16 16KiB buffers instead. Signed-off-by: Guennadi Liakhovetski --- include/linux/virtio_rpmsg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/virtio_rpmsg.h b/include/linux/virtio_rpmsg.h index 679be8b..1add468 100644 --- a/include/linux/virtio_rpmsg.h +++ b/include/linux/virtio_rpmsg.h @@ -72,8 +72,8 @@ enum rpmsg_ns_flags { * can change this without changing anything in the firmware of the remote * processor. */ -#define MAX_RPMSG_NUM_BUFS 512 -#define MAX_RPMSG_BUF_SIZE 512 +#define MAX_RPMSG_NUM_BUFS (512 / 32) +#define MAX_RPMSG_BUF_SIZE (512 * 32) /* Address 53 is reserved for advertising remote services */ #define RPMSG_NS_ADDR 53 -- 1.9.3 ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[RFC 12/12] rpmsg: add a device ID to also bind to the ADSP device
The ADSP device uses the RPMsg API to connect vhost and VirtIO SOF Audio DSP drivers on KVM host and guest. Signed-off-by: Guennadi Liakhovetski --- drivers/rpmsg/virtio_rpmsg_bus.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c index f3bd050..ebe3f19 100644 --- a/drivers/rpmsg/virtio_rpmsg_bus.c +++ b/drivers/rpmsg/virtio_rpmsg_bus.c @@ -949,6 +949,7 @@ static void rpmsg_remove(struct virtio_device *vdev) static struct virtio_device_id id_table[] = { { VIRTIO_ID_RPMSG, VIRTIO_DEV_ANY_ID }, + { VIRTIO_ID_ADSP, VIRTIO_DEV_ANY_ID }, { 0 }, }; -- 1.9.3 ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[RFC 04/12] ASoC: SOF: add a power status IPC
In a virtualised configuration the runtime PM of the host and any guests aren't synchronised. But guests have to be able to tell the host when they suspend and resume and know, whether the host has been runtime suspended since that guests's topology had been sent to the host last time. This is needed to decide whether to re-send the topology again. To support this we add a new PM IPC message SOF_IPC_PM_VFE_POWER_STATUS and a reset counter to track the state of the DSP. Signed-off-by: Guennadi Liakhovetski --- include/sound/sof/header.h | 1 + sound/soc/sof/core.c | 2 ++ sound/soc/sof/ipc.c| 2 ++ sound/soc/sof/loader.c | 4 sound/soc/sof/sof-priv.h | 4 5 files changed, 13 insertions(+) diff --git a/include/sound/sof/header.h b/include/sound/sof/header.h index 2d35997..5ee296c 100644 --- a/include/sound/sof/header.h +++ b/include/sound/sof/header.h @@ -77,6 +77,7 @@ #define SOF_IPC_PM_CLK_REQ SOF_CMD_TYPE(0x006) #define SOF_IPC_PM_CORE_ENABLE SOF_CMD_TYPE(0x007) #define SOF_IPC_PM_GATESOF_CMD_TYPE(0x008) +#define SOF_IPC_PM_VFE_POWER_STATUSSOF_CMD_TYPE(0x010) /* component runtime config - multiple different types */ #define SOF_IPC_COMP_SET_VALUE SOF_CMD_TYPE(0x001) diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 17f264f..61f045c 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -8,6 +8,7 @@ // Author: Liam Girdwood // +#include #include #include #include @@ -312,6 +313,7 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES) sdev->extractor_stream_tag = SOF_PROBE_INVALID_NODE_ID; #endif + atomic_set(>dsp_reset_count, 0); dev_set_drvdata(dev, sdev); /* check all mandatory ops */ diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index b3e1587..e9b0347 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -105,6 +105,8 @@ static void ipc_log_header(struct device *dev, u8 *text, u32 cmd) str2 = "CLK_REQ"; break; case SOF_IPC_PM_CORE_ENABLE: str2 = "CORE_ENABLE"; break; + case SOF_IPC_PM_VFE_POWER_STATUS: + str2 = "VFE_POWER_STATUS"; break; default: str2 = "unknown type"; break; } diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 4a5b57e..df95bcb 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -10,6 +10,7 @@ // Generic firmware loader. // +#include #include #include #include "ops.h" @@ -620,6 +621,9 @@ int snd_sof_run_firmware(struct snd_sof_dev *sdev) /* fw boot is complete. Update the active cores mask */ sdev->enabled_cores_mask = init_core_mask; + /* increment reset count */ + atomic_add(1, >dsp_reset_count); + return 0; } EXPORT_SYMBOL(snd_sof_run_firmware); diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 3ed39b8..29ab6ad 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -11,6 +11,7 @@ #ifndef __SOUND_SOC_SOF_PRIV_H #define __SOUND_SOC_SOF_PRIV_H +#include #include #include #include @@ -425,6 +426,9 @@ struct snd_sof_dev { unsigned int extractor_stream_tag; #endif + /* VirtIO fields for host and guest */ + atomic_t dsp_reset_count; + /* DMA for Trace */ struct snd_dma_buffer dmatb; struct snd_dma_buffer dmatp; -- 1.9.3 ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[RFC 06/12] ASoC: SOF: add an RPMsg VirtIO DSP driver
Add a VirtIO driver, designed to work with the SOF vhost driver, using the RPMsg protocol layer. This driver allows SOF to be used on Virtual Machines (VMs) where the host is also a Linux system, using the SOF driver natively. This driver communicates with the host using the RPMsg standard over Virtual Queues. This version uses 3 RPMsg endpoints: for control, for data and for position updates. The control endpoint uses exactly the same IPC protocol as what is used by the SOF driver natively to communicate with the DSP. In the future a zero-copy capability should be added thus eliminating 2 out of 3 endpoints and only preserving the control channel. Signed-off-by: Guennadi Liakhovetski --- include/sound/sof.h | 4 + include/sound/sof/header.h | 2 + include/sound/sof/rpmsg.h | 120 ++ include/sound/sof/topology.h| 9 +- include/uapi/linux/virtio_ids.h | 1 + sound/soc/sof/Kconfig | 7 + sound/soc/sof/Makefile | 4 + sound/soc/sof/core.c| 29 +- sound/soc/sof/ipc.c | 16 +- sound/soc/sof/pcm.c | 9 + sound/soc/sof/rpmsg-vfe.c | 881 sound/soc/sof/sof-priv.h| 28 ++ sound/soc/sof/topology.c| 18 +- 13 files changed, 1099 insertions(+), 29 deletions(-) create mode 100644 include/sound/sof/rpmsg.h create mode 100644 sound/soc/sof/rpmsg-vfe.c diff --git a/include/sound/sof.h b/include/sound/sof.h index f3e716c..761ef8c 100644 --- a/include/sound/sof.h +++ b/include/sound/sof.h @@ -17,6 +17,8 @@ struct snd_sof_dsp_ops; +struct sof_vfe; + /* * SOF Platform data. */ @@ -30,6 +32,8 @@ struct snd_sof_pdata { /* indicate how many first bytes shouldn't be loaded into DSP memory. */ size_t fw_offset; + struct sof_vfe *vfe; + /* * notification callback used if the hardware initialization * can take time or is handled in a workqueue. This callback diff --git a/include/sound/sof/header.h b/include/sound/sof/header.h index 5ee296c..9844fbe 100644 --- a/include/sound/sof/header.h +++ b/include/sound/sof/header.h @@ -67,6 +67,8 @@ #define SOF_IPC_TPLG_PIPE_COMPLETE SOF_CMD_TYPE(0x013) #define SOF_IPC_TPLG_BUFFER_NEWSOF_CMD_TYPE(0x020) #define SOF_IPC_TPLG_BUFFER_FREE SOF_CMD_TYPE(0x021) +#define SOF_IPC_TPLG_VFE_GET SOF_CMD_TYPE(0x030) +#define SOF_IPC_TPLG_VFE_COMP_ID SOF_CMD_TYPE(0x031) /* PM */ #define SOF_IPC_PM_CTX_SAVESOF_CMD_TYPE(0x001) diff --git a/include/sound/sof/rpmsg.h b/include/sound/sof/rpmsg.h new file mode 100644 index ..73dc34c --- /dev/null +++ b/include/sound/sof/rpmsg.h @@ -0,0 +1,120 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* + * Copyright(c) 2018-2020 Intel Corporation. All rights reserved. + * + * Contact Information: + * Author:Luo Xionghu + * Liam Girdwood + * Guennadi Liakhovetski + */ + +#ifndef _SOF_RPMSG_H +#define _SOF_RPMSG_H + +#include + +#include + +/* host endpoint addresses */ +enum { + SOF_RPMSG_ADDR_IPC, /* IPC commands and replies */ + SOF_RPMSG_ADDR_POSN,/* Stream position updates */ + SOF_RPMSG_ADDR_DATA,/* Audio data */ + SOF_RPMSG_ADDR_COUNT, /* Number of RPMsg endpoints */ +}; + +/** + * struct sof_rpmsg_ipc_tplg_req - request for topology data + * @hdr: the standard SOF IPC header + * @offset:the current offset when transferring a split file + */ +struct sof_rpmsg_ipc_tplg_req { + struct sof_ipc_cmd_hdr hdr; + size_t offset; +} __packed; + +/** + * struct sof_rpmsg_ipc_tplg_resp - response to a topology file request + * @reply: the standard SOF IPC response header + * @data: the complete topology file + * + * The topology file is transferred from the host to the guest over a virtual + * queue in chunks of SOF_IPC_MSG_MAX_SIZE - sizeof(struct sof_ipc_reply), so + * for data transfer the @data array is much smaller than 64KiB. 64KiB is what + * is included in struct sof_vfe for permanent storage of the complete file. + */ +struct sof_rpmsg_ipc_tplg_resp { + struct sof_ipc_reply reply; + /* There exist topology files already larger than 40KiB */ + uint8_t data[64 * 1024 - sizeof(struct sof_ipc_reply)]; +} __packed; + +/** + * struct sof_rpmsg_ipc_power_req - power status change IPC + * @hdr: the standard SOF IPC header + * @power: 1: on, 0: off + */ +struct sof_rpmsg_ipc_power_req { + struct sof_ipc_cmd_hdr hdr; + uint32_t power; +} __packed; + +enum sof_rpmsg_ipc_reset_status { + SOF_RPMSG_IPC_RESET_NONE, /* Host hasn't been reset */ + SOF_RPMSG_IPC_RESET_DONE, /* Host has been reset */ +}; + +/** + * struct sof_rpmsg_ipc_power_resp - response to a power status request + * @reply: the standard SOF IPC response header + * @reset_status: enum
[RFC 01/12] ASoC: add function parameters to enable forced path pruning
This is a preparation for the host part of a virtualised VirtIO audio host-guest driver pair. It adds a "mode" parameter to soc_dpcm_runtime_update() to allow it to be used when stopping streaming in a virtual machine, which requires forced DPCM audio path pruning. For audio virtualisation the host side driver will be using the vhost API, i.e. it will run completely in the kernel. When a guest begins to stream audio, the vhost calls snd_soc_runtime_activate() and soc_dpcm_runtime_update() to activate an audio path and update audio routing. When streaming is stopped, the vhost driver calls soc_dpcm_runtime_update() and snd_soc_runtime_deactivate(). The latter doesn't work at the moment, because the DPCM doesn't recognise the path as inactive. We address this by adding a "mode" parameter to soc_dpcm_runtime_update(). If virtualisation isn't used, the current behaviour isn't affected. Signed-off-by: Guennadi Liakhovetski --- include/sound/soc-dpcm.h | 28 sound/soc/soc-compress.c | 2 +- sound/soc/soc-dapm.c | 8 +++--- sound/soc/soc-pcm.c | 67 +--- 4 files changed, 74 insertions(+), 31 deletions(-) diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h index 0f6c50b..b961c06 100644 --- a/include/sound/soc-dpcm.h +++ b/include/sound/soc-dpcm.h @@ -61,6 +61,23 @@ enum snd_soc_dpcm_trigger { SND_SOC_DPCM_TRIGGER_BESPOKE, }; +/** + * enum snd_soc_dpcm_update_mode - mode for calling soc_dpcm_runtime_update() + * + * @SND_SOC_DPCM_UPDATE_FULL: default mode, used for mux, mixer, and + * volume widgets + * @SND_SOC_DPCM_UPDATE_NEW_ONLY: a pipeline is starting. Skip checking + * for old paths. + * @SND_SOC_DPCM_UPDATE_OLD_ONLY: a pipeline is shutting down. Skip + * checking for new paths, force old path + * pruning. + */ +enum snd_soc_dpcm_update_mode { + SND_SOC_DPCM_UPDATE_FULL, + SND_SOC_DPCM_UPDATE_NEW_ONLY, + SND_SOC_DPCM_UPDATE_OLD_ONLY, +}; + /* * Dynamic PCM link * This links together a FE and BE DAI at runtime and stores the link @@ -133,7 +150,8 @@ struct snd_pcm_substream * snd_soc_dpcm_get_substream(struct snd_soc_pcm_runtime *be, int stream); /* update audio routing between PCMs and any DAI links */ -int snd_soc_dpcm_runtime_update(struct snd_soc_card *card); +int snd_soc_dpcm_runtime_update(struct snd_soc_card *card, + enum snd_soc_dpcm_update_mode mode); #ifdef CONFIG_DEBUG_FS void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd); @@ -143,11 +161,11 @@ static inline void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd) } #endif -int dpcm_path_get(struct snd_soc_pcm_runtime *fe, - int stream, struct snd_soc_dapm_widget_list **list_); +int dpcm_path_get(struct snd_soc_pcm_runtime *fe, int stream, + struct snd_soc_dapm_widget_list **list_); void dpcm_path_put(struct snd_soc_dapm_widget_list **list); -int dpcm_process_paths(struct snd_soc_pcm_runtime *fe, - int stream, struct snd_soc_dapm_widget_list **list, int new); +int dpcm_process_paths(struct snd_soc_pcm_runtime *fe, int stream, + struct snd_soc_dapm_widget_list **list, bool new, bool force_prune); int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream); int dpcm_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream); void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream); diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 62ece72..c9539b8 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -155,7 +155,7 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) dev_dbg(fe->dev, "Compress ASoC: %s no valid %s route\n", fe->dai_link->name, stream ? "capture" : "playback"); /* calculate valid and active FE <-> BE dpcms */ - dpcm_process_paths(fe, stream, , 1); + dpcm_process_paths(fe, stream, , true, false); fe->dpcm[stream].runtime = fe_substream->runtime; fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index a4de3e4..e27d93d 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2311,7 +2311,7 @@ int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm, card->update = NULL; mutex_unlock(>dapm_mutex); if (ret > 0) - snd_soc_dpcm_runtime_update(card); + snd_soc_dpcm_runtime_update(card, SND_SOC_DPCM_UPDATE_FULL); return ret; } EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power); @@ -2376,7 +2376,7 @@ int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm, card->update = NULL; mutex_unlock(>dapm_mutex); if (ret > 0) -
[RFC 08/12] ASoC: SOF: add a vhost driver: sound part
The SOF VirtIO driver uses a vhost RPMsg driver as a counterpart to communicate with the DSP. This patch adds a sound interface of the vhost driver. Signed-off-by: Guennadi Liakhovetski --- include/sound/soc-topology.h |3 + include/sound/sof/rpmsg.h| 72 +++ include/uapi/linux/vhost.h |5 + include/uapi/linux/vhost_types.h |7 + sound/soc/soc-pcm.c | 31 +- sound/soc/sof/Makefile |6 +- sound/soc/sof/core.c |6 + sound/soc/sof/ipc.c |5 + sound/soc/sof/pcm.c |4 +- sound/soc/sof/pm.c |4 + sound/soc/sof/sof-audio.c|9 + sound/soc/sof/sof-audio.h| 16 + sound/soc/sof/sof-priv.h | 16 + sound/soc/sof/topology.c | 54 +- sound/soc/sof/vhost-vbe.c| 1102 ++ 15 files changed, 1324 insertions(+), 16 deletions(-) create mode 100644 sound/soc/sof/vhost-vbe.c diff --git a/include/sound/soc-topology.h b/include/sound/soc-topology.h index 5223896..ea0c2a64 100644 --- a/include/sound/soc-topology.h +++ b/include/sound/soc-topology.h @@ -34,6 +34,9 @@ /* object scan be loaded and unloaded in groups with identfying indexes */ #define SND_SOC_TPLG_INDEX_ALL 0 /* ID that matches all FW objects */ +#define SOC_VIRT_DAI_PLAYBACK "VM FE Playback" +#define SOC_VIRT_DAI_CAPTURE "VM FE Capture" + /* dynamic object type */ enum snd_soc_dobj_type { SND_SOC_DOBJ_NONE = 0,/* object is not dynamic */ diff --git a/include/sound/sof/rpmsg.h b/include/sound/sof/rpmsg.h index 73dc34c..ce522c6 100644 --- a/include/sound/sof/rpmsg.h +++ b/include/sound/sof/rpmsg.h @@ -11,6 +11,7 @@ #ifndef _SOF_RPMSG_H #define _SOF_RPMSG_H +#include #include #include @@ -117,4 +118,75 @@ struct sof_rpmsg_ipc_req { u8 ipc_msg[SOF_IPC_MSG_MAX_SIZE]; } __packed; +struct snd_sof_dev; +struct sof_ipc_stream_posn; + +#if IS_ENABLED(CONFIG_VHOST_SOF) +struct firmware; + +struct vhost_dsp; +struct sof_vhost_ops { + int (*update_posn)(struct vhost_dsp *dsp, + struct sof_ipc_stream_posn *posn); +}; + +struct sof_vhost_client { + const struct firmware *fw; + struct snd_sof_dev *sdev; + /* List of guest endpoints, connecting to the host mixer or demux */ + struct list_head pipe_conn; + /* List of vhost instances on a DSP */ + struct list_head list; + + /* Component ID range index in the bitmap */ + unsigned int id; + + /* the comp_ids for this vm audio */ + int comp_id_begin; + int comp_id_end; + + unsigned int reset_count; + + struct vhost_dsp *vhost; +}; + +/* The below functions are only referenced when VHOST_SOF is selected */ +struct device; +void sof_vhost_client_release(struct sof_vhost_client *client); +struct sof_vhost_client *sof_vhost_client_add(struct snd_sof_dev *sdev, + struct vhost_dsp *dsp); +struct device *sof_vhost_dev_init(const struct sof_vhost_ops *ops); +struct vhost_adsp_topology; +int sof_vhost_set_tplg(struct sof_vhost_client *client, + const struct vhost_adsp_topology *tplg); +/* Copy audio data between DMA and VirtQueue */ +void *sof_vhost_stream_data(struct sof_vhost_client *client, + const struct sof_rpmsg_data_req *req, + struct sof_rpmsg_data_resp *resp); +/* Forward an IPC message from a guest to the DSP */ +int sof_vhost_ipc_fwd(struct sof_vhost_client *client, + void *ipc_buf, void *reply_buf, + size_t count, size_t reply_sz); + +/* The below functions are always referenced, they need dummy counterparts */ +int sof_vhost_update_guest_posn(struct snd_sof_dev *sdev, + struct sof_ipc_stream_posn *posn); +void sof_vhost_suspend(struct snd_sof_dev *sdev); +void sof_vhost_dev_set(struct snd_sof_dev *sdev); +#else +static inline int sof_vhost_update_guest_posn(struct snd_sof_dev *sdev, + struct sof_ipc_stream_posn *posn) +{ + return 0; +} + +static inline void sof_vhost_suspend(struct snd_sof_dev *sdev) +{ +} + +static inline void sof_vhost_dev_set(struct snd_sof_dev *sdev) +{ +} +#endif + #endif diff --git a/include/uapi/linux/vhost.h b/include/uapi/linux/vhost.h index b54af9d..aa258e2 100644 --- a/include/uapi/linux/vhost.h +++ b/include/uapi/linux/vhost.h @@ -142,4 +142,9 @@ /* Get the max ring size. */ #define VHOST_VDPA_GET_VRING_NUM _IOR(VHOST_VIRTIO, 0x76, __u16) +/* VHOST_ADSP specific defines */ + +#define VHOST_ADSP_SET_GUEST_TPLG _IOW(VHOST_VIRTIO, 0x80,\ + struct vhost_adsp_topology) + #endif diff --git a/include/uapi/linux/vhost_types.h b/include/uapi/linux/vhost_types.h index 669457c..6364bc8 100644 --- a/include/uapi/linux/vhost_types.h +++
[RFC 03/12] ASoC: SOF: support IPC with immediate response
Usually when an IPC message is sent, we have to wait for a reply from the DSP or from the host in the VirtIO case. However, sometimes in the VirtIO case a response is available immediately. Skip sleeping in such cases. Signed-off-by: Guennadi Liakhovetski --- sound/soc/sof/ipc.c | 11 +++ sound/soc/sof/ops.h | 10 +- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index f7a0353..b3e1587 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -262,6 +262,12 @@ static int sof_ipc_tx_message_unlocked(struct snd_sof_ipc *ipc, u32 header, sdev->msg = msg; + /* +* If snd_sof_dsp_send_msg() returns a positive number it means, that a +* response is already available, no need to sleep waiting for it. In +* such a case msg->ipc_complete will stay true and tx_wait_done() will +* return immediately. +*/ ret = snd_sof_dsp_send_msg(sdev, msg); /* Next reply that we receive will be related to this message */ if (!ret) @@ -279,10 +285,7 @@ static int sof_ipc_tx_message_unlocked(struct snd_sof_ipc *ipc, u32 header, ipc_log_header(sdev->dev, "ipc tx", msg->header); /* now wait for completion */ - if (!ret) - ret = tx_wait_done(ipc, msg, reply_data); - - return ret; + return tx_wait_done(ipc, msg, reply_data); } /* send IPC message from host to DSP */ diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index b21632f..bf91467 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -274,7 +274,15 @@ static inline void snd_sof_dsp_block_write(struct snd_sof_dev *sdev, u32 bar, sof_ops(sdev)->block_write(sdev, bar, offset, src, bytes); } -/* ipc */ +/** + * snd_sof_dsp_send_msg - call sdev ops to send a message + * @sdev: sdev context + * @msg: message to send + * + * Returns < 0 - an error code + * 0 - the message has been sent, wait for a reply + * > 0 - the message has been sent, a reply is already available + */ static inline int snd_sof_dsp_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) { -- 1.9.3 ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[RFC 09/12] ASoC: SOF: VirtIO: free guest pipelines upon termination
Currently the SOF driver switches off the DSP every time runtime or system-wide suspend is entered. After the DSP is turned off, next time it's turned on, the firmware and topology have to be re-sent to it. When a guest SOF instance restarts it sends its topology to the host, which then forwards it to the DSP. This is correct if the DSP was suspended during that time and lost the guest's topology. However, if the DSP stayed active during that entire time, sending duplicate components to it produces errors. To prevent this from happening this patch adds freeing of components during guest shut down. Signed-off-by: Guennadi Liakhovetski --- include/sound/sof/rpmsg.h | 4 ++ sound/soc/sof/vhost-vbe.c | 158 +- 2 files changed, 161 insertions(+), 1 deletion(-) diff --git a/include/sound/sof/rpmsg.h b/include/sound/sof/rpmsg.h index ce522c6..7f907e6 100644 --- a/include/sound/sof/rpmsg.h +++ b/include/sound/sof/rpmsg.h @@ -137,6 +137,9 @@ struct sof_vhost_client { struct list_head pipe_conn; /* List of vhost instances on a DSP */ struct list_head list; + /* List of widgets to free for tear-down */ + struct list_head comp_list; + struct list_head pipe_list; /* Component ID range index in the bitmap */ unsigned int id; @@ -167,6 +170,7 @@ void *sof_vhost_stream_data(struct sof_vhost_client *client, int sof_vhost_ipc_fwd(struct sof_vhost_client *client, void *ipc_buf, void *reply_buf, size_t count, size_t reply_sz); +void sof_vhost_topology_purge(struct sof_vhost_client *client); /* The below functions are always referenced, they need dummy counterparts */ int sof_vhost_update_guest_posn(struct snd_sof_dev *sdev, diff --git a/sound/soc/sof/vhost-vbe.c b/sound/soc/sof/vhost-vbe.c index 8056e25..3887bba 100644 --- a/sound/soc/sof/vhost-vbe.c +++ b/sound/soc/sof/vhost-vbe.c @@ -43,6 +43,18 @@ struct dsp_pipeline_connect { struct list_head list; }; +struct sof_vhost_comp_list { + struct list_head list; + uint32_t comp_id; + enum sof_comp_type comp_type; +}; + +struct sof_vhost_pipe_list { + struct list_head list; + uint32_t comp_id; + uint32_t pipe_id; +}; + static const char dsp_pcm_name[] = "VHost PCM"; /* @@ -446,6 +458,75 @@ static int sof_vhost_ipc_comp(struct sof_vhost_client *client, cdata->comp_id >= client->comp_id_end ? -EINVAL : 0; } +void sof_vhost_topology_purge(struct sof_vhost_client *client) +{ + struct snd_sof_dev *sdev = client->sdev; + struct sof_ipc_free fcomp = { + .hdr = { + .size = sizeof(fcomp), + }, + }; + struct sof_ipc_reply reply; + struct sof_vhost_comp_list *citem, *ctmp; + struct sof_vhost_pipe_list *pitem, *ptmp; + int ret; + + pm_runtime_get_sync(sdev->dev); + + /* First free all pipelines */ + list_for_each_entry_safe(pitem, ptmp, >pipe_list, list) { + fcomp.id = pitem->comp_id; + fcomp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | + SOF_IPC_TPLG_PIPE_FREE; + + dev_dbg(sdev->dev, "tplg: unload component ID: %d pipe %u\n", + fcomp.id, pitem->pipe_id); + + /* send IPC to the DSP */ + ret = sof_ipc_tx_message(sdev->ipc, +fcomp.hdr.cmd, , sizeof(fcomp), +, sizeof(reply)); + if (ret < 0) + dev_err(sdev->dev, "error: %d unloading component %d\n", + ret, fcomp.id); + + list_del(>list); + kfree(pitem); + } + + /* Then free all individual components */ + list_for_each_entry_safe(citem, ctmp, >comp_list, list) { + fcomp.id = citem->comp_id; + switch (citem->comp_type) { + case SOF_COMP_BUFFER: + fcomp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | + SOF_IPC_TPLG_BUFFER_FREE; + break; + default: + fcomp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | + SOF_IPC_TPLG_COMP_FREE; + } + + dev_dbg(sdev->dev, "tplg: unload component ID: %d type %u\n", + fcomp.id, citem->comp_type); + + /* send IPC to the DSP */ + ret = sof_ipc_tx_message(sdev->ipc, +fcomp.hdr.cmd, , sizeof(fcomp), +, sizeof(reply)); + if (ret < 0) + dev_err(sdev->dev, "error: %d unloading component %d\n", + ret, fcomp.id); + + list_del(>list); + kfree(citem); + } + + pm_runtime_mark_last_busy(sdev->dev);
[RFC 10/12] vhost: add an SOF Audio DSP driver
The SOF ADSP vhost driver consists of two parts: a sound and a vhost part. This patch implements the vhost part of the driver. It handles QEMU communication with the vhost misc device and virtual queues to any VirtIO RPMsg guests. Signed-off-by: Guennadi Liakhovetski --- drivers/vhost/Kconfig | 10 + drivers/vhost/Makefile | 3 + drivers/vhost/adsp.c | 618 + 3 files changed, 631 insertions(+) create mode 100644 drivers/vhost/adsp.c diff --git a/drivers/vhost/Kconfig b/drivers/vhost/Kconfig index 8b91f3e..ef3e459 100644 --- a/drivers/vhost/Kconfig +++ b/drivers/vhost/Kconfig @@ -54,6 +54,16 @@ config VHOST_SCSI Say M here to enable the vhost_scsi TCM fabric module for use with virtio-scsi guests +config VHOST_SOF + tristate "Vhost SOF driver" + depends on SND_SOC_SOF + select VHOST + select VHOST_RPMSG + default n + help + SOF vhost VirtIO driver. It exports the same IPC interface, as the + one, used for Audio DSP communication, to Linux VirtIO guests. + config VHOST_VSOCK tristate "vhost virtio-vsock driver" depends on VSOCKETS && EVENTFD diff --git a/drivers/vhost/Makefile b/drivers/vhost/Makefile index 9cf459d..86cbd12 100644 --- a/drivers/vhost/Makefile +++ b/drivers/vhost/Makefile @@ -8,6 +8,9 @@ vhost_rpmsg-y := rpmsg.o obj-$(CONFIG_VHOST_SCSI) += vhost_scsi.o vhost_scsi-y := scsi.o +obj-$(CONFIG_VHOST_SOF) += vhost_sof.o +vhost_sof-y := adsp.o + obj-$(CONFIG_VHOST_VSOCK) += vhost_vsock.o vhost_vsock-y := vsock.o diff --git a/drivers/vhost/adsp.c b/drivers/vhost/adsp.c new file mode 100644 index ..c0a496f --- /dev/null +++ b/drivers/vhost/adsp.c @@ -0,0 +1,618 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* + * Copyright(c) 2019-2020 Intel Corporation. All rights reserved. + * + * Author: Guennadi Liakhovetski + * + * vhost-SOF VirtIO interface + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "vhost.h" +#include "vhost_rpmsg.h" + +#define VHOST_DSP_FEATURES (VHOST_FEATURES | (1ULL << VIRTIO_RPMSG_F_NS)) + +struct snd_sof_dev; +struct sof_vhost_client; + +struct vhost_dsp { + struct vhost_rpmsg vrdev; + + struct sof_vhost_client *snd; + + bool active; + + /* RPMsg address of the position update endpoint */ + u32 posn_addr; + /* position update buffer and work */ + struct vhost_work posn_work; + struct sof_ipc_stream_posn posn; + + /* IPC request buffer */ + struct sof_rpmsg_ipc_req ipc_buf; + /* IPC response buffer */ + u8 reply_buf[SOF_IPC_MSG_MAX_SIZE]; + /* +* data response header, captured audio data is copied directly from the +* DMA buffer +*/ + struct sof_rpmsg_data_resp data_resp; +}; + +/* A guest is booting */ +static int vhost_dsp_activate(struct vhost_dsp *dsp) +{ + unsigned int i; + int ret = 0; + + mutex_lock(>vrdev.dev.mutex); + + /* Wait until all the VirtQueues have been initialised */ + if (!dsp->active) { + struct vhost_virtqueue *vq; + + for (i = 0, vq = dsp->vrdev.vq; +i < ARRAY_SIZE(dsp->vrdev.vq); +i++, vq++) { + /* .private_data is required != NULL */ + vhost_vq_set_backend(vq, dsp); + /* needed for re-initialisation upon guest reboot */ + ret = vhost_vq_init_access(vq); + if (ret) + vq_err(vq, + "%s(): error %d initialising vq #%d\n", + __func__, ret, i); + } + + /* Send an RPMsg namespace announcement */ + if (!ret && !vhost_rpmsg_ns_announce(>vrdev, "sof_rpmsg", +SOF_RPMSG_ADDR_IPC)) + dsp->active = true; + } + + mutex_unlock(>vrdev.dev.mutex); + + return ret; +} + +/* A guest is powered off or reset */ +static void vhost_dsp_deactivate(struct vhost_dsp *dsp) +{ + unsigned int i; + + mutex_lock(>vrdev.dev.mutex); + + if (dsp->active) { + struct vhost_virtqueue *vq; + + dsp->active = false; + + /* If a VM reboots sof_vhost_client_release() isn't called */ + sof_vhost_topology_purge(dsp->snd); + + /* signal, that we're inactive */ + for (i = 0, vq = dsp->vrdev.vq; +i < ARRAY_SIZE(dsp->vrdev.vq); +i++, vq++) { + mutex_lock(>mutex); + vhost_vq_set_backend(vq, NULL); + mutex_unlock(>mutex); + } + } + +
[RFC 05/12] ASoC: SOF: add two helper lookup functions
Add two helper lookup functions for finding a widget by its component ID and a DAI by a pipeline ID. Signed-off-by: Guennadi Liakhovetski --- sound/soc/sof/sof-audio.c | 24 sound/soc/sof/sof-audio.h | 5 + sound/soc/sof/topology.c | 1 + 3 files changed, 30 insertions(+) diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 1c7698f..92fa6a8 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -395,6 +395,30 @@ struct snd_sof_dai *snd_sof_find_dai(struct snd_soc_component *scomp, return NULL; } +struct snd_sof_widget *snd_sof_find_swidget_id(struct snd_sof_dev *sdev, + unsigned int comp_id) +{ + struct snd_sof_widget *swidget; + + list_for_each_entry(swidget, >widget_list, list) + if (swidget->comp_id == comp_id) + return swidget; + + return NULL; +} + +struct snd_sof_dai *snd_sof_find_dai_pipe(struct snd_sof_dev *sdev, + unsigned int pipeline_id) +{ + struct snd_sof_dai *dai; + + list_for_each_entry(dai, >dai_list, list) + if (dai->pipeline_id == pipeline_id) + return dai; + + return NULL; +} + /* * SOF Driver enumeration. */ diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 9629994..8054e48 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -106,6 +106,7 @@ struct snd_sof_dai { struct snd_soc_component *scomp; const char *name; const char *cpu_dai_name; + unsigned int pipeline_id; struct sof_ipc_comp_dai comp_dai; struct sof_ipc_dai_config *dai_config; @@ -190,6 +191,10 @@ struct snd_sof_pcm *snd_sof_find_spcm_comp(struct snd_soc_component *scomp, int *direction); struct snd_sof_pcm *snd_sof_find_spcm_pcm_id(struct snd_soc_component *scomp, unsigned int pcm_id); +struct snd_sof_widget *snd_sof_find_swidget_id(struct snd_sof_dev *sdev, + unsigned int comp_id); +struct snd_sof_dai *snd_sof_find_dai_pipe(struct snd_sof_dev *sdev, + unsigned int pipeline_id); void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream); void snd_sof_pcm_period_elapsed_work(struct work_struct *work); diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 6a9703e..5a65dcf 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -1406,6 +1406,7 @@ static int sof_widget_load_dai(struct snd_soc_component *scomp, int index, if (ret == 0 && dai) { dai->scomp = scomp; + dai->pipeline_id = swidget->pipeline_id; memcpy(>comp_dai, _dai, sizeof(comp_dai)); } -- 1.9.3 ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[RFC 07/12] ASoC: SOF: use a macro instead of a hard-coded value
target_stats in sof_suspend should contain one of SOF_DSP_PM_* power state macros, not a hard-coded value 0. Signed-off-by: Guennadi Liakhovetski --- sound/soc/sof/pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index 5e804a7..c7aa2cf 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -174,7 +174,7 @@ static int sof_resume(struct device *dev, bool runtime_resume) static int sof_suspend(struct device *dev, bool runtime_suspend) { struct snd_sof_dev *sdev = dev_get_drvdata(dev); - u32 target_state = 0; + u32 target_state = SOF_DSP_PM_D0; int ret; /* do nothing if dsp suspend callback is not set */ -- 1.9.3 ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[RFC 02/12] ASoC: SOF: extract firmware-related operation into a function
In the VirtIO guest case the SOF will not be dealing with the firmware directly. Extract related functionality into a function to make the separation easier. Signed-off-by: Guennadi Liakhovetski --- sound/soc/sof/core.c | 85 ++-- 1 file changed, 49 insertions(+), 36 deletions(-) diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 339c493..17f264f 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -135,6 +135,53 @@ void snd_sof_get_status(struct snd_sof_dev *sdev, u32 panic_code, * (System Suspend/Runtime Suspend) */ +static int sof_load_and_run_firmware(struct snd_sof_dev *sdev) +{ + /* load the firmware */ + int ret = snd_sof_load_firmware(sdev); + if (ret < 0) { + dev_err(sdev->dev, "error: failed to load DSP firmware %d\n", + ret); + return ret; + } + + sdev->fw_state = SOF_FW_BOOT_IN_PROGRESS; + + /* +* Boot the firmware. The FW boot status will be modified +* in snd_sof_run_firmware() depending on the outcome. +*/ + ret = snd_sof_run_firmware(sdev); + if (ret < 0) { + dev_err(sdev->dev, "error: failed to boot DSP firmware %d\n", + ret); + goto fw_run_err; + } + + if (IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_FIRMWARE_TRACE) || + (sof_core_debug & SOF_DBG_ENABLE_TRACE)) { + sdev->dtrace_is_supported = true; + + /* init DMA trace */ + ret = snd_sof_init_trace(sdev); + if (ret < 0) { + /* non fatal */ + dev_warn(sdev->dev, +"warning: failed to initialize trace %d\n", +ret); + } + } else { + dev_dbg(sdev->dev, "SOF firmware trace disabled\n"); + } + + return 0; + +fw_run_err: + snd_sof_fw_unload(sdev); + + return ret; +} + static int sof_probe_continue(struct snd_sof_dev *sdev) { struct snd_sof_pdata *plat_data = sdev->pdata; @@ -181,42 +228,9 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) goto ipc_err; } - /* load the firmware */ - ret = snd_sof_load_firmware(sdev); - if (ret < 0) { - dev_err(sdev->dev, "error: failed to load DSP firmware %d\n", - ret); + ret = sof_load_and_run_firmware(sdev); + if (ret < 0) goto fw_load_err; - } - - sdev->fw_state = SOF_FW_BOOT_IN_PROGRESS; - - /* -* Boot the firmware. The FW boot status will be modified -* in snd_sof_run_firmware() depending on the outcome. -*/ - ret = snd_sof_run_firmware(sdev); - if (ret < 0) { - dev_err(sdev->dev, "error: failed to boot DSP firmware %d\n", - ret); - goto fw_run_err; - } - - if (IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_FIRMWARE_TRACE) || - (sof_core_debug & SOF_DBG_ENABLE_TRACE)) { - sdev->dtrace_is_supported = true; - - /* init DMA trace */ - ret = snd_sof_init_trace(sdev); - if (ret < 0) { - /* non fatal */ - dev_warn(sdev->dev, -"warning: failed to initialize trace %d\n", -ret); - } - } else { - dev_dbg(sdev->dev, "SOF firmware trace disabled\n"); - } /* hereafter all FW boot flows are for PM reasons */ sdev->first_boot = false; @@ -250,7 +264,6 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) fw_trace_err: snd_sof_free_trace(sdev); -fw_run_err: snd_sof_fw_unload(sdev); fw_load_err: snd_sof_ipc_free(sdev); -- 1.9.3 ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[RFC 00/12] Audio DSP VirtIO and vhost drivers
This patch set is a follow up to "Add a vhost RPMsg API" [1], it is marked as an RFC because firstly it depends on the RPMsg API series and secondly it is currently being reviewed on ALSA and SOF mailing lists, but any early comments from virtualisation developers would be highly appreciated too! Thanks Guennadi [1] https://mailman.alsa-project.org/pipermail/sound-open-firmware/2020-May/003879.html Guennadi Liakhovetski (12): ASoC: add function parameters to enable forced path pruning ASoC: SOF: extract firmware-related operation into a function ASoC: SOF: support IPC with immediate response ASoC: SOF: add a power status IPC ASoC: SOF: add two helper lookup functions ASoC: SOF: add an RPMsg VirtIO DSP driver ASoC: SOF: use a macro instead of a hard-coded value ASoC: SOF: add a vhost driver: sound part ASoC: SOF: VirtIO: free guest pipelines upon termination vhost: add an SOF Audio DSP driver rpmsg: increase buffer size and reduce buffer number rpmsg: add a device ID to also bind to the ADSP device drivers/rpmsg/virtio_rpmsg_bus.c |1 + drivers/vhost/Kconfig| 10 + drivers/vhost/Makefile |3 + drivers/vhost/adsp.c | 618 +++ include/linux/virtio_rpmsg.h |4 +- include/sound/soc-dpcm.h | 28 +- include/sound/soc-topology.h |3 + include/sound/sof.h |4 + include/sound/sof/header.h |3 + include/sound/sof/rpmsg.h| 196 ++ include/sound/sof/topology.h |9 +- include/uapi/linux/vhost.h |5 + include/uapi/linux/vhost_types.h |7 + include/uapi/linux/virtio_ids.h |1 + sound/soc/soc-compress.c |2 +- sound/soc/soc-dapm.c |8 +- sound/soc/soc-pcm.c | 98 ++- sound/soc/sof/Kconfig|7 + sound/soc/sof/Makefile |2 + sound/soc/sof/core.c | 114 ++-- sound/soc/sof/ipc.c | 34 +- sound/soc/sof/loader.c |4 + sound/soc/sof/ops.h | 10 +- sound/soc/sof/pcm.c | 13 +- sound/soc/sof/pm.c |6 +- sound/soc/sof/rpmsg-vfe.c| 881 ++ sound/soc/sof/sof-audio.c| 33 + sound/soc/sof/sof-audio.h| 21 + sound/soc/sof/sof-priv.h | 48 ++ sound/soc/sof/topology.c | 71 ++- sound/soc/sof/vhost-vbe.c| 1258 ++ 31 files changed, 3391 insertions(+), 111 deletions(-) create mode 100644 drivers/vhost/adsp.c create mode 100644 include/sound/sof/rpmsg.h create mode 100644 sound/soc/sof/rpmsg-vfe.c create mode 100644 sound/soc/sof/vhost-vbe.c -- 1.9.3 ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Re: [PATCH v3 0/5] Add a vhost RPMsg API
On 2020/5/29 下午2:50, Guennadi Liakhovetski wrote: Hi Jason, On Fri, May 29, 2020 at 02:01:53PM +0800, Jason Wang wrote: On 2020/5/28 上午2:05, Guennadi Liakhovetski wrote: v3: - address several checkpatch warnings - address comments from Mathieu Poirier v2: - update patch #5 with a correct vhost_dev_init() prototype - drop patch #6 - it depends on a different patch, that is currently an RFC - address comments from Pierre-Louis Bossart: * remove "default n" from Kconfig Linux supports RPMsg over VirtIO for "remote processor" /AMP use cases. It can however also be used for virtualisation scenarios, e.g. when using KVM to run Linux on both the host and the guests. This patch set adds a wrapper API to facilitate writing vhost drivers for such RPMsg-based solutions. The first use case is an audio DSP virtualisation project, currently under development, ready for review and submission, available at https://github.com/thesofproject/linux/pull/1501/commits A further patch for the ADSP vhost RPMsg driver will be sent separately for review only since it cannot be merged without audio patches being upstreamed first. Hi: It would be hard to evaluate this series without a real user. So if possible, I suggest to post the actual user for vhost rpmsg API. Sure, the whole series is available at https://github.com/thesofproject/linux/pull/1501/commits or would you prefer the missing patches posted to the lists too? Yes, since I see new virtio and vhost drivers there. Thanks Thanks Guennadi ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Re: [PATCH v3 0/5] Add a vhost RPMsg API
Hi Jason, On Fri, May 29, 2020 at 02:01:53PM +0800, Jason Wang wrote: > > On 2020/5/28 上午2:05, Guennadi Liakhovetski wrote: > > v3: > > - address several checkpatch warnings > > - address comments from Mathieu Poirier > > > > v2: > > - update patch #5 with a correct vhost_dev_init() prototype > > - drop patch #6 - it depends on a different patch, that is currently > >an RFC > > - address comments from Pierre-Louis Bossart: > >* remove "default n" from Kconfig > > > > Linux supports RPMsg over VirtIO for "remote processor" /AMP use > > cases. It can however also be used for virtualisation scenarios, > > e.g. when using KVM to run Linux on both the host and the guests. > > This patch set adds a wrapper API to facilitate writing vhost > > drivers for such RPMsg-based solutions. The first use case is an > > audio DSP virtualisation project, currently under development, ready > > for review and submission, available at > > https://github.com/thesofproject/linux/pull/1501/commits > > A further patch for the ADSP vhost RPMsg driver will be sent > > separately for review only since it cannot be merged without audio > > patches being upstreamed first. > > > Hi: > > It would be hard to evaluate this series without a real user. So if > possible, I suggest to post the actual user for vhost rpmsg API. Sure, the whole series is available at https://github.com/thesofproject/linux/pull/1501/commits or would you prefer the missing patches posted to the lists too? Thanks Guennadi ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Re: [PATCH v3 0/5] Add a vhost RPMsg API
On 2020/5/28 上午2:05, Guennadi Liakhovetski wrote: v3: - address several checkpatch warnings - address comments from Mathieu Poirier v2: - update patch #5 with a correct vhost_dev_init() prototype - drop patch #6 - it depends on a different patch, that is currently an RFC - address comments from Pierre-Louis Bossart: * remove "default n" from Kconfig Linux supports RPMsg over VirtIO for "remote processor" /AMP use cases. It can however also be used for virtualisation scenarios, e.g. when using KVM to run Linux on both the host and the guests. This patch set adds a wrapper API to facilitate writing vhost drivers for such RPMsg-based solutions. The first use case is an audio DSP virtualisation project, currently under development, ready for review and submission, available at https://github.com/thesofproject/linux/pull/1501/commits A further patch for the ADSP vhost RPMsg driver will be sent separately for review only since it cannot be merged without audio patches being upstreamed first. Hi: It would be hard to evaluate this series without a real user. So if possible, I suggest to post the actual user for vhost rpmsg API. Thanks Thanks Guennadi ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization