Michael S. Tsirkin
2009-Jun-05 10:23 UTC
[PATCHv3 08/13] qemu: add support for resizing regions
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 <mst at redhat.com>
---
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);
--
1.6.3.1.56.g79e1.dirty
Glauber Costa
2009-Jun-09 17:36 UTC
[Qemu-devel] [PATCHv3 08/13] qemu: add support for resizing regions
On Fri, Jun 05, 2009 at 01:23:55PM +0300, Michael S. Tsirkin wrote:> 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 <mst at redhat.com> > --- > 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); > + } > +} > +this is a good cleanup...> +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); > +} > +but the only user of this one seem to be commented out, and later removed. Why is this needed?
Michael S. Tsirkin
2009-Jun-10 10:05 UTC
[Qemu-devel] [PATCHv3 08/13] qemu: add support for resizing regions
On Tue, Jun 09, 2009 at 02:36:21PM -0300, Glauber Costa wrote:> On Fri, Jun 05, 2009 at 01:23:55PM +0300, Michael S. Tsirkin wrote: > > 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 <mst at redhat.com> > > --- > > 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); > > + } > > +} > > + > this is a good cleanup... > > > +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); > > +} > > + > but the only user of this one seem to be commented out, and later removed. > Why is this needed? >Um, I think this needs to be called on load: virtio has a memmory region if and only if it has MSI-X. -- MST
Michael S. Tsirkin
2009-Jun-10 10:46 UTC
[Qemu-devel] [PATCHv3 08/13] qemu: add support for resizing regions
On Tue, Jun 09, 2009 at 02:36:21PM -0300, Glauber Costa wrote:> On Fri, Jun 05, 2009 at 01:23:55PM +0300, Michael S. Tsirkin wrote: > > 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 <mst at redhat.com> > > --- > > 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); > > + } > > +} > > + > this is a good cleanup... > > > +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); > > +} > > + > but the only user of this one seem to be commented out, and later removed. > Why is this needed? >This was the missing bit: Set correct size for msi-x memory region when loading the device. Signed-off-by: Michael S. Tsirkin <mst at redhat.com> diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index 589fbb1..f657364 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -133,6 +133,8 @@ static int virtio_pci_load_config(void * opaque, QEMUFile *f) return ret; if (msix_present(&proxy->pci_dev)) qemu_get_be16s(f, &proxy->vdev->config_vector); + + pci_resize_io_region(&proxy->pci_dev, 1, msix_bar_size(&proxy->pci_dev)); return 0; } -- MST