From patchwork Fri Nov 12 17:47:21 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Williamson X-Patchwork-Id: 71001 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 3DED9B7115 for ; Sat, 13 Nov 2010 04:58:39 +1100 (EST) Received: from localhost ([127.0.0.1]:53310 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PGxtO-0001wY-7t for incoming@patchwork.ozlabs.org; Fri, 12 Nov 2010 12:58:30 -0500 Received: from [140.186.70.92] (port=37902 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PGxif-0005Ix-FM for qemu-devel@nongnu.org; Fri, 12 Nov 2010 12:47:26 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PGxie-0004rV-4M for qemu-devel@nongnu.org; Fri, 12 Nov 2010 12:47:25 -0500 Received: from mx1.redhat.com ([209.132.183.28]:24376) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PGxid-0004rR-Se for qemu-devel@nongnu.org; Fri, 12 Nov 2010 12:47:24 -0500 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 (8.13.8/8.13.8) with ESMTP id oACHlMig023245 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 12 Nov 2010 12:47:23 -0500 Received: from s20.home (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id oACHlLBD005783; Fri, 12 Nov 2010 12:47:22 -0500 From: Alex Williamson To: kvm@vger.kernel.org, mst@redhat.com Date: Fri, 12 Nov 2010 10:47:21 -0700 Message-ID: <20101112174716.3169.64085.stgit@s20.home> In-Reply-To: <20101112173929.3169.47618.stgit@s20.home> References: <20101112173929.3169.47618.stgit@s20.home> User-Agent: StGIT/0.14.3 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. Cc: chrisw@redhat.com, alex.williamson@redhat.com, qemu-devel@nongnu.org Subject: [Qemu-devel] [PATCH v2 9/9] pci: Store capability offsets in PCIDevice X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This not only makes pci_find_capability a directly lookup, but also allows us to better track added capabilities and avoids the proliferation of random additional capability offset markers. Signed-off-by: Alex Williamson --- hw/msix.c | 15 +++++++-------- hw/pci.c | 20 ++++++++++++++++++-- hw/pci.h | 5 +++-- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/hw/msix.c b/hw/msix.c index b98b34a..060f27b 100644 --- a/hw/msix.c +++ b/hw/msix.c @@ -204,7 +204,6 @@ static int msix_add_config(struct PCIDevice *pdev, unsigned short nentries, pci_set_long(config + MSIX_PBA_OFFSET, (bar_size + MSIX_PAGE_PENDING) | bar_nr); } - pdev->msix_cap = config_offset; /* Make flags bit writeable. */ pdev->wmask[config_offset + MSIX_CONTROL_OFFSET] |= MSIX_ENABLE_MASK | MSIX_MASKALL_MASK; @@ -253,7 +252,8 @@ static void msix_clr_pending(PCIDevice *dev, int vector) static int msix_function_masked(PCIDevice *dev) { - return dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] & MSIX_MASKALL_MASK; + return dev->config[dev->caps[PCI_CAP_ID_MSIX] + + MSIX_CONTROL_OFFSET] & MSIX_MASKALL_MASK; } static int msix_is_masked(PCIDevice *dev, int vector) @@ -275,7 +275,7 @@ static void msix_handle_mask_update(PCIDevice *dev, int vector) void msix_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int len) { - unsigned enable_pos = dev->msix_cap + MSIX_CONTROL_OFFSET; + unsigned enable_pos = dev->caps[PCI_CAP_ID_MSIX] + MSIX_CONTROL_OFFSET; int vector; if (!range_covers_byte(addr, len, enable_pos)) { @@ -334,7 +334,7 @@ static CPUReadMemoryFunc * const msix_mmio_read[] = { void msix_mmio_map(PCIDevice *d, int region_num, pcibus_t addr, pcibus_t size, int type) { - uint8_t *config = d->config + d->msix_cap; + uint8_t *config = d->config + d->caps[PCI_CAP_ID_MSIX]; uint32_t table = pci_get_long(config + MSIX_TABLE_OFFSET); uint32_t offset = table & ~(MSIX_PAGE_SIZE - 1); /* TODO: for assigned devices, we'll want to make it possible to map @@ -437,7 +437,6 @@ int msix_uninit(PCIDevice *dev) if (!(dev->cap_present & QEMU_PCI_CAP_MSIX)) return 0; pci_del_capability(dev, PCI_CAP_ID_MSIX, MSIX_CAP_LENGTH); - dev->msix_cap = 0; msix_free_irq_entries(dev); dev->msix_entries_nr = 0; cpu_unregister_io_memory(dev->msix_mmio_index); @@ -493,7 +492,7 @@ int msix_present(PCIDevice *dev) int msix_enabled(PCIDevice *dev) { return (dev->cap_present & QEMU_PCI_CAP_MSIX) && - (dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] & + (dev->config[dev->caps[PCI_CAP_ID_MSIX] + MSIX_CONTROL_OFFSET] & MSIX_ENABLE_MASK); } @@ -534,8 +533,8 @@ void msix_reset(PCIDevice *dev) if (!(dev->cap_present & QEMU_PCI_CAP_MSIX)) return; msix_free_irq_entries(dev); - dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] &= - ~dev->wmask[dev->msix_cap + MSIX_CONTROL_OFFSET]; + dev->config[dev->caps[PCI_CAP_ID_MSIX] + MSIX_CONTROL_OFFSET] &= + ~dev->wmask[dev->caps[PCI_CAP_ID_MSIX] + MSIX_CONTROL_OFFSET]; memset(dev->msix_table_page, 0, MSIX_PAGE_SIZE); msix_mask_all(dev, dev->msix_entries_nr); } diff --git a/hw/pci.c b/hw/pci.c index bc25be7..773afa5 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -1990,15 +1990,24 @@ int pci_add_capability_at_offset(PCIDevice *pdev, uint8_t cap_id, { uint8_t i, *config = pdev->config + offset; + /* Check overlap with existing capabilities, valid cap, already added */ for (i = 0; i < size; i++) { if (pdev->config_map[offset + i]) { return -EFAULT; } } + if (!cap_id || cap_id > PCI_CAP_ID_MAX) { + return -EINVAL; + } + + if (pdev->caps[cap_id]) { + return -EFAULT; + } + config[PCI_CAP_LIST_ID] = cap_id; config[PCI_CAP_LIST_NEXT] = pdev->config[PCI_CAPABILITY_LIST]; - pdev->config[PCI_CAPABILITY_LIST] = offset; + pdev->caps[cap_id] = pdev->config[PCI_CAPABILITY_LIST] = offset; memset(pdev->config_map + offset, cap_id, size); /* Make capability read-only by default */ memset(pdev->wmask + offset, 0, size); @@ -2033,6 +2042,7 @@ void pci_del_capability(PCIDevice *pdev, uint8_t cap_id, uint8_t size) /* Clear cmask as device-specific registers can't be checked */ memset(pdev->cmask + offset, 0, size); memset(pdev->config_map + offset, 0, size); + pdev->caps[cap_id] = 0; if (!pdev->config[PCI_CAPABILITY_LIST]) { pdev->config[PCI_STATUS] &= ~PCI_STATUS_CAP_LIST; @@ -2041,7 +2051,13 @@ void pci_del_capability(PCIDevice *pdev, uint8_t cap_id, uint8_t size) uint8_t pci_find_capability(PCIDevice *pdev, uint8_t cap_id) { - return pci_find_capability_list(pdev, cap_id, NULL); + if (cap_id == PCI_CAP_ID_BASIC) { + return 0; + } + if (cap_id && cap_id <= PCI_CAP_ID_MAX) { + return pdev->caps[cap_id]; + } + return 0xff; } static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent) diff --git a/hw/pci.h b/hw/pci.h index cea1c3a..b4c19ba 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -110,6 +110,7 @@ typedef struct PCIIORegion { #define PCI_NUM_PINS 4 /* A-D */ #define PCI_CAP_ID_BASIC 0xff +#define PCI_CAP_ID_MAX PCI_CAP_ID_AF /* Bits in cap_present field. */ enum { @@ -170,8 +171,8 @@ struct PCIDevice { /* Capability bits */ uint32_t cap_present; - /* Offset of MSI-X capability in config space */ - uint8_t msix_cap; + /* Offset capabilities in config space */ + uint8_t caps[PCI_CAP_ID_MAX + 1]; /* MSI-X entries */ int msix_entries_nr;