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