From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1M8DOM-0001T4-3U for qemu-devel@nongnu.org; Sun, 24 May 2009 09:05:30 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1M8DOG-0001PN-Vd for qemu-devel@nongnu.org; Sun, 24 May 2009 09:05:29 -0400 Received: from [199.232.76.173] (port=33931 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1M8DDo-0005b1-TN for qemu-devel@nongnu.org; Sun, 24 May 2009 08:54:37 -0400 Received: from mx2.redhat.com ([66.187.237.31]:49168) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1M8A1T-00014D-A8 for qemu-devel@nongnu.org; Sun, 24 May 2009 05:29:39 -0400 Received: from int-mx2.corp.redhat.com (int-mx2.corp.redhat.com [172.16.27.26]) by mx2.redhat.com (8.13.8/8.13.8) with ESMTP id n4O9TcfN008275 for ; Sun, 24 May 2009 05:29:38 -0400 From: Avi Kivity Date: Sun, 24 May 2009 12:29:34 +0300 Message-Id: <1243157375-14329-3-git-send-email-avi@redhat.com> In-Reply-To: <1243157375-14329-1-git-send-email-avi@redhat.com> References: <1243157375-14329-1-git-send-email-avi@redhat.com> Subject: [Qemu-devel] [PATCH 2/3] Add PCI memory region registration List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org A registered PCI memory region will be automatically mapped and unmapped as the associated BAR is manipulated. Signed-off-by: Avi Kivity --- hw/pci.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- hw/pci.h | 26 ++++++++++++++++++++ 2 files changed, 103 insertions(+), 1 deletions(-) diff --git a/hw/pci.c b/hw/pci.c index ee7d403..4c5323a 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -286,6 +286,9 @@ static void pci_unregister_io_regions(PCIDevice *pci_dev) for(i = 0; i < PCI_NUM_REGIONS; i++) { r = &pci_dev->io_regions[i]; + while (!LIST_EMPTY(&r->components)) { + pci_unregister_physical_memory(pci_dev, i, LIST_FIRST(&r->components)); + } if (!r->size || r->addr == -1) continue; if (r->type == PCI_ADDRESS_SPACE_IO) { @@ -343,11 +346,77 @@ void pci_register_io_region(PCIDevice *pci_dev, int region_num, addr = 0x10 + region_num * 4; } *(uint32_t *)(pci_dev->config + addr) = cpu_to_le32(type); + LIST_INIT(&r->components); +} + +PCIIORegionComponent *pci_register_physical_memory(PCIDevice *pci_dev, + int region_num, + target_phys_addr_t size, + ram_addr_t ram_addr) +{ + return pci_register_physical_memory_offset(pci_dev, region_num, 0, size, + ram_addr, 0); +} + +static void pci_region_instantiate(PCIIORegionComponent *pci_mem, + uint32_t old_addr, uint32_t new_addr) +{ + if (new_addr == old_addr) { + return; + } + + if (old_addr != -1) { + physical_memory_region_unregister(pci_mem->pmr); + pci_mem->pmr = NULL; + } + + if (new_addr != -1) { + pci_mem->pmr = physical_memory_region_register_offset( + new_addr + pci_mem->offset, + pci_mem->size, + pci_mem->ram_addr, + pci_mem->region_offset); + } +} + +PCIIORegionComponent *pci_register_physical_memory_offset( + PCIDevice *pci_dev, + int region_num, + target_phys_addr_t offset, + target_phys_addr_t size, + ram_addr_t ram_addr, + ram_addr_t region_offset) +{ + PCIIORegionComponent *pci_mem = (PCIIORegionComponent *)qemu_malloc(sizeof(*pci_mem)); + PCIIORegion *r = &pci_dev->io_regions[region_num]; + + pci_mem->offset = offset; + pci_mem->size = size; + pci_mem->ram_addr = ram_addr; + pci_mem->region_offset = region_offset; + pci_mem->pmr = NULL; + LIST_INSERT_HEAD(&r->components, pci_mem, link); + + pci_region_instantiate(pci_mem, -1, r->addr); + + return pci_mem; +} + +void pci_unregister_physical_memory(PCIDevice *pci_dev, + int region_num, + PCIIORegionComponent *pci_mem) +{ + PCIIORegion *r = &pci_dev->io_regions[region_num]; + + pci_region_instantiate(pci_mem, r->addr, -1); + LIST_REMOVE(pci_mem, link); + qemu_free(pci_mem); } static void pci_update_mappings(PCIDevice *d) { PCIIORegion *r; + PCIIORegionComponent *pci_mem; int cmd, i; uint32_t last_addr, new_addr, config_ofs; @@ -396,6 +465,11 @@ static void pci_update_mappings(PCIDevice *d) new_addr = -1; } } + + LIST_FOREACH(pci_mem, &r->components, link) { + pci_region_instantiate(pci_mem, r->addr, new_addr); + } + /* now do the real mapping */ if (new_addr != r->addr) { if (r->addr != -1) { @@ -418,7 +492,9 @@ static void pci_update_mappings(PCIDevice *d) } r->addr = new_addr; if (r->addr != -1) { - r->map_func(d, i, r->addr, r->size, r->type); + if (r->map_func) { + r->map_func(d, i, r->addr, r->size, r->type); + } } } } diff --git a/hw/pci.h b/hw/pci.h index ff858a1..b27e8fd 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -2,6 +2,7 @@ #define QEMU_PCI_H #include "qemu-common.h" +#include "sys-queue.h" /* PCI includes legacy ISA access. */ #include "isa.h" @@ -80,11 +81,21 @@ typedef int PCIUnregisterFunc(PCIDevice *pci_dev); #define PCI_ADDRESS_SPACE_IO 0x01 #define PCI_ADDRESS_SPACE_MEM_PREFETCH 0x08 +typedef struct PCIIORegionComponent { + PhysicalMemoryRegion *pmr; + target_phys_addr_t offset; + target_phys_addr_t size; + ram_addr_t ram_addr; + ram_addr_t region_offset; + LIST_ENTRY(PCIIORegionComponent) link; +} PCIIORegionComponent; + typedef struct PCIIORegion { uint32_t addr; /* current PCI mapping address. -1 means not mapped */ uint32_t size; uint8_t type; PCIMapIORegionFunc *map_func; + LIST_HEAD(pci_region_list, PCIIORegionComponent) components; } PCIIORegion; #define PCI_ROM_SLOT 6 @@ -171,6 +182,21 @@ void pci_register_io_region(PCIDevice *pci_dev, int region_num, uint32_t size, int type, PCIMapIORegionFunc *map_func); +PCIIORegionComponent *pci_register_physical_memory(PCIDevice *pci_dev, + int region_num, + target_phys_addr_t size, + ram_addr_t ram_addr); +PCIIORegionComponent *pci_register_physical_memory_offset( + PCIDevice *pci_dev, + int region_num, + target_phys_addr_t offset, + target_phys_addr_t size, + ram_addr_t ram_addr, + ram_addr_t region_offset); +void pci_unregister_physical_memory(PCIDevice *pci_dev, + int region_num, + PCIIORegionComponent *pci_mem); + uint32_t pci_default_read_config(PCIDevice *d, uint32_t address, int len); void pci_default_write_config(PCIDevice *d, -- 1.6.0.6