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: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-11-06 4:49 [PATCH] qemu: define and use VIRTIO_PFN_SHIFT Hollis Blanchard
[not found] ` <43a111ea61b542d3823e.1225946995-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2008-11-06 10:54 ` Mark McLoughlin
2008-11-06 14:01 ` Anthony Liguori
[not found] ` <4912F89D.1090908-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
2008-11-06 19:02 ` Hollis Blanchard
2008-11-06 20:02 ` Anthony Liguori
[not found] ` <49134D42.6080109-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
2008-11-06 23:27 ` dynamic virtio page size Hollis Blanchard
[not found] ` <1226014074.8620.69.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2008-11-06 23:32 ` Hollis Blanchard [this message]
2008-11-07 1:38 ` [PATCH] qemu: define and use VIRTIO_PFN_SHIFT Zhang, Xiantao
2008-11-07 5:05 ` Hollis Blanchard
[not found] ` <200811062305.03494.hollisb-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2008-11-10 5:55 ` Zhang, Xiantao
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-r/jw6+rmf7hqt0dzr+alfa@public.gmane.org \
--cc=anthony-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org \
--cc=kvm-ia64-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=kvm-ppc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=kvm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=rusty-8n+1lVoiYb80n/F98K4Iww@public.gmane.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox