* [Qemu-devel] [PATCH v3 0/4] PPC: e500: Support more RAM
@ 2014-11-12 21:56 Alexander Graf
2014-11-12 21:56 ` [Qemu-devel] [PATCH v3 1/4] PPC: e500: Move CCSR definition to params Alexander Graf
` (3 more replies)
0 siblings, 4 replies; 7+ messages in thread
From: Alexander Graf @ 2014-11-12 21:56 UTC (permalink / raw)
To: qemu-ppc; +Cc: stuart.yoder, qemu-devel
The e500 target today only supports 3GB of guest RAM. This can be too
little depending on your use case, so this patch set increases that limit
to a whopping 48GB!
Of course this change is too intrusive for 2.2, so I'm posting this
explicitly for 2.3.
v1 -> v2:
- make pci pio window device tree exposure dynamic
v2 -> v3:
- rename pci_base to pci_pio_base
- add ATMU support
Alex
Alexander Graf (4):
PPC: e500: Move CCSR definition to params
PPC: e500: Move CCSR and MMIO space to upper end of address space
PPC: mpc8554ds: Tell user about exceeding RAM limits
PPC: e500 pci host: Add support for ATMUs
hw/pci-host/ppce500.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++---
hw/ppc/e500.c | 34 +++++++--------
hw/ppc/e500.h | 5 +++
hw/ppc/e500plat.c | 5 +++
hw/ppc/mpc8544ds.c | 11 +++++
5 files changed, 143 insertions(+), 25 deletions(-)
--
1.8.1.4
^ permalink raw reply [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH v3 1/4] PPC: e500: Move CCSR definition to params
2014-11-12 21:56 [Qemu-devel] [PATCH v3 0/4] PPC: e500: Support more RAM Alexander Graf
@ 2014-11-12 21:56 ` Alexander Graf
2014-11-12 21:56 ` [Qemu-devel] [PATCH v3 2/4] PPC: e500: Move CCSR and MMIO space to upper end of address space Alexander Graf
` (2 subsequent siblings)
3 siblings, 0 replies; 7+ messages in thread
From: Alexander Graf @ 2014-11-12 21:56 UTC (permalink / raw)
To: qemu-ppc; +Cc: stuart.yoder, qemu-devel
We want to have different MMIO region offsets for the mpc8544ds machine
and our e500 PV machine, so move the definitions of those into the machine
specific params struct.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
v1 -> v2:
- make pci pio window device tree exposure dynamic
v2 -> v3:
- rename the pci pio window variable to reflect what it does
---
hw/ppc/e500.c | 30 ++++++++++++++----------------
hw/ppc/e500.h | 3 +++
hw/ppc/e500plat.c | 3 +++
hw/ppc/mpc8544ds.c | 3 +++
4 files changed, 23 insertions(+), 16 deletions(-)
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index 2832fc0..1aaa515 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -51,19 +51,14 @@
#define RAM_SIZES_ALIGN (64UL << 20)
/* TODO: parameterize */
-#define MPC8544_CCSRBAR_BASE 0xE0000000ULL
#define MPC8544_CCSRBAR_SIZE 0x00100000ULL
#define MPC8544_MPIC_REGS_OFFSET 0x40000ULL
#define MPC8544_MSI_REGS_OFFSET 0x41600ULL
#define MPC8544_SERIAL0_REGS_OFFSET 0x4500ULL
#define MPC8544_SERIAL1_REGS_OFFSET 0x4600ULL
#define MPC8544_PCI_REGS_OFFSET 0x8000ULL
-#define MPC8544_PCI_REGS_BASE (MPC8544_CCSRBAR_BASE + \
- MPC8544_PCI_REGS_OFFSET)
#define MPC8544_PCI_REGS_SIZE 0x1000ULL
-#define MPC8544_PCI_IO 0xE1000000ULL
#define MPC8544_UTIL_OFFSET 0xe0000ULL
-#define MPC8544_SPIN_BASE 0xEF000000ULL
#define MPC8XXX_GPIO_OFFSET 0x000FF000ULL
#define MPC8XXX_GPIO_IRQ 43
@@ -298,7 +293,7 @@ static int ppce500_load_device_tree(MachineState *machine,
0x0, 0x20000000,
0x1000000, 0x0, 0x0,
- 0x0, 0xe1000000,
+ params->pci_pio_base >> 32, params->pci_pio_base,
0x0, 0x10000,
};
QemuOpts *machine_opts = qemu_get_machine_opts();
@@ -389,7 +384,7 @@ static int ppce500_load_device_tree(MachineState *machine,
CPUState *cpu;
PowerPCCPU *pcpu;
char cpu_name[128];
- uint64_t cpu_release_addr = MPC8544_SPIN_BASE + (i * 0x20);
+ uint64_t cpu_release_addr = params->spin_base + (i * 0x20);
cpu = qemu_get_cpu(i);
if (cpu == NULL) {
@@ -426,7 +421,7 @@ static int ppce500_load_device_tree(MachineState *machine,
qemu_fdt_add_subnode(fdt, "/aliases");
/* XXX These should go into their respective devices' code */
- snprintf(soc, sizeof(soc), "/soc@%llx", MPC8544_CCSRBAR_BASE);
+ snprintf(soc, sizeof(soc), "/soc@%"PRIx64, params->ccsrbar_base);
qemu_fdt_add_subnode(fdt, soc);
qemu_fdt_setprop_string(fdt, soc, "device_type", "soc");
qemu_fdt_setprop(fdt, soc, "compatible", compatible_sb,
@@ -434,7 +429,7 @@ static int ppce500_load_device_tree(MachineState *machine,
qemu_fdt_setprop_cell(fdt, soc, "#address-cells", 1);
qemu_fdt_setprop_cell(fdt, soc, "#size-cells", 1);
qemu_fdt_setprop_cells(fdt, soc, "ranges", 0x0,
- MPC8544_CCSRBAR_BASE >> 32, MPC8544_CCSRBAR_BASE,
+ params->ccsrbar_base >> 32, params->ccsrbar_base,
MPC8544_CCSRBAR_SIZE);
/* XXX should contain a reasonable value */
qemu_fdt_setprop_cell(fdt, soc, "bus-frequency", 0);
@@ -493,7 +488,8 @@ static int ppce500_load_device_tree(MachineState *machine,
qemu_fdt_setprop_cell(fdt, msi, "phandle", msi_ph);
qemu_fdt_setprop_cell(fdt, msi, "linux,phandle", msi_ph);
- snprintf(pci, sizeof(pci), "/pci@%llx", MPC8544_PCI_REGS_BASE);
+ snprintf(pci, sizeof(pci), "/pci@%llx",
+ params->ccsrbar_base + MPC8544_PCI_REGS_OFFSET);
qemu_fdt_add_subnode(fdt, pci);
qemu_fdt_setprop_cell(fdt, pci, "cell-index", 0);
qemu_fdt_setprop_string(fdt, pci, "compatible", "fsl,mpc8540-pci");
@@ -512,8 +508,10 @@ static int ppce500_load_device_tree(MachineState *machine,
}
qemu_fdt_setprop_cell(fdt, pci, "fsl,msi", msi_ph);
qemu_fdt_setprop(fdt, pci, "ranges", pci_ranges, sizeof(pci_ranges));
- qemu_fdt_setprop_cells(fdt, pci, "reg", MPC8544_PCI_REGS_BASE >> 32,
- MPC8544_PCI_REGS_BASE, 0, 0x1000);
+ qemu_fdt_setprop_cells(fdt, pci, "reg",
+ (params->ccsrbar_base + MPC8544_PCI_REGS_OFFSET) >> 32,
+ (params->ccsrbar_base + MPC8544_PCI_REGS_OFFSET),
+ 0, 0x1000);
qemu_fdt_setprop_cell(fdt, pci, "clock-frequency", 66666666);
qemu_fdt_setprop_cell(fdt, pci, "#interrupt-cells", 1);
qemu_fdt_setprop_cell(fdt, pci, "#size-cells", 2);
@@ -841,7 +839,7 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)
irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT];
irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT];
env->spr_cb[SPR_BOOKE_PIR].default_value = cs->cpu_index = i;
- env->mpic_iack = MPC8544_CCSRBAR_BASE +
+ env->mpic_iack = params->ccsrbar_base +
MPC8544_MPIC_REGS_OFFSET + 0xa0;
ppc_booke_timers_init(cpu, 400000000, PPC_TIMER_E500);
@@ -875,7 +873,7 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)
qdev_init_nofail(dev);
ccsr = CCSR(dev);
ccsr_addr_space = &ccsr->ccsr_space;
- memory_region_add_subregion(address_space_mem, MPC8544_CCSRBAR_BASE,
+ memory_region_add_subregion(address_space_mem, params->ccsrbar_base,
ccsr_addr_space);
mpic = ppce500_init_mpic(params, ccsr_addr_space, irqs);
@@ -917,7 +915,7 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)
if (!pci_bus)
printf("couldn't create PCI controller!\n");
- sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, MPC8544_PCI_IO);
+ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, params->pci_pio_base);
if (pci_bus) {
/* Register network interfaces. */
@@ -927,7 +925,7 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)
}
/* Register spinning region */
- sysbus_create_simple("e500-spin", MPC8544_SPIN_BASE, NULL);
+ sysbus_create_simple("e500-spin", params->spin_base, NULL);
if (cur_base < (32 * 1024 * 1024)) {
/* u-boot occupies memory up to 32MB, so load blobs above */
diff --git a/hw/ppc/e500.h b/hw/ppc/e500.h
index 9f61ab2..d96f72d 100644
--- a/hw/ppc/e500.h
+++ b/hw/ppc/e500.h
@@ -17,6 +17,9 @@ typedef struct PPCE500Params {
hwaddr platform_bus_size;
int platform_bus_first_irq;
int platform_bus_num_irqs;
+ hwaddr ccsrbar_base;
+ hwaddr pci_pio_base;
+ hwaddr spin_base;
} PPCE500Params;
void ppce500_init(MachineState *machine, PPCE500Params *params);
diff --git a/hw/ppc/e500plat.c b/hw/ppc/e500plat.c
index d50ae00..1600fcf 100644
--- a/hw/ppc/e500plat.c
+++ b/hw/ppc/e500plat.c
@@ -41,6 +41,9 @@ static void e500plat_init(MachineState *machine)
.platform_bus_size = (128ULL * 1024 * 1024),
.platform_bus_first_irq = 5,
.platform_bus_num_irqs = 10,
+ .ccsrbar_base = 0xE0000000ULL,
+ .pci_pio_base = 0xE1000000ULL,
+ .spin_base = 0xEF000000ULL,
};
/* Older KVM versions don't support EPR which breaks guests when we announce
diff --git a/hw/ppc/mpc8544ds.c b/hw/ppc/mpc8544ds.c
index b99f74a..f131633 100644
--- a/hw/ppc/mpc8544ds.c
+++ b/hw/ppc/mpc8544ds.c
@@ -33,6 +33,9 @@ static void mpc8544ds_init(MachineState *machine)
.pci_nr_slots = 2,
.fixup_devtree = mpc8544ds_fixup_devtree,
.mpic_version = OPENPIC_MODEL_FSL_MPIC_20,
+ .ccsrbar_base = 0xE0000000ULL,
+ .pci_pio_base = 0xE1000000ULL,
+ .spin_base = 0xEF000000ULL,
};
ppce500_init(machine, ¶ms);
--
1.8.1.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH v3 2/4] PPC: e500: Move CCSR and MMIO space to upper end of address space
2014-11-12 21:56 [Qemu-devel] [PATCH v3 0/4] PPC: e500: Support more RAM Alexander Graf
2014-11-12 21:56 ` [Qemu-devel] [PATCH v3 1/4] PPC: e500: Move CCSR definition to params Alexander Graf
@ 2014-11-12 21:56 ` Alexander Graf
2014-11-12 21:56 ` [Qemu-devel] [PATCH v3 3/4] PPC: mpc8554ds: Tell user about exceeding RAM limits Alexander Graf
2014-11-12 21:56 ` [Qemu-devel] [PATCH v3 4/4] PPC: e500 pci host: Add support for ATMUs Alexander Graf
3 siblings, 0 replies; 7+ messages in thread
From: Alexander Graf @ 2014-11-12 21:56 UTC (permalink / raw)
To: qemu-ppc; +Cc: stuart.yoder, qemu-devel
On e500 we're basically guaranteed to have 36bits of physical address space
available for our enjoyment. Older chips (like the mpc8544) only had 32bits,
but everything from e500v2 onwards bumped it up.
It's reasonably safe to assume that if you're using the PV machine, your guest
kernel is configured to support 36bit physical address space. So in order to
support more guest RAM, we can move CCSR and other MMIO windows right below the
end of our 36bit address space, just like later SoC versions of e500 do.
With this patch, I'm able to successfully spawn an e500 VM with -m 48G.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/ppc/e500plat.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/hw/ppc/e500plat.c b/hw/ppc/e500plat.c
index 1600fcf..1b8a68d 100644
--- a/hw/ppc/e500plat.c
+++ b/hw/ppc/e500plat.c
@@ -41,9 +41,9 @@ static void e500plat_init(MachineState *machine)
.platform_bus_size = (128ULL * 1024 * 1024),
.platform_bus_first_irq = 5,
.platform_bus_num_irqs = 10,
- .ccsrbar_base = 0xE0000000ULL,
- .pci_pio_base = 0xE1000000ULL,
- .spin_base = 0xEF000000ULL,
+ .ccsrbar_base = 0xFE0000000ULL,
+ .pci_pio_base = 0xFE1000000ULL,
+ .spin_base = 0xFEF000000ULL,
};
/* Older KVM versions don't support EPR which breaks guests when we announce
--
1.8.1.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH v3 3/4] PPC: mpc8554ds: Tell user about exceeding RAM limits
2014-11-12 21:56 [Qemu-devel] [PATCH v3 0/4] PPC: e500: Support more RAM Alexander Graf
2014-11-12 21:56 ` [Qemu-devel] [PATCH v3 1/4] PPC: e500: Move CCSR definition to params Alexander Graf
2014-11-12 21:56 ` [Qemu-devel] [PATCH v3 2/4] PPC: e500: Move CCSR and MMIO space to upper end of address space Alexander Graf
@ 2014-11-12 21:56 ` Alexander Graf
2014-11-12 21:56 ` [Qemu-devel] [PATCH v3 4/4] PPC: e500 pci host: Add support for ATMUs Alexander Graf
3 siblings, 0 replies; 7+ messages in thread
From: Alexander Graf @ 2014-11-12 21:56 UTC (permalink / raw)
To: qemu-ppc; +Cc: stuart.yoder, qemu-devel
The mpc8544ds board only supports up to 3GB of RAM due to its limited
address space.
When the user requests more, abort and tell him that he should use less.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/ppc/mpc8544ds.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/hw/ppc/mpc8544ds.c b/hw/ppc/mpc8544ds.c
index f131633..fb74b3f 100644
--- a/hw/ppc/mpc8544ds.c
+++ b/hw/ppc/mpc8544ds.c
@@ -15,6 +15,7 @@
#include "hw/boards.h"
#include "sysemu/device_tree.h"
#include "hw/ppc/openpic.h"
+#include "qemu/error-report.h"
static void mpc8544ds_fixup_devtree(PPCE500Params *params, void *fdt)
{
@@ -38,6 +39,11 @@ static void mpc8544ds_init(MachineState *machine)
.spin_base = 0xEF000000ULL,
};
+ if (machine->ram_size > 0xc0000000) {
+ error_report("The MPC8544DS board only supports up to 3GB of RAM");
+ exit(1);
+ }
+
ppce500_init(machine, ¶ms);
}
--
1.8.1.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH v3 4/4] PPC: e500 pci host: Add support for ATMUs
2014-11-12 21:56 [Qemu-devel] [PATCH v3 0/4] PPC: e500: Support more RAM Alexander Graf
` (2 preceding siblings ...)
2014-11-12 21:56 ` [Qemu-devel] [PATCH v3 3/4] PPC: mpc8554ds: Tell user about exceeding RAM limits Alexander Graf
@ 2014-11-12 21:56 ` Alexander Graf
2014-11-13 15:08 ` [Qemu-devel] [Qemu-ppc] " Bharat.Bhushan
3 siblings, 1 reply; 7+ messages in thread
From: Alexander Graf @ 2014-11-12 21:56 UTC (permalink / raw)
To: qemu-ppc; +Cc: stuart.yoder, qemu-devel
The e500 PCI controller has configurable windows that allow a guest OS
to selectively map parts of the PCI bus space to CPU address space and
to selectively map parts of the CPU address space for DMA requests into
PCI visible address ranges.
So far, we've simply assumed that this mapping is 1:1 and ignored it.
However, the PCICSRBAR (CCSR mapped in PCI bus space) always has to live
inside the first 32bits of address space. This means if we always treat
all mappings as 1:1, this map will collide with our RAM map from the CPU's
point of view.
So this patch adds proper ATMU support which allows us to keep the PCICSRBAR
below 32bits local to the PCI bus and have another, different window to PCI
BARs at the upper end of address space. We leverage this on e500plat though,
mpc8544ds stays virtually 1:1 like it was before, but now also goes via ATMU.
With this patch, I can run guests with lots of RAM and not coincidently access
MSI-X mappings while I really want to access RAM.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/pci-host/ppce500.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++---
hw/ppc/e500.c | 6 +--
hw/ppc/e500.h | 2 +
hw/ppc/e500plat.c | 2 +
hw/ppc/mpc8544ds.c | 2 +
5 files changed, 115 insertions(+), 10 deletions(-)
diff --git a/hw/pci-host/ppce500.c b/hw/pci-host/ppce500.c
index 1b4c0f0..574f8b2 100644
--- a/hw/pci-host/ppce500.c
+++ b/hw/pci-host/ppce500.c
@@ -62,11 +62,19 @@
#define PPCE500_PCI_NR_POBS 5
#define PPCE500_PCI_NR_PIBS 3
+#define PIWAR_EN 0x80000000 /* Enable */
+#define PIWAR_PF 0x20000000 /* prefetch */
+#define PIWAR_TGI_LOCAL 0x00f00000 /* target - local memory */
+#define PIWAR_READ_SNOOP 0x00050000
+#define PIWAR_WRITE_SNOOP 0x00005000
+#define PIWAR_SZ_MASK 0x0000003f
+
struct pci_outbound {
uint32_t potar;
uint32_t potear;
uint32_t powbar;
uint32_t powar;
+ MemoryRegion mem;
};
struct pci_inbound {
@@ -74,6 +82,7 @@ struct pci_inbound {
uint32_t piwbar;
uint32_t piwbear;
uint32_t piwar;
+ MemoryRegion mem;
};
#define TYPE_PPC_E500_PCI_HOST_BRIDGE "e500-pcihost"
@@ -91,10 +100,13 @@ struct PPCE500PCIState {
uint32_t irq_num[PCI_NUM_PINS];
uint32_t first_slot;
uint32_t first_pin_irq;
+ AddressSpace bm_as;
+ MemoryRegion bm;
/* mmio maps */
MemoryRegion container;
MemoryRegion iomem;
MemoryRegion pio;
+ MemoryRegion busmem;
};
#define TYPE_PPC_E500_PCI_BRIDGE "e500-host-bridge"
@@ -181,6 +193,71 @@ static uint64_t pci_reg_read4(void *opaque, hwaddr addr,
return value;
}
+/* DMA mapping */
+static void e500_update_piw(PPCE500PCIState *pci, int idx)
+{
+ uint64_t tar = ((uint64_t)pci->pib[idx].pitar) << 12;
+ uint64_t wbar = ((uint64_t)pci->pib[idx].piwbar) << 12;
+ uint64_t war = pci->pib[idx].piwar;
+ uint64_t size = 2ULL << (war & PIWAR_SZ_MASK);
+ MemoryRegion *address_space_mem = get_system_memory();
+ MemoryRegion *mem = &pci->pib[idx].mem;
+ MemoryRegion *bm = &pci->bm;
+ char *name;
+
+ if (memory_region_is_mapped(mem)) {
+ /* Before we modify anything, unmap and destroy the region */
+ memory_region_del_subregion(bm, mem);
+ object_unparent(OBJECT(mem));
+ }
+
+ if (!(war & PIWAR_EN)) {
+ /* Not enabled, nothing to do */
+ return;
+ }
+
+ name = g_strdup_printf("PCI Inbound Window %d", idx);
+ memory_region_init_alias(mem, OBJECT(pci), name, address_space_mem, tar,
+ size);
+ memory_region_add_subregion_overlap(bm, wbar, mem, -1);
+ g_free(name);
+
+ pci_debug("%s: Added window of size=%#lx from PCI=%#lx to CPU=%#lx\n",
+ __func__, size, wbar, tar);
+}
+
+/* BAR mapping */
+static void e500_update_pow(PPCE500PCIState *pci, int idx)
+{
+ uint64_t tar = ((uint64_t)pci->pob[idx].potar) << 12;
+ uint64_t wbar = ((uint64_t)pci->pob[idx].powbar) << 12;
+ uint64_t war = pci->pob[idx].powar;
+ uint64_t size = 2ULL << (war & PIWAR_SZ_MASK);
+ MemoryRegion *mem = &pci->pob[idx].mem;
+ MemoryRegion *address_space_mem = get_system_memory();
+ char *name;
+
+ if (memory_region_is_mapped(mem)) {
+ /* Before we modify anything, unmap and destroy the region */
+ memory_region_del_subregion(address_space_mem, mem);
+ object_unparent(OBJECT(mem));
+ }
+
+ if (!(war & PIWAR_EN)) {
+ /* Not enabled, nothing to do */
+ return;
+ }
+
+ name = g_strdup_printf("PCI Outbound Window %d", idx);
+ memory_region_init_alias(mem, OBJECT(pci), name, &pci->busmem, tar,
+ size);
+ memory_region_add_subregion(address_space_mem, wbar, mem);
+ g_free(name);
+
+ pci_debug("%s: Added window of size=%#lx from CPU=%#lx to PCI=%#lx\n",
+ __func__, size, wbar, tar);
+}
+
static void pci_reg_write4(void *opaque, hwaddr addr,
uint64_t value, unsigned size)
{
@@ -199,18 +276,22 @@ static void pci_reg_write4(void *opaque, hwaddr addr,
case PPCE500_PCI_OW3:
case PPCE500_PCI_OW4:
idx = (addr >> 5) & 0x7;
- switch (addr & 0xC) {
+ switch (addr & 0x1F) {
case PCI_POTAR:
pci->pob[idx].potar = value;
+ e500_update_pow(pci, idx);
break;
case PCI_POTEAR:
pci->pob[idx].potear = value;
+ e500_update_pow(pci, idx);
break;
case PCI_POWBAR:
pci->pob[idx].powbar = value;
+ e500_update_pow(pci, idx);
break;
case PCI_POWAR:
pci->pob[idx].powar = value;
+ e500_update_pow(pci, idx);
break;
default:
break;
@@ -221,18 +302,22 @@ static void pci_reg_write4(void *opaque, hwaddr addr,
case PPCE500_PCI_IW2:
case PPCE500_PCI_IW1:
idx = ((addr >> 5) & 0x3) - 1;
- switch (addr & 0xC) {
+ switch (addr & 0x1F) {
case PCI_PITAR:
pci->pib[idx].pitar = value;
+ e500_update_piw(pci, idx);
break;
case PCI_PIWBAR:
pci->pib[idx].piwbar = value;
+ e500_update_piw(pci, idx);
break;
case PCI_PIWBEAR:
pci->pib[idx].piwbear = value;
+ e500_update_piw(pci, idx);
break;
case PCI_PIWAR:
pci->pib[idx].piwar = value;
+ e500_update_piw(pci, idx);
break;
default:
break;
@@ -349,13 +434,20 @@ static int e500_pcihost_bridge_initfn(PCIDevice *d)
return 0;
}
+static AddressSpace *e500_pcihost_set_iommu(PCIBus *bus, void *opaque,
+ int devfn)
+{
+ PPCE500PCIState *s = opaque;
+
+ return &s->bm_as;
+}
+
static int e500_pcihost_initfn(SysBusDevice *dev)
{
PCIHostState *h;
PPCE500PCIState *s;
PCIBus *b;
int i;
- MemoryRegion *address_space_mem = get_system_memory();
h = PCI_HOST_BRIDGE(dev);
s = PPC_E500_PCI_HOST_BRIDGE(dev);
@@ -369,12 +461,22 @@ static int e500_pcihost_initfn(SysBusDevice *dev)
}
memory_region_init(&s->pio, OBJECT(s), "pci-pio", PCIE500_PCI_IOLEN);
+ memory_region_init(&s->busmem, OBJECT(s), "pci bus memory", UINT64_MAX);
+
+ /* PIO lives at the bottom of our bus space */
+ memory_region_add_subregion_overlap(&s->busmem, 0, &s->pio, -2);
b = pci_register_bus(DEVICE(dev), NULL, mpc85xx_pci_set_irq,
- mpc85xx_pci_map_irq, s, address_space_mem,
- &s->pio, PCI_DEVFN(s->first_slot, 0), 4, TYPE_PCI_BUS);
+ mpc85xx_pci_map_irq, s, &s->busmem, &s->pio,
+ PCI_DEVFN(s->first_slot, 0), 4, TYPE_PCI_BUS);
h->bus = b;
+ /* Set up PCI view of memory */
+ memory_region_init(&s->bm, OBJECT(s), "bm-e500", UINT64_MAX);
+ memory_region_add_subregion(&s->bm, 0x0, &s->busmem);
+ address_space_init(&s->bm_as, &s->bm, "pci-bm");
+ pci_setup_iommu(b, e500_pcihost_set_iommu, s);
+
pci_create_simple(b, 0, "e500-host-bridge");
memory_region_init(&s->container, OBJECT(h), "pci-container", PCIE500_ALL_SIZE);
@@ -388,7 +490,6 @@ static int e500_pcihost_initfn(SysBusDevice *dev)
memory_region_add_subregion(&s->container, PCIE500_CFGDATA, &h->data_mem);
memory_region_add_subregion(&s->container, PCIE500_REG_BASE, &s->iomem);
sysbus_init_mmio(dev, &s->container);
- sysbus_init_mmio(dev, &s->pio);
pci_bus_set_route_irq_fn(b, e500_route_intx_pin_to_irq);
return 0;
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index 1aaa515..a2e60b4 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -288,8 +288,8 @@ static int ppce500_load_device_tree(MachineState *machine,
int len;
uint32_t pci_ranges[14] =
{
- 0x2000000, 0x0, 0xc0000000,
- 0x0, 0xc0000000,
+ 0x2000000, 0x0, params->pci_mmio_bus_base,
+ params->pci_mmio_base >> 32, params->pci_mmio_base,
0x0, 0x20000000,
0x1000000, 0x0, 0x0,
@@ -915,8 +915,6 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)
if (!pci_bus)
printf("couldn't create PCI controller!\n");
- sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, params->pci_pio_base);
-
if (pci_bus) {
/* Register network interfaces. */
for (i = 0; i < nb_nics; i++) {
diff --git a/hw/ppc/e500.h b/hw/ppc/e500.h
index d96f72d..ef224ea 100644
--- a/hw/ppc/e500.h
+++ b/hw/ppc/e500.h
@@ -19,6 +19,8 @@ typedef struct PPCE500Params {
int platform_bus_num_irqs;
hwaddr ccsrbar_base;
hwaddr pci_pio_base;
+ hwaddr pci_mmio_base;
+ hwaddr pci_mmio_bus_base;
hwaddr spin_base;
} PPCE500Params;
diff --git a/hw/ppc/e500plat.c b/hw/ppc/e500plat.c
index 1b8a68d..14b14ea 100644
--- a/hw/ppc/e500plat.c
+++ b/hw/ppc/e500plat.c
@@ -43,6 +43,8 @@ static void e500plat_init(MachineState *machine)
.platform_bus_num_irqs = 10,
.ccsrbar_base = 0xFE0000000ULL,
.pci_pio_base = 0xFE1000000ULL,
+ .pci_mmio_base = 0xC00000000ULL,
+ .pci_mmio_bus_base = 0xE0000000ULL,
.spin_base = 0xFEF000000ULL,
};
diff --git a/hw/ppc/mpc8544ds.c b/hw/ppc/mpc8544ds.c
index fb74b3f..3a3b141 100644
--- a/hw/ppc/mpc8544ds.c
+++ b/hw/ppc/mpc8544ds.c
@@ -35,6 +35,8 @@ static void mpc8544ds_init(MachineState *machine)
.fixup_devtree = mpc8544ds_fixup_devtree,
.mpic_version = OPENPIC_MODEL_FSL_MPIC_20,
.ccsrbar_base = 0xE0000000ULL,
+ .pci_mmio_base = 0xC0000000ULL,
+ .pci_mmio_bus_base = 0xC0000000ULL,
.pci_pio_base = 0xE1000000ULL,
.spin_base = 0xEF000000ULL,
};
--
1.8.1.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [Qemu-ppc] [PATCH v3 4/4] PPC: e500 pci host: Add support for ATMUs
2014-11-12 21:56 ` [Qemu-devel] [PATCH v3 4/4] PPC: e500 pci host: Add support for ATMUs Alexander Graf
@ 2014-11-13 15:08 ` Bharat.Bhushan
2014-11-13 19:06 ` Alexander Graf
0 siblings, 1 reply; 7+ messages in thread
From: Bharat.Bhushan @ 2014-11-13 15:08 UTC (permalink / raw)
To: Alexander Graf, qemu-ppc@nongnu.org; +Cc: Stuart Yoder, qemu-devel@nongnu.org
> -----Original Message-----
> From: qemu-ppc-bounces+bharat.bhushan=freescale.com@nongnu.org [mailto:qemu-ppc-
> bounces+bharat.bhushan=freescale.com@nongnu.org] On Behalf Of Alexander Graf
> Sent: Thursday, November 13, 2014 3:27 AM
> To: qemu-ppc@nongnu.org
> Cc: Yoder Stuart-B08248; qemu-devel@nongnu.org
> Subject: [Qemu-ppc] [PATCH v3 4/4] PPC: e500 pci host: Add support for ATMUs
>
> The e500 PCI controller has configurable windows that allow a guest OS
> to selectively map parts of the PCI bus space to CPU address space and
> to selectively map parts of the CPU address space for DMA requests into
> PCI visible address ranges.
>
> So far, we've simply assumed that this mapping is 1:1 and ignored it.
>
> However, the PCICSRBAR (CCSR mapped in PCI bus space) always has to live
> inside the first 32bits of address space. This means if we always treat
> all mappings as 1:1, this map will collide with our RAM map from the CPU's
> point of view.
>
> So this patch adds proper ATMU support which allows us to keep the PCICSRBAR
> below 32bits local to the PCI bus and have another, different window to PCI
> BARs at the upper end of address space. We leverage this on e500plat though,
> mpc8544ds stays virtually 1:1 like it was before, but now also goes via ATMU.
>
> With this patch, I can run guests with lots of RAM and not coincidently access
> MSI-X mappings while I really want to access RAM.
>
> Signed-off-by: Alexander Graf <agraf@suse.de>
> ---
> hw/pci-host/ppce500.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++---
> hw/ppc/e500.c | 6 +--
> hw/ppc/e500.h | 2 +
> hw/ppc/e500plat.c | 2 +
> hw/ppc/mpc8544ds.c | 2 +
> 5 files changed, 115 insertions(+), 10 deletions(-)
>
> diff --git a/hw/pci-host/ppce500.c b/hw/pci-host/ppce500.c
> index 1b4c0f0..574f8b2 100644
> --- a/hw/pci-host/ppce500.c
> +++ b/hw/pci-host/ppce500.c
> @@ -62,11 +62,19 @@
> #define PPCE500_PCI_NR_POBS 5
> #define PPCE500_PCI_NR_PIBS 3
>
> +#define PIWAR_EN 0x80000000 /* Enable */
> +#define PIWAR_PF 0x20000000 /* prefetch */
> +#define PIWAR_TGI_LOCAL 0x00f00000 /* target - local memory */
> +#define PIWAR_READ_SNOOP 0x00050000
> +#define PIWAR_WRITE_SNOOP 0x00005000
> +#define PIWAR_SZ_MASK 0x0000003f
> +
> struct pci_outbound {
> uint32_t potar;
> uint32_t potear;
> uint32_t powbar;
> uint32_t powar;
> + MemoryRegion mem;
> };
>
> struct pci_inbound {
> @@ -74,6 +82,7 @@ struct pci_inbound {
> uint32_t piwbar;
> uint32_t piwbear;
> uint32_t piwar;
> + MemoryRegion mem;
> };
>
> #define TYPE_PPC_E500_PCI_HOST_BRIDGE "e500-pcihost"
> @@ -91,10 +100,13 @@ struct PPCE500PCIState {
> uint32_t irq_num[PCI_NUM_PINS];
> uint32_t first_slot;
> uint32_t first_pin_irq;
> + AddressSpace bm_as;
> + MemoryRegion bm;
> /* mmio maps */
> MemoryRegion container;
> MemoryRegion iomem;
> MemoryRegion pio;
> + MemoryRegion busmem;
> };
>
> #define TYPE_PPC_E500_PCI_BRIDGE "e500-host-bridge"
> @@ -181,6 +193,71 @@ static uint64_t pci_reg_read4(void *opaque, hwaddr addr,
> return value;
> }
>
> +/* DMA mapping */
> +static void e500_update_piw(PPCE500PCIState *pci, int idx)
> +{
> + uint64_t tar = ((uint64_t)pci->pib[idx].pitar) << 12;
> + uint64_t wbar = ((uint64_t)pci->pib[idx].piwbar) << 12;
> + uint64_t war = pci->pib[idx].piwar;
> + uint64_t size = 2ULL << (war & PIWAR_SZ_MASK);
> + MemoryRegion *address_space_mem = get_system_memory();
> + MemoryRegion *mem = &pci->pib[idx].mem;
> + MemoryRegion *bm = &pci->bm;
> + char *name;
> +
> + if (memory_region_is_mapped(mem)) {
> + /* Before we modify anything, unmap and destroy the region */
> + memory_region_del_subregion(bm, mem);
> + object_unparent(OBJECT(mem));
> + }
> +
> + if (!(war & PIWAR_EN)) {
> + /* Not enabled, nothing to do */
> + return;
> + }
> +
> + name = g_strdup_printf("PCI Inbound Window %d", idx);
> + memory_region_init_alias(mem, OBJECT(pci), name, address_space_mem, tar,
> + size);
> + memory_region_add_subregion_overlap(bm, wbar, mem, -1);
> + g_free(name);
> +
> + pci_debug("%s: Added window of size=%#lx from PCI=%#lx to CPU=%#lx\n",
> + __func__, size, wbar, tar);
> +}
> +
> +/* BAR mapping */
> +static void e500_update_pow(PPCE500PCIState *pci, int idx)
> +{
> + uint64_t tar = ((uint64_t)pci->pob[idx].potar) << 12;
> + uint64_t wbar = ((uint64_t)pci->pob[idx].powbar) << 12;
> + uint64_t war = pci->pob[idx].powar;
> + uint64_t size = 2ULL << (war & PIWAR_SZ_MASK);
> + MemoryRegion *mem = &pci->pob[idx].mem;
> + MemoryRegion *address_space_mem = get_system_memory();
> + char *name;
> +
> + if (memory_region_is_mapped(mem)) {
> + /* Before we modify anything, unmap and destroy the region */
> + memory_region_del_subregion(address_space_mem, mem);
> + object_unparent(OBJECT(mem));
> + }
> +
> + if (!(war & PIWAR_EN)) {
> + /* Not enabled, nothing to do */
> + return;
> + }
> +
> + name = g_strdup_printf("PCI Outbound Window %d", idx);
> + memory_region_init_alias(mem, OBJECT(pci), name, &pci->busmem, tar,
> + size);
> + memory_region_add_subregion(address_space_mem, wbar, mem);
> + g_free(name);
> +
> + pci_debug("%s: Added window of size=%#lx from CPU=%#lx to PCI=%#lx\n",
> + __func__, size, wbar, tar);
> +}
> +
> static void pci_reg_write4(void *opaque, hwaddr addr,
> uint64_t value, unsigned size)
> {
> @@ -199,18 +276,22 @@ static void pci_reg_write4(void *opaque, hwaddr addr,
> case PPCE500_PCI_OW3:
> case PPCE500_PCI_OW4:
> idx = (addr >> 5) & 0x7;
> - switch (addr & 0xC) {
> + switch (addr & 0x1F) {
> case PCI_POTAR:
> pci->pob[idx].potar = value;
> + e500_update_pow(pci, idx);
> break;
> case PCI_POTEAR:
> pci->pob[idx].potear = value;
> + e500_update_pow(pci, idx);
> break;
> case PCI_POWBAR:
> pci->pob[idx].powbar = value;
> + e500_update_pow(pci, idx);
> break;
> case PCI_POWAR:
> pci->pob[idx].powar = value;
> + e500_update_pow(pci, idx);
> break;
> default:
> break;
> @@ -221,18 +302,22 @@ static void pci_reg_write4(void *opaque, hwaddr addr,
> case PPCE500_PCI_IW2:
> case PPCE500_PCI_IW1:
> idx = ((addr >> 5) & 0x3) - 1;
> - switch (addr & 0xC) {
> + switch (addr & 0x1F) {
> case PCI_PITAR:
> pci->pib[idx].pitar = value;
> + e500_update_piw(pci, idx);
> break;
> case PCI_PIWBAR:
> pci->pib[idx].piwbar = value;
> + e500_update_piw(pci, idx);
> break;
> case PCI_PIWBEAR:
> pci->pib[idx].piwbear = value;
> + e500_update_piw(pci, idx);
> break;
> case PCI_PIWAR:
> pci->pib[idx].piwar = value;
> + e500_update_piw(pci, idx);
> break;
> default:
> break;
> @@ -349,13 +434,20 @@ static int e500_pcihost_bridge_initfn(PCIDevice *d)
> return 0;
> }
>
> +static AddressSpace *e500_pcihost_set_iommu(PCIBus *bus, void *opaque,
> + int devfn)
> +{
> + PPCE500PCIState *s = opaque;
> +
> + return &s->bm_as;
> +}
> +
> static int e500_pcihost_initfn(SysBusDevice *dev)
> {
> PCIHostState *h;
> PPCE500PCIState *s;
> PCIBus *b;
> int i;
> - MemoryRegion *address_space_mem = get_system_memory();
>
> h = PCI_HOST_BRIDGE(dev);
> s = PPC_E500_PCI_HOST_BRIDGE(dev);
> @@ -369,12 +461,22 @@ static int e500_pcihost_initfn(SysBusDevice *dev)
> }
>
> memory_region_init(&s->pio, OBJECT(s), "pci-pio", PCIE500_PCI_IOLEN);
> + memory_region_init(&s->busmem, OBJECT(s), "pci bus memory", UINT64_MAX);
> +
> + /* PIO lives at the bottom of our bus space */
> + memory_region_add_subregion_overlap(&s->busmem, 0, &s->pio, -2);
>
> b = pci_register_bus(DEVICE(dev), NULL, mpc85xx_pci_set_irq,
> - mpc85xx_pci_map_irq, s, address_space_mem,
> - &s->pio, PCI_DEVFN(s->first_slot, 0), 4,
> TYPE_PCI_BUS);
> + mpc85xx_pci_map_irq, s, &s->busmem, &s->pio,
> + PCI_DEVFN(s->first_slot, 0), 4, TYPE_PCI_BUS);
> h->bus = b;
>
> + /* Set up PCI view of memory */
> + memory_region_init(&s->bm, OBJECT(s), "bm-e500", UINT64_MAX);
> + memory_region_add_subregion(&s->bm, 0x0, &s->busmem);
> + address_space_init(&s->bm_as, &s->bm, "pci-bm");
> + pci_setup_iommu(b, e500_pcihost_set_iommu, s);
> +
> pci_create_simple(b, 0, "e500-host-bridge");
>
> memory_region_init(&s->container, OBJECT(h), "pci-container",
> PCIE500_ALL_SIZE);
> @@ -388,7 +490,6 @@ static int e500_pcihost_initfn(SysBusDevice *dev)
> memory_region_add_subregion(&s->container, PCIE500_CFGDATA, &h->data_mem);
> memory_region_add_subregion(&s->container, PCIE500_REG_BASE, &s->iomem);
> sysbus_init_mmio(dev, &s->container);
> - sysbus_init_mmio(dev, &s->pio);
> pci_bus_set_route_irq_fn(b, e500_route_intx_pin_to_irq);
>
> return 0;
> diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
> index 1aaa515..a2e60b4 100644
> --- a/hw/ppc/e500.c
> +++ b/hw/ppc/e500.c
> @@ -288,8 +288,8 @@ static int ppce500_load_device_tree(MachineState *machine,
> int len;
> uint32_t pci_ranges[14] =
> {
> - 0x2000000, 0x0, 0xc0000000,
> - 0x0, 0xc0000000,
> + 0x2000000, 0x0, params->pci_mmio_bus_base,
> + params->pci_mmio_base >> 32, params->pci_mmio_base,
> 0x0, 0x20000000,
Alex, will getting these values from host (real h/w) make more sense?
Thanks
-Bharat
>
> 0x1000000, 0x0, 0x0,
> @@ -915,8 +915,6 @@ void ppce500_init(MachineState *machine, PPCE500Params
> *params)
> if (!pci_bus)
> printf("couldn't create PCI controller!\n");
>
> - sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, params->pci_pio_base);
> -
> if (pci_bus) {
> /* Register network interfaces. */
> for (i = 0; i < nb_nics; i++) {
> diff --git a/hw/ppc/e500.h b/hw/ppc/e500.h
> index d96f72d..ef224ea 100644
> --- a/hw/ppc/e500.h
> +++ b/hw/ppc/e500.h
> @@ -19,6 +19,8 @@ typedef struct PPCE500Params {
> int platform_bus_num_irqs;
> hwaddr ccsrbar_base;
> hwaddr pci_pio_base;
> + hwaddr pci_mmio_base;
> + hwaddr pci_mmio_bus_base;
> hwaddr spin_base;
> } PPCE500Params;
>
> diff --git a/hw/ppc/e500plat.c b/hw/ppc/e500plat.c
> index 1b8a68d..14b14ea 100644
> --- a/hw/ppc/e500plat.c
> +++ b/hw/ppc/e500plat.c
> @@ -43,6 +43,8 @@ static void e500plat_init(MachineState *machine)
> .platform_bus_num_irqs = 10,
> .ccsrbar_base = 0xFE0000000ULL,
> .pci_pio_base = 0xFE1000000ULL,
> + .pci_mmio_base = 0xC00000000ULL,
> + .pci_mmio_bus_base = 0xE0000000ULL,
> .spin_base = 0xFEF000000ULL,
> };
>
> diff --git a/hw/ppc/mpc8544ds.c b/hw/ppc/mpc8544ds.c
> index fb74b3f..3a3b141 100644
> --- a/hw/ppc/mpc8544ds.c
> +++ b/hw/ppc/mpc8544ds.c
> @@ -35,6 +35,8 @@ static void mpc8544ds_init(MachineState *machine)
> .fixup_devtree = mpc8544ds_fixup_devtree,
> .mpic_version = OPENPIC_MODEL_FSL_MPIC_20,
> .ccsrbar_base = 0xE0000000ULL,
> + .pci_mmio_base = 0xC0000000ULL,
> + .pci_mmio_bus_base = 0xC0000000ULL,
> .pci_pio_base = 0xE1000000ULL,
> .spin_base = 0xEF000000ULL,
> };
> --
> 1.8.1.4
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [Qemu-ppc] [PATCH v3 4/4] PPC: e500 pci host: Add support for ATMUs
2014-11-13 15:08 ` [Qemu-devel] [Qemu-ppc] " Bharat.Bhushan
@ 2014-11-13 19:06 ` Alexander Graf
0 siblings, 0 replies; 7+ messages in thread
From: Alexander Graf @ 2014-11-13 19:06 UTC (permalink / raw)
To: Bharat.Bhushan@freescale.com
Cc: qemu-ppc@nongnu.org, Stuart Yoder, qemu-devel@nongnu.org
> Am 13.11.2014 um 16:08 schrieb "Bharat.Bhushan@freescale.com" <Bharat.Bhushan@freescale.com>:
>
>
>
>> -----Original Message-----
>> From: qemu-ppc-bounces+bharat.bhushan=freescale.com@nongnu.org [mailto:qemu-ppc-
>> bounces+bharat.bhushan=freescale.com@nongnu.org] On Behalf Of Alexander Graf
>> Sent: Thursday, November 13, 2014 3:27 AM
>> To: qemu-ppc@nongnu.org
>> Cc: Yoder Stuart-B08248; qemu-devel@nongnu.org
>> Subject: [Qemu-ppc] [PATCH v3 4/4] PPC: e500 pci host: Add support for ATMUs
>>
>> The e500 PCI controller has configurable windows that allow a guest OS
>> to selectively map parts of the PCI bus space to CPU address space and
>> to selectively map parts of the CPU address space for DMA requests into
>> PCI visible address ranges.
>>
>> So far, we've simply assumed that this mapping is 1:1 and ignored it.
>>
>> However, the PCICSRBAR (CCSR mapped in PCI bus space) always has to live
>> inside the first 32bits of address space. This means if we always treat
>> all mappings as 1:1, this map will collide with our RAM map from the CPU's
>> point of view.
>>
>> So this patch adds proper ATMU support which allows us to keep the PCICSRBAR
>> below 32bits local to the PCI bus and have another, different window to PCI
>> BARs at the upper end of address space. We leverage this on e500plat though,
>> mpc8544ds stays virtually 1:1 like it was before, but now also goes via ATMU.
>>
>> With this patch, I can run guests with lots of RAM and not coincidently access
>> MSI-X mappings while I really want to access RAM.
>>
>> Signed-off-by: Alexander Graf <agraf@suse.de>
>> ---
>> hw/pci-host/ppce500.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++---
>> hw/ppc/e500.c | 6 +--
>> hw/ppc/e500.h | 2 +
>> hw/ppc/e500plat.c | 2 +
>> hw/ppc/mpc8544ds.c | 2 +
>> 5 files changed, 115 insertions(+), 10 deletions(-)
>>
>> diff --git a/hw/pci-host/ppce500.c b/hw/pci-host/ppce500.c
>> index 1b4c0f0..574f8b2 100644
>> --- a/hw/pci-host/ppce500.c
>> +++ b/hw/pci-host/ppce500.c
>> @@ -62,11 +62,19 @@
>> #define PPCE500_PCI_NR_POBS 5
>> #define PPCE500_PCI_NR_PIBS 3
>>
>> +#define PIWAR_EN 0x80000000 /* Enable */
>> +#define PIWAR_PF 0x20000000 /* prefetch */
>> +#define PIWAR_TGI_LOCAL 0x00f00000 /* target - local memory */
>> +#define PIWAR_READ_SNOOP 0x00050000
>> +#define PIWAR_WRITE_SNOOP 0x00005000
>> +#define PIWAR_SZ_MASK 0x0000003f
>> +
>> struct pci_outbound {
>> uint32_t potar;
>> uint32_t potear;
>> uint32_t powbar;
>> uint32_t powar;
>> + MemoryRegion mem;
>> };
>>
>> struct pci_inbound {
>> @@ -74,6 +82,7 @@ struct pci_inbound {
>> uint32_t piwbar;
>> uint32_t piwbear;
>> uint32_t piwar;
>> + MemoryRegion mem;
>> };
>>
>> #define TYPE_PPC_E500_PCI_HOST_BRIDGE "e500-pcihost"
>> @@ -91,10 +100,13 @@ struct PPCE500PCIState {
>> uint32_t irq_num[PCI_NUM_PINS];
>> uint32_t first_slot;
>> uint32_t first_pin_irq;
>> + AddressSpace bm_as;
>> + MemoryRegion bm;
>> /* mmio maps */
>> MemoryRegion container;
>> MemoryRegion iomem;
>> MemoryRegion pio;
>> + MemoryRegion busmem;
>> };
>>
>> #define TYPE_PPC_E500_PCI_BRIDGE "e500-host-bridge"
>> @@ -181,6 +193,71 @@ static uint64_t pci_reg_read4(void *opaque, hwaddr addr,
>> return value;
>> }
>>
>> +/* DMA mapping */
>> +static void e500_update_piw(PPCE500PCIState *pci, int idx)
>> +{
>> + uint64_t tar = ((uint64_t)pci->pib[idx].pitar) << 12;
>> + uint64_t wbar = ((uint64_t)pci->pib[idx].piwbar) << 12;
>> + uint64_t war = pci->pib[idx].piwar;
>> + uint64_t size = 2ULL << (war & PIWAR_SZ_MASK);
>> + MemoryRegion *address_space_mem = get_system_memory();
>> + MemoryRegion *mem = &pci->pib[idx].mem;
>> + MemoryRegion *bm = &pci->bm;
>> + char *name;
>> +
>> + if (memory_region_is_mapped(mem)) {
>> + /* Before we modify anything, unmap and destroy the region */
>> + memory_region_del_subregion(bm, mem);
>> + object_unparent(OBJECT(mem));
>> + }
>> +
>> + if (!(war & PIWAR_EN)) {
>> + /* Not enabled, nothing to do */
>> + return;
>> + }
>> +
>> + name = g_strdup_printf("PCI Inbound Window %d", idx);
>> + memory_region_init_alias(mem, OBJECT(pci), name, address_space_mem, tar,
>> + size);
>> + memory_region_add_subregion_overlap(bm, wbar, mem, -1);
>> + g_free(name);
>> +
>> + pci_debug("%s: Added window of size=%#lx from PCI=%#lx to CPU=%#lx\n",
>> + __func__, size, wbar, tar);
>> +}
>> +
>> +/* BAR mapping */
>> +static void e500_update_pow(PPCE500PCIState *pci, int idx)
>> +{
>> + uint64_t tar = ((uint64_t)pci->pob[idx].potar) << 12;
>> + uint64_t wbar = ((uint64_t)pci->pob[idx].powbar) << 12;
>> + uint64_t war = pci->pob[idx].powar;
>> + uint64_t size = 2ULL << (war & PIWAR_SZ_MASK);
>> + MemoryRegion *mem = &pci->pob[idx].mem;
>> + MemoryRegion *address_space_mem = get_system_memory();
>> + char *name;
>> +
>> + if (memory_region_is_mapped(mem)) {
>> + /* Before we modify anything, unmap and destroy the region */
>> + memory_region_del_subregion(address_space_mem, mem);
>> + object_unparent(OBJECT(mem));
>> + }
>> +
>> + if (!(war & PIWAR_EN)) {
>> + /* Not enabled, nothing to do */
>> + return;
>> + }
>> +
>> + name = g_strdup_printf("PCI Outbound Window %d", idx);
>> + memory_region_init_alias(mem, OBJECT(pci), name, &pci->busmem, tar,
>> + size);
>> + memory_region_add_subregion(address_space_mem, wbar, mem);
>> + g_free(name);
>> +
>> + pci_debug("%s: Added window of size=%#lx from CPU=%#lx to PCI=%#lx\n",
>> + __func__, size, wbar, tar);
>> +}
>> +
>> static void pci_reg_write4(void *opaque, hwaddr addr,
>> uint64_t value, unsigned size)
>> {
>> @@ -199,18 +276,22 @@ static void pci_reg_write4(void *opaque, hwaddr addr,
>> case PPCE500_PCI_OW3:
>> case PPCE500_PCI_OW4:
>> idx = (addr >> 5) & 0x7;
>> - switch (addr & 0xC) {
>> + switch (addr & 0x1F) {
>> case PCI_POTAR:
>> pci->pob[idx].potar = value;
>> + e500_update_pow(pci, idx);
>> break;
>> case PCI_POTEAR:
>> pci->pob[idx].potear = value;
>> + e500_update_pow(pci, idx);
>> break;
>> case PCI_POWBAR:
>> pci->pob[idx].powbar = value;
>> + e500_update_pow(pci, idx);
>> break;
>> case PCI_POWAR:
>> pci->pob[idx].powar = value;
>> + e500_update_pow(pci, idx);
>> break;
>> default:
>> break;
>> @@ -221,18 +302,22 @@ static void pci_reg_write4(void *opaque, hwaddr addr,
>> case PPCE500_PCI_IW2:
>> case PPCE500_PCI_IW1:
>> idx = ((addr >> 5) & 0x3) - 1;
>> - switch (addr & 0xC) {
>> + switch (addr & 0x1F) {
>> case PCI_PITAR:
>> pci->pib[idx].pitar = value;
>> + e500_update_piw(pci, idx);
>> break;
>> case PCI_PIWBAR:
>> pci->pib[idx].piwbar = value;
>> + e500_update_piw(pci, idx);
>> break;
>> case PCI_PIWBEAR:
>> pci->pib[idx].piwbear = value;
>> + e500_update_piw(pci, idx);
>> break;
>> case PCI_PIWAR:
>> pci->pib[idx].piwar = value;
>> + e500_update_piw(pci, idx);
>> break;
>> default:
>> break;
>> @@ -349,13 +434,20 @@ static int e500_pcihost_bridge_initfn(PCIDevice *d)
>> return 0;
>> }
>>
>> +static AddressSpace *e500_pcihost_set_iommu(PCIBus *bus, void *opaque,
>> + int devfn)
>> +{
>> + PPCE500PCIState *s = opaque;
>> +
>> + return &s->bm_as;
>> +}
>> +
>> static int e500_pcihost_initfn(SysBusDevice *dev)
>> {
>> PCIHostState *h;
>> PPCE500PCIState *s;
>> PCIBus *b;
>> int i;
>> - MemoryRegion *address_space_mem = get_system_memory();
>>
>> h = PCI_HOST_BRIDGE(dev);
>> s = PPC_E500_PCI_HOST_BRIDGE(dev);
>> @@ -369,12 +461,22 @@ static int e500_pcihost_initfn(SysBusDevice *dev)
>> }
>>
>> memory_region_init(&s->pio, OBJECT(s), "pci-pio", PCIE500_PCI_IOLEN);
>> + memory_region_init(&s->busmem, OBJECT(s), "pci bus memory", UINT64_MAX);
>> +
>> + /* PIO lives at the bottom of our bus space */
>> + memory_region_add_subregion_overlap(&s->busmem, 0, &s->pio, -2);
>>
>> b = pci_register_bus(DEVICE(dev), NULL, mpc85xx_pci_set_irq,
>> - mpc85xx_pci_map_irq, s, address_space_mem,
>> - &s->pio, PCI_DEVFN(s->first_slot, 0), 4,
>> TYPE_PCI_BUS);
>> + mpc85xx_pci_map_irq, s, &s->busmem, &s->pio,
>> + PCI_DEVFN(s->first_slot, 0), 4, TYPE_PCI_BUS);
>> h->bus = b;
>>
>> + /* Set up PCI view of memory */
>> + memory_region_init(&s->bm, OBJECT(s), "bm-e500", UINT64_MAX);
>> + memory_region_add_subregion(&s->bm, 0x0, &s->busmem);
>> + address_space_init(&s->bm_as, &s->bm, "pci-bm");
>> + pci_setup_iommu(b, e500_pcihost_set_iommu, s);
>> +
>> pci_create_simple(b, 0, "e500-host-bridge");
>>
>> memory_region_init(&s->container, OBJECT(h), "pci-container",
>> PCIE500_ALL_SIZE);
>> @@ -388,7 +490,6 @@ static int e500_pcihost_initfn(SysBusDevice *dev)
>> memory_region_add_subregion(&s->container, PCIE500_CFGDATA, &h->data_mem);
>> memory_region_add_subregion(&s->container, PCIE500_REG_BASE, &s->iomem);
>> sysbus_init_mmio(dev, &s->container);
>> - sysbus_init_mmio(dev, &s->pio);
>> pci_bus_set_route_irq_fn(b, e500_route_intx_pin_to_irq);
>>
>> return 0;
>> diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
>> index 1aaa515..a2e60b4 100644
>> --- a/hw/ppc/e500.c
>> +++ b/hw/ppc/e500.c
>> @@ -288,8 +288,8 @@ static int ppce500_load_device_tree(MachineState *machine,
>> int len;
>> uint32_t pci_ranges[14] =
>> {
>> - 0x2000000, 0x0, 0xc0000000,
>> - 0x0, 0xc0000000,
>> + 0x2000000, 0x0, params->pci_mmio_bus_base,
>> + params->pci_mmio_base >> 32, params->pci_mmio_base,
>> 0x0, 0x20000000,
>
> Alex, will getting these values from host (real h/w) make more sense?
IMHO we should always try as hard as we can to decouple guest hardware from host hardware. That way our complexity matrix stays managable.
Alex
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2014-11-13 19:06 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-11-12 21:56 [Qemu-devel] [PATCH v3 0/4] PPC: e500: Support more RAM Alexander Graf
2014-11-12 21:56 ` [Qemu-devel] [PATCH v3 1/4] PPC: e500: Move CCSR definition to params Alexander Graf
2014-11-12 21:56 ` [Qemu-devel] [PATCH v3 2/4] PPC: e500: Move CCSR and MMIO space to upper end of address space Alexander Graf
2014-11-12 21:56 ` [Qemu-devel] [PATCH v3 3/4] PPC: mpc8554ds: Tell user about exceeding RAM limits Alexander Graf
2014-11-12 21:56 ` [Qemu-devel] [PATCH v3 4/4] PPC: e500 pci host: Add support for ATMUs Alexander Graf
2014-11-13 15:08 ` [Qemu-devel] [Qemu-ppc] " Bharat.Bhushan
2014-11-13 19:06 ` Alexander Graf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).