[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH RFC 1/2] hw/pci: delay bus_master_enable_region init
From: |
Marcel Apfelbaum |
Subject: |
[Qemu-devel] [PATCH RFC 1/2] hw/pci: delay bus_master_enable_region initialization |
Date: |
Mon, 23 May 2016 17:01:29 +0300 |
Skip bus_master_enable region creation on PCI devices init
in order to be sure the IOMMU device (if present) would
be created in advance. Add this memory region at machine_done time.
Signed-off-by: Marcel Apfelbaum <address@hidden>
---
hw/i386/pc.c | 17 +++++++++++++++++
hw/pci/pci.c | 22 ++++++++++++----------
include/hw/pci/pci.h | 2 ++
3 files changed, 31 insertions(+), 10 deletions(-)
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 99437e0..f9ac543 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -32,6 +32,7 @@
#include "hw/ide.h"
#include "hw/pci/pci.h"
#include "hw/pci/pci_bus.h"
+#include "hw/pci/pci_bridge.h"
#include "hw/nvram/fw_cfg.h"
#include "hw/timer/hpet.h"
#include "hw/smbios/smbios.h"
@@ -1156,12 +1157,26 @@ typedef struct PcRomPciInfo {
uint64_t w64_max;
} PcRomPciInfo;
+static void pci_bus_enable_bus_master(PCIBus *bus, PCIDevice *dev, void
*opaque)
+{
+ PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
+
+ pci_init_bus_master(dev);
+
+ if (pc->is_bridge) {
+ PCIBus *sec_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(dev));
+ pci_for_each_device(sec_bus, pci_bus_num(sec_bus),
+ pci_bus_enable_bus_master, opaque);
+ }
+}
+
static
void pc_machine_done(Notifier *notifier, void *data)
{
PCMachineState *pcms = container_of(notifier,
PCMachineState, machine_done);
PCIBus *bus = pcms->bus;
+ pci_for_each_device(bus, pci_bus_num(bus), pci_bus_enable_bus_master,
NULL);
if (bus) {
int extra_hosts = 0;
@@ -1169,6 +1184,8 @@ void pc_machine_done(Notifier *notifier, void *data)
QLIST_FOREACH(bus, &bus->child, sibling) {
/* look for expander root buses */
if (pci_bus_is_root(bus)) {
+ pci_for_each_device(bus, pci_bus_num(bus),
+ pci_bus_enable_bus_master, NULL);
extra_hosts++;
}
}
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index bb605ef..e22b1c8 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -828,6 +828,18 @@ static void pci_config_free(PCIDevice *pci_dev)
g_free(pci_dev->used);
}
+void pci_init_bus_master(PCIDevice *pci_dev)
+{
+ AddressSpace *dma_as = pci_device_iommu_address_space(pci_dev);
+
+ memory_region_init_alias(&pci_dev->bus_master_enable_region,
+ OBJECT(pci_dev), "bus master",
+ dma_as->root, 0,
memory_region_size(dma_as->root));
+ memory_region_set_enabled(&pci_dev->bus_master_enable_region, false);
+ address_space_init(&pci_dev->bus_master_as,
&pci_dev->bus_master_enable_region,
+ pci_dev->name);
+}
+
static void do_pci_unregister_device(PCIDevice *pci_dev)
{
pci_dev->bus->devices[pci_dev->devfn] = NULL;
@@ -845,7 +857,6 @@ static PCIDevice *do_pci_register_device(PCIDevice
*pci_dev, PCIBus *bus,
PCIConfigReadFunc *config_read = pc->config_read;
PCIConfigWriteFunc *config_write = pc->config_write;
Error *local_err = NULL;
- AddressSpace *dma_as;
DeviceState *dev = DEVICE(pci_dev);
pci_dev->bus = bus;
@@ -885,15 +896,6 @@ static PCIDevice *do_pci_register_device(PCIDevice
*pci_dev, PCIBus *bus,
}
pci_dev->devfn = devfn;
- dma_as = pci_device_iommu_address_space(pci_dev);
-
- memory_region_init_alias(&pci_dev->bus_master_enable_region,
- OBJECT(pci_dev), "bus master",
- dma_as->root, 0,
memory_region_size(dma_as->root));
- memory_region_set_enabled(&pci_dev->bus_master_enable_region, false);
- address_space_init(&pci_dev->bus_master_as,
&pci_dev->bus_master_enable_region,
- name);
-
pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
pci_dev->irq_state = 0;
pci_config_alloc(pci_dev);
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index ef6ba51..95a930f 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -343,6 +343,8 @@ int pci_device_load(PCIDevice *s, QEMUFile *f);
MemoryRegion *pci_address_space(PCIDevice *dev);
MemoryRegion *pci_address_space_io(PCIDevice *dev);
+void pci_init_bus_master(PCIDevice *dev);
+
/*
* Should not normally be used by devices. For use by sPAPR target
* where QEMU emulates firmware.
--
2.4.3