From patchwork Thu Aug 4 13:06:29 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avi Kivity X-Patchwork-Id: 108476 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 0743AB6F6F for ; Thu, 4 Aug 2011 23:58:51 +1000 (EST) Received: from localhost ([::1]:49461 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Qoxff-00051c-Uh for incoming@patchwork.ozlabs.org; Thu, 04 Aug 2011 09:09:07 -0400 Received: from eggs.gnu.org ([140.186.70.92]:45268) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QoxdU-0000ou-Th for qemu-devel@nongnu.org; Thu, 04 Aug 2011 09:07:01 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QoxdM-0007Qi-Ap for qemu-devel@nongnu.org; Thu, 04 Aug 2011 09:06:52 -0400 Received: from mx1.redhat.com ([209.132.183.28]:64947) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QoxdL-0007Om-MM for qemu-devel@nongnu.org; Thu, 04 Aug 2011 09:06:44 -0400 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p74D6gUF022529 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 4 Aug 2011 09:06:42 -0400 Received: from cleopatra.tlv.redhat.com (cleopatra.tlv.redhat.com [10.35.255.11]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id p74D6d4V012288; Thu, 4 Aug 2011 09:06:41 -0400 Received: from s01.tlv.redhat.com (s01.tlv.redhat.com [10.35.255.8]) by cleopatra.tlv.redhat.com (Postfix) with ESMTP id 4F58F250B5A; Thu, 4 Aug 2011 16:06:38 +0300 (IDT) From: Avi Kivity To: Anthony Liguori , qemu-devel@nongnu.org Date: Thu, 4 Aug 2011 16:06:29 +0300 Message-Id: <1312463195-13605-34-git-send-email-avi@redhat.com> In-Reply-To: <1312463195-13605-1-git-send-email-avi@redhat.com> References: <1312463195-13605-1-git-send-email-avi@redhat.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.132.183.28 Cc: kvm@vger.kernel.org, "Michael S. Tsirkin" Subject: [Qemu-devel] [PATCH v3 33/39] msix: convert to memory API X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org The msix table is defined as a subregion, to allow for a BAR that mixes device specific regions with the msix table. Reviewed-by: Richard Henderson Signed-off-by: Avi Kivity --- hw/ivshmem.c | 11 +++++---- hw/msix.c | 64 +++++++++++++++++++------------------------------------ hw/msix.h | 6 +--- hw/pci.h | 2 +- hw/virtio-pci.c | 16 ++++++++----- hw/virtio-pci.h | 1 + 6 files changed, 42 insertions(+), 58 deletions(-) diff --git a/hw/ivshmem.c b/hw/ivshmem.c index f80e7b6..bacba60 100644 --- a/hw/ivshmem.c +++ b/hw/ivshmem.c @@ -65,6 +65,7 @@ typedef struct IVShmemState { */ MemoryRegion bar; MemoryRegion ivshmem; + MemoryRegion msix_bar; uint64_t ivshmem_size; /* size of shared memory region */ int shm_fd; /* shared memory file descriptor */ @@ -540,11 +541,11 @@ static void ivshmem_setup_msi(IVShmemState * s) { /* allocate the MSI-X vectors */ - if (!msix_init(&s->dev, s->vectors, 1, 0)) { - pci_register_bar(&s->dev, 1, - msix_bar_size(&s->dev), - PCI_BASE_ADDRESS_SPACE_MEMORY, - msix_mmio_map); + memory_region_init(&s->msix_bar, "ivshmem-msix", 4096); + if (!msix_init(&s->dev, s->vectors, &s->msix_bar, 1, 0)) { + pci_register_bar_region(&s->dev, 1, + PCI_BASE_ADDRESS_SPACE_MEMORY, + &s->msix_bar); IVSHMEM_DPRINTF("msix initialized (%d vectors)\n", s->vectors); } else { IVSHMEM_DPRINTF("msix initialization failed\n"); diff --git a/hw/msix.c b/hw/msix.c index e67e700..8536c3f 100644 --- a/hw/msix.c +++ b/hw/msix.c @@ -82,7 +82,8 @@ static int msix_add_config(struct PCIDevice *pdev, unsigned short nentries, return 0; } -static uint32_t msix_mmio_readl(void *opaque, target_phys_addr_t addr) +static uint64_t msix_mmio_read(void *opaque, target_phys_addr_t addr, + unsigned size) { PCIDevice *dev = opaque; unsigned int offset = addr & (MSIX_PAGE_SIZE - 1) & ~0x3; @@ -91,12 +92,6 @@ static uint32_t msix_mmio_readl(void *opaque, target_phys_addr_t addr) return pci_get_long(page + offset); } -static uint32_t msix_mmio_read_unallowed(void *opaque, target_phys_addr_t addr) -{ - fprintf(stderr, "MSI-X: only dword read is allowed!\n"); - return 0; -} - static uint8_t msix_pending_mask(int vector) { return 1 << (vector % 8); @@ -169,8 +164,8 @@ void msix_write_config(PCIDevice *dev, uint32_t addr, } } -static void msix_mmio_writel(void *opaque, target_phys_addr_t addr, - uint32_t val) +static void msix_mmio_write(void *opaque, target_phys_addr_t addr, + uint64_t val, unsigned size) { PCIDevice *dev = opaque; unsigned int offset = addr & (MSIX_PAGE_SIZE - 1) & ~0x3; @@ -179,37 +174,25 @@ static void msix_mmio_writel(void *opaque, target_phys_addr_t addr, msix_handle_mask_update(dev, vector); } -static void msix_mmio_write_unallowed(void *opaque, target_phys_addr_t addr, - uint32_t val) -{ - fprintf(stderr, "MSI-X: only dword write is allowed!\n"); -} - -static CPUWriteMemoryFunc * const msix_mmio_write[] = { - msix_mmio_write_unallowed, msix_mmio_write_unallowed, msix_mmio_writel -}; - -static CPUReadMemoryFunc * const msix_mmio_read[] = { - msix_mmio_read_unallowed, msix_mmio_read_unallowed, msix_mmio_readl +static const MemoryRegionOps msix_mmio_ops = { + .read = msix_mmio_read, + .write = msix_mmio_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + }, }; -/* Should be called from device's map method. */ -void msix_mmio_map(PCIDevice *d, int region_num, - pcibus_t addr, pcibus_t size, int type) +static void msix_mmio_setup(PCIDevice *d, MemoryRegion *bar) { uint8_t *config = d->config + d->msix_cap; uint32_t table = pci_get_long(config + PCI_MSIX_TABLE); uint32_t offset = table & ~(MSIX_PAGE_SIZE - 1); /* TODO: for assigned devices, we'll want to make it possible to map * pending bits separately in case they are in a separate bar. */ - int table_bir = table & PCI_MSIX_FLAGS_BIRMASK; - if (table_bir != region_num) - return; - if (size <= offset) - return; - cpu_register_physical_memory(addr + offset, size - offset, - d->msix_mmio_index); + memory_region_add_subregion(bar, offset, &d->msix_mmio); } static void msix_mask_all(struct PCIDevice *dev, unsigned nentries) @@ -225,6 +208,7 @@ static void msix_mask_all(struct PCIDevice *dev, unsigned nentries) /* Initialize the MSI-X structures. Note: if MSI-X is supported, BAR size is * modified, it should be retrieved with msix_bar_size. */ int msix_init(struct PCIDevice *dev, unsigned short nentries, + MemoryRegion *bar, unsigned bar_nr, unsigned bar_size) { int ret; @@ -241,13 +225,8 @@ int msix_init(struct PCIDevice *dev, unsigned short nentries, dev->msix_table_page = qemu_mallocz(MSIX_PAGE_SIZE); msix_mask_all(dev, nentries); - dev->msix_mmio_index = cpu_register_io_memory(msix_mmio_read, - msix_mmio_write, dev, - DEVICE_NATIVE_ENDIAN); - if (dev->msix_mmio_index == -1) { - ret = -EBUSY; - goto err_index; - } + memory_region_init_io(&dev->msix_mmio, &msix_mmio_ops, dev, + "msix", MSIX_PAGE_SIZE); dev->msix_entries_nr = nentries; ret = msix_add_config(dev, nentries, bar_nr, bar_size); @@ -255,12 +234,12 @@ int msix_init(struct PCIDevice *dev, unsigned short nentries, goto err_config; dev->cap_present |= QEMU_PCI_CAP_MSIX; + msix_mmio_setup(dev, bar); return 0; err_config: dev->msix_entries_nr = 0; - cpu_unregister_io_memory(dev->msix_mmio_index); -err_index: + memory_region_destroy(&dev->msix_mmio); qemu_free(dev->msix_table_page); dev->msix_table_page = NULL; qemu_free(dev->msix_entry_used); @@ -279,7 +258,7 @@ static void msix_free_irq_entries(PCIDevice *dev) } /* Clean up resources for the device. */ -int msix_uninit(PCIDevice *dev) +int msix_uninit(PCIDevice *dev, MemoryRegion *bar) { if (!(dev->cap_present & QEMU_PCI_CAP_MSIX)) return 0; @@ -287,7 +266,8 @@ int msix_uninit(PCIDevice *dev) dev->msix_cap = 0; msix_free_irq_entries(dev); dev->msix_entries_nr = 0; - cpu_unregister_io_memory(dev->msix_mmio_index); + memory_region_del_subregion(bar, &dev->msix_mmio); + memory_region_destroy(&dev->msix_mmio); qemu_free(dev->msix_table_page); dev->msix_table_page = NULL; qemu_free(dev->msix_entry_used); diff --git a/hw/msix.h b/hw/msix.h index a9f7993..7e04336 100644 --- a/hw/msix.h +++ b/hw/msix.h @@ -5,15 +5,13 @@ #include "pci.h" int msix_init(PCIDevice *pdev, unsigned short nentries, + MemoryRegion *bar, unsigned bar_nr, unsigned bar_size); void msix_write_config(PCIDevice *pci_dev, uint32_t address, uint32_t val, int len); -void msix_mmio_map(PCIDevice *pci_dev, int region_num, - pcibus_t addr, pcibus_t size, int type); - -int msix_uninit(PCIDevice *d); +int msix_uninit(PCIDevice *d, MemoryRegion *bar); void msix_save(PCIDevice *dev, QEMUFile *f); void msix_load(PCIDevice *dev, QEMUFile *f); diff --git a/hw/pci.h b/hw/pci.h index 928e96c..a95e2ad 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -176,7 +176,7 @@ struct PCIDevice { /* Space to store MSIX table */ uint8_t *msix_table_page; /* MMIO index used to map MSIX table and pending bit entries. */ - int msix_mmio_index; + MemoryRegion msix_mmio; /* Reference-count for entries actually in use by driver. */ unsigned *msix_entry_used; /* Region including the MSI-X table */ diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index 5d4c1be..86f2200 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -645,11 +645,12 @@ void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev) pci_set_word(config + 0x2e, vdev->device_id); config[0x3d] = 1; - if (vdev->nvectors && !msix_init(&proxy->pci_dev, vdev->nvectors, 1, 0)) { - pci_register_bar(&proxy->pci_dev, 1, - msix_bar_size(&proxy->pci_dev), - PCI_BASE_ADDRESS_SPACE_MEMORY, - msix_mmio_map); + memory_region_init(&proxy->msix_bar, "virtio-msix", 4096); + if (vdev->nvectors && !msix_init(&proxy->pci_dev, vdev->nvectors, + &proxy->msix_bar, 1, 0)) { + pci_register_bar_region(&proxy->pci_dev, 1, + PCI_BASE_ADDRESS_SPACE_MEMORY, + &proxy->msix_bar); } else vdev->nvectors = 0; @@ -702,9 +703,12 @@ static int virtio_blk_init_pci(PCIDevice *pci_dev) static int virtio_exit_pci(PCIDevice *pci_dev) { VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); + int r; memory_region_destroy(&proxy->bar); - return msix_uninit(pci_dev); + r = msix_uninit(pci_dev, &proxy->msix_bar); + memory_region_destroy(&proxy->msix_bar); + return r; } static int virtio_blk_exit_pci(PCIDevice *pci_dev) diff --git a/hw/virtio-pci.h b/hw/virtio-pci.h index 5af1c8c..14c10f7 100644 --- a/hw/virtio-pci.h +++ b/hw/virtio-pci.h @@ -22,6 +22,7 @@ typedef struct { PCIDevice pci_dev; VirtIODevice *vdev; MemoryRegion bar; + MemoryRegion msix_bar; uint32_t flags; uint32_t class_code; uint32_t nvectors;