From patchwork Mon May 25 12:26:05 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: 25819 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 n4PCUMB7006746 for ; Mon, 25 May 2009 12:30:22 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752571AbZEYM3l (ORCPT ); Mon, 25 May 2009 08:29:41 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1751600AbZEYM3l (ORCPT ); Mon, 25 May 2009 08:29:41 -0400 Received: from mx2.redhat.com ([66.187.237.31]:33577 "EHLO mx2.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751627AbZEYM3k (ORCPT ); Mon, 25 May 2009 08:29:40 -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 n4PCR5id022902; Mon, 25 May 2009 08:27:05 -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 n4PCR4k3029522; Mon, 25 May 2009 08:27:04 -0400 Received: from redhat.com (vpn-10-50.str.redhat.com [10.32.10.50]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id n4PCR0iU014990; Mon, 25 May 2009 08:27:01 -0400 Date: Mon, 25 May 2009 15:26:05 +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 Subject: [PATCH 08/11] qemu: add support for resizing regions Message-ID: <20090525122605.GI5046@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 6bc3819..19905b9 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);