From 9121d02cb33c96b444a3973579f5edc119597e81 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Mon, 15 Jul 2013 12:28:07 +0100 Subject: char/cadence_uart: Fix reset for unattached instances commit 1db8b5efe0c2b5000e50691eea61264a615f43de introduced an issue where QEMU would segfault if you have an unattached Cadence UART. Fix by guarding the flush-on-reset logic on there being a qemu_chr attachment. Reported-by: Soren Brinkmann Signed-off-by: Peter Crosthwaite Tested-by: Soren Brinkmann Message-id: 9009578ee10a50d994b2e10aa2840d73765f5968.1370577272.git.peter.crosthwaite@xilinx.com Signed-off-by: Peter Maydell --- hw/char/cadence_uart.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c index 131370a74b..4d457f8c65 100644 --- a/hw/char/cadence_uart.c +++ b/hw/char/cadence_uart.c @@ -157,7 +157,9 @@ static void uart_rx_reset(UartState *s) { s->rx_wpos = 0; s->rx_count = 0; - qemu_chr_accept_input(s->chr); + if (s->chr) { + qemu_chr_accept_input(s->chr); + } s->r[R_SR] |= UART_SR_INTR_REMPTY; s->r[R_SR] &= ~UART_SR_INTR_RFUL; -- cgit v1.2.3 From 528622421eb1be95eaadfe91e8e11729d1e46431 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 5 Jul 2013 14:54:41 +0100 Subject: hw/cpu/a15mpcore: Correct default value for num-irq The a15mpcore device claims that its default value for num-irq is the number of interrupts used by the A15MP in the vexpress-a15 board. However that chip has 128 external interrupts, not 64. Since there is only one A15 based model in QEMU currently, we can fix this by simply changing the default value. This error was causing recent (3.10) Linux kernels to print warnings/backtraces when the number of interrupts reported by the GIC was smaller than an interrupt number they wanted to use. Signed-off-by: Peter Maydell Message-id: 1373032481-15280-1-git-send-email-peter.maydell@linaro.org --- hw/cpu/a15mpcore.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c index 967b0809f3..c736257f24 100644 --- a/hw/cpu/a15mpcore.c +++ b/hw/cpu/a15mpcore.c @@ -82,12 +82,12 @@ static int a15mp_priv_init(SysBusDevice *dev) static Property a15mp_priv_properties[] = { DEFINE_PROP_UINT32("num-cpu", A15MPPrivState, num_cpu, 1), /* The Cortex-A15MP may have anything from 0 to 224 external interrupt - * IRQ lines (with another 32 internal). We default to 64+32, which + * IRQ lines (with another 32 internal). We default to 128+32, which * is the number provided by the Cortex-A15MP test chip in the * Versatile Express A15 development board. * Other boards may differ and should set this property appropriately. */ - DEFINE_PROP_UINT32("num-irq", A15MPPrivState, num_irq, 96), + DEFINE_PROP_UINT32("num-irq", A15MPPrivState, num_irq, 160), DEFINE_PROP_END_OF_LIST(), }; -- cgit v1.2.3 From 8827b0fb66cab9f7978c4e66dad4cf3c0989a72e Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 27 Jun 2013 15:03:51 +0100 Subject: sd/pl181.c: Avoid undefined shift behaviour in RWORD macro Add a cast to avoid potentially shifting into the sign bit of a signed value, which is undefined behaviour in C. (Detected with clang's -fsanitize=undefined.) Signed-off-by: Peter Maydell Message-id: 1372341831-4264-1-git-send-email-peter.maydell@linaro.org --- hw/sd/pl181.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c index 4b1723418d..f5eb1e4012 100644 --- a/hw/sd/pl181.c +++ b/hw/sd/pl181.c @@ -175,7 +175,7 @@ static void pl181_send_command(pl181_state *s) if (rlen < 0) goto error; if (s->cmd & PL181_CMD_RESPONSE) { -#define RWORD(n) ((response[n] << 24) | (response[n + 1] << 16) \ +#define RWORD(n) (((uint32_t)response[n] << 24) | (response[n + 1] << 16) \ | (response[n + 2] << 8) | response[n + 3]) if (rlen == 0 || (rlen == 4 && (s->cmd & PL181_CMD_LONGRESP))) goto error; -- cgit v1.2.3 From 7648673636bbd7dcb9abf3cc87a8ba7a65b85436 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 28 Jun 2013 13:51:59 +0100 Subject: hw/dma/omap_dma: Fix bugs with DMA requests above 32 The drqbmp field of struct soc_dma_s is a uint64_t; however several places in the code attempt to set bits in it using "(1 << drq)", which will fail if drq is large enough that the 1 bit gets shifted off the top of a 32 bit integer. Change these to "(1ULL << drq)" so that the promotion to 64 bit happens before the shift rather than afterwards. Signed-off-by: Peter Maydell Message-id: 1372423919-5669-1-git-send-email-peter.maydell@linaro.org --- hw/dma/omap_dma.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/hw/dma/omap_dma.c b/hw/dma/omap_dma.c index a81ffc4026..0e8cccd27f 100644 --- a/hw/dma/omap_dma.c +++ b/hw/dma/omap_dma.c @@ -248,7 +248,7 @@ static void omap_dma_deactivate_channel(struct omap_dma_s *s, /* Don't deactive the channel if it is synchronized and the DMA request is active */ - if (ch->sync && ch->enable && (s->dma->drqbmp & (1 << ch->sync))) + if (ch->sync && ch->enable && (s->dma->drqbmp & (1ULL << ch->sync))) return; if (ch->active) { @@ -268,8 +268,9 @@ static void omap_dma_enable_channel(struct omap_dma_s *s, /* TODO: theoretically if ch->sync && ch->prefetch && * !s->dma->drqbmp[ch->sync], we should also activate and fetch * from source and then stall until signalled. */ - if ((!ch->sync) || (s->dma->drqbmp & (1 << ch->sync))) + if ((!ch->sync) || (s->dma->drqbmp & (1ULL << ch->sync))) { omap_dma_activate_channel(s, ch); + } } } @@ -1551,12 +1552,12 @@ static void omap_dma_request(void *opaque, int drq, int req) struct omap_dma_s *s = (struct omap_dma_s *) opaque; /* The request pins are level triggered in QEMU. */ if (req) { - if (~s->dma->drqbmp & (1 << drq)) { - s->dma->drqbmp |= 1 << drq; + if (~s->dma->drqbmp & (1ULL << drq)) { + s->dma->drqbmp |= 1ULL << drq; omap_dma_process_request(s, drq); } } else - s->dma->drqbmp &= ~(1 << drq); + s->dma->drqbmp &= ~(1ULL << drq); } /* XXX: this won't be needed once soc_dma knows about clocks. */ -- cgit v1.2.3 From 8941d6ce25b43824cf96d30cb94742e02e80b2f2 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 9 Jul 2013 13:49:40 +0100 Subject: hw/arm/vexpress: Add alias for flash at address 0 on A15 board The A15 Versatile Express board can remap a variety of things at address 0. We don't currently emulate the Serial Configuration Controller which is how the guest can control this remapping, but we can provide the initial default mapping of the first flash device into this space. In particular this allows QEMU to boot flash images such as UEFI which expect to include an exception vector table. Signed-off-by: Peter Maydell Tested-by: Grant Likely Message-id: 1373374180-19884-1-git-send-email-peter.maydell@linaro.org --- hw/arm/vexpress.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c index fd18b60532..7d1b8233cd 100644 --- a/hw/arm/vexpress.c +++ b/hw/arm/vexpress.c @@ -67,6 +67,7 @@ enum { VE_CLCD, VE_NORFLASH0, VE_NORFLASH1, + VE_NORFLASHALIAS, VE_SRAM, VE_VIDEORAM, VE_ETHERNET, @@ -104,9 +105,11 @@ static hwaddr motherboard_legacy_map[] = { [VE_VIDEORAM] = 0x4c000000, [VE_ETHERNET] = 0x4e000000, [VE_USB] = 0x4f000000, + [VE_NORFLASHALIAS] = -1, /* not present */ }; static hwaddr motherboard_aseries_map[] = { + [VE_NORFLASHALIAS] = 0, /* CS0: 0x08000000 .. 0x0c000000 */ [VE_NORFLASH0] = 0x08000000, /* CS4: 0x0c000000 .. 0x10000000 */ @@ -400,10 +403,13 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard, qemu_irq pic[64]; uint32_t sys_id; DriveInfo *dinfo; + pflash_t *pflash0; ram_addr_t vram_size, sram_size; MemoryRegion *sysmem = get_system_memory(); MemoryRegion *vram = g_new(MemoryRegion, 1); MemoryRegion *sram = g_new(MemoryRegion, 1); + MemoryRegion *flashalias = g_new(MemoryRegion, 1); + MemoryRegion *flash0mem; const hwaddr *map = daughterboard->motherboard_map; int i; @@ -471,15 +477,24 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard, sysbus_create_simple("pl111", map[VE_CLCD], pic[14]); dinfo = drive_get_next(IF_PFLASH); - if (!pflash_cfi01_register(map[VE_NORFLASH0], NULL, "vexpress.flash0", + pflash0 = pflash_cfi01_register(map[VE_NORFLASH0], NULL, "vexpress.flash0", VEXPRESS_FLASH_SIZE, dinfo ? dinfo->bdrv : NULL, VEXPRESS_FLASH_SECT_SIZE, VEXPRESS_FLASH_SIZE / VEXPRESS_FLASH_SECT_SIZE, 4, - 0x00, 0x89, 0x00, 0x18, 0)) { + 0x00, 0x89, 0x00, 0x18, 0); + if (!pflash0) { fprintf(stderr, "vexpress: error registering flash 0.\n"); exit(1); } + if (map[VE_NORFLASHALIAS] != -1) { + /* Map flash 0 as an alias into low memory */ + flash0mem = sysbus_mmio_get_region(SYS_BUS_DEVICE(pflash0), 0); + memory_region_init_alias(flashalias, NULL, "vexpress.flashalias", + flash0mem, 0, VEXPRESS_FLASH_SIZE); + memory_region_add_subregion(sysmem, map[VE_NORFLASHALIAS], flashalias); + } + dinfo = drive_get_next(IF_PFLASH); if (!pflash_cfi01_register(map[VE_NORFLASH1], NULL, "vexpress.flash1", VEXPRESS_FLASH_SIZE, dinfo ? dinfo->bdrv : NULL, -- cgit v1.2.3 From 574f66bcbe10cd8fbf8bbf6d87451a944ae421bd Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Fri, 5 Jul 2013 14:21:36 +0200 Subject: ARM/highbank: prepare for adding similar machines To allow the modelling of machines similar to Calxeda Highbank, introduce a parameter to the init function and call it from a wrapper. This allows to tweak the definition for individual machines later on. Signed-off-by: Andre Przywara Message-id: 1373026897-12085-2-git-send-email-andre.przywara@calxeda.com Signed-off-by: Peter Maydell --- hw/arm/highbank.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c index 3a2fb4c81c..b8a7dd4de7 100644 --- a/hw/arm/highbank.c +++ b/hw/arm/highbank.c @@ -183,20 +183,24 @@ type_init(highbank_regs_register_types) static struct arm_boot_info highbank_binfo; +enum cxmachines { + CALXEDA_HIGHBANK, +}; + /* ram_size must be set to match the upper bound of memory in the * device tree (linux/arch/arm/boot/dts/highbank.dts), which is * normally 0xff900000 or -m 4089. When running this board on a * 32-bit host, set the reg value of memory to 0xf7ff00000 in the * device tree and pass -m 2047 to QEMU. */ -static void highbank_init(QEMUMachineInitArgs *args) +static void calxeda_init(QEMUMachineInitArgs *args, enum cxmachines machine) { ram_addr_t ram_size = args->ram_size; const char *cpu_model = args->cpu_model; const char *kernel_filename = args->kernel_filename; const char *kernel_cmdline = args->kernel_cmdline; const char *initrd_filename = args->initrd_filename; - DeviceState *dev; + DeviceState *dev = NULL; SysBusDevice *busdev; qemu_irq *irqp; qemu_irq pic[128]; @@ -208,7 +212,11 @@ static void highbank_init(QEMUMachineInitArgs *args) char *sysboot_filename; if (!cpu_model) { - cpu_model = "cortex-a9"; + switch (machine) { + case CALXEDA_HIGHBANK: + cpu_model = "cortex-a9"; + break; + } } for (n = 0; n < smp_cpus; n++) { @@ -246,7 +254,11 @@ static void highbank_init(QEMUMachineInitArgs *args) } } - dev = qdev_create(NULL, "a9mpcore_priv"); + switch (machine) { + case CALXEDA_HIGHBANK: + dev = qdev_create(NULL, "a9mpcore_priv"); + break; + } qdev_prop_set_uint32(dev, "num-cpu", smp_cpus); qdev_prop_set_uint32(dev, "num-irq", NIRQ_GIC); qdev_init_nofail(dev); @@ -324,6 +336,11 @@ static void highbank_init(QEMUMachineInitArgs *args) arm_load_kernel(ARM_CPU(first_cpu), &highbank_binfo); } +static void highbank_init(QEMUMachineInitArgs *args) +{ + calxeda_init(args, CALXEDA_HIGHBANK); +} + static QEMUMachine highbank_machine = { .name = "highbank", .desc = "Calxeda Highbank (ECX-1000)", @@ -333,9 +350,9 @@ static QEMUMachine highbank_machine = { DEFAULT_MACHINE_OPTIONS, }; -static void highbank_machine_init(void) +static void calxeda_machines_init(void) { qemu_register_machine(&highbank_machine); } -machine_init(highbank_machine_init); +machine_init(calxeda_machines_init); -- cgit v1.2.3 From b25a83f0538fceede15cba6cfd6ea0f1ffc9d777 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Fri, 5 Jul 2013 14:21:37 +0200 Subject: ARM/highbank: add support for Calxeda ECX-2000 / Midway The Calxeda ECX-2000 chip (aka. Midway) is model-wise quite similar to the Highbank. The most prominent difference is the Cortex-A15 CPU core in it, together with the associated core peripherals. Add a new ARM machine type called "midway". Move the L2 cache controller device into the Highbank specific part, since Midway does not have (and need) it. Signed-off-by: Andre Przywara Message-id: 1373026897-12085-3-git-send-email-andre.przywara@calxeda.com Signed-off-by: Peter Maydell --- hw/arm/highbank.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c index b8a7dd4de7..be264d3eb3 100644 --- a/hw/arm/highbank.c +++ b/hw/arm/highbank.c @@ -185,6 +185,7 @@ static struct arm_boot_info highbank_binfo; enum cxmachines { CALXEDA_HIGHBANK, + CALXEDA_MIDWAY, }; /* ram_size must be set to match the upper bound of memory in the @@ -216,6 +217,9 @@ static void calxeda_init(QEMUMachineInitArgs *args, enum cxmachines machine) case CALXEDA_HIGHBANK: cpu_model = "cortex-a9"; break; + case CALXEDA_MIDWAY: + cpu_model = "cortex-a15"; + break; } } @@ -256,8 +260,16 @@ static void calxeda_init(QEMUMachineInitArgs *args, enum cxmachines machine) switch (machine) { case CALXEDA_HIGHBANK: + dev = qdev_create(NULL, "l2x0"); + qdev_init_nofail(dev); + busdev = SYS_BUS_DEVICE(dev); + sysbus_mmio_map(busdev, 0, 0xfff12000); + dev = qdev_create(NULL, "a9mpcore_priv"); break; + case CALXEDA_MIDWAY: + dev = qdev_create(NULL, "a15mpcore_priv"); + break; } qdev_prop_set_uint32(dev, "num-cpu", smp_cpus); qdev_prop_set_uint32(dev, "num-irq", NIRQ_GIC); @@ -272,11 +284,6 @@ static void calxeda_init(QEMUMachineInitArgs *args, enum cxmachines machine) pic[n] = qdev_get_gpio_in(dev, n); } - dev = qdev_create(NULL, "l2x0"); - qdev_init_nofail(dev); - busdev = SYS_BUS_DEVICE(dev); - sysbus_mmio_map(busdev, 0, 0xfff12000); - dev = qdev_create(NULL, "sp804"); qdev_prop_set_uint32(dev, "freq0", 150000000); qdev_prop_set_uint32(dev, "freq1", 150000000); @@ -341,6 +348,11 @@ static void highbank_init(QEMUMachineInitArgs *args) calxeda_init(args, CALXEDA_HIGHBANK); } +static void midway_init(QEMUMachineInitArgs *args) +{ + calxeda_init(args, CALXEDA_MIDWAY); +} + static QEMUMachine highbank_machine = { .name = "highbank", .desc = "Calxeda Highbank (ECX-1000)", @@ -350,9 +362,19 @@ static QEMUMachine highbank_machine = { DEFAULT_MACHINE_OPTIONS, }; +static QEMUMachine midway_machine = { + .name = "midway", + .desc = "Calxeda Midway (ECX-2000)", + .init = midway_init, + .block_default_type = IF_SCSI, + .max_cpus = 4, + DEFAULT_MACHINE_OPTIONS, +}; + static void calxeda_machines_init(void) { qemu_register_machine(&highbank_machine); + qemu_register_machine(&midway_machine); } machine_init(calxeda_machines_init); -- cgit v1.2.3