@@ -25,42 +25,44 @@ typedef struct XlnxEP108 {
MemoryRegion ddr_ram;
} XlnxEP108;
-/* Max 2GB RAM */
-#define EP108_MAX_RAM_SIZE 0x80000000ull
-
static struct arm_boot_info xlnx_ep108_binfo;
static void xlnx_ep108_init(MachineState *machine)
{
XlnxEP108 *s = g_new0(XlnxEP108, 1);
Error *err = NULL;
+ uint64_t ram_size = machine->ram_size;
+
+ /* Create the memory region to pass to the SoC */
+ if (ram_size > XLNX_ZYNQMP_MAX_RAM_SIZE) {
+ error_report("ERROR: RAM size 0x%" PRIx64 " above max supported of "
+ "0x%llx", ram_size,
+ XLNX_ZYNQMP_MAX_RAM_SIZE);
+ exit(1);
+ }
+
+ if (ram_size < 0x08000000) {
+ qemu_log("WARNING: RAM size 0x%" PRIx64 " is small for EP108",
+ ram_size);
+ }
+
+ memory_region_allocate_system_memory(&s->ddr_ram, NULL, "ddr-ram",
+ ram_size);
object_initialize(&s->soc, sizeof(s->soc), TYPE_XLNX_ZYNQMP);
object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc),
&error_abort);
+ object_property_set_link(OBJECT(&s->soc), OBJECT(&s->ddr_ram),
+ "ddr-ram", &error_abort);
+
object_property_set_bool(OBJECT(&s->soc), true, "realized", &err);
if (err) {
error_report_err(err);
exit(1);
}
- if (machine->ram_size > EP108_MAX_RAM_SIZE) {
- error_report("WARNING: RAM size " RAM_ADDR_FMT " above max supported, "
- "reduced to %llx", machine->ram_size, EP108_MAX_RAM_SIZE);
- machine->ram_size = EP108_MAX_RAM_SIZE;
- }
-
- if (machine->ram_size < 0x08000000) {
- qemu_log("WARNING: RAM size " RAM_ADDR_FMT " is small for EP108",
- machine->ram_size);
- }
-
- memory_region_allocate_system_memory(&s->ddr_ram, NULL, "ddr-ram",
- machine->ram_size);
- memory_region_add_subregion(get_system_memory(), 0, &s->ddr_ram);
-
- xlnx_ep108_binfo.ram_size = machine->ram_size;
+ xlnx_ep108_binfo.ram_size = ram_size;
xlnx_ep108_binfo.kernel_filename = machine->kernel_filename;
xlnx_ep108_binfo.kernel_cmdline = machine->kernel_cmdline;
xlnx_ep108_binfo.initrd_filename = machine->initrd_filename;
@@ -90,6 +90,11 @@ static void xlnx_zynqmp_init(Object *obj)
&error_abort);
}
+ object_property_add_link(obj, "ddr-ram", TYPE_MEMORY_REGION,
+ (Object **)&s->ddr_ram,
+ qdev_prop_allow_set_link_before_realize,
+ OBJ_PROP_LINK_UNREF_ON_RELEASE, &error_abort);
+
object_initialize(&s->gic, sizeof(s->gic), TYPE_ARM_GIC);
qdev_set_parent_bus(DEVICE(&s->gic), sysbus_get_default());
@@ -119,10 +124,42 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
XlnxZynqMPState *s = XLNX_ZYNQMP(dev);
MemoryRegion *system_memory = get_system_memory();
uint8_t i;
+ uint64_t ram_size;
const char *boot_cpu = s->boot_cpu ? s->boot_cpu : "apu-cpu[0]";
+ ram_addr_t ddr_low_size, ddr_high_size;
qemu_irq gic_spi[GIC_NUM_SPI_INTR];
Error *err = NULL;
+ ram_size = memory_region_size(s->ddr_ram);
+
+ /* Create the DDR Memory Regions. User friendly checks should happen at
+ * the board level
+ */
+ if (ram_size > XLNX_ZYNQMP_MAX_LOW_RAM_SIZE) {
+ /* The RAM size is above the maximum available for the low DDR.
+ * Create the high DDR memory region as well.
+ */
+ assert(ram_size <= XLNX_ZYNQMP_MAX_RAM_SIZE);
+ ddr_low_size = XLNX_ZYNQMP_MAX_LOW_RAM_SIZE;
+ ddr_high_size = ram_size - XLNX_ZYNQMP_MAX_LOW_RAM_SIZE;
+
+ memory_region_init_alias(&s->ddr_ram_high, NULL,
+ "ddr-ram-high", s->ddr_ram,
+ ddr_low_size, ddr_high_size);
+ memory_region_add_subregion(get_system_memory(),
+ XLNX_ZYNQMP_HIGH_RAM_START,
+ &s->ddr_ram_high);
+ } else {
+ /* RAM must be non-zero */
+ assert(ram_size);
+ ddr_low_size = ram_size;
+ }
+
+ memory_region_init_alias(&s->ddr_ram_low, NULL,
+ "ddr-ram-low", s->ddr_ram,
+ 0, ddr_low_size);
+ memory_region_add_subregion(get_system_memory(), 0, &s->ddr_ram_low);
+
/* Create the four OCM banks */
for (i = 0; i < XLNX_ZYNQMP_NUM_OCM_BANKS; i++) {
char *ocm_name = g_strdup_printf("zynqmp.ocm_ram_bank_%d", i);
@@ -51,6 +51,14 @@
#define XLNX_ZYNQMP_GIC_REGION_SIZE 0x1000
#define XLNX_ZYNQMP_GIC_ALIASES (0x10000 / XLNX_ZYNQMP_GIC_REGION_SIZE - 1)
+#define XLNX_ZYNQMP_MAX_LOW_RAM_SIZE 0x80000000ull
+
+#define XLNX_ZYNQMP_MAX_HIGH_RAM_SIZE 0x800000000ull
+#define XLNX_ZYNQMP_HIGH_RAM_START 0x800000000ull
+
+#define XLNX_ZYNQMP_MAX_RAM_SIZE (XLNX_ZYNQMP_MAX_LOW_RAM_SIZE + \
+ XLNX_ZYNQMP_MAX_HIGH_RAM_SIZE)
+
typedef struct XlnxZynqMPState {
/*< private >*/
DeviceState parent_obj;
@@ -60,8 +68,12 @@ typedef struct XlnxZynqMPState {
ARMCPU rpu_cpu[XLNX_ZYNQMP_NUM_RPU_CPUS];
GICState gic;
MemoryRegion gic_mr[XLNX_ZYNQMP_GIC_REGIONS][XLNX_ZYNQMP_GIC_ALIASES];
+
MemoryRegion ocm_ram[XLNX_ZYNQMP_NUM_OCM_BANKS];
+ MemoryRegion *ddr_ram;
+ MemoryRegion ddr_ram_low, ddr_ram_high;
+
CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS];
CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS];
SysbusAHCIState sata;