Firstly, enable monitor mode and PSCI, both are which are features of this board.
In addition to PSCI, this board also uses SMC for cache maintainence ops. This means we need a secure monitor to catch these and nop them. Use the ARM boot board-setup feature to implement this. Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com> --- Changed since RFC: Use bootloader callback to load blob. Change "firmware" to "board-setup" for consistency. Tweak commit message. hw/arm/highbank.c | 57 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c index be04b27..98daba0 100644 --- a/hw/arm/highbank.c +++ b/hw/arm/highbank.c @@ -28,6 +28,9 @@ #include "exec/address-spaces.h" #include "qemu/error-report.h" +#define BOARD_SETUP_ADDR 0x0 +#define LOAD_ADDR 0x1000 + #define SMP_BOOT_ADDR 0x100 #define SMP_BOOT_REG 0x40 #define MPCORE_PERIPHBASE 0xfff10000 @@ -36,6 +39,38 @@ /* Board init. */ +static void hb_write_board_setup(ARMCPU *cpu, + const struct arm_boot_info *info) +{ + int n; + uint32_t board_setup_blob[] = { + /* Reset */ + 0xe320f000, /* nop */ + 0xe320f000, /* nop */ + /* smc */ + 0xe10f0000, /* mrs r0, CPSR */ + 0xe200001f, /* and r0, r0, #0x1f - mask off mode bits */ + 0xe3500016, /* cmp r0, #0x16 - are we in monitor mode? */ + /* if (!monitor_mode) { */ + 0x11600070, /* smcne - go to monitor mode */ + 0x112fff1e, /* bxne lr - return to caller */ + /* } */ + /* do setup from monitor mode */ + 0xe3a00000 + BOARD_SETUP_ADDR, /* mov r0, #BOARD_SETUP_ADDR */ + 0xee0c0f30, /* mcr p15, 0, r0, c12, c0, 1 - set mvbar */ + 0xe58fe008, /* save lr */ + 0xe8dfc000, /* exception return */ + 0, + 0, + 0, /* exception return link will end up here */ + }; + 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 void hb_write_secondary(ARMCPU *cpu, const struct arm_boot_info *info) { int n; @@ -248,16 +283,13 @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id) cpuobj = object_new(object_class_get_name(oc)); cpu = ARM_CPU(cpuobj); - /* By default A9 and A15 CPUs have EL3 enabled. This board does not - * currently support EL3 so the CPU EL3 property is disabled before - * realization. - */ - if (object_property_find(cpuobj, "has_el3", NULL)) { - object_property_set_bool(cpuobj, false, "has_el3", &err); - if (err) { - error_report_err(err); - exit(1); - } + object_property_set_int(cpuobj, QEMU_PSCI_CONDUIT_SMC, + "psci-conduit", &error_abort); + + if (n) { + /* Secondary CPUs start in PSCI powered-down state */ + object_property_set_bool(cpuobj, true, + "start-powered-off", &error_abort); } if (object_property_find(cpuobj, "reset-cbar", NULL)) { @@ -375,9 +407,12 @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id) */ highbank_binfo.board_id = -1; highbank_binfo.nb_cpus = smp_cpus; - highbank_binfo.loader_start = 0; + highbank_binfo.loader_start = LOAD_ADDR; highbank_binfo.write_secondary_boot = hb_write_secondary; highbank_binfo.secondary_cpu_reset_hook = hb_reset_secondary; + highbank_binfo.board_setup_addr = BOARD_SETUP_ADDR; + highbank_binfo.write_board_setup = hb_write_board_setup; + arm_load_kernel(ARM_CPU(first_cpu), &highbank_binfo); } -- 1.9.1