qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] Qemu-devel Digest, Vol 148, Issue 574


From: Ouyang, Changchun
Subject: Re: [Qemu-devel] Qemu-devel Digest, Vol 148, Issue 574
Date: Tue, 14 Jul 2015 08:00:56 +0000


> -----Original Message-----
> From: address@hidden
> [mailto:address@hidden
> On Behalf Of address@hidden
> Sent: Monday, July 13, 2015 11:28 PM
> To: address@hidden
> Subject: Qemu-devel Digest, Vol 148, Issue 574
> 
> Send Qemu-devel mailing list submissions to
>       address@hidden
> 
> To subscribe or unsubscribe via the World Wide Web, visit
>       https://lists.nongnu.org/mailman/listinfo/qemu-devel
> or, via email, send a message with subject or body 'help' to
>       address@hidden
> 
> You can reach the person managing the list at
>       address@hidden
> 
> When replying, please edit your Subject line so it is more specific than "Re:
> Contents of Qemu-devel digest..."
> 
> 
> Today's Topics:
> 
>    1. Re: [PATCH v4 1/5] cpu: Provide vcpu throttling interface
>       (Paolo Bonzini)
>    2. Re: [PATCH] net: vhost-user reconnect (Michael S. Tsirkin)
>    3. [RFC PATCH qemu v2 0/5] vfio: SPAPR IOMMU v2 (memory
>       preregistration support) (Alexey Kardashevskiy)
> 
> 
> ----------------------------------------------------------------------
> 
> Message: 1
> Date: Mon, 13 Jul 2015 17:14:32 +0200
> From: Paolo Bonzini <address@hidden>
> To: address@hidden, address@hidden,
>       address@hidden, address@hidden,
> address@hidden,
>       address@hidden, address@hidden
> Subject: Re: [Qemu-devel] [PATCH v4 1/5] cpu: Provide vcpu throttling
>       interface
> Message-ID: <address@hidden>
> Content-Type: text/plain; charset=windows-1252
> 
> 
> 
> On 13/07/2015 16:43, Jason J. Herne wrote:
> >>>
> >>> +    CPU_FOREACH(cpu) {
> >>> +        async_run_on_cpu(cpu, cpu_throttle_thread, NULL);
> >>> +    }
> >>> +
> >>> +    timer_mod(throttle_timer,
> >>> qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL_RT) +
> >>> +                                   CPU_THROTTLE_TIMESLICE); }
> >>
> >> This could cause callbacks to pile up I think.  David, do you have
> >> any idea how to fix it?
> >
> > I'm not sure how callbacks can pile up here. If the vcpus are running
> > then their thread's will execute the callbacks. If they are not
> > running then the use of QEMU_CLOCK_VIRTUAL_RT will prevent the
> > callbacks from stacking because the timer is not running, right?
> 
> Couldn't the iothread starve the VCPUs?  They need to take the iothread lock
> in order to process the callbacks.
> 
> Paolo
> 
> 
> 
> ------------------------------
> 
> Message: 2
> Date: Mon, 13 Jul 2015 18:18:51 +0300
> From: "Michael S. Tsirkin" <address@hidden>
> To: "Matus Fabian -X (matfabia - Pantheon Technologies SRO at Cisco)"
>       <address@hidden>
> Cc: "address@hidden" <address@hidden>,
>       "address@hidden"
>       <address@hidden>,       "address@hidden"
>       <address@hidden>,       "address@hidden"
> <address@hidden>,
>       "Damjan Marion \(damarion\)" <address@hidden>
> Subject: Re: [Qemu-devel] [PATCH] net: vhost-user reconnect
> Message-ID: <address@hidden>
> Content-Type: text/plain; charset=us-ascii
> 
> On Mon, Jul 13, 2015 at 02:44:37PM +0000, Matus Fabian -X (matfabia -
> Pantheon Technologies SRO at Cisco) wrote:
> > If userspace switch restarts it will reconnect to unix socket but QEMU
> > will not send any vhost-user information and that basically means that
> > userspace switch restart requires restart of VM.
> > Fix detects that userspace switch is disconnected and notify VM that
> > link status is down. After user space switch is reconnected QEMU send
> > vhost-user information to the userspace switch and notify VM that link is
> up.
> >
> > Signed-off-by: Matus Fabian <address@hidden>
> 
> This only works most of the time.  Reconnect can't be implemented without
> guest changes.
> See http://mid.gmane.org/1434945048-27958-1-git-send-email-
> address@hidden
> 

What's the status for these 2 patch sets?
Will they be applied into 2.4? or 2.5?

Just need choose one from both to apply? or need apply both to provide a good 
enough functionality of reconnection?

Thanks
Changchun


> 
> > ---
> >  hw/net/vhost_net.c         | 126
> +++++++++++++++++++++++++++++++++++++++++
> >  hw/net/virtio-net.c        |  62 ++++++++++++--------
> >  hw/virtio/vhost.c          | 137
> +++++++++++++++++++++++++++++++++++++++++++++
> >  hw/virtio/virtio.c         |  24 ++++++++
> >  include/hw/virtio/vhost.h  |   8 +++
> >  include/hw/virtio/virtio.h |   1 +
> >  include/net/vhost_net.h    |   7 +++
> >  include/sysemu/char.h      |   3 +
> >  net/vhost-user.c           |  24 ++++++++
> >  qemu-char.c                | 101 +++++++++++++++++++++++++++++++++
> >  10 files changed, 470 insertions(+), 23 deletions(-)
> >
> > diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index
> > 9bd360b..16a31d7 100644
> > --- a/hw/net/vhost_net.c
> > +++ b/hw/net/vhost_net.c
> > @@ -167,6 +167,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions
> *options)
> >      if (r < 0) {
> >          goto fail;
> >      }
> > +    net->dev.features |= 1 << VIRTIO_NET_F_STATUS;
> >      if (backend_kernel) {
> >          if (!qemu_has_vnet_hdr_len(options->net_backend,
> >                                 sizeof(struct
> > virtio_net_hdr_mrg_rxbuf))) { @@ -380,6 +381,23 @@ void
> vhost_net_cleanup(struct vhost_net *net)
> >      g_free(net);
> >  }
> >
> > +void vhost_net_reconnect_init(VHostNetState *net) {
> > +    int r;
> > +
> > +    r = vhost_dev_reconnect_init(&net->dev);
> > +    if (r < 0) {
> > +        fprintf(stderr, "vhost reconnect init failed: %d\n", r);
> > +        fflush(stderr);
> > +    }
> > +    net->dev.features |= 1 << VIRTIO_NET_F_STATUS; }
> > +
> > +void vhost_net_hup(VHostNetState *net) {
> > +    vhost_dev_hup(&net->dev);
> > +}
> > +
> >  bool vhost_net_virtqueue_pending(VHostNetState *net, int idx)  {
> >      return vhost_virtqueue_pending(&net->dev, idx); @@ -412,6 +430,89
> > @@ VHostNetState *get_vhost_net(NetClientState *nc)
> >
> >      return vhost_net;
> >  }
> > +
> > +bool vhost_net_in_reconnect(NetClientState *nc) {
> > +    VHostNetState *vhost_net = 0;
> > +
> > +    if (!nc) {
> > +        return false;
> > +    }
> > +    switch (nc->info->type) {
> > +    case NET_CLIENT_OPTIONS_KIND_TAP:
> > +        vhost_net = tap_get_vhost_net(nc);
> > +        break;
> > +    case NET_CLIENT_OPTIONS_KIND_VHOST_USER:
> > +        vhost_net = vhost_user_get_vhost_net(nc);
> > +        break;
> > +    default:
> > +        break;
> > +    }
> > +
> > +    if (!vhost_net) {
> > +        return false;
> > +    }
> > +
> > +    return vhost_dev_in_reconnect(&vhost_net->dev);
> > +}
> > +
> > +bool vhost_net_is_hup(NetClientState *nc) {
> > +    VHostNetState *vhost_net = 0;
> > +
> > +    if (!nc) {
> > +        return false;
> > +    }
> > +    switch (nc->info->type) {
> > +    case NET_CLIENT_OPTIONS_KIND_TAP:
> > +        vhost_net = tap_get_vhost_net(nc);
> > +        break;
> > +    case NET_CLIENT_OPTIONS_KIND_VHOST_USER:
> > +        vhost_net = vhost_user_get_vhost_net(nc);
> > +        break;
> > +    default:
> > +        break;
> > +    }
> > +
> > +    if (!vhost_net) {
> > +        return false;
> > +    }
> > +
> > +    return vhost_dev_is_hup(&vhost_net->dev);
> > +}
> > +
> > +int vhost_net_reconnect(VirtIODevice *dev, NetClientState *ncs,
> > +                        int total_queues) {
> > +    int r, i;
> > +
> > +    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev)));
> > +    VirtioBusState *vbus = VIRTIO_BUS(qbus);
> > +    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
> > +
> > +    if (!k->set_guest_notifiers) {
> > +        error_report("binding does not support guest notifiers");
> > +        r = -ENOSYS;
> > +        return r;
> > +    }
> > +
> > +    r = k->set_guest_notifiers(qbus->parent, total_queues * 2, true);
> > +    if (r < 0) {
> > +        error_report("Error binding guest notifier: %d", -r);
> > +        return r;
> > +    }
> > +
> > +    for (i = 0; i < total_queues; i++) {
> > +        VHostNetState *net = get_vhost_net(ncs[i].peer);
> > +        r = vhost_dev_reconnect(&net->dev, dev);
> > +        vhost_dev_reconnect_done(&net->dev);
> > +        if (r < 0) {
> > +            return r;
> > +        }
> > +    }
> > +    return 0;
> > +}
> > +
> >  #else
> >  struct vhost_net *vhost_net_init(VhostNetOptions *options)  { @@
> > -457,4 +558,29 @@ VHostNetState *get_vhost_net(NetClientState *nc)  {
> >      return 0;
> >  }
> > +
> > +void vhost_net_reconnect_init(VHostNetState *net) { }
> > +
> > +bool vhost_net_in_reconnect(NetClientState *nc) {
> > +    return false;
> > +}
> > +
> > +int vhost_net_reconnect(VirtIODevice *dev, NetClientState *ncs,
> > +                        int total_queues) {
> > +    return -ENOSYS;
> > +}
> > +
> > +void vhost_net_hup(VHostNetState *net) { }
> > +
> > +bool vhost_net_is_hup(NetClientState *nc) {
> > +    return false;
> > +}
> > +
> >  #endif
> > diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index
> > d728233..490a187 100644
> > --- a/hw/net/virtio-net.c
> > +++ b/hw/net/virtio-net.c
> > @@ -121,6 +121,11 @@ static void virtio_net_vhost_status(VirtIONet *n,
> uint8_t status)
> >          return;
> >      }
> >
> > +    if (vhost_net_in_reconnect(nc->peer)) {
> > +        vhost_net_reconnect(vdev, n->nic->ncs, queues);
> > +        return;
> > +    }
> > +
> >      if ((virtio_net_started(n, status) && !nc->peer->link_down) ==
> >          !!n->vhost_started) {
> >          return;
> > @@ -156,36 +161,44 @@ static void virtio_net_set_status(struct
> > VirtIODevice *vdev, uint8_t status)  {
> >      VirtIONet *n = VIRTIO_NET(vdev);
> >      VirtIONetQueue *q;
> > +    NetClientState *nc = qemu_get_queue(n->nic);
> >      int i;
> >      uint8_t queue_status;
> >
> > -    virtio_net_vhost_status(n, status);
> > -
> > -    for (i = 0; i < n->max_queues; i++) {
> > -        q = &n->vqs[i];
> > +    if (vhost_net_is_hup(nc->peer) && !(status & VIRTIO_NET_S_LINK_UP))
> {
> > +        return;
> > +    }
> >
> > -        if ((!n->multiqueue && i != 0) || i >= n->curr_queues) {
> > -            queue_status = 0;
> > -        } else {
> > -            queue_status = status;
> > -        }
> > +    virtio_net_vhost_status(n, status);
> >
> > -        if (!q->tx_waiting) {
> > -            continue;
> > -        }
> > +    if (!vhost_net_in_reconnect(nc->peer)) {
> > +        for (i = 0; i < n->max_queues; i++) {
> > +            q = &n->vqs[i];
> >
> > -        if (virtio_net_started(n, queue_status) && !n->vhost_started) {
> > -            if (q->tx_timer) {
> > -                timer_mod(q->tx_timer,
> > -                               qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + n-
> >tx_timeout);
> > +            if ((!n->multiqueue && i != 0) || i >= n->curr_queues) {
> > +                queue_status = 0;
> >              } else {
> > -                qemu_bh_schedule(q->tx_bh);
> > +                queue_status = status;
> >              }
> > -        } else {
> > -            if (q->tx_timer) {
> > -                timer_del(q->tx_timer);
> > +
> > +            if (!q->tx_waiting) {
> > +                continue;
> > +            }
> > +
> > +            if (virtio_net_started(n, queue_status) && !n->vhost_started) {
> > +                if (q->tx_timer) {
> > +                    timer_mod(q->tx_timer,
> > +                              qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
> > +                                                n->tx_timeout);
> > +                } else {
> > +                    qemu_bh_schedule(q->tx_bh);
> > +                }
> >              } else {
> > -                qemu_bh_cancel(q->tx_bh);
> > +                if (q->tx_timer) {
> > +                    timer_del(q->tx_timer);
> > +                } else {
> > +                    qemu_bh_cancel(q->tx_bh);
> > +                }
> >              }
> >          }
> >      }
> > @@ -197,10 +210,13 @@ static void
> virtio_net_set_link_status(NetClientState *nc)
> >      VirtIODevice *vdev = VIRTIO_DEVICE(n);
> >      uint16_t old_status = n->status;
> >
> > -    if (nc->link_down)
> > +    if (nc->link_down) {
> >          n->status &= ~VIRTIO_NET_S_LINK_UP;
> > -    else
> > +        vdev->status &= ~VIRTIO_NET_S_LINK_UP;
> > +    } else {
> >          n->status |= VIRTIO_NET_S_LINK_UP;
> > +        vdev->status |= VIRTIO_NET_S_LINK_UP;
> > +    }
> >
> >      if (n->status != old_status)
> >          virtio_notify_config(vdev);
> > diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index
> > 2712c6f..5edaa9a 100644
> > --- a/hw/virtio/vhost.c
> > +++ b/hw/virtio/vhost.c
> > @@ -817,6 +817,51 @@ fail_alloc_desc:
> >      return r;
> >  }
> >
> > +static int vhost_virtqueue_resend(struct vhost_dev *dev,
> > +                                  struct VirtIODevice *vdev,
> > +                                  struct vhost_virtqueue *vq,
> > +                                  unsigned idx) {
> > +    int r;
> > +    int vhost_vq_index = idx - dev->vq_index;
> > +    struct vhost_vring_file file = {
> > +        .index = vhost_vq_index
> > +    };
> > +    struct vhost_vring_state state = {
> > +        .index = vhost_vq_index
> > +    };
> > +    struct VirtQueue *vvq = virtio_get_queue(vdev, idx);
> > +
> > +    assert(idx >= dev->vq_index && idx < dev->vq_index + dev->nvqs);
> > +
> > +    vq->num = state.num = virtio_queue_get_num(vdev, idx);
> > +    r = dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_NUM,
> &state);
> > +    if (r) {
> > +        return -errno;
> > +    }
> > +
> > +    state.num = virtio_queue_reset_and_get_last_avail_idx(vdev, idx);
> > +    r = dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_BASE,
> &state);
> > +    if (r) {
> > +        return -errno;
> > +    }
> > +    r = vhost_virtqueue_set_addr(dev, vq, vhost_vq_index, dev-
> >log_enabled);
> > +    if (r < 0) {
> > +        return -errno;
> > +    }
> > +
> > +    file.fd = event_notifier_get_fd(virtio_queue_get_host_notifier(vvq));
> > +    r = dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_KICK, &file);
> > +    if (r) {
> > +        return -errno;
> > +    }
> > +
> > +    /* Clear and discard previous events if any. */
> > +    event_notifier_test_and_clear(&vq->masked_notifier);
> > +
> > +    return 0;
> > +}
> > +
> >  static void vhost_virtqueue_stop(struct vhost_dev *dev,
> >                                      struct VirtIODevice *vdev,
> >                                      struct vhost_virtqueue *vq, @@
> > -872,6 +917,17 @@ static void vhost_eventfd_del(MemoryListener
> > *listener,  {  }
> >
> > +static int vhost_virtqueue_recon(struct vhost_dev *dev,
> > +                                 struct vhost_virtqueue *vq, int n) {
> > +    struct vhost_vring_file file = {
> > +        .index = n,
> > +    };
> > +
> > +    file.fd = event_notifier_get_fd(&vq->masked_notifier);
> > +    return dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_CALL,
> > +&file); }
> > +
> >  static int vhost_virtqueue_init(struct vhost_dev *dev,
> >                                  struct vhost_virtqueue *vq, int n)  {
> > @@ -962,6 +1018,8 @@ int vhost_dev_init(struct vhost_dev *hdev, void
> *opaque,
> >      hdev->log_size = 0;
> >      hdev->log_enabled = false;
> >      hdev->started = false;
> > +    hdev->in_reconnect = false;
> > +    hdev->hup = false;
> >      hdev->memory_changed = false;
> >      memory_listener_register(&hdev->memory_listener,
> &address_space_memory);
> >      return 0;
> > @@ -1184,3 +1242,82 @@ void vhost_dev_stop(struct vhost_dev *hdev,
> VirtIODevice *vdev)
> >      hdev->log_size = 0;
> >  }
> >
> > +int vhost_dev_reconnect_init(struct vhost_dev *hdev) {
> > +    uint64_t features;
> > +    int i, r;
> > +
> > +    r = hdev->vhost_ops->vhost_call(hdev, VHOST_SET_OWNER, NULL);
> > +    if (r < 0) {
> > +        return r;
> > +    }
> > +    r = hdev->vhost_ops->vhost_call(hdev, VHOST_GET_FEATURES,
> &features);
> > +    if (r < 0) {
> > +        return r;
> > +    }
> > +    hdev->features = features;
> > +    hdev->in_reconnect = true;
> > +
> > +    for (i = 0; i < hdev->nvqs; ++i) {
> > +        r = vhost_virtqueue_recon(hdev, hdev->vqs + i, i);
> > +        if (r < 0) {
> > +            return r;
> > +        }
> > +    }
> > +
> > +    return r;
> > +}
> > +
> > +void vhost_dev_hup(struct vhost_dev *hdev) {
> > +    hdev->hup = true;
> > +}
> > +
> > +bool vhost_dev_in_reconnect(struct vhost_dev *hdev) {
> > +    return hdev->in_reconnect;
> > +}
> > +
> > +bool vhost_dev_is_hup(struct vhost_dev *hdev) {
> > +    return hdev->hup;
> > +}
> > +
> > +void vhost_dev_reconnect_done(struct vhost_dev *hdev) {
> > +    hdev->in_reconnect = false;
> > +    hdev->hup = false;
> > +}
> > +
> > +int vhost_dev_reconnect(struct vhost_dev *hdev, VirtIODevice *vdev) {
> > +    int i, r;
> > +
> > +    r = vhost_dev_set_features(hdev, hdev->log_enabled);
> > +    if (r < 0) {
> > +        return r;
> > +    }
> > +    r = hdev->vhost_ops->vhost_call(hdev, VHOST_SET_MEM_TABLE,
> hdev->mem);
> > +    if (r < 0) {
> > +        return r;
> > +    }
> > +    for (i = 0; i < hdev->nvqs; ++i) {
> > +        r = vhost_virtqueue_resend(hdev, vdev, hdev->vqs + i,
> > +                                   hdev->vq_index + i);
> > +        if (r < 0) {
> > +            return r;
> > +        }
> > +    }
> > +
> > +    if (hdev->log_enabled) {
> > +        hdev->log_size = vhost_get_log_size(hdev);
> > +        hdev->log = hdev->log_size ?
> > +            g_malloc0(hdev->log_size * sizeof *hdev->log) : NULL;
> > +        r = hdev->vhost_ops->vhost_call(hdev, VHOST_SET_LOG_BASE,
> hdev->log);
> > +        if (r < 0) {
> > +            return r;
> > +        }
> > +    }
> > +
> > +    return r;
> > +}
> > diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index
> > ee4e07c..ea7e1c7 100644
> > --- a/hw/virtio/virtio.c
> > +++ b/hw/virtio/virtio.c
> > @@ -151,6 +151,13 @@ static inline uint16_t vring_avail_idx(VirtQueue *vq)
> >      return virtio_lduw_phys(vq->vdev, pa);  }
> >
> > +static inline void vring_set_avail_idx(VirtQueue *vq, uint16_t val) {
> > +    hwaddr pa;
> > +    pa = vq->vring.avail + offsetof(VRingAvail, idx);
> > +    virtio_stw_phys(vq->vdev, pa, val); }
> > +
> >  static inline uint16_t vring_avail_ring(VirtQueue *vq, int i)  {
> >      hwaddr pa;
> > @@ -1424,6 +1431,23 @@ uint16_t
> virtio_queue_get_last_avail_idx(VirtIODevice *vdev, int n)
> >      return vdev->vq[n].last_avail_idx;  }
> >
> > +uint16_t virtio_queue_reset_and_get_last_avail_idx(VirtIODevice
> > +*vdev, int n) {
> > +    uint16_t r;
> > +    VirtQueue *q;
> > +
> > +    q = virtio_get_queue(vdev, n);
> > +
> > +    if (n % 2) {
> > +        r = vring_avail_idx(q);
> > +        vring_set_avail_idx(q, r);
> > +    } else {
> > +        r = vring_used_idx(q);
> > +    }
> > +
> > +    return r;
> > +}
> > +
> >  void virtio_queue_set_last_avail_idx(VirtIODevice *vdev, int n,
> > uint16_t idx)  {
> >      vdev->vq[n].last_avail_idx = idx; diff --git
> > a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h index
> > dd51050..cae4fe9 100644
> > --- a/include/hw/virtio/vhost.h
> > +++ b/include/hw/virtio/vhost.h
> > @@ -48,6 +48,8 @@ struct vhost_dev {
> >      unsigned long long acked_features;
> >      unsigned long long backend_features;
> >      bool started;
> > +    bool in_reconnect;
> > +    bool hup;
> >      bool log_enabled;
> >      unsigned long long log_size;
> >      Error *migration_blocker;
> > @@ -67,6 +69,12 @@ int vhost_dev_start(struct vhost_dev *hdev,
> > VirtIODevice *vdev);  void vhost_dev_stop(struct vhost_dev *hdev,
> > VirtIODevice *vdev);  int vhost_dev_enable_notifiers(struct vhost_dev
> > *hdev, VirtIODevice *vdev);  void vhost_dev_disable_notifiers(struct
> > vhost_dev *hdev, VirtIODevice *vdev);
> > +int vhost_dev_reconnect_init(struct vhost_dev *hdev); int
> > +vhost_dev_reconnect(struct vhost_dev *hdev, VirtIODevice *vdev); bool
> > +vhost_dev_in_reconnect(struct vhost_dev *hdev); void
> > +vhost_dev_reconnect_done(struct vhost_dev *hdev); void
> > +vhost_dev_hup(struct vhost_dev *hdev); bool vhost_dev_is_hup(struct
> > +vhost_dev *hdev);
> >
> >  /* Test and clear masked event pending status.
> >   * Should be called after unmask to avoid losing events.
> > diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
> > index 473fb75..c1564f1 100644
> > --- a/include/hw/virtio/virtio.h
> > +++ b/include/hw/virtio/virtio.h
> > @@ -225,6 +225,7 @@ hwaddr virtio_queue_get_avail_size(VirtIODevice
> > *vdev, int n);  hwaddr virtio_queue_get_used_size(VirtIODevice *vdev,
> > int n);  hwaddr virtio_queue_get_ring_size(VirtIODevice *vdev, int n);
> > uint16_t virtio_queue_get_last_avail_idx(VirtIODevice *vdev, int n);
> > +uint16_t virtio_queue_reset_and_get_last_avail_idx(VirtIODevice
> > +*vdev, int n);
> >  void virtio_queue_set_last_avail_idx(VirtIODevice *vdev, int n,
> > uint16_t idx);  void
> > virtio_queue_invalidate_signalled_used(VirtIODevice *vdev, int n);
> > VirtQueue *virtio_get_queue(VirtIODevice *vdev, int n); diff --git
> > a/include/net/vhost_net.h b/include/net/vhost_net.h index
> > 840d4b1..5ef6fdd 100644
> > --- a/include/net/vhost_net.h
> > +++ b/include/net/vhost_net.h
> > @@ -20,6 +20,13 @@ void vhost_net_stop(VirtIODevice *dev,
> > NetClientState *ncs, int total_queues);
> >
> >  void vhost_net_cleanup(VHostNetState *net);
> >
> > +void vhost_net_reconnect_init(VHostNetState *net); bool
> > +vhost_net_in_reconnect(NetClientState *nc); int
> > +vhost_net_reconnect(VirtIODevice *dev, NetClientState *ncs,
> > +                        int total_queues); void
> > +vhost_net_hup(VHostNetState *net); bool
> > +vhost_net_is_hup(NetClientState *nc);
> > +
> >  uint64_t vhost_net_get_features(VHostNetState *net, uint64_t
> > features);  void vhost_net_ack_features(VHostNetState *net, uint64_t
> > features);
> >
> > diff --git a/include/sysemu/char.h b/include/sysemu/char.h index
> > 832b7fe..9eb9b8c 100644
> > --- a/include/sysemu/char.h
> > +++ b/include/sysemu/char.h
> > @@ -18,6 +18,8 @@
> >  #define CHR_EVENT_MUX_IN  3 /* mux-focus was set to this terminal */
> > #define CHR_EVENT_MUX_OUT 4 /* mux-focus will move on */  #define
> > CHR_EVENT_CLOSED  5 /* connection closed */
> > +#define CHR_EVENT_RECON   6 /* connection reconnected */
> > +#define CHR_EVENT_HUP     7 /* connection hang up */
> >
> >
> >  #define CHR_IOCTL_SERIAL_SET_PARAMS   1
> > @@ -84,6 +86,7 @@ struct CharDriverState {
> >      int avail_connections;
> >      int is_mux;
> >      guint fd_in_tag;
> > +    guint fd_hup_tag;
> >      QemuOpts *opts;
> >      QTAILQ_ENTRY(CharDriverState) next;  }; diff --git
> > a/net/vhost-user.c b/net/vhost-user.c index b51bc04..33511a4 100644
> > --- a/net/vhost-user.c
> > +++ b/net/vhost-user.c
> > @@ -112,6 +112,20 @@ static void net_vhost_link_down(VhostUserState
> *s, bool link_down)
> >      }
> >  }
> >
> > +static void vhost_user_reconnect(VhostUserState *s) {
> > +    if (vhost_user_running(s)) {
> > +        vhost_net_reconnect_init(s->vhost_net);
> > +    }
> > +}
> > +
> > +static void vhost_user_hup(VhostUserState *s) {
> > +    if (vhost_user_running(s)) {
> > +        vhost_net_hup(s->vhost_net);
> > +    }
> > +}
> > +
> >  static void net_vhost_user_event(void *opaque, int event)  {
> >      VhostUserState *s = opaque;
> > @@ -127,6 +141,16 @@ static void net_vhost_user_event(void *opaque,
> int event)
> >          vhost_user_stop(s);
> >          error_report("chardev \"%s\" went down", s->nc.info_str);
> >          break;
> > +    case CHR_EVENT_RECON:
> > +        vhost_user_reconnect(s);
> > +        net_vhost_link_down(s, false);
> > +        error_report("chardev \"%s\" reconnected", s->nc.info_str);
> > +        break;
> > +    case CHR_EVENT_HUP:
> > +        vhost_user_hup(s);
> > +        net_vhost_link_down(s, true);
> > +        error_report("chardev \"%s\" hang up", s->nc.info_str);
> > +        break;
> >      }
> >  }
> >
> > diff --git a/qemu-char.c b/qemu-char.c index 617e034..9f42d04 100644
> > --- a/qemu-char.c
> > +++ b/qemu-char.c
> > @@ -2904,6 +2904,105 @@ CharDriverState *qemu_chr_open_eventfd(int
> > eventfd)  }  #endif
> >
> > +static gboolean tcp_chr_chan_hup(GIOChannel *chanel, GIOCondition
> cond,
> > +                                 void *opaque);
> > +
> > +static void tcp_chr_telnet_init(int fd);
> > +
> > +static gboolean tcp_chr_recon(GIOChannel *chanel, GIOCondition cond,
> > +                              void *opaque) {
> > +    CharDriverState *chr = opaque;
> > +    TCPCharDriver *s = chr->opaque;
> > +    struct sockaddr_in saddr;
> > +#ifndef _WIN32
> > +    struct sockaddr_un uaddr;
> > +#endif
> > +    struct sockaddr *addr;
> > +    socklen_t len;
> > +    int fd;
> > +
> > +    for (;;) {
> > +#ifndef _WIN32
> > +        if (s->is_unix) {
> > +            len = sizeof(uaddr);
> > +            addr = (struct sockaddr *)&uaddr;
> > +        } else
> > +#endif
> > +        {
> > +            len = sizeof(saddr);
> > +            addr = (struct sockaddr *)&saddr;
> > +        }
> > +        fd = qemu_accept(s->listen_fd, addr, &len);
> > +        if (fd < 0 && errno != EINTR) {
> > +            s->listen_tag = 0;
> > +            return FALSE;
> > +        } else if (fd >= 0) {
> > +            if (s->do_telnetopt) {
> > +                tcp_chr_telnet_init(fd);
> > +            }
> > +            break;
> > +        }
> > +    }
> > +    qemu_set_nonblock(fd);
> > +    if (s->do_nodelay) {
> > +        socket_set_nodelay(fd);
> > +    }
> > +    s->fd = fd;
> > +    s->chan = io_channel_from_socket(fd);
> > +    SocketAddress_to_str(chr->filename, CHR_MAX_FILENAME_SIZE,
> > +                         "", s->addr, s->is_listen, s->is_telnet);
> > +    s->connected = 1;
> > +    if (s->chan) {
> > +        chr->fd_in_tag = io_add_watch_poll(s->chan, tcp_chr_read_poll,
> > +                                           tcp_chr_read, chr);
> > +    }
> > +    if (chr->chr_event) {
> > +        chr->chr_event(chr->handler_opaque, CHR_EVENT_RECON);
> > +    }
> > +    if (s->listen_tag) {
> > +        g_source_remove(s->listen_tag);
> > +        s->listen_tag = 0;
> > +    }
> > +    if (s->chan) {
> > +        chr->fd_hup_tag = g_io_add_watch(s->chan, G_IO_HUP,
> tcp_chr_chan_hup,
> > +                                         chr);
> > +    }
> > +
> > +    return TRUE;
> > +}
> > +
> > +static gboolean tcp_chr_chan_hup(GIOChannel *chanel, GIOCondition
> cond,
> > +                                 void *opaque) {
> > +    CharDriverState *chr = opaque;
> > +    TCPCharDriver *s = chr->opaque;
> > +
> > +    if (!(cond & G_IO_HUP)) {
> > +        return FALSE;
> > +    }
> > +    if (chr->fd_hup_tag) {
> > +        g_source_remove(chr->fd_hup_tag);
> > +        chr->fd_hup_tag = 0;
> > +    }
> > +    if (s->is_listen) {
> > +        s->listen_tag = g_io_add_watch(s->listen_chan, G_IO_IN,
> tcp_chr_recon,
> > +                                       chr);
> > +    }
> > +    remove_fd_in_watch(chr);
> > +    g_io_channel_unref(s->chan);
> > +    s->chan = NULL;
> > +    closesocket(s->fd);
> > +    s->fd = -1;
> > +    SocketAddress_to_str(chr->filename, CHR_MAX_FILENAME_SIZE,
> > +                         "disconnected:", s->addr, s->is_listen, 
> > s->is_telnet);
> > +    if (chr->chr_event) {
> > +        chr->chr_event(chr->handler_opaque, CHR_EVENT_HUP);
> > +    }
> > +
> > +    return TRUE;
> > +}
> > +
> >  static void tcp_chr_connect(void *opaque)  {
> >      CharDriverState *chr = opaque;
> > @@ -2928,6 +3027,8 @@ static void tcp_chr_connect(void *opaque)
> >      if (s->chan) {
> >          chr->fd_in_tag = io_add_watch_poll(s->chan, tcp_chr_read_poll,
> >                                             tcp_chr_read, chr);
> > +        chr->fd_hup_tag = g_io_add_watch(s->chan, G_IO_HUP,
> tcp_chr_chan_hup,
> > +                                         chr);
> >      }
> >      qemu_chr_be_generic_open(chr);
> >  }
> > --
> > 1.9.1
> 
> 
> 
> ------------------------------
> 
> Message: 3
> Date: Tue, 14 Jul 2015 00:56:16 +1000
> From: Alexey Kardashevskiy <address@hidden>
> To: address@hidden
> Cc: Alexey Kardashevskiy <address@hidden>,    Alex Williamson
>       <address@hidden>,       address@hidden,
> Michael Roth
>       <address@hidden>,       David Gibson
>       <address@hidden>
> Subject: [Qemu-devel] [RFC PATCH qemu v2 0/5] vfio: SPAPR IOMMU v2
>       (memory preregistration support)
> Message-ID: <address@hidden>
> 
> Here are few patches to prepare an existing listener for handling memory
> preregistration for SPAPR guests running on POWER8.
> 
> This used to be a part of DDW patchset but now is separated as requested.
> I left versions in changelog of 5/5 for convenience.
> 
> Please comment, specifically about how many memory listeners we want to
> have in VFIO.
> 
> The existing listener listens on PCI address space which in fact is RAM
> on x86 but is not on sPAPR. Memory preregistration requires listening
> on RAM for sPAPR too. Having a listener without a filter is tricky as it
> will be notified on VIO address spaces too so having more that one listener
> makes some sense. Any input is welcome.
> 
> Thanks!
> 
> 
> Alexey Kardashevskiy (5):
>   vfio: Switch from TARGET_PAGE_MASK to qemu_real_host_page_mask
>   vfio: Skip PCI BARs in memory listener
>   vfio: Store IOMMU type in container
>   vfio: Refactor memory listener to accommodate more IOMMU types
>   vfio: spapr: Add SPAPR IOMMU v2 support (DMA memory preregistering)
> 
>  hw/vfio/common.c              | 207 ++++++++++++++++++++++++++++++++---
> -------
>  hw/vfio/pci.c                 |  30 +++---
>  include/hw/vfio/vfio-common.h |   7 ++
>  trace-events                  |   2 +
>  4 files changed, 183 insertions(+), 63 deletions(-)
> 
> --
> 2.4.0.rc3.8.gfb3e7d5
> 
> 
> 
> 
> ------------------------------
> 
> _______________________________________________
> Qemu-devel mailing list
> address@hidden
> https://lists.nongnu.org/mailman/listinfo/qemu-devel
> 
> 
> End of Qemu-devel Digest, Vol 148, Issue 574
> ********************************************



reply via email to

[Prev in Thread] Current Thread [Next in Thread]