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
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABCAAGBQJWOL2WAAoJEDwlJe0UNgzeJhEQAIZeC9hfomlu1QGVS7HmlzQ6
 Vao9PyW9oxNIc91oweCWzVjQConhZW15dZsGwPiRyCa+vrgn2fss/NCBa5w2Rr72
 xOSKRl12iXBGDay3GJsvBV/ZHwJTxxvowvEmSRl58IBdRG1Fn823FbHi/b7E8m4k
 GXWisdJ1C6r0FCS2TodSXAqkwL3fgScbEt5xAM0Zt9tkR+Z6HPMKJ2ZtZY9Kzd6S
 47LLcF8Sawffs625TKcIoUxoXhc+SPloqNAWwH7u/ey9vsrpJjUmNxeSkcR1xb8v
 FTxWXm51D5dZRUFfMio22aYAY9ct7u2l07MAuIQ37rzr3LDMlBMDdZ5sV92Y1EG5
 /1SbqWkaWJv4gs2+w6YjuIo3XavMuYnqukZsSvhma891L8KazPISFjwJbLFnh92Y
 xvcGOCiHAxHFY705laiOMOWCdvsRJBzBDjV7mTqjCM4VSAgQHTyW85vD+41YA7i8
 bTUEXLEvL5REODEC1cH31avstW/B+IJr6ReSRV8ZSQTH10JjLlACSvjCwRtlxemV
 SUbPosOl23g1I78skc/gab2Y/Zs/zniVtMLBUBPN1eTk30kj6ZmkBHF0m4adpHhw
 6AtMRlYEnOoTektrkMVk3IQth6FOQIGIyKMX4P27COjMUwFgG9Kiyn/+r6yH+pMZ
 CjSxuIcPi76HKLv+HWB2
 =5aa4
 -----END PGP SIGNATURE-----

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>
This commit is contained in:
Peter Maydell 2015-11-03 14:54:40 +00:00
commit 79cf9fad34
15 changed files with 251 additions and 93 deletions

View File

@ -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

View File

@ -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[] = {

View File

@ -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.

View File

@ -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];

View File

@ -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]));
}
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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)

View File

@ -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);
};
/**

View File

@ -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();
}

View File

@ -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];

View File

@ -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 */

View File

@ -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;

View File

@ -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;

View File

@ -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) {