1 /* 2 * QEMU ARMv7-M TCG-only CPUs. 3 * 4 * Copyright (c) 2012 SUSE LINUX Products GmbH 5 * 6 * This code is licensed under the GNU GPL v2 or later. 7 * 8 * SPDX-License-Identifier: GPL-2.0-or-later 9 */ 10 11 #include "qemu/osdep.h" 12 #include "cpu.h" 13 #include "accel/tcg/cpu-ops.h" 14 #include "internals.h" 15 16 #if !defined(CONFIG_USER_ONLY) 17 18 #include "hw/intc/armv7m_nvic.h" 19 20 static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request) 21 { 22 ARMCPU *cpu = ARM_CPU(cs); 23 CPUARMState *env = &cpu->env; 24 bool ret = false; 25 26 /* 27 * ARMv7-M interrupt masking works differently than -A or -R. 28 * There is no FIQ/IRQ distinction. Instead of I and F bits 29 * masking FIQ and IRQ interrupts, an exception is taken only 30 * if it is higher priority than the current execution priority 31 * (which depends on state like BASEPRI, FAULTMASK and the 32 * currently active exception). 33 */ 34 if (interrupt_request & CPU_INTERRUPT_HARD 35 && (armv7m_nvic_can_take_pending_exception(env->nvic))) { 36 cs->exception_index = EXCP_IRQ; 37 cs->cc->tcg_ops->do_interrupt(cs); 38 ret = true; 39 } 40 return ret; 41 } 42 43 #endif /* !CONFIG_USER_ONLY */ 44 45 static void cortex_m0_initfn(Object *obj) 46 { 47 ARMCPU *cpu = ARM_CPU(obj); 48 ARMISARegisters *isar = &cpu->isar; 49 set_feature(&cpu->env, ARM_FEATURE_V6); 50 set_feature(&cpu->env, ARM_FEATURE_M); 51 52 cpu->midr = 0x410cc200; 53 54 /* 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 60 * for the M3. 61 */ 62 SET_IDREG(isar, ID_PFR0, 0x00000030); 63 SET_IDREG(isar, ID_PFR1, 0x00000200); 64 SET_IDREG(isar, ID_DFR0, 0x00100000); 65 cpu->id_afr0 = 0x00000000; 66 SET_IDREG(isar, ID_MMFR0, 0x00000030); 67 SET_IDREG(isar, ID_MMFR1, 0x00000000); 68 SET_IDREG(isar, ID_MMFR2, 0x00000000); 69 SET_IDREG(isar, ID_MMFR3, 0x00000000); 70 SET_IDREG(isar, ID_ISAR0, 0x01141110); 71 SET_IDREG(isar, ID_ISAR1, 0x02111000); 72 SET_IDREG(isar, ID_ISAR2, 0x21112231); 73 SET_IDREG(isar, ID_ISAR3, 0x01111110); 74 SET_IDREG(isar, ID_ISAR4, 0x01310102); 75 SET_IDREG(isar, ID_ISAR5, 0x00000000); 76 SET_IDREG(isar, ID_ISAR6, 0x00000000); 77 } 78 79 static void cortex_m3_initfn(Object *obj) 80 { 81 ARMCPU *cpu = ARM_CPU(obj); 82 ARMISARegisters *isar = &cpu->isar; 83 set_feature(&cpu->env, ARM_FEATURE_V7); 84 set_feature(&cpu->env, ARM_FEATURE_M); 85 set_feature(&cpu->env, ARM_FEATURE_M_MAIN); 86 cpu->midr = 0x410fc231; 87 cpu->pmsav7_dregion = 8; 88 SET_IDREG(isar, ID_PFR0, 0x00000030); 89 SET_IDREG(isar, ID_PFR1, 0x00000200); 90 SET_IDREG(isar, ID_DFR0, 0x00100000); 91 cpu->id_afr0 = 0x00000000; 92 SET_IDREG(isar, ID_MMFR0, 0x00000030); 93 SET_IDREG(isar, ID_MMFR1, 0x00000000); 94 SET_IDREG(isar, ID_MMFR2, 0x00000000); 95 SET_IDREG(isar, ID_MMFR3, 0x00000000); 96 SET_IDREG(isar, ID_ISAR0, 0x01141110); 97 SET_IDREG(isar, ID_ISAR1, 0x02111000); 98 SET_IDREG(isar, ID_ISAR2, 0x21112231); 99 SET_IDREG(isar, ID_ISAR3, 0x01111110); 100 SET_IDREG(isar, ID_ISAR4, 0x01310102); 101 SET_IDREG(isar, ID_ISAR5, 0x00000000); 102 SET_IDREG(isar, ID_ISAR6, 0x00000000); 103 } 104 105 static void cortex_m4_initfn(Object *obj) 106 { 107 ARMCPU *cpu = ARM_CPU(obj); 108 ARMISARegisters *isar = &cpu->isar; 109 110 set_feature(&cpu->env, ARM_FEATURE_V7); 111 set_feature(&cpu->env, ARM_FEATURE_M); 112 set_feature(&cpu->env, ARM_FEATURE_M_MAIN); 113 set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP); 114 cpu->midr = 0x410fc240; /* r0p0 */ 115 cpu->pmsav7_dregion = 8; 116 cpu->isar.mvfr0 = 0x10110021; 117 cpu->isar.mvfr1 = 0x11000011; 118 cpu->isar.mvfr2 = 0x00000000; 119 SET_IDREG(isar, ID_PFR0, 0x00000030); 120 SET_IDREG(isar, ID_PFR1, 0x00000200); 121 SET_IDREG(isar, ID_DFR0, 0x00100000); 122 cpu->id_afr0 = 0x00000000; 123 SET_IDREG(isar, ID_MMFR0, 0x00000030); 124 SET_IDREG(isar, ID_MMFR1, 0x00000000); 125 SET_IDREG(isar, ID_MMFR2, 0x00000000); 126 SET_IDREG(isar, ID_MMFR3, 0x00000000); 127 SET_IDREG(isar, ID_ISAR0, 0x01141110); 128 SET_IDREG(isar, ID_ISAR1, 0x02111000); 129 SET_IDREG(isar, ID_ISAR2, 0x21112231); 130 SET_IDREG(isar, ID_ISAR3, 0x01111110); 131 SET_IDREG(isar, ID_ISAR4, 0x01310102); 132 SET_IDREG(isar, ID_ISAR5, 0x00000000); 133 SET_IDREG(isar, ID_ISAR6, 0x00000000); 134 } 135 136 static void cortex_m7_initfn(Object *obj) 137 { 138 ARMCPU *cpu = ARM_CPU(obj); 139 ARMISARegisters *isar = &cpu->isar; 140 141 set_feature(&cpu->env, ARM_FEATURE_V7); 142 set_feature(&cpu->env, ARM_FEATURE_M); 143 set_feature(&cpu->env, ARM_FEATURE_M_MAIN); 144 set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP); 145 cpu->midr = 0x411fc272; /* r1p2 */ 146 cpu->pmsav7_dregion = 8; 147 cpu->isar.mvfr0 = 0x10110221; 148 cpu->isar.mvfr1 = 0x12000011; 149 cpu->isar.mvfr2 = 0x00000040; 150 SET_IDREG(isar, ID_PFR0, 0x00000030); 151 SET_IDREG(isar, ID_PFR1, 0x00000200); 152 SET_IDREG(isar, ID_DFR0, 0x00100000); 153 cpu->id_afr0 = 0x00000000; 154 SET_IDREG(isar, ID_MMFR0, 0x00100030); 155 SET_IDREG(isar, ID_MMFR1, 0x00000000); 156 SET_IDREG(isar, ID_MMFR2, 0x01000000); 157 SET_IDREG(isar, ID_MMFR3, 0x00000000); 158 SET_IDREG(isar, ID_ISAR0, 0x01101110); 159 SET_IDREG(isar, ID_ISAR1, 0x02112000); 160 SET_IDREG(isar, ID_ISAR2, 0x20232231); 161 SET_IDREG(isar, ID_ISAR3, 0x01111131); 162 SET_IDREG(isar, ID_ISAR4, 0x01310132); 163 SET_IDREG(isar, ID_ISAR5, 0x00000000); 164 SET_IDREG(isar, ID_ISAR6, 0x00000000); 165 } 166 167 static void cortex_m33_initfn(Object *obj) 168 { 169 ARMCPU *cpu = ARM_CPU(obj); 170 ARMISARegisters *isar = &cpu->isar; 171 172 set_feature(&cpu->env, ARM_FEATURE_V8); 173 set_feature(&cpu->env, ARM_FEATURE_M); 174 set_feature(&cpu->env, ARM_FEATURE_M_MAIN); 175 set_feature(&cpu->env, ARM_FEATURE_M_SECURITY); 176 set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP); 177 cpu->midr = 0x410fd213; /* r0p3 */ 178 cpu->pmsav7_dregion = 16; 179 cpu->sau_sregion = 8; 180 cpu->isar.mvfr0 = 0x10110021; 181 cpu->isar.mvfr1 = 0x11000011; 182 cpu->isar.mvfr2 = 0x00000040; 183 SET_IDREG(isar, ID_PFR0, 0x00000030); 184 SET_IDREG(isar, ID_PFR1, 0x00000210); 185 SET_IDREG(isar, ID_DFR0, 0x00200000); 186 cpu->id_afr0 = 0x00000000; 187 SET_IDREG(isar, ID_MMFR0, 0x00101F40); 188 SET_IDREG(isar, ID_MMFR1, 0x00000000); 189 SET_IDREG(isar, ID_MMFR2, 0x01000000); 190 SET_IDREG(isar, ID_MMFR3, 0x00000000); 191 SET_IDREG(isar, ID_ISAR0, 0x01101110); 192 SET_IDREG(isar, ID_ISAR1, 0x02212000); 193 SET_IDREG(isar, ID_ISAR2, 0x20232232); 194 SET_IDREG(isar, ID_ISAR3, 0x01111131); 195 SET_IDREG(isar, ID_ISAR4, 0x01310132); 196 SET_IDREG(isar, ID_ISAR5, 0x00000000); 197 SET_IDREG(isar, ID_ISAR6, 0x00000000); 198 cpu->clidr = 0x00000000; 199 cpu->ctr = 0x8000c000; 200 } 201 202 static void cortex_m55_initfn(Object *obj) 203 { 204 ARMCPU *cpu = ARM_CPU(obj); 205 ARMISARegisters *isar = &cpu->isar; 206 207 set_feature(&cpu->env, ARM_FEATURE_V8); 208 set_feature(&cpu->env, ARM_FEATURE_V8_1M); 209 set_feature(&cpu->env, ARM_FEATURE_M); 210 set_feature(&cpu->env, ARM_FEATURE_M_MAIN); 211 set_feature(&cpu->env, ARM_FEATURE_M_SECURITY); 212 set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP); 213 cpu->midr = 0x410fd221; /* r0p1 */ 214 cpu->revidr = 0; 215 cpu->pmsav7_dregion = 16; 216 cpu->sau_sregion = 8; 217 /* These are the MVFR* values for the FPU + full MVE configuration */ 218 cpu->isar.mvfr0 = 0x10110221; 219 cpu->isar.mvfr1 = 0x12100211; 220 cpu->isar.mvfr2 = 0x00000040; 221 SET_IDREG(isar, ID_PFR0, 0x20000030); 222 SET_IDREG(isar, ID_PFR1, 0x00000230); 223 SET_IDREG(isar, ID_DFR0, 0x10200000); 224 cpu->id_afr0 = 0x00000000; 225 SET_IDREG(isar, ID_MMFR0, 0x00111040); 226 SET_IDREG(isar, ID_MMFR1, 0x00000000); 227 SET_IDREG(isar, ID_MMFR2, 0x01000000); 228 SET_IDREG(isar, ID_MMFR3, 0x00000011); 229 SET_IDREG(isar, ID_ISAR0, 0x01103110); 230 SET_IDREG(isar, ID_ISAR1, 0x02212000); 231 SET_IDREG(isar, ID_ISAR2, 0x20232232); 232 SET_IDREG(isar, ID_ISAR3, 0x01111131); 233 SET_IDREG(isar, ID_ISAR4, 0x01310132); 234 SET_IDREG(isar, ID_ISAR5, 0x00000000); 235 SET_IDREG(isar, ID_ISAR6, 0x00000000); 236 cpu->clidr = 0x00000000; /* caches not implemented */ 237 cpu->ctr = 0x8303c003; 238 } 239 240 static const TCGCPUOps arm_v7m_tcg_ops = { 241 /* ARM processors have a weak memory model */ 242 .guest_default_memory_order = 0, 243 .mttcg_supported = true, 244 245 .initialize = arm_translate_init, 246 .translate_code = arm_translate_code, 247 .get_tb_cpu_state = arm_get_tb_cpu_state, 248 .synchronize_from_tb = arm_cpu_synchronize_from_tb, 249 .debug_excp_handler = arm_debug_excp_handler, 250 .restore_state_to_opc = arm_restore_state_to_opc, 251 .mmu_index = arm_cpu_mmu_index, 252 253 #ifdef CONFIG_USER_ONLY 254 .record_sigsegv = arm_cpu_record_sigsegv, 255 .record_sigbus = arm_cpu_record_sigbus, 256 #else 257 .tlb_fill_align = arm_cpu_tlb_fill_align, 258 .pointer_wrap = cpu_pointer_wrap_uint32, 259 .cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt, 260 .cpu_exec_halt = arm_cpu_exec_halt, 261 .cpu_exec_reset = cpu_reset, 262 .do_interrupt = arm_v7m_cpu_do_interrupt, 263 .do_transaction_failed = arm_cpu_do_transaction_failed, 264 .do_unaligned_access = arm_cpu_do_unaligned_access, 265 .adjust_watchpoint_address = arm_adjust_watchpoint_address, 266 .debug_check_watchpoint = arm_debug_check_watchpoint, 267 .debug_check_breakpoint = arm_debug_check_breakpoint, 268 #endif /* !CONFIG_USER_ONLY */ 269 }; 270 271 static void arm_v7m_class_init(ObjectClass *oc, const void *data) 272 { 273 ARMCPUClass *acc = ARM_CPU_CLASS(oc); 274 CPUClass *cc = CPU_CLASS(oc); 275 276 acc->info = data; 277 cc->tcg_ops = &arm_v7m_tcg_ops; 278 } 279 280 static const ARMCPUInfo arm_v7m_cpus[] = { 281 { .name = "cortex-m0", .initfn = cortex_m0_initfn, 282 .class_init = arm_v7m_class_init }, 283 { .name = "cortex-m3", .initfn = cortex_m3_initfn, 284 .class_init = arm_v7m_class_init }, 285 { .name = "cortex-m4", .initfn = cortex_m4_initfn, 286 .class_init = arm_v7m_class_init }, 287 { .name = "cortex-m7", .initfn = cortex_m7_initfn, 288 .class_init = arm_v7m_class_init }, 289 { .name = "cortex-m33", .initfn = cortex_m33_initfn, 290 .class_init = arm_v7m_class_init }, 291 { .name = "cortex-m55", .initfn = cortex_m55_initfn, 292 .class_init = arm_v7m_class_init }, 293 }; 294 295 static void arm_v7m_cpu_register_types(void) 296 { 297 size_t i; 298 299 for (i = 0; i < ARRAY_SIZE(arm_v7m_cpus); ++i) { 300 arm_cpu_register(&arm_v7m_cpus[i]); 301 } 302 } 303 304 type_init(arm_v7m_cpu_register_types) 305