diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2015-11-03 14:54:40 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2015-11-03 14:54:40 +0000 |
commit | 79cf9fad341e6e7bd6b55395b71d5c5727d7f5b0 (patch) | |
tree | e8f39cefc49eac77c0e713ec08660a72e070e374 | |
parent | 19bb5467135df4b234af2c93bf6c50284158d6ca (diff) | |
parent | 5d9c1756140d680e66e5b45005a1fb7078b74ee1 (diff) |
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20151103' into staging
target-arm queue:
* code cleanup to use symbolic constants for register bank numbers
* fix direct booting of modern Linux kernels on xilinx_zynq by setting
SCLR values to what the kernel expects firmware to have done
* implement SYSRESETREQ for ARMv7M CPU (stellaris boards)
* update MAINTAINERS to mention new qemu-arm mailing list
* clean up display of PSTATE in AArch64 debug logs
* report Secure/Nonsecure status in CPU debug logs
* fix a missing _CCA attribute in ACPI tables
* add support for GICv3 to ACPI tables
# gpg: Signature made Tue 03 Nov 2015 13:58:46 GMT using RSA key ID 14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"
# gpg: aka "Peter Maydell <pmaydell@gmail.com>"
# gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>"
* remotes/pmaydell/tags/pull-target-arm-20151103:
ARM: ACPI: Fix MPIDR value in ACPI table
hw/arm/virt-acpi-build: Add GICC ACPI subtable for GICv3
hw/arm/virt-acpi-build: _CCA attribute is compulsory
target-arm: Report S/NS status in the CPU debug logs
target-arm: Bring AArch64 debug CPU display of PSTATE into line with AArch32
MAINTAINERS: Add new qemu-arm mailing list to ARM related entries
arm: stellaris: exit on external reset request
armv7-m: Implement SYSRESETREQ
armv7-m: Return DeviceState* from armv7m_init()
arm: xilinx_zynq: Add linux pre-boot
arm: boot: Add board specific setup code API
arm: boot: Adjust indentation of FIXUP comments
target-arm: Add and use symbolic names for register banks
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | MAINTAINERS | 23 | ||||
-rw-r--r-- | hw/arm/armv7m.c | 9 | ||||
-rw-r--r-- | hw/arm/boot.c | 36 | ||||
-rw-r--r-- | hw/arm/stellaris.c | 41 | ||||
-rw-r--r-- | hw/arm/stm32f205_soc.c | 15 | ||||
-rw-r--r-- | hw/arm/virt-acpi-build.c | 33 | ||||
-rw-r--r-- | hw/arm/xilinx_zynq.c | 42 | ||||
-rw-r--r-- | hw/intc/armv7m_nvic.c | 9 | ||||
-rw-r--r-- | include/hw/arm/arm.h | 12 | ||||
-rw-r--r-- | target-arm/helper.c | 37 | ||||
-rw-r--r-- | target-arm/internals.h | 16 | ||||
-rw-r--r-- | target-arm/kvm32.c | 34 | ||||
-rw-r--r-- | target-arm/op_helper.c | 8 | ||||
-rw-r--r-- | target-arm/translate-a64.c | 17 | ||||
-rw-r--r-- | target-arm/translate.c | 12 |
15 files changed, 251 insertions, 93 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 314411332c..fc8abe8dd3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -81,6 +81,7 @@ F: disas/alpha.c ARM M: Peter Maydell <peter.maydell@linaro.org> +L: qemu-arm@nongnu.org S: Maintained F: target-arm/ F: hw/arm/ @@ -216,6 +217,7 @@ F: */kvm.* ARM M: Peter Maydell <peter.maydell@linaro.org> +L: qemu-arm@nongnu.org S: Maintained F: target-arm/kvm.c @@ -287,6 +289,7 @@ ARM Machines ------------ Allwinner-a10 M: Beniamino Galvani <b.galvani@gmail.com> +L: qemu-arm@nongnu.org S: Maintained F: hw/*/allwinner* F: include/hw/*/allwinner* @@ -294,6 +297,7 @@ F: hw/arm/cubieboard.c ARM PrimeCell M: Peter Maydell <peter.maydell@linaro.org> +L: qemu-arm@nongnu.org S: Maintained F: hw/char/pl011.c F: hw/display/pl110* @@ -308,6 +312,7 @@ F: include/hw/arm/primecell.h ARM cores M: Peter Maydell <peter.maydell@linaro.org> +L: qemu-arm@nongnu.org S: Maintained F: hw/intc/arm* F: hw/intc/gic_internal.h @@ -327,54 +332,64 @@ M: Evgeny Voevodin <e.voevodin@samsung.com> M: Maksim Kozlov <m.kozlov@samsung.com> M: Igor Mitsyanko <i.mitsyanko@gmail.com> M: Dmitry Solodkiy <d.solodkiy@samsung.com> +L: qemu-arm@nongnu.org S: Maintained F: hw/*/exynos* Calxeda Highbank M: Rob Herring <robh@kernel.org> +L: qemu-arm@nongnu.org S: Maintained F: hw/arm/highbank.c F: hw/net/xgmac.c Canon DIGIC M: Antony Pavlov <antonynpavlov@gmail.com> +L: qemu-arm@nongnu.org S: Maintained F: include/hw/arm/digic.h F: hw/*/digic* Gumstix L: qemu-devel@nongnu.org +L: qemu-arm@nongnu.org S: Orphan F: hw/arm/gumstix.c i.MX31 M: Peter Chubb <peter.chubb@nicta.com.au> +L: qemu-arm@nongnu.org S: Odd fixes F: hw/*/imx* F: hw/arm/kzm.c Integrator CP M: Peter Maydell <peter.maydell@linaro.org> +L: qemu-arm@nongnu.org S: Maintained F: hw/arm/integratorcp.c Musicpal M: Jan Kiszka <jan.kiszka@web.de> +L: qemu-arm@nongnu.org S: Maintained F: hw/arm/musicpal.c nSeries M: Andrzej Zaborowski <balrogg@gmail.com> +L: qemu-arm@nongnu.org S: Maintained F: hw/arm/nseries.c Palm M: Andrzej Zaborowski <balrogg@gmail.com> +L: qemu-arm@nongnu.org S: Maintained F: hw/arm/palm.c Real View M: Peter Maydell <peter.maydell@linaro.org> +L: qemu-arm@nongnu.org S: Maintained F: hw/arm/realview* F: hw/intc/realview_gic.c @@ -382,6 +397,7 @@ F: include/hw/intc/realview_gic.h PXA2XX M: Andrzej Zaborowski <balrogg@gmail.com> +L: qemu-arm@nongnu.org S: Maintained F: hw/arm/mainstone.c F: hw/arm/spitz.c @@ -391,17 +407,20 @@ F: hw/*/pxa2xx* Stellaris M: Peter Maydell <peter.maydell@linaro.org> +L: qemu-arm@nongnu.org S: Maintained F: hw/*/stellaris* Versatile PB M: Peter Maydell <peter.maydell@linaro.org> +L: qemu-arm@nongnu.org S: Maintained F: hw/*/versatile* Xilinx Zynq M: Alistair Francis <alistair.francis@xilinx.com> M: Peter Crosthwaite <crosthwaite.peter@gmail.com> +L: qemu-arm@nongnu.org S: Maintained F: hw/arm/xilinx_zynq.c F: hw/misc/zynq_slcr.c @@ -411,6 +430,7 @@ F: hw/ssi/xilinx_spips.c Xilinx ZynqMP M: Alistair Francis <alistair.francis@xilinx.com> M: Peter Crosthwaite <crosthwaite.peter@gmail.com> +L: qemu-arm@nongnu.org S: Maintained F: hw/arm/xlnx-zynqmp.c F: hw/arm/xlnx-ep108.c @@ -419,6 +439,7 @@ F: include/hw/arm/xlnx-zynqmp.h ARM ACPI Subsystem M: Shannon Zhao <zhaoshenglong@huawei.com> M: Shannon Zhao <shannon.zhao@linaro.org> +L: qemu-arm@nongnu.org S: Maintained F: hw/arm/virt-acpi-build.c F: include/hw/arm/virt-acpi-build.h @@ -1235,6 +1256,7 @@ AArch64 target M: Claudio Fontana <claudio.fontana@huawei.com> M: Claudio Fontana <claudio.fontana@gmail.com> S: Maintained +L: qemu-arm@nongnu.org F: tcg/aarch64/ F: disas/arm-a64.cc F: disas/libvixl/ @@ -1242,6 +1264,7 @@ F: disas/libvixl/ ARM target M: Andrzej Zaborowski <balrogg@gmail.com> S: Maintained +L: qemu-arm@nongnu.org F: tcg/arm/ F: disas/arm.c diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c index eb214db443..a80d2ad29c 100644 --- a/hw/arm/armv7m.c +++ b/hw/arm/armv7m.c @@ -166,17 +166,15 @@ static void armv7m_reset(void *opaque) mem_size is in bytes. Returns the NVIC array. */ -qemu_irq *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq, +DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq, const char *kernel_filename, const char *cpu_model) { ARMCPU *cpu; CPUARMState *env; DeviceState *nvic; - qemu_irq *pic = g_new(qemu_irq, num_irq); int image_size; uint64_t entry; uint64_t lowaddr; - int i; int big_endian; MemoryRegion *hack = g_new(MemoryRegion, 1); @@ -198,9 +196,6 @@ qemu_irq *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq, qdev_init_nofail(nvic); sysbus_connect_irq(SYS_BUS_DEVICE(nvic), 0, qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ)); - for (i = 0; i < num_irq; i++) { - pic[i] = qdev_get_gpio_in(nvic, i); - } #ifdef TARGET_WORDS_BIGENDIAN big_endian = 1; @@ -234,7 +229,7 @@ qemu_irq *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq, memory_region_add_subregion(system_memory, 0xfffff000, hack); qemu_register_reset(armv7m_reset, cpu); - return pic; + return nvic; } static Property bitband_properties[] = { diff --git a/hw/arm/boot.c b/hw/arm/boot.c index bef451b3b2..b0879a5e76 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -28,14 +28,15 @@ #define KERNEL64_LOAD_ADDR 0x00080000 typedef enum { - FIXUP_NONE = 0, /* do nothing */ - FIXUP_TERMINATOR, /* end of insns */ - FIXUP_BOARDID, /* overwrite with board ID number */ - FIXUP_ARGPTR, /* overwrite with pointer to kernel args */ - FIXUP_ENTRYPOINT, /* overwrite with kernel entry point */ - FIXUP_GIC_CPU_IF, /* overwrite with GIC CPU interface address */ - FIXUP_BOOTREG, /* overwrite with boot register address */ - FIXUP_DSB, /* overwrite with correct DSB insn for cpu */ + FIXUP_NONE = 0, /* do nothing */ + FIXUP_TERMINATOR, /* end of insns */ + FIXUP_BOARDID, /* overwrite with board ID number */ + FIXUP_BOARD_SETUP, /* overwrite with board specific setup code address */ + FIXUP_ARGPTR, /* overwrite with pointer to kernel args */ + FIXUP_ENTRYPOINT, /* overwrite with kernel entry point */ + FIXUP_GIC_CPU_IF, /* overwrite with GIC CPU interface address */ + FIXUP_BOOTREG, /* overwrite with boot register address */ + FIXUP_DSB, /* overwrite with correct DSB insn for cpu */ FIXUP_MAX, } FixupType; @@ -58,8 +59,17 @@ static const ARMInsnFixup bootloader_aarch64[] = { { 0, FIXUP_TERMINATOR } }; -/* The worlds second smallest bootloader. Set r0-r2, then jump to kernel. */ +/* A very small bootloader: call the board-setup code (if needed), + * set r0-r2, then jump to the kernel. + * If we're not calling boot setup code then we don't copy across + * the first BOOTLOADER_NO_BOARD_SETUP_OFFSET insns in this array. + */ + static const ARMInsnFixup bootloader[] = { + { 0xe28fe008 }, /* add lr, pc, #8 */ + { 0xe51ff004 }, /* ldr pc, [pc, #-4] */ + { 0, FIXUP_BOARD_SETUP }, +#define BOOTLOADER_NO_BOARD_SETUP_OFFSET 3 { 0xe3a00000 }, /* mov r0, #0 */ { 0xe59f1004 }, /* ldr r1, [pc, #4] */ { 0xe59f2004 }, /* ldr r2, [pc, #4] */ @@ -131,6 +141,7 @@ static void write_bootloader(const char *name, hwaddr addr, case FIXUP_NONE: break; case FIXUP_BOARDID: + case FIXUP_BOARD_SETUP: case FIXUP_ARGPTR: case FIXUP_ENTRYPOINT: case FIXUP_GIC_CPU_IF: @@ -640,6 +651,9 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data) elf_machine = EM_AARCH64; } else { primary_loader = bootloader; + if (!info->write_board_setup) { + primary_loader += BOOTLOADER_NO_BOARD_SETUP_OFFSET; + } kernel_load_offset = KERNEL_LOAD_ADDR; elf_machine = EM_ARM; } @@ -745,6 +759,7 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data) info->initrd_size = initrd_size; fixupcontext[FIXUP_BOARDID] = info->board_id; + fixupcontext[FIXUP_BOARD_SETUP] = info->board_setup_addr; /* for device tree boot, we pass the DTB directly in r2. Otherwise * we point to the kernel args. @@ -793,6 +808,9 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data) if (info->nb_cpus > 1) { info->write_secondary_boot(cpu, info); } + if (info->write_board_setup) { + info->write_board_setup(cpu, info); + } /* Notify devices which need to fake up firmware initialization * that we're doing a direct kernel boot. diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c index 3d6486fcf5..0114e0a7f8 100644 --- a/hw/arm/stellaris.c +++ b/hw/arm/stellaris.c @@ -16,6 +16,7 @@ #include "net/net.h" #include "hw/boards.h" #include "exec/address-spaces.h" +#include "sysemu/sysemu.h" #define GPIO_A 0 #define GPIO_B 1 @@ -1176,6 +1177,14 @@ static int stellaris_adc_init(SysBusDevice *sbd) return 0; } +static +void do_sys_reset(void *opaque, int n, int level) +{ + if (level) { + qemu_system_reset_request(); + } +} + /* Board init. */ static stellaris_board_info stellaris_boards[] = { { "LM3S811EVB", @@ -1210,8 +1219,7 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, 0x40024000, 0x40025000, 0x40026000}; static const int gpio_irq[7] = {0, 1, 2, 3, 4, 30, 31}; - qemu_irq *pic; - DeviceState *gpio_dev[7]; + DeviceState *gpio_dev[7], *nvic; qemu_irq gpio_in[7][8]; qemu_irq gpio_out[7][8]; qemu_irq adc; @@ -1241,12 +1249,19 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, vmstate_register_ram_global(sram); memory_region_add_subregion(system_memory, 0x20000000, sram); - pic = armv7m_init(system_memory, flash_size, NUM_IRQ_LINES, + nvic = armv7m_init(system_memory, flash_size, NUM_IRQ_LINES, kernel_filename, cpu_model); + qdev_connect_gpio_out_named(nvic, "SYSRESETREQ", 0, + qemu_allocate_irq(&do_sys_reset, NULL, 0)); + if (board->dc1 & (1 << 16)) { dev = sysbus_create_varargs(TYPE_STELLARIS_ADC, 0x40038000, - pic[14], pic[15], pic[16], pic[17], NULL); + qdev_get_gpio_in(nvic, 14), + qdev_get_gpio_in(nvic, 15), + qdev_get_gpio_in(nvic, 16), + qdev_get_gpio_in(nvic, 17), + NULL); adc = qdev_get_gpio_in(dev, 0); } else { adc = NULL; @@ -1255,19 +1270,21 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, if (board->dc2 & (0x10000 << i)) { dev = sysbus_create_simple(TYPE_STELLARIS_GPTM, 0x40030000 + i * 0x1000, - pic[timer_irq[i]]); + qdev_get_gpio_in(nvic, timer_irq[i])); /* TODO: This is incorrect, but we get away with it because the ADC output is only ever pulsed. */ qdev_connect_gpio_out(dev, 0, adc); } } - stellaris_sys_init(0x400fe000, pic[28], board, nd_table[0].macaddr.a); + stellaris_sys_init(0x400fe000, qdev_get_gpio_in(nvic, 28), + board, nd_table[0].macaddr.a); for (i = 0; i < 7; i++) { if (board->dc4 & (1 << i)) { gpio_dev[i] = sysbus_create_simple("pl061_luminary", gpio_addr[i], - pic[gpio_irq[i]]); + qdev_get_gpio_in(nvic, + gpio_irq[i])); for (j = 0; j < 8; j++) { gpio_in[i][j] = qdev_get_gpio_in(gpio_dev[i], j); gpio_out[i][j] = NULL; @@ -1276,7 +1293,8 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, } if (board->dc2 & (1 << 12)) { - dev = sysbus_create_simple(TYPE_STELLARIS_I2C, 0x40020000, pic[8]); + dev = sysbus_create_simple(TYPE_STELLARIS_I2C, 0x40020000, + qdev_get_gpio_in(nvic, 8)); i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c"); if (board->peripherals & BP_OLED_I2C) { i2c_create_slave(i2c, "ssd0303", 0x3d); @@ -1286,11 +1304,12 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, for (i = 0; i < 4; i++) { if (board->dc2 & (1 << i)) { sysbus_create_simple("pl011_luminary", 0x4000c000 + i * 0x1000, - pic[uart_irq[i]]); + qdev_get_gpio_in(nvic, uart_irq[i])); } } if (board->dc2 & (1 << 4)) { - dev = sysbus_create_simple("pl022", 0x40008000, pic[7]); + dev = sysbus_create_simple("pl022", 0x40008000, + qdev_get_gpio_in(nvic, 7)); if (board->peripherals & BP_OLED_SSI) { void *bus; DeviceState *sddev; @@ -1326,7 +1345,7 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, qdev_set_nic_properties(enet, &nd_table[0]); qdev_init_nofail(enet); sysbus_mmio_map(SYS_BUS_DEVICE(enet), 0, 0x40048000); - sysbus_connect_irq(SYS_BUS_DEVICE(enet), 0, pic[42]); + sysbus_connect_irq(SYS_BUS_DEVICE(enet), 0, qdev_get_gpio_in(nvic, 42)); } if (board->peripherals & BP_GAMEPAD) { qemu_irq gpad_irq[5]; diff --git a/hw/arm/stm32f205_soc.c b/hw/arm/stm32f205_soc.c index 4d26a7ed91..3f993406dd 100644 --- a/hw/arm/stm32f205_soc.c +++ b/hw/arm/stm32f205_soc.c @@ -59,9 +59,8 @@ static void stm32f205_soc_initfn(Object *obj) static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp) { STM32F205State *s = STM32F205_SOC(dev_soc); - DeviceState *syscfgdev, *usartdev, *timerdev; + DeviceState *syscfgdev, *usartdev, *timerdev, *nvic; SysBusDevice *syscfgbusdev, *usartbusdev, *timerbusdev; - qemu_irq *pic; Error *err = NULL; int i; @@ -88,8 +87,8 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp) vmstate_register_ram_global(sram); memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram); - pic = armv7m_init(get_system_memory(), FLASH_SIZE, 96, - s->kernel_filename, s->cpu_model); + nvic = armv7m_init(get_system_memory(), FLASH_SIZE, 96, + s->kernel_filename, s->cpu_model); /* System configuration controller */ syscfgdev = DEVICE(&s->syscfg); @@ -100,7 +99,7 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp) } syscfgbusdev = SYS_BUS_DEVICE(syscfgdev); sysbus_mmio_map(syscfgbusdev, 0, 0x40013800); - sysbus_connect_irq(syscfgbusdev, 0, pic[71]); + sysbus_connect_irq(syscfgbusdev, 0, qdev_get_gpio_in(nvic, 71)); /* Attach UART (uses USART registers) and USART controllers */ for (i = 0; i < STM_NUM_USARTS; i++) { @@ -112,7 +111,8 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp) } usartbusdev = SYS_BUS_DEVICE(usartdev); sysbus_mmio_map(usartbusdev, 0, usart_addr[i]); - sysbus_connect_irq(usartbusdev, 0, pic[usart_irq[i]]); + sysbus_connect_irq(usartbusdev, 0, + qdev_get_gpio_in(nvic, usart_irq[i])); } /* Timer 2 to 5 */ @@ -126,7 +126,8 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp) } timerbusdev = SYS_BUS_DEVICE(timerdev); sysbus_mmio_map(timerbusdev, 0, timer_addr[i]); - sysbus_connect_irq(timerbusdev, 0, pic[timer_irq[i]]); + sysbus_connect_irq(timerbusdev, 0, + qdev_get_gpio_in(nvic, timer_irq[i])); } } diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 1aaff1f662..3c2c5d6bfa 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -180,6 +180,7 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, int irq, aml_append(dev, aml_name_decl("_ADR", aml_int(0))); aml_append(dev, aml_name_decl("_UID", aml_string("PCI0"))); aml_append(dev, aml_name_decl("_STR", aml_unicode("PCIe 0 Device"))); + aml_append(dev, aml_name_decl("_CCA", aml_int(1))); /* Declare the PCI Routing Table. */ Aml *rt_pkg = aml_package(nr_pcie_buses * PCI_NUM_PINS); @@ -448,6 +449,24 @@ build_madt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info, gicd->length = sizeof(*gicd); gicd->base_address = memmap[VIRT_GIC_DIST].base; + for (i = 0; i < guest_info->smp_cpus; i++) { + AcpiMadtGenericInterrupt *gicc = acpi_data_push(table_data, + sizeof *gicc); + ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i)); + + gicc->type = ACPI_APIC_GENERIC_INTERRUPT; + gicc->length = sizeof(*gicc); + if (guest_info->gic_version == 2) { + gicc->base_address = memmap[VIRT_GIC_CPU].base; + } + gicc->cpu_interface_number = i; + gicc->arm_mpidr = armcpu->mp_affinity; + gicc->uid = i; + if (test_bit(i, cpuinfo->found_cpus)) { + gicc->flags = cpu_to_le32(ACPI_GICC_ENABLED); + } + } + if (guest_info->gic_version == 3) { AcpiMadtGenericRedistributor *gicr = acpi_data_push(table_data, sizeof *gicr); @@ -457,20 +476,6 @@ build_madt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info, gicr->base_address = cpu_to_le64(memmap[VIRT_GIC_REDIST].base); gicr->range_length = cpu_to_le32(memmap[VIRT_GIC_REDIST].size); } else { - for (i = 0; i < guest_info->smp_cpus; i++) { - AcpiMadtGenericInterrupt *gicc = acpi_data_push(table_data, - sizeof *gicc); - gicc->type = ACPI_APIC_GENERIC_INTERRUPT; - gicc->length = sizeof(*gicc); - gicc->base_address = memmap[VIRT_GIC_CPU].base; - gicc->cpu_interface_number = i; - gicc->arm_mpidr = i; - gicc->uid = i; - if (test_bit(i, cpuinfo->found_cpus)) { - gicc->flags = cpu_to_le32(ACPI_GICC_ENABLED); - } - } - gic_msi = acpi_data_push(table_data, sizeof *gic_msi); gic_msi->type = ACPI_APIC_GENERIC_MSI_FRAME; gic_msi->length = sizeof(*gic_msi); diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c index 9f89483d6a..82a9db8120 100644 --- a/hw/arm/xilinx_zynq.c +++ b/hw/arm/xilinx_zynq.c @@ -43,6 +43,45 @@ static const int dma_irqs[8] = { 46, 47, 48, 49, 72, 73, 74, 75 }; +#define BOARD_SETUP_ADDR 0x100 + +#define SLCR_LOCK_OFFSET 0x004 +#define SLCR_UNLOCK_OFFSET 0x008 +#define SLCR_ARM_PLL_OFFSET 0x100 + +#define SLCR_XILINX_UNLOCK_KEY 0xdf0d +#define SLCR_XILINX_LOCK_KEY 0x767b + +#define ARMV7_IMM16(x) (extract32((x), 0, 12) | \ + extract32((x), 12, 4) << 16) + +/* Write immediate val to address r0 + addr. r0 should contain base offset + * of the SLCR block. Clobbers r1. + */ + +#define SLCR_WRITE(addr, val) \ + 0xe3001000 + ARMV7_IMM16(extract32((val), 0, 16)), /* movw r1 ... */ \ + 0xe3401000 + ARMV7_IMM16(extract32((val), 16, 16)), /* movt r1 ... */ \ + 0xe5801000 + (addr) + +static void zynq_write_board_setup(ARMCPU *cpu, + const struct arm_boot_info *info) +{ + int n; + uint32_t board_setup_blob[] = { + 0xe3a004f8, /* mov r0, #0xf8000000 */ + SLCR_WRITE(SLCR_UNLOCK_OFFSET, SLCR_XILINX_UNLOCK_KEY), + SLCR_WRITE(SLCR_ARM_PLL_OFFSET, 0x00014008), + SLCR_WRITE(SLCR_LOCK_OFFSET, SLCR_XILINX_LOCK_KEY), + 0xe12fff1e, /* bx lr */ + }; + for (n = 0; n < ARRAY_SIZE(board_setup_blob); n++) { + board_setup_blob[n] = tswap32(board_setup_blob[n]); + } + rom_add_blob_fixed("board-setup", board_setup_blob, + sizeof(board_setup_blob), BOARD_SETUP_ADDR); +} + static struct arm_boot_info zynq_binfo = {}; static void gem_init(NICInfo *nd, uint32_t base, qemu_irq irq) @@ -252,6 +291,9 @@ static void zynq_init(MachineState *machine) zynq_binfo.nb_cpus = 1; zynq_binfo.board_id = 0xd32; zynq_binfo.loader_start = 0; + zynq_binfo.board_setup_addr = BOARD_SETUP_ADDR; + zynq_binfo.write_board_setup = zynq_write_board_setup; + arm_load_kernel(ARM_CPU(first_cpu), &zynq_binfo); } diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index 3ec8408618..6fc167e230 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -28,6 +28,7 @@ typedef struct { MemoryRegion gic_iomem_alias; MemoryRegion container; uint32_t num_irq; + qemu_irq sysresetreq; } nvic_state; #define TYPE_NVIC "armv7m_nvic" @@ -348,10 +349,13 @@ static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value) break; case 0xd0c: /* Application Interrupt/Reset Control. */ if ((value >> 16) == 0x05fa) { + if (value & 4) { + qemu_irq_pulse(s->sysresetreq); + } if (value & 2) { qemu_log_mask(LOG_UNIMP, "VECTCLRACTIVE unimplemented\n"); } - if (value & 5) { + if (value & 1) { qemu_log_mask(LOG_UNIMP, "AIRCR system reset unimplemented\n"); } if (value & 0x700) { @@ -535,11 +539,14 @@ static void armv7m_nvic_instance_init(Object *obj) * value in the GICState struct. */ GICState *s = ARM_GIC_COMMON(obj); + DeviceState *dev = DEVICE(obj); + nvic_state *nvic = NVIC(obj); /* The ARM v7m may have anything from 0 to 496 external interrupt * IRQ lines. We default to 64. Other boards may differ and should * set the num-irq property appropriately. */ s->num_irq = 64; + qdev_init_gpio_out_named(dev, &nvic->sysresetreq, "SYSRESETREQ", 1); } static void armv7m_nvic_class_init(ObjectClass *klass, void *data) diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h index 4dcd4f9b63..67ba7db3bb 100644 --- a/include/hw/arm/arm.h +++ b/include/hw/arm/arm.h @@ -17,7 +17,7 @@ #include "cpu.h" /* armv7m.c */ -qemu_irq *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq, +DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq, const char *kernel_filename, const char *cpu_model); /* @@ -87,6 +87,16 @@ struct arm_boot_info { * -pflash. It also implies that fw_cfg_find() will succeed. */ bool firmware_loaded; + + /* Address at which board specific loader/setup code exists. If enabled, + * this code-blob will run before anything else. It must return to the + * caller via the link register. There is no stack set up. Enabled by + * defining write_board_setup, which is responsible for loading the blob + * to the specified address. + */ + hwaddr board_setup_addr; + void (*write_board_setup)(ARMCPU *cpu, + const struct arm_boot_info *info); }; /** diff --git a/target-arm/helper.c b/target-arm/helper.c index 1966f9c045..4ecae61197 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -3130,7 +3130,8 @@ static const ARMCPRegInfo v8_cp_reginfo[] = { { .name = "SPSR_EL1", .state = ARM_CP_STATE_AA64, .type = ARM_CP_ALIAS, .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 0, .opc2 = 0, - .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, banked_spsr[1]) }, + .access = PL1_RW, + .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_SVC]) }, /* We rely on the access checks not allowing the guest to write to the * state field when SPSel indicates that it's being used as the stack * pointer. @@ -3299,23 +3300,28 @@ static const ARMCPRegInfo el2_cp_reginfo[] = { { .name = "SPSR_EL2", .state = ARM_CP_STATE_AA64, .type = ARM_CP_ALIAS, .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 0, - .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, banked_spsr[6]) }, + .access = PL2_RW, + .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_HYP]) }, { .name = "SPSR_IRQ", .state = ARM_CP_STATE_AA64, .type = ARM_CP_ALIAS, .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 0, - .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, banked_spsr[4]) }, + .access = PL2_RW, + .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_IRQ]) }, { .name = "SPSR_ABT", .state = ARM_CP_STATE_AA64, .type = ARM_CP_ALIAS, .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 1, - .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, banked_spsr[2]) }, + .access = PL2_RW, + .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_ABT]) }, { .name = "SPSR_UND", .state = ARM_CP_STATE_AA64, .type = ARM_CP_ALIAS, .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 2, - .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, banked_spsr[3]) }, + .access = PL2_RW, + .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_UND]) }, { .name = "SPSR_FIQ", .state = ARM_CP_STATE_AA64, .type = ARM_CP_ALIAS, .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 3, - .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, banked_spsr[5]) }, + .access = PL2_RW, + .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_FIQ]) }, { .name = "VBAR_EL2", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 0, .access = PL2_RW, .writefn = vbar_write, @@ -3552,7 +3558,8 @@ static const ARMCPRegInfo el3_cp_reginfo[] = { { .name = "SPSR_EL3", .state = ARM_CP_STATE_AA64, .type = ARM_CP_ALIAS, .opc0 = 3, .opc1 = 6, .crn = 4, .crm = 0, .opc2 = 0, - .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, banked_spsr[7]) }, + .access = PL3_RW, + .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_MON]) }, { .name = "VBAR_EL3", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 6, .crn = 12, .crm = 0, .opc2 = 0, .access = PL3_RW, .writefn = vbar_write, @@ -5183,21 +5190,21 @@ int bank_number(int mode) switch (mode) { case ARM_CPU_MODE_USR: case ARM_CPU_MODE_SYS: - return 0; + return BANK_USRSYS; case ARM_CPU_MODE_SVC: - return 1; + return BANK_SVC; case ARM_CPU_MODE_ABT: - return 2; + return BANK_ABT; case ARM_CPU_MODE_UND: - return 3; + return BANK_UND; case ARM_CPU_MODE_IRQ: - return 4; + return BANK_IRQ; case ARM_CPU_MODE_FIQ: - return 5; + return BANK_FIQ; case ARM_CPU_MODE_HYP: - return 6; + return BANK_HYP; case ARM_CPU_MODE_MON: - return 7; + return BANK_MON; } g_assert_not_reached(); } diff --git a/target-arm/internals.h b/target-arm/internals.h index 412827bcbf..347998c8be 100644 --- a/target-arm/internals.h +++ b/target-arm/internals.h @@ -25,6 +25,16 @@ #ifndef TARGET_ARM_INTERNALS_H #define TARGET_ARM_INTERNALS_H +/* register banks for CPU modes */ +#define BANK_USRSYS 0 +#define BANK_SVC 1 +#define BANK_ABT 2 +#define BANK_UND 3 +#define BANK_IRQ 4 +#define BANK_FIQ 5 +#define BANK_HYP 6 +#define BANK_MON 7 + static inline bool excp_is_internal(int excp) { /* Return true if this exception number represents a QEMU-internal @@ -91,9 +101,9 @@ static inline void arm_log_exception(int idx) static inline unsigned int aarch64_banked_spsr_index(unsigned int el) { static const unsigned int map[4] = { - [1] = 1, /* EL1. */ - [2] = 6, /* EL2. */ - [3] = 7, /* EL3. */ + [1] = BANK_SVC, /* EL1. */ + [2] = BANK_HYP, /* EL2. */ + [3] = BANK_MON, /* EL3. */ }; assert(el >= 1 && el <= 3); return map[el]; diff --git a/target-arm/kvm32.c b/target-arm/kvm32.c index 3ae57a6d68..df1e2b0ebf 100644 --- a/target-arm/kvm32.c +++ b/target-arm/kvm32.c @@ -280,30 +280,30 @@ static const Reg regs[] = { COREREG(usr_regs.uregs[10], usr_regs[2]), COREREG(usr_regs.uregs[11], usr_regs[3]), COREREG(usr_regs.uregs[12], usr_regs[4]), - COREREG(usr_regs.uregs[13], banked_r13[0]), - COREREG(usr_regs.uregs[14], banked_r14[0]), + COREREG(usr_regs.uregs[13], banked_r13[BANK_USRSYS]), + COREREG(usr_regs.uregs[14], banked_r14[BANK_USRSYS]), /* R13, R14, SPSR for SVC, ABT, UND, IRQ banks */ - COREREG(svc_regs[0], banked_r13[1]), - COREREG(svc_regs[1], banked_r14[1]), - COREREG64(svc_regs[2], banked_spsr[1]), - COREREG(abt_regs[0], banked_r13[2]), - COREREG(abt_regs[1], banked_r14[2]), - COREREG64(abt_regs[2], banked_spsr[2]), - COREREG(und_regs[0], banked_r13[3]), - COREREG(und_regs[1], banked_r14[3]), - COREREG64(und_regs[2], banked_spsr[3]), - COREREG(irq_regs[0], banked_r13[4]), - COREREG(irq_regs[1], banked_r14[4]), - COREREG64(irq_regs[2], banked_spsr[4]), + COREREG(svc_regs[0], banked_r13[BANK_SVC]), + COREREG(svc_regs[1], banked_r14[BANK_SVC]), + COREREG64(svc_regs[2], banked_spsr[BANK_SVC]), + COREREG(abt_regs[0], banked_r13[BANK_ABT]), + COREREG(abt_regs[1], banked_r14[BANK_ABT]), + COREREG64(abt_regs[2], banked_spsr[BANK_ABT]), + COREREG(und_regs[0], banked_r13[BANK_UND]), + COREREG(und_regs[1], banked_r14[BANK_UND]), + COREREG64(und_regs[2], banked_spsr[BANK_UND]), + COREREG(irq_regs[0], banked_r13[BANK_IRQ]), + COREREG(irq_regs[1], banked_r14[BANK_IRQ]), + COREREG64(irq_regs[2], banked_spsr[BANK_IRQ]), /* R8_fiq .. R14_fiq and SPSR_fiq */ COREREG(fiq_regs[0], fiq_regs[0]), COREREG(fiq_regs[1], fiq_regs[1]), COREREG(fiq_regs[2], fiq_regs[2]), COREREG(fiq_regs[3], fiq_regs[3]), COREREG(fiq_regs[4], fiq_regs[4]), - COREREG(fiq_regs[5], banked_r13[5]), - COREREG(fiq_regs[6], banked_r14[5]), - COREREG64(fiq_regs[7], banked_spsr[5]), + COREREG(fiq_regs[5], banked_r13[BANK_FIQ]), + COREREG(fiq_regs[6], banked_r14[BANK_FIQ]), + COREREG64(fiq_regs[7], banked_spsr[BANK_FIQ]), /* R15 */ COREREG(usr_regs.uregs[15], regs[15]), /* VFP system registers */ diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index a4c4ebf9cd..b5db345ccd 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -392,9 +392,9 @@ uint32_t HELPER(get_user_reg)(CPUARMState *env, uint32_t regno) uint32_t val; if (regno == 13) { - val = env->banked_r13[0]; + val = env->banked_r13[BANK_USRSYS]; } else if (regno == 14) { - val = env->banked_r14[0]; + val = env->banked_r14[BANK_USRSYS]; } else if (regno >= 8 && (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) { val = env->usr_regs[regno - 8]; @@ -407,9 +407,9 @@ uint32_t HELPER(get_user_reg)(CPUARMState *env, uint32_t regno) void HELPER(set_user_reg)(CPUARMState *env, uint32_t regno, uint32_t val) { if (regno == 13) { - env->banked_r13[0] = val; + env->banked_r13[BANK_USRSYS] = val; } else if (regno == 14) { - env->banked_r14[0] = val; + env->banked_r14[BANK_USRSYS] = val; } else if (regno >= 8 && (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) { env->usr_regs[regno - 8] = val; diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index 83b8376210..d7e09549c0 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -126,6 +126,8 @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f, CPUARMState *env = &cpu->env; uint32_t psr = pstate_read(env); int i; + int el = arm_current_el(env); + const char *ns_status; cpu_fprintf(f, "PC=%016"PRIx64" SP=%016"PRIx64"\n", env->pc, env->xregs[31]); @@ -137,13 +139,22 @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f, cpu_fprintf(f, " "); } } - cpu_fprintf(f, "PSTATE=%08x (flags %c%c%c%c)\n", + + if (arm_feature(env, ARM_FEATURE_EL3) && el != 3) { + ns_status = env->cp15.scr_el3 & SCR_NS ? "NS " : "S "; + } else { + ns_status = ""; + } + + cpu_fprintf(f, "\nPSTATE=%08x %c%c%c%c %sEL%d%c\n", psr, psr & PSTATE_N ? 'N' : '-', psr & PSTATE_Z ? 'Z' : '-', psr & PSTATE_C ? 'C' : '-', - psr & PSTATE_V ? 'V' : '-'); - cpu_fprintf(f, "\n"); + psr & PSTATE_V ? 'V' : '-', + ns_status, + el, + psr & PSTATE_SP ? 'h' : 't'); if (flags & CPU_DUMP_FPU) { int numvfpregs = 32; diff --git a/target-arm/translate.c b/target-arm/translate.c index b10a455e70..ff262a2572 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -11602,6 +11602,7 @@ void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, CPUARMState *env = &cpu->env; int i; uint32_t psr; + const char *ns_status; if (is_a64(env)) { aarch64_cpu_dump_state(cs, f, cpu_fprintf, flags); @@ -11616,13 +11617,22 @@ void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, cpu_fprintf(f, " "); } psr = cpsr_read(env); - cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n", + + if (arm_feature(env, ARM_FEATURE_EL3) && + (psr & CPSR_M) != ARM_CPU_MODE_MON) { + ns_status = env->cp15.scr_el3 & SCR_NS ? "NS " : "S "; + } else { + ns_status = ""; + } + + cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%s%d\n", psr, psr & (1 << 31) ? 'N' : '-', psr & (1 << 30) ? 'Z' : '-', psr & (1 << 29) ? 'C' : '-', psr & (1 << 28) ? 'V' : '-', psr & CPSR_T ? 'T' : 'A', + ns_status, cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26); if (flags & CPU_DUMP_FPU) { |