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

Reply via email to