From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:53108) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SrVrx-00068M-Sj for qemu-devel@nongnu.org; Wed, 18 Jul 2012 11:09:04 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SrVrn-0000lv-QM for qemu-devel@nongnu.org; Wed, 18 Jul 2012 11:08:53 -0400 Received: from e06smtp16.uk.ibm.com ([195.75.94.112]:45462) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SrVrn-0000lX-H6 for qemu-devel@nongnu.org; Wed, 18 Jul 2012 11:08:43 -0400 Received: from /spool/local by e06smtp16.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 18 Jul 2012 16:08:42 +0100 Received: from d06av07.portsmouth.uk.ibm.com (d06av07.portsmouth.uk.ibm.com [9.149.37.248]) by d06nrmr1707.portsmouth.uk.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id q6IF8dUu2433050 for ; Wed, 18 Jul 2012 16:08:39 +0100 Received: from d06av07.portsmouth.uk.ibm.com (d06av07.portsmouth.uk.ibm.com [127.0.0.1]) by d06av07.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id q6IEnE0x003645 for ; Wed, 18 Jul 2012 10:49:14 -0400 From: Stefan Hajnoczi Date: Wed, 18 Jul 2012 16:07:44 +0100 Message-Id: <1342624074-24650-18-git-send-email-stefanha@linux.vnet.ibm.com> In-Reply-To: <1342624074-24650-1-git-send-email-stefanha@linux.vnet.ibm.com> References: <1342624074-24650-1-git-send-email-stefanha@linux.vnet.ibm.com> Subject: [Qemu-devel] [RFC v9 17/27] virtio-blk: Use guest notifier to raise interrupts List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Kevin Wolf , Anthony Liguori , Stefan Hajnoczi , kvm@vger.kernel.org, "Michael S. Tsirkin" , Khoa Huynh , Paolo Bonzini , Asias He The data plane thread isn't allowed to call virtio_irq() directly because that function is not thread-safe. Use the guest notifier just like virtio-net to handle IRQs. When MSI-X is in use and the vector is unmasked, the guest notifier directly sets the IRQ inside the host kernel. If the vector is masked, then QEMU's iothread needs to take note of the IRQ. If MSI-X is not in use, then QEMU's iothread handles the IRQ and this will be slower than synchronously calling notify_irq() from the data plane thread. --- hw/virtio-blk.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index d75c187..bdff68a 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -73,6 +73,18 @@ static int get_raw_posix_fd_hack(VirtIOBlock *s) return *(int*)s->bs->file->opaque; } +/* Raise an interrupt to signal guest, if necessary */ +static void virtio_blk_notify_guest(VirtIOBlock *s) +{ + /* Always notify when queue is empty (when feature acknowledge) */ + if ((s->vring.vr.avail->flags & VRING_AVAIL_F_NO_INTERRUPT) && + (s->vring.vr.avail->idx != s->vring.last_avail_idx || + !(s->vdev.guest_features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)))) + return; + + event_notifier_set(virtio_queue_get_guest_notifier(s->vq)); +} + static void complete_request(struct iocb *iocb, ssize_t ret, void *opaque) { VirtIOBlock *s = opaque; @@ -154,7 +166,7 @@ static void process_request(IOQueue *ioq, struct iovec iov[], unsigned int out_n fdatasync(get_raw_posix_fd_hack(s)); inhdr->status = VIRTIO_BLK_S_OK; vring_push(&s->vring, head, sizeof *inhdr); - virtio_irq(s->vq); + virtio_blk_notify_guest(s); } return; @@ -222,8 +234,7 @@ static bool handle_io(EventHandler *handler) VirtIOBlock *s = container_of(handler, VirtIOBlock, io_handler); if (ioq_run_completion(&s->ioqueue, complete_request, s) > 0) { - /* TODO is this thread-safe and can it be done faster? */ - virtio_irq(s->vq); + virtio_blk_notify_guest(s); } /* If there were more requests than iovecs, the vring will not be empty yet @@ -251,11 +262,17 @@ static void data_plane_start(VirtIOBlock *s) vring_setup(&s->vring, &s->vdev, 0); + /* Set up guest notifier (irq) */ + if (s->vdev.binding->set_guest_notifier(s->vdev.binding_opaque, 0, true) != 0) { + fprintf(stderr, "virtio-blk failed to set guest notifier, ensure -enable-kvm is set\n"); + exit(1); + } + event_poll_init(&s->event_poll); /* Set up virtqueue notify */ if (s->vdev.binding->set_host_notifier(s->vdev.binding_opaque, 0, true) != 0) { - fprintf(stderr, "virtio-blk failed to set host notifier, ensure -enable-kvm is set\n"); + fprintf(stderr, "virtio-blk failed to set host notifier\n"); exit(1); } event_poll_add(&s->event_poll, &s->notify_handler, @@ -296,6 +313,9 @@ static void data_plane_stop(VirtIOBlock *s) s->vdev.binding->set_host_notifier(s->vdev.binding_opaque, 0, false); event_poll_cleanup(&s->event_poll); + + /* Clean up guest notifier (irq) */ + s->vdev.binding->set_guest_notifier(s->vdev.binding_opaque, 0, false); } static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t val) -- 1.7.10.4