[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 43/43] hw/pci-host/gpex: Don't fault for unmapped parts of MMIO an
From: |
Peter Maydell |
Subject: |
[PULL 43/43] hw/pci-host/gpex: Don't fault for unmapped parts of MMIO and PIO windows |
Date: |
Fri, 30 Apr 2021 11:34:37 +0100 |
Currently the gpex PCI controller implements no special behaviour for
guest accesses to areas of the PIO and MMIO where it has not mapped
any PCI devices, which means that for Arm you end up with a CPU
exception due to a data abort.
Most host OSes expect "like an x86 PC" behaviour, where bad accesses
like this return -1 for reads and ignore writes. In the interests of
not being surprising, make host CPU accesses to these windows behave
as -1/discard where there's no mapped PCI device.
The old behaviour generally didn't cause any problems, because
almost always the guest OS will map the PCI devices and then only
access where it has mapped them. One corner case where you will see
this kind of access is if Linux attempts to probe legacy ISA
devices via a PIO window access. So far the only case where we've
seen this has been via the syzkaller fuzzer.
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Message-id: 20210325163315.27724-1-peter.maydell@linaro.org
Fixes: https://bugs.launchpad.net/qemu/+bug/1918917
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
include/hw/pci-host/gpex.h | 4 +++
hw/core/machine.c | 4 ++-
hw/pci-host/gpex.c | 56 ++++++++++++++++++++++++++++++++++++--
3 files changed, 60 insertions(+), 4 deletions(-)
diff --git a/include/hw/pci-host/gpex.h b/include/hw/pci-host/gpex.h
index d48a020a952..fcf8b638200 100644
--- a/include/hw/pci-host/gpex.h
+++ b/include/hw/pci-host/gpex.h
@@ -49,8 +49,12 @@ struct GPEXHost {
MemoryRegion io_ioport;
MemoryRegion io_mmio;
+ MemoryRegion io_ioport_window;
+ MemoryRegion io_mmio_window;
qemu_irq irq[GPEX_NUM_IRQS];
int irq_num[GPEX_NUM_IRQS];
+
+ bool allow_unmapped_accesses;
};
struct GPEXConfig {
diff --git a/hw/core/machine.c b/hw/core/machine.c
index cebcdcc3511..0f5ce43d0c2 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -36,7 +36,9 @@
#include "hw/virtio/virtio.h"
#include "hw/virtio/virtio-pci.h"
-GlobalProperty hw_compat_6_0[] = {};
+GlobalProperty hw_compat_6_0[] = {
+ { "gpex-pcihost", "allow-unmapped-accesses", "false" },
+};
const size_t hw_compat_6_0_len = G_N_ELEMENTS(hw_compat_6_0);
GlobalProperty hw_compat_5_2[] = {
diff --git a/hw/pci-host/gpex.c b/hw/pci-host/gpex.c
index 2bdbe7b4561..a6752fac5e8 100644
--- a/hw/pci-host/gpex.c
+++ b/hw/pci-host/gpex.c
@@ -83,12 +83,51 @@ static void gpex_host_realize(DeviceState *dev, Error
**errp)
int i;
pcie_host_mmcfg_init(pex, PCIE_MMCFG_SIZE_MAX);
+ sysbus_init_mmio(sbd, &pex->mmio);
+
+ /*
+ * Note that 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 behaviour 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 traditional
+ * x86 PC behaviour, which is not mandated by the PCI spec proper
+ * but expected by much PCI-using guest software, including Linux.
+ *
+ * In the interests of not being unnecessarily surprising, we
+ * implement it in the gpex PCI host controller, by providing the
+ * _window MRs, which are containers with io ops that implement
+ * the 'background' behaviour and which hold the real PCI MRs as
+ * subregions.
+ */
memory_region_init(&s->io_mmio, OBJECT(s), "gpex_mmio", UINT64_MAX);
memory_region_init(&s->io_ioport, OBJECT(s), "gpex_ioport", 64 * 1024);
- sysbus_init_mmio(sbd, &pex->mmio);
- sysbus_init_mmio(sbd, &s->io_mmio);
- sysbus_init_mmio(sbd, &s->io_ioport);
+ if (s->allow_unmapped_accesses) {
+ memory_region_init_io(&s->io_mmio_window, OBJECT(s),
+ &unassigned_io_ops, OBJECT(s),
+ "gpex_mmio_window", UINT64_MAX);
+ memory_region_init_io(&s->io_ioport_window, OBJECT(s),
+ &unassigned_io_ops, OBJECT(s),
+ "gpex_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);
+ } else {
+ sysbus_init_mmio(sbd, &s->io_mmio);
+ sysbus_init_mmio(sbd, &s->io_ioport);
+ }
+
for (i = 0; i < GPEX_NUM_IRQS; i++) {
sysbus_init_irq(sbd, &s->irq[i]);
s->irq_num[i] = -1;
@@ -108,6 +147,16 @@ static const char *gpex_host_root_bus_path(PCIHostState
*host_bridge,
return "0000:00";
}
+static Property gpex_host_properties[] = {
+ /*
+ * Permit CPU accesses to unmapped areas of the PIO and MMIO windows
+ * (discarding writes and returning -1 for reads) rather than aborting.
+ */
+ DEFINE_PROP_BOOL("allow-unmapped-accesses", GPEXHost,
+ allow_unmapped_accesses, true),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
static void gpex_host_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -117,6 +166,7 @@ static void gpex_host_class_init(ObjectClass *klass, void
*data)
dc->realize = gpex_host_realize;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
dc->fw_name = "pci";
+ device_class_set_props(dc, gpex_host_properties);
}
static void gpex_host_initfn(Object *obj)
--
2.20.1
- [PULL 29/43] target/arm: Enforce alignment for SRS, (continued)
- [PULL 29/43] target/arm: Enforce alignment for SRS, Peter Maydell, 2021/04/30
- [PULL 16/43] target/arm: Introduce CPUARMTBFlags, Peter Maydell, 2021/04/30
- [PULL 24/43] target/arm: Adjust gen_aa32_{ld, st}_i64 for align+endianness, Peter Maydell, 2021/04/30
- [PULL 31/43] target/arm: Enforce alignment for VLDR/VSTR, Peter Maydell, 2021/04/30
- [PULL 28/43] target/arm: Enforce alignment for RFE, Peter Maydell, 2021/04/30
- [PULL 34/43] target/arm: Enforce alignment for VLDn/VSTn (single), Peter Maydell, 2021/04/30
- [PULL 39/43] target/arm: Enforce alignment for aa64 vector LDn/STn (multiple), Peter Maydell, 2021/04/30
- [PULL 36/43] target/arm: Use finalize_memop for aa64 fpr load/store, Peter Maydell, 2021/04/30
- [PULL 35/43] target/arm: Use finalize_memop for aa64 gpr load/store, Peter Maydell, 2021/04/30
- [PULL 40/43] target/arm: Enforce alignment for aa64 vector LDn/STn (single), Peter Maydell, 2021/04/30
- [PULL 43/43] hw/pci-host/gpex: Don't fault for unmapped parts of MMIO and PIO windows,
Peter Maydell <=
- [PULL 41/43] target/arm: Enforce alignment for sve LD1R, Peter Maydell, 2021/04/30
- [PULL 30/43] target/arm: Enforce alignment for VLDM/VSTM, Peter Maydell, 2021/04/30
- [PULL 23/43] target/arm: Fix SCTLR_B test for TCGv_i64 load/store, Peter Maydell, 2021/04/30
- [PULL 33/43] target/arm: Enforce alignment for VLDn/VSTn (multiple), Peter Maydell, 2021/04/30
- [PULL 32/43] target/arm: Enforce alignment for VLDn (all lanes), Peter Maydell, 2021/04/30
- [PULL 37/43] target/arm: Enforce alignment for aa64 load-acq/store-rel, Peter Maydell, 2021/04/30
- [PULL 38/43] target/arm: Use MemOp for size + endian in aa64 vector ld/st, Peter Maydell, 2021/04/30
- [PULL 27/43] target/arm: Enforce alignment for LDM/STM, Peter Maydell, 2021/04/30
- [PULL 42/43] hw: add compat machines for 6.1, Peter Maydell, 2021/04/30
- Re: [PULL 00/43] target-arm queue, no-reply, 2021/04/30