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 set_feature(&cpu->env, ARM_FEATURE_V6); 49 set_feature(&cpu->env, ARM_FEATURE_M); 50 51 cpu->midr = 0x410cc200; 52 53 /* 54 * These ID register values are not guest visible, because 55 * we do not implement the Main Extension. They must be set 56 * to values corresponding to the Cortex-M0's implemented 57 * features, because QEMU generally controls its emulation 58 * by looking at ID register fields. We use the same values as 59 * for the M3. 60 */ 61 cpu->isar.id_pfr0 = 0x00000030; 62 cpu->isar.id_pfr1 = 0x00000200; 63 cpu->isar.id_dfr0 = 0x00100000; 64 cpu->id_afr0 = 0x00000000; 65 cpu->isar.id_mmfr0 = 0x00000030; 66 cpu->isar.id_mmfr1 = 0x00000000; 67 cpu->isar.id_mmfr2 = 0x00000000; 68 cpu->isar.id_mmfr3 = 0x00000000; 69 cpu->isar.id_isar0 = 0x01141110; 70 cpu->isar.id_isar1 = 0x02111000; 71 cpu->isar.id_isar2 = 0x21112231; 72 cpu->isar.id_isar3 = 0x01111110; 73 cpu->isar.id_isar4 = 0x01310102; 74 cpu->isar.id_isar5 = 0x00000000; 75 cpu->isar.id_isar6 = 0x00000000; 76 } 77 78 static void cortex_m3_initfn(Object *obj) 79 { 80 ARMCPU *cpu = ARM_CPU(obj); 81 set_feature(&cpu->env, ARM_FEATURE_V7); 82 set_feature(&cpu->env, ARM_FEATURE_M); 83 set_feature(&cpu->env, ARM_FEATURE_M_MAIN); 84 cpu->midr = 0x410fc231; 85 cpu->pmsav7_dregion = 8; 86 cpu->isar.id_pfr0 = 0x00000030; 87 cpu->isar.id_pfr1 = 0x00000200; 88 cpu->isar.id_dfr0 = 0x00100000; 89 cpu->id_afr0 = 0x00000000; 90 cpu->isar.id_mmfr0 = 0x00000030; 91 cpu->isar.id_mmfr1 = 0x00000000; 92 cpu->isar.id_mmfr2 = 0x00000000; 93 cpu->isar.id_mmfr3 = 0x00000000; 94 cpu->isar.id_isar0 = 0x01141110; 95 cpu->isar.id_isar1 = 0x02111000; 96 cpu->isar.id_isar2 = 0x21112231; 97 cpu->isar.id_isar3 = 0x01111110; 98 cpu->isar.id_isar4 = 0x01310102; 99 cpu->isar.id_isar5 = 0x00000000; 100 cpu->isar.id_isar6 = 0x00000000; 101 } 102 103 static void cortex_m4_initfn(Object *obj) 104 { 105 ARMCPU *cpu = ARM_CPU(obj); 106 107 set_feature(&cpu->env, ARM_FEATURE_V7); 108 set_feature(&cpu->env, ARM_FEATURE_M); 109 set_feature(&cpu->env, ARM_FEATURE_M_MAIN); 110 set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP); 111 cpu->midr = 0x410fc240; /* r0p0 */ 112 cpu->pmsav7_dregion = 8; 113 cpu->isar.mvfr0 = 0x10110021; 114 cpu->isar.mvfr1 = 0x11000011; 115 cpu->isar.mvfr2 = 0x00000000; 116 cpu->isar.id_pfr0 = 0x00000030; 117 cpu->isar.id_pfr1 = 0x00000200; 118 cpu->isar.id_dfr0 = 0x00100000; 119 cpu->id_afr0 = 0x00000000; 120 cpu->isar.id_mmfr0 = 0x00000030; 121 cpu->isar.id_mmfr1 = 0x00000000; 122 cpu->isar.id_mmfr2 = 0x00000000; 123 cpu->isar.id_mmfr3 = 0x00000000; 124 cpu->isar.id_isar0 = 0x01141110; 125 cpu->isar.id_isar1 = 0x02111000; 126 cpu->isar.id_isar2 = 0x21112231; 127 cpu->isar.id_isar3 = 0x01111110; 128 cpu->isar.id_isar4 = 0x01310102; 129 cpu->isar.id_isar5 = 0x00000000; 130 cpu->isar.id_isar6 = 0x00000000; 131 } 132 133 static void cortex_m7_initfn(Object *obj) 134 { 135 ARMCPU *cpu = ARM_CPU(obj); 136 137 set_feature(&cpu->env, ARM_FEATURE_V7); 138 set_feature(&cpu->env, ARM_FEATURE_M); 139 set_feature(&cpu->env, ARM_FEATURE_M_MAIN); 140 set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP); 141 cpu->midr = 0x411fc272; /* r1p2 */ 142 cpu->pmsav7_dregion = 8; 143 cpu->isar.mvfr0 = 0x10110221; 144 cpu->isar.mvfr1 = 0x12000011; 145 cpu->isar.mvfr2 = 0x00000040; 146 cpu->isar.id_pfr0 = 0x00000030; 147 cpu->isar.id_pfr1 = 0x00000200; 148 cpu->isar.id_dfr0 = 0x00100000; 149 cpu->id_afr0 = 0x00000000; 150 cpu->isar.id_mmfr0 = 0x00100030; 151 cpu->isar.id_mmfr1 = 0x00000000; 152 cpu->isar.id_mmfr2 = 0x01000000; 153 cpu->isar.id_mmfr3 = 0x00000000; 154 cpu->isar.id_isar0 = 0x01101110; 155 cpu->isar.id_isar1 = 0x02112000; 156 cpu->isar.id_isar2 = 0x20232231; 157 cpu->isar.id_isar3 = 0x01111131; 158 cpu->isar.id_isar4 = 0x01310132; 159 cpu->isar.id_isar5 = 0x00000000; 160 cpu->isar.id_isar6 = 0x00000000; 161 } 162 163 static void cortex_m33_initfn(Object *obj) 164 { 165 ARMCPU *cpu = ARM_CPU(obj); 166 167 set_feature(&cpu->env, ARM_FEATURE_V8); 168 set_feature(&cpu->env, ARM_FEATURE_M); 169 set_feature(&cpu->env, ARM_FEATURE_M_MAIN); 170 set_feature(&cpu->env, ARM_FEATURE_M_SECURITY); 171 set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP); 172 cpu->midr = 0x410fd213; /* r0p3 */ 173 cpu->pmsav7_dregion = 16; 174 cpu->sau_sregion = 8; 175 cpu->isar.mvfr0 = 0x10110021; 176 cpu->isar.mvfr1 = 0x11000011; 177 cpu->isar.mvfr2 = 0x00000040; 178 cpu->isar.id_pfr0 = 0x00000030; 179 cpu->isar.id_pfr1 = 0x00000210; 180 cpu->isar.id_dfr0 = 0x00200000; 181 cpu->id_afr0 = 0x00000000; 182 cpu->isar.id_mmfr0 = 0x00101F40; 183 cpu->isar.id_mmfr1 = 0x00000000; 184 cpu->isar.id_mmfr2 = 0x01000000; 185 cpu->isar.id_mmfr3 = 0x00000000; 186 cpu->isar.id_isar0 = 0x01101110; 187 cpu->isar.id_isar1 = 0x02212000; 188 cpu->isar.id_isar2 = 0x20232232; 189 cpu->isar.id_isar3 = 0x01111131; 190 cpu->isar.id_isar4 = 0x01310132; 191 cpu->isar.id_isar5 = 0x00000000; 192 cpu->isar.id_isar6 = 0x00000000; 193 cpu->clidr = 0x00000000; 194 cpu->ctr = 0x8000c000; 195 } 196 197 static void cortex_m55_initfn(Object *obj) 198 { 199 ARMCPU *cpu = ARM_CPU(obj); 200 201 set_feature(&cpu->env, ARM_FEATURE_V8); 202 set_feature(&cpu->env, ARM_FEATURE_V8_1M); 203 set_feature(&cpu->env, ARM_FEATURE_M); 204 set_feature(&cpu->env, ARM_FEATURE_M_MAIN); 205 set_feature(&cpu->env, ARM_FEATURE_M_SECURITY); 206 set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP); 207 cpu->midr = 0x410fd221; /* r0p1 */ 208 cpu->revidr = 0; 209 cpu->pmsav7_dregion = 16; 210 cpu->sau_sregion = 8; 211 /* These are the MVFR* values for the FPU + full MVE configuration */ 212 cpu->isar.mvfr0 = 0x10110221; 213 cpu->isar.mvfr1 = 0x12100211; 214 cpu->isar.mvfr2 = 0x00000040; 215 cpu->isar.id_pfr0 = 0x20000030; 216 cpu->isar.id_pfr1 = 0x00000230; 217 cpu->isar.id_dfr0 = 0x10200000; 218 cpu->id_afr0 = 0x00000000; 219 cpu->isar.id_mmfr0 = 0x00111040; 220 cpu->isar.id_mmfr1 = 0x00000000; 221 cpu->isar.id_mmfr2 = 0x01000000; 222 cpu->isar.id_mmfr3 = 0x00000011; 223 cpu->isar.id_isar0 = 0x01103110; 224 cpu->isar.id_isar1 = 0x02212000; 225 cpu->isar.id_isar2 = 0x20232232; 226 cpu->isar.id_isar3 = 0x01111131; 227 cpu->isar.id_isar4 = 0x01310132; 228 cpu->isar.id_isar5 = 0x00000000; 229 cpu->isar.id_isar6 = 0x00000000; 230 cpu->clidr = 0x00000000; /* caches not implemented */ 231 cpu->ctr = 0x8303c003; 232 } 233 234 static const TCGCPUOps arm_v7m_tcg_ops = { 235 .initialize = arm_translate_init, 236 .translate_code = arm_translate_code, 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, 240 241 #ifdef CONFIG_USER_ONLY 242 .record_sigsegv = arm_cpu_record_sigsegv, 243 .record_sigbus = arm_cpu_record_sigbus, 244 #else 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 */ 255 }; 256 257 static void arm_v7m_class_init(ObjectClass *oc, void *data) 258 { 259 ARMCPUClass *acc = ARM_CPU_CLASS(oc); 260 CPUClass *cc = CPU_CLASS(oc); 261 262 acc->info = data; 263 cc->tcg_ops = &arm_v7m_tcg_ops; 264 cc->gdb_core_xml_file = "arm-m-profile.xml"; 265 } 266 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 }, 280 }; 281 282 static void arm_v7m_cpu_register_types(void) 283 { 284 size_t i; 285 286 for (i = 0; i < ARRAY_SIZE(arm_v7m_cpus); ++i) { 287 arm_cpu_register(&arm_v7m_cpus[i]); 288 } 289 } 290 291 type_init(arm_v7m_cpu_register_types) 292