From 99a99c1fc8e9bfec1656ac5916c53977a93d3581 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Tue, 3 Nov 2015 13:49:41 +0000 Subject: target-arm: Add and use symbolic names for register banks Add BANK_ #defines to index banked registers. Suggested-by: Peter Maydell Signed-off-by: Soren Brinkmann Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target-arm/helper.c | 37 ++++++++++++++++++++++--------------- target-arm/internals.h | 16 +++++++++++++--- target-arm/kvm32.c | 34 +++++++++++++++++----------------- target-arm/op_helper.c | 8 ++++---- 4 files changed, 56 insertions(+), 39 deletions(-) diff --git a/target-arm/helper.c b/target-arm/helper.c index 1966f9c..4ecae61 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 412827b..347998c 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 3ae57a6..df1e2b0 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 a4c4ebf..b5db345 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; -- cgit v1.1 From 84e59397797ff2040439058b689adbfef608b879 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Tue, 3 Nov 2015 13:49:41 +0000 Subject: arm: boot: Adjust indentation of FIXUP comments These comments start immediately after the current longest name in the list. Tab them out to the next tab stop to give a little breathing room and prepare for FIXUP_BOARD_SETUP which will require more indent. Reviewed-by: Peter Maydell Signed-off-by: Peter Crosthwaite Message-id: b9b9bb8f1c307c1ef8a3f26ff1f34fabb34b332e.1446182614.git.crosthwaite.peter@gmail.com Signed-off-by: Peter Maydell --- hw/arm/boot.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/hw/arm/boot.c b/hw/arm/boot.c index bef451b..2a151e2 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -28,14 +28,14 @@ #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_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; -- cgit v1.1 From 10b8ec73e610e017ac2fbaf486fce21eec7061b2 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Tue, 3 Nov 2015 13:49:41 +0000 Subject: arm: boot: Add board specific setup code API Add an API for boards to inject their own preboot software (or firmware) sequence. The software then returns to the bootloader via the link register. This allows boards to do their own little bits of firmware setup without needed to replace the bootloader completely (which is the requirement for existing firmware support). The blob is loaded by a callback if and only if doing a linux boot (similar to the existing write_secondary support). Rewrite the comment for the primary boot blob. Reviewed-by: Peter Maydell Signed-off-by: Peter Crosthwaite Message-id: 070295644c6ac84696d743913296e8cfefb48c15.1446182614.git.crosthwaite.peter@gmail.com Signed-off-by: Peter Maydell --- hw/arm/boot.c | 20 +++++++++++++++++++- include/hw/arm/arm.h | 10 ++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/hw/arm/boot.c b/hw/arm/boot.c index 2a151e2..b0879a5 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -31,6 +31,7 @@ typedef enum { 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 */ @@ -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/include/hw/arm/arm.h b/include/hw/arm/arm.h index 4dcd4f9..9217b70 100644 --- a/include/hw/arm/arm.h +++ b/include/hw/arm/arm.h @@ -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); }; /** -- cgit v1.1 From c3a9a689c6ff07ba2e00bafc68626fad84587794 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Tue, 3 Nov 2015 13:49:41 +0000 Subject: arm: xilinx_zynq: Add linux pre-boot Add a Linux-specific pre-boot routine that matches the device- specific bootloaders behaviour. This is needed for modern Linux that expects the ARM PLL in SLCR to be a more even value (not 26). Cc: Alistair Francis Signed-off-by: Peter Crosthwaite Message-id: 9a9025ea65572586b50dca4e5819032e3c436d64.1446182614.git.crosthwaite.peter@gmail.com Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/xilinx_zynq.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c index 9f89483..82a9db8 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); } -- cgit v1.1 From 20c59c38927902a8e2c67da7d9a24b5222a31cb7 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Tue, 3 Nov 2015 13:49:41 +0000 Subject: armv7-m: Return DeviceState* from armv7m_init() Change armv7m_init to return the DeviceState* for the NVIC. This allows access to all GPIO blocks, not just the IRQ inputs. Move qdev_get_gpio_in() calls out of armv7m_init() into board code for stellaris and stm32f205 boards. Signed-off-by: Michael Davidsaver Reviewed-by: Peter Crosthwaite Signed-off-by: Peter Maydell --- hw/arm/armv7m.c | 9 ++------- hw/arm/stellaris.c | 29 ++++++++++++++++++----------- hw/arm/stm32f205_soc.c | 15 ++++++++------- include/hw/arm/arm.h | 2 +- 4 files changed, 29 insertions(+), 26 deletions(-) diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c index eb214db..a80d2ad 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/stellaris.c b/hw/arm/stellaris.c index 3d6486f..82a4ad5 100644 --- a/hw/arm/stellaris.c +++ b/hw/arm/stellaris.c @@ -1210,8 +1210,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 +1240,16 @@ 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); 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 +1258,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 +1281,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 +1292,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 +1333,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 4d26a7e..3f99340 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/include/hw/arm/arm.h b/include/hw/arm/arm.h index 9217b70..67ba7db 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); /* -- cgit v1.1 From e192becdc7b05276a41ebef9fe11e6c30ddb91e3 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Tue, 3 Nov 2015 13:49:41 +0000 Subject: armv7-m: Implement SYSRESETREQ Implement the SYSRESETREQ bit of the AIRCR register for armv7-m (ie. cortex-m3) to trigger a GPIO out. Signed-off-by: Michael Davidsaver Reviewed-by: Peter Crosthwaite Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/intc/armv7m_nvic.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index 3ec8408..6fc167e 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) -- cgit v1.1 From d69ffb5b48701d8f33cdfa2570a4ea1d5eb9de4d Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Tue, 3 Nov 2015 13:49:41 +0000 Subject: arm: stellaris: exit on external reset request Add GPIO in for the stellaris board which calls qemu_system_reset_request() on reset request. Signed-off-by: Michael Davidsaver Reviewed-by: Peter Crosthwaite Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/stellaris.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c index 82a4ad5..0114e0a 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", @@ -1243,6 +1252,9 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, 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, qdev_get_gpio_in(nvic, 14), -- cgit v1.1 From b4f2bd1ce89f3a324fd047c65573897b39d5aaf8 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 3 Nov 2015 13:49:42 +0000 Subject: MAINTAINERS: Add new qemu-arm mailing list to ARM related entries We now have a qemu-arm mailing list for ARM patches and discussion, so add an L: entry for it to the various ARM related entries in MAINTAINERS. Signed-off-by: Peter Maydell Reviewed-by: Alistair Francis Reviewed-by: Shannon Zhao Reviewed-by: Peter Crosthwaite Message-id: 1446129661-5239-1-git-send-email-peter.maydell@linaro.org --- MAINTAINERS | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 3144113..fc8abe8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -81,6 +81,7 @@ F: disas/alpha.c ARM M: Peter Maydell +L: qemu-arm@nongnu.org S: Maintained F: target-arm/ F: hw/arm/ @@ -216,6 +217,7 @@ F: */kvm.* ARM M: Peter Maydell +L: qemu-arm@nongnu.org S: Maintained F: target-arm/kvm.c @@ -287,6 +289,7 @@ ARM Machines ------------ Allwinner-a10 M: Beniamino Galvani +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 +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 +L: qemu-arm@nongnu.org S: Maintained F: hw/intc/arm* F: hw/intc/gic_internal.h @@ -327,54 +332,64 @@ M: Evgeny Voevodin M: Maksim Kozlov M: Igor Mitsyanko M: Dmitry Solodkiy +L: qemu-arm@nongnu.org S: Maintained F: hw/*/exynos* Calxeda Highbank M: Rob Herring +L: qemu-arm@nongnu.org S: Maintained F: hw/arm/highbank.c F: hw/net/xgmac.c Canon DIGIC M: Antony Pavlov +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 +L: qemu-arm@nongnu.org S: Odd fixes F: hw/*/imx* F: hw/arm/kzm.c Integrator CP M: Peter Maydell +L: qemu-arm@nongnu.org S: Maintained F: hw/arm/integratorcp.c Musicpal M: Jan Kiszka +L: qemu-arm@nongnu.org S: Maintained F: hw/arm/musicpal.c nSeries M: Andrzej Zaborowski +L: qemu-arm@nongnu.org S: Maintained F: hw/arm/nseries.c Palm M: Andrzej Zaborowski +L: qemu-arm@nongnu.org S: Maintained F: hw/arm/palm.c Real View M: Peter Maydell +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 +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 +L: qemu-arm@nongnu.org S: Maintained F: hw/*/stellaris* Versatile PB M: Peter Maydell +L: qemu-arm@nongnu.org S: Maintained F: hw/*/versatile* Xilinx Zynq M: Alistair Francis M: Peter Crosthwaite +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 M: Peter Crosthwaite +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 M: Shannon Zhao +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 M: Claudio Fontana 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 S: Maintained +L: qemu-arm@nongnu.org F: tcg/arm/ F: disas/arm.c -- cgit v1.1 From 08b8e0f527930208a548b424d2ab3103bf3c8c02 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 3 Nov 2015 13:49:42 +0000 Subject: target-arm: Bring AArch64 debug CPU display of PSTATE into line with AArch32 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The AArch64 debug CPU display of PSTATE as "PSTATE=200003c5 (flags --C-)" on the end of the same line as the last of the general purpose registers is unnecessarily different from the AArch32 display of PSR as "PSR=200001d3 --C- A svc32" on its own line. Update the AArch64 code to put PSTATE in its own line and in the same format, including printing the exception level (mode). Signed-off-by: Peter Maydell Reviewed-by: Edgar E. Iglesias Reviewed-by: Alex Bennée Message-id: 1445883178-576-2-git-send-email-peter.maydell@linaro.org --- target-arm/translate-a64.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index 83b8376..57503a0 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -126,6 +126,7 @@ 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); cpu_fprintf(f, "PC=%016"PRIx64" SP=%016"PRIx64"\n", env->pc, env->xregs[31]); @@ -137,13 +138,14 @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f, cpu_fprintf(f, " "); } } - cpu_fprintf(f, "PSTATE=%08x (flags %c%c%c%c)\n", + cpu_fprintf(f, "\nPSTATE=%08x %c%c%c%c EL%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' : '-', + el, + psr & PSTATE_SP ? 'h' : 't'); if (flags & CPU_DUMP_FPU) { int numvfpregs = 32; -- cgit v1.1 From 06e5cf7acd1f94ab7c1cd6945974a1f039672940 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 3 Nov 2015 13:49:42 +0000 Subject: target-arm: Report S/NS status in the CPU debug logs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If this CPU supports EL3, enhance the printing of the current CPU mode in debug logging to distinguish S from NS modes as appropriate. Signed-off-by: Peter Maydell Reviewed-by: Edgar E. Iglesias Reviewed-by: Alex Bennée Message-id: 1445883178-576-3-git-send-email-peter.maydell@linaro.org --- target-arm/translate-a64.c | 11 ++++++++++- target-arm/translate.c | 12 +++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index 57503a0..d7e0954 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -127,6 +127,7 @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f, 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]); @@ -138,12 +139,20 @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f, cpu_fprintf(f, " "); } } - cpu_fprintf(f, "\nPSTATE=%08x %c%c%c%c EL%d%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' : '-', + ns_status, el, psr & PSTATE_SP ? 'h' : 't'); diff --git a/target-arm/translate.c b/target-arm/translate.c index b10a455..ff262a2 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) { -- cgit v1.1 From bc64b96c984abfe84f43562ca7480bb4f2af0613 Mon Sep 17 00:00:00 2001 From: Graeme Gregory Date: Tue, 3 Nov 2015 13:49:42 +0000 Subject: hw/arm/virt-acpi-build: _CCA attribute is compulsory According to ACPI specification 6.2.17 _CCA (Cache Coherency Attribute) this attribute is compulsory on ARM systems. Add this attribute to the PCI host bridges as required. Without this the kernel will produce the error [Firmware Bug]: PCI device 0000:00:00.0 fail to setup DMA. Signed-off-by: Graeme Gregory Message-id: 1446460786-13663-1-git-send-email-graeme.gregory@linaro.org Reviewed-by: Shannon Zhao Signed-off-by: Peter Maydell --- hw/arm/virt-acpi-build.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 1aaff1f..1430125 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); -- cgit v1.1 From f2fbfacec024d1e78c10fc8498f3126557c21ed8 Mon Sep 17 00:00:00 2001 From: Shannon Zhao Date: Tue, 3 Nov 2015 13:49:42 +0000 Subject: hw/arm/virt-acpi-build: Add GICC ACPI subtable for GICv3 When booting VM with GICv3, the kernel needs GICC ACPI subtable to initialize the CPUs, e.g. MPIDR information. This adds GICC ACPI subtable for GICv3, but set GICC base address only when gic_version == 2 since it donesn't need GICC base address for GICv3. Signed-off-by: Shannon Zhao Message-id: 1446131773-5018-1-git-send-email-shannon.zhao@linaro.org Signed-off-by: Peter Maydell --- hw/arm/virt-acpi-build.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 1430125..b170dfa 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -449,6 +449,22 @@ 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); + 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 = i; + 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); @@ -458,20 +474,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); -- cgit v1.1 From 5d9c1756140d680e66e5b45005a1fb7078b74ee1 Mon Sep 17 00:00:00 2001 From: Shannon Zhao Date: Tue, 3 Nov 2015 13:49:42 +0000 Subject: ARM: ACPI: Fix MPIDR value in ACPI table Use mp_affinity of ARMCPU as the CPU MPIDR instead of the CPU index. Signed-off-by: Shannon Zhao Message-id: 1446285001-7316-1-git-send-email-zhaoshenglong@huawei.com Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/virt-acpi-build.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index b170dfa..3c2c5d6 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -452,13 +452,15 @@ build_madt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info, 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 = 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); -- cgit v1.1