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: 320352 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id oACHlRJu020371 for ; Fri, 12 Nov 2010 17:47:27 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755400Ab0KLRrY (ORCPT ); Fri, 12 Nov 2010 12:47:24 -0500 Received: from mx1.redhat.com ([209.132.183.28]:51768 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752967Ab0KLRrY (ORCPT ); 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 Subject: [PATCH v2 9/9] pci: Store capability offsets in PCIDevice To: kvm@vger.kernel.org, mst@redhat.com Cc: qemu-devel@nongnu.org, alex.williamson@redhat.com, chrisw@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 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Fri, 12 Nov 2010 17:47:28 +0000 (UTC) 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;