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