From patchwork Tue Apr 11 10:04:02 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Roger_Pau_Monn=C3=A9?= X-Patchwork-Id: 9674845 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 7C03060381 for ; Tue, 11 Apr 2017 10:07:58 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 74B20284DC for ; Tue, 11 Apr 2017 10:07:58 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6940928500; Tue, 11 Apr 2017 10:07:58 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id AE1B1284DC for ; Tue, 11 Apr 2017 10:07:57 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cxsg5-0006Bq-8Q; Tue, 11 Apr 2017 10:05:37 +0000 Received: from mail6.bemta5.messagelabs.com ([195.245.231.135]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cxsg4-0006BI-IL for xen-devel@lists.xenproject.org; Tue, 11 Apr 2017 10:05:36 +0000 Received: from [85.158.139.211] by server-5.bemta-5.messagelabs.com id B5/5C-02172-F6AACE85; Tue, 11 Apr 2017 10:05:35 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrOIsWRWlGSWpSXmKPExsXitHSDvW7Oqjc RBgtWSFh83zKZyYHR4/CHKywBjFGsmXlJ+RUJrBlLtt5kKVhiWnG69yxTA+NHjS5GDg4JAX+J qXd0uhg5OdgEdCQuzt3JBhIWEVCRuL3XoIuRi4NZ4ASjxJ/tR9lBaoQFgiX6nl1kA7FZBFQl+ jt+MILYvAKWEksefwCLSwjoSbyd+AIszilgJTHv1DuwuBBQzbYT25kg6gUlTs58wgJiMwtoSr Ru/80OYctLNG+dzQxRryjRP+8B2wRGvllIWmYhaZmFpGUBI/MqRvXi1KKy1CJdI72kosz0jJL cxMwcXUMDU73c1OLixPTUnMSkYr3k/NxNjMBAYwCCHYzf/zgdYpTkYFIS5Q2Y+TpCiC8pP6Uy I7E4I76oNCe1+BCjDAeHkgTvnJVvIoQEi1LTUyvSMnOAIQ+TluDgURLh9QFJ8xYXJOYWZ6ZDp E4x6nJcaf34nkmIJS8/L1VKnJcJpEgApCijNA9uBCz+LjHKSgnzMgIdJcRTkFqUm1mCKv+KUZ yDUUmYdxPIFJ7MvBK4Ta+AjmACOuLMrpcgR5QkIqSkGhhFxDLb2mvbzj4M6I2e5sp8YPOmc3b f9DJE5Q691Q4SfRjuqzLl9L8FN9d9yLz+PFD47Y19sna9tVL2nXWvUv/1T7a/qm5pukUs7fM3 8TgBpjnC87L3ZE1g4Uk/znYnfZKI+EJjrzsnDKRiOA9mhmdMXKF/z2TyGgtfxkvGzq4TY6Xmr dY5ra/EUpyRaKjFXFScCABZ+pKfugIAAA== X-Env-Sender: prvs=267e7865b=roger.pau@citrix.com X-Msg-Ref: server-15.tower-206.messagelabs.com!1491905127!78911912!2 X-Originating-IP: [66.165.176.63] X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni42MyA9PiAzMDYwNDg=\n, received_headers: No Received headers X-StarScan-Received: X-StarScan-Version: 9.4.12; banners=-,-,- X-VirusChecked: Checked Received: (qmail 33979 invoked from network); 11 Apr 2017 10:05:31 -0000 Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63) by server-15.tower-206.messagelabs.com with RC4-SHA encrypted SMTP; 11 Apr 2017 10:05:31 -0000 X-IronPort-AV: E=Sophos;i="5.37,185,1488844800"; d="scan'208";a="427326477" From: Roger Pau Monne To: Date: Tue, 11 Apr 2017 11:04:02 +0100 Message-ID: <20170411100402.56246-7-roger.pau@citrix.com> X-Mailer: git-send-email 2.11.0 (Apple Git-81) In-Reply-To: <20170411100402.56246-1-roger.pau@citrix.com> References: <20170411100402.56246-1-roger.pau@citrix.com> MIME-Version: 1.0 Cc: Andrew Cooper , julien.grall@arm.com, Jan Beulich , boris.ostrovsky@oracle.com, Roger Pau Monne Subject: [Xen-devel] [PATCH for-next 6/6] xen/vpci: trap access to the list of PCI capabilities X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP Add traps to each capability PCI_CAP_LIST_NEXT field in order to mask them on request. All capabilities from the device are fetched and stored in an internal list, that's later used in order to return the next capability to the guest. Note that this only removes the capability from the linked list as seen by the guest, but the actual capability structure could still be accessed by the guest, provided that it's position can be found using another mechanism. Finally the MSI and MSI-X capabilities are masked until Xen knows how to properly handle accesses to them. This should allow a PVH Dom0 to boot on some hardware, provided that the hardware doesn't require MSI/MSI-X and that there are no SR-IOV devices in the system, so the panic at the end of the PVH Dom0 build is replaced by a warning. Signed-off-by: Roger Pau Monné --- Cc: Jan Beulich Cc: Andrew Cooper --- xen/arch/x86/hvm/dom0_build.c | 2 +- xen/drivers/vpci/Makefile | 2 +- xen/drivers/vpci/capabilities.c | 153 ++++++++++++++++++++++++++++++++++++++++ xen/include/xen/vpci.h | 3 + 4 files changed, 158 insertions(+), 2 deletions(-) create mode 100644 xen/drivers/vpci/capabilities.c diff --git a/xen/arch/x86/hvm/dom0_build.c b/xen/arch/x86/hvm/dom0_build.c index 47600345ab..23ab20167e 100644 --- a/xen/arch/x86/hvm/dom0_build.c +++ b/xen/arch/x86/hvm/dom0_build.c @@ -1091,7 +1091,7 @@ int __init dom0_construct_pvh(struct domain *d, const module_t *image, return rc; } - panic("Building a PVHv2 Dom0 is not yet supported."); + printk("WARNING: PVH is an experimental mode with limited functionality\n"); return 0; } diff --git a/xen/drivers/vpci/Makefile b/xen/drivers/vpci/Makefile index 241467212f..c3f3085c93 100644 --- a/xen/drivers/vpci/Makefile +++ b/xen/drivers/vpci/Makefile @@ -1 +1 @@ -obj-y += vpci.o header.o +obj-y += vpci.o header.o capabilities.o diff --git a/xen/drivers/vpci/capabilities.c b/xen/drivers/vpci/capabilities.c new file mode 100644 index 0000000000..69ecd22537 --- /dev/null +++ b/xen/drivers/vpci/capabilities.c @@ -0,0 +1,153 @@ +/* + * Generic functionality for handling accesses to the PCI capabilities from + * the configuration space. + * + * Copyright (C) 2017 Citrix Systems R&D + * + * This program is free software; you can redistribute it and/or + * modify it under the terms and conditions of the GNU General Public + * License, version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; If not, see . + */ + +#include +#include + +struct vpci_capability { + struct list_head next; + uint8_t offset; + bool masked; +}; + +static int vpci_cap_read(struct pci_dev *dev, unsigned int reg, + union vpci_val *val, void *data) +{ + struct vpci_capability *next, *curr = data; + + val->half_word = 0; + + /* Return the position of the next non-masked capability. */ + while ( (next = list_next_entry(curr, next)) != NULL ) + { + if ( !next->masked ) + { + val->half_word = next->offset; + break; + } + curr = next; + } + + return 0; +} +static int vpci_cap_write(struct pci_dev *dev, unsigned int reg, + union vpci_val val, void *data) +{ + /* Ignored. */ + return 0; +} + +static int vpci_index_capabilities(struct pci_dev *pdev) +{ + uint8_t seg = pdev->seg, bus = pdev->bus; + uint8_t slot = PCI_SLOT(pdev->devfn), func = PCI_FUNC(pdev->devfn); + uint8_t pos = PCI_CAPABILITY_LIST; + uint16_t status; + unsigned int max_cap = 48; + struct vpci_capability *cap; + int rc; + + INIT_LIST_HEAD(&pdev->vpci->cap_list); + + /* Check if device has capabilities. */ + status = pci_conf_read16(seg, bus, slot, func, PCI_STATUS); + if ( (status & PCI_STATUS_CAP_LIST) == 0 ) + return 0; + + /* Add the root capability pointer. */ + cap = xzalloc(struct vpci_capability); + if ( !cap ) + return -ENOMEM; + + cap->offset = pos; + list_add_tail(&cap->next, &pdev->vpci->cap_list); + rc = xen_vpci_add_register(pdev, vpci_cap_read, vpci_cap_write, pos, + 1, cap); + if ( rc ) + return rc; + + /* + * Iterate over the list of capabilities present in the device, and + * add a handler for each pointer to the next item (PCI_CAP_LIST_NEXT). + */ + while ( max_cap-- ) + { + pos = pci_conf_read8(seg, bus, slot, func, pos); + if ( pos < 0x40 ) + break; + + cap = xzalloc(struct vpci_capability); + if ( !cap ) + return -ENOMEM; + + cap->offset = pos; + list_add_tail(&cap->next, &pdev->vpci->cap_list); + pos += PCI_CAP_LIST_NEXT; + rc = xen_vpci_add_register(pdev, vpci_cap_read, vpci_cap_write, pos, + 1, cap); + if ( rc ) + return rc; + } + + return 0; +} + +static void vpci_mask_capability(struct pci_dev *pdev, uint8_t cap_id) +{ + struct vpci_capability *cap; + uint8_t cap_offset; + + cap_offset = pci_find_cap_offset(pdev->seg, pdev->bus, + PCI_SLOT(pdev->devfn), + PCI_FUNC(pdev->devfn), cap_id); + if ( !cap_offset ) + return; + + list_for_each_entry ( cap, &pdev->vpci->cap_list, next ) + if ( cap->offset == cap_offset ) + cap->masked = true; +} + +static int vpci_capabilities_init(struct pci_dev *pdev) +{ + int rc; + + rc = vpci_index_capabilities(pdev); + if ( rc ) + return rc; + + /* Mask MSI and MSI-X capabilities until Xen handles them. */ + vpci_mask_capability(pdev, PCI_CAP_ID_MSI); + vpci_mask_capability(pdev, PCI_CAP_ID_MSIX); + + return 0; +} + +REGISTER_VPCI_INIT(vpci_capabilities_init); + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ + diff --git a/xen/include/xen/vpci.h b/xen/include/xen/vpci.h index 205d121a92..944f48d893 100644 --- a/xen/include/xen/vpci.h +++ b/xen/include/xen/vpci.h @@ -68,6 +68,9 @@ struct vpci { bool sizing; } bars[6]; } header; + + /* List of capabilities supported by the device. */ + struct list_head cap_list; #endif };