From patchwork Fri Jun 5 10:23:55 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Michael S. Tsirkin" X-Patchwork-Id: 28179 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n55AR1dZ004101 for ; Fri, 5 Jun 2009 10:27:01 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752572AbZFEK05 (ORCPT ); Fri, 5 Jun 2009 06:26:57 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1752513AbZFEK04 (ORCPT ); Fri, 5 Jun 2009 06:26:56 -0400 Received: from mx2.redhat.com ([66.187.237.31]:42587 "EHLO mx2.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752547AbZFEK04 (ORCPT ); Fri, 5 Jun 2009 06:26:56 -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 n55AOpgA011037; Fri, 5 Jun 2009 06:24:51 -0400 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx2.corp.redhat.com (8.13.1/8.13.1) with ESMTP id n55AOnxc014356; Fri, 5 Jun 2009 06:24:50 -0400 Received: from redhat.com (vpn-6-22.tlv.redhat.com [10.35.6.22]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id n55AOk4H007443; Fri, 5 Jun 2009 06:24:47 -0400 Date: Fri, 5 Jun 2009 13:23:55 +0300 From: "Michael S. Tsirkin" To: Paul Brook , Avi Kivity , qemu-devel@nongnu.org, Carsten Otte , kvm@vger.kernel.org, Rusty Russell , virtualization@lists.linux-foundation.org, Christian Borntraeger , Blue Swirl , Anthony Liguori Subject: [PATCHv3 08/13] qemu: add support for resizing regions Message-ID: <20090605102355.GI26770@redhat.com> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.18 (2008-05-17) X-Scanned-By: MIMEDefang 2.58 on 172.16.27.26 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Make it possible to resize PCI regions. This will be used by virtio with MSI-X, where the region size depends on whether MSI-X is enabled, and can change across load/save. Signed-off-by: Michael S. Tsirkin --- hw/pci.c | 54 ++++++++++++++++++++++++++++++++++++------------------ hw/pci.h | 3 +++ 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/hw/pci.c b/hw/pci.c index ed011b5..042a216 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -392,6 +392,41 @@ void pci_register_io_region(PCIDevice *pci_dev, int region_num, *(uint32_t *)(pci_dev->wmask + addr) = cpu_to_le32(wmask); } +static void pci_unmap_region(PCIDevice *d, PCIIORegion *r) +{ + if (r->addr == -1) + return; + if (r->type & PCI_ADDRESS_SPACE_IO) { + int class; + /* NOTE: specific hack for IDE in PC case: + only one byte must be mapped. */ + class = pci_get_word(d->config + PCI_CLASS_DEVICE); + if (class == 0x0101 && r->size == 4) { + isa_unassign_ioport(r->addr + 2, 1); + } else { + isa_unassign_ioport(r->addr, r->size); + } + } else { + cpu_register_physical_memory(pci_to_cpu_addr(r->addr), + r->size, + IO_MEM_UNASSIGNED); + qemu_unregister_coalesced_mmio(r->addr, r->size); + } +} + +void pci_resize_io_region(PCIDevice *pci_dev, int region_num, + uint32_t size) +{ + + PCIIORegion *r = &pci_dev->io_regions[region_num]; + if (r->size == size) + return; + r->size = size; + pci_unmap_region(pci_dev, r); + r->addr = -1; + pci_update_mappings(pci_dev); +} + static void pci_update_mappings(PCIDevice *d) { PCIIORegion *r; @@ -445,24 +480,7 @@ static void pci_update_mappings(PCIDevice *d) } /* now do the real mapping */ if (new_addr != r->addr) { - if (r->addr != -1) { - if (r->type & PCI_ADDRESS_SPACE_IO) { - int class; - /* NOTE: specific hack for IDE in PC case: - only one byte must be mapped. */ - class = d->config[0x0a] | (d->config[0x0b] << 8); - if (class == 0x0101 && r->size == 4) { - isa_unassign_ioport(r->addr + 2, 1); - } else { - isa_unassign_ioport(r->addr, r->size); - } - } else { - cpu_register_physical_memory(pci_to_cpu_addr(r->addr), - r->size, - IO_MEM_UNASSIGNED); - qemu_unregister_coalesced_mmio(r->addr, r->size); - } - } + pci_unmap_region(d, r); r->addr = new_addr; if (r->addr != -1) { r->map_func(d, i, r->addr, r->size, r->type); diff --git a/hw/pci.h b/hw/pci.h index 98a34ee..8e74033 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -221,6 +221,9 @@ void pci_register_io_region(PCIDevice *pci_dev, int region_num, uint32_t size, int type, PCIMapIORegionFunc *map_func); +void pci_resize_io_region(PCIDevice *pci_dev, int region_num, + uint32_t size); + int pci_add_capability(PCIDevice *pci_dev, uint8_t cap_id, uint8_t cap_size); void pci_del_capability(PCIDevice *pci_dev, uint8_t cap_id, uint8_t cap_size);