From patchwork Wed Apr 9 15:33:09 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Auger Eric X-Patchwork-Id: 28101 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-pd0-f199.google.com (mail-pd0-f199.google.com [209.85.192.199]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 1A3602145A for ; Wed, 9 Apr 2014 15:38:33 +0000 (UTC) Received: by mail-pd0-f199.google.com with SMTP id x10sf7494309pdj.10 for ; Wed, 09 Apr 2014 08:38:33 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:date :message-id:in-reply-to:references:cc:subject:precedence:list-id :list-unsubscribe:list-archive:list-post:list-help:list-subscribe :errors-to:sender:x-original-sender :x-original-authentication-results:mailing-list; bh=LQnk7wRiqgK/QQ6XWSaK8DFwSX7IO8t79C8Hx5qVFiY=; b=Q1+bulkndsvAW/OUWPDbfr4FUQknG05FQvB2DK6uWiTxiKKrXmn7AAvEoFvKZfNppe y6x1L/25RxOTDtetdGaea7pGVThW2hUqNA3Z2A9TWV7WFx64qOj8IxRhembTdq2E3W7s OJ3JC4TdZjIILluXoMSeKIv/hniWA5P1MRU3jI48N1Rn2lpnUZ0ohT2ul5EZ4ax/Ktgc 5l2VDNjbI0sa9FFD0nHTfUd+fjxRhp9cjN8jZ/CfscTxAceLUjW29WR9OI10zAsYNDO5 SOWhh/8UFtqvepOnDyX1nIMvEHdf1NaCHau/BMeU7zf+XunIteP4NtKs+kJJ8JTA4JKQ xiLA== X-Gm-Message-State: ALoCoQn02kW8PbKs1gRA1rwDec8LRYqIed4kykGWuhg+6/934Ca3saNukb3GKCTvoKcqcBeUIrYR X-Received: by 10.66.141.135 with SMTP id ro7mr5170412pab.28.1397057913290; Wed, 09 Apr 2014 08:38:33 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.90.11 with SMTP id w11ls694078qgd.43.gmail; Wed, 09 Apr 2014 08:38:33 -0700 (PDT) X-Received: by 10.221.22.71 with SMTP id qv7mr1117311vcb.34.1397057913014; Wed, 09 Apr 2014 08:38:33 -0700 (PDT) Received: from mail-vc0-f178.google.com (mail-vc0-f178.google.com [209.85.220.178]) by mx.google.com with ESMTPS id dh4si191611veb.211.2014.04.09.08.38.32 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 09 Apr 2014 08:38:33 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.220.178 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.220.178; Received: by mail-vc0-f178.google.com with SMTP id im17so2300867vcb.9 for ; Wed, 09 Apr 2014 08:38:32 -0700 (PDT) X-Received: by 10.220.4.132 with SMTP id 4mr9522931vcr.9.1397057912923; Wed, 09 Apr 2014 08:38:32 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.220.12.8 with SMTP id v8csp340029vcv; Wed, 9 Apr 2014 08:38:32 -0700 (PDT) X-Received: by 10.140.19.212 with SMTP id 78mr12859677qgh.84.1397057912441; Wed, 09 Apr 2014 08:38:32 -0700 (PDT) Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id d10si570336qaf.101.2014.04.09.08.38.32 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Wed, 09 Apr 2014 08:38:32 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Received: from localhost ([::1]:46776 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WXua8-0006EI-0m for patch@linaro.org; Wed, 09 Apr 2014 11:38:32 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46292) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WXuVz-00009N-0y for qemu-devel@nongnu.org; Wed, 09 Apr 2014 11:34:20 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WXuVs-0000GW-66 for qemu-devel@nongnu.org; Wed, 09 Apr 2014 11:34:14 -0400 Received: from mail-we0-f177.google.com ([74.125.82.177]:54597) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WXuVr-0000GJ-Tt for qemu-devel@nongnu.org; Wed, 09 Apr 2014 11:34:08 -0400 Received: by mail-we0-f177.google.com with SMTP id u57so2655032wes.36 for ; Wed, 09 Apr 2014 08:34:07 -0700 (PDT) X-Received: by 10.194.48.100 with SMTP id k4mr10357182wjn.49.1397057647161; Wed, 09 Apr 2014 08:34:07 -0700 (PDT) Received: from midway01-04-00.lavalab ([88.98.47.97]) by mx.google.com with ESMTPSA id ga10sm2170061wjb.23.2014.04.09.08.34.05 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 09 Apr 2014 08:34:06 -0700 (PDT) From: Eric Auger To: eric.auger@st.com, christoffer.dall@linaro.org, qemu-devel@nongnu.org Date: Wed, 9 Apr 2014 16:33:09 +0100 Message-Id: <1397057589-11779-7-git-send-email-eric.auger@linaro.org> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1397057589-11779-1-git-send-email-eric.auger@linaro.org> References: <1397057589-11779-1-git-send-email-eric.auger@linaro.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 74.125.82.177 Cc: peter.maydell@linaro.org, kim.phillips@freescale.com, Eric Auger , agraf@suse.de, stuart.yoder@freescale.com, alex.williamson@redhat.com, christophe.barnichon@st.com, a.motakis@virtualopensystems.com, kvmarm@lists.cs.columbia.edu Subject: [Qemu-devel] [RFC v2 6/6] vfio: add exit function and IRQ disable functions X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: qemu-devel-bounces+patch=linaro.org@nongnu.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: eric.auger@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.220.178 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 this patch brings misc improvements: - improve comments - remove interrupt field in VFIODevice - add IRQ disable routines used by new exitfn function Signed-off-by: Eric Auger --- hw/vfio/platform.c | 167 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 127 insertions(+), 40 deletions(-) diff --git a/hw/vfio/platform.c b/hw/vfio/platform.c index 8f30d41..c4a4286 100644 --- a/hw/vfio/platform.c +++ b/hw/vfio/platform.c @@ -40,7 +40,6 @@ #include "vfio-common.h" -#define DEBUG_VFIO #ifdef DEBUG_VFIO #define DPRINTF(fmt, ...) \ do { fprintf(stderr, "vfio: %s: " fmt, __func__, ## __VA_ARGS__); } \ @@ -69,7 +68,9 @@ typedef struct VFIORegion { } VFIORegion; -#define VFIO_INT_INTp 4 +/* + * The IRQ structure inspired from PCI VFIOINTx + */ typedef struct VFIOINTp { QLIST_ENTRY(VFIOINTp) next; @@ -91,9 +92,8 @@ typedef struct VFIODevice { int fd; int num_regions; int num_irqs; - int interrupt; /* type of the interrupt, might disappear */ char *name; - char *compat; + char *compat; /* compatibility string */ uint32_t mmap_timeout; /* mmap timeout value in ms */ VFIORegion regions[PLATFORM_NUM_REGIONS]; QLIST_ENTRY(VFIODevice) next; @@ -101,9 +101,11 @@ typedef struct VFIODevice { QLIST_HEAD(, VFIOINTp) intp_list; } VFIODevice; + /* * returns properties from a QEMU VFIO device such as * name, compatibility, num IRQs, size of the register set + * currently used by virt machine */ void vfio_get_props(SysBusDevice *s, char **pname, char **pcompat, int *pnum_irqs, size_t *psize); @@ -118,6 +120,20 @@ void vfio_get_props(SysBusDevice *s, char **pname, *psize = vdev->regions[0].size; } +static void vfio_disable_irqindex(VFIODevice *vdev, int index) +{ + struct vfio_irq_set irq_set = { + .argsz = sizeof(irq_set), + .flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_TRIGGER, + .index = index, + .start = 0, + .count = 0, + }; + + ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &irq_set); +} + + static void vfio_unmask_intp(VFIODevice *vdev, int index) { @@ -132,12 +148,17 @@ static void vfio_unmask_intp(VFIODevice *vdev, int index) ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &irq_set); } - +/* + * Checks whether the IRQ was EOI'ed. In the positive the fast path + * is restored (reg space is mmaped). In the negative the reg space + * stays as an MMIO region (ops) and the mmap timer is reprogrammed + * to check the same condition after mmap_timeout ms + */ static void vfio_intp_mmap_enable(void *opaque) { - VFIOINTp * intp = (VFIOINTp *)opaque; + VFIOINTp *intp = (VFIOINTp *)opaque; VFIODevice *vdev = intp->vdev; if (intp->pending) { @@ -153,6 +174,10 @@ static void vfio_intp_mmap_enable(void *opaque) } +/* + * The fd handler + */ + static void vfio_intp_interrupt(void *opaque) { @@ -176,11 +201,14 @@ static void vfio_intp_interrupt(void *opaque) */ VFIORegion *region = &vdev->regions[0]; + + /* register space is unmapped to trap EOI */ memory_region_set_enabled(®ion->mmap_mem, false); + /* trigger the virtual IRQ */ qemu_set_irq(intp->qemuirq, 1); - /* schedule the mmap timer which will restote mmap path after EOI*/ + /* schedule the mmap timer which will restore mmap path after EOI*/ if (intp->mmap_timeout) { timer_mod(intp->mmap_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + intp->mmap_timeout); @@ -200,13 +228,18 @@ static void vfio_irq_eoi(VFIODevice *vdev) if (intp->pending) { if (eoi_done) { DPRINTF("several IRQ pending simultaneously: \ - this is not a supported case yet\n"); + this case is not tested yet\n"); } + DPRINTF("EOI IRQ #%d fd=%d\n", intp->pin, event_notifier_get_fd(&intp->interrupt)); + intp->pending = false; + + /* deassert the virtual IRQ and unmask physical one */ qemu_set_irq(intp->qemuirq, 0); vfio_unmask_intp(vdev, intp->pin); + eoi_done = true; } } @@ -217,22 +250,6 @@ static void vfio_irq_eoi(VFIODevice *vdev) -#if 0 -static void vfio_list_intp(VFIODevice *vdev) -{ - VFIOINTp *intp; - int i = 0; - QLIST_FOREACH(intp, &vdev->intp_list, next) { - DPRINTF("IRQ #%d\n", i); - DPRINTF("- pin = %d\n", intp->pin); - DPRINTF("- fd = %d\n", event_notifier_get_fd(&intp->interrupt)); - DPRINTF("- pending = %d\n", (int)intp->pending); - DPRINTF("- kvm_accel = %d\n", (int)intp->kvm_accel); - i++; - } -} -#endif - static int vfio_enable_intp(VFIODevice *vdev, unsigned int index) { struct vfio_irq_set *irq_set; /* irq structure passed to vfio kernel */ @@ -242,8 +259,6 @@ static int vfio_enable_intp(VFIODevice *vdev, unsigned int index) int device = vdev->fd; SysBusDevice *sbdev = SYS_BUS_DEVICE(vdev); - vdev->interrupt = VFIO_INT_INTp; - /* allocate and populate a new VFIOINTp structure put in a queue list */ VFIOINTp *intp = g_malloc0(sizeof(*intp)); intp->vdev = vdev; @@ -251,17 +266,12 @@ static int vfio_enable_intp(VFIODevice *vdev, unsigned int index) intp->pending = false; intp->mmap_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, vfio_intp_mmap_enable, intp); - intp->mmap_timeout = 1100; - /* TO DO: timeout as parameter */ - /* incr sysbus num_irq and sets sysbus->irqp[n] = &intp->qemuirq - * only the address of the qemu_irq is set here - */ + /* TO DO: currently each IRQ has the same mmap timeout */ + intp->mmap_timeout = intp->vdev->mmap_timeout; sysbus_init_irq(sbdev, &intp->qemuirq); - /* content is set in sysbus_connect_irq (currently in machine definition) */ - ret = event_notifier_init(&intp->interrupt, 0); if (ret) { error_report("vfio: Error: event_notifier_init failed "); @@ -302,7 +312,7 @@ static int vfio_enable_intp(VFIODevice *vdev, unsigned int index) g_free(irq_set); if (ret) { - error_report("vfio: Error: Failed to pass Int fd to the driver: %m"); + error_report("vfio: Error: Failed to pass IRQ fd to the driver: %m"); qemu_set_fd_handler(*pfd, NULL, NULL, vdev); close(*pfd); /* TO DO : replace by event_notifier_cleanup */ return -errno; @@ -317,6 +327,30 @@ static int vfio_enable_intp(VFIODevice *vdev, unsigned int index) } +static void vfio_disable_intp(VFIODevice *vdev) +{ + VFIOINTp *intp; + int fd; + + QLIST_FOREACH(intp, &vdev->intp_list, next) { + fd = event_notifier_get_fd(&intp->interrupt); + DPRINTF("close IRQ pin=%d fd=%d\n", intp->pin, fd); + + vfio_disable_irqindex(vdev, intp->pin); + intp->pending = false; + qemu_set_irq(intp->qemuirq, 0); + + qemu_set_fd_handler(fd, NULL, NULL, vdev); + event_notifier_cleanup(&intp->interrupt); + } + + VFIORegion *region = &vdev->regions[0]; + memory_region_set_enabled(®ion->mmap_mem, true); + +} + + + static int vfio_mmap_region(VFIODevice *vdev, VFIORegion *region, @@ -386,11 +420,11 @@ static void vfio_region_write(void *opaque, hwaddr addr, } if (pwrite(region->fd, &buf, size, region->fd_offset + addr) != size) { - error_report("(,0x%"HWADDR_PRIx", 0x%"PRIx64", %d) failed: %m", + error_report("(0x%"HWADDR_PRIx", 0x%"PRIx64", %d) failed: %m", addr, data, size); } - DPRINTF("(region %d+0x%"HWADDR_PRIx", 0x%"PRIx64", %d)\n", + DPRINTF("(region %d, addr=0x%"HWADDR_PRIx", data= 0x%"PRIx64", %d)\n", region->nr, addr, data, size); vfio_irq_eoi(container_of(region, VFIODevice, regions[region->nr])); @@ -409,7 +443,7 @@ static uint64_t vfio_region_read(void *opaque, hwaddr addr, unsigned size) uint64_t data = 0; if (pread(region->fd, &buf, size, region->fd_offset + addr) != size) { - error_report("(,0x%"HWADDR_PRIx", %d) failed: %m", + error_report("(0x%"HWADDR_PRIx", %d) failed: %m", addr, size); return (uint64_t)-1; } @@ -429,7 +463,7 @@ static uint64_t vfio_region_read(void *opaque, hwaddr addr, unsigned size) break; } - DPRINTF("(region %d+0x%"HWADDR_PRIx", %d) = 0x%"PRIx64"\n", + DPRINTF("(region %d, addr= 0x%"HWADDR_PRIx", data=%d) = 0x%"PRIx64"\n", region->nr, addr, size, data); vfio_irq_eoi(container_of(region, VFIODevice, regions[region->nr])); @@ -464,6 +498,17 @@ static void vfio_map_region(VFIODevice *vdev, int nr) } } + +static void vfio_unmap_region(VFIODevice *vdev, int nr) +{ +VFIORegion *region = &vdev->regions[nr]; +memory_region_del_subregion(®ion->mem, ®ion->mmap_mem); +munmap(region->mmap, memory_region_size(®ion->mmap_mem)); +memory_region_destroy(®ion->mmap_mem); +} + + + static int vfio_get_device(VFIOGroup *group, const char *name, struct VFIODevice *vdev) { @@ -624,8 +669,6 @@ static void vfio_platform_realize(DeviceState *dev, Error **errp) } } - DPRINTF("Calling vfio_get_device ...\n"); - ret = vfio_get_device(group, path, vdev); if (ret) { error_report("vfio: failed to get device %s", path); @@ -639,11 +682,50 @@ static void vfio_platform_realize(DeviceState *dev, Error **errp) } } +static void vfio_platform_reset_handler(void *opaque) +{ +} + + +static void vfio_put_device(VFIODevice *vdev) +{ + QLIST_REMOVE(vdev, next); + vdev->group = NULL; + DPRINTF("vfio_put_device: close vdev->fd\n"); + close(vdev->fd); +} + +static void vfio_platform_exitfn(VFIODevice *dev) +{ + VFIOGroup *group = dev->group; + VFIOINTp *intp, *next_intp; + + vfio_disable_intp(dev); + + QLIST_FOREACH_SAFE(intp, &dev->intp_list, next, next_intp) { + QLIST_REMOVE(intp, next); + if (intp->mmap_timer) { + timer_free(intp->mmap_timer); + } + g_free(intp); + } + + vfio_unmap_region(dev, 0); + vfio_put_device(dev); + vfio_put_group(group, vfio_platform_reset_handler); +} + + static const VMStateDescription vfio_platform_vmstate = { .name = TYPE_VFIO_PLATFORM, .unmigratable = 1, }; +typedef struct VFIOPlatformDeviceClass { + DeviceClass parent_class; + void (*exit)(VFIODevice *); +} VFIOPlatformDeviceClass; + static Property vfio_platform_dev_properties[] = { DEFINE_PROP_STRING("vfio_device", VFIODevice, name), DEFINE_PROP_STRING("compat", VFIODevice, compat), @@ -651,15 +733,20 @@ DEFINE_PROP_UINT32("mmap-timeout-ms", VFIODevice, mmap_timeout, 1100), DEFINE_PROP_END_OF_LIST(), }; +#define VFIO_PLATFORM_DEVICE_CLASS(klass) \ + OBJECT_CLASS_CHECK(VFIOPlatformDeviceClass, (klass), TYPE_VFIO_PLATFORM) + static void vfio_platform_dev_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); + VFIOPlatformDeviceClass *vc = VFIO_PLATFORM_DEVICE_CLASS(klass); dc->realize = vfio_platform_realize; dc->vmsd = &vfio_platform_vmstate; dc->props = vfio_platform_dev_properties; dc->desc = "VFIO-based platform device assignment"; dc->cannot_instantiate_with_device_add_yet = false; + vc->exit = vfio_platform_exitfn; set_bit(DEVICE_CATEGORY_MISC, dc->categories); }