target-arm: Add 32-bit PSCI CPU_ON

Signed-off-by: Rob Herring <rob.herring@linaro.org>
diff --git a/target-arm/helper.c b/target-arm/helper.c
index fd7da35..a85f191 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2888,6 +2888,34 @@
     env->thumb = addr & 1;
 }
 
+static void arm_cpu_do_smc(CPUState *cs)
+{
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
+    uint32_t func = env->regs[0];
+    uint32_t cpu_num;
+    target_ulong entry;
+
+    cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
+
+    switch (func) {
+    case PSCI_FN_CPU_ON:
+        cpu_num = env->regs[1] & 0xFF;
+        env->regs[0] = 0;
+        entry = env->regs[2];
+
+        /* Initialize the cpu we are turning on */
+        cs = qemu_get_cpu(cpu_num);
+        cpu = ARM_CPU(cs);
+        cpu->env.regs[15] = entry;
+        cs->halted = 0;
+        break;
+    default:
+        abort();
+    }
+}
+
+
 /* Handle a CPU exception.  */
 void arm_cpu_do_interrupt(CPUState *cs)
 {
@@ -2913,6 +2941,9 @@
         else
             offset = 4;
         break;
+    case EXCP_SMC:
+        arm_cpu_do_smc(cs);
+        return;
     case EXCP_SWI:
         if (semihosting_enabled) {
             /* Check for semihosting interrupt.  */
diff --git a/target-arm/translate.c b/target-arm/translate.c
index a15c237..3042ce1 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -7662,6 +7662,10 @@
             /* SMC instruction (op1 == 3)
                and undefined instructions (op1 == 0 || op1 == 2)
                will trap */
+            if (op1 == 3) {
+                gen_exception_insn(s, 0, EXCP_SMC, imm16);
+                break;
+            }
             if (op1 != 1) {
                 goto illegal_op;
             }
@@ -9450,9 +9454,7 @@
 
                 if (insn & (1 << 26)) {
                     /* Secure monitor call (v6Z) */
-                    qemu_log_mask(LOG_UNIMP,
-                                  "arm: unimplemented secure monitor call\n");
-                    goto illegal_op; /* not implemented.  */
+                    gen_exception_insn(s, 0, EXCP_SMC, 0);
                 } else {
                     op = (insn >> 20) & 7;
                     switch (op) {