From patchwork Tue Jun 2 15:02:49 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: 27485 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 n52F6xal011479 for ; Tue, 2 Jun 2009 15:07:01 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756553AbZFBPG0 (ORCPT ); Tue, 2 Jun 2009 11:06:26 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1756309AbZFBPG0 (ORCPT ); Tue, 2 Jun 2009 11:06:26 -0400 Received: from mx2.redhat.com ([66.187.237.31]:47744 "EHLO mx2.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753237AbZFBPGZ (ORCPT ); Tue, 2 Jun 2009 11:06:25 -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 n52F3jns013202; Tue, 2 Jun 2009 11:03:45 -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 n52F3iuP011760; Tue, 2 Jun 2009 11:03:45 -0400 Received: from redhat.com (dhcp-0-223.tlv.redhat.com [10.35.0.223]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id n52F3fss019344; Tue, 2 Jun 2009 11:03:42 -0400 Date: Tue, 2 Jun 2009 18:02:49 +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: [PATCHv2 08/13] qemu: add support for resizing regions Message-ID: <20090602150249.GI6554@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 31ba2ed..a63d988 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->mask + addr) = cpu_to_le32(mask); } +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 6da626b..4072f16 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);