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