From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:48932) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z11Jx-0007DF-FX for qemu-devel@nongnu.org; Fri, 05 Jun 2015 19:46:42 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Z11Jw-0000ei-ET for qemu-devel@nongnu.org; Fri, 05 Jun 2015 19:46:41 -0400 Received: from mx1.redhat.com ([209.132.183.28]:59169) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z11Jw-0000eY-6u for qemu-devel@nongnu.org; Fri, 05 Jun 2015 19:46:40 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (Postfix) with ESMTPS id CAB303500EA for ; Fri, 5 Jun 2015 23:46:39 +0000 (UTC) From: Laszlo Ersek Date: Sat, 6 Jun 2015 01:46:28 +0200 Message-Id: <1433547989-7238-4-git-send-email-lersek@redhat.com> In-Reply-To: <1433547989-7238-1-git-send-email-lersek@redhat.com> References: <5572347E.1030105@redhat.com> <1433547989-7238-1-git-send-email-lersek@redhat.com> Subject: [Qemu-devel] [PATCH 3/4] hw/pci: allow the caller of pci_bar_address() to ignore command register List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org, lersek@redhat.com Cc: Marcel Apfelbaum , "Michael S. Tsirkin" The pci_bar_address() function calculates the start address of a given PCI BAR. Its main purpose is supporting MemoryRegion mapping / unmapping in pci_update_mappings(), which is guest-observable. For that reason it contains heavy logic to enforce the validity of the BAR, and this logic includes checks for the PCI command register: - If the PCI_COMMAND_IO bit is clear in the command register, then all IO space BARs will be reported unmapped (all bits one), - If the PCI_COMMAND_MEMORY bit is clear in the command register, then all MMIO space BARs will be reported unmapped (all bits one). For an upcoming use case, we'd like pci_bar_address() to calculate the BAR address from the config space *regardless* of the command register. Add a new parameter that allows the caller to cut out the command register verification. All current callers preserve their behaviors. Cc: Marcel Apfelbaum Cc: Michael S. Tsirkin Signed-off-by: Laszlo Ersek --- include/hw/pci/pci.h | 2 ++ hw/pci/pci.c | 18 +++++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index d44bc84..16b467b 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -314,6 +314,8 @@ void pci_register_vga(PCIDevice *pci_dev, MemoryRegion *mem, MemoryRegion *io_lo, MemoryRegion *io_hi); void pci_unregister_vga(PCIDevice *pci_dev); pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num); +pcibus_t pci_bar_address(PCIDevice *d, int reg, uint8_t type, pcibus_t size, + bool respect_command); int pci_add_capability(PCIDevice *pdev, uint8_t cap_id, uint8_t offset, uint8_t size); diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 750f3da..61a70de 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -1054,15 +1054,19 @@ pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num) return pci_dev->io_regions[region_num].addr; } -static pcibus_t pci_bar_address(PCIDevice *d, - int reg, uint8_t type, pcibus_t size) +pcibus_t pci_bar_address(PCIDevice *d, int reg, uint8_t type, pcibus_t size, + bool respect_command) { pcibus_t new_addr, last_addr; int bar = pci_bar(d, reg); - uint16_t cmd = pci_get_word(d->config + PCI_COMMAND); + uint16_t cmd; + + if (respect_command) { + cmd = pci_get_word(d->config + PCI_COMMAND); + } if (type & PCI_BASE_ADDRESS_SPACE_IO) { - if (!(cmd & PCI_COMMAND_IO)) { + if (respect_command && !(cmd & PCI_COMMAND_IO)) { return PCI_BAR_UNMAPPED; } new_addr = pci_get_long(d->config + bar) & ~(size - 1); @@ -1076,7 +1080,7 @@ static pcibus_t pci_bar_address(PCIDevice *d, return new_addr; } - if (!(cmd & PCI_COMMAND_MEMORY)) { + if (respect_command && !(cmd & PCI_COMMAND_MEMORY)) { return PCI_BAR_UNMAPPED; } if (type & PCI_BASE_ADDRESS_MEM_TYPE_64) { @@ -1134,7 +1138,7 @@ static void pci_update_mappings(PCIDevice *d) if (!r->size) continue; - new_addr = pci_bar_address(d, i, r->type, r->size); + new_addr = pci_bar_address(d, i, r->type, r->size, true); /* This bar isn't changed */ if (new_addr == r->addr) @@ -2427,7 +2431,7 @@ static void pci_dev_get_w64(PCIBus *b, PCIDevice *dev, void *opaque) !(r->type & PCI_BASE_ADDRESS_MEM_TYPE_64)) { continue; } - region_range.begin = pci_bar_address(dev, i, r->type, r->size); + region_range.begin = pci_bar_address(dev, i, r->type, r->size, true); region_range.end = region_range.begin + r->size; if (region_range.begin == PCI_BAR_UNMAPPED) { -- 1.8.3.1