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 "qapi/error.h" 24 #include "cpu.h" 25 #include "internal.h" 26 #include "kvm_mips.h" 27 #include "qemu/module.h" 28 #include "sysemu/kvm.h" 29 #include "sysemu/qtest.h" 30 #include "exec/exec-all.h" 31 #include "hw/qdev-properties.h" 32 #include "hw/qdev-clock.h" 33 34 static void mips_cpu_set_pc(CPUState *cs, vaddr value) 35 { 36 MIPSCPU *cpu = MIPS_CPU(cs); 37 CPUMIPSState *env = &cpu->env; 38 39 env->active_tc.PC = value & ~(target_ulong)1; 40 if (value & 1) { 41 env->hflags |= MIPS_HFLAG_M16; 42 } else { 43 env->hflags &= ~(MIPS_HFLAG_M16); 44 } 45 } 46 47 static void mips_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb) 48 { 49 MIPSCPU *cpu = MIPS_CPU(cs); 50 CPUMIPSState *env = &cpu->env; 51 52 env->active_tc.PC = tb->pc; 53 env->hflags &= ~MIPS_HFLAG_BMASK; 54 env->hflags |= tb->flags & MIPS_HFLAG_BMASK; 55 } 56 57 static bool mips_cpu_has_work(CPUState *cs) 58 { 59 MIPSCPU *cpu = MIPS_CPU(cs); 60 CPUMIPSState *env = &cpu->env; 61 bool has_work = false; 62 63 /* 64 * Prior to MIPS Release 6 it is implementation dependent if non-enabled 65 * interrupts wake-up the CPU, however most of the implementations only 66 * check for interrupts that can be taken. 67 */ 68 if ((cs->interrupt_request & CPU_INTERRUPT_HARD) && 69 cpu_mips_hw_interrupts_pending(env)) { 70 if (cpu_mips_hw_interrupts_enabled(env) || 71 (env->insn_flags & ISA_MIPS32R6)) { 72 has_work = true; 73 } 74 } 75 76 /* MIPS-MT has the ability to halt the CPU. */ 77 if (env->CP0_Config3 & (1 << CP0C3_MT)) { 78 /* 79 * The QEMU model will issue an _WAKE request whenever the CPUs 80 * should be woken up. 81 */ 82 if (cs->interrupt_request & CPU_INTERRUPT_WAKE) { 83 has_work = true; 84 } 85 86 if (!mips_vpe_active(env)) { 87 has_work = false; 88 } 89 } 90 /* MIPS Release 6 has the ability to halt the CPU. */ 91 if (env->CP0_Config5 & (1 << CP0C5_VP)) { 92 if (cs->interrupt_request & CPU_INTERRUPT_WAKE) { 93 has_work = true; 94 } 95 if (!mips_vp_active(env)) { 96 has_work = false; 97 } 98 } 99 return has_work; 100 } 101 102 static void mips_cpu_reset(DeviceState *dev) 103 { 104 CPUState *s = CPU(dev); 105 MIPSCPU *cpu = MIPS_CPU(s); 106 MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(cpu); 107 CPUMIPSState *env = &cpu->env; 108 109 mcc->parent_reset(dev); 110 111 memset(env, 0, offsetof(CPUMIPSState, end_reset_fields)); 112 113 cpu_state_reset(env); 114 115 #ifndef CONFIG_USER_ONLY 116 if (kvm_enabled()) { 117 kvm_mips_reset_vcpu(cpu); 118 } 119 #endif 120 } 121 122 static void mips_cpu_disas_set_info(CPUState *s, disassemble_info *info) 123 { 124 MIPSCPU *cpu = MIPS_CPU(s); 125 CPUMIPSState *env = &cpu->env; 126 127 if (!(env->insn_flags & ISA_NANOMIPS32)) { 128 #ifdef TARGET_WORDS_BIGENDIAN 129 info->print_insn = print_insn_big_mips; 130 #else 131 info->print_insn = print_insn_little_mips; 132 #endif 133 } else { 134 #if defined(CONFIG_NANOMIPS_DIS) 135 info->print_insn = print_insn_nanomips; 136 #endif 137 } 138 } 139 140 /* 141 * Since commit 6af0bf9c7c3 this model assumes a CPU clocked at 200MHz. 142 */ 143 #define CPU_FREQ_HZ_DEFAULT 200000000 144 #define CP0_COUNT_RATE_DEFAULT 2 145 146 static void mips_cp0_period_set(MIPSCPU *cpu) 147 { 148 CPUMIPSState *env = &cpu->env; 149 150 env->cp0_count_ns = cpu->cp0_count_rate 151 * clock_get_ns(MIPS_CPU(cpu)->clock); 152 assert(env->cp0_count_ns); 153 } 154 155 static void mips_cpu_realizefn(DeviceState *dev, Error **errp) 156 { 157 CPUState *cs = CPU(dev); 158 MIPSCPU *cpu = MIPS_CPU(dev); 159 MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(dev); 160 Error *local_err = NULL; 161 162 if (!clock_get(cpu->clock)) { 163 #ifndef CONFIG_USER_ONLY 164 if (!qtest_enabled()) { 165 g_autofree char *cpu_freq_str = freq_to_str(CPU_FREQ_HZ_DEFAULT); 166 167 warn_report("CPU input clock is not connected to any output clock, " 168 "using default frequency of %s.", cpu_freq_str); 169 } 170 #endif 171 /* Initialize the frequency in case the clock remains unconnected. */ 172 clock_set_hz(cpu->clock, CPU_FREQ_HZ_DEFAULT); 173 } 174 mips_cp0_period_set(cpu); 175 176 cpu_exec_realizefn(cs, &local_err); 177 if (local_err != NULL) { 178 error_propagate(errp, local_err); 179 return; 180 } 181 182 cpu_mips_realize_env(&cpu->env); 183 184 cpu_reset(cs); 185 qemu_init_vcpu(cs); 186 187 mcc->parent_realize(dev, errp); 188 } 189 190 static void mips_cpu_initfn(Object *obj) 191 { 192 MIPSCPU *cpu = MIPS_CPU(obj); 193 CPUMIPSState *env = &cpu->env; 194 MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(obj); 195 196 cpu_set_cpustate_pointers(cpu); 197 cpu->clock = qdev_init_clock_in(DEVICE(obj), "clk-in", NULL, cpu); 198 env->cpu_model = mcc->cpu_def; 199 } 200 201 static char *mips_cpu_type_name(const char *cpu_model) 202 { 203 return g_strdup_printf(MIPS_CPU_TYPE_NAME("%s"), cpu_model); 204 } 205 206 static ObjectClass *mips_cpu_class_by_name(const char *cpu_model) 207 { 208 ObjectClass *oc; 209 char *typename; 210 211 typename = mips_cpu_type_name(cpu_model); 212 oc = object_class_by_name(typename); 213 g_free(typename); 214 return oc; 215 } 216 217 static Property mips_cpu_properties[] = { 218 /* CP0 timer running at half the clock of the CPU */ 219 DEFINE_PROP_UINT32("cp0-count-rate", MIPSCPU, cp0_count_rate, 220 CP0_COUNT_RATE_DEFAULT), 221 DEFINE_PROP_END_OF_LIST() 222 }; 223 224 static void mips_cpu_class_init(ObjectClass *c, void *data) 225 { 226 MIPSCPUClass *mcc = MIPS_CPU_CLASS(c); 227 CPUClass *cc = CPU_CLASS(c); 228 DeviceClass *dc = DEVICE_CLASS(c); 229 230 device_class_set_parent_realize(dc, mips_cpu_realizefn, 231 &mcc->parent_realize); 232 device_class_set_parent_reset(dc, mips_cpu_reset, &mcc->parent_reset); 233 device_class_set_props(dc, mips_cpu_properties); 234 235 cc->class_by_name = mips_cpu_class_by_name; 236 cc->has_work = mips_cpu_has_work; 237 cc->do_interrupt = mips_cpu_do_interrupt; 238 cc->cpu_exec_interrupt = mips_cpu_exec_interrupt; 239 cc->dump_state = mips_cpu_dump_state; 240 cc->set_pc = mips_cpu_set_pc; 241 cc->synchronize_from_tb = mips_cpu_synchronize_from_tb; 242 cc->gdb_read_register = mips_cpu_gdb_read_register; 243 cc->gdb_write_register = mips_cpu_gdb_write_register; 244 #ifndef CONFIG_USER_ONLY 245 cc->do_transaction_failed = mips_cpu_do_transaction_failed; 246 cc->do_unaligned_access = mips_cpu_do_unaligned_access; 247 cc->get_phys_page_debug = mips_cpu_get_phys_page_debug; 248 cc->vmsd = &vmstate_mips_cpu; 249 #endif 250 cc->disas_set_info = mips_cpu_disas_set_info; 251 #ifdef CONFIG_TCG 252 cc->tcg_initialize = mips_tcg_init; 253 cc->tlb_fill = mips_cpu_tlb_fill; 254 #endif 255 256 cc->gdb_num_core_regs = 73; 257 cc->gdb_stop_before_watchpoint = true; 258 } 259 260 static const TypeInfo mips_cpu_type_info = { 261 .name = TYPE_MIPS_CPU, 262 .parent = TYPE_CPU, 263 .instance_size = sizeof(MIPSCPU), 264 .instance_init = mips_cpu_initfn, 265 .abstract = true, 266 .class_size = sizeof(MIPSCPUClass), 267 .class_init = mips_cpu_class_init, 268 }; 269 270 static void mips_cpu_cpudef_class_init(ObjectClass *oc, void *data) 271 { 272 MIPSCPUClass *mcc = MIPS_CPU_CLASS(oc); 273 mcc->cpu_def = data; 274 } 275 276 static void mips_register_cpudef_type(const struct mips_def_t *def) 277 { 278 char *typename = mips_cpu_type_name(def->name); 279 TypeInfo ti = { 280 .name = typename, 281 .parent = TYPE_MIPS_CPU, 282 .class_init = mips_cpu_cpudef_class_init, 283 .class_data = (void *)def, 284 }; 285 286 type_register(&ti); 287 g_free(typename); 288 } 289 290 static void mips_cpu_register_types(void) 291 { 292 int i; 293 294 type_register_static(&mips_cpu_type_info); 295 for (i = 0; i < mips_defs_number; i++) { 296 mips_register_cpudef_type(&mips_defs[i]); 297 } 298 } 299 300 type_init(mips_cpu_register_types) 301 302 /* Could be used by generic CPU object */ 303 MIPSCPU *mips_cpu_create_with_clock(const char *cpu_type, Clock *cpu_refclk) 304 { 305 DeviceState *cpu; 306 307 cpu = DEVICE(object_new(cpu_type)); 308 qdev_connect_clock_in(cpu, "clk-in", cpu_refclk); 309 qdev_realize(cpu, NULL, &error_abort); 310 311 return MIPS_CPU(cpu); 312 } 313