From patchwork Mon Mar 6 20:06:23 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Gordeev X-Patchwork-Id: 9607529 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 683E0601D2 for ; Mon, 6 Mar 2017 20:17:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4DD5027C2D for ; Mon, 6 Mar 2017 20:17:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 42775282ED; Mon, 6 Mar 2017 20:17:15 +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=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BE5AC27C2D for ; Mon, 6 Mar 2017 20:17:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753672AbdCFURO (ORCPT ); Mon, 6 Mar 2017 15:17:14 -0500 Received: from mx1.redhat.com ([209.132.183.28]:56116 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932086AbdCFURN (ORCPT ); Mon, 6 Mar 2017 15:17:13 -0500 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D6FA8C0467CA for ; Mon, 6 Mar 2017 20:06:26 +0000 (UTC) Received: from dhcp-27-118.brq.redhat.com (dhcp-27-122.brq.redhat.com [10.34.27.122]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v26K6NWv006737 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 6 Mar 2017 15:06:25 -0500 Date: Mon, 6 Mar 2017 21:06:23 +0100 From: Alexander Gordeev To: kvm@vger.kernel.org Cc: Thomas Huth , Andrew Jones , Peter Xu Subject: [kvm-unit-tests PATCH v4 6/5] pci: Add BAR sanity checks Message-ID: <20170306200622.GA27507@dhcp-27-118.brq.redhat.com> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.21 (2010-09-15) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Mon, 06 Mar 2017 20:06:26 +0000 (UTC) Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Cc: Thomas Huth Cc: Andrew Jones Cc: Peter Xu Signed-off-by: Alexander Gordeev --- lib/pci.c | 54 ++++++++++++++++++++++++++++++++++++++++-------------- lib/pci.h | 21 +++++++++++++-------- 2 files changed, 53 insertions(+), 22 deletions(-) diff --git a/lib/pci.c b/lib/pci.c index daf398100b7e..98fc3849d297 100644 --- a/lib/pci.c +++ b/lib/pci.c @@ -110,13 +110,14 @@ uint32_t pci_bar_mask(uint32_t bar) PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK; } -uint32_t pci_bar_get(struct pci_dev *dev, int bar_num) +uint32_t pci_bar_get(struct pci_dev *dev, unsigned int bar_num) { - return pci_config_readl(dev->bdf, PCI_BASE_ADDRESS_0 + - bar_num * 4); + CHECK_BAR_NUM(bar_num); + + return pci_config_readl(dev->bdf, PCI_BASE_ADDRESS_0 + bar_num * 4); } -static phys_addr_t __pci_bar_get_addr(struct pci_dev *dev, int bar_num) +static phys_addr_t __pci_bar_get_addr(struct pci_dev *dev, unsigned int bar_num) { uint32_t bar = pci_bar_get(dev, bar_num); uint32_t mask = pci_bar_mask(bar); @@ -132,15 +133,26 @@ static phys_addr_t __pci_bar_get_addr(struct pci_dev *dev, int bar_num) return phys_addr; } -phys_addr_t pci_bar_get_addr(struct pci_dev *dev, int bar_num) +phys_addr_t pci_bar_get_addr(struct pci_dev *dev, unsigned int bar_num) { + CHECK_BAR_NUM(bar_num); + return dev->resource[bar_num]; } -void pci_bar_set_addr(struct pci_dev *dev, int bar_num, phys_addr_t addr) +void pci_bar_set_addr(struct pci_dev *dev, + unsigned int bar_num, phys_addr_t addr) { int off = PCI_BASE_ADDRESS_0 + bar_num * 4; + CHECK_BAR_NUM(bar_num); + assert(addr != INVALID_PHYS_ADDR); + assert(dev->resource[bar_num] != INVALID_PHYS_ADDR); + if (pci_bar_is64(dev, bar_num)) { + assert(bar_num + 1 < PCI_BAR_NUM); + assert(dev->resource[bar_num] == dev->resource[bar_num + 1]); + } + pci_config_writel(dev->bdf, off, (uint32_t)addr); dev->resource[bar_num] = addr; @@ -161,7 +173,7 @@ void pci_bar_set_addr(struct pci_dev *dev, int bar_num, phys_addr_t addr) * The following pci_bar_size_helper() and pci_bar_size() functions * implement the algorithm. */ -static uint32_t pci_bar_size_helper(struct pci_dev *dev, int bar_num) +static uint32_t pci_bar_size_helper(struct pci_dev *dev, unsigned int bar_num) { int off = PCI_BASE_ADDRESS_0 + bar_num * 4; uint16_t bdf = dev->bdf; @@ -175,10 +187,12 @@ static uint32_t pci_bar_size_helper(struct pci_dev *dev, int bar_num) return val; } -phys_addr_t pci_bar_size(struct pci_dev *dev, int bar_num) +phys_addr_t pci_bar_size(struct pci_dev *dev, unsigned int bar_num) { uint32_t bar, size; + CHECK_BAR_NUM(bar_num); + size = pci_bar_size_helper(dev, bar_num); if (!size) return 0; @@ -196,21 +210,31 @@ phys_addr_t pci_bar_size(struct pci_dev *dev, int bar_num) } } -bool pci_bar_is_memory(struct pci_dev *dev, int bar_num) +bool pci_bar_is_memory(struct pci_dev *dev, unsigned int bar_num) { - uint32_t bar = pci_bar_get(dev, bar_num); + uint32_t bar; + + CHECK_BAR_NUM(bar_num); + + bar = pci_bar_get(dev, bar_num); return !(bar & PCI_BASE_ADDRESS_SPACE_IO); } -bool pci_bar_is_valid(struct pci_dev *dev, int bar_num) +bool pci_bar_is_valid(struct pci_dev *dev, unsigned int bar_num) { + CHECK_BAR_NUM(bar_num); + return dev->resource[bar_num] != INVALID_PHYS_ADDR; } -bool pci_bar_is64(struct pci_dev *dev, int bar_num) +bool pci_bar_is64(struct pci_dev *dev, unsigned int bar_num) { - uint32_t bar = pci_bar_get(dev, bar_num); + uint32_t bar; + + CHECK_BAR_NUM(bar_num); + + bar = pci_bar_get(dev, bar_num); if (bar & PCI_BASE_ADDRESS_SPACE_IO) return false; @@ -219,11 +243,13 @@ bool pci_bar_is64(struct pci_dev *dev, int bar_num) PCI_BASE_ADDRESS_MEM_TYPE_64; } -void pci_bar_print(struct pci_dev *dev, int bar_num) +void pci_bar_print(struct pci_dev *dev, unsigned int bar_num) { phys_addr_t size, start, end; uint32_t bar; + CHECK_BAR_NUM(bar_num); + if (!pci_bar_is_valid(dev, bar_num)) return; diff --git a/lib/pci.h b/lib/pci.h index 03cc0a72d48d..c770def840da 100644 --- a/lib/pci.h +++ b/lib/pci.h @@ -18,6 +18,9 @@ enum { #define PCI_BAR_NUM 6 #define PCI_DEVFN_MAX 256 +#define CHECK_BAR_NUM(bar_num) \ + do { assert(bar_num < PCI_BAR_NUM); } while (0) + #define PCI_BDF_GET_DEVFN(x) ((x) & 0xff) #define PCI_BDF_GET_BUS(x) (((x) >> 8) & 0xff) @@ -54,15 +57,17 @@ extern pcidevaddr_t pci_find_dev(uint16_t vendor_id, uint16_t device_id); * It is expected the caller is aware of the device BAR layout and never * tries to address the middle of a 64-bit register. */ -extern phys_addr_t pci_bar_get_addr(struct pci_dev *dev, int bar_num); -extern void pci_bar_set_addr(struct pci_dev *dev, int bar_num, phys_addr_t addr); -extern phys_addr_t pci_bar_size(struct pci_dev *dev, int bar_num); -extern uint32_t pci_bar_get(struct pci_dev *dev, int bar_num); + +extern phys_addr_t pci_bar_get_addr(struct pci_dev *dev, unsigned int bar_num); +extern void pci_bar_set_addr(struct pci_dev *dev, unsigned int bar_num, + phys_addr_t addr); +extern phys_addr_t pci_bar_size(struct pci_dev *dev, unsigned int bar_num); +extern uint32_t pci_bar_get(struct pci_dev *dev, unsigned int bar_num); extern uint32_t pci_bar_mask(uint32_t bar); -extern bool pci_bar_is64(struct pci_dev *dev, int bar_num); -extern bool pci_bar_is_memory(struct pci_dev *dev, int bar_num); -extern bool pci_bar_is_valid(struct pci_dev *dev, int bar_num); -extern void pci_bar_print(struct pci_dev *dev, int bar_num); +extern bool pci_bar_is64(struct pci_dev *dev, unsigned int bar_num); +extern bool pci_bar_is_memory(struct pci_dev *dev, unsigned int bar_num); +extern bool pci_bar_is_valid(struct pci_dev *dev, unsigned int bar_num); +extern void pci_bar_print(struct pci_dev *dev, unsigned int bar_num); extern void pci_dev_print_id(struct pci_dev *dev); extern void pci_dev_print(struct pci_dev *dev); extern uint8_t pci_intx_line(struct pci_dev *dev);