From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49166) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZkkbO-0006Uv-VH for qemu-devel@nongnu.org; Fri, 09 Oct 2015 23:13:47 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZkkbL-0001A2-Dm for qemu-devel@nongnu.org; Fri, 09 Oct 2015 23:13:42 -0400 Received: from mail-pa0-x229.google.com ([2607:f8b0:400e:c03::229]:36394) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZkkbL-00019F-4Z for qemu-devel@nongnu.org; Fri, 09 Oct 2015 23:13:39 -0400 Received: by pablk4 with SMTP id lk4so102922977pab.3 for ; Fri, 09 Oct 2015 20:13:38 -0700 (PDT) From: Peter Crosthwaite Date: Fri, 9 Oct 2015 20:13:26 -0700 Message-Id: In-Reply-To: References: In-Reply-To: References: Subject: [Qemu-devel] [RFC 2/3] arm: highbank: Implement dummy monitor List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: peter.maydell@linaro.org, Peter Crosthwaite , linux@roeck-us.net, robh@kernel.org 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 blob to implement this. FIXME: The blob population should be made Linux specific. Signed-off-by: Peter Crosthwaite --- hw/arm/highbank.c | 56 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 11 deletions(-) diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c index be04b27..1fca057 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 FW_BLOB_ADDR 0x0 +#define LOAD_ADDR 0x1000 + #define SMP_BOOT_ADDR 0x100 #define SMP_BOOT_REG 0x40 #define MPCORE_PERIPHBASE 0xfff10000 @@ -36,6 +39,36 @@ /* Board init. */ +static void hb_write_fw_blob(void) +{ + int n; + uint32_t fw_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 + FW_BLOB_ADDR, /* mov r0, #FW_BLOB_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(fw_blob); n++) { + fw_blob[n] = tswap32(fw_blob[n]); + } + rom_add_blob_fixed("firmware", fw_blob, sizeof(fw_blob), FW_BLOB_ADDR); +} + static void hb_write_secondary(ARMCPU *cpu, const struct arm_boot_info *info) { int n; @@ -248,16 +281,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 +405,13 @@ 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_blob = true; + highbank_binfo.board_setup_blob_addr = FW_BLOB_ADDR; + + hb_write_fw_blob(); arm_load_kernel(ARM_CPU(first_cpu), &highbank_binfo); } -- 1.9.1