@@ -38,6 +38,7 @@
#include "hw/pci-host/ppce500.h"
#include "qemu/error-report.h"
#include "hw/net/fsl_etsec/etsec.h"
+#include "hw/misc/dyn_sysbus_binding.h"
#define EPAPR_MAGIC (0x45504150)
#define BINARY_DEVICE_TREE_FILE "mpc8544ds.dtb"
@@ -196,13 +197,14 @@ static int sysbus_device_create_devtree(Object *obj, void *opaque)
static void platform_bus_create_devtree(PPCE500Params *params, void *fdt,
const char *mpic)
{
- gchar *node = g_strdup_printf("/platform@%"PRIx64, params->platform_bus_base);
+ gchar *node = g_strdup_printf("/platform@%"PRIx64,
+ params->dyn_sysbus_params.platform_bus_base);
const char platcomp[] = "qemu,platform\0simple-bus";
PlatformDevtreeData data;
Object *container;
- uint64_t addr = params->platform_bus_base;
- uint64_t size = params->platform_bus_size;
- int irq_start = params->platform_bus_first_irq;
+ uint64_t addr = params->dyn_sysbus_params.platform_bus_base;
+ uint64_t size = params->dyn_sysbus_params.platform_bus_size;
+ int irq_start = params->dyn_sysbus_params.platform_bus_first_irq;
/* Create a /platform node that we can put all devices into */
@@ -489,7 +491,7 @@ static int ppce500_load_device_tree(MachineState *machine,
qemu_fdt_setprop_cell(fdt, pci, "#address-cells", 3);
qemu_fdt_setprop_string(fdt, "/aliases", "pci0", pci);
- if (params->has_platform_bus) {
+ if (params->dyn_sysbus_params.has_platform_bus) {
platform_bus_create_devtree(params, fdt, mpic);
}
@@ -732,169 +734,6 @@ static qemu_irq *ppce500_init_mpic(PPCE500Params *params, MemoryRegion *ccsr,
return mpic;
}
-typedef struct PlatformBusNotifier {
- Notifier notifier;
- MemoryRegion *address_space_mem;
- qemu_irq *mpic;
- PPCE500Params params;
-} PlatformBusNotifier;
-
-typedef struct PlatformBusInitData {
- unsigned long *used_irqs;
- unsigned long *used_mem;
- MemoryRegion *mem;
- qemu_irq *irqs;
- int device_count;
- PPCE500Params *params;
-} PlatformBusInitData;
-
-static int platform_bus_map_irq(PPCE500Params *params, SysBusDevice *sbdev,
- int n, unsigned long *used_irqs,
- qemu_irq *platform_irqs)
-{
- int max_irqs = params->platform_bus_num_irqs;
- char *prop = g_strdup_printf("irq[%d]", n);
- int irqn = object_property_get_int(OBJECT(sbdev), prop, NULL);
-
- if (irqn == SYSBUS_DYNAMIC) {
- /* Find the first available IRQ */
- irqn = find_first_zero_bit(used_irqs, max_irqs);
- }
-
- if ((irqn >= max_irqs) || test_and_set_bit(irqn, used_irqs)) {
- hw_error("e500: IRQ %d is already allocated or no free IRQ left", irqn);
- }
-
- sysbus_connect_irq(sbdev, n, platform_irqs[irqn]);
- object_property_set_int(OBJECT(sbdev), irqn, prop, NULL);
-
- g_free(prop);
- return 0;
-}
-
-static int platform_bus_map_mmio(PPCE500Params *params, SysBusDevice *sbdev,
- int n, unsigned long *used_mem,
- MemoryRegion *pmem)
-{
- MemoryRegion *device_mem = sbdev->mmio[n].memory;
- uint64_t size = memory_region_size(device_mem);
- uint64_t page_size = (1 << E500_PLATFORM_BUS_PAGE_SHIFT);
- uint64_t page_mask = page_size - 1;
- uint64_t size_pages = (size + page_mask) >> E500_PLATFORM_BUS_PAGE_SHIFT;
- uint64_t max_size = params->platform_bus_size;
- uint64_t max_pages = max_size >> E500_PLATFORM_BUS_PAGE_SHIFT;
- char *prop = g_strdup_printf("mmio[%d]", n);
- hwaddr addr = object_property_get_int(OBJECT(sbdev), prop, NULL);
- int page;
- int i;
-
- page = addr >> E500_PLATFORM_BUS_PAGE_SHIFT;
- if (addr == SYSBUS_DYNAMIC) {
- uint64_t size_pages_align;
-
- /* Align the region to at least its own size granularity */
- if (is_power_of_2(size_pages)) {
- size_pages_align = size_pages;
- } else {
- size_pages_align = pow2floor(size_pages) << 1;
- }
-
- /* Find the first available region that fits */
- page = bitmap_find_next_zero_area(used_mem, max_pages, 0, size_pages,
- size_pages_align);
-
- addr = (uint64_t)page << E500_PLATFORM_BUS_PAGE_SHIFT;
- }
-
- if (page >= max_pages || test_bit(page, used_mem) ||
- (find_next_bit(used_mem, max_pages, page) < size_pages)) {
- hw_error("e500: Memory [%"PRIx64":%"PRIx64" is already allocated or "
- "no slot left", addr, size);
- }
-
- for (i = page; i < (page + size_pages); i++) {
- set_bit(i, used_mem);
- }
-
- memory_region_add_subregion(pmem, addr, device_mem);
- sbdev->mmio[n].addr = addr;
- object_property_set_int(OBJECT(sbdev), addr, prop, NULL);
-
- g_free(prop);
- return 0;
-}
-
-static int sysbus_device_check(Object *obj, void *opaque)
-{
- PlatformBusInitData *init = opaque;
- Object *dev;
- SysBusDevice *sbdev;
- int i;
-
- dev = object_dynamic_cast(obj, TYPE_SYS_BUS_DEVICE);
- sbdev = (SysBusDevice *)dev;
-
- if (!sbdev) {
- /* Container, traverse it for children */
- return object_child_foreach(obj, sysbus_device_check, opaque);
- }
-
- /* Connect sysbus device to virtual platform bus */
- for (i = 0; i < sbdev->num_irq; i++) {
- if (!sbdev->irqp[i]) {
- /* This IRQ is an incoming IRQ, we can't wire those here */
- continue;
- }
- platform_bus_map_irq(init->params, sbdev, i, init->used_irqs, init->irqs);
- }
-
- for (i = 0; i < sbdev->num_mmio; i++) {
- platform_bus_map_mmio(init->params, sbdev, i, init->used_mem, init->mem);
- }
-
- return 0;
-}
-
-static void platform_bus_init(PPCE500Params *params,
- MemoryRegion *address_space_mem,
- qemu_irq *mpic)
-{
- uint64_t max_size = params->platform_bus_size;
- uint64_t max_pages = max_size >> E500_PLATFORM_BUS_PAGE_SHIFT;
- DECLARE_BITMAP(used_irqs, params->platform_bus_num_irqs);
- DECLARE_BITMAP(used_mem, max_pages);
- MemoryRegion *platform_region = g_new(MemoryRegion, 1);
- Object *container;
- PlatformBusInitData init = {
- .used_irqs = used_irqs,
- .used_mem = used_mem,
- .mem = platform_region,
- .irqs = &mpic[params->platform_bus_first_irq],
- .params = params,
- };
-
- memory_region_init(platform_region, NULL, "platform devices",
- params->platform_bus_size);
-
- bitmap_clear(used_irqs, 0, params->platform_bus_num_irqs);
- bitmap_clear(used_mem, 0, max_pages);
-
- /* Loop through all sysbus devices that were spawened outside the machine */
- container = container_get(qdev_get_machine(), "/peripheral");
- sysbus_device_check(container, &init);
- container = container_get(qdev_get_machine(), "/peripheral-anon");
- sysbus_device_check(container, &init);
-
- memory_region_add_subregion(address_space_mem, params->platform_bus_base,
- platform_region);
-}
-
-static void platform_bus_init_notify(Notifier *notifier, void *data)
-{
- PlatformBusNotifier *pn = (PlatformBusNotifier *)notifier;
- platform_bus_init(&pn->params, pn->address_space_mem, pn->mpic);
-}
-
void ppce500_init(MachineState *machine, PPCE500Params *params)
{
MemoryRegion *address_space_mem = get_system_memory();
@@ -1047,13 +886,15 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)
}
/* Platform Devices */
- if (params->has_platform_bus) {
- PlatformBusNotifier *notifier = g_new(PlatformBusNotifier, 1);
+ if (params->dyn_sysbus_params.has_platform_bus) {
+ DynSysbusNotifier *notifier = g_new(DynSysbusNotifier, 1);
+ params->dyn_sysbus_params.page_shift =
+ E500_PLATFORM_BUS_PAGE_SHIFT;
notifier->notifier.notify = platform_bus_init_notify;
notifier->address_space_mem = address_space_mem;
notifier->mpic = mpic;
- notifier->params = *params;
+ notifier->params = params->dyn_sysbus_params;
qemu_add_machine_init_done_notifier(¬ifier->notifier);
}
@@ -2,6 +2,7 @@
#define PPCE500_H
#include "hw/boards.h"
+#include "hw/misc/dyn_sysbus_binding.h"
typedef struct PPCE500Params {
int pci_first_slot;
@@ -11,11 +12,7 @@ typedef struct PPCE500Params {
void (*fixup_devtree)(struct PPCE500Params *params, void *fdt);
int mpic_version;
- bool has_platform_bus;
- hwaddr platform_bus_base;
- hwaddr platform_bus_size;
- int platform_bus_first_irq;
- int platform_bus_num_irqs;
+ DynSysbusParams dyn_sysbus_params;
} PPCE500Params;
void ppce500_init(MachineState *machine, PPCE500Params *params);
@@ -35,11 +35,14 @@ static void e500plat_init(MachineState *machine)
.pci_nr_slots = PCI_SLOT_MAX - 1,
.fixup_devtree = e500plat_fixup_devtree,
.mpic_version = OPENPIC_MODEL_FSL_MPIC_42,
- .has_platform_bus = true,
- .platform_bus_base = 0xf00000000ULL,
- .platform_bus_size = (128ULL * 1024 * 1024),
- .platform_bus_first_irq = 5,
- .platform_bus_num_irqs = 10,
+ .dyn_sysbus_params = {
+ .has_platform_bus = true,
+ .platform_bus_base = 0xf00000000ULL,
+ .platform_bus_size = (128ULL * 1024 * 1024),
+ .platform_bus_first_irq = 5,
+ .platform_bus_num_irqs = 10,
+ .page_shift = 12 /* default */
+ }
};
/* Older KVM versions don't support EPR which breaks guests when we announce