[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
> ********************************************
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Re: [Qemu-devel] Qemu-devel Digest, Vol 148, Issue 574,
Ouyang, Changchun <=