From: Hollis Blanchard <hollisb@us.ibm.com>
To: kvm-ia64@vger.kernel.org
Subject: Re: dynamic virtio page size
Date: Thu, 06 Nov 2008 23:32:45 +0000 [thread overview]
Message-ID: <1226014365.8620.71.camel@localhost.localdomain> (raw)
In-Reply-To: <1226014074.8620.69.camel@localhost.localdomain>
On Thu, 2008-11-06 at 17:27 -0600, Hollis Blanchard wrote:
>
> In the patch I sent, they are named VIRTIO_PFN_SHIFT and
> VRING_PAGE_SIZE. In fact, the first could really be named
> VIRTIO_PCI_PFN_SHIFT or even more specific, which hopefully would
> alleviate the confusion.
>
> Anyways, I've been trying to implement your other idea, which was to
> advertise a "virtio page size" from the host to the guest. Since the
> virtio IO space is only 20 bytes long, and it's full, we need to offer a
> feature bit to notify the guest that the IO space has been expanded.
>
> virtio's PCI IO resource
> ------------------------------------
> | 20 bytes | |
> ------------------------------------
> virtio-pci virtio-<device>
> specific specific
> data data
>
> If guests don't acknowledge the feature, the host pretends the
> VIRTIO_PAGE_SIZE register (which would be the new IO offset 20) doesn't
> exist, and reads to offset 20 instead return the device-specific config
> data.
FWIW, here's my current (broken) patch. Aside from being broken, it also
doesn't seem like this approach will scale well should we need to extend
the IO space again in the future.
diff --git a/qemu/hw/virtio.c b/qemu/hw/virtio.c
--- a/qemu/hw/virtio.c
+++ b/qemu/hw/virtio.c
@@ -45,7 +45,11 @@
* a read-and-acknowledge. */
#define VIRTIO_PCI_ISR 19
-#define VIRTIO_PCI_CONFIG 20
+/* A 32-bit r/o register specifying the size of a "page", in bytes, in the
+ * virtio interface. */
+#define VIRTIO_PCI_PAGESIZE 20
+
+#define VIRTIO_PCI_CONFIG 24
/* Virtio ABI version, if we increment this, we break the guest driver. */
#define VIRTIO_PCI_ABI_VERSION 0
@@ -55,6 +59,12 @@
* KVM or if kqemu gets SMP support.
*/
#define wmb() do { } while (0)
+
+#define VIRTIO_PAGE_SHIFT 12
+#define VIRTIO_PAGE_SIZE (1<<VIRTIO_PAGE_SHIFT)
+#define VIRTIO_PAGE_MASK (~(VIRTIO_PAGE_SIZE - 1))
+#define VIRTIO_PAGE_ALIGN(x) (((x) + VIRTIO_PAGE_SIZE - 1) \
+ & VIRTIO_PAGE_MASK)
/* virt queue functions */
@@ -95,7 +105,7 @@ static void *virtio_map_gpa(target_phys_
static size_t virtqueue_size(int num)
{
- return TARGET_PAGE_ALIGN((sizeof(VRingDesc) * num) +
+ return VIRTIO_PAGE_ALIGN((sizeof(VRingDesc) * num) +
(sizeof(VRingAvail) + sizeof(uint16_t) * num)) +
(sizeof(VRingUsed) + sizeof(VRingUsedElem) * num);
}
@@ -104,7 +114,7 @@ static void virtqueue_init(VirtQueue *vq
{
vq->vring.desc = p;
vq->vring.avail = p + vq->vring.num * sizeof(VRingDesc);
- vq->vring.used = (void *)TARGET_PAGE_ALIGN((unsigned long)&vq->vring.avail->ring[vq->vring.num]);
+ vq->vring.used = (void *)VIRTIO_PAGE_ALIGN((unsigned long)&vq->vring.avail->ring[vq->vring.num]);
}
static unsigned virtqueue_next_desc(VirtQueue *vq, unsigned int i)
@@ -234,6 +244,9 @@ static uint32_t virtio_config_readb(void
vdev->get_config(vdev, vdev->config);
+ if (!(vdev->features & VIRTIO_F_EXPLICIT_PAGE_SIZE))
+ addr += 4;
+
addr -= vdev->addr + VIRTIO_PCI_CONFIG;
if (addr > (vdev->config_len - sizeof(val)))
return (uint32_t)-1;
@@ -248,6 +261,9 @@ static uint32_t virtio_config_readw(void
uint16_t val;
vdev->get_config(vdev, vdev->config);
+
+ if (!(vdev->features & VIRTIO_F_EXPLICIT_PAGE_SIZE))
+ addr += 4;
addr -= vdev->addr + VIRTIO_PCI_CONFIG;
if (addr > (vdev->config_len - sizeof(val)))
@@ -264,6 +280,9 @@ static uint32_t virtio_config_readl(void
vdev->get_config(vdev, vdev->config);
+ if (!(vdev->features & VIRTIO_F_EXPLICIT_PAGE_SIZE))
+ addr += 4;
+
addr -= vdev->addr + VIRTIO_PCI_CONFIG;
if (addr > (vdev->config_len - sizeof(val)))
return (uint32_t)-1;
@@ -276,6 +295,9 @@ static void virtio_config_writeb(void *o
{
VirtIODevice *vdev = opaque;
uint8_t val = data;
+
+ if (!(vdev->features & VIRTIO_F_EXPLICIT_PAGE_SIZE))
+ addr += 4;
addr -= vdev->addr + VIRTIO_PCI_CONFIG;
if (addr > (vdev->config_len - sizeof(val)))
@@ -292,6 +314,9 @@ static void virtio_config_writew(void *o
VirtIODevice *vdev = opaque;
uint16_t val = data;
+ if (!(vdev->features & VIRTIO_F_EXPLICIT_PAGE_SIZE))
+ addr += 4;
+
addr -= vdev->addr + VIRTIO_PCI_CONFIG;
if (addr > (vdev->config_len - sizeof(val)))
return;
@@ -306,6 +331,9 @@ static void virtio_config_writel(void *o
{
VirtIODevice *vdev = opaque;
uint32_t val = data;
+
+ if (!(vdev->features & VIRTIO_F_EXPLICIT_PAGE_SIZE))
+ addr += 4;
addr -= vdev->addr + VIRTIO_PCI_CONFIG;
if (addr > (vdev->config_len - sizeof(val)))
@@ -329,9 +357,10 @@ static void virtio_ioport_write(void *op
if (vdev->set_features)
vdev->set_features(vdev, val);
vdev->features = val;
+ printf("%s: features 0x%x\n", __func__, val);
break;
case VIRTIO_PCI_QUEUE_PFN:
- pa = (ram_addr_t)val << TARGET_PAGE_BITS;
+ pa = (ram_addr_t)val << VIRTIO_PAGE_SHIFT;
vdev->vq[vdev->queue_sel].pfn = val;
if (pa = 0) {
virtio_reset(vdev);
@@ -368,6 +397,7 @@ static uint32_t virtio_ioport_read(void
case VIRTIO_PCI_HOST_FEATURES:
ret = vdev->get_features(vdev);
ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
+ ret |= (1 << VIRTIO_F_EXPLICIT_PAGE_SIZE);
break;
case VIRTIO_PCI_GUEST_FEATURES:
ret = vdev->features;
@@ -390,6 +420,16 @@ static uint32_t virtio_ioport_read(void
vdev->isr = 0;
virtio_update_irq(vdev);
break;
+ case VIRTIO_PCI_PAGESIZE:
+ if (vdev->features & VIRTIO_F_EXPLICIT_PAGE_SIZE) {
+ /* Guest must have acknowledged this feature in order to enable
+ * this IO port. */
+ ret = VIRTIO_PAGE_SIZE;
+ } else {
+ /* If it hasn't, return device config space instead. */
+ ret = virtio_config_readl(vdev, addr);
+ }
+ break;
default:
break;
}
@@ -405,22 +445,24 @@ static void virtio_map(PCIDevice *pci_de
vdev->addr = addr;
for (i = 0; i < 3; i++) {
- register_ioport_write(addr, 20, 1 << i, virtio_ioport_write, vdev);
- register_ioport_read(addr, 20, 1 << i, virtio_ioport_read, vdev);
+ register_ioport_write(addr, VIRTIO_PCI_CONFIG, 1 << i,
+ virtio_ioport_write, vdev);
+ register_ioport_read(addr, VIRTIO_PCI_CONFIG, 1 << i,
+ virtio_ioport_read, vdev);
}
if (vdev->config_len) {
- register_ioport_write(addr + 20, vdev->config_len, 1,
+ register_ioport_write(addr + VIRTIO_PCI_CONFIG, vdev->config_len, 1,
virtio_config_writeb, vdev);
- register_ioport_write(addr + 20, vdev->config_len, 2,
+ register_ioport_write(addr + VIRTIO_PCI_CONFIG, vdev->config_len, 2,
virtio_config_writew, vdev);
- register_ioport_write(addr + 20, vdev->config_len, 4,
+ register_ioport_write(addr + VIRTIO_PCI_CONFIG, vdev->config_len, 4,
virtio_config_writel, vdev);
- register_ioport_read(addr + 20, vdev->config_len, 1,
+ register_ioport_read(addr + VIRTIO_PCI_CONFIG, vdev->config_len, 1,
virtio_config_readb, vdev);
- register_ioport_read(addr + 20, vdev->config_len, 2,
+ register_ioport_read(addr + VIRTIO_PCI_CONFIG, vdev->config_len, 2,
virtio_config_readw, vdev);
- register_ioport_read(addr + 20, vdev->config_len, 4,
+ register_ioport_read(addr + VIRTIO_PCI_CONFIG, vdev->config_len, 4,
virtio_config_readl, vdev);
vdev->get_config(vdev, vdev->config);
@@ -519,7 +561,7 @@ void virtio_load(VirtIODevice *vdev, QEM
size_t size;
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_PAGE_SHIFT;
size = virtqueue_size(vdev->vq[i].vring.num);
virtqueue_init(&vdev->vq[i], virtio_map_gpa(pa, size));
}
diff --git a/qemu/hw/virtio.h b/qemu/hw/virtio.h
--- a/qemu/hw/virtio.h
+++ b/qemu/hw/virtio.h
@@ -33,6 +33,9 @@
/* We notify when the ring is completely used, even if the guest is supressing
* callbacks */
#define VIRTIO_F_NOTIFY_ON_EMPTY 24
+
+/* Device advertises the size of a "page". */
+#define VIRTIO_F_EXPLICIT_PAGE_SIZE 28
/* from Linux's linux/virtio_ring.h */
--
Hollis Blanchard
IBM Linux Technology Center
WARNING: multiple messages have this Message-ID (diff)
From: Hollis Blanchard <hollisb@us.ibm.com>
To: Anthony Liguori <anthony-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
Cc: rusty-8n+1lVoiYb80n/F98K4Iww@public.gmane.org,
kvm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
kvm-ppc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
kvm-ia64-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: Re: dynamic virtio page size
Date: Thu, 06 Nov 2008 23:32:45 +0000 [thread overview]
Message-ID: <1226014365.8620.71.camel@localhost.localdomain> (raw)
In-Reply-To: <1226014074.8620.69.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
On Thu, 2008-11-06 at 17:27 -0600, Hollis Blanchard wrote:
>
> In the patch I sent, they are named VIRTIO_PFN_SHIFT and
> VRING_PAGE_SIZE. In fact, the first could really be named
> VIRTIO_PCI_PFN_SHIFT or even more specific, which hopefully would
> alleviate the confusion.
>
> Anyways, I've been trying to implement your other idea, which was to
> advertise a "virtio page size" from the host to the guest. Since the
> virtio IO space is only 20 bytes long, and it's full, we need to offer a
> feature bit to notify the guest that the IO space has been expanded.
>
> virtio's PCI IO resource
> ------------------------------------
> | 20 bytes | |
> ------------------------------------
> virtio-pci virtio-<device>
> specific specific
> data data
>
> If guests don't acknowledge the feature, the host pretends the
> VIRTIO_PAGE_SIZE register (which would be the new IO offset 20) doesn't
> exist, and reads to offset 20 instead return the device-specific config
> data.
FWIW, here's my current (broken) patch. Aside from being broken, it also
doesn't seem like this approach will scale well should we need to extend
the IO space again in the future.
diff --git a/qemu/hw/virtio.c b/qemu/hw/virtio.c
--- a/qemu/hw/virtio.c
+++ b/qemu/hw/virtio.c
@@ -45,7 +45,11 @@
* a read-and-acknowledge. */
#define VIRTIO_PCI_ISR 19
-#define VIRTIO_PCI_CONFIG 20
+/* A 32-bit r/o register specifying the size of a "page", in bytes, in the
+ * virtio interface. */
+#define VIRTIO_PCI_PAGESIZE 20
+
+#define VIRTIO_PCI_CONFIG 24
/* Virtio ABI version, if we increment this, we break the guest driver. */
#define VIRTIO_PCI_ABI_VERSION 0
@@ -55,6 +59,12 @@
* KVM or if kqemu gets SMP support.
*/
#define wmb() do { } while (0)
+
+#define VIRTIO_PAGE_SHIFT 12
+#define VIRTIO_PAGE_SIZE (1<<VIRTIO_PAGE_SHIFT)
+#define VIRTIO_PAGE_MASK (~(VIRTIO_PAGE_SIZE - 1))
+#define VIRTIO_PAGE_ALIGN(x) (((x) + VIRTIO_PAGE_SIZE - 1) \
+ & VIRTIO_PAGE_MASK)
/* virt queue functions */
@@ -95,7 +105,7 @@ static void *virtio_map_gpa(target_phys_
static size_t virtqueue_size(int num)
{
- return TARGET_PAGE_ALIGN((sizeof(VRingDesc) * num) +
+ return VIRTIO_PAGE_ALIGN((sizeof(VRingDesc) * num) +
(sizeof(VRingAvail) + sizeof(uint16_t) * num)) +
(sizeof(VRingUsed) + sizeof(VRingUsedElem) * num);
}
@@ -104,7 +114,7 @@ static void virtqueue_init(VirtQueue *vq
{
vq->vring.desc = p;
vq->vring.avail = p + vq->vring.num * sizeof(VRingDesc);
- vq->vring.used = (void *)TARGET_PAGE_ALIGN((unsigned long)&vq->vring.avail->ring[vq->vring.num]);
+ vq->vring.used = (void *)VIRTIO_PAGE_ALIGN((unsigned long)&vq->vring.avail->ring[vq->vring.num]);
}
static unsigned virtqueue_next_desc(VirtQueue *vq, unsigned int i)
@@ -234,6 +244,9 @@ static uint32_t virtio_config_readb(void
vdev->get_config(vdev, vdev->config);
+ if (!(vdev->features & VIRTIO_F_EXPLICIT_PAGE_SIZE))
+ addr += 4;
+
addr -= vdev->addr + VIRTIO_PCI_CONFIG;
if (addr > (vdev->config_len - sizeof(val)))
return (uint32_t)-1;
@@ -248,6 +261,9 @@ static uint32_t virtio_config_readw(void
uint16_t val;
vdev->get_config(vdev, vdev->config);
+
+ if (!(vdev->features & VIRTIO_F_EXPLICIT_PAGE_SIZE))
+ addr += 4;
addr -= vdev->addr + VIRTIO_PCI_CONFIG;
if (addr > (vdev->config_len - sizeof(val)))
@@ -264,6 +280,9 @@ static uint32_t virtio_config_readl(void
vdev->get_config(vdev, vdev->config);
+ if (!(vdev->features & VIRTIO_F_EXPLICIT_PAGE_SIZE))
+ addr += 4;
+
addr -= vdev->addr + VIRTIO_PCI_CONFIG;
if (addr > (vdev->config_len - sizeof(val)))
return (uint32_t)-1;
@@ -276,6 +295,9 @@ static void virtio_config_writeb(void *o
{
VirtIODevice *vdev = opaque;
uint8_t val = data;
+
+ if (!(vdev->features & VIRTIO_F_EXPLICIT_PAGE_SIZE))
+ addr += 4;
addr -= vdev->addr + VIRTIO_PCI_CONFIG;
if (addr > (vdev->config_len - sizeof(val)))
@@ -292,6 +314,9 @@ static void virtio_config_writew(void *o
VirtIODevice *vdev = opaque;
uint16_t val = data;
+ if (!(vdev->features & VIRTIO_F_EXPLICIT_PAGE_SIZE))
+ addr += 4;
+
addr -= vdev->addr + VIRTIO_PCI_CONFIG;
if (addr > (vdev->config_len - sizeof(val)))
return;
@@ -306,6 +331,9 @@ static void virtio_config_writel(void *o
{
VirtIODevice *vdev = opaque;
uint32_t val = data;
+
+ if (!(vdev->features & VIRTIO_F_EXPLICIT_PAGE_SIZE))
+ addr += 4;
addr -= vdev->addr + VIRTIO_PCI_CONFIG;
if (addr > (vdev->config_len - sizeof(val)))
@@ -329,9 +357,10 @@ static void virtio_ioport_write(void *op
if (vdev->set_features)
vdev->set_features(vdev, val);
vdev->features = val;
+ printf("%s: features 0x%x\n", __func__, val);
break;
case VIRTIO_PCI_QUEUE_PFN:
- pa = (ram_addr_t)val << TARGET_PAGE_BITS;
+ pa = (ram_addr_t)val << VIRTIO_PAGE_SHIFT;
vdev->vq[vdev->queue_sel].pfn = val;
if (pa = 0) {
virtio_reset(vdev);
@@ -368,6 +397,7 @@ static uint32_t virtio_ioport_read(void
case VIRTIO_PCI_HOST_FEATURES:
ret = vdev->get_features(vdev);
ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
+ ret |= (1 << VIRTIO_F_EXPLICIT_PAGE_SIZE);
break;
case VIRTIO_PCI_GUEST_FEATURES:
ret = vdev->features;
@@ -390,6 +420,16 @@ static uint32_t virtio_ioport_read(void
vdev->isr = 0;
virtio_update_irq(vdev);
break;
+ case VIRTIO_PCI_PAGESIZE:
+ if (vdev->features & VIRTIO_F_EXPLICIT_PAGE_SIZE) {
+ /* Guest must have acknowledged this feature in order to enable
+ * this IO port. */
+ ret = VIRTIO_PAGE_SIZE;
+ } else {
+ /* If it hasn't, return device config space instead. */
+ ret = virtio_config_readl(vdev, addr);
+ }
+ break;
default:
break;
}
@@ -405,22 +445,24 @@ static void virtio_map(PCIDevice *pci_de
vdev->addr = addr;
for (i = 0; i < 3; i++) {
- register_ioport_write(addr, 20, 1 << i, virtio_ioport_write, vdev);
- register_ioport_read(addr, 20, 1 << i, virtio_ioport_read, vdev);
+ register_ioport_write(addr, VIRTIO_PCI_CONFIG, 1 << i,
+ virtio_ioport_write, vdev);
+ register_ioport_read(addr, VIRTIO_PCI_CONFIG, 1 << i,
+ virtio_ioport_read, vdev);
}
if (vdev->config_len) {
- register_ioport_write(addr + 20, vdev->config_len, 1,
+ register_ioport_write(addr + VIRTIO_PCI_CONFIG, vdev->config_len, 1,
virtio_config_writeb, vdev);
- register_ioport_write(addr + 20, vdev->config_len, 2,
+ register_ioport_write(addr + VIRTIO_PCI_CONFIG, vdev->config_len, 2,
virtio_config_writew, vdev);
- register_ioport_write(addr + 20, vdev->config_len, 4,
+ register_ioport_write(addr + VIRTIO_PCI_CONFIG, vdev->config_len, 4,
virtio_config_writel, vdev);
- register_ioport_read(addr + 20, vdev->config_len, 1,
+ register_ioport_read(addr + VIRTIO_PCI_CONFIG, vdev->config_len, 1,
virtio_config_readb, vdev);
- register_ioport_read(addr + 20, vdev->config_len, 2,
+ register_ioport_read(addr + VIRTIO_PCI_CONFIG, vdev->config_len, 2,
virtio_config_readw, vdev);
- register_ioport_read(addr + 20, vdev->config_len, 4,
+ register_ioport_read(addr + VIRTIO_PCI_CONFIG, vdev->config_len, 4,
virtio_config_readl, vdev);
vdev->get_config(vdev, vdev->config);
@@ -519,7 +561,7 @@ void virtio_load(VirtIODevice *vdev, QEM
size_t size;
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_PAGE_SHIFT;
size = virtqueue_size(vdev->vq[i].vring.num);
virtqueue_init(&vdev->vq[i], virtio_map_gpa(pa, size));
}
diff --git a/qemu/hw/virtio.h b/qemu/hw/virtio.h
--- a/qemu/hw/virtio.h
+++ b/qemu/hw/virtio.h
@@ -33,6 +33,9 @@
/* We notify when the ring is completely used, even if the guest is supressing
* callbacks */
#define VIRTIO_F_NOTIFY_ON_EMPTY 24
+
+/* Device advertises the size of a "page". */
+#define VIRTIO_F_EXPLICIT_PAGE_SIZE 28
/* from Linux's linux/virtio_ring.h */
--
Hollis Blanchard
IBM Linux Technology Center
WARNING: multiple messages have this Message-ID (diff)
From: Hollis Blanchard <hollisb-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
To: Anthony Liguori <anthony-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
Cc: rusty-8n+1lVoiYb80n/F98K4Iww@public.gmane.org,
kvm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
kvm-ppc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
kvm-ia64-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: Re: dynamic virtio page size
Date: Thu, 06 Nov 2008 17:32:45 -0600 [thread overview]
Message-ID: <1226014365.8620.71.camel@localhost.localdomain> (raw)
In-Reply-To: <1226014074.8620.69.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
On Thu, 2008-11-06 at 17:27 -0600, Hollis Blanchard wrote:
>
> In the patch I sent, they are named VIRTIO_PFN_SHIFT and
> VRING_PAGE_SIZE. In fact, the first could really be named
> VIRTIO_PCI_PFN_SHIFT or even more specific, which hopefully would
> alleviate the confusion.
>
> Anyways, I've been trying to implement your other idea, which was to
> advertise a "virtio page size" from the host to the guest. Since the
> virtio IO space is only 20 bytes long, and it's full, we need to offer a
> feature bit to notify the guest that the IO space has been expanded.
>
> virtio's PCI IO resource
> ------------------------------------
> | 20 bytes | |
> ------------------------------------
> virtio-pci virtio-<device>
> specific specific
> data data
>
> If guests don't acknowledge the feature, the host pretends the
> VIRTIO_PAGE_SIZE register (which would be the new IO offset 20) doesn't
> exist, and reads to offset 20 instead return the device-specific config
> data.
FWIW, here's my current (broken) patch. Aside from being broken, it also
doesn't seem like this approach will scale well should we need to extend
the IO space again in the future.
diff --git a/qemu/hw/virtio.c b/qemu/hw/virtio.c
--- a/qemu/hw/virtio.c
+++ b/qemu/hw/virtio.c
@@ -45,7 +45,11 @@
* a read-and-acknowledge. */
#define VIRTIO_PCI_ISR 19
-#define VIRTIO_PCI_CONFIG 20
+/* A 32-bit r/o register specifying the size of a "page", in bytes, in the
+ * virtio interface. */
+#define VIRTIO_PCI_PAGESIZE 20
+
+#define VIRTIO_PCI_CONFIG 24
/* Virtio ABI version, if we increment this, we break the guest driver. */
#define VIRTIO_PCI_ABI_VERSION 0
@@ -55,6 +59,12 @@
* KVM or if kqemu gets SMP support.
*/
#define wmb() do { } while (0)
+
+#define VIRTIO_PAGE_SHIFT 12
+#define VIRTIO_PAGE_SIZE (1<<VIRTIO_PAGE_SHIFT)
+#define VIRTIO_PAGE_MASK (~(VIRTIO_PAGE_SIZE - 1))
+#define VIRTIO_PAGE_ALIGN(x) (((x) + VIRTIO_PAGE_SIZE - 1) \
+ & VIRTIO_PAGE_MASK)
/* virt queue functions */
@@ -95,7 +105,7 @@ static void *virtio_map_gpa(target_phys_
static size_t virtqueue_size(int num)
{
- return TARGET_PAGE_ALIGN((sizeof(VRingDesc) * num) +
+ return VIRTIO_PAGE_ALIGN((sizeof(VRingDesc) * num) +
(sizeof(VRingAvail) + sizeof(uint16_t) * num)) +
(sizeof(VRingUsed) + sizeof(VRingUsedElem) * num);
}
@@ -104,7 +114,7 @@ static void virtqueue_init(VirtQueue *vq
{
vq->vring.desc = p;
vq->vring.avail = p + vq->vring.num * sizeof(VRingDesc);
- vq->vring.used = (void *)TARGET_PAGE_ALIGN((unsigned long)&vq->vring.avail->ring[vq->vring.num]);
+ vq->vring.used = (void *)VIRTIO_PAGE_ALIGN((unsigned long)&vq->vring.avail->ring[vq->vring.num]);
}
static unsigned virtqueue_next_desc(VirtQueue *vq, unsigned int i)
@@ -234,6 +244,9 @@ static uint32_t virtio_config_readb(void
vdev->get_config(vdev, vdev->config);
+ if (!(vdev->features & VIRTIO_F_EXPLICIT_PAGE_SIZE))
+ addr += 4;
+
addr -= vdev->addr + VIRTIO_PCI_CONFIG;
if (addr > (vdev->config_len - sizeof(val)))
return (uint32_t)-1;
@@ -248,6 +261,9 @@ static uint32_t virtio_config_readw(void
uint16_t val;
vdev->get_config(vdev, vdev->config);
+
+ if (!(vdev->features & VIRTIO_F_EXPLICIT_PAGE_SIZE))
+ addr += 4;
addr -= vdev->addr + VIRTIO_PCI_CONFIG;
if (addr > (vdev->config_len - sizeof(val)))
@@ -264,6 +280,9 @@ static uint32_t virtio_config_readl(void
vdev->get_config(vdev, vdev->config);
+ if (!(vdev->features & VIRTIO_F_EXPLICIT_PAGE_SIZE))
+ addr += 4;
+
addr -= vdev->addr + VIRTIO_PCI_CONFIG;
if (addr > (vdev->config_len - sizeof(val)))
return (uint32_t)-1;
@@ -276,6 +295,9 @@ static void virtio_config_writeb(void *o
{
VirtIODevice *vdev = opaque;
uint8_t val = data;
+
+ if (!(vdev->features & VIRTIO_F_EXPLICIT_PAGE_SIZE))
+ addr += 4;
addr -= vdev->addr + VIRTIO_PCI_CONFIG;
if (addr > (vdev->config_len - sizeof(val)))
@@ -292,6 +314,9 @@ static void virtio_config_writew(void *o
VirtIODevice *vdev = opaque;
uint16_t val = data;
+ if (!(vdev->features & VIRTIO_F_EXPLICIT_PAGE_SIZE))
+ addr += 4;
+
addr -= vdev->addr + VIRTIO_PCI_CONFIG;
if (addr > (vdev->config_len - sizeof(val)))
return;
@@ -306,6 +331,9 @@ static void virtio_config_writel(void *o
{
VirtIODevice *vdev = opaque;
uint32_t val = data;
+
+ if (!(vdev->features & VIRTIO_F_EXPLICIT_PAGE_SIZE))
+ addr += 4;
addr -= vdev->addr + VIRTIO_PCI_CONFIG;
if (addr > (vdev->config_len - sizeof(val)))
@@ -329,9 +357,10 @@ static void virtio_ioport_write(void *op
if (vdev->set_features)
vdev->set_features(vdev, val);
vdev->features = val;
+ printf("%s: features 0x%x\n", __func__, val);
break;
case VIRTIO_PCI_QUEUE_PFN:
- pa = (ram_addr_t)val << TARGET_PAGE_BITS;
+ pa = (ram_addr_t)val << VIRTIO_PAGE_SHIFT;
vdev->vq[vdev->queue_sel].pfn = val;
if (pa == 0) {
virtio_reset(vdev);
@@ -368,6 +397,7 @@ static uint32_t virtio_ioport_read(void
case VIRTIO_PCI_HOST_FEATURES:
ret = vdev->get_features(vdev);
ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
+ ret |= (1 << VIRTIO_F_EXPLICIT_PAGE_SIZE);
break;
case VIRTIO_PCI_GUEST_FEATURES:
ret = vdev->features;
@@ -390,6 +420,16 @@ static uint32_t virtio_ioport_read(void
vdev->isr = 0;
virtio_update_irq(vdev);
break;
+ case VIRTIO_PCI_PAGESIZE:
+ if (vdev->features & VIRTIO_F_EXPLICIT_PAGE_SIZE) {
+ /* Guest must have acknowledged this feature in order to enable
+ * this IO port. */
+ ret = VIRTIO_PAGE_SIZE;
+ } else {
+ /* If it hasn't, return device config space instead. */
+ ret = virtio_config_readl(vdev, addr);
+ }
+ break;
default:
break;
}
@@ -405,22 +445,24 @@ static void virtio_map(PCIDevice *pci_de
vdev->addr = addr;
for (i = 0; i < 3; i++) {
- register_ioport_write(addr, 20, 1 << i, virtio_ioport_write, vdev);
- register_ioport_read(addr, 20, 1 << i, virtio_ioport_read, vdev);
+ register_ioport_write(addr, VIRTIO_PCI_CONFIG, 1 << i,
+ virtio_ioport_write, vdev);
+ register_ioport_read(addr, VIRTIO_PCI_CONFIG, 1 << i,
+ virtio_ioport_read, vdev);
}
if (vdev->config_len) {
- register_ioport_write(addr + 20, vdev->config_len, 1,
+ register_ioport_write(addr + VIRTIO_PCI_CONFIG, vdev->config_len, 1,
virtio_config_writeb, vdev);
- register_ioport_write(addr + 20, vdev->config_len, 2,
+ register_ioport_write(addr + VIRTIO_PCI_CONFIG, vdev->config_len, 2,
virtio_config_writew, vdev);
- register_ioport_write(addr + 20, vdev->config_len, 4,
+ register_ioport_write(addr + VIRTIO_PCI_CONFIG, vdev->config_len, 4,
virtio_config_writel, vdev);
- register_ioport_read(addr + 20, vdev->config_len, 1,
+ register_ioport_read(addr + VIRTIO_PCI_CONFIG, vdev->config_len, 1,
virtio_config_readb, vdev);
- register_ioport_read(addr + 20, vdev->config_len, 2,
+ register_ioport_read(addr + VIRTIO_PCI_CONFIG, vdev->config_len, 2,
virtio_config_readw, vdev);
- register_ioport_read(addr + 20, vdev->config_len, 4,
+ register_ioport_read(addr + VIRTIO_PCI_CONFIG, vdev->config_len, 4,
virtio_config_readl, vdev);
vdev->get_config(vdev, vdev->config);
@@ -519,7 +561,7 @@ void virtio_load(VirtIODevice *vdev, QEM
size_t size;
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_PAGE_SHIFT;
size = virtqueue_size(vdev->vq[i].vring.num);
virtqueue_init(&vdev->vq[i], virtio_map_gpa(pa, size));
}
diff --git a/qemu/hw/virtio.h b/qemu/hw/virtio.h
--- a/qemu/hw/virtio.h
+++ b/qemu/hw/virtio.h
@@ -33,6 +33,9 @@
/* We notify when the ring is completely used, even if the guest is supressing
* callbacks */
#define VIRTIO_F_NOTIFY_ON_EMPTY 24
+
+/* Device advertises the size of a "page". */
+#define VIRTIO_F_EXPLICIT_PAGE_SIZE 28
/* from Linux's linux/virtio_ring.h */
--
Hollis Blanchard
IBM Linux Technology Center
--
To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
next prev parent reply other threads:[~2008-11-06 23:32 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-11-06 23:27 dynamic virtio page size Hollis Blanchard
2008-11-06 23:27 ` Hollis Blanchard
2008-11-06 23:27 ` Hollis Blanchard
2008-11-06 23:32 ` Hollis Blanchard [this message]
2008-11-06 23:32 ` Hollis Blanchard
2008-11-06 23:32 ` Hollis Blanchard
-- strict thread matches above, loose matches on Subject: below --
2008-11-06 10:54 [PATCH] qemu: define and use VIRTIO_PFN_SHIFT Mark McLoughlin
2008-11-06 10:54 ` Mark McLoughlin
2008-11-06 10:54 ` Mark McLoughlin
2008-11-06 14:01 ` Anthony Liguori
2008-11-06 14:01 ` Anthony Liguori
2008-11-06 14:01 ` Anthony Liguori
2008-11-06 19:02 ` Hollis Blanchard
2008-11-06 19:02 ` Hollis Blanchard
2008-11-06 19:02 ` Hollis Blanchard
2008-11-06 20:02 ` Anthony Liguori
2008-11-06 20:02 ` Anthony Liguori
2008-11-06 20:02 ` Anthony Liguori
2008-11-07 1:38 ` Zhang, Xiantao
2008-11-07 1:38 ` Zhang, Xiantao
2008-11-07 1:38 ` Zhang, Xiantao
2008-11-07 5:05 ` Hollis Blanchard
2008-11-07 5:05 ` Hollis Blanchard
2008-11-07 5:05 ` Hollis Blanchard
2008-11-10 5:55 ` Zhang, Xiantao
2008-11-10 5:55 ` Zhang, Xiantao
2008-11-10 5:55 ` Zhang, Xiantao
2008-11-06 4:49 Hollis Blanchard
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1226014365.8620.71.camel@localhost.localdomain \
--to=hollisb@us.ibm.com \
--cc=kvm-ia64@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.