From patchwork Wed Jan 9 06:26:24 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Pandarathil, Vijaymohan R" X-Patchwork-Id: 210632 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 4B7172C00D8 for ; Wed, 9 Jan 2013 17:28:09 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757182Ab3AIG1o (ORCPT ); Wed, 9 Jan 2013 01:27:44 -0500 Received: from g4t0015.houston.hp.com ([15.201.24.18]:41777 "EHLO g4t0015.houston.hp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757284Ab3AIG1m convert rfc822-to-8bit (ORCPT ); Wed, 9 Jan 2013 01:27:42 -0500 Received: from G4W6310.americas.hpqcorp.net (g4w6310.houston.hp.com [16.210.26.217]) (using TLSv1 with cipher AES128-SHA (128/128 bits)) (No client certificate requested) by g4t0015.houston.hp.com (Postfix) with ESMTPS id 24F1886AB; Wed, 9 Jan 2013 06:27:42 +0000 (UTC) Received: from G9W3616.americas.hpqcorp.net (16.216.186.51) by G4W6310.americas.hpqcorp.net (16.210.26.217) with Microsoft SMTP Server (TLS) id 14.2.283.4; Wed, 9 Jan 2013 06:26:24 +0000 Received: from G9W0717.americas.hpqcorp.net ([169.254.4.192]) by G9W3616.americas.hpqcorp.net ([16.216.186.51]) with mapi id 14.02.0283.004; Wed, 9 Jan 2013 06:26:24 +0000 From: "Pandarathil, Vijaymohan R" To: Alex Williamson , Bjorn Helgaas , Gleb Natapov CC: "kvm@vger.kernel.org" , "qemu-devel@nongnu.org" , "linux-pci@vger.kernel.org" , "linux-kernel@vger.kernel.org" Subject: [PATCH 2/2] QEMU-AER: Qemu changes to support AER for VFIO-PCI devices Thread-Topic: [PATCH 2/2] QEMU-AER: Qemu changes to support AER for VFIO-PCI devices Thread-Index: AQHN7jI/NxaDlJRulEClJd4cCU38Mg== Date: Wed, 9 Jan 2013 06:26:24 +0000 Message-ID: Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [15.201.58.14] MIME-Version: 1.0 Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org - Create eventfd per vfio device assigned to a guest and register an event handler - This fd is passed to the vfio_pci driver through a new ioctl - When the device encounters an error, the eventfd is signaled and the qemu eventfd handler gets invoked. - In the handler decide what action to take. Current action taken is to terminate the guest. Signed-off-by: Vijay Mohan Pandarathil --- hw/vfio_pci.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++ linux-headers/linux/vfio.h | 9 ++++++++ 2 files changed, 65 insertions(+) diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c index 28c8303..9c3c28b 100644 --- a/hw/vfio_pci.c +++ b/hw/vfio_pci.c @@ -38,6 +38,7 @@ #include "qemu/error-report.h" #include "qemu/queue.h" #include "qemu/range.h" +#include "sysemu/sysemu.h" /* #define DEBUG_VFIO */ #ifdef DEBUG_VFIO @@ -130,6 +131,8 @@ typedef struct VFIODevice { QLIST_ENTRY(VFIODevice) next; struct VFIOGroup *group; bool reset_works; + EventNotifier errfd; + __u32 dev_info_flags; } VFIODevice; typedef struct VFIOGroup { @@ -1805,6 +1808,8 @@ static int vfio_get_device(VFIOGroup *group, const char *name, VFIODevice *vdev) DPRINTF("Device %s flags: %u, regions: %u, irgs: %u\n", name, dev_info.flags, dev_info.num_regions, dev_info.num_irqs); + vdev->dev_info_flags = dev_info.flags; + if (!(dev_info.flags & VFIO_DEVICE_FLAGS_PCI)) { error_report("vfio: Um, this isn't a PCI device\n"); goto error; @@ -1900,6 +1905,55 @@ static void vfio_put_device(VFIODevice *vdev) } } +static void vfio_errfd_handler(void *opaque) +{ + VFIODevice *vdev = opaque; + + if (!event_notifier_test_and_clear(&vdev->errfd)) { + return; + } + + /* + * TBD. Retrieve the error details and decide what action + * needs to be taken. One of the actions could be to pass + * the error to the guest and have the guest driver recover + * the error. This requires that PCIe capabilities be + * exposed to the guest. At present, we just terminate the + * guest to contain the error. + */ + error_report("%s(%04x:%02x:%02x.%x) " + "Unrecoverable error detected... Terminating guest\n", + __func__, vdev->host.domain, vdev->host.bus, vdev->host.slot, + vdev->host.function); + + qemu_system_shutdown_request(); + return; +} + +static void vfio_register_errfd(VFIODevice *vdev) +{ + int32_t pfd; + int ret; + + if (!(vdev->dev_info_flags & VFIO_DEVICE_FLAGS_AER_NOTIFY)) { + error_report("vfio: Warning: Error notification not supported for the device\n"); + return; + } + if (event_notifier_init(&vdev->errfd, 0)) { + error_report("vfio: Warning: Unable to init event notifier for error detection\n"); + return; + } + pfd = event_notifier_get_fd(&vdev->errfd); + qemu_set_fd_handler(pfd, vfio_errfd_handler, NULL, vdev); + + ret = ioctl(vdev->fd, VFIO_DEVICE_SET_ERRFD, pfd); + if (ret) { + error_report("vfio: Warning: Failed to setup error fd: %d\n", ret); + qemu_set_fd_handler(pfd, NULL, NULL, vdev); + event_notifier_cleanup(&vdev->errfd); + } + return; +} static int vfio_initfn(PCIDevice *pdev) { VFIODevice *pvdev, *vdev = DO_UPCAST(VFIODevice, pdev, pdev); @@ -2010,6 +2064,8 @@ static int vfio_initfn(PCIDevice *pdev) } } + vfio_register_errfd(vdev); + return 0; out_teardown: diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h index 4758d1b..0ca4eeb 100644 --- a/linux-headers/linux/vfio.h +++ b/linux-headers/linux/vfio.h @@ -147,6 +147,7 @@ struct vfio_device_info { __u32 flags; #define VFIO_DEVICE_FLAGS_RESET (1 << 0) /* Device supports reset */ #define VFIO_DEVICE_FLAGS_PCI (1 << 1) /* vfio-pci device */ +#define VFIO_DEVICE_FLAGS_AER_NOTIFY (1 << 2) /* Supports aer notification */ __u32 num_regions; /* Max region index + 1 */ __u32 num_irqs; /* Max IRQ index + 1 */ }; @@ -288,6 +289,14 @@ struct vfio_irq_set { */ #define VFIO_DEVICE_RESET _IO(VFIO_TYPE, VFIO_BASE + 11) +/** + * VFIO_DEVICE_SET_ERRFD - _IO(VFIO_TYPE, VFIO_BASE + 12) + * + * Pass the eventfd to the vfio-pci driver for signalling any device + * error notifications + */ +#define VFIO_DEVICE_SET_ERRFD _IO(VFIO_TYPE, VFIO_BASE + 12) + /* * The VFIO-PCI bus driver makes use of the following fixed region and * IRQ index mapping. Unimplemented regions return a size of zero.