1 /* 2 * QEMU MIPS CPU 3 * 4 * Copyright (c) 2012 SUSE LINUX Products GmbH 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, see 18 * <http://www.gnu.org/licenses/lgpl-2.1.html> 19 */ 20 21 #include "qemu/osdep.h" 22 #include "qemu/cutils.h" 23 #include "qemu/qemu-print.h" 24 #include "qapi/error.h" 25 #include "cpu.h" 26 #include "internal.h" 27 #include "kvm_mips.h" 28 #include "qemu/module.h" 29 #include "sysemu/kvm.h" 30 #include "sysemu/qtest.h" 31 #include "exec/exec-all.h" 32 #include "hw/qdev-properties.h" 33 #include "hw/qdev-clock.h" 34 #include "hw/semihosting/semihost.h" 35 #include "qapi/qapi-commands-machine-target.h" 36 37 static void mips_cpu_set_pc(CPUState *cs, vaddr value) 38 { 39 MIPSCPU *cpu = MIPS_CPU(cs); 40 CPUMIPSState *env = &cpu->env; 41 42 env->active_tc.PC = value & ~(target_ulong)1; 43 if (value & 1) { 44 env->hflags |= MIPS_HFLAG_M16; 45 } else { 46 env->hflags &= ~(MIPS_HFLAG_M16); 47 } 48 } 49 50 static void mips_cpu_synchronize_from_tb(CPUState *cs, 51 const TranslationBlock *tb) 52 { 53 MIPSCPU *cpu = MIPS_CPU(cs); 54 CPUMIPSState *env = &cpu->env; 55 56 env->active_tc.PC = tb->pc; 57 env->hflags &= ~MIPS_HFLAG_BMASK; 58 env->hflags |= tb->flags & MIPS_HFLAG_BMASK; 59 } 60 61 static bool mips_cpu_has_work(CPUState *cs) 62 { 63 MIPSCPU *cpu = MIPS_CPU(cs); 64 CPUMIPSState *env = &cpu->env; 65 bool has_work = false; 66 67 /* 68 * Prior to MIPS Release 6 it is implementation dependent if non-enabled 69 * interrupts wake-up the CPU, however most of the implementations only 70 * check for interrupts that can be taken. 71 */ 72 if ((cs->interrupt_request & CPU_INTERRUPT_HARD) && 73 cpu_mips_hw_interrupts_pending(env)) { 74 if (cpu_mips_hw_interrupts_enabled(env) || 75 (env->insn_flags & ISA_MIPS32R6)) { 76 has_work = true; 77 } 78 } 79 80 /* MIPS-MT has the ability to halt the CPU. */ 81 if (ase_mt_available(env)) { 82 /* 83 * The QEMU model will issue an _WAKE request whenever the CPUs 84 * should be woken up. 85 */ 86 if (cs->interrupt_request & CPU_INTERRUPT_WAKE) { 87 has_work = true; 88 } 89 90 if (!mips_vpe_active(env)) { 91 has_work = false; 92 } 93 } 94 /* MIPS Release 6 has the ability to halt the CPU. */ 95 if (env->CP0_Config5 & (1 << CP0C5_VP)) { 96 if (cs->interrupt_request & CPU_INTERRUPT_WAKE) { 97 has_work = true; 98 } 99 if (!mips_vp_active(env)) { 100 has_work = false; 101 } 102 } 103 return has_work; 104 } 105 106 #include "translate_init.c.inc" 107 108 /* TODO QOM'ify CPU reset and remove */ 109 static void cpu_state_reset(CPUMIPSState *env) 110 { 111 CPUState *cs = env_cpu(env); 112 113 /* Reset registers to their default values */ 114 env->CP0_PRid = env->cpu_model->CP0_PRid; 115 env->CP0_Config0 = env->cpu_model->CP0_Config0; 116 #ifdef TARGET_WORDS_BIGENDIAN 117 env->CP0_Config0 |= (1 << CP0C0_BE); 118 #endif 119 env->CP0_Config1 = env->cpu_model->CP0_Config1; 120 env->CP0_Config2 = env->cpu_model->CP0_Config2; 121 env->CP0_Config3 = env->cpu_model->CP0_Config3; 122 env->CP0_Config4 = env->cpu_model->CP0_Config4; 123 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask; 124 env->CP0_Config5 = env->cpu_model->CP0_Config5; 125 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask; 126 env->CP0_Config6 = env->cpu_model->CP0_Config6; 127 env->CP0_Config6_rw_bitmask = env->cpu_model->CP0_Config6_rw_bitmask; 128 env->CP0_Config7 = env->cpu_model->CP0_Config7; 129 env->CP0_Config7_rw_bitmask = env->cpu_model->CP0_Config7_rw_bitmask; 130 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask 131 << env->cpu_model->CP0_LLAddr_shift; 132 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift; 133 env->SYNCI_Step = env->cpu_model->SYNCI_Step; 134 env->CCRes = env->cpu_model->CCRes; 135 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask; 136 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask; 137 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl; 138 env->current_tc = 0; 139 env->SEGBITS = env->cpu_model->SEGBITS; 140 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1); 141 #if defined(TARGET_MIPS64) 142 if (env->cpu_model->insn_flags & ISA_MIPS3) { 143 env->SEGMask |= 3ULL << 62; 144 } 145 #endif 146 env->PABITS = env->cpu_model->PABITS; 147 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask; 148 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0; 149 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask; 150 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1; 151 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask; 152 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2; 153 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask; 154 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3; 155 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask; 156 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4; 157 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask; 158 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain; 159 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask; 160 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0; 161 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask; 162 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31; 163 env->msair = env->cpu_model->MSAIR; 164 env->insn_flags = env->cpu_model->insn_flags; 165 166 #if defined(CONFIG_USER_ONLY) 167 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU); 168 # ifdef TARGET_MIPS64 169 /* Enable 64-bit register mode. */ 170 env->CP0_Status |= (1 << CP0St_PX); 171 # endif 172 # ifdef TARGET_ABI_MIPSN64 173 /* Enable 64-bit address mode. */ 174 env->CP0_Status |= (1 << CP0St_UX); 175 # endif 176 /* 177 * Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR 178 * hardware registers. 179 */ 180 env->CP0_HWREna |= 0x0000000F; 181 if (env->CP0_Config1 & (1 << CP0C1_FP)) { 182 env->CP0_Status |= (1 << CP0St_CU1); 183 } 184 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) { 185 env->CP0_Status |= (1 << CP0St_MX); 186 } 187 # if defined(TARGET_MIPS64) 188 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */ 189 if ((env->CP0_Config1 & (1 << CP0C1_FP)) && 190 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) { 191 env->CP0_Status |= (1 << CP0St_FR); 192 } 193 # endif 194 #else /* !CONFIG_USER_ONLY */ 195 if (env->hflags & MIPS_HFLAG_BMASK) { 196 /* 197 * If the exception was raised from a delay slot, 198 * come back to the jump. 199 */ 200 env->CP0_ErrorEPC = (env->active_tc.PC 201 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4)); 202 } else { 203 env->CP0_ErrorEPC = env->active_tc.PC; 204 } 205 env->active_tc.PC = env->exception_base; 206 env->CP0_Random = env->tlb->nb_tlb - 1; 207 env->tlb->tlb_in_use = env->tlb->nb_tlb; 208 env->CP0_Wired = 0; 209 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId; 210 env->CP0_EBase = (cs->cpu_index & 0x3FF); 211 if (mips_um_ksegs_enabled()) { 212 env->CP0_EBase |= 0x40000000; 213 } else { 214 env->CP0_EBase |= (int32_t)0x80000000; 215 } 216 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) { 217 env->CP0_CMGCRBase = 0x1fbf8000 >> 4; 218 } 219 env->CP0_EntryHi_ASID_mask = (env->CP0_Config5 & (1 << CP0C5_MI)) ? 220 0x0 : (env->CP0_Config4 & (1 << CP0C4_AE)) ? 0x3ff : 0xff; 221 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL); 222 /* 223 * Vectored interrupts not implemented, timer on int 7, 224 * no performance counters. 225 */ 226 env->CP0_IntCtl = 0xe0000000; 227 { 228 int i; 229 230 for (i = 0; i < 7; i++) { 231 env->CP0_WatchLo[i] = 0; 232 env->CP0_WatchHi[i] = 0x80000000; 233 } 234 env->CP0_WatchLo[7] = 0; 235 env->CP0_WatchHi[7] = 0; 236 } 237 /* Count register increments in debug mode, EJTAG version 1 */ 238 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER); 239 240 cpu_mips_store_count(env, 1); 241 242 if (ase_mt_available(env)) { 243 int i; 244 245 /* Only TC0 on VPE 0 starts as active. */ 246 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) { 247 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE; 248 env->tcs[i].CP0_TCHalt = 1; 249 } 250 env->active_tc.CP0_TCHalt = 1; 251 cs->halted = 1; 252 253 if (cs->cpu_index == 0) { 254 /* VPE0 starts up enabled. */ 255 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP); 256 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA); 257 258 /* TC0 starts up unhalted. */ 259 cs->halted = 0; 260 env->active_tc.CP0_TCHalt = 0; 261 env->tcs[0].CP0_TCHalt = 0; 262 /* With thread 0 active. */ 263 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A); 264 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A); 265 } 266 } 267 268 /* 269 * Configure default legacy segmentation control. We use this regardless of 270 * whether segmentation control is presented to the guest. 271 */ 272 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */ 273 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM); 274 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */ 275 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16; 276 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */ 277 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) | 278 (2 << CP0SC_C); 279 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */ 280 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) | 281 (3 << CP0SC_C)) << 16; 282 /* USeg (seg4 0x40000000..0x7FFFFFFF) */ 283 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) | 284 (1 << CP0SC_EU) | (2 << CP0SC_C); 285 /* USeg (seg5 0x00000000..0x3FFFFFFF) */ 286 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) | 287 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16; 288 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */ 289 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM); 290 #endif /* !CONFIG_USER_ONLY */ 291 if ((env->insn_flags & ISA_MIPS32R6) && 292 (env->active_fpu.fcr0 & (1 << FCR0_F64))) { 293 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */ 294 env->CP0_Status |= (1 << CP0St_FR); 295 } 296 297 if (env->insn_flags & ISA_MIPS32R6) { 298 /* PTW = 1 */ 299 env->CP0_PWSize = 0x40; 300 /* GDI = 12 */ 301 /* UDI = 12 */ 302 /* MDI = 12 */ 303 /* PRI = 12 */ 304 /* PTEI = 2 */ 305 env->CP0_PWField = 0x0C30C302; 306 } else { 307 /* GDI = 0 */ 308 /* UDI = 0 */ 309 /* MDI = 0 */ 310 /* PRI = 0 */ 311 /* PTEI = 2 */ 312 env->CP0_PWField = 0x02; 313 } 314 315 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) { 316 /* microMIPS on reset when Config3.ISA is 3 */ 317 env->hflags |= MIPS_HFLAG_M16; 318 } 319 320 /* MSA */ 321 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) { 322 msa_reset(env); 323 } 324 325 compute_hflags(env); 326 restore_fp_status(env); 327 restore_pamask(env); 328 cs->exception_index = EXCP_NONE; 329 330 if (semihosting_get_argc()) { 331 /* UHI interface can be used to obtain argc and argv */ 332 env->active_tc.gpr[4] = -1; 333 } 334 } 335 336 static void mips_cpu_reset(DeviceState *dev) 337 { 338 CPUState *s = CPU(dev); 339 MIPSCPU *cpu = MIPS_CPU(s); 340 MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(cpu); 341 CPUMIPSState *env = &cpu->env; 342 343 mcc->parent_reset(dev); 344 345 memset(env, 0, offsetof(CPUMIPSState, end_reset_fields)); 346 347 cpu_state_reset(env); 348 349 #ifndef CONFIG_USER_ONLY 350 if (kvm_enabled()) { 351 kvm_mips_reset_vcpu(cpu); 352 } 353 #endif 354 } 355 356 static void mips_cpu_disas_set_info(CPUState *s, disassemble_info *info) 357 { 358 MIPSCPU *cpu = MIPS_CPU(s); 359 CPUMIPSState *env = &cpu->env; 360 361 if (!(env->insn_flags & ISA_NANOMIPS32)) { 362 #ifdef TARGET_WORDS_BIGENDIAN 363 info->print_insn = print_insn_big_mips; 364 #else 365 info->print_insn = print_insn_little_mips; 366 #endif 367 } else { 368 #if defined(CONFIG_NANOMIPS_DIS) 369 info->print_insn = print_insn_nanomips; 370 #endif 371 } 372 } 373 374 /* 375 * Since commit 6af0bf9c7c3 this model assumes a CPU clocked at 200MHz. 376 */ 377 #define CPU_FREQ_HZ_DEFAULT 200000000 378 #define CP0_COUNT_RATE_DEFAULT 2 379 380 static void mips_cp0_period_set(MIPSCPU *cpu) 381 { 382 CPUMIPSState *env = &cpu->env; 383 384 env->cp0_count_ns = clock_ticks_to_ns(MIPS_CPU(cpu)->clock, 385 cpu->cp0_count_rate); 386 assert(env->cp0_count_ns); 387 } 388 389 static void mips_cpu_realizefn(DeviceState *dev, Error **errp) 390 { 391 CPUState *cs = CPU(dev); 392 MIPSCPU *cpu = MIPS_CPU(dev); 393 CPUMIPSState *env = &cpu->env; 394 MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(dev); 395 Error *local_err = NULL; 396 397 if (!clock_get(cpu->clock)) { 398 #ifndef CONFIG_USER_ONLY 399 if (!qtest_enabled()) { 400 g_autofree char *cpu_freq_str = freq_to_str(CPU_FREQ_HZ_DEFAULT); 401 402 warn_report("CPU input clock is not connected to any output clock, " 403 "using default frequency of %s.", cpu_freq_str); 404 } 405 #endif 406 /* Initialize the frequency in case the clock remains unconnected. */ 407 clock_set_hz(cpu->clock, CPU_FREQ_HZ_DEFAULT); 408 } 409 mips_cp0_period_set(cpu); 410 411 cpu_exec_realizefn(cs, &local_err); 412 if (local_err != NULL) { 413 error_propagate(errp, local_err); 414 return; 415 } 416 417 env->exception_base = (int32_t)0xBFC00000; 418 419 #ifndef CONFIG_USER_ONLY 420 mmu_init(env, env->cpu_model); 421 #endif 422 fpu_init(env, env->cpu_model); 423 mvp_init(env); 424 425 cpu_reset(cs); 426 qemu_init_vcpu(cs); 427 428 mcc->parent_realize(dev, errp); 429 } 430 431 static void mips_cpu_initfn(Object *obj) 432 { 433 MIPSCPU *cpu = MIPS_CPU(obj); 434 CPUMIPSState *env = &cpu->env; 435 MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(obj); 436 437 cpu_set_cpustate_pointers(cpu); 438 cpu->clock = qdev_init_clock_in(DEVICE(obj), "clk-in", NULL, cpu); 439 env->cpu_model = mcc->cpu_def; 440 } 441 442 static char *mips_cpu_type_name(const char *cpu_model) 443 { 444 return g_strdup_printf(MIPS_CPU_TYPE_NAME("%s"), cpu_model); 445 } 446 447 static ObjectClass *mips_cpu_class_by_name(const char *cpu_model) 448 { 449 ObjectClass *oc; 450 char *typename; 451 452 typename = mips_cpu_type_name(cpu_model); 453 oc = object_class_by_name(typename); 454 g_free(typename); 455 return oc; 456 } 457 458 static Property mips_cpu_properties[] = { 459 /* CP0 timer running at half the clock of the CPU */ 460 DEFINE_PROP_UINT32("cp0-count-rate", MIPSCPU, cp0_count_rate, 461 CP0_COUNT_RATE_DEFAULT), 462 DEFINE_PROP_END_OF_LIST() 463 }; 464 465 static void mips_cpu_class_init(ObjectClass *c, void *data) 466 { 467 MIPSCPUClass *mcc = MIPS_CPU_CLASS(c); 468 CPUClass *cc = CPU_CLASS(c); 469 DeviceClass *dc = DEVICE_CLASS(c); 470 471 device_class_set_parent_realize(dc, mips_cpu_realizefn, 472 &mcc->parent_realize); 473 device_class_set_parent_reset(dc, mips_cpu_reset, &mcc->parent_reset); 474 device_class_set_props(dc, mips_cpu_properties); 475 476 cc->class_by_name = mips_cpu_class_by_name; 477 cc->has_work = mips_cpu_has_work; 478 cc->do_interrupt = mips_cpu_do_interrupt; 479 cc->cpu_exec_interrupt = mips_cpu_exec_interrupt; 480 cc->dump_state = mips_cpu_dump_state; 481 cc->set_pc = mips_cpu_set_pc; 482 cc->synchronize_from_tb = mips_cpu_synchronize_from_tb; 483 cc->gdb_read_register = mips_cpu_gdb_read_register; 484 cc->gdb_write_register = mips_cpu_gdb_write_register; 485 #ifndef CONFIG_USER_ONLY 486 cc->do_transaction_failed = mips_cpu_do_transaction_failed; 487 cc->do_unaligned_access = mips_cpu_do_unaligned_access; 488 cc->get_phys_page_debug = mips_cpu_get_phys_page_debug; 489 cc->vmsd = &vmstate_mips_cpu; 490 #endif 491 cc->disas_set_info = mips_cpu_disas_set_info; 492 #ifdef CONFIG_TCG 493 cc->tcg_initialize = mips_tcg_init; 494 cc->tlb_fill = mips_cpu_tlb_fill; 495 #endif 496 497 cc->gdb_num_core_regs = 73; 498 cc->gdb_stop_before_watchpoint = true; 499 } 500 501 static const TypeInfo mips_cpu_type_info = { 502 .name = TYPE_MIPS_CPU, 503 .parent = TYPE_CPU, 504 .instance_size = sizeof(MIPSCPU), 505 .instance_init = mips_cpu_initfn, 506 .abstract = true, 507 .class_size = sizeof(MIPSCPUClass), 508 .class_init = mips_cpu_class_init, 509 }; 510 511 static void mips_cpu_cpudef_class_init(ObjectClass *oc, void *data) 512 { 513 MIPSCPUClass *mcc = MIPS_CPU_CLASS(oc); 514 mcc->cpu_def = data; 515 } 516 517 static void mips_register_cpudef_type(const struct mips_def_t *def) 518 { 519 char *typename = mips_cpu_type_name(def->name); 520 TypeInfo ti = { 521 .name = typename, 522 .parent = TYPE_MIPS_CPU, 523 .class_init = mips_cpu_cpudef_class_init, 524 .class_data = (void *)def, 525 }; 526 527 type_register(&ti); 528 g_free(typename); 529 } 530 531 static void mips_cpu_register_types(void) 532 { 533 int i; 534 535 type_register_static(&mips_cpu_type_info); 536 for (i = 0; i < mips_defs_number; i++) { 537 mips_register_cpudef_type(&mips_defs[i]); 538 } 539 } 540 541 type_init(mips_cpu_register_types) 542 543 static void mips_cpu_add_definition(gpointer data, gpointer user_data) 544 { 545 ObjectClass *oc = data; 546 CpuDefinitionInfoList **cpu_list = user_data; 547 CpuDefinitionInfo *info; 548 const char *typename; 549 550 typename = object_class_get_name(oc); 551 info = g_malloc0(sizeof(*info)); 552 info->name = g_strndup(typename, 553 strlen(typename) - strlen("-" TYPE_MIPS_CPU)); 554 info->q_typename = g_strdup(typename); 555 556 QAPI_LIST_PREPEND(*cpu_list, info); 557 } 558 559 CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp) 560 { 561 CpuDefinitionInfoList *cpu_list = NULL; 562 GSList *list; 563 564 list = object_class_get_list(TYPE_MIPS_CPU, false); 565 g_slist_foreach(list, mips_cpu_add_definition, &cpu_list); 566 g_slist_free(list); 567 568 return cpu_list; 569 } 570 571 /* Could be used by generic CPU object */ 572 MIPSCPU *mips_cpu_create_with_clock(const char *cpu_type, Clock *cpu_refclk) 573 { 574 DeviceState *cpu; 575 576 cpu = DEVICE(object_new(cpu_type)); 577 qdev_connect_clock_in(cpu, "clk-in", cpu_refclk); 578 qdev_realize(cpu, NULL, &error_abort); 579 580 return MIPS_CPU(cpu); 581 } 582 583 bool cpu_supports_isa(const CPUMIPSState *env, uint64_t isa_mask) 584 { 585 return (env->cpu_model->insn_flags & isa_mask) != 0; 586 } 587 588 bool cpu_type_supports_isa(const char *cpu_type, uint64_t isa) 589 { 590 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type)); 591 return (mcc->cpu_def->insn_flags & isa) != 0; 592 } 593 594 bool cpu_type_supports_cps_smp(const char *cpu_type) 595 { 596 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type)); 597 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0; 598 } 599 600 void cpu_set_exception_base(int vp_index, target_ulong address) 601 { 602 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index)); 603 vp->env.exception_base = address; 604 } 605