diff mbox

[RFC,2/3] arm: highbank: Implement dummy monitor

Message ID fc926a43acb4a6c6b45fe451bd16b09ef08cee2a.1443931379.git.crosthwaite.peter@gmail.com
State New
Headers show

Commit Message

Peter Crosthwaite Oct. 10, 2015, 3:13 a.m. UTC
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 <crosthwaite.peter@gmail.com>
---
 hw/arm/highbank.c | 56 ++++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 45 insertions(+), 11 deletions(-)
diff mbox

Patch

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