aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Herring <rob.herring@linaro.org>2014-02-06 16:54:26 -0600
committerRob Herring <rob.herring@linaro.org>2014-02-11 19:52:05 -0600
commitb80e72ae79e1796af62eb8f8a4fb56f76301124b (patch)
treef6212835a24a600c5936022487f40ff4aa3079bd
parentbebd384aadc90c059c964e6e2055636f3f2877e1 (diff)
target-arm: Add 32-bit PSCI CPU_ONa64-system
Signed-off-by: Rob Herring <rob.herring@linaro.org>
-rw-r--r--target-arm/helper.c31
-rw-r--r--target-arm/translate.c8
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) {