1
From e02ac60868c370ec9a5464bfa4d65cf867f0f679 Mon Sep 17 00:00:00 2001
2
From: Peter Maydell <peter.maydell@linaro.org>
3
Date: Mon, 18 Feb 2013 16:58:34 +0000
4
Subject: [PATCH 60/70] target-arm: add support for smc
7
target-arm/cpu.h | 9 +++++---
8
target-arm/helper.c | 58 +++++++++++++++++++++++++++++++++-----------------
9
target-arm/machine.c | 6 +++---
10
target-arm/translate.c | 47 ++++++++++++++++++++++++++++++----------
11
4 files changed, 83 insertions(+), 37 deletions(-)
13
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
14
index 0f8cb4e..8c9f6a8 100644
15
--- a/target-arm/cpu.h
16
+++ b/target-arm/cpu.h
18
#define EXCP_EXCEPTION_EXIT 8 /* Return from v7M exception. */
19
#define EXCP_KERNEL_TRAP 9 /* Jumped to kernel code page. */
21
+#define EXCP_SMC 11 /* secure monitor call */
23
#define ARMV7M_EXCP_RESET 1
24
#define ARMV7M_EXCP_NMI 2
25
@@ -124,9 +125,9 @@ typedef struct CPUARMState {
28
/* Banked registers. */
29
- uint32_t banked_spsr[6];
30
- uint32_t banked_r13[6];
31
- uint32_t banked_r14[6];
32
+ uint32_t banked_spsr[7];
33
+ uint32_t banked_r13[7];
34
+ uint32_t banked_r14[7];
36
/* These hold r8-r12. */
38
@@ -179,6 +180,7 @@ typedef struct CPUARMState {
39
uint32_t c9_pmuserenr; /* perf monitor user enable */
40
uint32_t c9_pminten; /* perf monitor interrupt enables */
41
uint32_t c12_vbar; /* vector base address register */
42
+ uint32_t c12_mvbar; /* monitor vector base address register. */
43
uint32_t c13_fcse; /* FCSE PID. */
44
uint32_t c13_context; /* Context ID. */
45
uint32_t c13_tls1; /* User RW Thread register. */
46
@@ -404,6 +406,7 @@ enum arm_cpu_mode {
47
ARM_CPU_MODE_FIQ = 0x11,
48
ARM_CPU_MODE_IRQ = 0x12,
49
ARM_CPU_MODE_SVC = 0x13,
50
+ ARM_CPU_MODE_SMC = 0x16,
51
ARM_CPU_MODE_ABT = 0x17,
52
ARM_CPU_MODE_UND = 0x1b,
53
ARM_CPU_MODE_SYS = 0x1f
54
diff --git a/target-arm/helper.c b/target-arm/helper.c
55
index c4633be..9ff9699 100644
56
--- a/target-arm/helper.c
57
+++ b/target-arm/helper.c
58
@@ -543,13 +543,6 @@ static int pmintenclr_write(CPUARMState *env, const ARMCPRegInfo *ri,
62
-static int vbar_write(CPUARMState *env, const ARMCPRegInfo *ri,
65
- env->cp15.c12_vbar = value & ~0x1Ful;
69
static int ccsidr_read(CPUARMState *env, const ARMCPRegInfo *ri,
72
@@ -1510,6 +1503,12 @@ static const ARMCPRegInfo lpae_cp_reginfo[] = {
76
+static int vbar_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
78
+ CPREG_FIELD32(env, ri) = value & ~0x1f;
82
static const ARMCPRegInfo trustzone_cp_reginfo[] = {
83
/* Dummy implementations of registers; we don't enforce the
84
* 'secure mode only' access checks. TODO: revisit as part of
85
@@ -1529,7 +1528,8 @@ static const ARMCPRegInfo trustzone_cp_reginfo[] = {
86
.fieldoffset = offsetof(CPUARMState, cp15.c12_vbar),
88
{ .name = "MVBAR", .cp = 15, .crn = 12, .crm = 0, .opc1 = 0, .opc2 = 1,
89
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
90
+ .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c12_mvbar),
91
+ .writefn = vbar_write, .resetvalue = 0 },
95
@@ -2204,6 +2204,8 @@ int bank_number(int mode)
97
case ARM_CPU_MODE_FIQ:
99
+ case ARM_CPU_MODE_SMC:
102
hw_error("bank number requested for bad CPSR mode value 0x%x\n", mode);
104
@@ -2500,23 +2502,39 @@ void arm_cpu_do_interrupt(CPUState *cs)
105
mask = CPSR_A | CPSR_I | CPSR_F;
109
+ if (semihosting_enabled) {
110
+ cpu_abort(env, "SMC handling under semihosting not implemented\n");
113
+ if ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_SMC) {
114
+ env->cp15.c1_scr &= ~1;
116
+ offset = env->thumb ? 2 : 0;
117
+ new_mode = ARM_CPU_MODE_SMC;
119
+ mask = CPSR_A | CPSR_I | CPSR_F;
122
cpu_abort(env, "Unhandled exception 0x%x\n", env->exception_index);
123
return; /* Never happens. Keep compiler happy. */
125
- /* High vectors. */
126
- if (env->cp15.c1_sys & (1 << 13)) {
127
- /* when enabled, base address cannot be remapped. */
128
- addr += 0xffff0000;
129
+ if (arm_feature(env, ARM_FEATURE_TRUSTZONE)) {
130
+ if (new_mode == ARM_CPU_MODE_SMC ||
131
+ (env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_SMC) {
132
+ addr += env->cp15.c12_mvbar;
134
+ if (env->cp15.c1_sys & (1 << 13)) {
135
+ addr += 0xffff0000;
137
+ addr += env->cp15.c12_vbar;
141
- /* ARM v7 architectures provide a vector base address register to remap
142
- * the interrupt vector table.
143
- * This register is only followed in non-monitor mode, and has a secure
144
- * and un-secure copy. Since the cpu is always in a un-secure operation
145
- * and is never in monitor mode this feature is always active.
146
- * Note: only bits 31:5 are valid.
148
- addr += env->cp15.c12_vbar;
149
+ /* High vectors. */
150
+ if (env->cp15.c1_sys & (1 << 13)) {
151
+ addr += 0xffff0000;
154
switch_mode (env, new_mode);
155
env->spsr = cpsr_read(env);
156
diff --git a/target-arm/machine.c b/target-arm/machine.c
157
index 74f010f..3a41dd0 100644
158
--- a/target-arm/machine.c
159
+++ b/target-arm/machine.c
160
@@ -238,9 +238,9 @@ const VMStateDescription vmstate_arm_cpu = {
163
VMSTATE_UINT32(env.spsr, ARMCPU),
164
- VMSTATE_UINT32_ARRAY(env.banked_spsr, ARMCPU, 6),
165
- VMSTATE_UINT32_ARRAY(env.banked_r13, ARMCPU, 6),
166
- VMSTATE_UINT32_ARRAY(env.banked_r14, ARMCPU, 6),
167
+ VMSTATE_UINT32_ARRAY(env.banked_spsr, ARMCPU, 7),
168
+ VMSTATE_UINT32_ARRAY(env.banked_r13, ARMCPU, 7),
169
+ VMSTATE_UINT32_ARRAY(env.banked_r14, ARMCPU, 7),
170
VMSTATE_UINT32_ARRAY(env.usr_regs, ARMCPU, 5),
171
VMSTATE_UINT32_ARRAY(env.fiq_regs, ARMCPU, 5),
172
/* The length-check must come before the arrays to avoid
173
diff --git a/target-arm/translate.c b/target-arm/translate.c
174
index 5f003e7..6954b56 100644
175
--- a/target-arm/translate.c
176
+++ b/target-arm/translate.c
177
@@ -60,6 +60,7 @@ static uint32_t gen_opc_condexec_bits[OPC_BUF_SIZE];
178
conditional execution state has been updated. */
184
/* We reuse the same 64-bit temporaries for efficiency. */
185
@@ -904,6 +905,12 @@ DO_GEN_ST(st8)
189
+static inline void gen_smc(CPUARMState *env, DisasContext *s)
191
+ tcg_gen_movi_i32(cpu_R[15], s->pc);
192
+ s->is_jmp = DISAS_SMC;
195
static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
198
@@ -6878,8 +6885,13 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
199
} else if ((insn & 0x0fe00000) == 0x0c400000) {
200
/* Coprocessor double register transfer. */
202
+ /* XXX doesn't belong in the trustzone patch: should just UNDEF? */
203
+ cpu_abort(env, "unsupported coprocessor double register transfer\n");
204
} else if ((insn & 0x0f000010) == 0x0e000010) {
205
/* Additional coprocessor register transfer. */
206
+ if (!disas_coproc_insn(env, s, insn)) {
209
} else if ((insn & 0x0ff10020) == 0x01000000) {
212
@@ -7030,15 +7042,19 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
213
store_reg(s, rd, tmp);
216
- /* SMC instruction (op1 == 3)
217
- and undefined instructions (op1 == 0 || op1 == 2)
223
+ gen_exception_insn(s, 4, EXCP_BKPT);
224
+ } else if (op1 == 3) {
226
+ if (!arm_feature(env, ARM_FEATURE_TRUSTZONE) || IS_USER(s)) {
235
- gen_exception_insn(s, 4, EXCP_BKPT);
237
case 0x8: /* signed multiply */
239
@@ -8808,10 +8824,12 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
242
if (insn & (1 << 26)) {
243
- /* Secure monitor call (v6Z) */
244
- qemu_log_mask(LOG_UNIMP,
245
- "arm: unimplemented secure monitor call\n");
246
- goto illegal_op; /* not implemented. */
247
+ /* Secure monitor call / smc (v6Z) */
248
+ if (!arm_feature(env, ARM_FEATURE_TRUSTZONE)
254
op = (insn >> 20) & 7;
256
@@ -10205,6 +10223,8 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
257
gen_set_condexec(dc);
258
if (dc->is_jmp == DISAS_SWI) {
259
gen_exception(EXCP_SWI);
260
+ } else if (dc->is_jmp == DISAS_SMC) {
261
+ gen_exception(EXCP_SMC);
263
gen_exception(EXCP_DEBUG);
265
@@ -10217,6 +10237,8 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
266
gen_set_condexec(dc);
267
if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
268
gen_exception(EXCP_SWI);
269
+ } else if (dc->is_jmp == DISAS_SMC && !dc->condjmp) {
270
+ gen_exception(EXCP_SMC);
272
/* FIXME: Single stepping a WFI insn will not halt
274
@@ -10251,6 +10273,9 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
276
gen_exception(EXCP_SWI);
279
+ gen_exception(EXCP_SMC);
283
gen_set_label(dc->condlabel);