Hi Sergey,
On 26/2/24 01:02, Sergey Kambalin wrote:
Signed-off-by: Sergey Kambalin <sergey.kamba...@auriga.com>
---
hw/arm/bcm2838_pcie.c | 217 +++++++++++++++++++++++++++++++++-
hw/arm/trace-events | 4 +
include/hw/arm/bcm2838_pcie.h | 22 ++++
3 files changed, 241 insertions(+), 2 deletions(-)
+static void bcm2838_pcie_host_realize(DeviceState *dev, Error **errp)
+{
+ PCIHostState *pci = PCI_HOST_BRIDGE(dev);
+ BCM2838PcieHostState *s = BCM2838_PCIE_HOST(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+ int i;
+
+ memory_region_init_io(&s->cfg_regs, OBJECT(s), &bcm2838_pcie_host_ops, s,
+ "bcm2838_pcie_cfg_regs", BCM2838_PCIE_REGS_SIZE);
+ sysbus_init_mmio(sbd, &s->cfg_regs);
+
+ /*
+ * The MemoryRegions io_mmio and io_ioport that we pass to
+ * pci_register_root_bus() are not the same as the MemoryRegions
+ * io_mmio_window and io_ioport_window that we expose as SysBus MRs.
+ * The difference is in the behavior of accesses to addresses where no PCI
+ * device has been mapped.
+ *
+ * io_mmio and io_ioport are the underlying PCI view of the PCI address
+ * space, and when a PCI device does a bus master access to a bad address
+ * this is reported back to it as a transaction failure.
+ *
+ * io_mmio_window and io_ioport_window implement "unmapped addresses read
as
+ * -1 and ignore writes"; this is a traditional x86 PC behavior, which is
+ * not mandated properly by the PCI spec but expected by the majority of
+ * PCI-using guest software, including Linux.
+ *
+ * We implement it in the PCIe host controller, by providing the *_window
+ * MRs, which are containers with io ops that implement the 'background'
+ * behavior and which hold the real PCI MRs as sub-regions.
+ */
+ memory_region_init(&s->io_mmio, OBJECT(s), "bcm2838_pcie_mmio",
UINT64_MAX);
+ memory_region_init(&s->io_ioport, OBJECT(s), "bcm2838_pcie_ioport",
+ 64 * 1024);
+
+ memory_region_init_io(&s->io_mmio_window, OBJECT(s),
+ &unassigned_io_ops, OBJECT(s),
+ "bcm2838_pcie_mmio_window", UINT64_MAX);
+ memory_region_init_io(&s->io_ioport_window, OBJECT(s),
+ &unassigned_io_ops, OBJECT(s),
+ "bcm2838_pcie_ioport_window", 64 * 1024);
+
+ memory_region_add_subregion(&s->io_mmio_window, 0, &s->io_mmio);
+ memory_region_add_subregion(&s->io_ioport_window, 0, &s->io_ioport);
+ sysbus_init_mmio(sbd, &s->io_mmio_window);
+ sysbus_init_mmio(sbd, &s->io_ioport_window);
+
+ for (i = 0; i < BCM2838_PCIE_NUM_IRQS; i++) {
+ sysbus_init_irq(sbd, &s->irq[i]);
+ s->irq_num[i] = -1;
+ }
+
+ pci->bus = pci_register_root_bus(dev, "pcie.0", bcm2838_pcie_host_set_irq,
+ bcm2838_pcie_host_map_irq, s, &s->io_mmio,
+ &s->io_ioport, 0, BCM2838_PCIE_NUM_IRQS,
+ TYPE_PCIE_BUS);
+ pci_bus_set_route_irq_fn(pci->bus,
bcm2838_pcie_host_route_intx_pin_to_irq);
+ qdev_realize(DEVICE(&s->root_port), BUS(pci->bus), &error_fatal);
+}
Something is odd:
(qemu) info mtree
...
address-space: memory
0000000000000000-ffffffffffffffff (prio 0, i/o): system
...
[DETECTED OVERFLOW!] 0000000600000000-00000005ffffffff (prio 0,
i/o): bcm2838_pcie_mmio_window
[DETECTED OVERFLOW!] 0000000600000000-00000005ffffffff (prio 0,
i/o): bcm2838_pcie_mmio
0000000600000000-0000000600000000 (prio 1, i/o): alias
pci_bridge_mem @pci_bridge_pci 0000000000000000-0000000000000000
0000000600000000-0000000600000000 (prio 1, i/o): alias
pci_bridge_pref_mem @pci_bridge_pci 0000000000000000-0000000000000000