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 "elf.h" 24 #include "cpu_loop-common.h" 25 #include "semihosting/common-semi.h" 26 27 #define get_user_code_u32(x, gaddr, env) \ 28 ({ abi_long __r = get_user_u32((x), (gaddr)); \ 29 if (!__r && bswap_code(arm_sctlr_b(env))) { \ 30 (x) = bswap32(x); \ 31 } \ 32 __r; \ 33 }) 34 35 #define get_user_code_u16(x, gaddr, env) \ 36 ({ abi_long __r = get_user_u16((x), (gaddr)); \ 37 if (!__r && bswap_code(arm_sctlr_b(env))) { \ 38 (x) = bswap16(x); \ 39 } \ 40 __r; \ 41 }) 42 43 #define get_user_data_u32(x, gaddr, env) \ 44 ({ abi_long __r = get_user_u32((x), (gaddr)); \ 45 if (!__r && arm_cpu_bswap_data(env)) { \ 46 (x) = bswap32(x); \ 47 } \ 48 __r; \ 49 }) 50 51 #define get_user_data_u16(x, gaddr, env) \ 52 ({ abi_long __r = get_user_u16((x), (gaddr)); \ 53 if (!__r && arm_cpu_bswap_data(env)) { \ 54 (x) = bswap16(x); \ 55 } \ 56 __r; \ 57 }) 58 59 #define put_user_data_u32(x, gaddr, env) \ 60 ({ typeof(x) __x = (x); \ 61 if (arm_cpu_bswap_data(env)) { \ 62 __x = bswap32(__x); \ 63 } \ 64 put_user_u32(__x, (gaddr)); \ 65 }) 66 67 #define put_user_data_u16(x, gaddr, env) \ 68 ({ typeof(x) __x = (x); \ 69 if (arm_cpu_bswap_data(env)) { \ 70 __x = bswap16(__x); \ 71 } \ 72 put_user_u16(__x, (gaddr)); \ 73 }) 74 75 /* Commpage handling -- there is no commpage for AArch64 */ 76 77 /* 78 * See the Linux kernel's Documentation/arm/kernel_user_helpers.txt 79 * Input: 80 * r0 = pointer to oldval 81 * r1 = pointer to newval 82 * r2 = pointer to target value 83 * 84 * Output: 85 * r0 = 0 if *ptr was changed, non-0 if no exchange happened 86 * C set if *ptr was changed, clear if no exchange happened 87 * 88 * Note segv's in kernel helpers are a bit tricky, we can set the 89 * data address sensibly but the PC address is just the entry point. 90 */ 91 static void arm_kernel_cmpxchg64_helper(CPUARMState *env) 92 { 93 uint64_t oldval, newval, val; 94 uint32_t addr, cpsr; 95 target_siginfo_t info; 96 97 /* Based on the 32 bit code in do_kernel_trap */ 98 99 /* XXX: This only works between threads, not between processes. 100 It's probably possible to implement this with native host 101 operations. However things like ldrex/strex are much harder so 102 there's not much point trying. */ 103 start_exclusive(); 104 cpsr = cpsr_read(env); 105 addr = env->regs[2]; 106 107 if (get_user_u64(oldval, env->regs[0])) { 108 env->exception.vaddress = env->regs[0]; 109 goto segv; 110 }; 111 112 if (get_user_u64(newval, env->regs[1])) { 113 env->exception.vaddress = env->regs[1]; 114 goto segv; 115 }; 116 117 if (get_user_u64(val, addr)) { 118 env->exception.vaddress = addr; 119 goto segv; 120 } 121 122 if (val == oldval) { 123 val = newval; 124 125 if (put_user_u64(val, addr)) { 126 env->exception.vaddress = addr; 127 goto segv; 128 }; 129 130 env->regs[0] = 0; 131 cpsr |= CPSR_C; 132 } else { 133 env->regs[0] = -1; 134 cpsr &= ~CPSR_C; 135 } 136 cpsr_write(env, cpsr, CPSR_C, CPSRWriteByInstr); 137 end_exclusive(); 138 return; 139 140 segv: 141 end_exclusive(); 142 /* We get the PC of the entry address - which is as good as anything, 143 on a real kernel what you get depends on which mode it uses. */ 144 info.si_signo = TARGET_SIGSEGV; 145 info.si_errno = 0; 146 /* XXX: check env->error_code */ 147 info.si_code = TARGET_SEGV_MAPERR; 148 info._sifields._sigfault._addr = env->exception.vaddress; 149 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 150 } 151 152 /* Handle a jump to the kernel code page. */ 153 static int 154 do_kernel_trap(CPUARMState *env) 155 { 156 uint32_t addr; 157 uint32_t cpsr; 158 uint32_t val; 159 160 switch (env->regs[15]) { 161 case 0xffff0fa0: /* __kernel_memory_barrier */ 162 /* ??? No-op. Will need to do better for SMP. */ 163 break; 164 case 0xffff0fc0: /* __kernel_cmpxchg */ 165 /* XXX: This only works between threads, not between processes. 166 It's probably possible to implement this with native host 167 operations. However things like ldrex/strex are much harder so 168 there's not much point trying. */ 169 start_exclusive(); 170 cpsr = cpsr_read(env); 171 addr = env->regs[2]; 172 /* FIXME: This should SEGV if the access fails. */ 173 if (get_user_u32(val, addr)) 174 val = ~env->regs[0]; 175 if (val == env->regs[0]) { 176 val = env->regs[1]; 177 /* FIXME: Check for segfaults. */ 178 put_user_u32(val, addr); 179 env->regs[0] = 0; 180 cpsr |= CPSR_C; 181 } else { 182 env->regs[0] = -1; 183 cpsr &= ~CPSR_C; 184 } 185 cpsr_write(env, cpsr, CPSR_C, CPSRWriteByInstr); 186 end_exclusive(); 187 break; 188 case 0xffff0fe0: /* __kernel_get_tls */ 189 env->regs[0] = cpu_get_tls(env); 190 break; 191 case 0xffff0f60: /* __kernel_cmpxchg64 */ 192 arm_kernel_cmpxchg64_helper(env); 193 break; 194 195 default: 196 return 1; 197 } 198 /* Jump back to the caller. */ 199 addr = env->regs[14]; 200 if (addr & 1) { 201 env->thumb = 1; 202 addr &= ~1; 203 } 204 env->regs[15] = addr; 205 206 return 0; 207 } 208 209 static bool insn_is_linux_bkpt(uint32_t opcode, bool is_thumb) 210 { 211 /* 212 * Return true if this insn is one of the three magic UDF insns 213 * which the kernel treats as breakpoint insns. 214 */ 215 if (!is_thumb) { 216 return (opcode & 0x0fffffff) == 0x07f001f0; 217 } else { 218 /* 219 * Note that we get the two halves of the 32-bit T32 insn 220 * in the opposite order to the value the kernel uses in 221 * its undef_hook struct. 222 */ 223 return ((opcode & 0xffff) == 0xde01) || (opcode == 0xa000f7f0); 224 } 225 } 226 227 static bool emulate_arm_fpa11(CPUARMState *env, uint32_t opcode) 228 { 229 TaskState *ts = env_cpu(env)->opaque; 230 int rc = EmulateAll(opcode, &ts->fpa, env); 231 int raise, enabled; 232 233 if (rc == 0) { 234 /* Illegal instruction */ 235 return false; 236 } 237 if (rc > 0) { 238 /* Everything ok. */ 239 env->regs[15] += 4; 240 return true; 241 } 242 243 /* FP exception */ 244 rc = -rc; 245 raise = 0; 246 247 /* Translate softfloat flags to FPSR flags */ 248 if (rc & float_flag_invalid) { 249 raise |= BIT_IOC; 250 } 251 if (rc & float_flag_divbyzero) { 252 raise |= BIT_DZC; 253 } 254 if (rc & float_flag_overflow) { 255 raise |= BIT_OFC; 256 } 257 if (rc & float_flag_underflow) { 258 raise |= BIT_UFC; 259 } 260 if (rc & float_flag_inexact) { 261 raise |= BIT_IXC; 262 } 263 264 /* Accumulate unenabled exceptions */ 265 enabled = ts->fpa.fpsr >> 16; 266 ts->fpa.fpsr |= raise & ~enabled; 267 268 if (raise & enabled) { 269 target_siginfo_t info = { }; 270 271 /* 272 * The kernel's nwfpe emulator does not pass a real si_code. 273 * It merely uses send_sig(SIGFPE, current, 1). 274 */ 275 info.si_signo = TARGET_SIGFPE; 276 info.si_code = TARGET_SI_KERNEL; 277 278 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 279 } else { 280 env->regs[15] += 4; 281 } 282 return true; 283 } 284 285 void cpu_loop(CPUARMState *env) 286 { 287 CPUState *cs = env_cpu(env); 288 int trapnr; 289 unsigned int n, insn; 290 target_siginfo_t info; 291 uint32_t addr; 292 abi_ulong ret; 293 294 for(;;) { 295 cpu_exec_start(cs); 296 trapnr = cpu_exec(cs); 297 cpu_exec_end(cs); 298 process_queued_cpu_work(cs); 299 300 switch(trapnr) { 301 case EXCP_UDEF: 302 case EXCP_NOCP: 303 case EXCP_INVSTATE: 304 { 305 uint32_t opcode; 306 307 /* we handle the FPU emulation here, as Linux */ 308 /* we get the opcode */ 309 /* FIXME - what to do if get_user() fails? */ 310 get_user_code_u32(opcode, env->regs[15], env); 311 312 /* 313 * The Linux kernel treats some UDF patterns specially 314 * to use as breakpoints (instead of the architectural 315 * bkpt insn). These should trigger a SIGTRAP rather 316 * than SIGILL. 317 */ 318 if (insn_is_linux_bkpt(opcode, env->thumb)) { 319 goto excp_debug; 320 } 321 322 if (!env->thumb && emulate_arm_fpa11(env, opcode)) { 323 break; 324 } 325 326 info.si_signo = TARGET_SIGILL; 327 info.si_errno = 0; 328 info.si_code = TARGET_ILL_ILLOPN; 329 info._sifields._sigfault._addr = env->regs[15]; 330 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 331 } 332 break; 333 case EXCP_SWI: 334 { 335 env->eabi = 1; 336 /* system call */ 337 if (env->thumb) { 338 /* Thumb is always EABI style with syscall number in r7 */ 339 n = env->regs[7]; 340 } else { 341 /* 342 * Equivalent of kernel CONFIG_OABI_COMPAT: read the 343 * Arm SVC insn to extract the immediate, which is the 344 * syscall number in OABI. 345 */ 346 /* FIXME - what to do if get_user() fails? */ 347 get_user_code_u32(insn, env->regs[15] - 4, env); 348 n = insn & 0xffffff; 349 if (n == 0) { 350 /* zero immediate: EABI, syscall number in r7 */ 351 n = env->regs[7]; 352 } else { 353 /* 354 * This XOR matches the kernel code: an immediate 355 * in the valid range (0x900000 .. 0x9fffff) is 356 * converted into the correct EABI-style syscall 357 * number; invalid immediates end up as values 358 * > 0xfffff and are handled below as out-of-range. 359 */ 360 n ^= ARM_SYSCALL_BASE; 361 env->eabi = 0; 362 } 363 } 364 365 if (n > ARM_NR_BASE) { 366 switch (n) { 367 case ARM_NR_cacheflush: 368 /* nop */ 369 break; 370 case ARM_NR_set_tls: 371 cpu_set_tls(env, env->regs[0]); 372 env->regs[0] = 0; 373 break; 374 case ARM_NR_breakpoint: 375 env->regs[15] -= env->thumb ? 2 : 4; 376 goto excp_debug; 377 case ARM_NR_get_tls: 378 env->regs[0] = cpu_get_tls(env); 379 break; 380 default: 381 if (n < 0xf0800) { 382 /* 383 * Syscalls 0xf0000..0xf07ff (or 0x9f0000.. 384 * 0x9f07ff in OABI numbering) are defined 385 * to return -ENOSYS rather than raising 386 * SIGILL. Note that we have already 387 * removed the 0x900000 prefix. 388 */ 389 qemu_log_mask(LOG_UNIMP, 390 "qemu: Unsupported ARM syscall: 0x%x\n", 391 n); 392 env->regs[0] = -TARGET_ENOSYS; 393 } else { 394 /* 395 * Otherwise SIGILL. This includes any SWI with 396 * immediate not originally 0x9fxxxx, because 397 * of the earlier XOR. 398 */ 399 info.si_signo = TARGET_SIGILL; 400 info.si_errno = 0; 401 info.si_code = TARGET_ILL_ILLTRP; 402 info._sifields._sigfault._addr = env->regs[15]; 403 if (env->thumb) { 404 info._sifields._sigfault._addr -= 2; 405 } else { 406 info._sifields._sigfault._addr -= 4; 407 } 408 queue_signal(env, info.si_signo, 409 QEMU_SI_FAULT, &info); 410 } 411 break; 412 } 413 } else { 414 ret = do_syscall(env, 415 n, 416 env->regs[0], 417 env->regs[1], 418 env->regs[2], 419 env->regs[3], 420 env->regs[4], 421 env->regs[5], 422 0, 0); 423 if (ret == -TARGET_ERESTARTSYS) { 424 env->regs[15] -= env->thumb ? 2 : 4; 425 } else if (ret != -TARGET_QEMU_ESIGRETURN) { 426 env->regs[0] = ret; 427 } 428 } 429 } 430 break; 431 case EXCP_SEMIHOST: 432 env->regs[0] = do_common_semihosting(cs); 433 env->regs[15] += env->thumb ? 2 : 4; 434 break; 435 case EXCP_INTERRUPT: 436 /* just indicate that signals should be handled asap */ 437 break; 438 case EXCP_PREFETCH_ABORT: 439 case EXCP_DATA_ABORT: 440 addr = env->exception.vaddress; 441 { 442 info.si_signo = TARGET_SIGSEGV; 443 info.si_errno = 0; 444 /* XXX: check env->error_code */ 445 info.si_code = TARGET_SEGV_MAPERR; 446 info._sifields._sigfault._addr = addr; 447 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 448 } 449 break; 450 case EXCP_DEBUG: 451 case EXCP_BKPT: 452 excp_debug: 453 info.si_signo = TARGET_SIGTRAP; 454 info.si_errno = 0; 455 info.si_code = TARGET_TRAP_BRKPT; 456 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 457 break; 458 case EXCP_KERNEL_TRAP: 459 if (do_kernel_trap(env)) 460 goto error; 461 break; 462 case EXCP_YIELD: 463 /* nothing to do here for user-mode, just resume guest code */ 464 break; 465 case EXCP_ATOMIC: 466 cpu_exec_step_atomic(cs); 467 break; 468 default: 469 error: 470 EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr); 471 abort(); 472 } 473 process_pending_signals(env); 474 } 475 } 476 477 void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) 478 { 479 CPUState *cpu = env_cpu(env); 480 TaskState *ts = cpu->opaque; 481 struct image_info *info = ts->info; 482 int i; 483 484 cpsr_write(env, regs->uregs[16], CPSR_USER | CPSR_EXEC, 485 CPSRWriteByInstr); 486 for(i = 0; i < 16; i++) { 487 env->regs[i] = regs->uregs[i]; 488 } 489 #ifdef TARGET_WORDS_BIGENDIAN 490 /* Enable BE8. */ 491 if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4 492 && (info->elf_flags & EF_ARM_BE8)) { 493 env->uncached_cpsr |= CPSR_E; 494 env->cp15.sctlr_el[1] |= SCTLR_E0E; 495 } else { 496 env->cp15.sctlr_el[1] |= SCTLR_B; 497 } 498 arm_rebuild_hflags(env); 499 #endif 500 501 ts->stack_base = info->start_stack; 502 ts->heap_base = info->brk; 503 /* This will be filled in on the first SYS_HEAPINFO call. */ 504 ts->heap_limit = 0; 505 } 506