diff options
-rw-r--r-- | target-arm/helper.c | 31 | ||||
-rw-r--r-- | target-arm/translate.c | 8 |
2 files changed, 36 insertions, 3 deletions
diff --git a/target-arm/helper.c b/target-arm/helper.c index fd7da3520..a85f191ec 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -2888,6 +2888,34 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs) 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 @@ void arm_cpu_do_interrupt(CPUState *cs) 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 a15c23712..3042ce1fb 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -7662,6 +7662,10 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) /* 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 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw 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) { |