mirror of
https://github.com/Motorhead1991/qemu.git
synced 2026-03-04 09:04:39 -07:00
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. Tsirkin <mst@redhat.com> Cc: Stefan Hajnoczi <stefanha@redhat.com> Cc: Kevin Wolf <kwolf@redhat.com> Cc: Amit Shah <amit.shah@redhat.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: qemu-block@nongnu.org Signed-off-by: Jason Wang <jasowang@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
a08aaff811
commit
8607f5c307
9 changed files with 93 additions and 36 deletions
|
|
@ -17,6 +17,7 @@
|
|||
#define QEMU_VIRTIO_ACCESS_H
|
||||
|
||||
#include "hw/virtio/virtio.h"
|
||||
#include "hw/virtio/virtio-bus.h"
|
||||
#include "exec/address-spaces.h"
|
||||
|
||||
#if defined(TARGET_PPC64) || defined(TARGET_ARM)
|
||||
|
|
@ -40,45 +41,55 @@ static inline bool virtio_access_is_big_endian(VirtIODevice *vdev)
|
|||
|
||||
static inline uint16_t virtio_lduw_phys(VirtIODevice *vdev, hwaddr pa)
|
||||
{
|
||||
AddressSpace *dma_as = vdev->dma_as;
|
||||
|
||||
if (virtio_access_is_big_endian(vdev)) {
|
||||
return lduw_be_phys(&address_space_memory, pa);
|
||||
return lduw_be_phys(dma_as, pa);
|
||||
}
|
||||
return lduw_le_phys(&address_space_memory, pa);
|
||||
return lduw_le_phys(dma_as, pa);
|
||||
}
|
||||
|
||||
static inline uint32_t virtio_ldl_phys(VirtIODevice *vdev, hwaddr pa)
|
||||
{
|
||||
AddressSpace *dma_as = vdev->dma_as;
|
||||
|
||||
if (virtio_access_is_big_endian(vdev)) {
|
||||
return ldl_be_phys(&address_space_memory, pa);
|
||||
return ldl_be_phys(dma_as, pa);
|
||||
}
|
||||
return ldl_le_phys(&address_space_memory, pa);
|
||||
return ldl_le_phys(dma_as, pa);
|
||||
}
|
||||
|
||||
static inline uint64_t virtio_ldq_phys(VirtIODevice *vdev, hwaddr pa)
|
||||
{
|
||||
AddressSpace *dma_as = vdev->dma_as;
|
||||
|
||||
if (virtio_access_is_big_endian(vdev)) {
|
||||
return ldq_be_phys(&address_space_memory, pa);
|
||||
return ldq_be_phys(dma_as, pa);
|
||||
}
|
||||
return ldq_le_phys(&address_space_memory, pa);
|
||||
return ldq_le_phys(dma_as, pa);
|
||||
}
|
||||
|
||||
static inline void virtio_stw_phys(VirtIODevice *vdev, hwaddr pa,
|
||||
uint16_t value)
|
||||
{
|
||||
AddressSpace *dma_as = vdev->dma_as;
|
||||
|
||||
if (virtio_access_is_big_endian(vdev)) {
|
||||
stw_be_phys(&address_space_memory, pa, value);
|
||||
stw_be_phys(dma_as, pa, value);
|
||||
} else {
|
||||
stw_le_phys(&address_space_memory, pa, value);
|
||||
stw_le_phys(dma_as, pa, value);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void virtio_stl_phys(VirtIODevice *vdev, hwaddr pa,
|
||||
uint32_t value)
|
||||
{
|
||||
AddressSpace *dma_as = vdev->dma_as;
|
||||
|
||||
if (virtio_access_is_big_endian(vdev)) {
|
||||
stl_be_phys(&address_space_memory, pa, value);
|
||||
stl_be_phys(dma_as, pa, value);
|
||||
} else {
|
||||
stl_le_phys(&address_space_memory, pa, value);
|
||||
stl_le_phys(dma_as, pa, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ typedef struct VirtioBusClass {
|
|||
* Note that changing this will break migration for this transport.
|
||||
*/
|
||||
bool has_variable_vring_alignment;
|
||||
AddressSpace *(*get_dma_as)(DeviceState *d);
|
||||
} VirtioBusClass;
|
||||
|
||||
struct VirtioBusState {
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ struct VirtIODevice
|
|||
char *bus_name;
|
||||
uint8_t device_endian;
|
||||
bool use_guest_notifier_mask;
|
||||
AddressSpace *dma_as;
|
||||
QLIST_HEAD(, VirtQueue) *vector_queues;
|
||||
};
|
||||
|
||||
|
|
@ -170,9 +171,9 @@ bool virtqueue_rewind(VirtQueue *vq, unsigned int num);
|
|||
void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
|
||||
unsigned int len, unsigned int idx);
|
||||
|
||||
void virtqueue_map(VirtQueueElement *elem);
|
||||
void virtqueue_map(VirtIODevice *vdev, VirtQueueElement *elem);
|
||||
void *virtqueue_pop(VirtQueue *vq, size_t sz);
|
||||
void *qemu_get_virtqueue_element(QEMUFile *f, size_t sz);
|
||||
void *qemu_get_virtqueue_element(VirtIODevice *vdev, QEMUFile *f, size_t sz);
|
||||
void qemu_put_virtqueue_element(QEMUFile *f, VirtQueueElement *elem);
|
||||
int virtqueue_avail_bytes(VirtQueue *vq, unsigned int in_bytes,
|
||||
unsigned int out_bytes);
|
||||
|
|
@ -255,7 +256,9 @@ typedef struct VirtIORNGConf VirtIORNGConf;
|
|||
DEFINE_PROP_BIT64("notify_on_empty", _state, _field, \
|
||||
VIRTIO_F_NOTIFY_ON_EMPTY, true), \
|
||||
DEFINE_PROP_BIT64("any_layout", _state, _field, \
|
||||
VIRTIO_F_ANY_LAYOUT, true)
|
||||
VIRTIO_F_ANY_LAYOUT, true), \
|
||||
DEFINE_PROP_BIT64("iommu_platform", _state, _field, \
|
||||
VIRTIO_F_IOMMU_PLATFORM, false)
|
||||
|
||||
hwaddr virtio_queue_get_desc_addr(VirtIODevice *vdev, int n);
|
||||
hwaddr virtio_queue_get_avail_addr(VirtIODevice *vdev, int n);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue