aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorAlexey Kardashevskiy <aik@ozlabs.ru>2015-01-30 12:53:19 +1100
committerAlexander Graf <agraf@suse.de>2015-03-09 14:59:54 +0100
commitb194df478ae7607d93b47a8307e623c9f9f2b3ab (patch)
treee971685430228c9b0755de8da0e5aaf82c80b161 /hw
parent3dab024430cf72ea65afce227585f9768fb3bfa7 (diff)
spapr-pci: Enable huge BARs
At the moment sPAPR only supports 512MB window for MMIO BARs. However modern devices might want bigger 64bit BARs. This extends MMIO window from 512MB to 62GB (aligned to SPAPR_PCI_WINDOW_SPACING) and advertises it in 2 records in the PHB "ranges" property. 32bit gets the space from SPAPR_PCI_MEM_WIN_BUS_OFFSET till the end of 4GB, 64bit gets the rest of the space. If no space is left, 64bit range is not advertised. The MMIO space size is set to old value of 0x20000000 by default for pseries machines older than 2.3. The approach changes the device tree which is a guest visible change, however it won't break migration as: 1. we do not support migration to older QEMU versions 2. migration to newer QEMU will migrate the device tree as well and since the new layout only extends the old one and does not change address mappigns, no breakage is expected here too. SLOF change is required to utilize this extension. Suggested-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> Reviewed-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'hw')
-rw-r--r--hw/ppc/spapr.c16
-rw-r--r--hw/ppc/spapr_pci.c14
2 files changed, 28 insertions, 2 deletions
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index e1a9fd7ff3..7a1b8c6f45 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1759,11 +1759,22 @@ static const TypeInfo spapr_machine_info = {
},
};
+#define SPAPR_COMPAT_2_2 \
+ {\
+ .driver = TYPE_SPAPR_PCI_HOST_BRIDGE,\
+ .property = "mem_win_size",\
+ .value = "0x20000000",\
+ }
+
+#define SPAPR_COMPAT_2_1 \
+ SPAPR_COMPAT_2_2
+
static void spapr_machine_2_1_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
static GlobalProperty compat_props[] = {
HW_COMPAT_2_1,
+ SPAPR_COMPAT_2_1,
{ /* end of list */ }
};
@@ -1780,10 +1791,15 @@ static const TypeInfo spapr_machine_2_1_info = {
static void spapr_machine_2_2_class_init(ObjectClass *oc, void *data)
{
+ static GlobalProperty compat_props[] = {
+ SPAPR_COMPAT_2_2,
+ { /* end of list */ }
+ };
MachineClass *mc = MACHINE_CLASS(oc);
mc->name = "pseries-2.2";
mc->desc = "pSeries Logical Partition (PAPR compliant) v2.2";
+ mc->compat_props = compat_props;
}
static const TypeInfo spapr_machine_2_2_info = {
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 6deeb19e3f..cebdeb3516 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -868,6 +868,10 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb,
int bus_off, i, j;
char nodename[256];
uint32_t bus_range[] = { cpu_to_be32(0), cpu_to_be32(0xff) };
+ const uint64_t mmiosize = memory_region_size(&phb->memwindow);
+ const uint64_t w32max = (1ULL << 32) - SPAPR_PCI_MEM_WIN_BUS_OFFSET;
+ const uint64_t w32size = MIN(w32max, mmiosize);
+ const uint64_t w64size = (mmiosize > w32size) ? (mmiosize - w32size) : 0;
struct {
uint32_t hi;
uint64_t child;
@@ -882,9 +886,15 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb,
{
cpu_to_be32(b_ss(2)), cpu_to_be64(SPAPR_PCI_MEM_WIN_BUS_OFFSET),
cpu_to_be64(phb->mem_win_addr),
- cpu_to_be64(memory_region_size(&phb->memwindow)),
+ cpu_to_be64(w32size),
+ },
+ {
+ cpu_to_be32(b_ss(3)), cpu_to_be64(1ULL << 32),
+ cpu_to_be64(phb->mem_win_addr + w32size),
+ cpu_to_be64(w64size)
},
};
+ const unsigned sizeof_ranges = (w64size ? 3 : 2) * sizeof(ranges[0]);
uint64_t bus_reg[] = { cpu_to_be64(phb->buid), 0 };
uint32_t interrupt_map_mask[] = {
cpu_to_be32(b_ddddd(-1)|b_fff(0)), 0x0, 0x0, cpu_to_be32(-1)};
@@ -913,7 +923,7 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb,
_FDT(fdt_setprop_cell(fdt, bus_off, "#interrupt-cells", 0x1));
_FDT(fdt_setprop(fdt, bus_off, "used-by-rtas", NULL, 0));
_FDT(fdt_setprop(fdt, bus_off, "bus-range", &bus_range, sizeof(bus_range)));
- _FDT(fdt_setprop(fdt, bus_off, "ranges", &ranges, sizeof(ranges)));
+ _FDT(fdt_setprop(fdt, bus_off, "ranges", &ranges, sizeof_ranges));
_FDT(fdt_setprop(fdt, bus_off, "reg", &bus_reg, sizeof(bus_reg)));
_FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pci-config-space-type", 0x1));
_FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pe-total-#msi", XICS_IRQS));