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

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