2 * QEMU ARMv7-M TCG-only CPUs.
4 * Copyright (c) 2012 SUSE LINUX Products GmbH
6 * This code is licensed under the GNU GPL v2 or later.
8 * SPDX-License-Identifier: GPL-2.0-or-later
11 #include "qemu/osdep.h"
13 #include "hw/core/tcg-cpu-ops.h"
14 #include "internals.h"
16 #if !defined(CONFIG_USER_ONLY)
18 #include "hw/intc/armv7m_nvic.h"
20 static bool arm_v7m_cpu_exec_interrupt(CPUState
*cs
, int interrupt_request
)
22 CPUClass
*cc
= CPU_GET_CLASS(cs
);
23 ARMCPU
*cpu
= ARM_CPU(cs
);
24 CPUARMState
*env
= &cpu
->env
;
28 * ARMv7-M interrupt masking works differently than -A or -R.
29 * There is no FIQ/IRQ distinction. Instead of I and F bits
30 * masking FIQ and IRQ interrupts, an exception is taken only
31 * if it is higher priority than the current execution priority
32 * (which depends on state like BASEPRI, FAULTMASK and the
33 * currently active exception).
35 if (interrupt_request
& CPU_INTERRUPT_HARD
36 && (armv7m_nvic_can_take_pending_exception(env
->nvic
))) {
37 cs
->exception_index
= EXCP_IRQ
;
38 cc
->tcg_ops
->do_interrupt(cs
);
44 #endif /* !CONFIG_USER_ONLY */
46 static void cortex_m0_initfn(Object
*obj
)
48 ARMCPU
*cpu
= ARM_CPU(obj
);
49 set_feature(&cpu
->env
, ARM_FEATURE_V6
);
50 set_feature(&cpu
->env
, ARM_FEATURE_M
);
52 cpu
->midr
= 0x410cc200;
55 * These ID register values are not guest visible, because
56 * we do not implement the Main Extension. They must be set
57 * to values corresponding to the Cortex-M0's implemented
58 * features, because QEMU generally controls its emulation
59 * by looking at ID register fields. We use the same values as
62 cpu
->isar
.id_pfr0
= 0x00000030;
63 cpu
->isar
.id_pfr1
= 0x00000200;
64 cpu
->isar
.id_dfr0
= 0x00100000;
65 cpu
->id_afr0
= 0x00000000;
66 cpu
->isar
.id_mmfr0
= 0x00000030;
67 cpu
->isar
.id_mmfr1
= 0x00000000;
68 cpu
->isar
.id_mmfr2
= 0x00000000;
69 cpu
->isar
.id_mmfr3
= 0x00000000;
70 cpu
->isar
.id_isar0
= 0x01141110;
71 cpu
->isar
.id_isar1
= 0x02111000;
72 cpu
->isar
.id_isar2
= 0x21112231;
73 cpu
->isar
.id_isar3
= 0x01111110;
74 cpu
->isar
.id_isar4
= 0x01310102;
75 cpu
->isar
.id_isar5
= 0x00000000;
76 cpu
->isar
.id_isar6
= 0x00000000;
79 static void cortex_m3_initfn(Object
*obj
)
81 ARMCPU
*cpu
= ARM_CPU(obj
);
82 set_feature(&cpu
->env
, ARM_FEATURE_V7
);
83 set_feature(&cpu
->env
, ARM_FEATURE_M
);
84 set_feature(&cpu
->env
, ARM_FEATURE_M_MAIN
);
85 cpu
->midr
= 0x410fc231;
86 cpu
->pmsav7_dregion
= 8;
87 cpu
->isar
.id_pfr0
= 0x00000030;
88 cpu
->isar
.id_pfr1
= 0x00000200;
89 cpu
->isar
.id_dfr0
= 0x00100000;
90 cpu
->id_afr0
= 0x00000000;
91 cpu
->isar
.id_mmfr0
= 0x00000030;
92 cpu
->isar
.id_mmfr1
= 0x00000000;
93 cpu
->isar
.id_mmfr2
= 0x00000000;
94 cpu
->isar
.id_mmfr3
= 0x00000000;
95 cpu
->isar
.id_isar0
= 0x01141110;
96 cpu
->isar
.id_isar1
= 0x02111000;
97 cpu
->isar
.id_isar2
= 0x21112231;
98 cpu
->isar
.id_isar3
= 0x01111110;
99 cpu
->isar
.id_isar4
= 0x01310102;
100 cpu
->isar
.id_isar5
= 0x00000000;
101 cpu
->isar
.id_isar6
= 0x00000000;
104 static void cortex_m4_initfn(Object
*obj
)
106 ARMCPU
*cpu
= ARM_CPU(obj
);
108 set_feature(&cpu
->env
, ARM_FEATURE_V7
);
109 set_feature(&cpu
->env
, ARM_FEATURE_M
);
110 set_feature(&cpu
->env
, ARM_FEATURE_M_MAIN
);
111 set_feature(&cpu
->env
, ARM_FEATURE_THUMB_DSP
);
112 cpu
->midr
= 0x410fc240; /* r0p0 */
113 cpu
->pmsav7_dregion
= 8;
114 cpu
->isar
.mvfr0
= 0x10110021;
115 cpu
->isar
.mvfr1
= 0x11000011;
116 cpu
->isar
.mvfr2
= 0x00000000;
117 cpu
->isar
.id_pfr0
= 0x00000030;
118 cpu
->isar
.id_pfr1
= 0x00000200;
119 cpu
->isar
.id_dfr0
= 0x00100000;
120 cpu
->id_afr0
= 0x00000000;
121 cpu
->isar
.id_mmfr0
= 0x00000030;
122 cpu
->isar
.id_mmfr1
= 0x00000000;
123 cpu
->isar
.id_mmfr2
= 0x00000000;
124 cpu
->isar
.id_mmfr3
= 0x00000000;
125 cpu
->isar
.id_isar0
= 0x01141110;
126 cpu
->isar
.id_isar1
= 0x02111000;
127 cpu
->isar
.id_isar2
= 0x21112231;
128 cpu
->isar
.id_isar3
= 0x01111110;
129 cpu
->isar
.id_isar4
= 0x01310102;
130 cpu
->isar
.id_isar5
= 0x00000000;
131 cpu
->isar
.id_isar6
= 0x00000000;
134 static void cortex_m7_initfn(Object
*obj
)
136 ARMCPU
*cpu
= ARM_CPU(obj
);
138 set_feature(&cpu
->env
, ARM_FEATURE_V7
);
139 set_feature(&cpu
->env
, ARM_FEATURE_M
);
140 set_feature(&cpu
->env
, ARM_FEATURE_M_MAIN
);
141 set_feature(&cpu
->env
, ARM_FEATURE_THUMB_DSP
);
142 cpu
->midr
= 0x411fc272; /* r1p2 */
143 cpu
->pmsav7_dregion
= 8;
144 cpu
->isar
.mvfr0
= 0x10110221;
145 cpu
->isar
.mvfr1
= 0x12000011;
146 cpu
->isar
.mvfr2
= 0x00000040;
147 cpu
->isar
.id_pfr0
= 0x00000030;
148 cpu
->isar
.id_pfr1
= 0x00000200;
149 cpu
->isar
.id_dfr0
= 0x00100000;
150 cpu
->id_afr0
= 0x00000000;
151 cpu
->isar
.id_mmfr0
= 0x00100030;
152 cpu
->isar
.id_mmfr1
= 0x00000000;
153 cpu
->isar
.id_mmfr2
= 0x01000000;
154 cpu
->isar
.id_mmfr3
= 0x00000000;
155 cpu
->isar
.id_isar0
= 0x01101110;
156 cpu
->isar
.id_isar1
= 0x02112000;
157 cpu
->isar
.id_isar2
= 0x20232231;
158 cpu
->isar
.id_isar3
= 0x01111131;
159 cpu
->isar
.id_isar4
= 0x01310132;
160 cpu
->isar
.id_isar5
= 0x00000000;
161 cpu
->isar
.id_isar6
= 0x00000000;
164 static void cortex_m33_initfn(Object
*obj
)
166 ARMCPU
*cpu
= ARM_CPU(obj
);
168 set_feature(&cpu
->env
, ARM_FEATURE_V8
);
169 set_feature(&cpu
->env
, ARM_FEATURE_M
);
170 set_feature(&cpu
->env
, ARM_FEATURE_M_MAIN
);
171 set_feature(&cpu
->env
, ARM_FEATURE_M_SECURITY
);
172 set_feature(&cpu
->env
, ARM_FEATURE_THUMB_DSP
);
173 cpu
->midr
= 0x410fd213; /* r0p3 */
174 cpu
->pmsav7_dregion
= 16;
175 cpu
->sau_sregion
= 8;
176 cpu
->isar
.mvfr0
= 0x10110021;
177 cpu
->isar
.mvfr1
= 0x11000011;
178 cpu
->isar
.mvfr2
= 0x00000040;
179 cpu
->isar
.id_pfr0
= 0x00000030;
180 cpu
->isar
.id_pfr1
= 0x00000210;
181 cpu
->isar
.id_dfr0
= 0x00200000;
182 cpu
->id_afr0
= 0x00000000;
183 cpu
->isar
.id_mmfr0
= 0x00101F40;
184 cpu
->isar
.id_mmfr1
= 0x00000000;
185 cpu
->isar
.id_mmfr2
= 0x01000000;
186 cpu
->isar
.id_mmfr3
= 0x00000000;
187 cpu
->isar
.id_isar0
= 0x01101110;
188 cpu
->isar
.id_isar1
= 0x02212000;
189 cpu
->isar
.id_isar2
= 0x20232232;
190 cpu
->isar
.id_isar3
= 0x01111131;
191 cpu
->isar
.id_isar4
= 0x01310132;
192 cpu
->isar
.id_isar5
= 0x00000000;
193 cpu
->isar
.id_isar6
= 0x00000000;
194 cpu
->clidr
= 0x00000000;
195 cpu
->ctr
= 0x8000c000;
198 static void cortex_m55_initfn(Object
*obj
)
200 ARMCPU
*cpu
= ARM_CPU(obj
);
202 set_feature(&cpu
->env
, ARM_FEATURE_V8
);
203 set_feature(&cpu
->env
, ARM_FEATURE_V8_1M
);
204 set_feature(&cpu
->env
, ARM_FEATURE_M
);
205 set_feature(&cpu
->env
, ARM_FEATURE_M_MAIN
);
206 set_feature(&cpu
->env
, ARM_FEATURE_M_SECURITY
);
207 set_feature(&cpu
->env
, ARM_FEATURE_THUMB_DSP
);
208 cpu
->midr
= 0x410fd221; /* r0p1 */
210 cpu
->pmsav7_dregion
= 16;
211 cpu
->sau_sregion
= 8;
212 /* These are the MVFR* values for the FPU + full MVE configuration */
213 cpu
->isar
.mvfr0
= 0x10110221;
214 cpu
->isar
.mvfr1
= 0x12100211;
215 cpu
->isar
.mvfr2
= 0x00000040;
216 cpu
->isar
.id_pfr0
= 0x20000030;
217 cpu
->isar
.id_pfr1
= 0x00000230;
218 cpu
->isar
.id_dfr0
= 0x10200000;
219 cpu
->id_afr0
= 0x00000000;
220 cpu
->isar
.id_mmfr0
= 0x00111040;
221 cpu
->isar
.id_mmfr1
= 0x00000000;
222 cpu
->isar
.id_mmfr2
= 0x01000000;
223 cpu
->isar
.id_mmfr3
= 0x00000011;
224 cpu
->isar
.id_isar0
= 0x01103110;
225 cpu
->isar
.id_isar1
= 0x02212000;
226 cpu
->isar
.id_isar2
= 0x20232232;
227 cpu
->isar
.id_isar3
= 0x01111131;
228 cpu
->isar
.id_isar4
= 0x01310132;
229 cpu
->isar
.id_isar5
= 0x00000000;
230 cpu
->isar
.id_isar6
= 0x00000000;
231 cpu
->clidr
= 0x00000000; /* caches not implemented */
232 cpu
->ctr
= 0x8303c003;
235 static const TCGCPUOps arm_v7m_tcg_ops
= {
236 .initialize
= arm_translate_init
,
237 .synchronize_from_tb
= arm_cpu_synchronize_from_tb
,
238 .debug_excp_handler
= arm_debug_excp_handler
,
239 .restore_state_to_opc
= arm_restore_state_to_opc
,
241 #ifdef CONFIG_USER_ONLY
242 .record_sigsegv
= arm_cpu_record_sigsegv
,
243 .record_sigbus
= arm_cpu_record_sigbus
,
245 .tlb_fill_align
= arm_cpu_tlb_fill_align
,
246 .cpu_exec_interrupt
= arm_v7m_cpu_exec_interrupt
,
247 .cpu_exec_halt
= arm_cpu_exec_halt
,
248 .do_interrupt
= arm_v7m_cpu_do_interrupt
,
249 .do_transaction_failed
= arm_cpu_do_transaction_failed
,
250 .do_unaligned_access
= arm_cpu_do_unaligned_access
,
251 .adjust_watchpoint_address
= arm_adjust_watchpoint_address
,
252 .debug_check_watchpoint
= arm_debug_check_watchpoint
,
253 .debug_check_breakpoint
= arm_debug_check_breakpoint
,
254 #endif /* !CONFIG_USER_ONLY */
257 static void arm_v7m_class_init(ObjectClass
*oc
, void *data
)
259 ARMCPUClass
*acc
= ARM_CPU_CLASS(oc
);
260 CPUClass
*cc
= CPU_CLASS(oc
);
263 cc
->tcg_ops
= &arm_v7m_tcg_ops
;
264 cc
->gdb_core_xml_file
= "arm-m-profile.xml";
267 static const ARMCPUInfo arm_v7m_cpus
[] = {
268 { .name
= "cortex-m0", .initfn
= cortex_m0_initfn
,
269 .class_init
= arm_v7m_class_init
},
270 { .name
= "cortex-m3", .initfn
= cortex_m3_initfn
,
271 .class_init
= arm_v7m_class_init
},
272 { .name
= "cortex-m4", .initfn
= cortex_m4_initfn
,
273 .class_init
= arm_v7m_class_init
},
274 { .name
= "cortex-m7", .initfn
= cortex_m7_initfn
,
275 .class_init
= arm_v7m_class_init
},
276 { .name
= "cortex-m33", .initfn
= cortex_m33_initfn
,
277 .class_init
= arm_v7m_class_init
},
278 { .name
= "cortex-m55", .initfn
= cortex_m55_initfn
,
279 .class_init
= arm_v7m_class_init
},
282 static void arm_v7m_cpu_register_types(void)
286 for (i
= 0; i
< ARRAY_SIZE(arm_v7m_cpus
); ++i
) {
287 arm_cpu_register(&arm_v7m_cpus
[i
]);
291 type_init(arm_v7m_cpu_register_types
)