Anthony Liguori wrote:
> For merging virtio, I thought I'd try a different approach from the
> fix out of tree and merge all at once approach I took with live migration.
>
> What I would like to do is make some minimal changes to virtio in
> kvm-userspace
> so that some form of virtio could be merged in upstream QEMU. We'll have to
> maintain a small diff in the kvm-userspace tree until we work out some of the
> issues, but I'd rather work out those issues in the QEMU tree instead of
> fixing
> them all outside of the tree first.
>
> The attached patch uses USE_KVM guards to separate KVM specific code. This is
> not KVM code, per say, but rather routines that aren't mergable right now. I
> think using the guards make it more clear and easier to deal with merges.
>
> When we submit virtio to qemu-devel and eventually commit, we'll strip out any
> ifdef USE_KVM block.
>
> The only real significant change in this patch is the use of accessors for
> the virtio queues. We've discussed patches like this before.
>
> The point of this patch is to make no functional change in the KVM tree. I've
> confirmed that performance does not regress in virtio-net and that both
> virtio-blk and virtio-net seem to be functional.
>
> Signed-off-by: Anthony Liguori <[EMAIL PROTECTED]>
>
> diff --git a/qemu/hw/virtio-blk.c b/qemu/hw/virtio-blk.c
> index 727119b..fb703eb 100644
> --- a/qemu/hw/virtio-blk.c
> +++ b/qemu/hw/virtio-blk.c
> @@ -276,7 +276,9 @@ void *virtio_blk_init(PCIBus *bus, uint16_t vendor,
> uint16_t device,
> BlockDriverState *bs)
> {
> VirtIOBlock *s;
> +#ifdef USE_KVM
> int cylinders, heads, secs;
> +#endif
> static int virtio_blk_id;
>
> s = (VirtIOBlock *)virtio_init_pci(bus, "virtio-blk", vendor, device,
> @@ -290,9 +292,12 @@ void *virtio_blk_init(PCIBus *bus, uint16_t vendor,
> uint16_t device,
> s->vdev.get_features = virtio_blk_get_features;
> s->vdev.reset = virtio_blk_reset;
> s->bs = bs;
> +#ifdef USE_KVM
> bs->devfn = s->vdev.pci_dev.devfn;
> + /* FIXME this can definitely go in upstream QEMU */
> bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
> bdrv_set_geometry_hint(s->bs, cylinders, heads, secs);
> +#endif
>
Why not merge these bits prior to merging virtio? They aren't kvm
specific and would be good in mainline qemu.
>
> static int virtio_net_can_receive(void *opaque)
> {
> VirtIONet *n = opaque;
>
> - if (n->rx_vq->vring.avail == NULL ||
> + if (!virtio_queue_ready(n->rx_vq) ||
> !(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))
> return 0;
>
> - if (n->rx_vq->vring.avail->idx == n->rx_vq->last_avail_idx) {
> - n->rx_vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
> + if (virtio_queue_empty(n->rx_vq)) {
> + virtio_queue_set_notification(n->rx_vq, 1);
> return 0;
> }
>
> - n->rx_vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
> + virtio_queue_set_notification(n->rx_vq, 0);
> return 1;
> }
>
This should be in a separate patch.
>
> +#ifdef USE_KVM
> /* dhclient uses AF_PACKET but doesn't pass auxdata to the kernel so
> * it never finds out that the packets don't have valid checksums. This
> * causes dhclient to get upset. Fedora's carried a patch for ages to
> @@ -181,6 +190,7 @@ static void work_around_broken_dhclient(struct
> virtio_net_hdr *hdr,
> hdr->flags &= ~VIRTIO_NET_HDR_F_NEEDS_CSUM;
> }
> }
> +#endif
>
Is this kvm specific?
>
> static void virtio_net_receive(void *opaque, const uint8_t *buf, int size)
> {
> @@ -190,6 +200,11 @@ static void virtio_net_receive(void *opaque, const
> uint8_t *buf, int size)
> int offset, i;
> int total;
>
> +#ifndef USE_KVM
> + if (!virtio_queue_ready(n->rx_vq))
> + return;
> +#endif
> +
>
Or this?
>
> +#ifdef USE_KVM
> if (tap_has_vnet_hdr(n->vc->vlan->first_client)) {
> memcpy(hdr, buf, sizeof(*hdr));
> offset += total;
> work_around_broken_dhclient(hdr, buf + offset, size - offset);
> }
> +#endif
>
Or this?
>
> /* copy in packet. ugh */
> i = 1;
> @@ -230,7 +247,11 @@ static void virtio_net_receive(void *opaque, const
> uint8_t *buf, int size)
> static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq)
> {
> VirtQueueElement elem;
> +#ifdef USE_KVM
> int has_vnet_hdr = tap_has_vnet_hdr(n->vc->vlan->first_client);
> +#else
> + int has_vnet_hdr = 0;
> +#endif
>
Or this?
>
> if (!(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))
> return;
> @@ -252,7 +273,32 @@ static void virtio_net_flush_tx(VirtIONet *n, VirtQueue
> *vq)
> len += sizeof(struct virtio_net_hdr);
> }
>
> +#ifdef USE_KVM
> len += qemu_sendv_packet(n->vc, out_sg, out_num);
> +#else
> + {
> + size_t size = 0;
> + size_t offset = 0;
> + int i;
> + void *packet;
> +
> + for (i = 0; i < out_num; i++)
> + size += out_sg[i].iov_len;
> +
> + packet = qemu_malloc(size);
> + if (packet) {
> + for (i = 0; i < out_num; i++) {
> + memcpy(packet + offset,
> + out_sg[i].iov_base,
> + out_sg[i].iov_len);
> + offset += out_sg[i].iov_len;
> + }
> + qemu_send_packet(n->vc, packet, size);
> + len += size;
> + }
> + qemu_free(packet);
> + }
> +#endif
>
Why not merge qemu_sendv_packet? Perhaps with the alternate code as the
body if some infrastructure in qemu is missing?
>
> virtqueue_push(vq, &elem, len);
> virtio_notify(&n->vdev, vq);
> @@ -264,7 +310,7 @@ static void virtio_net_handle_tx(VirtIODevice *vdev,
> VirtQueue *vq)
> VirtIONet *n = to_virtio_net(vdev);
>
> if (n->tx_timer_active) {
> - vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
> + virtio_queue_set_notification(vq, 1);
>
Separate patch.
> +#ifdef USE_KVM
> + VRingDesc *desc;
> + VRingAvail *avail;
> + VRingUsed *used;
> +#else
> + target_phys_addr_t desc;
> + target_phys_addr_t avail;
> + target_phys_addr_t used;
> +#endif
> +} VRing;
>
Stumped. Why?
--
Do not meddle in the internals of kernels, for they are subtle and quick to
panic.
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html