Re: [Qemu-block] [PATCH V2 02/11] virtio: convert to use DMA api
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
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
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. TsirkinCc: 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) { +