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 "hw/core/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 CPUClass *cc = CPU_GET_CLASS(cs); 23 ARMCPU *cpu = ARM_CPU(cs); 24 CPUARMState *env = &cpu->env; 25 bool ret = false; 26 27 /* 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). 34 */ 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); 39 ret = true; 40 } 41 return ret; 42 } 43 44 #endif /* !CONFIG_USER_ONLY */ 45 46 static void cortex_m0_initfn(Object *obj) 47 { 48 ARMCPU *cpu = ARM_CPU(obj); 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 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; 77 } 78 79 static void cortex_m3_initfn(Object *obj) 80 { 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; 102 } 103 104 static void cortex_m4_initfn(Object *obj) 105 { 106 ARMCPU *cpu = ARM_CPU(obj); 107 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; 132 } 133 134 static void cortex_m7_initfn(Object *obj) 135 { 136 ARMCPU *cpu = ARM_CPU(obj); 137 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; 162 } 163 164 static void cortex_m33_initfn(Object *obj) 165 { 166 ARMCPU *cpu = ARM_CPU(obj); 167 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; 196 } 197 198 static void cortex_m55_initfn(Object *obj) 199 { 200 ARMCPU *cpu = ARM_CPU(obj); 201 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 */ 209 cpu->revidr = 0; 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; 233 } 234 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, 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 = arm_cpu_tlb_fill, 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