Re: [Qemu-block] [PATCH V2 02/11] virtio: convert to use DMA api

2016-11-04 Thread Jason Wang



On 2016年11月04日 03:46, Michael S. Tsirkin wrote:

@@ -244,6 +245,7 @@ int virtio_queue_empty(VirtQueue *vq)
>  static void virtqueue_unmap_sg(VirtQueue *vq, const VirtQueueElement *elem,
> unsigned int len)
>  {
>+AddressSpace *dma_as = virtio_get_dma_as(vq->vdev);
>  unsigned int offset;
>  int i;

Can't we use

vdev->dma_as

here?

I'd like to avoid query on data path.

Same in most other places below.




Will use vdev->dma_as in next version.

Thanks



Re: [Qemu-block] [PATCH V2 02/11] virtio: convert to use DMA api

2016-11-03 Thread Michael S. Tsirkin
On Thu, Nov 03, 2016 at 05:27:14PM +0800, Jason Wang wrote:
> Currently, all virtio devices bypass IOMMU completely. This is because
> address_space_memory is assumed and used during DMA emulation. This
> patch converts the virtio core API to use DMA API. This idea is
> 
> - introducing a new transport specific helper to query the dma address
>   space. (only pci version is implemented).
> - query and use this address space during virtio device guest memory
>   accessing when iommu platform (VIRTIO_F_IOMMU_PLATFORM) was enabled
>   for this device.
> 
> Cc: Michael S. Tsirkin 
> Cc: Stefan Hajnoczi 
> Cc: Kevin Wolf 
> Cc: Amit Shah 
> Cc: Paolo Bonzini 
> Cc: qemu-block@nongnu.org
> Signed-off-by: Jason Wang 
> ---
>  hw/block/virtio-blk.c |  2 +-
>  hw/char/virtio-serial-bus.c   |  3 ++-
>  hw/scsi/virtio-scsi.c |  4 ++-
>  hw/virtio/virtio-bus.c|  8 ++
>  hw/virtio/virtio-pci.c| 14 ++
>  hw/virtio/virtio.c| 57 
> +--
>  include/hw/virtio/virtio-access.h | 36 ++---
>  include/hw/virtio/virtio-bus.h|  1 +
>  include/hw/virtio/virtio.h|  9 ---
>  9 files changed, 98 insertions(+), 36 deletions(-)
> 
> diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
> index 37fe72b..6a2dbaf 100644
> --- a/hw/block/virtio-blk.c
> +++ b/hw/block/virtio-blk.c
> @@ -860,7 +860,7 @@ static int virtio_blk_load_device(VirtIODevice *vdev, 
> QEMUFile *f,
>  }
>  }
>  
> -req = qemu_get_virtqueue_element(f, sizeof(VirtIOBlockReq));
> +req = qemu_get_virtqueue_element(vdev, f, sizeof(VirtIOBlockReq));
>  virtio_blk_init_request(s, virtio_get_queue(vdev, vq_idx), req);
>  req->next = s->rq;
>  s->rq = req;
> diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
> index 7975c2c..d544cd9 100644
> --- a/hw/char/virtio-serial-bus.c
> +++ b/hw/char/virtio-serial-bus.c
> @@ -732,6 +732,7 @@ static void virtio_serial_post_load_timer_cb(void *opaque)
>  static int fetch_active_ports_list(QEMUFile *f,
> VirtIOSerial *s, uint32_t nr_active_ports)
>  {
> +VirtIODevice *vdev = VIRTIO_DEVICE(s);
>  uint32_t i;
>  
>  s->post_load = g_malloc0(sizeof(*s->post_load));
> @@ -765,7 +766,7 @@ static int fetch_active_ports_list(QEMUFile *f,
>  qemu_get_be64s(f, >iov_offset);
>  
>  port->elem =
> -qemu_get_virtqueue_element(f, sizeof(VirtQueueElement));
> +qemu_get_virtqueue_element(vdev, f, 
> sizeof(VirtQueueElement));
>  
>  /*
>   *  Port was throttled on source machine.  Let's
> diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
> index 4762f05..1519cee 100644
> --- a/hw/scsi/virtio-scsi.c
> +++ b/hw/scsi/virtio-scsi.c
> @@ -198,12 +198,14 @@ static void *virtio_scsi_load_request(QEMUFile *f, 
> SCSIRequest *sreq)
>  SCSIBus *bus = sreq->bus;
>  VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
>  VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
> +VirtIODevice *vdev = VIRTIO_DEVICE(s);
>  VirtIOSCSIReq *req;
>  uint32_t n;
>  
>  qemu_get_be32s(f, );
>  assert(n < vs->conf.num_queues);
> -req = qemu_get_virtqueue_element(f, sizeof(VirtIOSCSIReq) + 
> vs->cdb_size);
> +req = qemu_get_virtqueue_element(vdev, f,
> + sizeof(VirtIOSCSIReq) + vs->cdb_size);
>  virtio_scsi_init_req(s, vs->cmd_vqs[n], req);
>  
>  if (virtio_scsi_parse_req(req, sizeof(VirtIOSCSICmdReq) + vs->cdb_size,
> diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c
> index 11f65bd..8597762 100644
> --- a/hw/virtio/virtio-bus.c
> +++ b/hw/virtio/virtio-bus.c
> @@ -28,6 +28,7 @@
>  #include "hw/qdev.h"
>  #include "hw/virtio/virtio-bus.h"
>  #include "hw/virtio/virtio.h"
> +#include "exec/address-spaces.h"
>  
>  /* #define DEBUG_VIRTIO_BUS */
>  
> @@ -61,6 +62,13 @@ void virtio_bus_device_plugged(VirtIODevice *vdev, Error 
> **errp)
>  if (klass->device_plugged != NULL) {
>  klass->device_plugged(qbus->parent, errp);
>  }
> +
> +if (klass->get_dma_as != NULL &&
> +virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM)) {
> +vdev->dma_as = klass->get_dma_as(qbus->parent);
> +} else {
> +vdev->dma_as = _space_memory;
> +}
>  }
>  
>  /* Reset the virtio_bus */
> diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
> index 06831de..6ceb43e 100644
> --- a/hw/virtio/virtio-pci.c
> +++ b/hw/virtio/virtio-pci.c
> @@ -1168,6 +1168,14 @@ static int virtio_pci_query_nvectors(DeviceState *d)
>  return proxy->nvectors;
>  }
>  
> +static AddressSpace *virtio_pci_get_dma_as(DeviceState *d)
> +{
> +VirtIOPCIProxy *proxy = VIRTIO_PCI(d);
> +PCIDevice 

[Qemu-block] [PATCH V2 02/11] virtio: convert to use DMA api

2016-11-03 Thread Jason Wang
Currently, all virtio devices bypass IOMMU completely. This is because
address_space_memory is assumed and used during DMA emulation. This
patch converts the virtio core API to use DMA API. This idea is

- introducing a new transport specific helper to query the dma address
  space. (only pci version is implemented).
- query and use this address space during virtio device guest memory
  accessing when iommu platform (VIRTIO_F_IOMMU_PLATFORM) was enabled
  for this device.

Cc: Michael S. Tsirkin 
Cc: Stefan Hajnoczi 
Cc: Kevin Wolf 
Cc: Amit Shah 
Cc: Paolo Bonzini 
Cc: qemu-block@nongnu.org
Signed-off-by: Jason Wang 
---
 hw/block/virtio-blk.c |  2 +-
 hw/char/virtio-serial-bus.c   |  3 ++-
 hw/scsi/virtio-scsi.c |  4 ++-
 hw/virtio/virtio-bus.c|  8 ++
 hw/virtio/virtio-pci.c| 14 ++
 hw/virtio/virtio.c| 57 +--
 include/hw/virtio/virtio-access.h | 36 ++---
 include/hw/virtio/virtio-bus.h|  1 +
 include/hw/virtio/virtio.h|  9 ---
 9 files changed, 98 insertions(+), 36 deletions(-)

diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index 37fe72b..6a2dbaf 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -860,7 +860,7 @@ static int virtio_blk_load_device(VirtIODevice *vdev, 
QEMUFile *f,
 }
 }
 
-req = qemu_get_virtqueue_element(f, sizeof(VirtIOBlockReq));
+req = qemu_get_virtqueue_element(vdev, f, sizeof(VirtIOBlockReq));
 virtio_blk_init_request(s, virtio_get_queue(vdev, vq_idx), req);
 req->next = s->rq;
 s->rq = req;
diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
index 7975c2c..d544cd9 100644
--- a/hw/char/virtio-serial-bus.c
+++ b/hw/char/virtio-serial-bus.c
@@ -732,6 +732,7 @@ static void virtio_serial_post_load_timer_cb(void *opaque)
 static int fetch_active_ports_list(QEMUFile *f,
VirtIOSerial *s, uint32_t nr_active_ports)
 {
+VirtIODevice *vdev = VIRTIO_DEVICE(s);
 uint32_t i;
 
 s->post_load = g_malloc0(sizeof(*s->post_load));
@@ -765,7 +766,7 @@ static int fetch_active_ports_list(QEMUFile *f,
 qemu_get_be64s(f, >iov_offset);
 
 port->elem =
-qemu_get_virtqueue_element(f, sizeof(VirtQueueElement));
+qemu_get_virtqueue_element(vdev, f, sizeof(VirtQueueElement));
 
 /*
  *  Port was throttled on source machine.  Let's
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 4762f05..1519cee 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -198,12 +198,14 @@ static void *virtio_scsi_load_request(QEMUFile *f, 
SCSIRequest *sreq)
 SCSIBus *bus = sreq->bus;
 VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
 VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
+VirtIODevice *vdev = VIRTIO_DEVICE(s);
 VirtIOSCSIReq *req;
 uint32_t n;
 
 qemu_get_be32s(f, );
 assert(n < vs->conf.num_queues);
-req = qemu_get_virtqueue_element(f, sizeof(VirtIOSCSIReq) + vs->cdb_size);
+req = qemu_get_virtqueue_element(vdev, f,
+ sizeof(VirtIOSCSIReq) + vs->cdb_size);
 virtio_scsi_init_req(s, vs->cmd_vqs[n], req);
 
 if (virtio_scsi_parse_req(req, sizeof(VirtIOSCSICmdReq) + vs->cdb_size,
diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c
index 11f65bd..8597762 100644
--- a/hw/virtio/virtio-bus.c
+++ b/hw/virtio/virtio-bus.c
@@ -28,6 +28,7 @@
 #include "hw/qdev.h"
 #include "hw/virtio/virtio-bus.h"
 #include "hw/virtio/virtio.h"
+#include "exec/address-spaces.h"
 
 /* #define DEBUG_VIRTIO_BUS */
 
@@ -61,6 +62,13 @@ void virtio_bus_device_plugged(VirtIODevice *vdev, Error 
**errp)
 if (klass->device_plugged != NULL) {
 klass->device_plugged(qbus->parent, errp);
 }
+
+if (klass->get_dma_as != NULL &&
+virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM)) {
+vdev->dma_as = klass->get_dma_as(qbus->parent);
+} else {
+vdev->dma_as = _space_memory;
+}
 }
 
 /* Reset the virtio_bus */
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 06831de..6ceb43e 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -1168,6 +1168,14 @@ static int virtio_pci_query_nvectors(DeviceState *d)
 return proxy->nvectors;
 }
 
+static AddressSpace *virtio_pci_get_dma_as(DeviceState *d)
+{
+VirtIOPCIProxy *proxy = VIRTIO_PCI(d);
+PCIDevice *dev = >pci_dev;
+
+return pci_get_address_space(dev);
+}
+
 static int virtio_pci_add_mem_cap(VirtIOPCIProxy *proxy,
struct virtio_pci_cap *cap)
 {
@@ -1624,6 +1632,11 @@ static void virtio_pci_device_plugged(DeviceState *d, 
Error **errp)
 }
 
 if (legacy) {
+