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