[PATCH 2/2] vhost: convert get_user_pages() --> pin_user_pages()

2020-05-29 Thread John Hubbard
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"

2020-05-29 Thread John Hubbard
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"

2020-05-29 Thread John Hubbard
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

2020-05-29 Thread Rob Miller via Virtualization
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

2020-05-29 Thread Stefano Garzarella
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

2020-05-29 Thread Tom Lendacky




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

2020-05-29 Thread Stefano Garzarella
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

2020-05-29 Thread Christoph Hellwig
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

2020-05-29 Thread Jason Wang


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

2020-05-29 Thread Borislav Petkov
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

2020-05-29 Thread Jason Wang
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

2020-05-29 Thread Jason Wang
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

2020-05-29 Thread Jason Wang
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

2020-05-29 Thread Jason Wang
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

2020-05-29 Thread Jason Wang
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

2020-05-29 Thread Jason Wang
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

2020-05-29 Thread Jason Wang
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

2020-05-29 Thread Guennadi Liakhovetski
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

2020-05-29 Thread Guennadi Liakhovetski
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

2020-05-29 Thread Guennadi Liakhovetski
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

2020-05-29 Thread Guennadi Liakhovetski
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

2020-05-29 Thread Guennadi Liakhovetski
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

2020-05-29 Thread Guennadi Liakhovetski
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

2020-05-29 Thread Guennadi Liakhovetski
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

2020-05-29 Thread Guennadi Liakhovetski
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

2020-05-29 Thread Guennadi Liakhovetski
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

2020-05-29 Thread Guennadi Liakhovetski
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

2020-05-29 Thread Guennadi Liakhovetski
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

2020-05-29 Thread Guennadi Liakhovetski
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

2020-05-29 Thread Guennadi Liakhovetski
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

2020-05-29 Thread Jason Wang


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

2020-05-29 Thread Guennadi Liakhovetski
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

2020-05-29 Thread Jason Wang


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