From patchwork Thu Jan 29 03:54:43 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yijing Wang X-Patchwork-Id: 5737321 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id C84EC9F54F for ; Thu, 29 Jan 2015 03:56:37 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id E50C6201BB for ; Thu, 29 Jan 2015 03:56:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C1B1420221 for ; Thu, 29 Jan 2015 03:56:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757887AbbA2D4c (ORCPT ); Wed, 28 Jan 2015 22:56:32 -0500 Received: from szxga03-in.huawei.com ([119.145.14.66]:15059 "EHLO szxga03-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752352AbbA2D43 (ORCPT ); Wed, 28 Jan 2015 22:56:29 -0500 Received: from 172.24.2.119 (EHLO szxeml427-hub.china.huawei.com) ([172.24.2.119]) by szxrg03-dlp.huawei.com (MOS 4.4.3-GA FastPath queued) with ESMTP id BBC11926; Thu, 29 Jan 2015 11:56:18 +0800 (CST) Received: from localhost.localdomain (10.175.100.166) by szxeml427-hub.china.huawei.com (10.82.67.182) with Microsoft SMTP Server id 14.3.158.1; Thu, 29 Jan 2015 11:56:07 +0800 From: Yijing Wang To: CC: , , , , , , , , Yijing Wang Subject: [PATCH v3] PCI: Add guard to avoid mapping a invalid msix base address Date: Thu, 29 Jan 2015 11:54:43 +0800 Message-ID: <1422503683-19709-1-git-send-email-wangyijing@huawei.com> X-Mailer: git-send-email 1.7.1 MIME-Version: 1.0 X-Originating-IP: [10.175.100.166] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A020201.54C9AF63.004C, ss=1, re=0.001, recu=0.000, reip=0.000, cl=1, cld=1, fgs=0, ip=0.0.0.0, so=2013-05-26 15:14:31, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: 107c6237fc5d80361e8ee89d98443f10 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Sometimes, a pci bridge device BAR was not assigned properly. After we call pci_bus_assign_resources(), the resource of the BAR would be reseted. So if we try to enable msix for this device, it will map a invalid resource as the msix base address, and a warning call trace will report. pci_bus_assign_resources() __pci_bus_assign_resources() pbus_assign_resources_sorted() __assign_resources_sorted() assign_requested_resources_sorted() pci_assign_resource() -->fail reset_resource() -->res->start/end/flags = 0 pcie_port_device_register() init_service_irqs() pcie_port_enable_msix() ... msix_capability_init() msix_map_region() phys_addr = pci_resource_start(dev, bir) + table_offset; If BAR(index=bir) was not assign properly, pci_resource_start(dev, bir) here would return 0, so phys_addr is a invalid physical address of msix. [ 43.094087] ------------[ cut here ]------------ [ 43.097418] WARNING: CPU: 1 PID: 1800 at arch/arm64/mm/ioremap.c:58 __ioremap_caller+0xd4/0xe8() ... [ 43.121694] CPU: 1 PID: 1800 Comm: insmod Tainted: G O 3.16.0 #5 [ 43.127374] Call trace: [ 43.128522] [] dump_backtrace+0x0/0x130 [ 43.132637] [] show_stack+0x10/0x1c [ 43.136402] [] dump_stack+0x74/0x94 [ 43.140166] [] warn_slowpath_common+0x8c/0xb4 [ 43.144804] [] warn_slowpath_null+0x14/0x20 [ 43.149266] [] __ioremap_caller+0xd0/0xe8 [ 43.153555] [] __ioremap+0xc/0x18 [ 43.157145] [] pci_enable_msix+0x238/0x44c [ 43.161521] [] pci_enable_msix_range+0x34/0x80 [ 43.166243] [] pcie_port_device_register+0x104/0x480 [ 43.171491] [] pcie_portdrv_probe+0x38/0xa0 [ 43.175952] [] pci_device_probe+0x78/0xd4 [ 43.180238] [] really_probe+0x6c/0x22c [ 43.184265] [] __device_attach+0x5c/0x6c [ 43.188466] [] bus_for_each_drv+0x50/0x94 [ 43.192755] [] device_attach+0x9c/0xc0 [ 43.196780] [] pci_bus_add_device+0x38/0x80 [ 43.201243] [] pci_bus_add_devices+0x4c/0xd4 [ 43.205791] [] pci_common_init+0x274/0x378 [ 43.210170] [] $x+0xb8c/0xc88 [pcie] [ 43.214024] [] platform_drv_probe+0x20/0x58 [ 43.218483] [] really_probe+0xc4/0x22c [ 43.222510] [] __driver_attach+0xa0/0xa8 [ 43.226708] [] bus_for_each_dev+0x54/0x98 [ 43.231000] [] driver_attach+0x1c/0x28 [ 43.235024] [] bus_add_driver+0x14c/0x204 [ 43.239309] [] driver_register+0x64/0x130 [ 43.243598] [] __platform_driver_register+0x5c/0x68 [ 43.248757] [] platform_driver_probe+0x28/0xac [ 43.253485] [] pcie_init+0x30/0x3c [pcie] [ 43.258293] [] do_one_initcall+0x88/0x19c [ 43.262585] [] load_module+0xc2c/0xf2c [ 43.266609] [] SyS_finit_module+0x78/0x88 [ 43.270897] ---[ end trace ea5eb60837afb5aa ]--- Reported-by: Zhang Jukuo Tested-by: Zhang Jukuo Signed-off-by: Yijing Wang --- arch/x86/pci/xen.c | 4 ++++ drivers/pci/msi.c | 5 +++++ 2 files changed, 9 insertions(+), 0 deletions(-) diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index c489ef2..34fc418 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -298,12 +298,16 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) map_irq.entry_nr = nvec; } else if (type == PCI_CAP_ID_MSIX) { int pos; + unsigned long flags; u32 table_offset, bir; pos = dev->msix_cap; pci_read_config_dword(dev, pos + PCI_MSIX_TABLE, &table_offset); bir = (u8)(table_offset & PCI_MSIX_TABLE_BIR); + flags = pci_resource_flags(dev, bir); + if (!flags || (flags & IORESOURCE_UNSET)) + return -EINVAL; map_irq.table_base = pci_resource_start(dev, bir); map_irq.entry_nr = msidesc->msi_attrib.entry_nr; diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index fd60806..c3e7dfc 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -694,11 +694,16 @@ static void __iomem *msix_map_region(struct pci_dev *dev, unsigned nr_entries) { resource_size_t phys_addr; u32 table_offset; + unsigned long flags; u8 bir; pci_read_config_dword(dev, dev->msix_cap + PCI_MSIX_TABLE, &table_offset); bir = (u8)(table_offset & PCI_MSIX_TABLE_BIR); + flags = pci_resource_flags(dev, bir); + if (!flags || (flags & IORESOURCE_UNSET)) + return NULL; + table_offset &= PCI_MSIX_TABLE_OFFSET; phys_addr = pci_resource_start(dev, bir) + table_offset;