summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/virtio.c16
-rw-r--r--hw/virtio.h6
2 files changed, 19 insertions, 3 deletions
diff --git a/hw/virtio.c b/hw/virtio.c
index 93965800df..4135a97fdc 100644
--- a/hw/virtio.c
+++ b/hw/virtio.c
@@ -52,6 +52,14 @@
/* Virtio ABI version, if we increment this, we break the guest driver. */
#define VIRTIO_PCI_ABI_VERSION 0
+/* How many bits to shift physical queue address written to QUEUE_PFN.
+ * 12 is historical, and due to x86 page size. */
+#define VIRTIO_PCI_QUEUE_ADDR_SHIFT 12
+
+/* The alignment to use between consumer and producer parts of vring.
+ * x86 pagesize again. */
+#define VIRTIO_PCI_VRING_ALIGN 4096
+
/* QEMU doesn't strictly need write barriers since everything runs in
* lock-step. We'll leave the calls to wmb() in though to make it obvious for
* KVM or if kqemu gets SMP support.
@@ -147,7 +155,9 @@ static void virtqueue_init(VirtQueue *vq, target_phys_addr_t pa)
{
vq->vring.desc = pa;
vq->vring.avail = pa + vq->vring.num * sizeof(VRingDesc);
- vq->vring.used = TARGET_PAGE_ALIGN(vq->vring.avail + offsetof(VRingAvail, ring[vq->vring.num]));
+ vq->vring.used = vring_align(vq->vring.avail +
+ offsetof(VRingAvail, ring[vq->vring.num]),
+ VIRTIO_PCI_VRING_ALIGN);
}
static inline uint64_t vring_desc_addr(VirtQueue *vq, int i)
@@ -501,7 +511,7 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
vdev->features = val;
break;
case VIRTIO_PCI_QUEUE_PFN:
- pa = (ram_addr_t)val << TARGET_PAGE_BITS;
+ pa = (ram_addr_t)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT;
vdev->vq[vdev->queue_sel].pfn = val;
if (pa == 0) {
virtio_reset(vdev);
@@ -776,7 +786,7 @@ void virtio_load(VirtIODevice *vdev, QEMUFile *f)
if (vdev->vq[i].pfn) {
target_phys_addr_t pa;
- pa = (ram_addr_t)vdev->vq[i].pfn << TARGET_PAGE_BITS;
+ pa = (ram_addr_t)vdev->vq[i].pfn << VIRTIO_PCI_QUEUE_ADDR_SHIFT;
virtqueue_init(&vdev->vq[i], pa);
}
}
diff --git a/hw/virtio.h b/hw/virtio.h
index f04e75f887..8c9cbaf63e 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -48,6 +48,12 @@
struct VirtQueue;
+static inline target_phys_addr_t vring_align(target_phys_addr_t addr,
+ unsigned long align)
+{
+ return (addr + align - 1) & ~(align - 1);
+}
+
typedef struct VirtQueue VirtQueue;
typedef struct VirtIODevice VirtIODevice;