cpu_loop.c (15400B)
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 32static const int8_t mips_syscall_args[] = { 33#include "syscall-args-o32.c.inc" 34}; 35# endif /* O32 */ 36 37/* Break codes */ 38enum { 39 BRK_OVERFLOW = 6, 40 BRK_DIVZERO = 7 41}; 42 43static 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 68void 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 } 136done_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 == -TARGET_ERESTARTSYS) { 145 env->active_tc.PC -= 4; 146 break; 147 } 148 if (ret == -TARGET_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_TLBL: 162 case EXCP_TLBS: 163 case EXCP_AdEL: 164 case EXCP_AdES: 165 info.si_signo = TARGET_SIGSEGV; 166 info.si_errno = 0; 167 /* XXX: check env->error_code */ 168 info.si_code = TARGET_SEGV_MAPERR; 169 info._sifields._sigfault._addr = env->CP0_BadVAddr; 170 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 171 break; 172 case EXCP_CpU: 173 case EXCP_RI: 174 info.si_signo = TARGET_SIGILL; 175 info.si_errno = 0; 176 info.si_code = 0; 177 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 178 break; 179 case EXCP_INTERRUPT: 180 /* just indicate that signals should be handled asap */ 181 break; 182 case EXCP_DEBUG: 183 info.si_signo = TARGET_SIGTRAP; 184 info.si_errno = 0; 185 info.si_code = TARGET_TRAP_BRKPT; 186 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 187 break; 188 case EXCP_DSPDIS: 189 info.si_signo = TARGET_SIGILL; 190 info.si_errno = 0; 191 info.si_code = TARGET_ILL_ILLOPC; 192 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 193 break; 194 case EXCP_FPE: 195 info.si_signo = TARGET_SIGFPE; 196 info.si_errno = 0; 197 info.si_code = TARGET_FPE_FLTUNK; 198 if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID) { 199 info.si_code = TARGET_FPE_FLTINV; 200 } else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_DIV0) { 201 info.si_code = TARGET_FPE_FLTDIV; 202 } else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_OVERFLOW) { 203 info.si_code = TARGET_FPE_FLTOVF; 204 } else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_UNDERFLOW) { 205 info.si_code = TARGET_FPE_FLTUND; 206 } else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INEXACT) { 207 info.si_code = TARGET_FPE_FLTRES; 208 } 209 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 210 break; 211 /* The code below was inspired by the MIPS Linux kernel trap 212 * handling code in arch/mips/kernel/traps.c. 213 */ 214 case EXCP_BREAK: 215 { 216 abi_ulong trap_instr; 217 unsigned int code; 218 219 if (env->hflags & MIPS_HFLAG_M16) { 220 if (env->insn_flags & ASE_MICROMIPS) { 221 /* microMIPS mode */ 222 ret = get_user_u16(trap_instr, env->active_tc.PC); 223 if (ret != 0) { 224 goto error; 225 } 226 227 if ((trap_instr >> 10) == 0x11) { 228 /* 16-bit instruction */ 229 code = trap_instr & 0xf; 230 } else { 231 /* 32-bit instruction */ 232 abi_ulong instr_lo; 233 234 ret = get_user_u16(instr_lo, 235 env->active_tc.PC + 2); 236 if (ret != 0) { 237 goto error; 238 } 239 trap_instr = (trap_instr << 16) | instr_lo; 240 code = ((trap_instr >> 6) & ((1 << 20) - 1)); 241 /* Unfortunately, microMIPS also suffers from 242 the old assembler bug... */ 243 if (code >= (1 << 10)) { 244 code >>= 10; 245 } 246 } 247 } else { 248 /* MIPS16e mode */ 249 ret = get_user_u16(trap_instr, env->active_tc.PC); 250 if (ret != 0) { 251 goto error; 252 } 253 code = (trap_instr >> 6) & 0x3f; 254 } 255 } else { 256 ret = get_user_u32(trap_instr, env->active_tc.PC); 257 if (ret != 0) { 258 goto error; 259 } 260 261 /* As described in the original Linux kernel code, the 262 * below checks on 'code' are to work around an old 263 * assembly bug. 264 */ 265 code = ((trap_instr >> 6) & ((1 << 20) - 1)); 266 if (code >= (1 << 10)) { 267 code >>= 10; 268 } 269 } 270 271 if (do_break(env, &info, code) != 0) { 272 goto error; 273 } 274 } 275 break; 276 case EXCP_TRAP: 277 { 278 abi_ulong trap_instr; 279 unsigned int code = 0; 280 281 if (env->hflags & MIPS_HFLAG_M16) { 282 /* microMIPS mode */ 283 abi_ulong instr[2]; 284 285 ret = get_user_u16(instr[0], env->active_tc.PC) || 286 get_user_u16(instr[1], env->active_tc.PC + 2); 287 288 trap_instr = (instr[0] << 16) | instr[1]; 289 } else { 290 ret = get_user_u32(trap_instr, env->active_tc.PC); 291 } 292 293 if (ret != 0) { 294 goto error; 295 } 296 297 /* The immediate versions don't provide a code. */ 298 if (!(trap_instr & 0xFC000000)) { 299 if (env->hflags & MIPS_HFLAG_M16) { 300 /* microMIPS mode */ 301 code = ((trap_instr >> 12) & ((1 << 4) - 1)); 302 } else { 303 code = ((trap_instr >> 6) & ((1 << 10) - 1)); 304 } 305 } 306 307 if (do_break(env, &info, code) != 0) { 308 goto error; 309 } 310 } 311 break; 312 case EXCP_ATOMIC: 313 cpu_exec_step_atomic(cs); 314 break; 315 default: 316error: 317 EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr); 318 abort(); 319 } 320 process_pending_signals(env); 321 } 322} 323 324void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) 325{ 326 CPUState *cpu = env_cpu(env); 327 TaskState *ts = cpu->opaque; 328 struct image_info *info = ts->info; 329 int i; 330 331 struct mode_req { 332 bool single; 333 bool soft; 334 bool fr1; 335 bool frdefault; 336 bool fre; 337 }; 338 339 static const struct mode_req fpu_reqs[] = { 340 [MIPS_ABI_FP_ANY] = { true, true, true, true, true }, 341 [MIPS_ABI_FP_DOUBLE] = { false, false, false, true, true }, 342 [MIPS_ABI_FP_SINGLE] = { true, false, false, false, false }, 343 [MIPS_ABI_FP_SOFT] = { false, true, false, false, false }, 344 [MIPS_ABI_FP_OLD_64] = { false, false, false, false, false }, 345 [MIPS_ABI_FP_XX] = { false, false, true, true, true }, 346 [MIPS_ABI_FP_64] = { false, false, true, false, false }, 347 [MIPS_ABI_FP_64A] = { false, false, true, false, true } 348 }; 349 350 /* 351 * Mode requirements when .MIPS.abiflags is not present in the ELF. 352 * Not present means that everything is acceptable except FR1. 353 */ 354 static struct mode_req none_req = { true, true, false, true, true }; 355 356 struct mode_req prog_req; 357 struct mode_req interp_req; 358 359 for(i = 0; i < 32; i++) { 360 env->active_tc.gpr[i] = regs->regs[i]; 361 } 362 env->active_tc.PC = regs->cp0_epc & ~(target_ulong)1; 363 if (regs->cp0_epc & 1) { 364 env->hflags |= MIPS_HFLAG_M16; 365 } 366 367#ifdef TARGET_ABI_MIPSO32 368# define MAX_FP_ABI MIPS_ABI_FP_64A 369#else 370# define MAX_FP_ABI MIPS_ABI_FP_SOFT 371#endif 372 if ((info->fp_abi > MAX_FP_ABI && info->fp_abi != MIPS_ABI_FP_UNKNOWN) 373 || (info->interp_fp_abi > MAX_FP_ABI && 374 info->interp_fp_abi != MIPS_ABI_FP_UNKNOWN)) { 375 fprintf(stderr, "qemu: Unexpected FPU mode\n"); 376 exit(1); 377 } 378 379 prog_req = (info->fp_abi == MIPS_ABI_FP_UNKNOWN) ? none_req 380 : fpu_reqs[info->fp_abi]; 381 interp_req = (info->interp_fp_abi == MIPS_ABI_FP_UNKNOWN) ? none_req 382 : fpu_reqs[info->interp_fp_abi]; 383 384 prog_req.single &= interp_req.single; 385 prog_req.soft &= interp_req.soft; 386 prog_req.fr1 &= interp_req.fr1; 387 prog_req.frdefault &= interp_req.frdefault; 388 prog_req.fre &= interp_req.fre; 389 390 bool cpu_has_mips_r2_r6 = env->insn_flags & ISA_MIPS_R2 || 391 env->insn_flags & ISA_MIPS_R6; 392 393 if (prog_req.fre && !prog_req.frdefault && !prog_req.fr1) { 394 env->CP0_Config5 |= (1 << CP0C5_FRE); 395 if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) { 396 env->hflags |= MIPS_HFLAG_FRE; 397 } 398 } else if ((prog_req.fr1 && prog_req.frdefault) || 399 (prog_req.single && !prog_req.frdefault)) { 400 if ((env->active_fpu.fcr0 & (1 << FCR0_F64) 401 && cpu_has_mips_r2_r6) || prog_req.fr1) { 402 env->CP0_Status |= (1 << CP0St_FR); 403 env->hflags |= MIPS_HFLAG_F64; 404 } 405 } else if (!prog_req.fre && !prog_req.frdefault && 406 !prog_req.fr1 && !prog_req.single && !prog_req.soft) { 407 fprintf(stderr, "qemu: Can't find a matching FPU mode\n"); 408 exit(1); 409 } 410 411 if (env->insn_flags & ISA_NANOMIPS32) { 412 return; 413 } 414 if (((info->elf_flags & EF_MIPS_NAN2008) != 0) != 415 ((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) != 0)) { 416 if ((env->active_fpu.fcr31_rw_bitmask & 417 (1 << FCR31_NAN2008)) == 0) { 418 fprintf(stderr, "ELF binary's NaN mode not supported by CPU\n"); 419 exit(1); 420 } 421 if ((info->elf_flags & EF_MIPS_NAN2008) != 0) { 422 env->active_fpu.fcr31 |= (1 << FCR31_NAN2008); 423 } else { 424 env->active_fpu.fcr31 &= ~(1 << FCR31_NAN2008); 425 } 426 restore_snan_bit_mode(env); 427 } 428}