From 6e411af9351c1b82c2a749653eb4b8d35bf8c04a Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sun, 29 Jun 2014 18:38:39 +0100 Subject: [PATCH 1/8] hw/arm/virt: Provide PL031 RTC UEFI mandates that the platform must include an RTC, so provide one in 'virt', using the PL031. This is also useful for directly booting Linux kernels which would otherwise have to run ntpdate. Signed-off-by: Peter Maydell Tested-by: Aurelien Jarno Reviewed-by: Aurelien Jarno --- hw/arm/virt.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 72fe030e93..405c61d39c 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -65,6 +65,7 @@ enum { VIRT_GIC_CPU, VIRT_UART, VIRT_MMIO, + VIRT_RTC, }; typedef struct MemMapEntry { @@ -92,6 +93,8 @@ typedef struct VirtBoardInfo { * high memory region beyond 4GB). * This represents a compromise between how much RAM can be given to * a 32 bit VM and leaving space for expansion and in particular for PCI. + * Note that devices should generally be placed at multiples of 0x10000, + * to accommodate guests using 64K pages. */ static const MemMapEntry a15memmap[] = { /* Space up to 0x8000000 is reserved for a boot ROM */ @@ -101,6 +104,7 @@ static const MemMapEntry a15memmap[] = { [VIRT_GIC_DIST] = { 0x8000000, 0x10000 }, [VIRT_GIC_CPU] = { 0x8010000, 0x10000 }, [VIRT_UART] = { 0x9000000, 0x1000 }, + [VIRT_RTC] = { 0x90010000, 0x1000 }, [VIRT_MMIO] = { 0xa000000, 0x200 }, /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ /* 0x10000000 .. 0x40000000 reserved for PCI */ @@ -109,6 +113,7 @@ static const MemMapEntry a15memmap[] = { static const int a15irqmap[] = { [VIRT_UART] = 1, + [VIRT_RTC] = 2, [VIRT_MMIO] = 16, /* ...to 16 + NUM_VIRTIO_TRANSPORTS - 1 */ }; @@ -353,6 +358,29 @@ static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic) g_free(nodename); } +static void create_rtc(const VirtBoardInfo *vbi, qemu_irq *pic) +{ + char *nodename; + hwaddr base = vbi->memmap[VIRT_RTC].base; + hwaddr size = vbi->memmap[VIRT_RTC].size; + int irq = vbi->irqmap[VIRT_RTC]; + const char compat[] = "arm,pl031\0arm,primecell"; + + sysbus_create_simple("pl031", base, pic[irq]); + + nodename = g_strdup_printf("/pl031@%" PRIx64, base); + qemu_fdt_add_subnode(vbi->fdt, nodename); + qemu_fdt_setprop(vbi->fdt, nodename, "compatible", compat, sizeof(compat)); + qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg", + 2, base, 2, size); + qemu_fdt_setprop_cells(vbi->fdt, nodename, "interrupts", + GIC_FDT_IRQ_TYPE_SPI, irq, + GIC_FDT_IRQ_FLAGS_EDGE_LO_HI); + qemu_fdt_setprop_cell(vbi->fdt, nodename, "clocks", vbi->clock_phandle); + qemu_fdt_setprop_string(vbi->fdt, nodename, "clock-names", "apb_pclk"); + g_free(nodename); +} + static void create_virtio_devices(const VirtBoardInfo *vbi, qemu_irq *pic) { int i; @@ -469,6 +497,8 @@ static void machvirt_init(MachineState *machine) create_uart(vbi, pic); + create_rtc(vbi, pic); + /* Create mmio transports, so the user can create virtio backends * (which will be automatically plugged in to the transports). If * no backend is created the transport will just sit harmlessly idle. From 92335a0d4021a3b44ccc88c9fc6c0fd2113f1882 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sun, 29 Jun 2014 18:38:39 +0100 Subject: [PATCH 2/8] hw/arm/strongarm: Fix handling of GPSR/GPCR reads The StrongARM GPIO GPSR and GPCR registers are write-only, with reads being undefined behaviour. Instead of having GPCR return 31337 and GPSR return the value last written, make both log the guest error and return 0. Signed-off-by: Peter Maydell Reviewed-by: Peter Crosthwaite --- hw/arm/strongarm.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c index 0da9015333..cc2d7f20e9 100644 --- a/hw/arm/strongarm.c +++ b/hw/arm/strongarm.c @@ -480,7 +480,6 @@ struct StrongARMGPIOInfo { uint32_t rising; uint32_t falling; uint32_t status; - uint32_t gpsr; uint32_t gafr; uint32_t prev_level; @@ -544,14 +543,14 @@ static uint64_t strongarm_gpio_read(void *opaque, hwaddr offset, return s->dir; case GPSR: /* GPIO Pin-Output Set registers */ - DPRINTF("%s: Read from a write-only register 0x" TARGET_FMT_plx "\n", - __func__, offset); - return s->gpsr; /* Return last written value. */ + qemu_log_mask(LOG_GUEST_ERROR, + "strongarm GPIO: read from write only register GPSR\n"); + return 0; case GPCR: /* GPIO Pin-Output Clear registers */ - DPRINTF("%s: Read from a write-only register 0x" TARGET_FMT_plx "\n", - __func__, offset); - return 31337; /* Specified as unpredictable in the docs. */ + qemu_log_mask(LOG_GUEST_ERROR, + "strongarm GPIO: read from write only register GPCR\n"); + return 0; case GRER: /* GPIO Rising-Edge Detect Enable registers */ return s->rising; @@ -590,7 +589,6 @@ static void strongarm_gpio_write(void *opaque, hwaddr offset, case GPSR: /* GPIO Pin-Output Set registers */ s->olevel |= value; strongarm_gpio_handler_update(s); - s->gpsr = value; break; case GPCR: /* GPIO Pin-Output Clear registers */ From ed657d7117d751dfaf5b00e5b17e45cd4a6d974d Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sun, 29 Jun 2014 18:38:39 +0100 Subject: [PATCH 3/8] hw/arm/strongarm: Wire up missing GPIO and PPC vmstate The VMStateDescription structs for the GPIO and PPC devices were accidentally never wired up. Add missing state fields and register them via dc->vmsd. Signed-off-by: Peter Maydell Reviewed-by: Peter Crosthwaite --- hw/arm/strongarm.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c index cc2d7f20e9..9e2a0d48aa 100644 --- a/hw/arm/strongarm.c +++ b/hw/arm/strongarm.c @@ -674,6 +674,7 @@ static const VMStateDescription vmstate_strongarm_gpio_regs = { VMSTATE_UINT32(falling, StrongARMGPIOInfo), VMSTATE_UINT32(status, StrongARMGPIOInfo), VMSTATE_UINT32(gafr, StrongARMGPIOInfo), + VMSTATE_UINT32(prev_level, StrongARMGPIOInfo), VMSTATE_END_OF_LIST(), }, }; @@ -685,6 +686,7 @@ static void strongarm_gpio_class_init(ObjectClass *klass, void *data) k->init = strongarm_gpio_initfn; dc->desc = "StrongARM GPIO controller"; + dc->vmsd = &vmstate_strongarm_gpio_regs; } static const TypeInfo strongarm_gpio_info = { @@ -844,6 +846,7 @@ static const VMStateDescription vmstate_strongarm_ppc_regs = { VMSTATE_UINT32(ppar, StrongARMPPCInfo), VMSTATE_UINT32(psdr, StrongARMPPCInfo), VMSTATE_UINT32(ppfr, StrongARMPPCInfo), + VMSTATE_UINT32(prev_level, StrongARMPPCInfo), VMSTATE_END_OF_LIST(), }, }; @@ -855,6 +858,7 @@ static void strongarm_ppc_class_init(ObjectClass *klass, void *data) k->init = strongarm_ppc_init; dc->desc = "StrongARM PPC controller"; + dc->vmsd = &vmstate_strongarm_ppc_regs; } static const TypeInfo strongarm_ppc_info = { From ab7a0f0b6dbe8836d490c736803abef6e3695e1f Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sun, 29 Jun 2014 18:38:40 +0100 Subject: [PATCH 4/8] hw/arm/pxa2xx_gpio: Fix handling of GPSR/GPCR reads The PXA2xx GPIO GPSR and GPCR registers are write-only, with reads being undefined behaviour. Instead of having GPCR return 31337 and GPSR return the value last written, make both log the guest error and return 0. Signed-off-by: Peter Maydell Reviewed-by: Peter Crosthwaite --- hw/arm/pxa2xx_gpio.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/hw/arm/pxa2xx_gpio.c b/hw/arm/pxa2xx_gpio.c index 7f75f05137..cd506dfd1a 100644 --- a/hw/arm/pxa2xx_gpio.c +++ b/hw/arm/pxa2xx_gpio.c @@ -36,7 +36,6 @@ struct PXA2xxGPIOInfo { uint32_t rising[PXA2XX_GPIO_BANKS]; uint32_t falling[PXA2XX_GPIO_BANKS]; uint32_t status[PXA2XX_GPIO_BANKS]; - uint32_t gpsr[PXA2XX_GPIO_BANKS]; uint32_t gafr[PXA2XX_GPIO_BANKS * 2]; uint32_t prev_level[PXA2XX_GPIO_BANKS]; @@ -162,14 +161,14 @@ static uint64_t pxa2xx_gpio_read(void *opaque, hwaddr offset, return s->dir[bank]; case GPSR: /* GPIO Pin-Output Set registers */ - printf("%s: Read from a write-only register " REG_FMT "\n", - __FUNCTION__, offset); - return s->gpsr[bank]; /* Return last written value. */ + qemu_log_mask(LOG_GUEST_ERROR, + "pxa2xx GPIO: read from write only register GPSR\n"); + return 0; case GPCR: /* GPIO Pin-Output Clear registers */ - printf("%s: Read from a write-only register " REG_FMT "\n", - __FUNCTION__, offset); - return 31337; /* Specified as unpredictable in the docs. */ + qemu_log_mask(LOG_GUEST_ERROR, + "pxa2xx GPIO: read from write only register GPCR\n"); + return 0; case GRER: /* GPIO Rising-Edge Detect Enable registers */ return s->rising[bank]; @@ -217,7 +216,6 @@ static void pxa2xx_gpio_write(void *opaque, hwaddr offset, case GPSR: /* GPIO Pin-Output Set registers */ s->olevel[bank] |= value; pxa2xx_gpio_handler_update(s); - s->gpsr[bank] = value; break; case GPCR: /* GPIO Pin-Output Clear registers */ From 166fa9999688ebbcc3db945309bbdcef1aab5774 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sun, 29 Jun 2014 18:38:40 +0100 Subject: [PATCH 5/8] hw/arm/pxa2xx_gpio: Correct and register vmstate The pxa2xx-gpio device has a VMStateDescription, but it was accidentally never actually registered, and it wasn't quite correct. Remove the 'lines' field (this is a device property, not mutable state), add the missing 'prev_level' field, and set dc->vmsd so it actually gets used. Signed-off-by: Peter Maydell Reviewed-by: Peter Crosthwaite --- hw/arm/pxa2xx_gpio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/arm/pxa2xx_gpio.c b/hw/arm/pxa2xx_gpio.c index cd506dfd1a..354ccf1ea1 100644 --- a/hw/arm/pxa2xx_gpio.c +++ b/hw/arm/pxa2xx_gpio.c @@ -312,7 +312,6 @@ static const VMStateDescription vmstate_pxa2xx_gpio_regs = { .version_id = 1, .minimum_version_id = 1, .fields = (VMStateField[]) { - VMSTATE_INT32(lines, PXA2xxGPIOInfo), VMSTATE_UINT32_ARRAY(ilevel, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS), VMSTATE_UINT32_ARRAY(olevel, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS), VMSTATE_UINT32_ARRAY(dir, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS), @@ -320,6 +319,7 @@ static const VMStateDescription vmstate_pxa2xx_gpio_regs = { VMSTATE_UINT32_ARRAY(falling, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS), VMSTATE_UINT32_ARRAY(status, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS), VMSTATE_UINT32_ARRAY(gafr, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS * 2), + VMSTATE_UINT32_ARRAY(prev_level, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS), VMSTATE_END_OF_LIST(), }, }; @@ -338,6 +338,7 @@ static void pxa2xx_gpio_class_init(ObjectClass *klass, void *data) k->init = pxa2xx_gpio_initfn; dc->desc = "PXA2xx GPIO controller"; dc->props = pxa2xx_gpio_properties; + dc->vmsd = &vmstate_pxa2xx_gpio_regs; } static const TypeInfo pxa2xx_gpio_info = { From b841642daa0252b3de711214bc4874ed415586a8 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Sun, 29 Jun 2014 18:38:40 +0100 Subject: [PATCH 6/8] timer: cadence_ttc: Convert to instance_init SysBusDevice::init is deprecated. Convert to instance_init as prescribed by QOM conventions. Signed-off-by: Alistair Francis Message-id: 1223f14833159b9ea5c57734dd2ffa88d4b15a83.1403583596.git.alistair.francis@xilinx.com Reviewed-by: Peter Crosthwaite Signed-off-by: Peter Maydell --- hw/timer/cadence_ttc.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/hw/timer/cadence_ttc.c b/hw/timer/cadence_ttc.c index 52bbbbca7f..d46db3c0e2 100644 --- a/hw/timer/cadence_ttc.c +++ b/hw/timer/cadence_ttc.c @@ -406,21 +406,19 @@ static void cadence_timer_init(uint32_t freq, CadenceTimerState *s) s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cadence_timer_tick, s); } -static int cadence_ttc_init(SysBusDevice *dev) +static void cadence_ttc_init(Object *obj) { - CadenceTTCState *s = CADENCE_TTC(dev); + CadenceTTCState *s = CADENCE_TTC(obj); int i; for (i = 0; i < 3; ++i) { cadence_timer_init(133000000, &s->timer[i]); - sysbus_init_irq(dev, &s->timer[i].irq); + sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->timer[i].irq); } - memory_region_init_io(&s->iomem, OBJECT(s), &cadence_ttc_ops, s, + memory_region_init_io(&s->iomem, obj, &cadence_ttc_ops, s, "timer", 0x1000); - sysbus_init_mmio(dev, &s->iomem); - - return 0; + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem); } static void cadence_timer_pre_save(void *opaque) @@ -474,9 +472,7 @@ static const VMStateDescription vmstate_cadence_ttc = { static void cadence_ttc_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass); - sdc->init = cadence_ttc_init; dc->vmsd = &vmstate_cadence_ttc; } @@ -484,6 +480,7 @@ static const TypeInfo cadence_ttc_info = { .name = TYPE_CADENCE_TTC, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(CadenceTTCState), + .instance_init = cadence_ttc_init, .class_init = cadence_ttc_class_init, }; From 1ce8be7e0de4698b1c8bd76ea568e1f46524412c Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 27 May 2014 13:43:48 -0700 Subject: [PATCH 7/8] disas/libvixl: Update README for version base Signed-off-by: Richard Henderson Signed-off-by: Peter Maydell --- disas/libvixl/README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/disas/libvixl/README b/disas/libvixl/README index 96814a5dc1..a0ecac3dd3 100644 --- a/disas/libvixl/README +++ b/disas/libvixl/README @@ -2,7 +2,7 @@ The code in this directory is a subset of libvixl: https://github.com/armvixl/vixl (specifically, it is the set of files needed for disassembly only, -taken from libvixl 1.1). +taken from libvixl 1.4). Bugfixes should preferably be sent upstream initially. The disassembler does not currently support the entire A64 instruction From ffebe8997523fd922da58a8e19ddffee6b035429 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Wed, 18 Jun 2014 19:49:11 +0200 Subject: [PATCH 8/8] disas/libvixl: Fix wrong format strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the compiler is told to check the arguments of AppendToOutput, it reports several errors of this kind: error: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘int64_t {aka long int}’ [-Werror=format] Fix those bugs by using the correct format strings with PRId64, PRIx64. Signed-off-by: Stefan Weil Message-id: 1403113751-19799-1-git-send-email-sw@weilnetz.de Signed-off-by: Peter Maydell --- disas/libvixl/a64/disasm-a64.cc | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/disas/libvixl/a64/disasm-a64.cc b/disas/libvixl/a64/disasm-a64.cc index aa133a99bf..f81ce4bbb8 100644 --- a/disas/libvixl/a64/disasm-a64.cc +++ b/disas/libvixl/a64/disasm-a64.cc @@ -1369,7 +1369,7 @@ int Disassembler::SubstituteImmediateField(Instruction* instr, VIXL_ASSERT(format[5] == 'L'); AppendToOutput("#0x%" PRIx64, instr->ImmMoveWide()); if (instr->ShiftMoveWide() > 0) { - AppendToOutput(", lsl #%d", 16 * instr->ShiftMoveWide()); + AppendToOutput(", lsl #%" PRId64, 16 * instr->ShiftMoveWide()); } } return 8; @@ -1418,7 +1418,7 @@ int Disassembler::SubstituteImmediateField(Instruction* instr, } case 'F': { // IFPSingle, IFPDouble or IFPFBits. if (format[3] == 'F') { // IFPFbits. - AppendToOutput("#%d", 64 - instr->FPScale()); + AppendToOutput("#%" PRId64, 64 - instr->FPScale()); return 8; } else { AppendToOutput("#0x%" PRIx64 " (%.4f)", instr->ImmFP(), @@ -1439,23 +1439,23 @@ int Disassembler::SubstituteImmediateField(Instruction* instr, return 5; } case 'P': { // IP - Conditional compare. - AppendToOutput("#%d", instr->ImmCondCmp()); + AppendToOutput("#%" PRId64, instr->ImmCondCmp()); return 2; } case 'B': { // Bitfields. return SubstituteBitfieldImmediateField(instr, format); } case 'E': { // IExtract. - AppendToOutput("#%d", instr->ImmS()); + AppendToOutput("#%" PRId64, instr->ImmS()); return 8; } case 'S': { // IS - Test and branch bit. - AppendToOutput("#%d", (instr->ImmTestBranchBit5() << 5) | - instr->ImmTestBranchBit40()); + AppendToOutput("#%" PRId64, (instr->ImmTestBranchBit5() << 5) | + instr->ImmTestBranchBit40()); return 2; } case 'D': { // IDebug - HLT and BRK instructions. - AppendToOutput("#0x%x", instr->ImmException()); + AppendToOutput("#0x%" PRIx64, instr->ImmException()); return 6; } default: { @@ -1626,12 +1626,12 @@ int Disassembler::SubstituteExtendField(Instruction* instr, (((instr->ExtendMode() == UXTW) && (instr->SixtyFourBits() == 0)) || (instr->ExtendMode() == UXTX))) { if (instr->ImmExtendShift() > 0) { - AppendToOutput(", lsl #%d", instr->ImmExtendShift()); + AppendToOutput(", lsl #%" PRId64, instr->ImmExtendShift()); } } else { AppendToOutput(", %s", extend_mode[instr->ExtendMode()]); if (instr->ImmExtendShift() > 0) { - AppendToOutput(" #%d", instr->ImmExtendShift()); + AppendToOutput(" #%" PRId64, instr->ImmExtendShift()); } } return 3; @@ -1660,7 +1660,7 @@ int Disassembler::SubstituteLSRegOffsetField(Instruction* instr, if (!((ext == UXTX) && (shift == 0))) { AppendToOutput(", %s", extend_mode[ext]); if (shift != 0) { - AppendToOutput(" #%d", instr->SizeLS()); + AppendToOutput(" #%" PRId64, instr->SizeLS()); } } return 9;