1 /* 2 * qemu user cpu loop 3 * 4 * Copyright (c) 2003-2008 Fabrice Bellard 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program 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 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include "qemu/osdep.h" 21 #include "qemu-common.h" 22 #include "qemu.h" 23 #include "user-internals.h" 24 #include "cpu_loop-common.h" 25 #include "signal-common.h" 26 #include "elf.h" 27 #include "internal.h" 28 #include "fpu_helper.h" 29 30 # ifdef TARGET_ABI_MIPSO32 31 # define MIPS_SYSCALL_NUMBER_UNUSED -1 32 static const int8_t mips_syscall_args[] = { 33 #include "syscall-args-o32.c.inc" 34 }; 35 # endif /* O32 */ 36 37 /* Break codes */ 38 enum { 39 BRK_OVERFLOW = 6, 40 BRK_DIVZERO = 7 41 }; 42 43 static int do_break(CPUMIPSState *env, target_siginfo_t *info, 44 unsigned int code) 45 { 46 int ret = -1; 47 48 switch (code) { 49 case BRK_OVERFLOW: 50 case BRK_DIVZERO: 51 info->si_signo = TARGET_SIGFPE; 52 info->si_errno = 0; 53 info->si_code = (code == BRK_OVERFLOW) ? FPE_INTOVF : FPE_INTDIV; 54 queue_signal(env, info->si_signo, QEMU_SI_FAULT, &*info); 55 ret = 0; 56 break; 57 default: 58 info->si_signo = TARGET_SIGTRAP; 59 info->si_errno = 0; 60 queue_signal(env, info->si_signo, QEMU_SI_FAULT, &*info); 61 ret = 0; 62 break; 63 } 64 65 return ret; 66 } 67 68 void cpu_loop(CPUMIPSState *env) 69 { 70 CPUState *cs = env_cpu(env); 71 target_siginfo_t info; 72 int trapnr; 73 abi_long ret; 74 # ifdef TARGET_ABI_MIPSO32 75 unsigned int syscall_num; 76 # endif 77 78 for(;;) { 79 cpu_exec_start(cs); 80 trapnr = cpu_exec(cs); 81 cpu_exec_end(cs); 82 process_queued_cpu_work(cs); 83 84 switch(trapnr) { 85 case EXCP_SYSCALL: 86 env->active_tc.PC += 4; 87 # ifdef TARGET_ABI_MIPSO32 88 syscall_num = env->active_tc.gpr[2] - 4000; 89 if (syscall_num >= sizeof(mips_syscall_args)) { 90 /* syscall_num is larger that any defined for MIPS O32 */ 91 ret = -TARGET_ENOSYS; 92 } else if (mips_syscall_args[syscall_num] == 93 MIPS_SYSCALL_NUMBER_UNUSED) { 94 /* syscall_num belongs to the range not defined for MIPS O32 */ 95 ret = -TARGET_ENOSYS; 96 } else { 97 /* syscall_num is valid */ 98 int nb_args; 99 abi_ulong sp_reg; 100 abi_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0; 101 102 nb_args = mips_syscall_args[syscall_num]; 103 sp_reg = env->active_tc.gpr[29]; 104 switch (nb_args) { 105 /* these arguments are taken from the stack */ 106 case 8: 107 if ((ret = get_user_ual(arg8, sp_reg + 28)) != 0) { 108 goto done_syscall; 109 } 110 /* fall through */ 111 case 7: 112 if ((ret = get_user_ual(arg7, sp_reg + 24)) != 0) { 113 goto done_syscall; 114 } 115 /* fall through */ 116 case 6: 117 if ((ret = get_user_ual(arg6, sp_reg + 20)) != 0) { 118 goto done_syscall; 119 } 120 /* fall through */ 121 case 5: 122 if ((ret = get_user_ual(arg5, sp_reg + 16)) != 0) { 123 goto done_syscall; 124 } 125 /* fall through */ 126 default: 127 break; 128 } 129 ret = do_syscall(env, env->active_tc.gpr[2], 130 env->active_tc.gpr[4], 131 env->active_tc.gpr[5], 132 env->active_tc.gpr[6], 133 env->active_tc.gpr[7], 134 arg5, arg6, arg7, arg8); 135 } 136 done_syscall: 137 # else 138 ret = do_syscall(env, env->active_tc.gpr[2], 139 env->active_tc.gpr[4], env->active_tc.gpr[5], 140 env->active_tc.gpr[6], env->active_tc.gpr[7], 141 env->active_tc.gpr[8], env->active_tc.gpr[9], 142 env->active_tc.gpr[10], env->active_tc.gpr[11]); 143 # endif /* O32 */ 144 if (ret == -QEMU_ERESTARTSYS) { 145 env->active_tc.PC -= 4; 146 break; 147 } 148 if (ret == -QEMU_ESIGRETURN) { 149 /* Returning from a successful sigreturn syscall. 150 Avoid clobbering register state. */ 151 break; 152 } 153 if ((abi_ulong)ret >= (abi_ulong)-1133) { 154 env->active_tc.gpr[7] = 1; /* error flag */ 155 ret = -ret; 156 } else { 157 env->active_tc.gpr[7] = 0; /* error flag */ 158 } 159 env->active_tc.gpr[2] = ret; 160 break; 161 case EXCP_CpU: 162 case EXCP_RI: 163 info.si_signo = TARGET_SIGILL; 164 info.si_errno = 0; 165 info.si_code = 0; 166 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 167 break; 168 case EXCP_INTERRUPT: 169 /* just indicate that signals should be handled asap */ 170 break; 171 case EXCP_DEBUG: 172 info.si_signo = TARGET_SIGTRAP; 173 info.si_errno = 0; 174 info.si_code = TARGET_TRAP_BRKPT; 175 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 176 break; 177 case EXCP_DSPDIS: 178 info.si_signo = TARGET_SIGILL; 179 info.si_errno = 0; 180 info.si_code = TARGET_ILL_ILLOPC; 181 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 182 break; 183 case EXCP_FPE: 184 info.si_signo = TARGET_SIGFPE; 185 info.si_errno = 0; 186 info.si_code = TARGET_FPE_FLTUNK; 187 if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID) { 188 info.si_code = TARGET_FPE_FLTINV; 189 } else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_DIV0) { 190 info.si_code = TARGET_FPE_FLTDIV; 191 } else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_OVERFLOW) { 192 info.si_code = TARGET_FPE_FLTOVF; 193 } else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_UNDERFLOW) { 194 info.si_code = TARGET_FPE_FLTUND; 195 } else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INEXACT) { 196 info.si_code = TARGET_FPE_FLTRES; 197 } 198 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 199 break; 200 /* The code below was inspired by the MIPS Linux kernel trap 201 * handling code in arch/mips/kernel/traps.c. 202 */ 203 case EXCP_BREAK: 204 { 205 abi_ulong trap_instr; 206 unsigned int code; 207 208 if (env->hflags & MIPS_HFLAG_M16) { 209 if (env->insn_flags & ASE_MICROMIPS) { 210 /* microMIPS mode */ 211 ret = get_user_u16(trap_instr, env->active_tc.PC); 212 if (ret != 0) { 213 goto error; 214 } 215 216 if ((trap_instr >> 10) == 0x11) { 217 /* 16-bit instruction */ 218 code = trap_instr & 0xf; 219 } else { 220 /* 32-bit instruction */ 221 abi_ulong instr_lo; 222 223 ret = get_user_u16(instr_lo, 224 env->active_tc.PC + 2); 225 if (ret != 0) { 226 goto error; 227 } 228 trap_instr = (trap_instr << 16) | instr_lo; 229 code = ((trap_instr >> 6) & ((1 << 20) - 1)); 230 /* Unfortunately, microMIPS also suffers from 231 the old assembler bug... */ 232 if (code >= (1 << 10)) { 233 code >>= 10; 234 } 235 } 236 } else { 237 /* MIPS16e mode */ 238 ret = get_user_u16(trap_instr, env->active_tc.PC); 239 if (ret != 0) { 240 goto error; 241 } 242 code = (trap_instr >> 6) & 0x3f; 243 } 244 } else { 245 ret = get_user_u32(trap_instr, env->active_tc.PC); 246 if (ret != 0) { 247 goto error; 248 } 249 250 /* As described in the original Linux kernel code, the 251 * below checks on 'code' are to work around an old 252 * assembly bug. 253 */ 254 code = ((trap_instr >> 6) & ((1 << 20) - 1)); 255 if (code >= (1 << 10)) { 256 code >>= 10; 257 } 258 } 259 260 if (do_break(env, &info, code) != 0) { 261 goto error; 262 } 263 } 264 break; 265 case EXCP_TRAP: 266 { 267 abi_ulong trap_instr; 268 unsigned int code = 0; 269 270 if (env->hflags & MIPS_HFLAG_M16) { 271 /* microMIPS mode */ 272 abi_ulong instr[2]; 273 274 ret = get_user_u16(instr[0], env->active_tc.PC) || 275 get_user_u16(instr[1], env->active_tc.PC + 2); 276 277 trap_instr = (instr[0] << 16) | instr[1]; 278 } else { 279 ret = get_user_u32(trap_instr, env->active_tc.PC); 280 } 281 282 if (ret != 0) { 283 goto error; 284 } 285 286 /* The immediate versions don't provide a code. */ 287 if (!(trap_instr & 0xFC000000)) { 288 if (env->hflags & MIPS_HFLAG_M16) { 289 /* microMIPS mode */ 290 code = ((trap_instr >> 12) & ((1 << 4) - 1)); 291 } else { 292 code = ((trap_instr >> 6) & ((1 << 10) - 1)); 293 } 294 } 295 296 if (do_break(env, &info, code) != 0) { 297 goto error; 298 } 299 } 300 break; 301 case EXCP_ATOMIC: 302 cpu_exec_step_atomic(cs); 303 break; 304 default: 305 error: 306 EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr); 307 abort(); 308 } 309 process_pending_signals(env); 310 } 311 } 312 313 void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) 314 { 315 CPUState *cpu = env_cpu(env); 316 TaskState *ts = cpu->opaque; 317 struct image_info *info = ts->info; 318 int i; 319 320 struct mode_req { 321 bool single; 322 bool soft; 323 bool fr1; 324 bool frdefault; 325 bool fre; 326 }; 327 328 static const struct mode_req fpu_reqs[] = { 329 [MIPS_ABI_FP_ANY] = { true, true, true, true, true }, 330 [MIPS_ABI_FP_DOUBLE] = { false, false, false, true, true }, 331 [MIPS_ABI_FP_SINGLE] = { true, false, false, false, false }, 332 [MIPS_ABI_FP_SOFT] = { false, true, false, false, false }, 333 [MIPS_ABI_FP_OLD_64] = { false, false, false, false, false }, 334 [MIPS_ABI_FP_XX] = { false, false, true, true, true }, 335 [MIPS_ABI_FP_64] = { false, false, true, false, false }, 336 [MIPS_ABI_FP_64A] = { false, false, true, false, true } 337 }; 338 339 /* 340 * Mode requirements when .MIPS.abiflags is not present in the ELF. 341 * Not present means that everything is acceptable except FR1. 342 */ 343 static struct mode_req none_req = { true, true, false, true, true }; 344 345 struct mode_req prog_req; 346 struct mode_req interp_req; 347 348 for(i = 0; i < 32; i++) { 349 env->active_tc.gpr[i] = regs->regs[i]; 350 } 351 env->active_tc.PC = regs->cp0_epc & ~(target_ulong)1; 352 if (regs->cp0_epc & 1) { 353 env->hflags |= MIPS_HFLAG_M16; 354 } 355 356 #ifdef TARGET_ABI_MIPSO32 357 # define MAX_FP_ABI MIPS_ABI_FP_64A 358 #else 359 # define MAX_FP_ABI MIPS_ABI_FP_SOFT 360 #endif 361 if ((info->fp_abi > MAX_FP_ABI && info->fp_abi != MIPS_ABI_FP_UNKNOWN) 362 || (info->interp_fp_abi > MAX_FP_ABI && 363 info->interp_fp_abi != MIPS_ABI_FP_UNKNOWN)) { 364 fprintf(stderr, "qemu: Unexpected FPU mode\n"); 365 exit(1); 366 } 367 368 prog_req = (info->fp_abi == MIPS_ABI_FP_UNKNOWN) ? none_req 369 : fpu_reqs[info->fp_abi]; 370 interp_req = (info->interp_fp_abi == MIPS_ABI_FP_UNKNOWN) ? none_req 371 : fpu_reqs[info->interp_fp_abi]; 372 373 prog_req.single &= interp_req.single; 374 prog_req.soft &= interp_req.soft; 375 prog_req.fr1 &= interp_req.fr1; 376 prog_req.frdefault &= interp_req.frdefault; 377 prog_req.fre &= interp_req.fre; 378 379 bool cpu_has_mips_r2_r6 = env->insn_flags & ISA_MIPS_R2 || 380 env->insn_flags & ISA_MIPS_R6; 381 382 if (prog_req.fre && !prog_req.frdefault && !prog_req.fr1) { 383 env->CP0_Config5 |= (1 << CP0C5_FRE); 384 if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) { 385 env->hflags |= MIPS_HFLAG_FRE; 386 } 387 } else if ((prog_req.fr1 && prog_req.frdefault) || 388 (prog_req.single && !prog_req.frdefault)) { 389 if ((env->active_fpu.fcr0 & (1 << FCR0_F64) 390 && cpu_has_mips_r2_r6) || prog_req.fr1) { 391 env->CP0_Status |= (1 << CP0St_FR); 392 env->hflags |= MIPS_HFLAG_F64; 393 } 394 } else if (!prog_req.fre && !prog_req.frdefault && 395 !prog_req.fr1 && !prog_req.single && !prog_req.soft) { 396 fprintf(stderr, "qemu: Can't find a matching FPU mode\n"); 397 exit(1); 398 } 399 400 if (env->insn_flags & ISA_NANOMIPS32) { 401 return; 402 } 403 if (((info->elf_flags & EF_MIPS_NAN2008) != 0) != 404 ((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) != 0)) { 405 if ((env->active_fpu.fcr31_rw_bitmask & 406 (1 << FCR31_NAN2008)) == 0) { 407 fprintf(stderr, "ELF binary's NaN mode not supported by CPU\n"); 408 exit(1); 409 } 410 if ((info->elf_flags & EF_MIPS_NAN2008) != 0) { 411 env->active_fpu.fcr31 |= (1 << FCR31_NAN2008); 412 } else { 413 env->active_fpu.fcr31 &= ~(1 << FCR31_NAN2008); 414 } 415 restore_snan_bit_mode(env); 416 } 417 } 418