From patchwork Thu Jun 18 13:14:38 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: 31134 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 n5IDHdjn008060 for ; Thu, 18 Jun 2009 13:17:41 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1761178AbZFRNRg (ORCPT ); Thu, 18 Jun 2009 09:17:36 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1760988AbZFRNRg (ORCPT ); Thu, 18 Jun 2009 09:17:36 -0400 Received: from mx2.redhat.com ([66.187.237.31]:35277 "EHLO mx2.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1760505AbZFRNRf (ORCPT ); Thu, 18 Jun 2009 09:17:35 -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 n5IDF1Aw022234; Thu, 18 Jun 2009 09:15:01 -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 n5IDF0Wu024908; Thu, 18 Jun 2009 09:15:00 -0400 Received: from redhat.com (vpn-6-65.tlv.redhat.com [10.35.6.65]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id n5IDEuLR026261; Thu, 18 Jun 2009 09:14:57 -0400 Date: Thu, 18 Jun 2009 16:14:38 +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 , Glauber Costa Subject: [PATCHv5 08/13] qemu: add support for resizing regions Message-ID: <20090618131438.GI19092@redhat.com> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.19 (2009-01-05) 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 | 53 +++++++++++++++++++++++++++++++++++------------------ hw/pci.h | 2 ++ 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/hw/pci.c b/hw/pci.c index e3f80d0..aa88a0b 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -386,6 +386,40 @@ void pci_register_bar(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_bar(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; @@ -439,24 +473,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 25865d7..67e4b4d 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -217,6 +217,8 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num, uint32_t size, int type, PCIMapIORegionFunc *map_func); +void pci_resize_bar(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);