131e31b8aSbellard /* 293ac68bcSbellard * qemu user main 331e31b8aSbellard * 468d0f70eSbellard * Copyright (c) 2003-2008 Fabrice Bellard 531e31b8aSbellard * 631e31b8aSbellard * This program is free software; you can redistribute it and/or modify 731e31b8aSbellard * it under the terms of the GNU General Public License as published by 831e31b8aSbellard * the Free Software Foundation; either version 2 of the License, or 931e31b8aSbellard * (at your option) any later version. 1031e31b8aSbellard * 1131e31b8aSbellard * This program is distributed in the hope that it will be useful, 1231e31b8aSbellard * but WITHOUT ANY WARRANTY; without even the implied warranty of 1331e31b8aSbellard * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1431e31b8aSbellard * GNU General Public License for more details. 1531e31b8aSbellard * 1631e31b8aSbellard * You should have received a copy of the GNU General Public License 178167ee88SBlue Swirl * along with this program; if not, see <http://www.gnu.org/licenses/>. 1831e31b8aSbellard */ 19d39594e9SPeter Maydell #include "qemu/osdep.h" 2067a1de0dSFam Zheng #include "qemu-version.h" 21edf8e2afSMika Westerberg #include <sys/syscall.h> 22703e0e89SRichard Henderson #include <sys/resource.h> 2331e31b8aSbellard 24daa76aa4SMarkus Armbruster #include "qapi/error.h" 253ef693a0Sbellard #include "qemu.h" 26f348b6d1SVeronia Bahaa #include "qemu/path.h" 276533dd6eSLluís Vilanova #include "qemu/config-file.h" 28f348b6d1SVeronia Bahaa #include "qemu/cutils.h" 29f348b6d1SVeronia Bahaa #include "qemu/help_option.h" 302b41f10eSBlue Swirl #include "cpu.h" 3163c91552SPaolo Bonzini #include "exec/exec-all.h" 329002ec79SRichard Henderson #include "tcg.h" 331de7afc9SPaolo Bonzini #include "qemu/timer.h" 341de7afc9SPaolo Bonzini #include "qemu/envlist.h" 35d8fd2954SPaul Brook #include "elf.h" 36508127e2SPaolo Bonzini #include "exec/log.h" 376533dd6eSLluís Vilanova #include "trace/control.h" 386533dd6eSLluís Vilanova #include "glib-compat.h" 3904a6dfebSaurel32 40d088d664Saurel32 char *exec_path; 41d088d664Saurel32 421b530a6dSaurel32 int singlestep; 438cb76755SStefan Weil static const char *filename; 448cb76755SStefan Weil static const char *argv0; 458cb76755SStefan Weil static int gdbstub_port; 468cb76755SStefan Weil static envlist_t *envlist; 4751fb256aSAndreas Färber static const char *cpu_model; 48379f6698SPaul Brook unsigned long mmap_min_addr; 49379f6698SPaul Brook unsigned long guest_base; 50379f6698SPaul Brook int have_guest_base; 51120a9848SPaolo Bonzini 52120a9848SPaolo Bonzini #define EXCP_DUMP(env, fmt, ...) \ 53120a9848SPaolo Bonzini do { \ 54120a9848SPaolo Bonzini CPUState *cs = ENV_GET_CPU(env); \ 55120a9848SPaolo Bonzini fprintf(stderr, fmt , ## __VA_ARGS__); \ 56120a9848SPaolo Bonzini cpu_dump_state(cs, stderr, fprintf, 0); \ 57120a9848SPaolo Bonzini if (qemu_log_separate()) { \ 58120a9848SPaolo Bonzini qemu_log(fmt, ## __VA_ARGS__); \ 59120a9848SPaolo Bonzini log_cpu_state(cs, 0); \ 60120a9848SPaolo Bonzini } \ 61120a9848SPaolo Bonzini } while (0) 62120a9848SPaolo Bonzini 63288e65b9SAlexander Graf /* 64288e65b9SAlexander Graf * When running 32-on-64 we should make sure we can fit all of the possible 65288e65b9SAlexander Graf * guest address space into a contiguous chunk of virtual host memory. 66288e65b9SAlexander Graf * 67288e65b9SAlexander Graf * This way we will never overlap with our own libraries or binaries or stack 68288e65b9SAlexander Graf * or anything else that QEMU maps. 69*18e80c55SRichard Henderson * 70*18e80c55SRichard Henderson * Many cpus reserve the high bit (or more than one for some 64-bit cpus) 71*18e80c55SRichard Henderson * of the address for the kernel. Some cpus rely on this and user space 72*18e80c55SRichard Henderson * uses the high bit(s) for pointer tagging and the like. For them, we 73*18e80c55SRichard Henderson * must preserve the expected address space. 74288e65b9SAlexander Graf */ 75*18e80c55SRichard Henderson #ifndef MAX_RESERVED_VA 76*18e80c55SRichard Henderson # if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS 77*18e80c55SRichard Henderson # if TARGET_VIRT_ADDR_SPACE_BITS == 32 && \ 78*18e80c55SRichard Henderson (TARGET_LONG_BITS == 32 || defined(TARGET_ABI32)) 79*18e80c55SRichard Henderson /* There are a number of places where we assign reserved_va to a variable 80*18e80c55SRichard Henderson of type abi_ulong and expect it to fit. Avoid the last page. */ 81*18e80c55SRichard Henderson # define MAX_RESERVED_VA (0xfffffffful & TARGET_PAGE_MASK) 82314992b1SAlexander Graf # else 83*18e80c55SRichard Henderson # define MAX_RESERVED_VA (1ul << TARGET_VIRT_ADDR_SPACE_BITS) 84314992b1SAlexander Graf # endif 85288e65b9SAlexander Graf # else 86*18e80c55SRichard Henderson # define MAX_RESERVED_VA 0 87*18e80c55SRichard Henderson # endif 88*18e80c55SRichard Henderson #endif 89*18e80c55SRichard Henderson 90*18e80c55SRichard Henderson /* That said, reserving *too* much vm space via mmap can run into problems 91*18e80c55SRichard Henderson with rlimits, oom due to page table creation, etc. We will still try it, 92*18e80c55SRichard Henderson if directed by the command-line option, but not by default. */ 93*18e80c55SRichard Henderson #if HOST_LONG_BITS == 64 && TARGET_VIRT_ADDR_SPACE_BITS <= 32 94*18e80c55SRichard Henderson unsigned long reserved_va = MAX_RESERVED_VA; 95*18e80c55SRichard Henderson #else 9668a1c816SPaul Brook unsigned long reserved_va; 97379f6698SPaul Brook #endif 981b530a6dSaurel32 99d03f9c32SMeador Inge static void usage(int exitcode); 100fc9c5412SJohannes Schauer 1017ee2822cSPaolo Bonzini static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX; 102e586822aSRiku Voipio const char *qemu_uname_release; 103586314f2Sbellard 1049de5e440Sbellard /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so 1059de5e440Sbellard we allocate a bigger stack. Need a better solution, for example 1069de5e440Sbellard by remapping the process stack directly at the right place */ 107703e0e89SRichard Henderson unsigned long guest_stack_size = 8 * 1024 * 1024UL; 10831e31b8aSbellard 10931e31b8aSbellard void gemu_log(const char *fmt, ...) 11031e31b8aSbellard { 11131e31b8aSbellard va_list ap; 11231e31b8aSbellard 11331e31b8aSbellard va_start(ap, fmt); 11431e31b8aSbellard vfprintf(stderr, fmt, ap); 11531e31b8aSbellard va_end(ap); 11631e31b8aSbellard } 11731e31b8aSbellard 1188fcd3692Sblueswir1 #if defined(TARGET_I386) 11905390248SAndreas Färber int cpu_get_pic_interrupt(CPUX86State *env) 12092ccca6aSbellard { 12192ccca6aSbellard return -1; 12292ccca6aSbellard } 1238fcd3692Sblueswir1 #endif 12492ccca6aSbellard 125d5975363Spbrook /***********************************************************/ 126d5975363Spbrook /* Helper routines for implementing atomic operations. */ 127d5975363Spbrook 128d5975363Spbrook /* Make sure everything is in a consistent state for calling fork(). */ 129d5975363Spbrook void fork_start(void) 130d5975363Spbrook { 131267f685bSPaolo Bonzini cpu_list_lock(); 132677ef623SKONRAD Frederic qemu_mutex_lock(&tcg_ctx.tb_ctx.tb_lock); 133d032d1b4SRiku Voipio mmap_fork_start(); 134d5975363Spbrook } 135d5975363Spbrook 136d5975363Spbrook void fork_end(int child) 137d5975363Spbrook { 138d032d1b4SRiku Voipio mmap_fork_end(child); 139d5975363Spbrook if (child) { 140bdc44640SAndreas Färber CPUState *cpu, *next_cpu; 141d5975363Spbrook /* Child processes created by fork() only have a single thread. 142d5975363Spbrook Discard information about the parent threads. */ 143bdc44640SAndreas Färber CPU_FOREACH_SAFE(cpu, next_cpu) { 144bdc44640SAndreas Färber if (cpu != thread_cpu) { 145014628a7SPeter Maydell QTAILQ_REMOVE(&cpus, cpu, node); 146bdc44640SAndreas Färber } 147bdc44640SAndreas Färber } 148677ef623SKONRAD Frederic qemu_mutex_init(&tcg_ctx.tb_ctx.tb_lock); 149267f685bSPaolo Bonzini qemu_init_cpu_list(); 150f7ec7f7bSPeter Crosthwaite gdbserver_fork(thread_cpu); 151d5975363Spbrook } else { 152677ef623SKONRAD Frederic qemu_mutex_unlock(&tcg_ctx.tb_ctx.tb_lock); 153267f685bSPaolo Bonzini cpu_list_unlock(); 154d5975363Spbrook } 155d5975363Spbrook } 156d5975363Spbrook 157a541f297Sbellard #ifdef TARGET_I386 158a541f297Sbellard /***********************************************************/ 159a541f297Sbellard /* CPUX86 core interface */ 160a541f297Sbellard 16128ab0e2eSbellard uint64_t cpu_get_tsc(CPUX86State *env) 16228ab0e2eSbellard { 1634a7428c5SChristopher Covington return cpu_get_host_ticks(); 16428ab0e2eSbellard } 16528ab0e2eSbellard 166f4beb510Sbellard static void write_dt(void *ptr, unsigned long addr, unsigned long limit, 167f4beb510Sbellard int flags) 1686dbad63eSbellard { 169f4beb510Sbellard unsigned int e1, e2; 17053a5960aSpbrook uint32_t *p; 1716dbad63eSbellard e1 = (addr << 16) | (limit & 0xffff); 1726dbad63eSbellard e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000); 173f4beb510Sbellard e2 |= flags; 17453a5960aSpbrook p = ptr; 175d538e8f5Smalc p[0] = tswap32(e1); 176d538e8f5Smalc p[1] = tswap32(e2); 177f4beb510Sbellard } 178f4beb510Sbellard 179e441570fSbalrog static uint64_t *idt_table; 180eb38c52cSblueswir1 #ifdef TARGET_X86_64 181d2fd1af7Sbellard static void set_gate64(void *ptr, unsigned int type, unsigned int dpl, 182d2fd1af7Sbellard uint64_t addr, unsigned int sel) 183d2fd1af7Sbellard { 1844dbc422bSbellard uint32_t *p, e1, e2; 185d2fd1af7Sbellard e1 = (addr & 0xffff) | (sel << 16); 186d2fd1af7Sbellard e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8); 187d2fd1af7Sbellard p = ptr; 1884dbc422bSbellard p[0] = tswap32(e1); 1894dbc422bSbellard p[1] = tswap32(e2); 1904dbc422bSbellard p[2] = tswap32(addr >> 32); 1914dbc422bSbellard p[3] = 0; 192d2fd1af7Sbellard } 193d2fd1af7Sbellard /* only dpl matters as we do only user space emulation */ 194d2fd1af7Sbellard static void set_idt(int n, unsigned int dpl) 195d2fd1af7Sbellard { 196d2fd1af7Sbellard set_gate64(idt_table + n * 2, 0, dpl, 0, 0); 197d2fd1af7Sbellard } 198d2fd1af7Sbellard #else 199f4beb510Sbellard static void set_gate(void *ptr, unsigned int type, unsigned int dpl, 200d2fd1af7Sbellard uint32_t addr, unsigned int sel) 201f4beb510Sbellard { 2024dbc422bSbellard uint32_t *p, e1, e2; 203f4beb510Sbellard e1 = (addr & 0xffff) | (sel << 16); 204f4beb510Sbellard e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8); 20553a5960aSpbrook p = ptr; 2064dbc422bSbellard p[0] = tswap32(e1); 2074dbc422bSbellard p[1] = tswap32(e2); 2086dbad63eSbellard } 2096dbad63eSbellard 210f4beb510Sbellard /* only dpl matters as we do only user space emulation */ 211f4beb510Sbellard static void set_idt(int n, unsigned int dpl) 212f4beb510Sbellard { 213f4beb510Sbellard set_gate(idt_table + n, 0, dpl, 0, 0); 214f4beb510Sbellard } 215d2fd1af7Sbellard #endif 21631e31b8aSbellard 21789e957e7Sbellard void cpu_loop(CPUX86State *env) 218bc8a22ccSbellard { 219db6b81d4SAndreas Färber CPUState *cs = CPU(x86_env_get_cpu(env)); 220bc8a22ccSbellard int trapnr; 221992f48a0Sblueswir1 abi_ulong pc; 2220284b03bSTimothy E Baldwin abi_ulong ret; 223c227f099SAnthony Liguori target_siginfo_t info; 224bc8a22ccSbellard 225bc8a22ccSbellard for(;;) { 226b040bc9cSPeter Maydell cpu_exec_start(cs); 2278642c1b8SPeter Crosthwaite trapnr = cpu_exec(cs); 228b040bc9cSPeter Maydell cpu_exec_end(cs); 229d148d90eSSergey Fedorov process_queued_cpu_work(cs); 230d148d90eSSergey Fedorov 231bc8a22ccSbellard switch(trapnr) { 232f4beb510Sbellard case 0x80: 233d2fd1af7Sbellard /* linux syscall from int $0x80 */ 2340284b03bSTimothy E Baldwin ret = do_syscall(env, 2351b6b029eSbellard env->regs[R_EAX], 2361b6b029eSbellard env->regs[R_EBX], 2371b6b029eSbellard env->regs[R_ECX], 2381b6b029eSbellard env->regs[R_EDX], 2391b6b029eSbellard env->regs[R_ESI], 2401b6b029eSbellard env->regs[R_EDI], 2415945cfcbSPeter Maydell env->regs[R_EBP], 2425945cfcbSPeter Maydell 0, 0); 2430284b03bSTimothy E Baldwin if (ret == -TARGET_ERESTARTSYS) { 2440284b03bSTimothy E Baldwin env->eip -= 2; 2450284b03bSTimothy E Baldwin } else if (ret != -TARGET_QEMU_ESIGRETURN) { 2460284b03bSTimothy E Baldwin env->regs[R_EAX] = ret; 2470284b03bSTimothy E Baldwin } 248f4beb510Sbellard break; 249d2fd1af7Sbellard #ifndef TARGET_ABI32 250d2fd1af7Sbellard case EXCP_SYSCALL: 2515ba18547SStefan Weil /* linux syscall from syscall instruction */ 2520284b03bSTimothy E Baldwin ret = do_syscall(env, 253d2fd1af7Sbellard env->regs[R_EAX], 254d2fd1af7Sbellard env->regs[R_EDI], 255d2fd1af7Sbellard env->regs[R_ESI], 256d2fd1af7Sbellard env->regs[R_EDX], 257d2fd1af7Sbellard env->regs[10], 258d2fd1af7Sbellard env->regs[8], 2595945cfcbSPeter Maydell env->regs[9], 2605945cfcbSPeter Maydell 0, 0); 2610284b03bSTimothy E Baldwin if (ret == -TARGET_ERESTARTSYS) { 2620284b03bSTimothy E Baldwin env->eip -= 2; 2630284b03bSTimothy E Baldwin } else if (ret != -TARGET_QEMU_ESIGRETURN) { 2640284b03bSTimothy E Baldwin env->regs[R_EAX] = ret; 2650284b03bSTimothy E Baldwin } 266d2fd1af7Sbellard break; 267d2fd1af7Sbellard #endif 268f4beb510Sbellard case EXCP0B_NOSEG: 269f4beb510Sbellard case EXCP0C_STACK: 270a86b3c64SChen Gang S info.si_signo = TARGET_SIGBUS; 271f4beb510Sbellard info.si_errno = 0; 272f4beb510Sbellard info.si_code = TARGET_SI_KERNEL; 273f4beb510Sbellard info._sifields._sigfault._addr = 0; 2749d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 275f4beb510Sbellard break; 276f4beb510Sbellard case EXCP0D_GPF: 277d2fd1af7Sbellard /* XXX: potential problem if ABI32 */ 27884409ddbSj_mayer #ifndef TARGET_X86_64 279f4beb510Sbellard if (env->eflags & VM_MASK) { 280f4beb510Sbellard handle_vm86_fault(env); 28184409ddbSj_mayer } else 28284409ddbSj_mayer #endif 28384409ddbSj_mayer { 284a86b3c64SChen Gang S info.si_signo = TARGET_SIGSEGV; 2859de5e440Sbellard info.si_errno = 0; 286b689bc57Sbellard info.si_code = TARGET_SI_KERNEL; 2879de5e440Sbellard info._sifields._sigfault._addr = 0; 2889d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 2891b6b029eSbellard } 2901b6b029eSbellard break; 291b689bc57Sbellard case EXCP0E_PAGE: 292a86b3c64SChen Gang S info.si_signo = TARGET_SIGSEGV; 293b689bc57Sbellard info.si_errno = 0; 294b689bc57Sbellard if (!(env->error_code & 1)) 295b689bc57Sbellard info.si_code = TARGET_SEGV_MAPERR; 296b689bc57Sbellard else 297b689bc57Sbellard info.si_code = TARGET_SEGV_ACCERR; 298970a87a6Sbellard info._sifields._sigfault._addr = env->cr[2]; 2999d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 300b689bc57Sbellard break; 3019de5e440Sbellard case EXCP00_DIVZ: 30284409ddbSj_mayer #ifndef TARGET_X86_64 303bc8a22ccSbellard if (env->eflags & VM_MASK) { 304447db213Sbellard handle_vm86_trap(env, trapnr); 30584409ddbSj_mayer } else 30684409ddbSj_mayer #endif 30784409ddbSj_mayer { 3089de5e440Sbellard /* division by zero */ 309a86b3c64SChen Gang S info.si_signo = TARGET_SIGFPE; 3109de5e440Sbellard info.si_errno = 0; 3119de5e440Sbellard info.si_code = TARGET_FPE_INTDIV; 3129de5e440Sbellard info._sifields._sigfault._addr = env->eip; 3139d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 314bc8a22ccSbellard } 3159de5e440Sbellard break; 31601df040bSaliguori case EXCP01_DB: 317447db213Sbellard case EXCP03_INT3: 31884409ddbSj_mayer #ifndef TARGET_X86_64 319447db213Sbellard if (env->eflags & VM_MASK) { 320447db213Sbellard handle_vm86_trap(env, trapnr); 32184409ddbSj_mayer } else 32284409ddbSj_mayer #endif 32384409ddbSj_mayer { 324a86b3c64SChen Gang S info.si_signo = TARGET_SIGTRAP; 325447db213Sbellard info.si_errno = 0; 32601df040bSaliguori if (trapnr == EXCP01_DB) { 327447db213Sbellard info.si_code = TARGET_TRAP_BRKPT; 328447db213Sbellard info._sifields._sigfault._addr = env->eip; 329447db213Sbellard } else { 330447db213Sbellard info.si_code = TARGET_SI_KERNEL; 331447db213Sbellard info._sifields._sigfault._addr = 0; 332447db213Sbellard } 3339d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 334447db213Sbellard } 335447db213Sbellard break; 3369de5e440Sbellard case EXCP04_INTO: 3379de5e440Sbellard case EXCP05_BOUND: 33884409ddbSj_mayer #ifndef TARGET_X86_64 339bc8a22ccSbellard if (env->eflags & VM_MASK) { 340447db213Sbellard handle_vm86_trap(env, trapnr); 34184409ddbSj_mayer } else 34284409ddbSj_mayer #endif 34384409ddbSj_mayer { 344a86b3c64SChen Gang S info.si_signo = TARGET_SIGSEGV; 3459de5e440Sbellard info.si_errno = 0; 346b689bc57Sbellard info.si_code = TARGET_SI_KERNEL; 3479de5e440Sbellard info._sifields._sigfault._addr = 0; 3489d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 349bc8a22ccSbellard } 3509de5e440Sbellard break; 3519de5e440Sbellard case EXCP06_ILLOP: 352a86b3c64SChen Gang S info.si_signo = TARGET_SIGILL; 3539de5e440Sbellard info.si_errno = 0; 3549de5e440Sbellard info.si_code = TARGET_ILL_ILLOPN; 3559de5e440Sbellard info._sifields._sigfault._addr = env->eip; 3569d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 3579de5e440Sbellard break; 3589de5e440Sbellard case EXCP_INTERRUPT: 3599de5e440Sbellard /* just indicate that signals should be handled asap */ 3609de5e440Sbellard break; 3611fddef4bSbellard case EXCP_DEBUG: 3621fddef4bSbellard { 3631fddef4bSbellard int sig; 3641fddef4bSbellard 365db6b81d4SAndreas Färber sig = gdb_handlesig(cs, TARGET_SIGTRAP); 3661fddef4bSbellard if (sig) 3671fddef4bSbellard { 3681fddef4bSbellard info.si_signo = sig; 3691fddef4bSbellard info.si_errno = 0; 3701fddef4bSbellard info.si_code = TARGET_TRAP_BRKPT; 3719d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 3721fddef4bSbellard } 3731fddef4bSbellard } 3741fddef4bSbellard break; 375fdbc2b57SRichard Henderson case EXCP_ATOMIC: 376fdbc2b57SRichard Henderson cpu_exec_step_atomic(cs); 377fdbc2b57SRichard Henderson break; 3781b6b029eSbellard default: 379970a87a6Sbellard pc = env->segs[R_CS].base + env->eip; 380120a9848SPaolo Bonzini EXCP_DUMP(env, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n", 381bc8a22ccSbellard (long)pc, trapnr); 3821b6b029eSbellard abort(); 3831b6b029eSbellard } 38466fb9763Sbellard process_pending_signals(env); 3851b6b029eSbellard } 3861b6b029eSbellard } 387b346ff46Sbellard #endif 388b346ff46Sbellard 389b346ff46Sbellard #ifdef TARGET_ARM 390b346ff46Sbellard 39149017bd8SPaolo Bonzini #define get_user_code_u32(x, gaddr, env) \ 392d8fd2954SPaul Brook ({ abi_long __r = get_user_u32((x), (gaddr)); \ 393f9fd40ebSPaolo Bonzini if (!__r && bswap_code(arm_sctlr_b(env))) { \ 394d8fd2954SPaul Brook (x) = bswap32(x); \ 395d8fd2954SPaul Brook } \ 396d8fd2954SPaul Brook __r; \ 397d8fd2954SPaul Brook }) 398d8fd2954SPaul Brook 39949017bd8SPaolo Bonzini #define get_user_code_u16(x, gaddr, env) \ 400d8fd2954SPaul Brook ({ abi_long __r = get_user_u16((x), (gaddr)); \ 401f9fd40ebSPaolo Bonzini if (!__r && bswap_code(arm_sctlr_b(env))) { \ 402d8fd2954SPaul Brook (x) = bswap16(x); \ 403d8fd2954SPaul Brook } \ 404d8fd2954SPaul Brook __r; \ 405d8fd2954SPaul Brook }) 406d8fd2954SPaul Brook 407c3ae85fcSPaolo Bonzini #define get_user_data_u32(x, gaddr, env) \ 408c3ae85fcSPaolo Bonzini ({ abi_long __r = get_user_u32((x), (gaddr)); \ 409c3ae85fcSPaolo Bonzini if (!__r && arm_cpu_bswap_data(env)) { \ 410c3ae85fcSPaolo Bonzini (x) = bswap32(x); \ 411c3ae85fcSPaolo Bonzini } \ 412c3ae85fcSPaolo Bonzini __r; \ 413c3ae85fcSPaolo Bonzini }) 414c3ae85fcSPaolo Bonzini 415c3ae85fcSPaolo Bonzini #define get_user_data_u16(x, gaddr, env) \ 416c3ae85fcSPaolo Bonzini ({ abi_long __r = get_user_u16((x), (gaddr)); \ 417c3ae85fcSPaolo Bonzini if (!__r && arm_cpu_bswap_data(env)) { \ 418c3ae85fcSPaolo Bonzini (x) = bswap16(x); \ 419c3ae85fcSPaolo Bonzini } \ 420c3ae85fcSPaolo Bonzini __r; \ 421c3ae85fcSPaolo Bonzini }) 422c3ae85fcSPaolo Bonzini 423c3ae85fcSPaolo Bonzini #define put_user_data_u32(x, gaddr, env) \ 424c3ae85fcSPaolo Bonzini ({ typeof(x) __x = (x); \ 425c3ae85fcSPaolo Bonzini if (arm_cpu_bswap_data(env)) { \ 426c3ae85fcSPaolo Bonzini __x = bswap32(__x); \ 427c3ae85fcSPaolo Bonzini } \ 428c3ae85fcSPaolo Bonzini put_user_u32(__x, (gaddr)); \ 429c3ae85fcSPaolo Bonzini }) 430c3ae85fcSPaolo Bonzini 431c3ae85fcSPaolo Bonzini #define put_user_data_u16(x, gaddr, env) \ 432c3ae85fcSPaolo Bonzini ({ typeof(x) __x = (x); \ 433c3ae85fcSPaolo Bonzini if (arm_cpu_bswap_data(env)) { \ 434c3ae85fcSPaolo Bonzini __x = bswap16(__x); \ 435c3ae85fcSPaolo Bonzini } \ 436c3ae85fcSPaolo Bonzini put_user_u16(__x, (gaddr)); \ 437c3ae85fcSPaolo Bonzini }) 438c3ae85fcSPaolo Bonzini 4391861c454SPeter Maydell #ifdef TARGET_ABI32 4401861c454SPeter Maydell /* Commpage handling -- there is no commpage for AArch64 */ 4411861c454SPeter Maydell 44297cc7560SDr. David Alan Gilbert /* 44397cc7560SDr. David Alan Gilbert * See the Linux kernel's Documentation/arm/kernel_user_helpers.txt 44497cc7560SDr. David Alan Gilbert * Input: 44597cc7560SDr. David Alan Gilbert * r0 = pointer to oldval 44697cc7560SDr. David Alan Gilbert * r1 = pointer to newval 44797cc7560SDr. David Alan Gilbert * r2 = pointer to target value 44897cc7560SDr. David Alan Gilbert * 44997cc7560SDr. David Alan Gilbert * Output: 45097cc7560SDr. David Alan Gilbert * r0 = 0 if *ptr was changed, non-0 if no exchange happened 45197cc7560SDr. David Alan Gilbert * C set if *ptr was changed, clear if no exchange happened 45297cc7560SDr. David Alan Gilbert * 45397cc7560SDr. David Alan Gilbert * Note segv's in kernel helpers are a bit tricky, we can set the 45497cc7560SDr. David Alan Gilbert * data address sensibly but the PC address is just the entry point. 45597cc7560SDr. David Alan Gilbert */ 45697cc7560SDr. David Alan Gilbert static void arm_kernel_cmpxchg64_helper(CPUARMState *env) 45797cc7560SDr. David Alan Gilbert { 45897cc7560SDr. David Alan Gilbert uint64_t oldval, newval, val; 45997cc7560SDr. David Alan Gilbert uint32_t addr, cpsr; 46097cc7560SDr. David Alan Gilbert target_siginfo_t info; 46197cc7560SDr. David Alan Gilbert 46297cc7560SDr. David Alan Gilbert /* Based on the 32 bit code in do_kernel_trap */ 46397cc7560SDr. David Alan Gilbert 46497cc7560SDr. David Alan Gilbert /* XXX: This only works between threads, not between processes. 46597cc7560SDr. David Alan Gilbert It's probably possible to implement this with native host 46697cc7560SDr. David Alan Gilbert operations. However things like ldrex/strex are much harder so 46797cc7560SDr. David Alan Gilbert there's not much point trying. */ 46897cc7560SDr. David Alan Gilbert start_exclusive(); 46997cc7560SDr. David Alan Gilbert cpsr = cpsr_read(env); 47097cc7560SDr. David Alan Gilbert addr = env->regs[2]; 47197cc7560SDr. David Alan Gilbert 47297cc7560SDr. David Alan Gilbert if (get_user_u64(oldval, env->regs[0])) { 473abf1172fSPeter Maydell env->exception.vaddress = env->regs[0]; 47497cc7560SDr. David Alan Gilbert goto segv; 47597cc7560SDr. David Alan Gilbert }; 47697cc7560SDr. David Alan Gilbert 47797cc7560SDr. David Alan Gilbert if (get_user_u64(newval, env->regs[1])) { 478abf1172fSPeter Maydell env->exception.vaddress = env->regs[1]; 47997cc7560SDr. David Alan Gilbert goto segv; 48097cc7560SDr. David Alan Gilbert }; 48197cc7560SDr. David Alan Gilbert 48297cc7560SDr. David Alan Gilbert if (get_user_u64(val, addr)) { 483abf1172fSPeter Maydell env->exception.vaddress = addr; 48497cc7560SDr. David Alan Gilbert goto segv; 48597cc7560SDr. David Alan Gilbert } 48697cc7560SDr. David Alan Gilbert 48797cc7560SDr. David Alan Gilbert if (val == oldval) { 48897cc7560SDr. David Alan Gilbert val = newval; 48997cc7560SDr. David Alan Gilbert 49097cc7560SDr. David Alan Gilbert if (put_user_u64(val, addr)) { 491abf1172fSPeter Maydell env->exception.vaddress = addr; 49297cc7560SDr. David Alan Gilbert goto segv; 49397cc7560SDr. David Alan Gilbert }; 49497cc7560SDr. David Alan Gilbert 49597cc7560SDr. David Alan Gilbert env->regs[0] = 0; 49697cc7560SDr. David Alan Gilbert cpsr |= CPSR_C; 49797cc7560SDr. David Alan Gilbert } else { 49897cc7560SDr. David Alan Gilbert env->regs[0] = -1; 49997cc7560SDr. David Alan Gilbert cpsr &= ~CPSR_C; 50097cc7560SDr. David Alan Gilbert } 50150866ba5SPeter Maydell cpsr_write(env, cpsr, CPSR_C, CPSRWriteByInstr); 50297cc7560SDr. David Alan Gilbert end_exclusive(); 50397cc7560SDr. David Alan Gilbert return; 50497cc7560SDr. David Alan Gilbert 50597cc7560SDr. David Alan Gilbert segv: 50697cc7560SDr. David Alan Gilbert end_exclusive(); 50797cc7560SDr. David Alan Gilbert /* We get the PC of the entry address - which is as good as anything, 50897cc7560SDr. David Alan Gilbert on a real kernel what you get depends on which mode it uses. */ 509a86b3c64SChen Gang S info.si_signo = TARGET_SIGSEGV; 51097cc7560SDr. David Alan Gilbert info.si_errno = 0; 51197cc7560SDr. David Alan Gilbert /* XXX: check env->error_code */ 51297cc7560SDr. David Alan Gilbert info.si_code = TARGET_SEGV_MAPERR; 513abf1172fSPeter Maydell info._sifields._sigfault._addr = env->exception.vaddress; 5149d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 51597cc7560SDr. David Alan Gilbert } 51697cc7560SDr. David Alan Gilbert 517fbb4a2e3Spbrook /* Handle a jump to the kernel code page. */ 518fbb4a2e3Spbrook static int 519fbb4a2e3Spbrook do_kernel_trap(CPUARMState *env) 520fbb4a2e3Spbrook { 521fbb4a2e3Spbrook uint32_t addr; 522fbb4a2e3Spbrook uint32_t cpsr; 523fbb4a2e3Spbrook uint32_t val; 524fbb4a2e3Spbrook 525fbb4a2e3Spbrook switch (env->regs[15]) { 526fbb4a2e3Spbrook case 0xffff0fa0: /* __kernel_memory_barrier */ 527fbb4a2e3Spbrook /* ??? No-op. Will need to do better for SMP. */ 528fbb4a2e3Spbrook break; 529fbb4a2e3Spbrook case 0xffff0fc0: /* __kernel_cmpxchg */ 530d5975363Spbrook /* XXX: This only works between threads, not between processes. 531d5975363Spbrook It's probably possible to implement this with native host 532d5975363Spbrook operations. However things like ldrex/strex are much harder so 533d5975363Spbrook there's not much point trying. */ 534d5975363Spbrook start_exclusive(); 535fbb4a2e3Spbrook cpsr = cpsr_read(env); 536fbb4a2e3Spbrook addr = env->regs[2]; 537fbb4a2e3Spbrook /* FIXME: This should SEGV if the access fails. */ 538fbb4a2e3Spbrook if (get_user_u32(val, addr)) 539fbb4a2e3Spbrook val = ~env->regs[0]; 540fbb4a2e3Spbrook if (val == env->regs[0]) { 541fbb4a2e3Spbrook val = env->regs[1]; 542fbb4a2e3Spbrook /* FIXME: Check for segfaults. */ 543fbb4a2e3Spbrook put_user_u32(val, addr); 544fbb4a2e3Spbrook env->regs[0] = 0; 545fbb4a2e3Spbrook cpsr |= CPSR_C; 546fbb4a2e3Spbrook } else { 547fbb4a2e3Spbrook env->regs[0] = -1; 548fbb4a2e3Spbrook cpsr &= ~CPSR_C; 549fbb4a2e3Spbrook } 55050866ba5SPeter Maydell cpsr_write(env, cpsr, CPSR_C, CPSRWriteByInstr); 551d5975363Spbrook end_exclusive(); 552fbb4a2e3Spbrook break; 553fbb4a2e3Spbrook case 0xffff0fe0: /* __kernel_get_tls */ 554b8d43285SMikhail Ilyin env->regs[0] = cpu_get_tls(env); 555fbb4a2e3Spbrook break; 55697cc7560SDr. David Alan Gilbert case 0xffff0f60: /* __kernel_cmpxchg64 */ 55797cc7560SDr. David Alan Gilbert arm_kernel_cmpxchg64_helper(env); 55897cc7560SDr. David Alan Gilbert break; 55997cc7560SDr. David Alan Gilbert 560fbb4a2e3Spbrook default: 561fbb4a2e3Spbrook return 1; 562fbb4a2e3Spbrook } 563fbb4a2e3Spbrook /* Jump back to the caller. */ 564fbb4a2e3Spbrook addr = env->regs[14]; 565fbb4a2e3Spbrook if (addr & 1) { 566fbb4a2e3Spbrook env->thumb = 1; 567fbb4a2e3Spbrook addr &= ~1; 568fbb4a2e3Spbrook } 569fbb4a2e3Spbrook env->regs[15] = addr; 570fbb4a2e3Spbrook 571fbb4a2e3Spbrook return 0; 572fbb4a2e3Spbrook } 573fbb4a2e3Spbrook 574b346ff46Sbellard void cpu_loop(CPUARMState *env) 575b346ff46Sbellard { 5760315c31cSAndreas Färber CPUState *cs = CPU(arm_env_get_cpu(env)); 577b346ff46Sbellard int trapnr; 578b346ff46Sbellard unsigned int n, insn; 579c227f099SAnthony Liguori target_siginfo_t info; 580b5ff1b31Sbellard uint32_t addr; 581f0267ef7STimothy E Baldwin abi_ulong ret; 582b346ff46Sbellard 583b346ff46Sbellard for(;;) { 5840315c31cSAndreas Färber cpu_exec_start(cs); 5858642c1b8SPeter Crosthwaite trapnr = cpu_exec(cs); 5860315c31cSAndreas Färber cpu_exec_end(cs); 587d148d90eSSergey Fedorov process_queued_cpu_work(cs); 588d148d90eSSergey Fedorov 589b346ff46Sbellard switch(trapnr) { 590b346ff46Sbellard case EXCP_UDEF: 5917517748eSPeter Maydell case EXCP_NOCP: 592e13886e3SPeter Maydell case EXCP_INVSTATE: 593c6981055Sbellard { 5940429a971SAndreas Färber TaskState *ts = cs->opaque; 595c6981055Sbellard uint32_t opcode; 5966d9a42beSaurel32 int rc; 597c6981055Sbellard 598c6981055Sbellard /* we handle the FPU emulation here, as Linux */ 599c6981055Sbellard /* we get the opcode */ 6002f619698Sbellard /* FIXME - what to do if get_user() fails? */ 60149017bd8SPaolo Bonzini get_user_code_u32(opcode, env->regs[15], env); 602c6981055Sbellard 6036d9a42beSaurel32 rc = EmulateAll(opcode, &ts->fpa, env); 6046d9a42beSaurel32 if (rc == 0) { /* illegal instruction */ 605a86b3c64SChen Gang S info.si_signo = TARGET_SIGILL; 606b346ff46Sbellard info.si_errno = 0; 607b346ff46Sbellard info.si_code = TARGET_ILL_ILLOPN; 608b346ff46Sbellard info._sifields._sigfault._addr = env->regs[15]; 6099d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 6106d9a42beSaurel32 } else if (rc < 0) { /* FP exception */ 6116d9a42beSaurel32 int arm_fpe=0; 6126d9a42beSaurel32 6136d9a42beSaurel32 /* translate softfloat flags to FPSR flags */ 6146d9a42beSaurel32 if (-rc & float_flag_invalid) 6156d9a42beSaurel32 arm_fpe |= BIT_IOC; 6166d9a42beSaurel32 if (-rc & float_flag_divbyzero) 6176d9a42beSaurel32 arm_fpe |= BIT_DZC; 6186d9a42beSaurel32 if (-rc & float_flag_overflow) 6196d9a42beSaurel32 arm_fpe |= BIT_OFC; 6206d9a42beSaurel32 if (-rc & float_flag_underflow) 6216d9a42beSaurel32 arm_fpe |= BIT_UFC; 6226d9a42beSaurel32 if (-rc & float_flag_inexact) 6236d9a42beSaurel32 arm_fpe |= BIT_IXC; 6246d9a42beSaurel32 6256d9a42beSaurel32 FPSR fpsr = ts->fpa.fpsr; 6266d9a42beSaurel32 //printf("fpsr 0x%x, arm_fpe 0x%x\n",fpsr,arm_fpe); 6276d9a42beSaurel32 6286d9a42beSaurel32 if (fpsr & (arm_fpe << 16)) { /* exception enabled? */ 629a86b3c64SChen Gang S info.si_signo = TARGET_SIGFPE; 6306d9a42beSaurel32 info.si_errno = 0; 6316d9a42beSaurel32 6326d9a42beSaurel32 /* ordered by priority, least first */ 6336d9a42beSaurel32 if (arm_fpe & BIT_IXC) info.si_code = TARGET_FPE_FLTRES; 6346d9a42beSaurel32 if (arm_fpe & BIT_UFC) info.si_code = TARGET_FPE_FLTUND; 6356d9a42beSaurel32 if (arm_fpe & BIT_OFC) info.si_code = TARGET_FPE_FLTOVF; 6366d9a42beSaurel32 if (arm_fpe & BIT_DZC) info.si_code = TARGET_FPE_FLTDIV; 6376d9a42beSaurel32 if (arm_fpe & BIT_IOC) info.si_code = TARGET_FPE_FLTINV; 6386d9a42beSaurel32 6396d9a42beSaurel32 info._sifields._sigfault._addr = env->regs[15]; 6409d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 641c6981055Sbellard } else { 6426d9a42beSaurel32 env->regs[15] += 4; 6436d9a42beSaurel32 } 6446d9a42beSaurel32 6456d9a42beSaurel32 /* accumulate unenabled exceptions */ 6466d9a42beSaurel32 if ((!(fpsr & BIT_IXE)) && (arm_fpe & BIT_IXC)) 6476d9a42beSaurel32 fpsr |= BIT_IXC; 6486d9a42beSaurel32 if ((!(fpsr & BIT_UFE)) && (arm_fpe & BIT_UFC)) 6496d9a42beSaurel32 fpsr |= BIT_UFC; 6506d9a42beSaurel32 if ((!(fpsr & BIT_OFE)) && (arm_fpe & BIT_OFC)) 6516d9a42beSaurel32 fpsr |= BIT_OFC; 6526d9a42beSaurel32 if ((!(fpsr & BIT_DZE)) && (arm_fpe & BIT_DZC)) 6536d9a42beSaurel32 fpsr |= BIT_DZC; 6546d9a42beSaurel32 if ((!(fpsr & BIT_IOE)) && (arm_fpe & BIT_IOC)) 6556d9a42beSaurel32 fpsr |= BIT_IOC; 6566d9a42beSaurel32 ts->fpa.fpsr=fpsr; 6576d9a42beSaurel32 } else { /* everything OK */ 658c6981055Sbellard /* increment PC */ 659c6981055Sbellard env->regs[15] += 4; 660c6981055Sbellard } 661c6981055Sbellard } 662b346ff46Sbellard break; 663b346ff46Sbellard case EXCP_SWI: 66406c949e6Spbrook case EXCP_BKPT: 665b346ff46Sbellard { 666ce4defa0Spbrook env->eabi = 1; 667b346ff46Sbellard /* system call */ 66806c949e6Spbrook if (trapnr == EXCP_BKPT) { 66906c949e6Spbrook if (env->thumb) { 6702f619698Sbellard /* FIXME - what to do if get_user() fails? */ 67149017bd8SPaolo Bonzini get_user_code_u16(insn, env->regs[15], env); 67206c949e6Spbrook n = insn & 0xff; 67306c949e6Spbrook env->regs[15] += 2; 67406c949e6Spbrook } else { 6752f619698Sbellard /* FIXME - what to do if get_user() fails? */ 67649017bd8SPaolo Bonzini get_user_code_u32(insn, env->regs[15], env); 67706c949e6Spbrook n = (insn & 0xf) | ((insn >> 4) & 0xff0); 67806c949e6Spbrook env->regs[15] += 4; 67906c949e6Spbrook } 68006c949e6Spbrook } else { 681192c7bd9Sbellard if (env->thumb) { 6822f619698Sbellard /* FIXME - what to do if get_user() fails? */ 68349017bd8SPaolo Bonzini get_user_code_u16(insn, env->regs[15] - 2, env); 684192c7bd9Sbellard n = insn & 0xff; 685192c7bd9Sbellard } else { 6862f619698Sbellard /* FIXME - what to do if get_user() fails? */ 68749017bd8SPaolo Bonzini get_user_code_u32(insn, env->regs[15] - 4, env); 688b346ff46Sbellard n = insn & 0xffffff; 689192c7bd9Sbellard } 69006c949e6Spbrook } 691192c7bd9Sbellard 6926f1f31c0Sbellard if (n == ARM_NR_cacheflush) { 693dcfd14b3SBlue Swirl /* nop */ 694a4f81979Sbellard } else if (n == ARM_NR_semihosting 695a4f81979Sbellard || n == ARM_NR_thumb_semihosting) { 696a4f81979Sbellard env->regs[0] = do_arm_semihosting (env); 6973a1363acSAlexander Graf } else if (n == 0 || n >= ARM_SYSCALL_BASE || env->thumb) { 698b346ff46Sbellard /* linux syscall */ 699ce4defa0Spbrook if (env->thumb || n == 0) { 700192c7bd9Sbellard n = env->regs[7]; 701192c7bd9Sbellard } else { 702b346ff46Sbellard n -= ARM_SYSCALL_BASE; 703ce4defa0Spbrook env->eabi = 0; 704192c7bd9Sbellard } 705fbb4a2e3Spbrook if ( n > ARM_NR_BASE) { 706fbb4a2e3Spbrook switch (n) { 707fbb4a2e3Spbrook case ARM_NR_cacheflush: 708dcfd14b3SBlue Swirl /* nop */ 709fbb4a2e3Spbrook break; 710fbb4a2e3Spbrook case ARM_NR_set_tls: 711fbb4a2e3Spbrook cpu_set_tls(env, env->regs[0]); 712fbb4a2e3Spbrook env->regs[0] = 0; 713fbb4a2e3Spbrook break; 714d5355087SHunter Laux case ARM_NR_breakpoint: 715d5355087SHunter Laux env->regs[15] -= env->thumb ? 2 : 4; 716d5355087SHunter Laux goto excp_debug; 717fbb4a2e3Spbrook default: 718fbb4a2e3Spbrook gemu_log("qemu: Unsupported ARM syscall: 0x%x\n", 719fbb4a2e3Spbrook n); 720fbb4a2e3Spbrook env->regs[0] = -TARGET_ENOSYS; 721fbb4a2e3Spbrook break; 722fbb4a2e3Spbrook } 723fbb4a2e3Spbrook } else { 724f0267ef7STimothy E Baldwin ret = do_syscall(env, 725b346ff46Sbellard n, 726b346ff46Sbellard env->regs[0], 727b346ff46Sbellard env->regs[1], 728b346ff46Sbellard env->regs[2], 729b346ff46Sbellard env->regs[3], 730b346ff46Sbellard env->regs[4], 7315945cfcbSPeter Maydell env->regs[5], 7325945cfcbSPeter Maydell 0, 0); 733f0267ef7STimothy E Baldwin if (ret == -TARGET_ERESTARTSYS) { 734f0267ef7STimothy E Baldwin env->regs[15] -= env->thumb ? 2 : 4; 735f0267ef7STimothy E Baldwin } else if (ret != -TARGET_QEMU_ESIGRETURN) { 736f0267ef7STimothy E Baldwin env->regs[0] = ret; 737f0267ef7STimothy E Baldwin } 738fbb4a2e3Spbrook } 739b346ff46Sbellard } else { 740b346ff46Sbellard goto error; 741b346ff46Sbellard } 742b346ff46Sbellard } 743b346ff46Sbellard break; 74419a6e31cSPeter Maydell case EXCP_SEMIHOST: 74519a6e31cSPeter Maydell env->regs[0] = do_arm_semihosting(env); 74619a6e31cSPeter Maydell break; 74743fff238Sbellard case EXCP_INTERRUPT: 74843fff238Sbellard /* just indicate that signals should be handled asap */ 74943fff238Sbellard break; 75068016c62Sbellard case EXCP_PREFETCH_ABORT: 75168016c62Sbellard case EXCP_DATA_ABORT: 752abf1172fSPeter Maydell addr = env->exception.vaddress; 75368016c62Sbellard { 754a86b3c64SChen Gang S info.si_signo = TARGET_SIGSEGV; 75568016c62Sbellard info.si_errno = 0; 75668016c62Sbellard /* XXX: check env->error_code */ 75768016c62Sbellard info.si_code = TARGET_SEGV_MAPERR; 758b5ff1b31Sbellard info._sifields._sigfault._addr = addr; 7599d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 76068016c62Sbellard } 76168016c62Sbellard break; 7621fddef4bSbellard case EXCP_DEBUG: 763d5355087SHunter Laux excp_debug: 7641fddef4bSbellard { 7651fddef4bSbellard int sig; 7661fddef4bSbellard 767db6b81d4SAndreas Färber sig = gdb_handlesig(cs, TARGET_SIGTRAP); 7681fddef4bSbellard if (sig) 7691fddef4bSbellard { 7701fddef4bSbellard info.si_signo = sig; 7711fddef4bSbellard info.si_errno = 0; 7721fddef4bSbellard info.si_code = TARGET_TRAP_BRKPT; 7739d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 7741fddef4bSbellard } 7751fddef4bSbellard } 7761fddef4bSbellard break; 777fbb4a2e3Spbrook case EXCP_KERNEL_TRAP: 778fbb4a2e3Spbrook if (do_kernel_trap(env)) 779fbb4a2e3Spbrook goto error; 780fbb4a2e3Spbrook break; 781f911e0a3SPeter Maydell case EXCP_YIELD: 782f911e0a3SPeter Maydell /* nothing to do here for user-mode, just resume guest code */ 783f911e0a3SPeter Maydell break; 784fdbc2b57SRichard Henderson case EXCP_ATOMIC: 785fdbc2b57SRichard Henderson cpu_exec_step_atomic(cs); 786fdbc2b57SRichard Henderson break; 787b346ff46Sbellard default: 788b346ff46Sbellard error: 789120a9848SPaolo Bonzini EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr); 790b346ff46Sbellard abort(); 791b346ff46Sbellard } 792b346ff46Sbellard process_pending_signals(env); 793b346ff46Sbellard } 794b346ff46Sbellard } 795b346ff46Sbellard 7961861c454SPeter Maydell #else 7971861c454SPeter Maydell 7981861c454SPeter Maydell /* AArch64 main loop */ 7991861c454SPeter Maydell void cpu_loop(CPUARMState *env) 8001861c454SPeter Maydell { 8011861c454SPeter Maydell CPUState *cs = CPU(arm_env_get_cpu(env)); 8021861c454SPeter Maydell int trapnr, sig; 803f0267ef7STimothy E Baldwin abi_long ret; 8041861c454SPeter Maydell target_siginfo_t info; 8051861c454SPeter Maydell 8061861c454SPeter Maydell for (;;) { 8071861c454SPeter Maydell cpu_exec_start(cs); 8088642c1b8SPeter Crosthwaite trapnr = cpu_exec(cs); 8091861c454SPeter Maydell cpu_exec_end(cs); 810d148d90eSSergey Fedorov process_queued_cpu_work(cs); 8111861c454SPeter Maydell 8121861c454SPeter Maydell switch (trapnr) { 8131861c454SPeter Maydell case EXCP_SWI: 814f0267ef7STimothy E Baldwin ret = do_syscall(env, 8151861c454SPeter Maydell env->xregs[8], 8161861c454SPeter Maydell env->xregs[0], 8171861c454SPeter Maydell env->xregs[1], 8181861c454SPeter Maydell env->xregs[2], 8191861c454SPeter Maydell env->xregs[3], 8201861c454SPeter Maydell env->xregs[4], 8211861c454SPeter Maydell env->xregs[5], 8221861c454SPeter Maydell 0, 0); 823f0267ef7STimothy E Baldwin if (ret == -TARGET_ERESTARTSYS) { 824f0267ef7STimothy E Baldwin env->pc -= 4; 825f0267ef7STimothy E Baldwin } else if (ret != -TARGET_QEMU_ESIGRETURN) { 826f0267ef7STimothy E Baldwin env->xregs[0] = ret; 827f0267ef7STimothy E Baldwin } 8281861c454SPeter Maydell break; 8291861c454SPeter Maydell case EXCP_INTERRUPT: 8301861c454SPeter Maydell /* just indicate that signals should be handled asap */ 8311861c454SPeter Maydell break; 8321861c454SPeter Maydell case EXCP_UDEF: 833a86b3c64SChen Gang S info.si_signo = TARGET_SIGILL; 8341861c454SPeter Maydell info.si_errno = 0; 8351861c454SPeter Maydell info.si_code = TARGET_ILL_ILLOPN; 8361861c454SPeter Maydell info._sifields._sigfault._addr = env->pc; 8379d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 8381861c454SPeter Maydell break; 8391861c454SPeter Maydell case EXCP_PREFETCH_ABORT: 8401861c454SPeter Maydell case EXCP_DATA_ABORT: 841a86b3c64SChen Gang S info.si_signo = TARGET_SIGSEGV; 8421861c454SPeter Maydell info.si_errno = 0; 8431861c454SPeter Maydell /* XXX: check env->error_code */ 8441861c454SPeter Maydell info.si_code = TARGET_SEGV_MAPERR; 845686581adSRiku Voipio info._sifields._sigfault._addr = env->exception.vaddress; 8469d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 8471861c454SPeter Maydell break; 8481861c454SPeter Maydell case EXCP_DEBUG: 8491861c454SPeter Maydell case EXCP_BKPT: 8501861c454SPeter Maydell sig = gdb_handlesig(cs, TARGET_SIGTRAP); 8511861c454SPeter Maydell if (sig) { 8521861c454SPeter Maydell info.si_signo = sig; 8531861c454SPeter Maydell info.si_errno = 0; 8541861c454SPeter Maydell info.si_code = TARGET_TRAP_BRKPT; 8559d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 8561861c454SPeter Maydell } 8571861c454SPeter Maydell break; 8588012c84fSPeter Maydell case EXCP_SEMIHOST: 8598012c84fSPeter Maydell env->xregs[0] = do_arm_semihosting(env); 8608012c84fSPeter Maydell break; 861f911e0a3SPeter Maydell case EXCP_YIELD: 862f911e0a3SPeter Maydell /* nothing to do here for user-mode, just resume guest code */ 863f911e0a3SPeter Maydell break; 864fdbc2b57SRichard Henderson case EXCP_ATOMIC: 865fdbc2b57SRichard Henderson cpu_exec_step_atomic(cs); 866fdbc2b57SRichard Henderson break; 8671861c454SPeter Maydell default: 868120a9848SPaolo Bonzini EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr); 8691861c454SPeter Maydell abort(); 8701861c454SPeter Maydell } 8711861c454SPeter Maydell process_pending_signals(env); 872fa2ef212SMichael Matz /* Exception return on AArch64 always clears the exclusive monitor, 873fa2ef212SMichael Matz * so any return to running guest code implies this. 874fa2ef212SMichael Matz */ 875fa2ef212SMichael Matz env->exclusive_addr = -1; 8761861c454SPeter Maydell } 8771861c454SPeter Maydell } 8781861c454SPeter Maydell #endif /* ndef TARGET_ABI32 */ 8791861c454SPeter Maydell 880b346ff46Sbellard #endif 8811b6b029eSbellard 882d2fbca94SGuan Xuetao #ifdef TARGET_UNICORE32 883d2fbca94SGuan Xuetao 88405390248SAndreas Färber void cpu_loop(CPUUniCore32State *env) 885d2fbca94SGuan Xuetao { 8860315c31cSAndreas Färber CPUState *cs = CPU(uc32_env_get_cpu(env)); 887d2fbca94SGuan Xuetao int trapnr; 888d2fbca94SGuan Xuetao unsigned int n, insn; 889d2fbca94SGuan Xuetao target_siginfo_t info; 890d2fbca94SGuan Xuetao 891d2fbca94SGuan Xuetao for (;;) { 8920315c31cSAndreas Färber cpu_exec_start(cs); 8938642c1b8SPeter Crosthwaite trapnr = cpu_exec(cs); 8940315c31cSAndreas Färber cpu_exec_end(cs); 895d148d90eSSergey Fedorov process_queued_cpu_work(cs); 896d148d90eSSergey Fedorov 897d2fbca94SGuan Xuetao switch (trapnr) { 898d2fbca94SGuan Xuetao case UC32_EXCP_PRIV: 899d2fbca94SGuan Xuetao { 900d2fbca94SGuan Xuetao /* system call */ 901d2fbca94SGuan Xuetao get_user_u32(insn, env->regs[31] - 4); 902d2fbca94SGuan Xuetao n = insn & 0xffffff; 903d2fbca94SGuan Xuetao 904d2fbca94SGuan Xuetao if (n >= UC32_SYSCALL_BASE) { 905d2fbca94SGuan Xuetao /* linux syscall */ 906d2fbca94SGuan Xuetao n -= UC32_SYSCALL_BASE; 907d2fbca94SGuan Xuetao if (n == UC32_SYSCALL_NR_set_tls) { 908d2fbca94SGuan Xuetao cpu_set_tls(env, env->regs[0]); 909d2fbca94SGuan Xuetao env->regs[0] = 0; 910d2fbca94SGuan Xuetao } else { 911256cb6afSTimothy E Baldwin abi_long ret = do_syscall(env, 912d2fbca94SGuan Xuetao n, 913d2fbca94SGuan Xuetao env->regs[0], 914d2fbca94SGuan Xuetao env->regs[1], 915d2fbca94SGuan Xuetao env->regs[2], 916d2fbca94SGuan Xuetao env->regs[3], 917d2fbca94SGuan Xuetao env->regs[4], 9185945cfcbSPeter Maydell env->regs[5], 9195945cfcbSPeter Maydell 0, 0); 920256cb6afSTimothy E Baldwin if (ret == -TARGET_ERESTARTSYS) { 921256cb6afSTimothy E Baldwin env->regs[31] -= 4; 922256cb6afSTimothy E Baldwin } else if (ret != -TARGET_QEMU_ESIGRETURN) { 923256cb6afSTimothy E Baldwin env->regs[0] = ret; 924256cb6afSTimothy E Baldwin } 925d2fbca94SGuan Xuetao } 926d2fbca94SGuan Xuetao } else { 927d2fbca94SGuan Xuetao goto error; 928d2fbca94SGuan Xuetao } 929d2fbca94SGuan Xuetao } 930d2fbca94SGuan Xuetao break; 931d48813ddSGuan Xuetao case UC32_EXCP_DTRAP: 932d48813ddSGuan Xuetao case UC32_EXCP_ITRAP: 933a86b3c64SChen Gang S info.si_signo = TARGET_SIGSEGV; 934d2fbca94SGuan Xuetao info.si_errno = 0; 935d2fbca94SGuan Xuetao /* XXX: check env->error_code */ 936d2fbca94SGuan Xuetao info.si_code = TARGET_SEGV_MAPERR; 937d2fbca94SGuan Xuetao info._sifields._sigfault._addr = env->cp0.c4_faultaddr; 9389d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 939d2fbca94SGuan Xuetao break; 940d2fbca94SGuan Xuetao case EXCP_INTERRUPT: 941d2fbca94SGuan Xuetao /* just indicate that signals should be handled asap */ 942d2fbca94SGuan Xuetao break; 943d2fbca94SGuan Xuetao case EXCP_DEBUG: 944d2fbca94SGuan Xuetao { 945d2fbca94SGuan Xuetao int sig; 946d2fbca94SGuan Xuetao 947db6b81d4SAndreas Färber sig = gdb_handlesig(cs, TARGET_SIGTRAP); 948d2fbca94SGuan Xuetao if (sig) { 949d2fbca94SGuan Xuetao info.si_signo = sig; 950d2fbca94SGuan Xuetao info.si_errno = 0; 951d2fbca94SGuan Xuetao info.si_code = TARGET_TRAP_BRKPT; 9529d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 953d2fbca94SGuan Xuetao } 954d2fbca94SGuan Xuetao } 955d2fbca94SGuan Xuetao break; 956fdbc2b57SRichard Henderson case EXCP_ATOMIC: 957fdbc2b57SRichard Henderson cpu_exec_step_atomic(cs); 958fdbc2b57SRichard Henderson break; 959d2fbca94SGuan Xuetao default: 960d2fbca94SGuan Xuetao goto error; 961d2fbca94SGuan Xuetao } 962d2fbca94SGuan Xuetao process_pending_signals(env); 963d2fbca94SGuan Xuetao } 964d2fbca94SGuan Xuetao 965d2fbca94SGuan Xuetao error: 966120a9848SPaolo Bonzini EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr); 967d2fbca94SGuan Xuetao abort(); 968d2fbca94SGuan Xuetao } 969d2fbca94SGuan Xuetao #endif 970d2fbca94SGuan Xuetao 97193ac68bcSbellard #ifdef TARGET_SPARC 972ed23fbd9Sblueswir1 #define SPARC64_STACK_BIAS 2047 97393ac68bcSbellard 974060366c5Sbellard //#define DEBUG_WIN 975060366c5Sbellard 9762623cbafSbellard /* WARNING: dealing with register windows _is_ complicated. More info 9772623cbafSbellard can be found at http://www.sics.se/~psm/sparcstack.html */ 978060366c5Sbellard static inline int get_reg_index(CPUSPARCState *env, int cwp, int index) 979060366c5Sbellard { 9801a14026eSblueswir1 index = (index + cwp * 16) % (16 * env->nwindows); 981060366c5Sbellard /* wrap handling : if cwp is on the last window, then we use the 982060366c5Sbellard registers 'after' the end */ 9831a14026eSblueswir1 if (index < 8 && env->cwp == env->nwindows - 1) 9841a14026eSblueswir1 index += 16 * env->nwindows; 985060366c5Sbellard return index; 986060366c5Sbellard } 987060366c5Sbellard 9882623cbafSbellard /* save the register window 'cwp1' */ 9892623cbafSbellard static inline void save_window_offset(CPUSPARCState *env, int cwp1) 990060366c5Sbellard { 9912623cbafSbellard unsigned int i; 992992f48a0Sblueswir1 abi_ulong sp_ptr; 993060366c5Sbellard 99453a5960aSpbrook sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)]; 995ed23fbd9Sblueswir1 #ifdef TARGET_SPARC64 996ed23fbd9Sblueswir1 if (sp_ptr & 3) 997ed23fbd9Sblueswir1 sp_ptr += SPARC64_STACK_BIAS; 998ed23fbd9Sblueswir1 #endif 999060366c5Sbellard #if defined(DEBUG_WIN) 10002daf0284Sblueswir1 printf("win_overflow: sp_ptr=0x" TARGET_ABI_FMT_lx " save_cwp=%d\n", 10012daf0284Sblueswir1 sp_ptr, cwp1); 1002060366c5Sbellard #endif 10032623cbafSbellard for(i = 0; i < 16; i++) { 10042f619698Sbellard /* FIXME - what to do if put_user() fails? */ 10052f619698Sbellard put_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr); 1006992f48a0Sblueswir1 sp_ptr += sizeof(abi_ulong); 10072623cbafSbellard } 1008060366c5Sbellard } 1009060366c5Sbellard 1010060366c5Sbellard static void save_window(CPUSPARCState *env) 1011060366c5Sbellard { 10125ef54116Sbellard #ifndef TARGET_SPARC64 10132623cbafSbellard unsigned int new_wim; 10141a14026eSblueswir1 new_wim = ((env->wim >> 1) | (env->wim << (env->nwindows - 1))) & 10151a14026eSblueswir1 ((1LL << env->nwindows) - 1); 10161a14026eSblueswir1 save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2)); 10172623cbafSbellard env->wim = new_wim; 10185ef54116Sbellard #else 10191a14026eSblueswir1 save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2)); 10205ef54116Sbellard env->cansave++; 10215ef54116Sbellard env->canrestore--; 10225ef54116Sbellard #endif 1023060366c5Sbellard } 1024060366c5Sbellard 1025060366c5Sbellard static void restore_window(CPUSPARCState *env) 1026060366c5Sbellard { 1027eda52953Sblueswir1 #ifndef TARGET_SPARC64 1028eda52953Sblueswir1 unsigned int new_wim; 1029eda52953Sblueswir1 #endif 1030eda52953Sblueswir1 unsigned int i, cwp1; 1031992f48a0Sblueswir1 abi_ulong sp_ptr; 1032060366c5Sbellard 1033eda52953Sblueswir1 #ifndef TARGET_SPARC64 10341a14026eSblueswir1 new_wim = ((env->wim << 1) | (env->wim >> (env->nwindows - 1))) & 10351a14026eSblueswir1 ((1LL << env->nwindows) - 1); 1036eda52953Sblueswir1 #endif 1037060366c5Sbellard 1038060366c5Sbellard /* restore the invalid window */ 10391a14026eSblueswir1 cwp1 = cpu_cwp_inc(env, env->cwp + 1); 104053a5960aSpbrook sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)]; 1041ed23fbd9Sblueswir1 #ifdef TARGET_SPARC64 1042ed23fbd9Sblueswir1 if (sp_ptr & 3) 1043ed23fbd9Sblueswir1 sp_ptr += SPARC64_STACK_BIAS; 1044ed23fbd9Sblueswir1 #endif 1045060366c5Sbellard #if defined(DEBUG_WIN) 10462daf0284Sblueswir1 printf("win_underflow: sp_ptr=0x" TARGET_ABI_FMT_lx " load_cwp=%d\n", 10472daf0284Sblueswir1 sp_ptr, cwp1); 1048060366c5Sbellard #endif 10492623cbafSbellard for(i = 0; i < 16; i++) { 10502f619698Sbellard /* FIXME - what to do if get_user() fails? */ 10512f619698Sbellard get_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr); 1052992f48a0Sblueswir1 sp_ptr += sizeof(abi_ulong); 10532623cbafSbellard } 10545ef54116Sbellard #ifdef TARGET_SPARC64 10555ef54116Sbellard env->canrestore++; 10561a14026eSblueswir1 if (env->cleanwin < env->nwindows - 1) 10575ef54116Sbellard env->cleanwin++; 10585ef54116Sbellard env->cansave--; 1059eda52953Sblueswir1 #else 1060eda52953Sblueswir1 env->wim = new_wim; 10615ef54116Sbellard #endif 1062060366c5Sbellard } 1063060366c5Sbellard 1064060366c5Sbellard static void flush_windows(CPUSPARCState *env) 1065060366c5Sbellard { 1066060366c5Sbellard int offset, cwp1; 10672623cbafSbellard 10682623cbafSbellard offset = 1; 1069060366c5Sbellard for(;;) { 1070060366c5Sbellard /* if restore would invoke restore_window(), then we can stop */ 10711a14026eSblueswir1 cwp1 = cpu_cwp_inc(env, env->cwp + offset); 1072eda52953Sblueswir1 #ifndef TARGET_SPARC64 1073060366c5Sbellard if (env->wim & (1 << cwp1)) 1074060366c5Sbellard break; 1075eda52953Sblueswir1 #else 1076eda52953Sblueswir1 if (env->canrestore == 0) 1077eda52953Sblueswir1 break; 1078eda52953Sblueswir1 env->cansave++; 1079eda52953Sblueswir1 env->canrestore--; 1080eda52953Sblueswir1 #endif 10812623cbafSbellard save_window_offset(env, cwp1); 1082060366c5Sbellard offset++; 1083060366c5Sbellard } 10841a14026eSblueswir1 cwp1 = cpu_cwp_inc(env, env->cwp + 1); 1085eda52953Sblueswir1 #ifndef TARGET_SPARC64 1086eda52953Sblueswir1 /* set wim so that restore will reload the registers */ 10872623cbafSbellard env->wim = 1 << cwp1; 1088eda52953Sblueswir1 #endif 10892623cbafSbellard #if defined(DEBUG_WIN) 10902623cbafSbellard printf("flush_windows: nb=%d\n", offset - 1); 109180a9d035Sbellard #endif 10922623cbafSbellard } 1093060366c5Sbellard 109493ac68bcSbellard void cpu_loop (CPUSPARCState *env) 109593ac68bcSbellard { 1096878096eeSAndreas Färber CPUState *cs = CPU(sparc_env_get_cpu(env)); 10972cc20260SRichard Henderson int trapnr; 10982cc20260SRichard Henderson abi_long ret; 1099c227f099SAnthony Liguori target_siginfo_t info; 110093ac68bcSbellard 110193ac68bcSbellard while (1) { 1102b040bc9cSPeter Maydell cpu_exec_start(cs); 11038642c1b8SPeter Crosthwaite trapnr = cpu_exec(cs); 1104b040bc9cSPeter Maydell cpu_exec_end(cs); 1105d148d90eSSergey Fedorov process_queued_cpu_work(cs); 110693ac68bcSbellard 110720132b96SRichard Henderson /* Compute PSR before exposing state. */ 110820132b96SRichard Henderson if (env->cc_op != CC_OP_FLAGS) { 110920132b96SRichard Henderson cpu_get_psr(env); 111020132b96SRichard Henderson } 111120132b96SRichard Henderson 111293ac68bcSbellard switch (trapnr) { 11135ef54116Sbellard #ifndef TARGET_SPARC64 1114060366c5Sbellard case 0x88: 1115060366c5Sbellard case 0x90: 11165ef54116Sbellard #else 1117cb33da57Sblueswir1 case 0x110: 11185ef54116Sbellard case 0x16d: 11195ef54116Sbellard #endif 1120060366c5Sbellard ret = do_syscall (env, env->gregs[1], 1121060366c5Sbellard env->regwptr[0], env->regwptr[1], 1122060366c5Sbellard env->regwptr[2], env->regwptr[3], 11235945cfcbSPeter Maydell env->regwptr[4], env->regwptr[5], 11245945cfcbSPeter Maydell 0, 0); 1125c0bea68fSTimothy E Baldwin if (ret == -TARGET_ERESTARTSYS || ret == -TARGET_QEMU_ESIGRETURN) { 1126c0bea68fSTimothy E Baldwin break; 1127c0bea68fSTimothy E Baldwin } 11282cc20260SRichard Henderson if ((abi_ulong)ret >= (abi_ulong)(-515)) { 1129992f48a0Sblueswir1 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) 113027908725Sbellard env->xcc |= PSR_CARRY; 113127908725Sbellard #else 113293ac68bcSbellard env->psr |= PSR_CARRY; 113327908725Sbellard #endif 1134060366c5Sbellard ret = -ret; 1135060366c5Sbellard } else { 1136992f48a0Sblueswir1 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) 113727908725Sbellard env->xcc &= ~PSR_CARRY; 113827908725Sbellard #else 1139060366c5Sbellard env->psr &= ~PSR_CARRY; 114027908725Sbellard #endif 1141060366c5Sbellard } 1142060366c5Sbellard env->regwptr[0] = ret; 1143060366c5Sbellard /* next instruction */ 1144060366c5Sbellard env->pc = env->npc; 1145060366c5Sbellard env->npc = env->npc + 4; 1146060366c5Sbellard break; 1147060366c5Sbellard case 0x83: /* flush windows */ 1148992f48a0Sblueswir1 #ifdef TARGET_ABI32 1149992f48a0Sblueswir1 case 0x103: 1150992f48a0Sblueswir1 #endif 11512623cbafSbellard flush_windows(env); 1152060366c5Sbellard /* next instruction */ 1153060366c5Sbellard env->pc = env->npc; 1154060366c5Sbellard env->npc = env->npc + 4; 1155060366c5Sbellard break; 11563475187dSbellard #ifndef TARGET_SPARC64 1157060366c5Sbellard case TT_WIN_OVF: /* window overflow */ 1158060366c5Sbellard save_window(env); 1159060366c5Sbellard break; 1160060366c5Sbellard case TT_WIN_UNF: /* window underflow */ 1161060366c5Sbellard restore_window(env); 116293ac68bcSbellard break; 116361ff6f58Sbellard case TT_TFAULT: 116461ff6f58Sbellard case TT_DFAULT: 116561ff6f58Sbellard { 116659f7182fSRichard Henderson info.si_signo = TARGET_SIGSEGV; 116761ff6f58Sbellard info.si_errno = 0; 116861ff6f58Sbellard /* XXX: check env->error_code */ 116961ff6f58Sbellard info.si_code = TARGET_SEGV_MAPERR; 117061ff6f58Sbellard info._sifields._sigfault._addr = env->mmuregs[4]; 11719d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 117261ff6f58Sbellard } 117361ff6f58Sbellard break; 11743475187dSbellard #else 11755ef54116Sbellard case TT_SPILL: /* window overflow */ 11765ef54116Sbellard save_window(env); 11775ef54116Sbellard break; 11785ef54116Sbellard case TT_FILL: /* window underflow */ 11795ef54116Sbellard restore_window(env); 11805ef54116Sbellard break; 11817f84a729Sblueswir1 case TT_TFAULT: 11827f84a729Sblueswir1 case TT_DFAULT: 11837f84a729Sblueswir1 { 118459f7182fSRichard Henderson info.si_signo = TARGET_SIGSEGV; 11857f84a729Sblueswir1 info.si_errno = 0; 11867f84a729Sblueswir1 /* XXX: check env->error_code */ 11877f84a729Sblueswir1 info.si_code = TARGET_SEGV_MAPERR; 11887f84a729Sblueswir1 if (trapnr == TT_DFAULT) 118996df2bc9SArtyom Tarasenko info._sifields._sigfault._addr = env->dmmu.mmuregs[4]; 11907f84a729Sblueswir1 else 11918194f35aSIgor Kovalenko info._sifields._sigfault._addr = cpu_tsptr(env)->tpc; 11929d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 11937f84a729Sblueswir1 } 11947f84a729Sblueswir1 break; 119527524dc3Sbellard #ifndef TARGET_ABI32 11965bfb56b2Sblueswir1 case 0x16e: 11975bfb56b2Sblueswir1 flush_windows(env); 11985bfb56b2Sblueswir1 sparc64_get_context(env); 11995bfb56b2Sblueswir1 break; 12005bfb56b2Sblueswir1 case 0x16f: 12015bfb56b2Sblueswir1 flush_windows(env); 12025bfb56b2Sblueswir1 sparc64_set_context(env); 12035bfb56b2Sblueswir1 break; 12043475187dSbellard #endif 120527524dc3Sbellard #endif 120648dc41ebSbellard case EXCP_INTERRUPT: 120748dc41ebSbellard /* just indicate that signals should be handled asap */ 1208e80cfcfcSbellard break; 120975f22e4eSRichard Henderson case TT_ILL_INSN: 121075f22e4eSRichard Henderson { 121175f22e4eSRichard Henderson info.si_signo = TARGET_SIGILL; 121275f22e4eSRichard Henderson info.si_errno = 0; 121375f22e4eSRichard Henderson info.si_code = TARGET_ILL_ILLOPC; 121475f22e4eSRichard Henderson info._sifields._sigfault._addr = env->pc; 12159d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 121675f22e4eSRichard Henderson } 121775f22e4eSRichard Henderson break; 12181fddef4bSbellard case EXCP_DEBUG: 12191fddef4bSbellard { 12201fddef4bSbellard int sig; 12211fddef4bSbellard 1222db6b81d4SAndreas Färber sig = gdb_handlesig(cs, TARGET_SIGTRAP); 12231fddef4bSbellard if (sig) 12241fddef4bSbellard { 12251fddef4bSbellard info.si_signo = sig; 12261fddef4bSbellard info.si_errno = 0; 12271fddef4bSbellard info.si_code = TARGET_TRAP_BRKPT; 12289d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 12291fddef4bSbellard } 12301fddef4bSbellard } 12311fddef4bSbellard break; 1232fdbc2b57SRichard Henderson case EXCP_ATOMIC: 1233fdbc2b57SRichard Henderson cpu_exec_step_atomic(cs); 1234fdbc2b57SRichard Henderson break; 123593ac68bcSbellard default: 1236060366c5Sbellard printf ("Unhandled trap: 0x%x\n", trapnr); 1237878096eeSAndreas Färber cpu_dump_state(cs, stderr, fprintf, 0); 12384d1275c2SRiku Voipio exit(EXIT_FAILURE); 123993ac68bcSbellard } 124093ac68bcSbellard process_pending_signals (env); 124193ac68bcSbellard } 124293ac68bcSbellard } 124393ac68bcSbellard 124493ac68bcSbellard #endif 124593ac68bcSbellard 124667867308Sbellard #ifdef TARGET_PPC 124705390248SAndreas Färber static inline uint64_t cpu_ppc_get_tb(CPUPPCState *env) 12489fddaa0cSbellard { 12494a7428c5SChristopher Covington return cpu_get_host_ticks(); 12509fddaa0cSbellard } 12519fddaa0cSbellard 125205390248SAndreas Färber uint64_t cpu_ppc_load_tbl(CPUPPCState *env) 12539fddaa0cSbellard { 1254e3ea6529SAlexander Graf return cpu_ppc_get_tb(env); 12559fddaa0cSbellard } 12569fddaa0cSbellard 125705390248SAndreas Färber uint32_t cpu_ppc_load_tbu(CPUPPCState *env) 12589fddaa0cSbellard { 12599fddaa0cSbellard return cpu_ppc_get_tb(env) >> 32; 12609fddaa0cSbellard } 12619fddaa0cSbellard 126205390248SAndreas Färber uint64_t cpu_ppc_load_atbl(CPUPPCState *env) 12639fddaa0cSbellard { 1264b711de95SAurelien Jarno return cpu_ppc_get_tb(env); 12659fddaa0cSbellard } 12669fddaa0cSbellard 126705390248SAndreas Färber uint32_t cpu_ppc_load_atbu(CPUPPCState *env) 12689fddaa0cSbellard { 1269a062e36cSj_mayer return cpu_ppc_get_tb(env) >> 32; 12709fddaa0cSbellard } 12719fddaa0cSbellard 127205390248SAndreas Färber uint32_t cpu_ppc601_load_rtcu(CPUPPCState *env) 127376a66253Sj_mayer __attribute__ (( alias ("cpu_ppc_load_tbu") )); 127476a66253Sj_mayer 127505390248SAndreas Färber uint32_t cpu_ppc601_load_rtcl(CPUPPCState *env) 12769fddaa0cSbellard { 127776a66253Sj_mayer return cpu_ppc_load_tbl(env) & 0x3FFFFF80; 12789fddaa0cSbellard } 12799fddaa0cSbellard 1280a750fc0bSj_mayer /* XXX: to be fixed */ 128173b01960SAlexander Graf int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp) 1282a750fc0bSj_mayer { 1283a750fc0bSj_mayer return -1; 1284a750fc0bSj_mayer } 1285a750fc0bSj_mayer 128673b01960SAlexander Graf int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val) 1287a750fc0bSj_mayer { 1288a750fc0bSj_mayer return -1; 1289a750fc0bSj_mayer } 1290a750fc0bSj_mayer 129156f066bbSNathan Froyd static int do_store_exclusive(CPUPPCState *env) 129256f066bbSNathan Froyd { 129356f066bbSNathan Froyd target_ulong addr; 129456f066bbSNathan Froyd target_ulong page_addr; 1295e22c357bSDoug Kwan target_ulong val, val2 __attribute__((unused)) = 0; 129656f066bbSNathan Froyd int flags; 129756f066bbSNathan Froyd int segv = 0; 129856f066bbSNathan Froyd 129956f066bbSNathan Froyd addr = env->reserve_ea; 130056f066bbSNathan Froyd page_addr = addr & TARGET_PAGE_MASK; 130156f066bbSNathan Froyd start_exclusive(); 130256f066bbSNathan Froyd mmap_lock(); 130356f066bbSNathan Froyd flags = page_get_flags(page_addr); 130456f066bbSNathan Froyd if ((flags & PAGE_READ) == 0) { 130556f066bbSNathan Froyd segv = 1; 130656f066bbSNathan Froyd } else { 130756f066bbSNathan Froyd int reg = env->reserve_info & 0x1f; 13084b1daa72STom Musta int size = env->reserve_info >> 5; 130956f066bbSNathan Froyd int stored = 0; 131056f066bbSNathan Froyd 131156f066bbSNathan Froyd if (addr == env->reserve_addr) { 131256f066bbSNathan Froyd switch (size) { 131356f066bbSNathan Froyd case 1: segv = get_user_u8(val, addr); break; 131456f066bbSNathan Froyd case 2: segv = get_user_u16(val, addr); break; 131556f066bbSNathan Froyd case 4: segv = get_user_u32(val, addr); break; 131656f066bbSNathan Froyd #if defined(TARGET_PPC64) 131756f066bbSNathan Froyd case 8: segv = get_user_u64(val, addr); break; 131827b95bfeSTom Musta case 16: { 131927b95bfeSTom Musta segv = get_user_u64(val, addr); 132027b95bfeSTom Musta if (!segv) { 132127b95bfeSTom Musta segv = get_user_u64(val2, addr + 8); 132227b95bfeSTom Musta } 132327b95bfeSTom Musta break; 132427b95bfeSTom Musta } 132556f066bbSNathan Froyd #endif 132656f066bbSNathan Froyd default: abort(); 132756f066bbSNathan Froyd } 132856f066bbSNathan Froyd if (!segv && val == env->reserve_val) { 132956f066bbSNathan Froyd val = env->gpr[reg]; 133056f066bbSNathan Froyd switch (size) { 133156f066bbSNathan Froyd case 1: segv = put_user_u8(val, addr); break; 133256f066bbSNathan Froyd case 2: segv = put_user_u16(val, addr); break; 133356f066bbSNathan Froyd case 4: segv = put_user_u32(val, addr); break; 133456f066bbSNathan Froyd #if defined(TARGET_PPC64) 133556f066bbSNathan Froyd case 8: segv = put_user_u64(val, addr); break; 133627b95bfeSTom Musta case 16: { 133727b95bfeSTom Musta if (val2 == env->reserve_val2) { 1338e22c357bSDoug Kwan if (msr_le) { 1339e22c357bSDoug Kwan val2 = val; 1340e22c357bSDoug Kwan val = env->gpr[reg+1]; 1341e22c357bSDoug Kwan } else { 1342e22c357bSDoug Kwan val2 = env->gpr[reg+1]; 1343e22c357bSDoug Kwan } 134427b95bfeSTom Musta segv = put_user_u64(val, addr); 134527b95bfeSTom Musta if (!segv) { 134627b95bfeSTom Musta segv = put_user_u64(val2, addr + 8); 134727b95bfeSTom Musta } 134827b95bfeSTom Musta } 134927b95bfeSTom Musta break; 135027b95bfeSTom Musta } 135156f066bbSNathan Froyd #endif 135256f066bbSNathan Froyd default: abort(); 135356f066bbSNathan Froyd } 135456f066bbSNathan Froyd if (!segv) { 135556f066bbSNathan Froyd stored = 1; 135656f066bbSNathan Froyd } 135756f066bbSNathan Froyd } 135856f066bbSNathan Froyd } 135956f066bbSNathan Froyd env->crf[0] = (stored << 1) | xer_so; 136056f066bbSNathan Froyd env->reserve_addr = (target_ulong)-1; 136156f066bbSNathan Froyd } 136256f066bbSNathan Froyd if (!segv) { 136356f066bbSNathan Froyd env->nip += 4; 136456f066bbSNathan Froyd } 136556f066bbSNathan Froyd mmap_unlock(); 136656f066bbSNathan Froyd end_exclusive(); 136756f066bbSNathan Froyd return segv; 136856f066bbSNathan Froyd } 136956f066bbSNathan Froyd 137067867308Sbellard void cpu_loop(CPUPPCState *env) 137167867308Sbellard { 13720315c31cSAndreas Färber CPUState *cs = CPU(ppc_env_get_cpu(env)); 1373c227f099SAnthony Liguori target_siginfo_t info; 137461190b14Sbellard int trapnr; 13759e0e2f96SRichard Henderson target_ulong ret; 137667867308Sbellard 137767867308Sbellard for(;;) { 13780315c31cSAndreas Färber cpu_exec_start(cs); 13798642c1b8SPeter Crosthwaite trapnr = cpu_exec(cs); 13800315c31cSAndreas Färber cpu_exec_end(cs); 1381d148d90eSSergey Fedorov process_queued_cpu_work(cs); 1382d148d90eSSergey Fedorov 138367867308Sbellard switch(trapnr) { 1384e1833e1fSj_mayer case POWERPC_EXCP_NONE: 1385e1833e1fSj_mayer /* Just go on */ 138667867308Sbellard break; 1387e1833e1fSj_mayer case POWERPC_EXCP_CRITICAL: /* Critical input */ 1388a47dddd7SAndreas Färber cpu_abort(cs, "Critical interrupt while in user mode. " 1389e1833e1fSj_mayer "Aborting\n"); 1390e1833e1fSj_mayer break; 1391e1833e1fSj_mayer case POWERPC_EXCP_MCHECK: /* Machine check exception */ 1392a47dddd7SAndreas Färber cpu_abort(cs, "Machine check exception while in user mode. " 1393e1833e1fSj_mayer "Aborting\n"); 1394e1833e1fSj_mayer break; 1395e1833e1fSj_mayer case POWERPC_EXCP_DSI: /* Data storage exception */ 1396e1833e1fSj_mayer /* XXX: check this. Seems bugged */ 1397e1833e1fSj_mayer switch (env->error_code & 0xFF000000) { 1398e1833e1fSj_mayer case 0x40000000: 1399ba4a8df8SBenjamin Herrenschmidt case 0x42000000: 1400e1833e1fSj_mayer info.si_signo = TARGET_SIGSEGV; 1401e1833e1fSj_mayer info.si_errno = 0; 1402e1833e1fSj_mayer info.si_code = TARGET_SEGV_MAPERR; 1403e1833e1fSj_mayer break; 1404e1833e1fSj_mayer case 0x04000000: 1405e1833e1fSj_mayer info.si_signo = TARGET_SIGILL; 1406e1833e1fSj_mayer info.si_errno = 0; 1407e1833e1fSj_mayer info.si_code = TARGET_ILL_ILLADR; 1408e1833e1fSj_mayer break; 1409e1833e1fSj_mayer case 0x08000000: 1410e1833e1fSj_mayer info.si_signo = TARGET_SIGSEGV; 1411e1833e1fSj_mayer info.si_errno = 0; 1412e1833e1fSj_mayer info.si_code = TARGET_SEGV_ACCERR; 1413e1833e1fSj_mayer break; 1414e1833e1fSj_mayer default: 1415e1833e1fSj_mayer /* Let's send a regular segfault... */ 1416e1833e1fSj_mayer EXCP_DUMP(env, "Invalid segfault errno (%02x)\n", 1417e1833e1fSj_mayer env->error_code); 1418e1833e1fSj_mayer info.si_signo = TARGET_SIGSEGV; 1419e1833e1fSj_mayer info.si_errno = 0; 1420e1833e1fSj_mayer info.si_code = TARGET_SEGV_MAPERR; 1421e1833e1fSj_mayer break; 1422e1833e1fSj_mayer } 1423e1833e1fSj_mayer info._sifields._sigfault._addr = env->nip; 14249d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 1425e1833e1fSj_mayer break; 1426e1833e1fSj_mayer case POWERPC_EXCP_ISI: /* Instruction storage exception */ 1427e1833e1fSj_mayer /* XXX: check this */ 1428e1833e1fSj_mayer switch (env->error_code & 0xFF000000) { 1429e1833e1fSj_mayer case 0x40000000: 1430e1833e1fSj_mayer info.si_signo = TARGET_SIGSEGV; 1431e1833e1fSj_mayer info.si_errno = 0; 1432e1833e1fSj_mayer info.si_code = TARGET_SEGV_MAPERR; 1433e1833e1fSj_mayer break; 1434e1833e1fSj_mayer case 0x10000000: 1435e1833e1fSj_mayer case 0x08000000: 1436e1833e1fSj_mayer info.si_signo = TARGET_SIGSEGV; 1437e1833e1fSj_mayer info.si_errno = 0; 1438e1833e1fSj_mayer info.si_code = TARGET_SEGV_ACCERR; 1439e1833e1fSj_mayer break; 1440e1833e1fSj_mayer default: 1441e1833e1fSj_mayer /* Let's send a regular segfault... */ 1442e1833e1fSj_mayer EXCP_DUMP(env, "Invalid segfault errno (%02x)\n", 1443e1833e1fSj_mayer env->error_code); 1444e1833e1fSj_mayer info.si_signo = TARGET_SIGSEGV; 1445e1833e1fSj_mayer info.si_errno = 0; 1446e1833e1fSj_mayer info.si_code = TARGET_SEGV_MAPERR; 1447e1833e1fSj_mayer break; 1448e1833e1fSj_mayer } 1449e1833e1fSj_mayer info._sifields._sigfault._addr = env->nip - 4; 14509d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 1451e1833e1fSj_mayer break; 1452e1833e1fSj_mayer case POWERPC_EXCP_EXTERNAL: /* External input */ 1453a47dddd7SAndreas Färber cpu_abort(cs, "External interrupt while in user mode. " 1454e1833e1fSj_mayer "Aborting\n"); 1455e1833e1fSj_mayer break; 1456e1833e1fSj_mayer case POWERPC_EXCP_ALIGN: /* Alignment exception */ 1457e1833e1fSj_mayer /* XXX: check this */ 1458e1833e1fSj_mayer info.si_signo = TARGET_SIGBUS; 1459e1833e1fSj_mayer info.si_errno = 0; 1460e1833e1fSj_mayer info.si_code = TARGET_BUS_ADRALN; 14616bb9a0a9SAnton Blanchard info._sifields._sigfault._addr = env->nip; 14629d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 1463e1833e1fSj_mayer break; 1464e1833e1fSj_mayer case POWERPC_EXCP_PROGRAM: /* Program exception */ 14659b2faddaSBenjamin Herrenschmidt case POWERPC_EXCP_HV_EMU: /* HV emulation */ 1466e1833e1fSj_mayer /* XXX: check this */ 1467e1833e1fSj_mayer switch (env->error_code & ~0xF) { 1468e1833e1fSj_mayer case POWERPC_EXCP_FP: 1469e1833e1fSj_mayer info.si_signo = TARGET_SIGFPE; 1470e1833e1fSj_mayer info.si_errno = 0; 1471e1833e1fSj_mayer switch (env->error_code & 0xF) { 1472e1833e1fSj_mayer case POWERPC_EXCP_FP_OX: 1473e1833e1fSj_mayer info.si_code = TARGET_FPE_FLTOVF; 1474e1833e1fSj_mayer break; 1475e1833e1fSj_mayer case POWERPC_EXCP_FP_UX: 1476e1833e1fSj_mayer info.si_code = TARGET_FPE_FLTUND; 1477e1833e1fSj_mayer break; 1478e1833e1fSj_mayer case POWERPC_EXCP_FP_ZX: 1479e1833e1fSj_mayer case POWERPC_EXCP_FP_VXZDZ: 1480e1833e1fSj_mayer info.si_code = TARGET_FPE_FLTDIV; 1481e1833e1fSj_mayer break; 1482e1833e1fSj_mayer case POWERPC_EXCP_FP_XX: 1483e1833e1fSj_mayer info.si_code = TARGET_FPE_FLTRES; 1484e1833e1fSj_mayer break; 1485e1833e1fSj_mayer case POWERPC_EXCP_FP_VXSOFT: 1486e1833e1fSj_mayer info.si_code = TARGET_FPE_FLTINV; 1487e1833e1fSj_mayer break; 14887c58044cSj_mayer case POWERPC_EXCP_FP_VXSNAN: 1489e1833e1fSj_mayer case POWERPC_EXCP_FP_VXISI: 1490e1833e1fSj_mayer case POWERPC_EXCP_FP_VXIDI: 1491e1833e1fSj_mayer case POWERPC_EXCP_FP_VXIMZ: 1492e1833e1fSj_mayer case POWERPC_EXCP_FP_VXVC: 1493e1833e1fSj_mayer case POWERPC_EXCP_FP_VXSQRT: 1494e1833e1fSj_mayer case POWERPC_EXCP_FP_VXCVI: 1495e1833e1fSj_mayer info.si_code = TARGET_FPE_FLTSUB; 1496e1833e1fSj_mayer break; 1497e1833e1fSj_mayer default: 1498e1833e1fSj_mayer EXCP_DUMP(env, "Unknown floating point exception (%02x)\n", 1499e1833e1fSj_mayer env->error_code); 1500e1833e1fSj_mayer break; 1501e1833e1fSj_mayer } 1502e1833e1fSj_mayer break; 1503e1833e1fSj_mayer case POWERPC_EXCP_INVAL: 1504e1833e1fSj_mayer info.si_signo = TARGET_SIGILL; 1505e1833e1fSj_mayer info.si_errno = 0; 1506e1833e1fSj_mayer switch (env->error_code & 0xF) { 1507e1833e1fSj_mayer case POWERPC_EXCP_INVAL_INVAL: 1508e1833e1fSj_mayer info.si_code = TARGET_ILL_ILLOPC; 1509e1833e1fSj_mayer break; 1510e1833e1fSj_mayer case POWERPC_EXCP_INVAL_LSWX: 1511e1833e1fSj_mayer info.si_code = TARGET_ILL_ILLOPN; 1512e1833e1fSj_mayer break; 1513e1833e1fSj_mayer case POWERPC_EXCP_INVAL_SPR: 1514e1833e1fSj_mayer info.si_code = TARGET_ILL_PRVREG; 1515e1833e1fSj_mayer break; 1516e1833e1fSj_mayer case POWERPC_EXCP_INVAL_FP: 1517e1833e1fSj_mayer info.si_code = TARGET_ILL_COPROC; 1518e1833e1fSj_mayer break; 1519e1833e1fSj_mayer default: 1520e1833e1fSj_mayer EXCP_DUMP(env, "Unknown invalid operation (%02x)\n", 1521e1833e1fSj_mayer env->error_code & 0xF); 1522e1833e1fSj_mayer info.si_code = TARGET_ILL_ILLADR; 1523e1833e1fSj_mayer break; 1524e1833e1fSj_mayer } 1525e1833e1fSj_mayer break; 1526e1833e1fSj_mayer case POWERPC_EXCP_PRIV: 1527e1833e1fSj_mayer info.si_signo = TARGET_SIGILL; 1528e1833e1fSj_mayer info.si_errno = 0; 1529e1833e1fSj_mayer switch (env->error_code & 0xF) { 1530e1833e1fSj_mayer case POWERPC_EXCP_PRIV_OPC: 1531e1833e1fSj_mayer info.si_code = TARGET_ILL_PRVOPC; 1532e1833e1fSj_mayer break; 1533e1833e1fSj_mayer case POWERPC_EXCP_PRIV_REG: 1534e1833e1fSj_mayer info.si_code = TARGET_ILL_PRVREG; 1535e1833e1fSj_mayer break; 1536e1833e1fSj_mayer default: 1537e1833e1fSj_mayer EXCP_DUMP(env, "Unknown privilege violation (%02x)\n", 1538e1833e1fSj_mayer env->error_code & 0xF); 1539e1833e1fSj_mayer info.si_code = TARGET_ILL_PRVOPC; 1540e1833e1fSj_mayer break; 1541e1833e1fSj_mayer } 1542e1833e1fSj_mayer break; 1543e1833e1fSj_mayer case POWERPC_EXCP_TRAP: 1544a47dddd7SAndreas Färber cpu_abort(cs, "Tried to call a TRAP\n"); 1545e1833e1fSj_mayer break; 1546e1833e1fSj_mayer default: 1547e1833e1fSj_mayer /* Should not happen ! */ 1548a47dddd7SAndreas Färber cpu_abort(cs, "Unknown program exception (%02x)\n", 1549e1833e1fSj_mayer env->error_code); 1550e1833e1fSj_mayer break; 1551e1833e1fSj_mayer } 1552bd6fefe7SBenjamin Herrenschmidt info._sifields._sigfault._addr = env->nip; 15539d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 1554e1833e1fSj_mayer break; 1555e1833e1fSj_mayer case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ 1556e1833e1fSj_mayer info.si_signo = TARGET_SIGILL; 1557e1833e1fSj_mayer info.si_errno = 0; 1558e1833e1fSj_mayer info.si_code = TARGET_ILL_COPROC; 1559bd6fefe7SBenjamin Herrenschmidt info._sifields._sigfault._addr = env->nip; 15609d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 1561e1833e1fSj_mayer break; 1562e1833e1fSj_mayer case POWERPC_EXCP_SYSCALL: /* System call exception */ 1563a47dddd7SAndreas Färber cpu_abort(cs, "Syscall exception while in user mode. " 1564e1833e1fSj_mayer "Aborting\n"); 1565e1833e1fSj_mayer break; 1566e1833e1fSj_mayer case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */ 1567e1833e1fSj_mayer info.si_signo = TARGET_SIGILL; 1568e1833e1fSj_mayer info.si_errno = 0; 1569e1833e1fSj_mayer info.si_code = TARGET_ILL_COPROC; 1570bd6fefe7SBenjamin Herrenschmidt info._sifields._sigfault._addr = env->nip; 15719d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 1572e1833e1fSj_mayer break; 1573e1833e1fSj_mayer case POWERPC_EXCP_DECR: /* Decrementer exception */ 1574a47dddd7SAndreas Färber cpu_abort(cs, "Decrementer interrupt while in user mode. " 1575e1833e1fSj_mayer "Aborting\n"); 1576e1833e1fSj_mayer break; 1577e1833e1fSj_mayer case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */ 1578a47dddd7SAndreas Färber cpu_abort(cs, "Fix interval timer interrupt while in user mode. " 1579e1833e1fSj_mayer "Aborting\n"); 1580e1833e1fSj_mayer break; 1581e1833e1fSj_mayer case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */ 1582a47dddd7SAndreas Färber cpu_abort(cs, "Watchdog timer interrupt while in user mode. " 1583e1833e1fSj_mayer "Aborting\n"); 1584e1833e1fSj_mayer break; 1585e1833e1fSj_mayer case POWERPC_EXCP_DTLB: /* Data TLB error */ 1586a47dddd7SAndreas Färber cpu_abort(cs, "Data TLB exception while in user mode. " 1587e1833e1fSj_mayer "Aborting\n"); 1588e1833e1fSj_mayer break; 1589e1833e1fSj_mayer case POWERPC_EXCP_ITLB: /* Instruction TLB error */ 1590a47dddd7SAndreas Färber cpu_abort(cs, "Instruction TLB exception while in user mode. " 1591e1833e1fSj_mayer "Aborting\n"); 1592e1833e1fSj_mayer break; 1593e1833e1fSj_mayer case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */ 1594e1833e1fSj_mayer info.si_signo = TARGET_SIGILL; 1595e1833e1fSj_mayer info.si_errno = 0; 1596e1833e1fSj_mayer info.si_code = TARGET_ILL_COPROC; 1597bd6fefe7SBenjamin Herrenschmidt info._sifields._sigfault._addr = env->nip; 15989d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 1599e1833e1fSj_mayer break; 1600e1833e1fSj_mayer case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */ 1601a47dddd7SAndreas Färber cpu_abort(cs, "Embedded floating-point data IRQ not handled\n"); 1602e1833e1fSj_mayer break; 1603e1833e1fSj_mayer case POWERPC_EXCP_EFPRI: /* Embedded floating-point round IRQ */ 1604a47dddd7SAndreas Färber cpu_abort(cs, "Embedded floating-point round IRQ not handled\n"); 1605e1833e1fSj_mayer break; 1606e1833e1fSj_mayer case POWERPC_EXCP_EPERFM: /* Embedded performance monitor IRQ */ 1607a47dddd7SAndreas Färber cpu_abort(cs, "Performance monitor exception not handled\n"); 1608e1833e1fSj_mayer break; 1609e1833e1fSj_mayer case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */ 1610a47dddd7SAndreas Färber cpu_abort(cs, "Doorbell interrupt while in user mode. " 1611e1833e1fSj_mayer "Aborting\n"); 1612e1833e1fSj_mayer break; 1613e1833e1fSj_mayer case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */ 1614a47dddd7SAndreas Färber cpu_abort(cs, "Doorbell critical interrupt while in user mode. " 1615e1833e1fSj_mayer "Aborting\n"); 1616e1833e1fSj_mayer break; 1617e1833e1fSj_mayer case POWERPC_EXCP_RESET: /* System reset exception */ 1618a47dddd7SAndreas Färber cpu_abort(cs, "Reset interrupt while in user mode. " 1619e1833e1fSj_mayer "Aborting\n"); 1620e1833e1fSj_mayer break; 1621e1833e1fSj_mayer case POWERPC_EXCP_DSEG: /* Data segment exception */ 1622a47dddd7SAndreas Färber cpu_abort(cs, "Data segment exception while in user mode. " 1623e1833e1fSj_mayer "Aborting\n"); 1624e1833e1fSj_mayer break; 1625e1833e1fSj_mayer case POWERPC_EXCP_ISEG: /* Instruction segment exception */ 1626a47dddd7SAndreas Färber cpu_abort(cs, "Instruction segment exception " 1627e1833e1fSj_mayer "while in user mode. Aborting\n"); 1628e1833e1fSj_mayer break; 1629e85e7c6eSj_mayer /* PowerPC 64 with hypervisor mode support */ 1630e1833e1fSj_mayer case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */ 1631a47dddd7SAndreas Färber cpu_abort(cs, "Hypervisor decrementer interrupt " 1632e1833e1fSj_mayer "while in user mode. Aborting\n"); 1633e1833e1fSj_mayer break; 1634e1833e1fSj_mayer case POWERPC_EXCP_TRACE: /* Trace exception */ 1635e1833e1fSj_mayer /* Nothing to do: 1636e1833e1fSj_mayer * we use this exception to emulate step-by-step execution mode. 1637e1833e1fSj_mayer */ 1638e1833e1fSj_mayer break; 1639e85e7c6eSj_mayer /* PowerPC 64 with hypervisor mode support */ 1640e1833e1fSj_mayer case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */ 1641a47dddd7SAndreas Färber cpu_abort(cs, "Hypervisor data storage exception " 1642e1833e1fSj_mayer "while in user mode. Aborting\n"); 1643e1833e1fSj_mayer break; 1644e1833e1fSj_mayer case POWERPC_EXCP_HISI: /* Hypervisor instruction storage excp */ 1645a47dddd7SAndreas Färber cpu_abort(cs, "Hypervisor instruction storage exception " 1646e1833e1fSj_mayer "while in user mode. Aborting\n"); 1647e1833e1fSj_mayer break; 1648e1833e1fSj_mayer case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */ 1649a47dddd7SAndreas Färber cpu_abort(cs, "Hypervisor data segment exception " 1650e1833e1fSj_mayer "while in user mode. Aborting\n"); 1651e1833e1fSj_mayer break; 1652e1833e1fSj_mayer case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment excp */ 1653a47dddd7SAndreas Färber cpu_abort(cs, "Hypervisor instruction segment exception " 1654e1833e1fSj_mayer "while in user mode. Aborting\n"); 1655e1833e1fSj_mayer break; 1656e1833e1fSj_mayer case POWERPC_EXCP_VPU: /* Vector unavailable exception */ 1657e1833e1fSj_mayer info.si_signo = TARGET_SIGILL; 1658e1833e1fSj_mayer info.si_errno = 0; 1659e1833e1fSj_mayer info.si_code = TARGET_ILL_COPROC; 1660bd6fefe7SBenjamin Herrenschmidt info._sifields._sigfault._addr = env->nip; 16619d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 1662e1833e1fSj_mayer break; 1663e1833e1fSj_mayer case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */ 1664a47dddd7SAndreas Färber cpu_abort(cs, "Programmable interval timer interrupt " 1665e1833e1fSj_mayer "while in user mode. Aborting\n"); 1666e1833e1fSj_mayer break; 1667e1833e1fSj_mayer case POWERPC_EXCP_IO: /* IO error exception */ 1668a47dddd7SAndreas Färber cpu_abort(cs, "IO error exception while in user mode. " 1669e1833e1fSj_mayer "Aborting\n"); 1670e1833e1fSj_mayer break; 1671e1833e1fSj_mayer case POWERPC_EXCP_RUNM: /* Run mode exception */ 1672a47dddd7SAndreas Färber cpu_abort(cs, "Run mode exception while in user mode. " 1673e1833e1fSj_mayer "Aborting\n"); 1674e1833e1fSj_mayer break; 1675e1833e1fSj_mayer case POWERPC_EXCP_EMUL: /* Emulation trap exception */ 1676a47dddd7SAndreas Färber cpu_abort(cs, "Emulation trap exception not handled\n"); 1677e1833e1fSj_mayer break; 1678e1833e1fSj_mayer case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */ 1679a47dddd7SAndreas Färber cpu_abort(cs, "Instruction fetch TLB exception " 1680e1833e1fSj_mayer "while in user-mode. Aborting"); 1681e1833e1fSj_mayer break; 1682e1833e1fSj_mayer case POWERPC_EXCP_DLTLB: /* Data load TLB miss */ 1683a47dddd7SAndreas Färber cpu_abort(cs, "Data load TLB exception while in user-mode. " 1684e1833e1fSj_mayer "Aborting"); 1685e1833e1fSj_mayer break; 1686e1833e1fSj_mayer case POWERPC_EXCP_DSTLB: /* Data store TLB miss */ 1687a47dddd7SAndreas Färber cpu_abort(cs, "Data store TLB exception while in user-mode. " 1688e1833e1fSj_mayer "Aborting"); 1689e1833e1fSj_mayer break; 1690e1833e1fSj_mayer case POWERPC_EXCP_FPA: /* Floating-point assist exception */ 1691a47dddd7SAndreas Färber cpu_abort(cs, "Floating-point assist exception not handled\n"); 1692e1833e1fSj_mayer break; 1693e1833e1fSj_mayer case POWERPC_EXCP_IABR: /* Instruction address breakpoint */ 1694a47dddd7SAndreas Färber cpu_abort(cs, "Instruction address breakpoint exception " 1695e1833e1fSj_mayer "not handled\n"); 1696e1833e1fSj_mayer break; 1697e1833e1fSj_mayer case POWERPC_EXCP_SMI: /* System management interrupt */ 1698a47dddd7SAndreas Färber cpu_abort(cs, "System management interrupt while in user mode. " 1699e1833e1fSj_mayer "Aborting\n"); 1700e1833e1fSj_mayer break; 1701e1833e1fSj_mayer case POWERPC_EXCP_THERM: /* Thermal interrupt */ 1702a47dddd7SAndreas Färber cpu_abort(cs, "Thermal interrupt interrupt while in user mode. " 1703e1833e1fSj_mayer "Aborting\n"); 1704e1833e1fSj_mayer break; 1705e1833e1fSj_mayer case POWERPC_EXCP_PERFM: /* Embedded performance monitor IRQ */ 1706a47dddd7SAndreas Färber cpu_abort(cs, "Performance monitor exception not handled\n"); 1707e1833e1fSj_mayer break; 1708e1833e1fSj_mayer case POWERPC_EXCP_VPUA: /* Vector assist exception */ 1709a47dddd7SAndreas Färber cpu_abort(cs, "Vector assist exception not handled\n"); 1710e1833e1fSj_mayer break; 1711e1833e1fSj_mayer case POWERPC_EXCP_SOFTP: /* Soft patch exception */ 1712a47dddd7SAndreas Färber cpu_abort(cs, "Soft patch exception not handled\n"); 1713e1833e1fSj_mayer break; 1714e1833e1fSj_mayer case POWERPC_EXCP_MAINT: /* Maintenance exception */ 1715a47dddd7SAndreas Färber cpu_abort(cs, "Maintenance exception while in user mode. " 1716e1833e1fSj_mayer "Aborting\n"); 1717e1833e1fSj_mayer break; 1718e1833e1fSj_mayer case POWERPC_EXCP_STOP: /* stop translation */ 1719e1833e1fSj_mayer /* We did invalidate the instruction cache. Go on */ 1720e1833e1fSj_mayer break; 1721e1833e1fSj_mayer case POWERPC_EXCP_BRANCH: /* branch instruction: */ 1722e1833e1fSj_mayer /* We just stopped because of a branch. Go on */ 1723e1833e1fSj_mayer break; 1724e1833e1fSj_mayer case POWERPC_EXCP_SYSCALL_USER: 1725e1833e1fSj_mayer /* system call in user-mode emulation */ 172667867308Sbellard /* WARNING: 172767867308Sbellard * PPC ABI uses overflow flag in cr0 to signal an error 172867867308Sbellard * in syscalls. 172967867308Sbellard */ 173067867308Sbellard env->crf[0] &= ~0x1; 17312635531fSSam Bobroff env->nip += 4; 173267867308Sbellard ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4], 173367867308Sbellard env->gpr[5], env->gpr[6], env->gpr[7], 17345945cfcbSPeter Maydell env->gpr[8], 0, 0); 17356db9d00eSTimothy E Baldwin if (ret == -TARGET_ERESTARTSYS) { 17362635531fSSam Bobroff env->nip -= 4; 17376db9d00eSTimothy E Baldwin break; 17386db9d00eSTimothy E Baldwin } 17399e0e2f96SRichard Henderson if (ret == (target_ulong)(-TARGET_QEMU_ESIGRETURN)) { 1740bcd4933aSNathan Froyd /* Returning from a successful sigreturn syscall. 1741bcd4933aSNathan Froyd Avoid corrupting register state. */ 1742bcd4933aSNathan Froyd break; 1743bcd4933aSNathan Froyd } 17449e0e2f96SRichard Henderson if (ret > (target_ulong)(-515)) { 174567867308Sbellard env->crf[0] |= 0x1; 174667867308Sbellard ret = -ret; 174767867308Sbellard } 174867867308Sbellard env->gpr[3] = ret; 174961190b14Sbellard break; 175056f066bbSNathan Froyd case POWERPC_EXCP_STCX: 175156f066bbSNathan Froyd if (do_store_exclusive(env)) { 175256f066bbSNathan Froyd info.si_signo = TARGET_SIGSEGV; 175356f066bbSNathan Froyd info.si_errno = 0; 175456f066bbSNathan Froyd info.si_code = TARGET_SEGV_MAPERR; 175556f066bbSNathan Froyd info._sifields._sigfault._addr = env->nip; 17569d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 175756f066bbSNathan Froyd } 175856f066bbSNathan Froyd break; 175971f75756Saurel32 case EXCP_DEBUG: 176071f75756Saurel32 { 176171f75756Saurel32 int sig; 176271f75756Saurel32 1763db6b81d4SAndreas Färber sig = gdb_handlesig(cs, TARGET_SIGTRAP); 176471f75756Saurel32 if (sig) { 176571f75756Saurel32 info.si_signo = sig; 176671f75756Saurel32 info.si_errno = 0; 176771f75756Saurel32 info.si_code = TARGET_TRAP_BRKPT; 17689d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 176971f75756Saurel32 } 177071f75756Saurel32 } 177171f75756Saurel32 break; 177256ba31ffSj_mayer case EXCP_INTERRUPT: 177356ba31ffSj_mayer /* just indicate that signals should be handled asap */ 177456ba31ffSj_mayer break; 1775fdbc2b57SRichard Henderson case EXCP_ATOMIC: 1776fdbc2b57SRichard Henderson cpu_exec_step_atomic(cs); 1777fdbc2b57SRichard Henderson break; 177861190b14Sbellard default: 17798223f345SLaurent Vivier cpu_abort(cs, "Unknown exception 0x%x. Aborting\n", trapnr); 178067867308Sbellard break; 178167867308Sbellard } 178267867308Sbellard process_pending_signals(env); 178367867308Sbellard } 178467867308Sbellard } 178567867308Sbellard #endif 178667867308Sbellard 1787048f6b4dSbellard #ifdef TARGET_MIPS 1788048f6b4dSbellard 1789ff4f7382SRichard Henderson # ifdef TARGET_ABI_MIPSO32 1790048f6b4dSbellard # define MIPS_SYS(name, args) args, 1791048f6b4dSbellard static const uint8_t mips_syscall_args[] = { 179229fb0f25SAn-Cheng Huang MIPS_SYS(sys_syscall , 8) /* 4000 */ 1793048f6b4dSbellard MIPS_SYS(sys_exit , 1) 1794048f6b4dSbellard MIPS_SYS(sys_fork , 0) 1795048f6b4dSbellard MIPS_SYS(sys_read , 3) 1796048f6b4dSbellard MIPS_SYS(sys_write , 3) 1797048f6b4dSbellard MIPS_SYS(sys_open , 3) /* 4005 */ 1798048f6b4dSbellard MIPS_SYS(sys_close , 1) 1799048f6b4dSbellard MIPS_SYS(sys_waitpid , 3) 1800048f6b4dSbellard MIPS_SYS(sys_creat , 2) 1801048f6b4dSbellard MIPS_SYS(sys_link , 2) 1802048f6b4dSbellard MIPS_SYS(sys_unlink , 1) /* 4010 */ 1803048f6b4dSbellard MIPS_SYS(sys_execve , 0) 1804048f6b4dSbellard MIPS_SYS(sys_chdir , 1) 1805048f6b4dSbellard MIPS_SYS(sys_time , 1) 1806048f6b4dSbellard MIPS_SYS(sys_mknod , 3) 1807048f6b4dSbellard MIPS_SYS(sys_chmod , 2) /* 4015 */ 1808048f6b4dSbellard MIPS_SYS(sys_lchown , 3) 1809048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 1810048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was sys_stat */ 1811048f6b4dSbellard MIPS_SYS(sys_lseek , 3) 1812048f6b4dSbellard MIPS_SYS(sys_getpid , 0) /* 4020 */ 1813048f6b4dSbellard MIPS_SYS(sys_mount , 5) 1814868e34d7SRichard Henderson MIPS_SYS(sys_umount , 1) 1815048f6b4dSbellard MIPS_SYS(sys_setuid , 1) 1816048f6b4dSbellard MIPS_SYS(sys_getuid , 0) 1817048f6b4dSbellard MIPS_SYS(sys_stime , 1) /* 4025 */ 1818048f6b4dSbellard MIPS_SYS(sys_ptrace , 4) 1819048f6b4dSbellard MIPS_SYS(sys_alarm , 1) 1820048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was sys_fstat */ 1821048f6b4dSbellard MIPS_SYS(sys_pause , 0) 1822048f6b4dSbellard MIPS_SYS(sys_utime , 2) /* 4030 */ 1823048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 1824048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 1825048f6b4dSbellard MIPS_SYS(sys_access , 2) 1826048f6b4dSbellard MIPS_SYS(sys_nice , 1) 1827048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* 4035 */ 1828048f6b4dSbellard MIPS_SYS(sys_sync , 0) 1829048f6b4dSbellard MIPS_SYS(sys_kill , 2) 1830048f6b4dSbellard MIPS_SYS(sys_rename , 2) 1831048f6b4dSbellard MIPS_SYS(sys_mkdir , 2) 1832048f6b4dSbellard MIPS_SYS(sys_rmdir , 1) /* 4040 */ 1833048f6b4dSbellard MIPS_SYS(sys_dup , 1) 1834048f6b4dSbellard MIPS_SYS(sys_pipe , 0) 1835048f6b4dSbellard MIPS_SYS(sys_times , 1) 1836048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 1837048f6b4dSbellard MIPS_SYS(sys_brk , 1) /* 4045 */ 1838048f6b4dSbellard MIPS_SYS(sys_setgid , 1) 1839048f6b4dSbellard MIPS_SYS(sys_getgid , 0) 1840048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was signal(2) */ 1841048f6b4dSbellard MIPS_SYS(sys_geteuid , 0) 1842048f6b4dSbellard MIPS_SYS(sys_getegid , 0) /* 4050 */ 1843048f6b4dSbellard MIPS_SYS(sys_acct , 0) 1844868e34d7SRichard Henderson MIPS_SYS(sys_umount2 , 2) 1845048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 1846048f6b4dSbellard MIPS_SYS(sys_ioctl , 3) 1847048f6b4dSbellard MIPS_SYS(sys_fcntl , 3) /* 4055 */ 1848048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 2) 1849048f6b4dSbellard MIPS_SYS(sys_setpgid , 2) 1850048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 1851048f6b4dSbellard MIPS_SYS(sys_olduname , 1) 1852048f6b4dSbellard MIPS_SYS(sys_umask , 1) /* 4060 */ 1853048f6b4dSbellard MIPS_SYS(sys_chroot , 1) 1854048f6b4dSbellard MIPS_SYS(sys_ustat , 2) 1855048f6b4dSbellard MIPS_SYS(sys_dup2 , 2) 1856048f6b4dSbellard MIPS_SYS(sys_getppid , 0) 1857048f6b4dSbellard MIPS_SYS(sys_getpgrp , 0) /* 4065 */ 1858048f6b4dSbellard MIPS_SYS(sys_setsid , 0) 1859048f6b4dSbellard MIPS_SYS(sys_sigaction , 3) 1860048f6b4dSbellard MIPS_SYS(sys_sgetmask , 0) 1861048f6b4dSbellard MIPS_SYS(sys_ssetmask , 1) 1862048f6b4dSbellard MIPS_SYS(sys_setreuid , 2) /* 4070 */ 1863048f6b4dSbellard MIPS_SYS(sys_setregid , 2) 1864048f6b4dSbellard MIPS_SYS(sys_sigsuspend , 0) 1865048f6b4dSbellard MIPS_SYS(sys_sigpending , 1) 1866048f6b4dSbellard MIPS_SYS(sys_sethostname , 2) 1867048f6b4dSbellard MIPS_SYS(sys_setrlimit , 2) /* 4075 */ 1868048f6b4dSbellard MIPS_SYS(sys_getrlimit , 2) 1869048f6b4dSbellard MIPS_SYS(sys_getrusage , 2) 1870048f6b4dSbellard MIPS_SYS(sys_gettimeofday, 2) 1871048f6b4dSbellard MIPS_SYS(sys_settimeofday, 2) 1872048f6b4dSbellard MIPS_SYS(sys_getgroups , 2) /* 4080 */ 1873048f6b4dSbellard MIPS_SYS(sys_setgroups , 2) 1874048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* old_select */ 1875048f6b4dSbellard MIPS_SYS(sys_symlink , 2) 1876048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was sys_lstat */ 1877048f6b4dSbellard MIPS_SYS(sys_readlink , 3) /* 4085 */ 1878048f6b4dSbellard MIPS_SYS(sys_uselib , 1) 1879048f6b4dSbellard MIPS_SYS(sys_swapon , 2) 1880048f6b4dSbellard MIPS_SYS(sys_reboot , 3) 1881048f6b4dSbellard MIPS_SYS(old_readdir , 3) 1882048f6b4dSbellard MIPS_SYS(old_mmap , 6) /* 4090 */ 1883048f6b4dSbellard MIPS_SYS(sys_munmap , 2) 1884048f6b4dSbellard MIPS_SYS(sys_truncate , 2) 1885048f6b4dSbellard MIPS_SYS(sys_ftruncate , 2) 1886048f6b4dSbellard MIPS_SYS(sys_fchmod , 2) 1887048f6b4dSbellard MIPS_SYS(sys_fchown , 3) /* 4095 */ 1888048f6b4dSbellard MIPS_SYS(sys_getpriority , 2) 1889048f6b4dSbellard MIPS_SYS(sys_setpriority , 3) 1890048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 1891048f6b4dSbellard MIPS_SYS(sys_statfs , 2) 1892048f6b4dSbellard MIPS_SYS(sys_fstatfs , 2) /* 4100 */ 1893048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was ioperm(2) */ 1894048f6b4dSbellard MIPS_SYS(sys_socketcall , 2) 1895048f6b4dSbellard MIPS_SYS(sys_syslog , 3) 1896048f6b4dSbellard MIPS_SYS(sys_setitimer , 3) 1897048f6b4dSbellard MIPS_SYS(sys_getitimer , 2) /* 4105 */ 1898048f6b4dSbellard MIPS_SYS(sys_newstat , 2) 1899048f6b4dSbellard MIPS_SYS(sys_newlstat , 2) 1900048f6b4dSbellard MIPS_SYS(sys_newfstat , 2) 1901048f6b4dSbellard MIPS_SYS(sys_uname , 1) 1902048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* 4110 was iopl(2) */ 1903048f6b4dSbellard MIPS_SYS(sys_vhangup , 0) 1904048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was sys_idle() */ 1905048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was sys_vm86 */ 1906048f6b4dSbellard MIPS_SYS(sys_wait4 , 4) 1907048f6b4dSbellard MIPS_SYS(sys_swapoff , 1) /* 4115 */ 1908048f6b4dSbellard MIPS_SYS(sys_sysinfo , 1) 1909048f6b4dSbellard MIPS_SYS(sys_ipc , 6) 1910048f6b4dSbellard MIPS_SYS(sys_fsync , 1) 1911048f6b4dSbellard MIPS_SYS(sys_sigreturn , 0) 191218113962SPaul Brook MIPS_SYS(sys_clone , 6) /* 4120 */ 1913048f6b4dSbellard MIPS_SYS(sys_setdomainname, 2) 1914048f6b4dSbellard MIPS_SYS(sys_newuname , 1) 1915048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* sys_modify_ldt */ 1916048f6b4dSbellard MIPS_SYS(sys_adjtimex , 1) 1917048f6b4dSbellard MIPS_SYS(sys_mprotect , 3) /* 4125 */ 1918048f6b4dSbellard MIPS_SYS(sys_sigprocmask , 3) 1919048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was create_module */ 1920048f6b4dSbellard MIPS_SYS(sys_init_module , 5) 1921048f6b4dSbellard MIPS_SYS(sys_delete_module, 1) 1922048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* 4130 was get_kernel_syms */ 1923048f6b4dSbellard MIPS_SYS(sys_quotactl , 0) 1924048f6b4dSbellard MIPS_SYS(sys_getpgid , 1) 1925048f6b4dSbellard MIPS_SYS(sys_fchdir , 1) 1926048f6b4dSbellard MIPS_SYS(sys_bdflush , 2) 1927048f6b4dSbellard MIPS_SYS(sys_sysfs , 3) /* 4135 */ 1928048f6b4dSbellard MIPS_SYS(sys_personality , 1) 1929048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* for afs_syscall */ 1930048f6b4dSbellard MIPS_SYS(sys_setfsuid , 1) 1931048f6b4dSbellard MIPS_SYS(sys_setfsgid , 1) 1932048f6b4dSbellard MIPS_SYS(sys_llseek , 5) /* 4140 */ 1933048f6b4dSbellard MIPS_SYS(sys_getdents , 3) 1934048f6b4dSbellard MIPS_SYS(sys_select , 5) 1935048f6b4dSbellard MIPS_SYS(sys_flock , 2) 1936048f6b4dSbellard MIPS_SYS(sys_msync , 3) 1937048f6b4dSbellard MIPS_SYS(sys_readv , 3) /* 4145 */ 1938048f6b4dSbellard MIPS_SYS(sys_writev , 3) 1939048f6b4dSbellard MIPS_SYS(sys_cacheflush , 3) 1940048f6b4dSbellard MIPS_SYS(sys_cachectl , 3) 1941048f6b4dSbellard MIPS_SYS(sys_sysmips , 4) 1942048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* 4150 */ 1943048f6b4dSbellard MIPS_SYS(sys_getsid , 1) 1944048f6b4dSbellard MIPS_SYS(sys_fdatasync , 0) 1945048f6b4dSbellard MIPS_SYS(sys_sysctl , 1) 1946048f6b4dSbellard MIPS_SYS(sys_mlock , 2) 1947048f6b4dSbellard MIPS_SYS(sys_munlock , 2) /* 4155 */ 1948048f6b4dSbellard MIPS_SYS(sys_mlockall , 1) 1949048f6b4dSbellard MIPS_SYS(sys_munlockall , 0) 1950048f6b4dSbellard MIPS_SYS(sys_sched_setparam, 2) 1951048f6b4dSbellard MIPS_SYS(sys_sched_getparam, 2) 1952048f6b4dSbellard MIPS_SYS(sys_sched_setscheduler, 3) /* 4160 */ 1953048f6b4dSbellard MIPS_SYS(sys_sched_getscheduler, 1) 1954048f6b4dSbellard MIPS_SYS(sys_sched_yield , 0) 1955048f6b4dSbellard MIPS_SYS(sys_sched_get_priority_max, 1) 1956048f6b4dSbellard MIPS_SYS(sys_sched_get_priority_min, 1) 1957048f6b4dSbellard MIPS_SYS(sys_sched_rr_get_interval, 2) /* 4165 */ 1958048f6b4dSbellard MIPS_SYS(sys_nanosleep, 2) 1959b0932e06SPetar Jovanovic MIPS_SYS(sys_mremap , 5) 1960048f6b4dSbellard MIPS_SYS(sys_accept , 3) 1961048f6b4dSbellard MIPS_SYS(sys_bind , 3) 1962048f6b4dSbellard MIPS_SYS(sys_connect , 3) /* 4170 */ 1963048f6b4dSbellard MIPS_SYS(sys_getpeername , 3) 1964048f6b4dSbellard MIPS_SYS(sys_getsockname , 3) 1965048f6b4dSbellard MIPS_SYS(sys_getsockopt , 5) 1966048f6b4dSbellard MIPS_SYS(sys_listen , 2) 1967048f6b4dSbellard MIPS_SYS(sys_recv , 4) /* 4175 */ 1968048f6b4dSbellard MIPS_SYS(sys_recvfrom , 6) 1969048f6b4dSbellard MIPS_SYS(sys_recvmsg , 3) 1970048f6b4dSbellard MIPS_SYS(sys_send , 4) 1971048f6b4dSbellard MIPS_SYS(sys_sendmsg , 3) 1972048f6b4dSbellard MIPS_SYS(sys_sendto , 6) /* 4180 */ 1973048f6b4dSbellard MIPS_SYS(sys_setsockopt , 5) 1974048f6b4dSbellard MIPS_SYS(sys_shutdown , 2) 1975048f6b4dSbellard MIPS_SYS(sys_socket , 3) 1976048f6b4dSbellard MIPS_SYS(sys_socketpair , 4) 1977048f6b4dSbellard MIPS_SYS(sys_setresuid , 3) /* 4185 */ 1978048f6b4dSbellard MIPS_SYS(sys_getresuid , 3) 1979048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was sys_query_module */ 1980048f6b4dSbellard MIPS_SYS(sys_poll , 3) 1981048f6b4dSbellard MIPS_SYS(sys_nfsservctl , 3) 1982048f6b4dSbellard MIPS_SYS(sys_setresgid , 3) /* 4190 */ 1983048f6b4dSbellard MIPS_SYS(sys_getresgid , 3) 1984048f6b4dSbellard MIPS_SYS(sys_prctl , 5) 1985048f6b4dSbellard MIPS_SYS(sys_rt_sigreturn, 0) 1986048f6b4dSbellard MIPS_SYS(sys_rt_sigaction, 4) 1987048f6b4dSbellard MIPS_SYS(sys_rt_sigprocmask, 4) /* 4195 */ 1988048f6b4dSbellard MIPS_SYS(sys_rt_sigpending, 2) 1989048f6b4dSbellard MIPS_SYS(sys_rt_sigtimedwait, 4) 1990048f6b4dSbellard MIPS_SYS(sys_rt_sigqueueinfo, 3) 1991048f6b4dSbellard MIPS_SYS(sys_rt_sigsuspend, 0) 1992048f6b4dSbellard MIPS_SYS(sys_pread64 , 6) /* 4200 */ 1993048f6b4dSbellard MIPS_SYS(sys_pwrite64 , 6) 1994048f6b4dSbellard MIPS_SYS(sys_chown , 3) 1995048f6b4dSbellard MIPS_SYS(sys_getcwd , 2) 1996048f6b4dSbellard MIPS_SYS(sys_capget , 2) 1997048f6b4dSbellard MIPS_SYS(sys_capset , 2) /* 4205 */ 1998053ebb27SWesley W. Terpstra MIPS_SYS(sys_sigaltstack , 2) 1999048f6b4dSbellard MIPS_SYS(sys_sendfile , 4) 2000048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 2001048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 2002048f6b4dSbellard MIPS_SYS(sys_mmap2 , 6) /* 4210 */ 2003048f6b4dSbellard MIPS_SYS(sys_truncate64 , 4) 2004048f6b4dSbellard MIPS_SYS(sys_ftruncate64 , 4) 2005048f6b4dSbellard MIPS_SYS(sys_stat64 , 2) 2006048f6b4dSbellard MIPS_SYS(sys_lstat64 , 2) 2007048f6b4dSbellard MIPS_SYS(sys_fstat64 , 2) /* 4215 */ 2008048f6b4dSbellard MIPS_SYS(sys_pivot_root , 2) 2009048f6b4dSbellard MIPS_SYS(sys_mincore , 3) 2010048f6b4dSbellard MIPS_SYS(sys_madvise , 3) 2011048f6b4dSbellard MIPS_SYS(sys_getdents64 , 3) 2012048f6b4dSbellard MIPS_SYS(sys_fcntl64 , 3) /* 4220 */ 2013048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 2014048f6b4dSbellard MIPS_SYS(sys_gettid , 0) 2015048f6b4dSbellard MIPS_SYS(sys_readahead , 5) 2016048f6b4dSbellard MIPS_SYS(sys_setxattr , 5) 2017048f6b4dSbellard MIPS_SYS(sys_lsetxattr , 5) /* 4225 */ 2018048f6b4dSbellard MIPS_SYS(sys_fsetxattr , 5) 2019048f6b4dSbellard MIPS_SYS(sys_getxattr , 4) 2020048f6b4dSbellard MIPS_SYS(sys_lgetxattr , 4) 2021048f6b4dSbellard MIPS_SYS(sys_fgetxattr , 4) 2022048f6b4dSbellard MIPS_SYS(sys_listxattr , 3) /* 4230 */ 2023048f6b4dSbellard MIPS_SYS(sys_llistxattr , 3) 2024048f6b4dSbellard MIPS_SYS(sys_flistxattr , 3) 2025048f6b4dSbellard MIPS_SYS(sys_removexattr , 2) 2026048f6b4dSbellard MIPS_SYS(sys_lremovexattr, 2) 2027048f6b4dSbellard MIPS_SYS(sys_fremovexattr, 2) /* 4235 */ 2028048f6b4dSbellard MIPS_SYS(sys_tkill , 2) 2029048f6b4dSbellard MIPS_SYS(sys_sendfile64 , 5) 203043be1343SPetar Jovanovic MIPS_SYS(sys_futex , 6) 2031048f6b4dSbellard MIPS_SYS(sys_sched_setaffinity, 3) 2032048f6b4dSbellard MIPS_SYS(sys_sched_getaffinity, 3) /* 4240 */ 2033048f6b4dSbellard MIPS_SYS(sys_io_setup , 2) 2034048f6b4dSbellard MIPS_SYS(sys_io_destroy , 1) 2035048f6b4dSbellard MIPS_SYS(sys_io_getevents, 5) 2036048f6b4dSbellard MIPS_SYS(sys_io_submit , 3) 2037048f6b4dSbellard MIPS_SYS(sys_io_cancel , 3) /* 4245 */ 2038048f6b4dSbellard MIPS_SYS(sys_exit_group , 1) 2039048f6b4dSbellard MIPS_SYS(sys_lookup_dcookie, 3) 2040048f6b4dSbellard MIPS_SYS(sys_epoll_create, 1) 2041048f6b4dSbellard MIPS_SYS(sys_epoll_ctl , 4) 2042048f6b4dSbellard MIPS_SYS(sys_epoll_wait , 3) /* 4250 */ 2043048f6b4dSbellard MIPS_SYS(sys_remap_file_pages, 5) 2044048f6b4dSbellard MIPS_SYS(sys_set_tid_address, 1) 2045048f6b4dSbellard MIPS_SYS(sys_restart_syscall, 0) 2046048f6b4dSbellard MIPS_SYS(sys_fadvise64_64, 7) 2047048f6b4dSbellard MIPS_SYS(sys_statfs64 , 3) /* 4255 */ 2048048f6b4dSbellard MIPS_SYS(sys_fstatfs64 , 2) 2049048f6b4dSbellard MIPS_SYS(sys_timer_create, 3) 2050048f6b4dSbellard MIPS_SYS(sys_timer_settime, 4) 2051048f6b4dSbellard MIPS_SYS(sys_timer_gettime, 2) 2052048f6b4dSbellard MIPS_SYS(sys_timer_getoverrun, 1) /* 4260 */ 2053048f6b4dSbellard MIPS_SYS(sys_timer_delete, 1) 2054048f6b4dSbellard MIPS_SYS(sys_clock_settime, 2) 2055048f6b4dSbellard MIPS_SYS(sys_clock_gettime, 2) 2056048f6b4dSbellard MIPS_SYS(sys_clock_getres, 2) 2057048f6b4dSbellard MIPS_SYS(sys_clock_nanosleep, 4) /* 4265 */ 2058048f6b4dSbellard MIPS_SYS(sys_tgkill , 3) 2059048f6b4dSbellard MIPS_SYS(sys_utimes , 2) 2060048f6b4dSbellard MIPS_SYS(sys_mbind , 4) 2061048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* sys_get_mempolicy */ 2062048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* 4270 sys_set_mempolicy */ 2063048f6b4dSbellard MIPS_SYS(sys_mq_open , 4) 2064048f6b4dSbellard MIPS_SYS(sys_mq_unlink , 1) 2065048f6b4dSbellard MIPS_SYS(sys_mq_timedsend, 5) 2066048f6b4dSbellard MIPS_SYS(sys_mq_timedreceive, 5) 2067048f6b4dSbellard MIPS_SYS(sys_mq_notify , 2) /* 4275 */ 2068048f6b4dSbellard MIPS_SYS(sys_mq_getsetattr, 3) 2069048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* sys_vserver */ 2070048f6b4dSbellard MIPS_SYS(sys_waitid , 4) 2071048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* available, was setaltroot */ 2072048f6b4dSbellard MIPS_SYS(sys_add_key , 5) 2073048f6b4dSbellard MIPS_SYS(sys_request_key, 4) 2074048f6b4dSbellard MIPS_SYS(sys_keyctl , 5) 20756f5b89a0Sths MIPS_SYS(sys_set_thread_area, 1) 2076388bb21aSths MIPS_SYS(sys_inotify_init, 0) 2077388bb21aSths MIPS_SYS(sys_inotify_add_watch, 3) /* 4285 */ 2078388bb21aSths MIPS_SYS(sys_inotify_rm_watch, 2) 2079388bb21aSths MIPS_SYS(sys_migrate_pages, 4) 2080388bb21aSths MIPS_SYS(sys_openat, 4) 2081388bb21aSths MIPS_SYS(sys_mkdirat, 3) 2082388bb21aSths MIPS_SYS(sys_mknodat, 4) /* 4290 */ 2083388bb21aSths MIPS_SYS(sys_fchownat, 5) 2084388bb21aSths MIPS_SYS(sys_futimesat, 3) 2085388bb21aSths MIPS_SYS(sys_fstatat64, 4) 2086388bb21aSths MIPS_SYS(sys_unlinkat, 3) 2087388bb21aSths MIPS_SYS(sys_renameat, 4) /* 4295 */ 2088388bb21aSths MIPS_SYS(sys_linkat, 5) 2089388bb21aSths MIPS_SYS(sys_symlinkat, 3) 2090388bb21aSths MIPS_SYS(sys_readlinkat, 4) 2091388bb21aSths MIPS_SYS(sys_fchmodat, 3) 2092388bb21aSths MIPS_SYS(sys_faccessat, 3) /* 4300 */ 2093388bb21aSths MIPS_SYS(sys_pselect6, 6) 2094388bb21aSths MIPS_SYS(sys_ppoll, 5) 2095388bb21aSths MIPS_SYS(sys_unshare, 1) 2096b0932e06SPetar Jovanovic MIPS_SYS(sys_splice, 6) 2097388bb21aSths MIPS_SYS(sys_sync_file_range, 7) /* 4305 */ 2098388bb21aSths MIPS_SYS(sys_tee, 4) 2099388bb21aSths MIPS_SYS(sys_vmsplice, 4) 2100388bb21aSths MIPS_SYS(sys_move_pages, 6) 2101388bb21aSths MIPS_SYS(sys_set_robust_list, 2) 2102388bb21aSths MIPS_SYS(sys_get_robust_list, 3) /* 4310 */ 2103388bb21aSths MIPS_SYS(sys_kexec_load, 4) 2104388bb21aSths MIPS_SYS(sys_getcpu, 3) 2105388bb21aSths MIPS_SYS(sys_epoll_pwait, 6) 2106388bb21aSths MIPS_SYS(sys_ioprio_set, 3) 2107388bb21aSths MIPS_SYS(sys_ioprio_get, 2) 2108d979e8ebSPeter Maydell MIPS_SYS(sys_utimensat, 4) 2109d979e8ebSPeter Maydell MIPS_SYS(sys_signalfd, 3) 2110d979e8ebSPeter Maydell MIPS_SYS(sys_ni_syscall, 0) /* was timerfd */ 2111d979e8ebSPeter Maydell MIPS_SYS(sys_eventfd, 1) 2112d979e8ebSPeter Maydell MIPS_SYS(sys_fallocate, 6) /* 4320 */ 2113d979e8ebSPeter Maydell MIPS_SYS(sys_timerfd_create, 2) 2114d979e8ebSPeter Maydell MIPS_SYS(sys_timerfd_gettime, 2) 2115d979e8ebSPeter Maydell MIPS_SYS(sys_timerfd_settime, 4) 2116d979e8ebSPeter Maydell MIPS_SYS(sys_signalfd4, 4) 2117d979e8ebSPeter Maydell MIPS_SYS(sys_eventfd2, 2) /* 4325 */ 2118d979e8ebSPeter Maydell MIPS_SYS(sys_epoll_create1, 1) 2119d979e8ebSPeter Maydell MIPS_SYS(sys_dup3, 3) 2120d979e8ebSPeter Maydell MIPS_SYS(sys_pipe2, 2) 2121d979e8ebSPeter Maydell MIPS_SYS(sys_inotify_init1, 1) 21222e6eeb67SAleksandar Markovic MIPS_SYS(sys_preadv, 5) /* 4330 */ 21232e6eeb67SAleksandar Markovic MIPS_SYS(sys_pwritev, 5) 2124d979e8ebSPeter Maydell MIPS_SYS(sys_rt_tgsigqueueinfo, 4) 2125d979e8ebSPeter Maydell MIPS_SYS(sys_perf_event_open, 5) 2126d979e8ebSPeter Maydell MIPS_SYS(sys_accept4, 4) 2127d979e8ebSPeter Maydell MIPS_SYS(sys_recvmmsg, 5) /* 4335 */ 2128d979e8ebSPeter Maydell MIPS_SYS(sys_fanotify_init, 2) 2129d979e8ebSPeter Maydell MIPS_SYS(sys_fanotify_mark, 6) 2130d979e8ebSPeter Maydell MIPS_SYS(sys_prlimit64, 4) 2131d979e8ebSPeter Maydell MIPS_SYS(sys_name_to_handle_at, 5) 2132d979e8ebSPeter Maydell MIPS_SYS(sys_open_by_handle_at, 3) /* 4340 */ 2133d979e8ebSPeter Maydell MIPS_SYS(sys_clock_adjtime, 2) 2134d979e8ebSPeter Maydell MIPS_SYS(sys_syncfs, 1) 21352e6eeb67SAleksandar Markovic MIPS_SYS(sys_sendmmsg, 4) 21362e6eeb67SAleksandar Markovic MIPS_SYS(sys_setns, 2) 21372e6eeb67SAleksandar Markovic MIPS_SYS(sys_process_vm_readv, 6) /* 345 */ 21382e6eeb67SAleksandar Markovic MIPS_SYS(sys_process_vm_writev, 6) 21392e6eeb67SAleksandar Markovic MIPS_SYS(sys_kcmp, 5) 21402e6eeb67SAleksandar Markovic MIPS_SYS(sys_finit_module, 3) 21412e6eeb67SAleksandar Markovic MIPS_SYS(sys_sched_setattr, 2) 21422e6eeb67SAleksandar Markovic MIPS_SYS(sys_sched_getattr, 3) /* 350 */ 21432e6eeb67SAleksandar Markovic MIPS_SYS(sys_renameat2, 5) 21442e6eeb67SAleksandar Markovic MIPS_SYS(sys_seccomp, 3) 21452e6eeb67SAleksandar Markovic MIPS_SYS(sys_getrandom, 3) 21462e6eeb67SAleksandar Markovic MIPS_SYS(sys_memfd_create, 2) 21472e6eeb67SAleksandar Markovic MIPS_SYS(sys_bpf, 3) /* 355 */ 21482e6eeb67SAleksandar Markovic MIPS_SYS(sys_execveat, 5) 21492e6eeb67SAleksandar Markovic MIPS_SYS(sys_userfaultfd, 1) 21502e6eeb67SAleksandar Markovic MIPS_SYS(sys_membarrier, 2) 21512e6eeb67SAleksandar Markovic MIPS_SYS(sys_mlock2, 3) 21522e6eeb67SAleksandar Markovic MIPS_SYS(sys_copy_file_range, 6) /* 360 */ 21532e6eeb67SAleksandar Markovic MIPS_SYS(sys_preadv2, 6) 21542e6eeb67SAleksandar Markovic MIPS_SYS(sys_pwritev2, 6) 2155048f6b4dSbellard }; 2156048f6b4dSbellard # undef MIPS_SYS 2157ff4f7382SRichard Henderson # endif /* O32 */ 2158048f6b4dSbellard 2159590bc601SPaul Brook static int do_store_exclusive(CPUMIPSState *env) 2160590bc601SPaul Brook { 2161590bc601SPaul Brook target_ulong addr; 2162590bc601SPaul Brook target_ulong page_addr; 2163590bc601SPaul Brook target_ulong val; 2164590bc601SPaul Brook int flags; 2165590bc601SPaul Brook int segv = 0; 2166590bc601SPaul Brook int reg; 2167590bc601SPaul Brook int d; 2168590bc601SPaul Brook 21695499b6ffSAurelien Jarno addr = env->lladdr; 2170590bc601SPaul Brook page_addr = addr & TARGET_PAGE_MASK; 2171590bc601SPaul Brook start_exclusive(); 2172590bc601SPaul Brook mmap_lock(); 2173590bc601SPaul Brook flags = page_get_flags(page_addr); 2174590bc601SPaul Brook if ((flags & PAGE_READ) == 0) { 2175590bc601SPaul Brook segv = 1; 2176590bc601SPaul Brook } else { 2177590bc601SPaul Brook reg = env->llreg & 0x1f; 2178590bc601SPaul Brook d = (env->llreg & 0x20) != 0; 2179590bc601SPaul Brook if (d) { 2180590bc601SPaul Brook segv = get_user_s64(val, addr); 2181590bc601SPaul Brook } else { 2182590bc601SPaul Brook segv = get_user_s32(val, addr); 2183590bc601SPaul Brook } 2184590bc601SPaul Brook if (!segv) { 2185590bc601SPaul Brook if (val != env->llval) { 2186590bc601SPaul Brook env->active_tc.gpr[reg] = 0; 2187590bc601SPaul Brook } else { 2188590bc601SPaul Brook if (d) { 2189590bc601SPaul Brook segv = put_user_u64(env->llnewval, addr); 2190590bc601SPaul Brook } else { 2191590bc601SPaul Brook segv = put_user_u32(env->llnewval, addr); 2192590bc601SPaul Brook } 2193590bc601SPaul Brook if (!segv) { 2194590bc601SPaul Brook env->active_tc.gpr[reg] = 1; 2195590bc601SPaul Brook } 2196590bc601SPaul Brook } 2197590bc601SPaul Brook } 2198590bc601SPaul Brook } 21995499b6ffSAurelien Jarno env->lladdr = -1; 2200590bc601SPaul Brook if (!segv) { 2201590bc601SPaul Brook env->active_tc.PC += 4; 2202590bc601SPaul Brook } 2203590bc601SPaul Brook mmap_unlock(); 2204590bc601SPaul Brook end_exclusive(); 2205590bc601SPaul Brook return segv; 2206590bc601SPaul Brook } 2207590bc601SPaul Brook 220854b2f42cSMeador Inge /* Break codes */ 220954b2f42cSMeador Inge enum { 221054b2f42cSMeador Inge BRK_OVERFLOW = 6, 221154b2f42cSMeador Inge BRK_DIVZERO = 7 221254b2f42cSMeador Inge }; 221354b2f42cSMeador Inge 221454b2f42cSMeador Inge static int do_break(CPUMIPSState *env, target_siginfo_t *info, 221554b2f42cSMeador Inge unsigned int code) 221654b2f42cSMeador Inge { 221754b2f42cSMeador Inge int ret = -1; 221854b2f42cSMeador Inge 221954b2f42cSMeador Inge switch (code) { 222054b2f42cSMeador Inge case BRK_OVERFLOW: 222154b2f42cSMeador Inge case BRK_DIVZERO: 222254b2f42cSMeador Inge info->si_signo = TARGET_SIGFPE; 222354b2f42cSMeador Inge info->si_errno = 0; 222454b2f42cSMeador Inge info->si_code = (code == BRK_OVERFLOW) ? FPE_INTOVF : FPE_INTDIV; 22259d2803f7SPeter Maydell queue_signal(env, info->si_signo, QEMU_SI_FAULT, &*info); 222654b2f42cSMeador Inge ret = 0; 222754b2f42cSMeador Inge break; 222854b2f42cSMeador Inge default: 2229b51910baSPetar Jovanovic info->si_signo = TARGET_SIGTRAP; 2230b51910baSPetar Jovanovic info->si_errno = 0; 22319d2803f7SPeter Maydell queue_signal(env, info->si_signo, QEMU_SI_FAULT, &*info); 2232b51910baSPetar Jovanovic ret = 0; 223354b2f42cSMeador Inge break; 223454b2f42cSMeador Inge } 223554b2f42cSMeador Inge 223654b2f42cSMeador Inge return ret; 223754b2f42cSMeador Inge } 223854b2f42cSMeador Inge 2239048f6b4dSbellard void cpu_loop(CPUMIPSState *env) 2240048f6b4dSbellard { 22410315c31cSAndreas Färber CPUState *cs = CPU(mips_env_get_cpu(env)); 2242c227f099SAnthony Liguori target_siginfo_t info; 2243ff4f7382SRichard Henderson int trapnr; 2244ff4f7382SRichard Henderson abi_long ret; 2245ff4f7382SRichard Henderson # ifdef TARGET_ABI_MIPSO32 2246048f6b4dSbellard unsigned int syscall_num; 2247ff4f7382SRichard Henderson # endif 2248048f6b4dSbellard 2249048f6b4dSbellard for(;;) { 22500315c31cSAndreas Färber cpu_exec_start(cs); 22518642c1b8SPeter Crosthwaite trapnr = cpu_exec(cs); 22520315c31cSAndreas Färber cpu_exec_end(cs); 2253d148d90eSSergey Fedorov process_queued_cpu_work(cs); 2254d148d90eSSergey Fedorov 2255048f6b4dSbellard switch(trapnr) { 2256048f6b4dSbellard case EXCP_SYSCALL: 2257b5dc7732Sths env->active_tc.PC += 4; 2258ff4f7382SRichard Henderson # ifdef TARGET_ABI_MIPSO32 2259ff4f7382SRichard Henderson syscall_num = env->active_tc.gpr[2] - 4000; 2260048f6b4dSbellard if (syscall_num >= sizeof(mips_syscall_args)) { 22617c2f6157SWesley W. Terpstra ret = -TARGET_ENOSYS; 2262048f6b4dSbellard } else { 2263388bb21aSths int nb_args; 2264992f48a0Sblueswir1 abi_ulong sp_reg; 2265992f48a0Sblueswir1 abi_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0; 2266388bb21aSths 2267048f6b4dSbellard nb_args = mips_syscall_args[syscall_num]; 2268b5dc7732Sths sp_reg = env->active_tc.gpr[29]; 2269388bb21aSths switch (nb_args) { 2270048f6b4dSbellard /* these arguments are taken from the stack */ 227194c19610SAn-Cheng Huang case 8: 227294c19610SAn-Cheng Huang if ((ret = get_user_ual(arg8, sp_reg + 28)) != 0) { 227394c19610SAn-Cheng Huang goto done_syscall; 227494c19610SAn-Cheng Huang } 227594c19610SAn-Cheng Huang case 7: 227694c19610SAn-Cheng Huang if ((ret = get_user_ual(arg7, sp_reg + 24)) != 0) { 227794c19610SAn-Cheng Huang goto done_syscall; 227894c19610SAn-Cheng Huang } 227994c19610SAn-Cheng Huang case 6: 228094c19610SAn-Cheng Huang if ((ret = get_user_ual(arg6, sp_reg + 20)) != 0) { 228194c19610SAn-Cheng Huang goto done_syscall; 228294c19610SAn-Cheng Huang } 228394c19610SAn-Cheng Huang case 5: 228494c19610SAn-Cheng Huang if ((ret = get_user_ual(arg5, sp_reg + 16)) != 0) { 228594c19610SAn-Cheng Huang goto done_syscall; 228694c19610SAn-Cheng Huang } 2287388bb21aSths default: 2288388bb21aSths break; 2289048f6b4dSbellard } 2290b5dc7732Sths ret = do_syscall(env, env->active_tc.gpr[2], 2291b5dc7732Sths env->active_tc.gpr[4], 2292b5dc7732Sths env->active_tc.gpr[5], 2293b5dc7732Sths env->active_tc.gpr[6], 2294b5dc7732Sths env->active_tc.gpr[7], 22955945cfcbSPeter Maydell arg5, arg6, arg7, arg8); 2296048f6b4dSbellard } 229794c19610SAn-Cheng Huang done_syscall: 2298ff4f7382SRichard Henderson # else 2299ff4f7382SRichard Henderson ret = do_syscall(env, env->active_tc.gpr[2], 2300ff4f7382SRichard Henderson env->active_tc.gpr[4], env->active_tc.gpr[5], 2301ff4f7382SRichard Henderson env->active_tc.gpr[6], env->active_tc.gpr[7], 2302ff4f7382SRichard Henderson env->active_tc.gpr[8], env->active_tc.gpr[9], 2303ff4f7382SRichard Henderson env->active_tc.gpr[10], env->active_tc.gpr[11]); 2304ff4f7382SRichard Henderson # endif /* O32 */ 23052eb3ae27STimothy E Baldwin if (ret == -TARGET_ERESTARTSYS) { 23062eb3ae27STimothy E Baldwin env->active_tc.PC -= 4; 23072eb3ae27STimothy E Baldwin break; 23082eb3ae27STimothy E Baldwin } 23090b1bcb00Spbrook if (ret == -TARGET_QEMU_ESIGRETURN) { 23100b1bcb00Spbrook /* Returning from a successful sigreturn syscall. 23110b1bcb00Spbrook Avoid clobbering register state. */ 23120b1bcb00Spbrook break; 23130b1bcb00Spbrook } 2314ff4f7382SRichard Henderson if ((abi_ulong)ret >= (abi_ulong)-1133) { 2315b5dc7732Sths env->active_tc.gpr[7] = 1; /* error flag */ 2316048f6b4dSbellard ret = -ret; 2317048f6b4dSbellard } else { 2318b5dc7732Sths env->active_tc.gpr[7] = 0; /* error flag */ 2319388bb21aSths } 2320b5dc7732Sths env->active_tc.gpr[2] = ret; 2321048f6b4dSbellard break; 2322ca7c2b1bSths case EXCP_TLBL: 2323ca7c2b1bSths case EXCP_TLBS: 2324e6e5bd2dSWesley W. Terpstra case EXCP_AdEL: 2325e6e5bd2dSWesley W. Terpstra case EXCP_AdES: 2326e4474235Spbrook info.si_signo = TARGET_SIGSEGV; 2327e4474235Spbrook info.si_errno = 0; 2328e4474235Spbrook /* XXX: check env->error_code */ 2329e4474235Spbrook info.si_code = TARGET_SEGV_MAPERR; 2330e4474235Spbrook info._sifields._sigfault._addr = env->CP0_BadVAddr; 23319d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 2332e4474235Spbrook break; 23336900e84bSbellard case EXCP_CpU: 2334048f6b4dSbellard case EXCP_RI: 2335048f6b4dSbellard info.si_signo = TARGET_SIGILL; 2336048f6b4dSbellard info.si_errno = 0; 2337048f6b4dSbellard info.si_code = 0; 23389d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 2339048f6b4dSbellard break; 2340106ec879Sbellard case EXCP_INTERRUPT: 2341106ec879Sbellard /* just indicate that signals should be handled asap */ 2342106ec879Sbellard break; 2343d08b2a28Spbrook case EXCP_DEBUG: 2344d08b2a28Spbrook { 2345d08b2a28Spbrook int sig; 2346d08b2a28Spbrook 2347db6b81d4SAndreas Färber sig = gdb_handlesig(cs, TARGET_SIGTRAP); 2348d08b2a28Spbrook if (sig) 2349d08b2a28Spbrook { 2350d08b2a28Spbrook info.si_signo = sig; 2351d08b2a28Spbrook info.si_errno = 0; 2352d08b2a28Spbrook info.si_code = TARGET_TRAP_BRKPT; 23539d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 2354d08b2a28Spbrook } 2355d08b2a28Spbrook } 2356d08b2a28Spbrook break; 2357590bc601SPaul Brook case EXCP_SC: 2358590bc601SPaul Brook if (do_store_exclusive(env)) { 2359590bc601SPaul Brook info.si_signo = TARGET_SIGSEGV; 2360590bc601SPaul Brook info.si_errno = 0; 2361590bc601SPaul Brook info.si_code = TARGET_SEGV_MAPERR; 2362590bc601SPaul Brook info._sifields._sigfault._addr = env->active_tc.PC; 23639d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 2364590bc601SPaul Brook } 2365590bc601SPaul Brook break; 2366853c3240SJia Liu case EXCP_DSPDIS: 2367853c3240SJia Liu info.si_signo = TARGET_SIGILL; 2368853c3240SJia Liu info.si_errno = 0; 2369853c3240SJia Liu info.si_code = TARGET_ILL_ILLOPC; 23709d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 2371853c3240SJia Liu break; 237254b2f42cSMeador Inge /* The code below was inspired by the MIPS Linux kernel trap 237354b2f42cSMeador Inge * handling code in arch/mips/kernel/traps.c. 237454b2f42cSMeador Inge */ 237554b2f42cSMeador Inge case EXCP_BREAK: 237654b2f42cSMeador Inge { 237754b2f42cSMeador Inge abi_ulong trap_instr; 237854b2f42cSMeador Inge unsigned int code; 237954b2f42cSMeador Inge 2380a0333817SKwok Cheung Yeung if (env->hflags & MIPS_HFLAG_M16) { 2381a0333817SKwok Cheung Yeung if (env->insn_flags & ASE_MICROMIPS) { 2382a0333817SKwok Cheung Yeung /* microMIPS mode */ 23831308c464SKwok Cheung Yeung ret = get_user_u16(trap_instr, env->active_tc.PC); 23841308c464SKwok Cheung Yeung if (ret != 0) { 23851308c464SKwok Cheung Yeung goto error; 23861308c464SKwok Cheung Yeung } 2387a0333817SKwok Cheung Yeung 23881308c464SKwok Cheung Yeung if ((trap_instr >> 10) == 0x11) { 23891308c464SKwok Cheung Yeung /* 16-bit instruction */ 23901308c464SKwok Cheung Yeung code = trap_instr & 0xf; 23911308c464SKwok Cheung Yeung } else { 23921308c464SKwok Cheung Yeung /* 32-bit instruction */ 23931308c464SKwok Cheung Yeung abi_ulong instr_lo; 2394a0333817SKwok Cheung Yeung 23951308c464SKwok Cheung Yeung ret = get_user_u16(instr_lo, 23961308c464SKwok Cheung Yeung env->active_tc.PC + 2); 23971308c464SKwok Cheung Yeung if (ret != 0) { 23981308c464SKwok Cheung Yeung goto error; 23991308c464SKwok Cheung Yeung } 24001308c464SKwok Cheung Yeung trap_instr = (trap_instr << 16) | instr_lo; 24011308c464SKwok Cheung Yeung code = ((trap_instr >> 6) & ((1 << 20) - 1)); 24021308c464SKwok Cheung Yeung /* Unfortunately, microMIPS also suffers from 24031308c464SKwok Cheung Yeung the old assembler bug... */ 24041308c464SKwok Cheung Yeung if (code >= (1 << 10)) { 24051308c464SKwok Cheung Yeung code >>= 10; 24061308c464SKwok Cheung Yeung } 24071308c464SKwok Cheung Yeung } 2408a0333817SKwok Cheung Yeung } else { 2409a0333817SKwok Cheung Yeung /* MIPS16e mode */ 2410a0333817SKwok Cheung Yeung ret = get_user_u16(trap_instr, env->active_tc.PC); 2411a0333817SKwok Cheung Yeung if (ret != 0) { 2412a0333817SKwok Cheung Yeung goto error; 2413a0333817SKwok Cheung Yeung } 2414a0333817SKwok Cheung Yeung code = (trap_instr >> 6) & 0x3f; 2415a0333817SKwok Cheung Yeung } 2416a0333817SKwok Cheung Yeung } else { 2417f01a361bSAndrew Bennett ret = get_user_u32(trap_instr, env->active_tc.PC); 241854b2f42cSMeador Inge if (ret != 0) { 241954b2f42cSMeador Inge goto error; 242054b2f42cSMeador Inge } 242154b2f42cSMeador Inge 242254b2f42cSMeador Inge /* As described in the original Linux kernel code, the 242354b2f42cSMeador Inge * below checks on 'code' are to work around an old 242454b2f42cSMeador Inge * assembly bug. 242554b2f42cSMeador Inge */ 242654b2f42cSMeador Inge code = ((trap_instr >> 6) & ((1 << 20) - 1)); 242754b2f42cSMeador Inge if (code >= (1 << 10)) { 242854b2f42cSMeador Inge code >>= 10; 242954b2f42cSMeador Inge } 24301308c464SKwok Cheung Yeung } 243154b2f42cSMeador Inge 243254b2f42cSMeador Inge if (do_break(env, &info, code) != 0) { 243354b2f42cSMeador Inge goto error; 243454b2f42cSMeador Inge } 243554b2f42cSMeador Inge } 243654b2f42cSMeador Inge break; 243754b2f42cSMeador Inge case EXCP_TRAP: 243854b2f42cSMeador Inge { 243954b2f42cSMeador Inge abi_ulong trap_instr; 244054b2f42cSMeador Inge unsigned int code = 0; 244154b2f42cSMeador Inge 2442a0333817SKwok Cheung Yeung if (env->hflags & MIPS_HFLAG_M16) { 2443a0333817SKwok Cheung Yeung /* microMIPS mode */ 2444a0333817SKwok Cheung Yeung abi_ulong instr[2]; 2445a0333817SKwok Cheung Yeung 2446a0333817SKwok Cheung Yeung ret = get_user_u16(instr[0], env->active_tc.PC) || 2447a0333817SKwok Cheung Yeung get_user_u16(instr[1], env->active_tc.PC + 2); 2448a0333817SKwok Cheung Yeung 2449a0333817SKwok Cheung Yeung trap_instr = (instr[0] << 16) | instr[1]; 2450a0333817SKwok Cheung Yeung } else { 2451f01a361bSAndrew Bennett ret = get_user_u32(trap_instr, env->active_tc.PC); 2452a0333817SKwok Cheung Yeung } 2453a0333817SKwok Cheung Yeung 245454b2f42cSMeador Inge if (ret != 0) { 245554b2f42cSMeador Inge goto error; 245654b2f42cSMeador Inge } 245754b2f42cSMeador Inge 245854b2f42cSMeador Inge /* The immediate versions don't provide a code. */ 245954b2f42cSMeador Inge if (!(trap_instr & 0xFC000000)) { 2460a0333817SKwok Cheung Yeung if (env->hflags & MIPS_HFLAG_M16) { 2461a0333817SKwok Cheung Yeung /* microMIPS mode */ 2462a0333817SKwok Cheung Yeung code = ((trap_instr >> 12) & ((1 << 4) - 1)); 2463a0333817SKwok Cheung Yeung } else { 246454b2f42cSMeador Inge code = ((trap_instr >> 6) & ((1 << 10) - 1)); 246554b2f42cSMeador Inge } 2466a0333817SKwok Cheung Yeung } 246754b2f42cSMeador Inge 246854b2f42cSMeador Inge if (do_break(env, &info, code) != 0) { 246954b2f42cSMeador Inge goto error; 247054b2f42cSMeador Inge } 247154b2f42cSMeador Inge } 247254b2f42cSMeador Inge break; 2473fdbc2b57SRichard Henderson case EXCP_ATOMIC: 2474fdbc2b57SRichard Henderson cpu_exec_step_atomic(cs); 2475fdbc2b57SRichard Henderson break; 2476048f6b4dSbellard default: 247754b2f42cSMeador Inge error: 2478120a9848SPaolo Bonzini EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr); 2479048f6b4dSbellard abort(); 2480048f6b4dSbellard } 2481048f6b4dSbellard process_pending_signals(env); 2482048f6b4dSbellard } 2483048f6b4dSbellard } 2484048f6b4dSbellard #endif 2485048f6b4dSbellard 2486a0a839b6SMarek Vasut #ifdef TARGET_NIOS2 2487a0a839b6SMarek Vasut 2488a0a839b6SMarek Vasut void cpu_loop(CPUNios2State *env) 2489a0a839b6SMarek Vasut { 2490a0a839b6SMarek Vasut CPUState *cs = ENV_GET_CPU(env); 2491a0a839b6SMarek Vasut Nios2CPU *cpu = NIOS2_CPU(cs); 2492a0a839b6SMarek Vasut target_siginfo_t info; 2493a0a839b6SMarek Vasut int trapnr, gdbsig, ret; 2494a0a839b6SMarek Vasut 2495a0a839b6SMarek Vasut for (;;) { 2496a0a839b6SMarek Vasut cpu_exec_start(cs); 2497a0a839b6SMarek Vasut trapnr = cpu_exec(cs); 2498a0a839b6SMarek Vasut cpu_exec_end(cs); 2499a0a839b6SMarek Vasut gdbsig = 0; 2500a0a839b6SMarek Vasut 2501a0a839b6SMarek Vasut switch (trapnr) { 2502a0a839b6SMarek Vasut case EXCP_INTERRUPT: 2503a0a839b6SMarek Vasut /* just indicate that signals should be handled asap */ 2504a0a839b6SMarek Vasut break; 2505a0a839b6SMarek Vasut case EXCP_TRAP: 2506a0a839b6SMarek Vasut if (env->regs[R_AT] == 0) { 2507a0a839b6SMarek Vasut abi_long ret; 2508a0a839b6SMarek Vasut qemu_log_mask(CPU_LOG_INT, "\nSyscall\n"); 2509a0a839b6SMarek Vasut 2510a0a839b6SMarek Vasut ret = do_syscall(env, env->regs[2], 2511a0a839b6SMarek Vasut env->regs[4], env->regs[5], env->regs[6], 2512a0a839b6SMarek Vasut env->regs[7], env->regs[8], env->regs[9], 2513a0a839b6SMarek Vasut 0, 0); 2514a0a839b6SMarek Vasut 2515a0a839b6SMarek Vasut if (env->regs[2] == 0) { /* FIXME: syscall 0 workaround */ 2516a0a839b6SMarek Vasut ret = 0; 2517a0a839b6SMarek Vasut } 2518a0a839b6SMarek Vasut 2519a0a839b6SMarek Vasut env->regs[2] = abs(ret); 2520a0a839b6SMarek Vasut /* Return value is 0..4096 */ 2521a0a839b6SMarek Vasut env->regs[7] = (ret > 0xfffffffffffff000ULL); 2522a0a839b6SMarek Vasut env->regs[CR_ESTATUS] = env->regs[CR_STATUS]; 2523a0a839b6SMarek Vasut env->regs[CR_STATUS] &= ~0x3; 2524a0a839b6SMarek Vasut env->regs[R_EA] = env->regs[R_PC] + 4; 2525a0a839b6SMarek Vasut env->regs[R_PC] += 4; 2526a0a839b6SMarek Vasut break; 2527a0a839b6SMarek Vasut } else { 2528a0a839b6SMarek Vasut qemu_log_mask(CPU_LOG_INT, "\nTrap\n"); 2529a0a839b6SMarek Vasut 2530a0a839b6SMarek Vasut env->regs[CR_ESTATUS] = env->regs[CR_STATUS]; 2531a0a839b6SMarek Vasut env->regs[CR_STATUS] &= ~0x3; 2532a0a839b6SMarek Vasut env->regs[R_EA] = env->regs[R_PC] + 4; 2533a0a839b6SMarek Vasut env->regs[R_PC] = cpu->exception_addr; 2534a0a839b6SMarek Vasut 2535a0a839b6SMarek Vasut gdbsig = TARGET_SIGTRAP; 2536a0a839b6SMarek Vasut break; 2537a0a839b6SMarek Vasut } 2538a0a839b6SMarek Vasut case 0xaa: 2539a0a839b6SMarek Vasut switch (env->regs[R_PC]) { 2540a0a839b6SMarek Vasut /*case 0x1000:*/ /* TODO:__kuser_helper_version */ 2541a0a839b6SMarek Vasut case 0x1004: /* __kuser_cmpxchg */ 2542a0a839b6SMarek Vasut start_exclusive(); 2543a0a839b6SMarek Vasut if (env->regs[4] & 0x3) { 2544a0a839b6SMarek Vasut goto kuser_fail; 2545a0a839b6SMarek Vasut } 2546a0a839b6SMarek Vasut ret = get_user_u32(env->regs[2], env->regs[4]); 2547a0a839b6SMarek Vasut if (ret) { 2548a0a839b6SMarek Vasut end_exclusive(); 2549a0a839b6SMarek Vasut goto kuser_fail; 2550a0a839b6SMarek Vasut } 2551a0a839b6SMarek Vasut env->regs[2] -= env->regs[5]; 2552a0a839b6SMarek Vasut if (env->regs[2] == 0) { 2553a0a839b6SMarek Vasut put_user_u32(env->regs[6], env->regs[4]); 2554a0a839b6SMarek Vasut } 2555a0a839b6SMarek Vasut end_exclusive(); 2556a0a839b6SMarek Vasut env->regs[R_PC] = env->regs[R_RA]; 2557a0a839b6SMarek Vasut break; 2558a0a839b6SMarek Vasut /*case 0x1040:*/ /* TODO:__kuser_sigtramp */ 2559a0a839b6SMarek Vasut default: 2560a0a839b6SMarek Vasut ; 2561a0a839b6SMarek Vasut kuser_fail: 2562a0a839b6SMarek Vasut info.si_signo = TARGET_SIGSEGV; 2563a0a839b6SMarek Vasut info.si_errno = 0; 2564a0a839b6SMarek Vasut /* TODO: check env->error_code */ 2565a0a839b6SMarek Vasut info.si_code = TARGET_SEGV_MAPERR; 2566a0a839b6SMarek Vasut info._sifields._sigfault._addr = env->regs[R_PC]; 2567a0a839b6SMarek Vasut queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 2568a0a839b6SMarek Vasut } 2569a0a839b6SMarek Vasut break; 2570a0a839b6SMarek Vasut default: 2571a0a839b6SMarek Vasut EXCP_DUMP(env, "\nqemu: unhandled CPU exception %#x - aborting\n", 2572a0a839b6SMarek Vasut trapnr); 2573a0a839b6SMarek Vasut gdbsig = TARGET_SIGILL; 2574a0a839b6SMarek Vasut break; 2575a0a839b6SMarek Vasut } 2576a0a839b6SMarek Vasut if (gdbsig) { 2577a0a839b6SMarek Vasut gdb_handlesig(cs, gdbsig); 2578a0a839b6SMarek Vasut if (gdbsig != TARGET_SIGTRAP) { 2579a0a839b6SMarek Vasut exit(EXIT_FAILURE); 2580a0a839b6SMarek Vasut } 2581a0a839b6SMarek Vasut } 2582a0a839b6SMarek Vasut 2583a0a839b6SMarek Vasut process_pending_signals(env); 2584a0a839b6SMarek Vasut } 2585a0a839b6SMarek Vasut } 2586a0a839b6SMarek Vasut 2587a0a839b6SMarek Vasut #endif /* TARGET_NIOS2 */ 2588a0a839b6SMarek Vasut 2589d962783eSJia Liu #ifdef TARGET_OPENRISC 2590d962783eSJia Liu 2591d962783eSJia Liu void cpu_loop(CPUOpenRISCState *env) 2592d962783eSJia Liu { 2593878096eeSAndreas Färber CPUState *cs = CPU(openrisc_env_get_cpu(env)); 2594a0adc417SRichard Henderson int trapnr; 25957fe7231aSTimothy E Baldwin abi_long ret; 2596a0adc417SRichard Henderson target_siginfo_t info; 2597d962783eSJia Liu 2598d962783eSJia Liu for (;;) { 2599b040bc9cSPeter Maydell cpu_exec_start(cs); 26008642c1b8SPeter Crosthwaite trapnr = cpu_exec(cs); 2601b040bc9cSPeter Maydell cpu_exec_end(cs); 2602d148d90eSSergey Fedorov process_queued_cpu_work(cs); 2603d962783eSJia Liu 2604d962783eSJia Liu switch (trapnr) { 2605d962783eSJia Liu case EXCP_SYSCALL: 2606d962783eSJia Liu env->pc += 4; /* 0xc00; */ 26077fe7231aSTimothy E Baldwin ret = do_syscall(env, 2608d89e71e8SStafford Horne cpu_get_gpr(env, 11), /* return value */ 2609d89e71e8SStafford Horne cpu_get_gpr(env, 3), /* r3 - r7 are params */ 2610d89e71e8SStafford Horne cpu_get_gpr(env, 4), 2611d89e71e8SStafford Horne cpu_get_gpr(env, 5), 2612d89e71e8SStafford Horne cpu_get_gpr(env, 6), 2613d89e71e8SStafford Horne cpu_get_gpr(env, 7), 2614d89e71e8SStafford Horne cpu_get_gpr(env, 8), 0, 0); 26157fe7231aSTimothy E Baldwin if (ret == -TARGET_ERESTARTSYS) { 26167fe7231aSTimothy E Baldwin env->pc -= 4; 26177fe7231aSTimothy E Baldwin } else if (ret != -TARGET_QEMU_ESIGRETURN) { 2618d89e71e8SStafford Horne cpu_set_gpr(env, 11, ret); 26197fe7231aSTimothy E Baldwin } 2620d962783eSJia Liu break; 2621a0adc417SRichard Henderson case EXCP_DPF: 2622a0adc417SRichard Henderson case EXCP_IPF: 2623a0adc417SRichard Henderson case EXCP_RANGE: 2624a0adc417SRichard Henderson info.si_signo = TARGET_SIGSEGV; 2625a0adc417SRichard Henderson info.si_errno = 0; 2626a0adc417SRichard Henderson info.si_code = TARGET_SEGV_MAPERR; 2627a0adc417SRichard Henderson info._sifields._sigfault._addr = env->pc; 2628a0adc417SRichard Henderson queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 2629a0adc417SRichard Henderson break; 2630a0adc417SRichard Henderson case EXCP_ALIGN: 2631a0adc417SRichard Henderson info.si_signo = TARGET_SIGBUS; 2632a0adc417SRichard Henderson info.si_errno = 0; 2633a0adc417SRichard Henderson info.si_code = TARGET_BUS_ADRALN; 2634a0adc417SRichard Henderson info._sifields._sigfault._addr = env->pc; 2635a0adc417SRichard Henderson queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 2636a0adc417SRichard Henderson break; 2637a0adc417SRichard Henderson case EXCP_ILLEGAL: 2638a0adc417SRichard Henderson info.si_signo = TARGET_SIGILL; 2639a0adc417SRichard Henderson info.si_errno = 0; 2640a0adc417SRichard Henderson info.si_code = TARGET_ILL_ILLOPC; 2641a0adc417SRichard Henderson info._sifields._sigfault._addr = env->pc; 2642a0adc417SRichard Henderson queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 2643a0adc417SRichard Henderson break; 2644d962783eSJia Liu case EXCP_FPE: 2645a0adc417SRichard Henderson info.si_signo = TARGET_SIGFPE; 2646a0adc417SRichard Henderson info.si_errno = 0; 2647a0adc417SRichard Henderson info.si_code = 0; 2648a0adc417SRichard Henderson info._sifields._sigfault._addr = env->pc; 2649a0adc417SRichard Henderson queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 2650d962783eSJia Liu break; 2651a0adc417SRichard Henderson case EXCP_INTERRUPT: 2652a0adc417SRichard Henderson /* We processed the pending cpu work above. */ 2653d962783eSJia Liu break; 2654a0adc417SRichard Henderson case EXCP_DEBUG: 2655a0adc417SRichard Henderson trapnr = gdb_handlesig(cs, TARGET_SIGTRAP); 2656a0adc417SRichard Henderson if (trapnr) { 2657a0adc417SRichard Henderson info.si_signo = trapnr; 2658a0adc417SRichard Henderson info.si_errno = 0; 2659a0adc417SRichard Henderson info.si_code = TARGET_TRAP_BRKPT; 2660a0adc417SRichard Henderson queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 2661a0adc417SRichard Henderson } 2662d962783eSJia Liu break; 2663fdbc2b57SRichard Henderson case EXCP_ATOMIC: 2664fdbc2b57SRichard Henderson cpu_exec_step_atomic(cs); 2665fdbc2b57SRichard Henderson break; 2666d962783eSJia Liu default: 2667a0adc417SRichard Henderson g_assert_not_reached(); 2668d962783eSJia Liu } 2669d962783eSJia Liu process_pending_signals(env); 2670d962783eSJia Liu } 2671d962783eSJia Liu } 2672d962783eSJia Liu 2673d962783eSJia Liu #endif /* TARGET_OPENRISC */ 2674d962783eSJia Liu 2675fdf9b3e8Sbellard #ifdef TARGET_SH4 267605390248SAndreas Färber void cpu_loop(CPUSH4State *env) 2677fdf9b3e8Sbellard { 2678878096eeSAndreas Färber CPUState *cs = CPU(sh_env_get_cpu(env)); 2679fdf9b3e8Sbellard int trapnr, ret; 2680c227f099SAnthony Liguori target_siginfo_t info; 2681fdf9b3e8Sbellard 2682fdf9b3e8Sbellard while (1) { 2683b040bc9cSPeter Maydell cpu_exec_start(cs); 26848642c1b8SPeter Crosthwaite trapnr = cpu_exec(cs); 2685b040bc9cSPeter Maydell cpu_exec_end(cs); 2686d148d90eSSergey Fedorov process_queued_cpu_work(cs); 2687fdf9b3e8Sbellard 2688fdf9b3e8Sbellard switch (trapnr) { 2689fdf9b3e8Sbellard case 0x160: 26900b6d3ae0Saurel32 env->pc += 2; 2691fdf9b3e8Sbellard ret = do_syscall(env, 26929c2a9ea1Spbrook env->gregs[3], 26939c2a9ea1Spbrook env->gregs[4], 26949c2a9ea1Spbrook env->gregs[5], 26959c2a9ea1Spbrook env->gregs[6], 26969c2a9ea1Spbrook env->gregs[7], 26979c2a9ea1Spbrook env->gregs[0], 26985945cfcbSPeter Maydell env->gregs[1], 26995945cfcbSPeter Maydell 0, 0); 2700ba412496STimothy E Baldwin if (ret == -TARGET_ERESTARTSYS) { 2701ba412496STimothy E Baldwin env->pc -= 2; 2702ba412496STimothy E Baldwin } else if (ret != -TARGET_QEMU_ESIGRETURN) { 27039c2a9ea1Spbrook env->gregs[0] = ret; 2704ba412496STimothy E Baldwin } 2705fdf9b3e8Sbellard break; 2706c3b5bc8aSths case EXCP_INTERRUPT: 2707c3b5bc8aSths /* just indicate that signals should be handled asap */ 2708c3b5bc8aSths break; 2709355fb23dSpbrook case EXCP_DEBUG: 2710355fb23dSpbrook { 2711355fb23dSpbrook int sig; 2712355fb23dSpbrook 2713db6b81d4SAndreas Färber sig = gdb_handlesig(cs, TARGET_SIGTRAP); 2714355fb23dSpbrook if (sig) 2715355fb23dSpbrook { 2716355fb23dSpbrook info.si_signo = sig; 2717355fb23dSpbrook info.si_errno = 0; 2718355fb23dSpbrook info.si_code = TARGET_TRAP_BRKPT; 27199d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 2720355fb23dSpbrook } 2721355fb23dSpbrook } 2722355fb23dSpbrook break; 2723c3b5bc8aSths case 0xa0: 2724c3b5bc8aSths case 0xc0: 2725a86b3c64SChen Gang S info.si_signo = TARGET_SIGSEGV; 2726c3b5bc8aSths info.si_errno = 0; 2727c3b5bc8aSths info.si_code = TARGET_SEGV_MAPERR; 2728c3b5bc8aSths info._sifields._sigfault._addr = env->tea; 27299d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 2730c3b5bc8aSths break; 2731c3b5bc8aSths 2732fdbc2b57SRichard Henderson case EXCP_ATOMIC: 2733fdbc2b57SRichard Henderson cpu_exec_step_atomic(cs); 2734fdbc2b57SRichard Henderson break; 2735fdf9b3e8Sbellard default: 2736fdf9b3e8Sbellard printf ("Unhandled trap: 0x%x\n", trapnr); 2737878096eeSAndreas Färber cpu_dump_state(cs, stderr, fprintf, 0); 27384d1275c2SRiku Voipio exit(EXIT_FAILURE); 2739fdf9b3e8Sbellard } 2740fdf9b3e8Sbellard process_pending_signals (env); 2741fdf9b3e8Sbellard } 2742fdf9b3e8Sbellard } 2743fdf9b3e8Sbellard #endif 2744fdf9b3e8Sbellard 274548733d19Sths #ifdef TARGET_CRIS 274605390248SAndreas Färber void cpu_loop(CPUCRISState *env) 274748733d19Sths { 2748878096eeSAndreas Färber CPUState *cs = CPU(cris_env_get_cpu(env)); 274948733d19Sths int trapnr, ret; 2750c227f099SAnthony Liguori target_siginfo_t info; 275148733d19Sths 275248733d19Sths while (1) { 2753b040bc9cSPeter Maydell cpu_exec_start(cs); 27548642c1b8SPeter Crosthwaite trapnr = cpu_exec(cs); 2755b040bc9cSPeter Maydell cpu_exec_end(cs); 2756d148d90eSSergey Fedorov process_queued_cpu_work(cs); 2757d148d90eSSergey Fedorov 275848733d19Sths switch (trapnr) { 275948733d19Sths case 0xaa: 276048733d19Sths { 2761a86b3c64SChen Gang S info.si_signo = TARGET_SIGSEGV; 276248733d19Sths info.si_errno = 0; 276348733d19Sths /* XXX: check env->error_code */ 276448733d19Sths info.si_code = TARGET_SEGV_MAPERR; 2765e00c1e71Sedgar_igl info._sifields._sigfault._addr = env->pregs[PR_EDA]; 27669d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 276748733d19Sths } 276848733d19Sths break; 2769b6d3abdaSedgar_igl case EXCP_INTERRUPT: 2770b6d3abdaSedgar_igl /* just indicate that signals should be handled asap */ 2771b6d3abdaSedgar_igl break; 277248733d19Sths case EXCP_BREAK: 277348733d19Sths ret = do_syscall(env, 277448733d19Sths env->regs[9], 277548733d19Sths env->regs[10], 277648733d19Sths env->regs[11], 277748733d19Sths env->regs[12], 277848733d19Sths env->regs[13], 277948733d19Sths env->pregs[7], 27805945cfcbSPeter Maydell env->pregs[11], 27815945cfcbSPeter Maydell 0, 0); 278262050865STimothy E Baldwin if (ret == -TARGET_ERESTARTSYS) { 278362050865STimothy E Baldwin env->pc -= 2; 278462050865STimothy E Baldwin } else if (ret != -TARGET_QEMU_ESIGRETURN) { 278548733d19Sths env->regs[10] = ret; 278662050865STimothy E Baldwin } 278748733d19Sths break; 278848733d19Sths case EXCP_DEBUG: 278948733d19Sths { 279048733d19Sths int sig; 279148733d19Sths 2792db6b81d4SAndreas Färber sig = gdb_handlesig(cs, TARGET_SIGTRAP); 279348733d19Sths if (sig) 279448733d19Sths { 279548733d19Sths info.si_signo = sig; 279648733d19Sths info.si_errno = 0; 279748733d19Sths info.si_code = TARGET_TRAP_BRKPT; 27989d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 279948733d19Sths } 280048733d19Sths } 280148733d19Sths break; 2802fdbc2b57SRichard Henderson case EXCP_ATOMIC: 2803fdbc2b57SRichard Henderson cpu_exec_step_atomic(cs); 2804fdbc2b57SRichard Henderson break; 280548733d19Sths default: 280648733d19Sths printf ("Unhandled trap: 0x%x\n", trapnr); 2807878096eeSAndreas Färber cpu_dump_state(cs, stderr, fprintf, 0); 28084d1275c2SRiku Voipio exit(EXIT_FAILURE); 280948733d19Sths } 281048733d19Sths process_pending_signals (env); 281148733d19Sths } 281248733d19Sths } 281348733d19Sths #endif 281448733d19Sths 2815b779e29eSEdgar E. Iglesias #ifdef TARGET_MICROBLAZE 281605390248SAndreas Färber void cpu_loop(CPUMBState *env) 2817b779e29eSEdgar E. Iglesias { 2818878096eeSAndreas Färber CPUState *cs = CPU(mb_env_get_cpu(env)); 2819b779e29eSEdgar E. Iglesias int trapnr, ret; 2820c227f099SAnthony Liguori target_siginfo_t info; 2821b779e29eSEdgar E. Iglesias 2822b779e29eSEdgar E. Iglesias while (1) { 2823b040bc9cSPeter Maydell cpu_exec_start(cs); 28248642c1b8SPeter Crosthwaite trapnr = cpu_exec(cs); 2825b040bc9cSPeter Maydell cpu_exec_end(cs); 2826d148d90eSSergey Fedorov process_queued_cpu_work(cs); 2827d148d90eSSergey Fedorov 2828b779e29eSEdgar E. Iglesias switch (trapnr) { 2829b779e29eSEdgar E. Iglesias case 0xaa: 2830b779e29eSEdgar E. Iglesias { 2831a86b3c64SChen Gang S info.si_signo = TARGET_SIGSEGV; 2832b779e29eSEdgar E. Iglesias info.si_errno = 0; 2833b779e29eSEdgar E. Iglesias /* XXX: check env->error_code */ 2834b779e29eSEdgar E. Iglesias info.si_code = TARGET_SEGV_MAPERR; 2835b779e29eSEdgar E. Iglesias info._sifields._sigfault._addr = 0; 28369d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 2837b779e29eSEdgar E. Iglesias } 2838b779e29eSEdgar E. Iglesias break; 2839b779e29eSEdgar E. Iglesias case EXCP_INTERRUPT: 2840b779e29eSEdgar E. Iglesias /* just indicate that signals should be handled asap */ 2841b779e29eSEdgar E. Iglesias break; 2842b779e29eSEdgar E. Iglesias case EXCP_BREAK: 2843b779e29eSEdgar E. Iglesias /* Return address is 4 bytes after the call. */ 2844b779e29eSEdgar E. Iglesias env->regs[14] += 4; 2845d7dce494SEdgar E. Iglesias env->sregs[SR_PC] = env->regs[14]; 2846b779e29eSEdgar E. Iglesias ret = do_syscall(env, 2847b779e29eSEdgar E. Iglesias env->regs[12], 2848b779e29eSEdgar E. Iglesias env->regs[5], 2849b779e29eSEdgar E. Iglesias env->regs[6], 2850b779e29eSEdgar E. Iglesias env->regs[7], 2851b779e29eSEdgar E. Iglesias env->regs[8], 2852b779e29eSEdgar E. Iglesias env->regs[9], 28535945cfcbSPeter Maydell env->regs[10], 28545945cfcbSPeter Maydell 0, 0); 28554134ecfeSTimothy E Baldwin if (ret == -TARGET_ERESTARTSYS) { 28564134ecfeSTimothy E Baldwin /* Wind back to before the syscall. */ 28574134ecfeSTimothy E Baldwin env->sregs[SR_PC] -= 4; 28584134ecfeSTimothy E Baldwin } else if (ret != -TARGET_QEMU_ESIGRETURN) { 2859b779e29eSEdgar E. Iglesias env->regs[3] = ret; 28604134ecfeSTimothy E Baldwin } 2861d7749ab7SPeter Maydell /* All syscall exits result in guest r14 being equal to the 2862d7749ab7SPeter Maydell * PC we return to, because the kernel syscall exit "rtbd" does 2863d7749ab7SPeter Maydell * this. (This is true even for sigreturn(); note that r14 is 2864d7749ab7SPeter Maydell * not a userspace-usable register, as the kernel may clobber it 2865d7749ab7SPeter Maydell * at any point.) 2866d7749ab7SPeter Maydell */ 2867d7749ab7SPeter Maydell env->regs[14] = env->sregs[SR_PC]; 2868b779e29eSEdgar E. Iglesias break; 2869b76da7e3SEdgar E. Iglesias case EXCP_HW_EXCP: 2870b76da7e3SEdgar E. Iglesias env->regs[17] = env->sregs[SR_PC] + 4; 2871b76da7e3SEdgar E. Iglesias if (env->iflags & D_FLAG) { 2872b76da7e3SEdgar E. Iglesias env->sregs[SR_ESR] |= 1 << 12; 2873b76da7e3SEdgar E. Iglesias env->sregs[SR_PC] -= 4; 2874b76da7e3SEdgar E. Iglesias /* FIXME: if branch was immed, replay the imm as well. */ 2875b76da7e3SEdgar E. Iglesias } 2876b76da7e3SEdgar E. Iglesias 2877b76da7e3SEdgar E. Iglesias env->iflags &= ~(IMM_FLAG | D_FLAG); 2878b76da7e3SEdgar E. Iglesias 2879b76da7e3SEdgar E. Iglesias switch (env->sregs[SR_ESR] & 31) { 288022a78d64SEdgar E. Iglesias case ESR_EC_DIVZERO: 2881a86b3c64SChen Gang S info.si_signo = TARGET_SIGFPE; 288222a78d64SEdgar E. Iglesias info.si_errno = 0; 288322a78d64SEdgar E. Iglesias info.si_code = TARGET_FPE_FLTDIV; 288422a78d64SEdgar E. Iglesias info._sifields._sigfault._addr = 0; 28859d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 288622a78d64SEdgar E. Iglesias break; 2887b76da7e3SEdgar E. Iglesias case ESR_EC_FPU: 2888a86b3c64SChen Gang S info.si_signo = TARGET_SIGFPE; 2889b76da7e3SEdgar E. Iglesias info.si_errno = 0; 2890b76da7e3SEdgar E. Iglesias if (env->sregs[SR_FSR] & FSR_IO) { 2891b76da7e3SEdgar E. Iglesias info.si_code = TARGET_FPE_FLTINV; 2892b76da7e3SEdgar E. Iglesias } 2893b76da7e3SEdgar E. Iglesias if (env->sregs[SR_FSR] & FSR_DZ) { 2894b76da7e3SEdgar E. Iglesias info.si_code = TARGET_FPE_FLTDIV; 2895b76da7e3SEdgar E. Iglesias } 2896b76da7e3SEdgar E. Iglesias info._sifields._sigfault._addr = 0; 28979d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 2898b76da7e3SEdgar E. Iglesias break; 2899b76da7e3SEdgar E. Iglesias default: 2900b76da7e3SEdgar E. Iglesias printf ("Unhandled hw-exception: 0x%x\n", 29012e42d52dSEdgar E. Iglesias env->sregs[SR_ESR] & ESR_EC_MASK); 2902878096eeSAndreas Färber cpu_dump_state(cs, stderr, fprintf, 0); 29034d1275c2SRiku Voipio exit(EXIT_FAILURE); 2904b76da7e3SEdgar E. Iglesias break; 2905b76da7e3SEdgar E. Iglesias } 2906b76da7e3SEdgar E. Iglesias break; 2907b779e29eSEdgar E. Iglesias case EXCP_DEBUG: 2908b779e29eSEdgar E. Iglesias { 2909b779e29eSEdgar E. Iglesias int sig; 2910b779e29eSEdgar E. Iglesias 2911db6b81d4SAndreas Färber sig = gdb_handlesig(cs, TARGET_SIGTRAP); 2912b779e29eSEdgar E. Iglesias if (sig) 2913b779e29eSEdgar E. Iglesias { 2914b779e29eSEdgar E. Iglesias info.si_signo = sig; 2915b779e29eSEdgar E. Iglesias info.si_errno = 0; 2916b779e29eSEdgar E. Iglesias info.si_code = TARGET_TRAP_BRKPT; 29179d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 2918b779e29eSEdgar E. Iglesias } 2919b779e29eSEdgar E. Iglesias } 2920b779e29eSEdgar E. Iglesias break; 2921fdbc2b57SRichard Henderson case EXCP_ATOMIC: 2922fdbc2b57SRichard Henderson cpu_exec_step_atomic(cs); 2923fdbc2b57SRichard Henderson break; 2924b779e29eSEdgar E. Iglesias default: 2925b779e29eSEdgar E. Iglesias printf ("Unhandled trap: 0x%x\n", trapnr); 2926878096eeSAndreas Färber cpu_dump_state(cs, stderr, fprintf, 0); 29274d1275c2SRiku Voipio exit(EXIT_FAILURE); 2928b779e29eSEdgar E. Iglesias } 2929b779e29eSEdgar E. Iglesias process_pending_signals (env); 2930b779e29eSEdgar E. Iglesias } 2931b779e29eSEdgar E. Iglesias } 2932b779e29eSEdgar E. Iglesias #endif 2933b779e29eSEdgar E. Iglesias 2934e6e5906bSpbrook #ifdef TARGET_M68K 2935e6e5906bSpbrook 2936e6e5906bSpbrook void cpu_loop(CPUM68KState *env) 2937e6e5906bSpbrook { 2938878096eeSAndreas Färber CPUState *cs = CPU(m68k_env_get_cpu(env)); 2939e6e5906bSpbrook int trapnr; 2940e6e5906bSpbrook unsigned int n; 2941c227f099SAnthony Liguori target_siginfo_t info; 29420429a971SAndreas Färber TaskState *ts = cs->opaque; 2943e6e5906bSpbrook 2944e6e5906bSpbrook for(;;) { 2945b040bc9cSPeter Maydell cpu_exec_start(cs); 29468642c1b8SPeter Crosthwaite trapnr = cpu_exec(cs); 2947b040bc9cSPeter Maydell cpu_exec_end(cs); 2948d148d90eSSergey Fedorov process_queued_cpu_work(cs); 2949d148d90eSSergey Fedorov 2950e6e5906bSpbrook switch(trapnr) { 2951e6e5906bSpbrook case EXCP_ILLEGAL: 2952e6e5906bSpbrook { 2953e6e5906bSpbrook if (ts->sim_syscalls) { 2954e6e5906bSpbrook uint16_t nr; 2955d8d5119cSPeter Maydell get_user_u16(nr, env->pc + 2); 2956e6e5906bSpbrook env->pc += 4; 2957e6e5906bSpbrook do_m68k_simcall(env, nr); 2958e6e5906bSpbrook } else { 2959e6e5906bSpbrook goto do_sigill; 2960e6e5906bSpbrook } 2961e6e5906bSpbrook } 2962e6e5906bSpbrook break; 2963a87295e8Spbrook case EXCP_HALT_INSN: 2964e6e5906bSpbrook /* Semihosing syscall. */ 2965a87295e8Spbrook env->pc += 4; 2966e6e5906bSpbrook do_m68k_semihosting(env, env->dregs[0]); 2967e6e5906bSpbrook break; 2968e6e5906bSpbrook case EXCP_LINEA: 2969e6e5906bSpbrook case EXCP_LINEF: 2970e6e5906bSpbrook case EXCP_UNSUPPORTED: 2971e6e5906bSpbrook do_sigill: 2972a86b3c64SChen Gang S info.si_signo = TARGET_SIGILL; 2973e6e5906bSpbrook info.si_errno = 0; 2974e6e5906bSpbrook info.si_code = TARGET_ILL_ILLOPN; 2975e6e5906bSpbrook info._sifields._sigfault._addr = env->pc; 29769d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 2977e6e5906bSpbrook break; 29780ccb9c1dSLaurent Vivier case EXCP_DIV0: 29790ccb9c1dSLaurent Vivier info.si_signo = TARGET_SIGFPE; 29800ccb9c1dSLaurent Vivier info.si_errno = 0; 29810ccb9c1dSLaurent Vivier info.si_code = TARGET_FPE_INTDIV; 29820ccb9c1dSLaurent Vivier info._sifields._sigfault._addr = env->pc; 29830ccb9c1dSLaurent Vivier queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 29840ccb9c1dSLaurent Vivier break; 2985e6e5906bSpbrook case EXCP_TRAP0: 2986e6e5906bSpbrook { 29877ccb84a9STimothy E Baldwin abi_long ret; 2988e6e5906bSpbrook ts->sim_syscalls = 0; 2989e6e5906bSpbrook n = env->dregs[0]; 2990e6e5906bSpbrook env->pc += 2; 29917ccb84a9STimothy E Baldwin ret = do_syscall(env, 2992e6e5906bSpbrook n, 2993e6e5906bSpbrook env->dregs[1], 2994e6e5906bSpbrook env->dregs[2], 2995e6e5906bSpbrook env->dregs[3], 2996e6e5906bSpbrook env->dregs[4], 2997e6e5906bSpbrook env->dregs[5], 29985945cfcbSPeter Maydell env->aregs[0], 29995945cfcbSPeter Maydell 0, 0); 30007ccb84a9STimothy E Baldwin if (ret == -TARGET_ERESTARTSYS) { 30017ccb84a9STimothy E Baldwin env->pc -= 2; 30027ccb84a9STimothy E Baldwin } else if (ret != -TARGET_QEMU_ESIGRETURN) { 30037ccb84a9STimothy E Baldwin env->dregs[0] = ret; 30047ccb84a9STimothy E Baldwin } 3005e6e5906bSpbrook } 3006e6e5906bSpbrook break; 3007e6e5906bSpbrook case EXCP_INTERRUPT: 3008e6e5906bSpbrook /* just indicate that signals should be handled asap */ 3009e6e5906bSpbrook break; 3010e6e5906bSpbrook case EXCP_ACCESS: 3011e6e5906bSpbrook { 3012a86b3c64SChen Gang S info.si_signo = TARGET_SIGSEGV; 3013e6e5906bSpbrook info.si_errno = 0; 3014e6e5906bSpbrook /* XXX: check env->error_code */ 3015e6e5906bSpbrook info.si_code = TARGET_SEGV_MAPERR; 3016e6e5906bSpbrook info._sifields._sigfault._addr = env->mmu.ar; 30179d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 3018e6e5906bSpbrook } 3019e6e5906bSpbrook break; 3020e6e5906bSpbrook case EXCP_DEBUG: 3021e6e5906bSpbrook { 3022e6e5906bSpbrook int sig; 3023e6e5906bSpbrook 3024db6b81d4SAndreas Färber sig = gdb_handlesig(cs, TARGET_SIGTRAP); 3025e6e5906bSpbrook if (sig) 3026e6e5906bSpbrook { 3027e6e5906bSpbrook info.si_signo = sig; 3028e6e5906bSpbrook info.si_errno = 0; 3029e6e5906bSpbrook info.si_code = TARGET_TRAP_BRKPT; 30309d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 3031e6e5906bSpbrook } 3032e6e5906bSpbrook } 3033e6e5906bSpbrook break; 3034fdbc2b57SRichard Henderson case EXCP_ATOMIC: 3035fdbc2b57SRichard Henderson cpu_exec_step_atomic(cs); 3036fdbc2b57SRichard Henderson break; 3037e6e5906bSpbrook default: 3038120a9848SPaolo Bonzini EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr); 3039e6e5906bSpbrook abort(); 3040e6e5906bSpbrook } 3041e6e5906bSpbrook process_pending_signals(env); 3042e6e5906bSpbrook } 3043e6e5906bSpbrook } 3044e6e5906bSpbrook #endif /* TARGET_M68K */ 3045e6e5906bSpbrook 30467a3148a9Sj_mayer #ifdef TARGET_ALPHA 304705390248SAndreas Färber void cpu_loop(CPUAlphaState *env) 30487a3148a9Sj_mayer { 3049878096eeSAndreas Färber CPUState *cs = CPU(alpha_env_get_cpu(env)); 3050e96efcfcSj_mayer int trapnr; 3051c227f099SAnthony Liguori target_siginfo_t info; 30526049f4f8SRichard Henderson abi_long sysret; 30537a3148a9Sj_mayer 30547a3148a9Sj_mayer while (1) { 3055bcd2625dSRichard Henderson bool arch_interrupt = true; 3056bcd2625dSRichard Henderson 3057b040bc9cSPeter Maydell cpu_exec_start(cs); 30588642c1b8SPeter Crosthwaite trapnr = cpu_exec(cs); 3059b040bc9cSPeter Maydell cpu_exec_end(cs); 3060d148d90eSSergey Fedorov process_queued_cpu_work(cs); 30617a3148a9Sj_mayer 30627a3148a9Sj_mayer switch (trapnr) { 30637a3148a9Sj_mayer case EXCP_RESET: 30647a3148a9Sj_mayer fprintf(stderr, "Reset requested. Exit\n"); 30654d1275c2SRiku Voipio exit(EXIT_FAILURE); 30667a3148a9Sj_mayer break; 30677a3148a9Sj_mayer case EXCP_MCHK: 30687a3148a9Sj_mayer fprintf(stderr, "Machine check exception. Exit\n"); 30694d1275c2SRiku Voipio exit(EXIT_FAILURE); 30707a3148a9Sj_mayer break; 307107b6c13bSRichard Henderson case EXCP_SMP_INTERRUPT: 307207b6c13bSRichard Henderson case EXCP_CLK_INTERRUPT: 307307b6c13bSRichard Henderson case EXCP_DEV_INTERRUPT: 30747a3148a9Sj_mayer fprintf(stderr, "External interrupt. Exit\n"); 30754d1275c2SRiku Voipio exit(EXIT_FAILURE); 30767a3148a9Sj_mayer break; 307707b6c13bSRichard Henderson case EXCP_MMFAULT: 30786049f4f8SRichard Henderson info.si_signo = TARGET_SIGSEGV; 30796049f4f8SRichard Henderson info.si_errno = 0; 3080129d8aa5SRichard Henderson info.si_code = (page_get_flags(env->trap_arg0) & PAGE_VALID 30810be1d07cSRichard Henderson ? TARGET_SEGV_ACCERR : TARGET_SEGV_MAPERR); 3082129d8aa5SRichard Henderson info._sifields._sigfault._addr = env->trap_arg0; 30839d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 30847a3148a9Sj_mayer break; 30857a3148a9Sj_mayer case EXCP_UNALIGN: 30866049f4f8SRichard Henderson info.si_signo = TARGET_SIGBUS; 30876049f4f8SRichard Henderson info.si_errno = 0; 30886049f4f8SRichard Henderson info.si_code = TARGET_BUS_ADRALN; 3089129d8aa5SRichard Henderson info._sifields._sigfault._addr = env->trap_arg0; 30909d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 30917a3148a9Sj_mayer break; 30927a3148a9Sj_mayer case EXCP_OPCDEC: 30936049f4f8SRichard Henderson do_sigill: 30946049f4f8SRichard Henderson info.si_signo = TARGET_SIGILL; 30956049f4f8SRichard Henderson info.si_errno = 0; 30966049f4f8SRichard Henderson info.si_code = TARGET_ILL_ILLOPC; 30976049f4f8SRichard Henderson info._sifields._sigfault._addr = env->pc; 30989d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 30997a3148a9Sj_mayer break; 310007b6c13bSRichard Henderson case EXCP_ARITH: 310107b6c13bSRichard Henderson info.si_signo = TARGET_SIGFPE; 310207b6c13bSRichard Henderson info.si_errno = 0; 310307b6c13bSRichard Henderson info.si_code = TARGET_FPE_FLTINV; 310407b6c13bSRichard Henderson info._sifields._sigfault._addr = env->pc; 31059d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 310607b6c13bSRichard Henderson break; 31077a3148a9Sj_mayer case EXCP_FEN: 31086049f4f8SRichard Henderson /* No-op. Linux simply re-enables the FPU. */ 31097a3148a9Sj_mayer break; 311007b6c13bSRichard Henderson case EXCP_CALL_PAL: 311107b6c13bSRichard Henderson switch (env->error_code) { 31126049f4f8SRichard Henderson case 0x80: 31136049f4f8SRichard Henderson /* BPT */ 31146049f4f8SRichard Henderson info.si_signo = TARGET_SIGTRAP; 31156049f4f8SRichard Henderson info.si_errno = 0; 31166049f4f8SRichard Henderson info.si_code = TARGET_TRAP_BRKPT; 31176049f4f8SRichard Henderson info._sifields._sigfault._addr = env->pc; 31189d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 31196049f4f8SRichard Henderson break; 31206049f4f8SRichard Henderson case 0x81: 31216049f4f8SRichard Henderson /* BUGCHK */ 31226049f4f8SRichard Henderson info.si_signo = TARGET_SIGTRAP; 31236049f4f8SRichard Henderson info.si_errno = 0; 31246049f4f8SRichard Henderson info.si_code = 0; 31256049f4f8SRichard Henderson info._sifields._sigfault._addr = env->pc; 31269d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 31276049f4f8SRichard Henderson break; 31286049f4f8SRichard Henderson case 0x83: 31296049f4f8SRichard Henderson /* CALLSYS */ 31306049f4f8SRichard Henderson trapnr = env->ir[IR_V0]; 31316049f4f8SRichard Henderson sysret = do_syscall(env, trapnr, 31326049f4f8SRichard Henderson env->ir[IR_A0], env->ir[IR_A1], 31336049f4f8SRichard Henderson env->ir[IR_A2], env->ir[IR_A3], 31345945cfcbSPeter Maydell env->ir[IR_A4], env->ir[IR_A5], 31355945cfcbSPeter Maydell 0, 0); 3136338c858cSTimothy E Baldwin if (sysret == -TARGET_ERESTARTSYS) { 3137338c858cSTimothy E Baldwin env->pc -= 4; 3138338c858cSTimothy E Baldwin break; 3139338c858cSTimothy E Baldwin } 3140338c858cSTimothy E Baldwin if (sysret == -TARGET_QEMU_ESIGRETURN) { 3141a5b3b13bSRichard Henderson break; 3142a5b3b13bSRichard Henderson } 3143a5b3b13bSRichard Henderson /* Syscall writes 0 to V0 to bypass error check, similar 31440e141977SRichard Henderson to how this is handled internal to Linux kernel. 31450e141977SRichard Henderson (Ab)use trapnr temporarily as boolean indicating error. */ 31460e141977SRichard Henderson trapnr = (env->ir[IR_V0] != 0 && sysret < 0); 31470e141977SRichard Henderson env->ir[IR_V0] = (trapnr ? -sysret : sysret); 31480e141977SRichard Henderson env->ir[IR_A3] = trapnr; 31496049f4f8SRichard Henderson break; 31506049f4f8SRichard Henderson case 0x86: 31516049f4f8SRichard Henderson /* IMB */ 31526049f4f8SRichard Henderson /* ??? We can probably elide the code using page_unprotect 31536049f4f8SRichard Henderson that is checking for self-modifying code. Instead we 31546049f4f8SRichard Henderson could simply call tb_flush here. Until we work out the 31556049f4f8SRichard Henderson changes required to turn off the extra write protection, 31566049f4f8SRichard Henderson this can be a no-op. */ 31576049f4f8SRichard Henderson break; 31586049f4f8SRichard Henderson case 0x9E: 31596049f4f8SRichard Henderson /* RDUNIQUE */ 31606049f4f8SRichard Henderson /* Handled in the translator for usermode. */ 31616049f4f8SRichard Henderson abort(); 31626049f4f8SRichard Henderson case 0x9F: 31636049f4f8SRichard Henderson /* WRUNIQUE */ 31646049f4f8SRichard Henderson /* Handled in the translator for usermode. */ 31656049f4f8SRichard Henderson abort(); 31666049f4f8SRichard Henderson case 0xAA: 31676049f4f8SRichard Henderson /* GENTRAP */ 31686049f4f8SRichard Henderson info.si_signo = TARGET_SIGFPE; 31696049f4f8SRichard Henderson switch (env->ir[IR_A0]) { 31706049f4f8SRichard Henderson case TARGET_GEN_INTOVF: 31716049f4f8SRichard Henderson info.si_code = TARGET_FPE_INTOVF; 31726049f4f8SRichard Henderson break; 31736049f4f8SRichard Henderson case TARGET_GEN_INTDIV: 31746049f4f8SRichard Henderson info.si_code = TARGET_FPE_INTDIV; 31756049f4f8SRichard Henderson break; 31766049f4f8SRichard Henderson case TARGET_GEN_FLTOVF: 31776049f4f8SRichard Henderson info.si_code = TARGET_FPE_FLTOVF; 31786049f4f8SRichard Henderson break; 31796049f4f8SRichard Henderson case TARGET_GEN_FLTUND: 31806049f4f8SRichard Henderson info.si_code = TARGET_FPE_FLTUND; 31816049f4f8SRichard Henderson break; 31826049f4f8SRichard Henderson case TARGET_GEN_FLTINV: 31836049f4f8SRichard Henderson info.si_code = TARGET_FPE_FLTINV; 31846049f4f8SRichard Henderson break; 31856049f4f8SRichard Henderson case TARGET_GEN_FLTINE: 31866049f4f8SRichard Henderson info.si_code = TARGET_FPE_FLTRES; 31876049f4f8SRichard Henderson break; 31886049f4f8SRichard Henderson case TARGET_GEN_ROPRAND: 31896049f4f8SRichard Henderson info.si_code = 0; 31906049f4f8SRichard Henderson break; 31916049f4f8SRichard Henderson default: 31926049f4f8SRichard Henderson info.si_signo = TARGET_SIGTRAP; 31936049f4f8SRichard Henderson info.si_code = 0; 31946049f4f8SRichard Henderson break; 31956049f4f8SRichard Henderson } 31966049f4f8SRichard Henderson info.si_errno = 0; 31976049f4f8SRichard Henderson info._sifields._sigfault._addr = env->pc; 31989d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 31996049f4f8SRichard Henderson break; 32006049f4f8SRichard Henderson default: 32016049f4f8SRichard Henderson goto do_sigill; 32026049f4f8SRichard Henderson } 32037a3148a9Sj_mayer break; 32047a3148a9Sj_mayer case EXCP_DEBUG: 3205db6b81d4SAndreas Färber info.si_signo = gdb_handlesig(cs, TARGET_SIGTRAP); 32066049f4f8SRichard Henderson if (info.si_signo) { 32077a3148a9Sj_mayer info.si_errno = 0; 32087a3148a9Sj_mayer info.si_code = TARGET_TRAP_BRKPT; 32099d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 3210bcd2625dSRichard Henderson } else { 3211bcd2625dSRichard Henderson arch_interrupt = false; 32127a3148a9Sj_mayer } 32137a3148a9Sj_mayer break; 3214d0f20495SRichard Henderson case EXCP_INTERRUPT: 3215d0f20495SRichard Henderson /* Just indicate that signals should be handled asap. */ 3216d0f20495SRichard Henderson break; 3217fdbc2b57SRichard Henderson case EXCP_ATOMIC: 3218fdbc2b57SRichard Henderson cpu_exec_step_atomic(cs); 3219bcd2625dSRichard Henderson arch_interrupt = false; 3220fdbc2b57SRichard Henderson break; 32217a3148a9Sj_mayer default: 32227a3148a9Sj_mayer printf ("Unhandled trap: 0x%x\n", trapnr); 3223878096eeSAndreas Färber cpu_dump_state(cs, stderr, fprintf, 0); 32244d1275c2SRiku Voipio exit(EXIT_FAILURE); 32257a3148a9Sj_mayer } 32267a3148a9Sj_mayer process_pending_signals (env); 3227bcd2625dSRichard Henderson 3228bcd2625dSRichard Henderson /* Most of the traps imply a transition through PALcode, which 3229bcd2625dSRichard Henderson implies an REI instruction has been executed. Which means 3230bcd2625dSRichard Henderson that RX and LOCK_ADDR should be cleared. But there are a 3231bcd2625dSRichard Henderson few exceptions for traps internal to QEMU. */ 3232bcd2625dSRichard Henderson if (arch_interrupt) { 3233bcd2625dSRichard Henderson env->flags &= ~ENV_FLAG_RX_FLAG; 3234bcd2625dSRichard Henderson env->lock_addr = -1; 3235bcd2625dSRichard Henderson } 32367a3148a9Sj_mayer } 32377a3148a9Sj_mayer } 32387a3148a9Sj_mayer #endif /* TARGET_ALPHA */ 32397a3148a9Sj_mayer 3240a4c075f1SUlrich Hecht #ifdef TARGET_S390X 3241a4c075f1SUlrich Hecht void cpu_loop(CPUS390XState *env) 3242a4c075f1SUlrich Hecht { 3243878096eeSAndreas Färber CPUState *cs = CPU(s390_env_get_cpu(env)); 3244d5a103cdSRichard Henderson int trapnr, n, sig; 3245a4c075f1SUlrich Hecht target_siginfo_t info; 3246d5a103cdSRichard Henderson target_ulong addr; 324747405ab6STimothy E Baldwin abi_long ret; 3248a4c075f1SUlrich Hecht 3249a4c075f1SUlrich Hecht while (1) { 3250b040bc9cSPeter Maydell cpu_exec_start(cs); 32518642c1b8SPeter Crosthwaite trapnr = cpu_exec(cs); 3252b040bc9cSPeter Maydell cpu_exec_end(cs); 3253d148d90eSSergey Fedorov process_queued_cpu_work(cs); 3254d148d90eSSergey Fedorov 3255a4c075f1SUlrich Hecht switch (trapnr) { 3256a4c075f1SUlrich Hecht case EXCP_INTERRUPT: 3257d5a103cdSRichard Henderson /* Just indicate that signals should be handled asap. */ 3258a4c075f1SUlrich Hecht break; 3259a4c075f1SUlrich Hecht 3260a4c075f1SUlrich Hecht case EXCP_SVC: 3261d5a103cdSRichard Henderson n = env->int_svc_code; 3262a4c075f1SUlrich Hecht if (!n) { 3263a4c075f1SUlrich Hecht /* syscalls > 255 */ 3264a4c075f1SUlrich Hecht n = env->regs[1]; 3265a4c075f1SUlrich Hecht } 3266d5a103cdSRichard Henderson env->psw.addr += env->int_svc_ilen; 326747405ab6STimothy E Baldwin ret = do_syscall(env, n, env->regs[2], env->regs[3], 3268d5a103cdSRichard Henderson env->regs[4], env->regs[5], 3269d5a103cdSRichard Henderson env->regs[6], env->regs[7], 0, 0); 327047405ab6STimothy E Baldwin if (ret == -TARGET_ERESTARTSYS) { 327147405ab6STimothy E Baldwin env->psw.addr -= env->int_svc_ilen; 327247405ab6STimothy E Baldwin } else if (ret != -TARGET_QEMU_ESIGRETURN) { 327347405ab6STimothy E Baldwin env->regs[2] = ret; 327447405ab6STimothy E Baldwin } 3275d5a103cdSRichard Henderson break; 3276d5a103cdSRichard Henderson 3277d5a103cdSRichard Henderson case EXCP_DEBUG: 3278db6b81d4SAndreas Färber sig = gdb_handlesig(cs, TARGET_SIGTRAP); 3279d5a103cdSRichard Henderson if (sig) { 3280d5a103cdSRichard Henderson n = TARGET_TRAP_BRKPT; 3281d5a103cdSRichard Henderson goto do_signal_pc; 3282a4c075f1SUlrich Hecht } 3283a4c075f1SUlrich Hecht break; 3284d5a103cdSRichard Henderson case EXCP_PGM: 3285d5a103cdSRichard Henderson n = env->int_pgm_code; 3286d5a103cdSRichard Henderson switch (n) { 3287d5a103cdSRichard Henderson case PGM_OPERATION: 3288d5a103cdSRichard Henderson case PGM_PRIVILEGED: 3289a86b3c64SChen Gang S sig = TARGET_SIGILL; 3290d5a103cdSRichard Henderson n = TARGET_ILL_ILLOPC; 3291d5a103cdSRichard Henderson goto do_signal_pc; 3292d5a103cdSRichard Henderson case PGM_PROTECTION: 3293d5a103cdSRichard Henderson case PGM_ADDRESSING: 3294a86b3c64SChen Gang S sig = TARGET_SIGSEGV; 3295a4c075f1SUlrich Hecht /* XXX: check env->error_code */ 3296d5a103cdSRichard Henderson n = TARGET_SEGV_MAPERR; 3297d5a103cdSRichard Henderson addr = env->__excp_addr; 3298d5a103cdSRichard Henderson goto do_signal; 3299d5a103cdSRichard Henderson case PGM_EXECUTE: 3300d5a103cdSRichard Henderson case PGM_SPECIFICATION: 3301d5a103cdSRichard Henderson case PGM_SPECIAL_OP: 3302d5a103cdSRichard Henderson case PGM_OPERAND: 3303d5a103cdSRichard Henderson do_sigill_opn: 3304a86b3c64SChen Gang S sig = TARGET_SIGILL; 3305d5a103cdSRichard Henderson n = TARGET_ILL_ILLOPN; 3306d5a103cdSRichard Henderson goto do_signal_pc; 3307d5a103cdSRichard Henderson 3308d5a103cdSRichard Henderson case PGM_FIXPT_OVERFLOW: 3309a86b3c64SChen Gang S sig = TARGET_SIGFPE; 3310d5a103cdSRichard Henderson n = TARGET_FPE_INTOVF; 3311d5a103cdSRichard Henderson goto do_signal_pc; 3312d5a103cdSRichard Henderson case PGM_FIXPT_DIVIDE: 3313a86b3c64SChen Gang S sig = TARGET_SIGFPE; 3314d5a103cdSRichard Henderson n = TARGET_FPE_INTDIV; 3315d5a103cdSRichard Henderson goto do_signal_pc; 3316d5a103cdSRichard Henderson 3317d5a103cdSRichard Henderson case PGM_DATA: 3318d5a103cdSRichard Henderson n = (env->fpc >> 8) & 0xff; 3319d5a103cdSRichard Henderson if (n == 0xff) { 3320d5a103cdSRichard Henderson /* compare-and-trap */ 3321d5a103cdSRichard Henderson goto do_sigill_opn; 3322d5a103cdSRichard Henderson } else { 3323d5a103cdSRichard Henderson /* An IEEE exception, simulated or otherwise. */ 3324d5a103cdSRichard Henderson if (n & 0x80) { 3325d5a103cdSRichard Henderson n = TARGET_FPE_FLTINV; 3326d5a103cdSRichard Henderson } else if (n & 0x40) { 3327d5a103cdSRichard Henderson n = TARGET_FPE_FLTDIV; 3328d5a103cdSRichard Henderson } else if (n & 0x20) { 3329d5a103cdSRichard Henderson n = TARGET_FPE_FLTOVF; 3330d5a103cdSRichard Henderson } else if (n & 0x10) { 3331d5a103cdSRichard Henderson n = TARGET_FPE_FLTUND; 3332d5a103cdSRichard Henderson } else if (n & 0x08) { 3333d5a103cdSRichard Henderson n = TARGET_FPE_FLTRES; 3334d5a103cdSRichard Henderson } else { 3335d5a103cdSRichard Henderson /* ??? Quantum exception; BFP, DFP error. */ 3336d5a103cdSRichard Henderson goto do_sigill_opn; 3337a4c075f1SUlrich Hecht } 3338a86b3c64SChen Gang S sig = TARGET_SIGFPE; 3339d5a103cdSRichard Henderson goto do_signal_pc; 3340a4c075f1SUlrich Hecht } 3341d5a103cdSRichard Henderson 3342a4c075f1SUlrich Hecht default: 3343d5a103cdSRichard Henderson fprintf(stderr, "Unhandled program exception: %#x\n", n); 3344878096eeSAndreas Färber cpu_dump_state(cs, stderr, fprintf, 0); 33454d1275c2SRiku Voipio exit(EXIT_FAILURE); 3346d5a103cdSRichard Henderson } 3347d5a103cdSRichard Henderson break; 3348d5a103cdSRichard Henderson 3349d5a103cdSRichard Henderson do_signal_pc: 3350d5a103cdSRichard Henderson addr = env->psw.addr; 3351d5a103cdSRichard Henderson do_signal: 3352d5a103cdSRichard Henderson info.si_signo = sig; 3353d5a103cdSRichard Henderson info.si_errno = 0; 3354d5a103cdSRichard Henderson info.si_code = n; 3355d5a103cdSRichard Henderson info._sifields._sigfault._addr = addr; 33569d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 3357d5a103cdSRichard Henderson break; 3358d5a103cdSRichard Henderson 3359fdbc2b57SRichard Henderson case EXCP_ATOMIC: 3360fdbc2b57SRichard Henderson cpu_exec_step_atomic(cs); 3361fdbc2b57SRichard Henderson break; 3362d5a103cdSRichard Henderson default: 3363d5a103cdSRichard Henderson fprintf(stderr, "Unhandled trap: 0x%x\n", trapnr); 3364878096eeSAndreas Färber cpu_dump_state(cs, stderr, fprintf, 0); 33654d1275c2SRiku Voipio exit(EXIT_FAILURE); 3366a4c075f1SUlrich Hecht } 3367a4c075f1SUlrich Hecht process_pending_signals (env); 3368a4c075f1SUlrich Hecht } 3369a4c075f1SUlrich Hecht } 3370a4c075f1SUlrich Hecht 3371a4c075f1SUlrich Hecht #endif /* TARGET_S390X */ 3372a4c075f1SUlrich Hecht 3373b16189b2SChen Gang #ifdef TARGET_TILEGX 3374b16189b2SChen Gang 3375b16189b2SChen Gang static void gen_sigill_reg(CPUTLGState *env) 3376b16189b2SChen Gang { 3377b16189b2SChen Gang target_siginfo_t info; 3378b16189b2SChen Gang 3379b16189b2SChen Gang info.si_signo = TARGET_SIGILL; 3380b16189b2SChen Gang info.si_errno = 0; 3381b16189b2SChen Gang info.si_code = TARGET_ILL_PRVREG; 3382b16189b2SChen Gang info._sifields._sigfault._addr = env->pc; 33839d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 3384b16189b2SChen Gang } 3385b16189b2SChen Gang 3386a0577d2aSRichard Henderson static void do_signal(CPUTLGState *env, int signo, int sigcode) 3387dd8070d8SChen Gang { 3388dd8070d8SChen Gang target_siginfo_t info; 3389dd8070d8SChen Gang 3390a0577d2aSRichard Henderson info.si_signo = signo; 3391dd8070d8SChen Gang info.si_errno = 0; 3392dd8070d8SChen Gang info._sifields._sigfault._addr = env->pc; 3393a0577d2aSRichard Henderson 3394a0577d2aSRichard Henderson if (signo == TARGET_SIGSEGV) { 3395a0577d2aSRichard Henderson /* The passed in sigcode is a dummy; check for a page mapping 3396a0577d2aSRichard Henderson and pass either MAPERR or ACCERR. */ 3397a0577d2aSRichard Henderson target_ulong addr = env->excaddr; 3398a0577d2aSRichard Henderson info._sifields._sigfault._addr = addr; 3399a0577d2aSRichard Henderson if (page_check_range(addr, 1, PAGE_VALID) < 0) { 3400a0577d2aSRichard Henderson sigcode = TARGET_SEGV_MAPERR; 3401a0577d2aSRichard Henderson } else { 3402a0577d2aSRichard Henderson sigcode = TARGET_SEGV_ACCERR; 3403a0577d2aSRichard Henderson } 3404a0577d2aSRichard Henderson } 3405a0577d2aSRichard Henderson info.si_code = sigcode; 3406a0577d2aSRichard Henderson 34079d2803f7SPeter Maydell queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 3408dd8070d8SChen Gang } 3409dd8070d8SChen Gang 3410a0577d2aSRichard Henderson static void gen_sigsegv_maperr(CPUTLGState *env, target_ulong addr) 3411a0577d2aSRichard Henderson { 3412a0577d2aSRichard Henderson env->excaddr = addr; 3413a0577d2aSRichard Henderson do_signal(env, TARGET_SIGSEGV, 0); 3414a0577d2aSRichard Henderson } 3415a0577d2aSRichard Henderson 34160583b233SRichard Henderson static void set_regval(CPUTLGState *env, uint8_t reg, uint64_t val) 34170583b233SRichard Henderson { 34180583b233SRichard Henderson if (unlikely(reg >= TILEGX_R_COUNT)) { 34190583b233SRichard Henderson switch (reg) { 34200583b233SRichard Henderson case TILEGX_R_SN: 34210583b233SRichard Henderson case TILEGX_R_ZERO: 34220583b233SRichard Henderson return; 34230583b233SRichard Henderson case TILEGX_R_IDN0: 34240583b233SRichard Henderson case TILEGX_R_IDN1: 34250583b233SRichard Henderson case TILEGX_R_UDN0: 34260583b233SRichard Henderson case TILEGX_R_UDN1: 34270583b233SRichard Henderson case TILEGX_R_UDN2: 34280583b233SRichard Henderson case TILEGX_R_UDN3: 34290583b233SRichard Henderson gen_sigill_reg(env); 34300583b233SRichard Henderson return; 34310583b233SRichard Henderson default: 34320583b233SRichard Henderson g_assert_not_reached(); 34330583b233SRichard Henderson } 34340583b233SRichard Henderson } 34350583b233SRichard Henderson env->regs[reg] = val; 34360583b233SRichard Henderson } 34370583b233SRichard Henderson 34380583b233SRichard Henderson /* 34390583b233SRichard Henderson * Compare the 8-byte contents of the CmpValue SPR with the 8-byte value in 34400583b233SRichard Henderson * memory at the address held in the first source register. If the values are 34410583b233SRichard Henderson * not equal, then no memory operation is performed. If the values are equal, 34420583b233SRichard Henderson * the 8-byte quantity from the second source register is written into memory 34430583b233SRichard Henderson * at the address held in the first source register. In either case, the result 34440583b233SRichard Henderson * of the instruction is the value read from memory. The compare and write to 34450583b233SRichard Henderson * memory are atomic and thus can be used for synchronization purposes. This 34460583b233SRichard Henderson * instruction only operates for addresses aligned to a 8-byte boundary. 34470583b233SRichard Henderson * Unaligned memory access causes an Unaligned Data Reference interrupt. 34480583b233SRichard Henderson * 34490583b233SRichard Henderson * Functional Description (64-bit) 34500583b233SRichard Henderson * uint64_t memVal = memoryReadDoubleWord (rf[SrcA]); 34510583b233SRichard Henderson * rf[Dest] = memVal; 34520583b233SRichard Henderson * if (memVal == SPR[CmpValueSPR]) 34530583b233SRichard Henderson * memoryWriteDoubleWord (rf[SrcA], rf[SrcB]); 34540583b233SRichard Henderson * 34550583b233SRichard Henderson * Functional Description (32-bit) 34560583b233SRichard Henderson * uint64_t memVal = signExtend32 (memoryReadWord (rf[SrcA])); 34570583b233SRichard Henderson * rf[Dest] = memVal; 34580583b233SRichard Henderson * if (memVal == signExtend32 (SPR[CmpValueSPR])) 34590583b233SRichard Henderson * memoryWriteWord (rf[SrcA], rf[SrcB]); 34600583b233SRichard Henderson * 34610583b233SRichard Henderson * 34620583b233SRichard Henderson * This function also processes exch and exch4 which need not process SPR. 34630583b233SRichard Henderson */ 34640583b233SRichard Henderson static void do_exch(CPUTLGState *env, bool quad, bool cmp) 34650583b233SRichard Henderson { 34660583b233SRichard Henderson target_ulong addr; 34670583b233SRichard Henderson target_long val, sprval; 34680583b233SRichard Henderson 34690583b233SRichard Henderson start_exclusive(); 34700583b233SRichard Henderson 34710583b233SRichard Henderson addr = env->atomic_srca; 34720583b233SRichard Henderson if (quad ? get_user_s64(val, addr) : get_user_s32(val, addr)) { 34730583b233SRichard Henderson goto sigsegv_maperr; 34740583b233SRichard Henderson } 34750583b233SRichard Henderson 34760583b233SRichard Henderson if (cmp) { 34770583b233SRichard Henderson if (quad) { 34780583b233SRichard Henderson sprval = env->spregs[TILEGX_SPR_CMPEXCH]; 34790583b233SRichard Henderson } else { 34800583b233SRichard Henderson sprval = sextract64(env->spregs[TILEGX_SPR_CMPEXCH], 0, 32); 34810583b233SRichard Henderson } 34820583b233SRichard Henderson } 34830583b233SRichard Henderson 34840583b233SRichard Henderson if (!cmp || val == sprval) { 34850583b233SRichard Henderson target_long valb = env->atomic_srcb; 34860583b233SRichard Henderson if (quad ? put_user_u64(valb, addr) : put_user_u32(valb, addr)) { 34870583b233SRichard Henderson goto sigsegv_maperr; 34880583b233SRichard Henderson } 34890583b233SRichard Henderson } 34900583b233SRichard Henderson 34910583b233SRichard Henderson set_regval(env, env->atomic_dstr, val); 34920583b233SRichard Henderson end_exclusive(); 34930583b233SRichard Henderson return; 34940583b233SRichard Henderson 34950583b233SRichard Henderson sigsegv_maperr: 34960583b233SRichard Henderson end_exclusive(); 34970583b233SRichard Henderson gen_sigsegv_maperr(env, addr); 34980583b233SRichard Henderson } 34990583b233SRichard Henderson 35000583b233SRichard Henderson static void do_fetch(CPUTLGState *env, int trapnr, bool quad) 35010583b233SRichard Henderson { 35020583b233SRichard Henderson int8_t write = 1; 35030583b233SRichard Henderson target_ulong addr; 35040583b233SRichard Henderson target_long val, valb; 35050583b233SRichard Henderson 35060583b233SRichard Henderson start_exclusive(); 35070583b233SRichard Henderson 35080583b233SRichard Henderson addr = env->atomic_srca; 35090583b233SRichard Henderson valb = env->atomic_srcb; 35100583b233SRichard Henderson if (quad ? get_user_s64(val, addr) : get_user_s32(val, addr)) { 35110583b233SRichard Henderson goto sigsegv_maperr; 35120583b233SRichard Henderson } 35130583b233SRichard Henderson 35140583b233SRichard Henderson switch (trapnr) { 35150583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHADD: 35160583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHADD4: 35170583b233SRichard Henderson valb += val; 35180583b233SRichard Henderson break; 35190583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHADDGEZ: 35200583b233SRichard Henderson valb += val; 35210583b233SRichard Henderson if (valb < 0) { 35220583b233SRichard Henderson write = 0; 35230583b233SRichard Henderson } 35240583b233SRichard Henderson break; 35250583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHADDGEZ4: 35260583b233SRichard Henderson valb += val; 35270583b233SRichard Henderson if ((int32_t)valb < 0) { 35280583b233SRichard Henderson write = 0; 35290583b233SRichard Henderson } 35300583b233SRichard Henderson break; 35310583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHAND: 35320583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHAND4: 35330583b233SRichard Henderson valb &= val; 35340583b233SRichard Henderson break; 35350583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHOR: 35360583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHOR4: 35370583b233SRichard Henderson valb |= val; 35380583b233SRichard Henderson break; 35390583b233SRichard Henderson default: 35400583b233SRichard Henderson g_assert_not_reached(); 35410583b233SRichard Henderson } 35420583b233SRichard Henderson 35430583b233SRichard Henderson if (write) { 35440583b233SRichard Henderson if (quad ? put_user_u64(valb, addr) : put_user_u32(valb, addr)) { 35450583b233SRichard Henderson goto sigsegv_maperr; 35460583b233SRichard Henderson } 35470583b233SRichard Henderson } 35480583b233SRichard Henderson 35490583b233SRichard Henderson set_regval(env, env->atomic_dstr, val); 35500583b233SRichard Henderson end_exclusive(); 35510583b233SRichard Henderson return; 35520583b233SRichard Henderson 35530583b233SRichard Henderson sigsegv_maperr: 35540583b233SRichard Henderson end_exclusive(); 35550583b233SRichard Henderson gen_sigsegv_maperr(env, addr); 35560583b233SRichard Henderson } 35570583b233SRichard Henderson 3558b16189b2SChen Gang void cpu_loop(CPUTLGState *env) 3559b16189b2SChen Gang { 3560b16189b2SChen Gang CPUState *cs = CPU(tilegx_env_get_cpu(env)); 3561b16189b2SChen Gang int trapnr; 3562b16189b2SChen Gang 3563b16189b2SChen Gang while (1) { 3564b16189b2SChen Gang cpu_exec_start(cs); 35658642c1b8SPeter Crosthwaite trapnr = cpu_exec(cs); 3566b16189b2SChen Gang cpu_exec_end(cs); 3567d148d90eSSergey Fedorov process_queued_cpu_work(cs); 3568d148d90eSSergey Fedorov 3569b16189b2SChen Gang switch (trapnr) { 3570b16189b2SChen Gang case TILEGX_EXCP_SYSCALL: 3571a9175169SPeter Maydell { 3572a9175169SPeter Maydell abi_ulong ret = do_syscall(env, env->regs[TILEGX_R_NR], 3573b16189b2SChen Gang env->regs[0], env->regs[1], 3574b16189b2SChen Gang env->regs[2], env->regs[3], 3575b16189b2SChen Gang env->regs[4], env->regs[5], 3576b16189b2SChen Gang env->regs[6], env->regs[7]); 3577a9175169SPeter Maydell if (ret == -TARGET_ERESTARTSYS) { 3578a9175169SPeter Maydell env->pc -= 8; 3579a9175169SPeter Maydell } else if (ret != -TARGET_QEMU_ESIGRETURN) { 3580a9175169SPeter Maydell env->regs[TILEGX_R_RE] = ret; 3581a9175169SPeter Maydell env->regs[TILEGX_R_ERR] = TILEGX_IS_ERRNO(ret) ? -ret : 0; 3582a9175169SPeter Maydell } 3583b16189b2SChen Gang break; 3584a9175169SPeter Maydell } 35850583b233SRichard Henderson case TILEGX_EXCP_OPCODE_EXCH: 35860583b233SRichard Henderson do_exch(env, true, false); 35870583b233SRichard Henderson break; 35880583b233SRichard Henderson case TILEGX_EXCP_OPCODE_EXCH4: 35890583b233SRichard Henderson do_exch(env, false, false); 35900583b233SRichard Henderson break; 35910583b233SRichard Henderson case TILEGX_EXCP_OPCODE_CMPEXCH: 35920583b233SRichard Henderson do_exch(env, true, true); 35930583b233SRichard Henderson break; 35940583b233SRichard Henderson case TILEGX_EXCP_OPCODE_CMPEXCH4: 35950583b233SRichard Henderson do_exch(env, false, true); 35960583b233SRichard Henderson break; 35970583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHADD: 35980583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHADDGEZ: 35990583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHAND: 36000583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHOR: 36010583b233SRichard Henderson do_fetch(env, trapnr, true); 36020583b233SRichard Henderson break; 36030583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHADD4: 36040583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHADDGEZ4: 36050583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHAND4: 36060583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHOR4: 36070583b233SRichard Henderson do_fetch(env, trapnr, false); 36080583b233SRichard Henderson break; 3609dd8070d8SChen Gang case TILEGX_EXCP_SIGNAL: 3610a0577d2aSRichard Henderson do_signal(env, env->signo, env->sigcode); 3611dd8070d8SChen Gang break; 3612b16189b2SChen Gang case TILEGX_EXCP_REG_IDN_ACCESS: 3613b16189b2SChen Gang case TILEGX_EXCP_REG_UDN_ACCESS: 3614b16189b2SChen Gang gen_sigill_reg(env); 3615b16189b2SChen Gang break; 3616fdbc2b57SRichard Henderson case EXCP_ATOMIC: 3617fdbc2b57SRichard Henderson cpu_exec_step_atomic(cs); 3618fdbc2b57SRichard Henderson break; 3619b16189b2SChen Gang default: 3620b16189b2SChen Gang fprintf(stderr, "trapnr is %d[0x%x].\n", trapnr, trapnr); 3621b16189b2SChen Gang g_assert_not_reached(); 3622b16189b2SChen Gang } 3623b16189b2SChen Gang process_pending_signals(env); 3624b16189b2SChen Gang } 3625b16189b2SChen Gang } 3626b16189b2SChen Gang 3627b16189b2SChen Gang #endif 3628b16189b2SChen Gang 36297c248bcdSRichard Henderson #ifdef TARGET_HPPA 36307c248bcdSRichard Henderson 36317c248bcdSRichard Henderson static abi_ulong hppa_lws(CPUHPPAState *env) 36327c248bcdSRichard Henderson { 36337c248bcdSRichard Henderson uint32_t which = env->gr[20]; 36347c248bcdSRichard Henderson abi_ulong addr = env->gr[26]; 36357c248bcdSRichard Henderson abi_ulong old = env->gr[25]; 36367c248bcdSRichard Henderson abi_ulong new = env->gr[24]; 36377c248bcdSRichard Henderson abi_ulong size, ret; 36387c248bcdSRichard Henderson 36397c248bcdSRichard Henderson switch (which) { 36407c248bcdSRichard Henderson default: 36417c248bcdSRichard Henderson return -TARGET_ENOSYS; 36427c248bcdSRichard Henderson 36437c248bcdSRichard Henderson case 0: /* elf32 atomic 32bit cmpxchg */ 36447c248bcdSRichard Henderson if ((addr & 3) || !access_ok(VERIFY_WRITE, addr, 4)) { 36457c248bcdSRichard Henderson return -TARGET_EFAULT; 36467c248bcdSRichard Henderson } 36477c248bcdSRichard Henderson old = tswap32(old); 36487c248bcdSRichard Henderson new = tswap32(new); 36497c248bcdSRichard Henderson ret = atomic_cmpxchg((uint32_t *)g2h(addr), old, new); 36507c248bcdSRichard Henderson ret = tswap32(ret); 36517c248bcdSRichard Henderson break; 36527c248bcdSRichard Henderson 36537c248bcdSRichard Henderson case 2: /* elf32 atomic "new" cmpxchg */ 36547c248bcdSRichard Henderson size = env->gr[23]; 36557c248bcdSRichard Henderson if (size >= 4) { 36567c248bcdSRichard Henderson return -TARGET_ENOSYS; 36577c248bcdSRichard Henderson } 36587c248bcdSRichard Henderson if (((addr | old | new) & ((1 << size) - 1)) 36597c248bcdSRichard Henderson || !access_ok(VERIFY_WRITE, addr, 1 << size) 36607c248bcdSRichard Henderson || !access_ok(VERIFY_READ, old, 1 << size) 36617c248bcdSRichard Henderson || !access_ok(VERIFY_READ, new, 1 << size)) { 36627c248bcdSRichard Henderson return -TARGET_EFAULT; 36637c248bcdSRichard Henderson } 36647c248bcdSRichard Henderson /* Note that below we use host-endian loads so that the cmpxchg 36657c248bcdSRichard Henderson can be host-endian as well. */ 36667c248bcdSRichard Henderson switch (size) { 36677c248bcdSRichard Henderson case 0: 36687c248bcdSRichard Henderson old = *(uint8_t *)g2h(old); 36697c248bcdSRichard Henderson new = *(uint8_t *)g2h(new); 36707c248bcdSRichard Henderson ret = atomic_cmpxchg((uint8_t *)g2h(addr), old, new); 36717c248bcdSRichard Henderson ret = ret != old; 36727c248bcdSRichard Henderson break; 36737c248bcdSRichard Henderson case 1: 36747c248bcdSRichard Henderson old = *(uint16_t *)g2h(old); 36757c248bcdSRichard Henderson new = *(uint16_t *)g2h(new); 36767c248bcdSRichard Henderson ret = atomic_cmpxchg((uint16_t *)g2h(addr), old, new); 36777c248bcdSRichard Henderson ret = ret != old; 36787c248bcdSRichard Henderson break; 36797c248bcdSRichard Henderson case 2: 36807c248bcdSRichard Henderson old = *(uint32_t *)g2h(old); 36817c248bcdSRichard Henderson new = *(uint32_t *)g2h(new); 36827c248bcdSRichard Henderson ret = atomic_cmpxchg((uint32_t *)g2h(addr), old, new); 36837c248bcdSRichard Henderson ret = ret != old; 36847c248bcdSRichard Henderson break; 36857c248bcdSRichard Henderson case 3: 36867c248bcdSRichard Henderson { 36877c248bcdSRichard Henderson uint64_t o64, n64, r64; 36887c248bcdSRichard Henderson o64 = *(uint64_t *)g2h(old); 36897c248bcdSRichard Henderson n64 = *(uint64_t *)g2h(new); 36907c248bcdSRichard Henderson #ifdef CONFIG_ATOMIC64 36917c248bcdSRichard Henderson r64 = atomic_cmpxchg__nocheck((uint64_t *)g2h(addr), o64, n64); 36927c248bcdSRichard Henderson ret = r64 != o64; 36937c248bcdSRichard Henderson #else 36947c248bcdSRichard Henderson start_exclusive(); 36957c248bcdSRichard Henderson r64 = *(uint64_t *)g2h(addr); 36967c248bcdSRichard Henderson ret = 1; 36977c248bcdSRichard Henderson if (r64 == o64) { 36987c248bcdSRichard Henderson *(uint64_t *)g2h(addr) = n64; 36997c248bcdSRichard Henderson ret = 0; 37007c248bcdSRichard Henderson } 37017c248bcdSRichard Henderson end_exclusive(); 37027c248bcdSRichard Henderson #endif 37037c248bcdSRichard Henderson } 37047c248bcdSRichard Henderson break; 37057c248bcdSRichard Henderson } 37067c248bcdSRichard Henderson break; 37077c248bcdSRichard Henderson } 37087c248bcdSRichard Henderson 37097c248bcdSRichard Henderson env->gr[28] = ret; 37107c248bcdSRichard Henderson return 0; 37117c248bcdSRichard Henderson } 37127c248bcdSRichard Henderson 37137c248bcdSRichard Henderson void cpu_loop(CPUHPPAState *env) 37147c248bcdSRichard Henderson { 37157c248bcdSRichard Henderson CPUState *cs = CPU(hppa_env_get_cpu(env)); 37167c248bcdSRichard Henderson target_siginfo_t info; 37177c248bcdSRichard Henderson abi_ulong ret; 37187c248bcdSRichard Henderson int trapnr; 37197c248bcdSRichard Henderson 37207c248bcdSRichard Henderson while (1) { 37217c248bcdSRichard Henderson cpu_exec_start(cs); 37227c248bcdSRichard Henderson trapnr = cpu_exec(cs); 37237c248bcdSRichard Henderson cpu_exec_end(cs); 37247c248bcdSRichard Henderson process_queued_cpu_work(cs); 37257c248bcdSRichard Henderson 37267c248bcdSRichard Henderson switch (trapnr) { 37277c248bcdSRichard Henderson case EXCP_SYSCALL: 37287c248bcdSRichard Henderson ret = do_syscall(env, env->gr[20], 37297c248bcdSRichard Henderson env->gr[26], env->gr[25], 37307c248bcdSRichard Henderson env->gr[24], env->gr[23], 37317c248bcdSRichard Henderson env->gr[22], env->gr[21], 0, 0); 37327c248bcdSRichard Henderson switch (ret) { 37337c248bcdSRichard Henderson default: 37347c248bcdSRichard Henderson env->gr[28] = ret; 37357c248bcdSRichard Henderson /* We arrived here by faking the gateway page. Return. */ 37367c248bcdSRichard Henderson env->iaoq_f = env->gr[31]; 37377c248bcdSRichard Henderson env->iaoq_b = env->gr[31] + 4; 37387c248bcdSRichard Henderson break; 37397c248bcdSRichard Henderson case -TARGET_ERESTARTSYS: 37407c248bcdSRichard Henderson case -TARGET_QEMU_ESIGRETURN: 37417c248bcdSRichard Henderson break; 37427c248bcdSRichard Henderson } 37437c248bcdSRichard Henderson break; 37447c248bcdSRichard Henderson case EXCP_SYSCALL_LWS: 37457c248bcdSRichard Henderson env->gr[21] = hppa_lws(env); 37467c248bcdSRichard Henderson /* We arrived here by faking the gateway page. Return. */ 37477c248bcdSRichard Henderson env->iaoq_f = env->gr[31]; 37487c248bcdSRichard Henderson env->iaoq_b = env->gr[31] + 4; 37497c248bcdSRichard Henderson break; 37507c248bcdSRichard Henderson case EXCP_SIGSEGV: 37517c248bcdSRichard Henderson info.si_signo = TARGET_SIGSEGV; 37527c248bcdSRichard Henderson info.si_errno = 0; 37537c248bcdSRichard Henderson info.si_code = TARGET_SEGV_ACCERR; 37547c248bcdSRichard Henderson info._sifields._sigfault._addr = env->ior; 37557c248bcdSRichard Henderson queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 37567c248bcdSRichard Henderson break; 37577c248bcdSRichard Henderson case EXCP_SIGILL: 37587c248bcdSRichard Henderson info.si_signo = TARGET_SIGILL; 37597c248bcdSRichard Henderson info.si_errno = 0; 37607c248bcdSRichard Henderson info.si_code = TARGET_ILL_ILLOPN; 37617c248bcdSRichard Henderson info._sifields._sigfault._addr = env->iaoq_f; 37627c248bcdSRichard Henderson queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 37637c248bcdSRichard Henderson break; 37647c248bcdSRichard Henderson case EXCP_SIGFPE: 37657c248bcdSRichard Henderson info.si_signo = TARGET_SIGFPE; 37667c248bcdSRichard Henderson info.si_errno = 0; 37677c248bcdSRichard Henderson info.si_code = 0; 37687c248bcdSRichard Henderson info._sifields._sigfault._addr = env->iaoq_f; 37697c248bcdSRichard Henderson queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); 37707c248bcdSRichard Henderson break; 37717c248bcdSRichard Henderson case EXCP_DEBUG: 37727c248bcdSRichard Henderson trapnr = gdb_handlesig(cs, TARGET_SIGTRAP); 37737c248bcdSRichard Henderson if (trapnr) { 37747c248bcdSRichard Henderson info.si_signo = trapnr; 37757c248bcdSRichard Henderson info.si_errno = 0; 37767c248bcdSRichard Henderson info.si_code = TARGET_TRAP_BRKPT; 37777c248bcdSRichard Henderson queue_signal(env, trapnr, QEMU_SI_FAULT, &info); 37787c248bcdSRichard Henderson } 37797c248bcdSRichard Henderson break; 37807c248bcdSRichard Henderson case EXCP_INTERRUPT: 37817c248bcdSRichard Henderson /* just indicate that signals should be handled asap */ 37827c248bcdSRichard Henderson break; 37837c248bcdSRichard Henderson default: 37847c248bcdSRichard Henderson g_assert_not_reached(); 37857c248bcdSRichard Henderson } 37867c248bcdSRichard Henderson process_pending_signals(env); 37877c248bcdSRichard Henderson } 37887c248bcdSRichard Henderson } 37897c248bcdSRichard Henderson 37907c248bcdSRichard Henderson #endif /* TARGET_HPPA */ 37917c248bcdSRichard Henderson 3792a2247f8eSAndreas Färber THREAD CPUState *thread_cpu; 379359faf6d6Sbellard 3794178f9429SSergey Fedorov bool qemu_cpu_is_self(CPUState *cpu) 3795178f9429SSergey Fedorov { 3796178f9429SSergey Fedorov return thread_cpu == cpu; 3797178f9429SSergey Fedorov } 3798178f9429SSergey Fedorov 3799178f9429SSergey Fedorov void qemu_cpu_kick(CPUState *cpu) 3800178f9429SSergey Fedorov { 3801178f9429SSergey Fedorov cpu_exit(cpu); 3802178f9429SSergey Fedorov } 3803178f9429SSergey Fedorov 3804edf8e2afSMika Westerberg void task_settid(TaskState *ts) 3805edf8e2afSMika Westerberg { 3806edf8e2afSMika Westerberg if (ts->ts_tid == 0) { 3807edf8e2afSMika Westerberg ts->ts_tid = (pid_t)syscall(SYS_gettid); 3808edf8e2afSMika Westerberg } 3809edf8e2afSMika Westerberg } 3810edf8e2afSMika Westerberg 3811edf8e2afSMika Westerberg void stop_all_tasks(void) 3812edf8e2afSMika Westerberg { 3813edf8e2afSMika Westerberg /* 3814edf8e2afSMika Westerberg * We trust that when using NPTL, start_exclusive() 3815edf8e2afSMika Westerberg * handles thread stopping correctly. 3816edf8e2afSMika Westerberg */ 3817edf8e2afSMika Westerberg start_exclusive(); 3818edf8e2afSMika Westerberg } 3819edf8e2afSMika Westerberg 3820c3a92833Spbrook /* Assumes contents are already zeroed. */ 3821624f7979Spbrook void init_task_state(TaskState *ts) 3822624f7979Spbrook { 3823624f7979Spbrook ts->used = 1; 3824624f7979Spbrook } 38259de5e440Sbellard 382630ba0ee5SAndreas Färber CPUArchState *cpu_copy(CPUArchState *env) 382730ba0ee5SAndreas Färber { 3828ff4700b0SAndreas Färber CPUState *cpu = ENV_GET_CPU(env); 38292994fd96SEduardo Habkost CPUState *new_cpu = cpu_init(cpu_model); 383061c7480fSLeon Alrae CPUArchState *new_env = new_cpu->env_ptr; 383130ba0ee5SAndreas Färber CPUBreakpoint *bp; 383230ba0ee5SAndreas Färber CPUWatchpoint *wp; 383330ba0ee5SAndreas Färber 383430ba0ee5SAndreas Färber /* Reset non arch specific state */ 383575a34036SAndreas Färber cpu_reset(new_cpu); 383630ba0ee5SAndreas Färber 383730ba0ee5SAndreas Färber memcpy(new_env, env, sizeof(CPUArchState)); 383830ba0ee5SAndreas Färber 383930ba0ee5SAndreas Färber /* Clone all break/watchpoints. 384030ba0ee5SAndreas Färber Note: Once we support ptrace with hw-debug register access, make sure 384130ba0ee5SAndreas Färber BP_CPU break/watchpoints are handled correctly on clone. */ 38421d085f6cSThierry Bultel QTAILQ_INIT(&new_cpu->breakpoints); 38431d085f6cSThierry Bultel QTAILQ_INIT(&new_cpu->watchpoints); 3844f0c3c505SAndreas Färber QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) { 3845b3310ab3SAndreas Färber cpu_breakpoint_insert(new_cpu, bp->pc, bp->flags, NULL); 384630ba0ee5SAndreas Färber } 3847ff4700b0SAndreas Färber QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { 384805068c0dSPeter Maydell cpu_watchpoint_insert(new_cpu, wp->vaddr, wp->len, wp->flags, NULL); 384930ba0ee5SAndreas Färber } 385030ba0ee5SAndreas Färber 385130ba0ee5SAndreas Färber return new_env; 385230ba0ee5SAndreas Färber } 385330ba0ee5SAndreas Färber 3854fc9c5412SJohannes Schauer static void handle_arg_help(const char *arg) 3855fc9c5412SJohannes Schauer { 38564d1275c2SRiku Voipio usage(EXIT_SUCCESS); 3857fc9c5412SJohannes Schauer } 3858fc9c5412SJohannes Schauer 3859fc9c5412SJohannes Schauer static void handle_arg_log(const char *arg) 3860fc9c5412SJohannes Schauer { 3861fc9c5412SJohannes Schauer int mask; 3862fc9c5412SJohannes Schauer 38634fde1ebaSPeter Maydell mask = qemu_str_to_log_mask(arg); 3864fc9c5412SJohannes Schauer if (!mask) { 386559a6fa6eSPeter Maydell qemu_print_log_usage(stdout); 38664d1275c2SRiku Voipio exit(EXIT_FAILURE); 3867fc9c5412SJohannes Schauer } 3868f2937a33SPaolo Bonzini qemu_log_needs_buffers(); 386924537a01SPeter Maydell qemu_set_log(mask); 3870fc9c5412SJohannes Schauer } 3871fc9c5412SJohannes Schauer 387250171d42S陳韋任 static void handle_arg_log_filename(const char *arg) 387350171d42S陳韋任 { 3874daa76aa4SMarkus Armbruster qemu_set_log_filename(arg, &error_fatal); 387550171d42S陳韋任 } 387650171d42S陳韋任 3877fc9c5412SJohannes Schauer static void handle_arg_set_env(const char *arg) 3878fc9c5412SJohannes Schauer { 3879fc9c5412SJohannes Schauer char *r, *p, *token; 3880fc9c5412SJohannes Schauer r = p = strdup(arg); 3881fc9c5412SJohannes Schauer while ((token = strsep(&p, ",")) != NULL) { 3882fc9c5412SJohannes Schauer if (envlist_setenv(envlist, token) != 0) { 38834d1275c2SRiku Voipio usage(EXIT_FAILURE); 3884fc9c5412SJohannes Schauer } 3885fc9c5412SJohannes Schauer } 3886fc9c5412SJohannes Schauer free(r); 3887fc9c5412SJohannes Schauer } 3888fc9c5412SJohannes Schauer 3889fc9c5412SJohannes Schauer static void handle_arg_unset_env(const char *arg) 3890fc9c5412SJohannes Schauer { 3891fc9c5412SJohannes Schauer char *r, *p, *token; 3892fc9c5412SJohannes Schauer r = p = strdup(arg); 3893fc9c5412SJohannes Schauer while ((token = strsep(&p, ",")) != NULL) { 3894fc9c5412SJohannes Schauer if (envlist_unsetenv(envlist, token) != 0) { 38954d1275c2SRiku Voipio usage(EXIT_FAILURE); 3896fc9c5412SJohannes Schauer } 3897fc9c5412SJohannes Schauer } 3898fc9c5412SJohannes Schauer free(r); 3899fc9c5412SJohannes Schauer } 3900fc9c5412SJohannes Schauer 3901fc9c5412SJohannes Schauer static void handle_arg_argv0(const char *arg) 3902fc9c5412SJohannes Schauer { 3903fc9c5412SJohannes Schauer argv0 = strdup(arg); 3904fc9c5412SJohannes Schauer } 3905fc9c5412SJohannes Schauer 3906fc9c5412SJohannes Schauer static void handle_arg_stack_size(const char *arg) 3907fc9c5412SJohannes Schauer { 3908fc9c5412SJohannes Schauer char *p; 3909fc9c5412SJohannes Schauer guest_stack_size = strtoul(arg, &p, 0); 3910fc9c5412SJohannes Schauer if (guest_stack_size == 0) { 39114d1275c2SRiku Voipio usage(EXIT_FAILURE); 3912fc9c5412SJohannes Schauer } 3913fc9c5412SJohannes Schauer 3914fc9c5412SJohannes Schauer if (*p == 'M') { 3915fc9c5412SJohannes Schauer guest_stack_size *= 1024 * 1024; 3916fc9c5412SJohannes Schauer } else if (*p == 'k' || *p == 'K') { 3917fc9c5412SJohannes Schauer guest_stack_size *= 1024; 3918fc9c5412SJohannes Schauer } 3919fc9c5412SJohannes Schauer } 3920fc9c5412SJohannes Schauer 3921fc9c5412SJohannes Schauer static void handle_arg_ld_prefix(const char *arg) 3922fc9c5412SJohannes Schauer { 3923fc9c5412SJohannes Schauer interp_prefix = strdup(arg); 3924fc9c5412SJohannes Schauer } 3925fc9c5412SJohannes Schauer 3926fc9c5412SJohannes Schauer static void handle_arg_pagesize(const char *arg) 3927fc9c5412SJohannes Schauer { 3928fc9c5412SJohannes Schauer qemu_host_page_size = atoi(arg); 3929fc9c5412SJohannes Schauer if (qemu_host_page_size == 0 || 3930fc9c5412SJohannes Schauer (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) { 3931fc9c5412SJohannes Schauer fprintf(stderr, "page size must be a power of two\n"); 39324d1275c2SRiku Voipio exit(EXIT_FAILURE); 3933fc9c5412SJohannes Schauer } 3934fc9c5412SJohannes Schauer } 3935fc9c5412SJohannes Schauer 3936c5e4a5a9SMagnus Reftel static void handle_arg_randseed(const char *arg) 3937c5e4a5a9SMagnus Reftel { 3938c5e4a5a9SMagnus Reftel unsigned long long seed; 3939c5e4a5a9SMagnus Reftel 3940c5e4a5a9SMagnus Reftel if (parse_uint_full(arg, &seed, 0) != 0 || seed > UINT_MAX) { 3941c5e4a5a9SMagnus Reftel fprintf(stderr, "Invalid seed number: %s\n", arg); 39424d1275c2SRiku Voipio exit(EXIT_FAILURE); 3943c5e4a5a9SMagnus Reftel } 3944c5e4a5a9SMagnus Reftel srand(seed); 3945c5e4a5a9SMagnus Reftel } 3946c5e4a5a9SMagnus Reftel 3947fc9c5412SJohannes Schauer static void handle_arg_gdb(const char *arg) 3948fc9c5412SJohannes Schauer { 3949fc9c5412SJohannes Schauer gdbstub_port = atoi(arg); 3950fc9c5412SJohannes Schauer } 3951fc9c5412SJohannes Schauer 3952fc9c5412SJohannes Schauer static void handle_arg_uname(const char *arg) 3953fc9c5412SJohannes Schauer { 3954fc9c5412SJohannes Schauer qemu_uname_release = strdup(arg); 3955fc9c5412SJohannes Schauer } 3956fc9c5412SJohannes Schauer 3957fc9c5412SJohannes Schauer static void handle_arg_cpu(const char *arg) 3958fc9c5412SJohannes Schauer { 3959fc9c5412SJohannes Schauer cpu_model = strdup(arg); 3960c8057f95SPeter Maydell if (cpu_model == NULL || is_help_option(cpu_model)) { 3961fc9c5412SJohannes Schauer /* XXX: implement xxx_cpu_list for targets that still miss it */ 3962e916cbf8SPeter Maydell #if defined(cpu_list) 3963e916cbf8SPeter Maydell cpu_list(stdout, &fprintf); 3964fc9c5412SJohannes Schauer #endif 39654d1275c2SRiku Voipio exit(EXIT_FAILURE); 3966fc9c5412SJohannes Schauer } 3967fc9c5412SJohannes Schauer } 3968fc9c5412SJohannes Schauer 3969fc9c5412SJohannes Schauer static void handle_arg_guest_base(const char *arg) 3970fc9c5412SJohannes Schauer { 3971fc9c5412SJohannes Schauer guest_base = strtol(arg, NULL, 0); 3972fc9c5412SJohannes Schauer have_guest_base = 1; 3973fc9c5412SJohannes Schauer } 3974fc9c5412SJohannes Schauer 3975fc9c5412SJohannes Schauer static void handle_arg_reserved_va(const char *arg) 3976fc9c5412SJohannes Schauer { 3977fc9c5412SJohannes Schauer char *p; 3978fc9c5412SJohannes Schauer int shift = 0; 3979fc9c5412SJohannes Schauer reserved_va = strtoul(arg, &p, 0); 3980fc9c5412SJohannes Schauer switch (*p) { 3981fc9c5412SJohannes Schauer case 'k': 3982fc9c5412SJohannes Schauer case 'K': 3983fc9c5412SJohannes Schauer shift = 10; 3984fc9c5412SJohannes Schauer break; 3985fc9c5412SJohannes Schauer case 'M': 3986fc9c5412SJohannes Schauer shift = 20; 3987fc9c5412SJohannes Schauer break; 3988fc9c5412SJohannes Schauer case 'G': 3989fc9c5412SJohannes Schauer shift = 30; 3990fc9c5412SJohannes Schauer break; 3991fc9c5412SJohannes Schauer } 3992fc9c5412SJohannes Schauer if (shift) { 3993fc9c5412SJohannes Schauer unsigned long unshifted = reserved_va; 3994fc9c5412SJohannes Schauer p++; 3995fc9c5412SJohannes Schauer reserved_va <<= shift; 3996*18e80c55SRichard Henderson if (reserved_va >> shift != unshifted 3997*18e80c55SRichard Henderson || (MAX_RESERVED_VA && reserved_va > MAX_RESERVED_VA)) { 3998fc9c5412SJohannes Schauer fprintf(stderr, "Reserved virtual address too big\n"); 39994d1275c2SRiku Voipio exit(EXIT_FAILURE); 4000fc9c5412SJohannes Schauer } 4001fc9c5412SJohannes Schauer } 4002fc9c5412SJohannes Schauer if (*p) { 4003fc9c5412SJohannes Schauer fprintf(stderr, "Unrecognised -R size suffix '%s'\n", p); 40044d1275c2SRiku Voipio exit(EXIT_FAILURE); 4005fc9c5412SJohannes Schauer } 4006fc9c5412SJohannes Schauer } 4007fc9c5412SJohannes Schauer 4008fc9c5412SJohannes Schauer static void handle_arg_singlestep(const char *arg) 4009fc9c5412SJohannes Schauer { 4010fc9c5412SJohannes Schauer singlestep = 1; 4011fc9c5412SJohannes Schauer } 4012fc9c5412SJohannes Schauer 4013fc9c5412SJohannes Schauer static void handle_arg_strace(const char *arg) 4014fc9c5412SJohannes Schauer { 4015fc9c5412SJohannes Schauer do_strace = 1; 4016fc9c5412SJohannes Schauer } 4017fc9c5412SJohannes Schauer 4018fc9c5412SJohannes Schauer static void handle_arg_version(const char *arg) 4019fc9c5412SJohannes Schauer { 40202e59915dSPaolo Bonzini printf("qemu-" TARGET_NAME " version " QEMU_VERSION QEMU_PKGVERSION 40210781dd6eSThomas Huth "\n" QEMU_COPYRIGHT "\n"); 40224d1275c2SRiku Voipio exit(EXIT_SUCCESS); 4023fc9c5412SJohannes Schauer } 4024fc9c5412SJohannes Schauer 40256533dd6eSLluís Vilanova static char *trace_file; 40266533dd6eSLluís Vilanova static void handle_arg_trace(const char *arg) 40276533dd6eSLluís Vilanova { 40286533dd6eSLluís Vilanova g_free(trace_file); 40296533dd6eSLluís Vilanova trace_file = trace_opt_parse(arg); 40306533dd6eSLluís Vilanova } 40316533dd6eSLluís Vilanova 4032fc9c5412SJohannes Schauer struct qemu_argument { 4033fc9c5412SJohannes Schauer const char *argv; 4034fc9c5412SJohannes Schauer const char *env; 4035fc9c5412SJohannes Schauer bool has_arg; 4036fc9c5412SJohannes Schauer void (*handle_opt)(const char *arg); 4037fc9c5412SJohannes Schauer const char *example; 4038fc9c5412SJohannes Schauer const char *help; 4039fc9c5412SJohannes Schauer }; 4040fc9c5412SJohannes Schauer 404142644ceeSJim Meyering static const struct qemu_argument arg_table[] = { 4042fc9c5412SJohannes Schauer {"h", "", false, handle_arg_help, 4043fc9c5412SJohannes Schauer "", "print this help"}, 4044daaf8c8eSMeador Inge {"help", "", false, handle_arg_help, 4045daaf8c8eSMeador Inge "", ""}, 4046fc9c5412SJohannes Schauer {"g", "QEMU_GDB", true, handle_arg_gdb, 4047fc9c5412SJohannes Schauer "port", "wait gdb connection to 'port'"}, 4048fc9c5412SJohannes Schauer {"L", "QEMU_LD_PREFIX", true, handle_arg_ld_prefix, 4049fc9c5412SJohannes Schauer "path", "set the elf interpreter prefix to 'path'"}, 4050fc9c5412SJohannes Schauer {"s", "QEMU_STACK_SIZE", true, handle_arg_stack_size, 4051fc9c5412SJohannes Schauer "size", "set the stack size to 'size' bytes"}, 4052fc9c5412SJohannes Schauer {"cpu", "QEMU_CPU", true, handle_arg_cpu, 4053c8057f95SPeter Maydell "model", "select CPU (-cpu help for list)"}, 4054fc9c5412SJohannes Schauer {"E", "QEMU_SET_ENV", true, handle_arg_set_env, 4055fc9c5412SJohannes Schauer "var=value", "sets targets environment variable (see below)"}, 4056fc9c5412SJohannes Schauer {"U", "QEMU_UNSET_ENV", true, handle_arg_unset_env, 4057fc9c5412SJohannes Schauer "var", "unsets targets environment variable (see below)"}, 4058fc9c5412SJohannes Schauer {"0", "QEMU_ARGV0", true, handle_arg_argv0, 4059fc9c5412SJohannes Schauer "argv0", "forces target process argv[0] to be 'argv0'"}, 4060fc9c5412SJohannes Schauer {"r", "QEMU_UNAME", true, handle_arg_uname, 4061fc9c5412SJohannes Schauer "uname", "set qemu uname release string to 'uname'"}, 4062fc9c5412SJohannes Schauer {"B", "QEMU_GUEST_BASE", true, handle_arg_guest_base, 4063fc9c5412SJohannes Schauer "address", "set guest_base address to 'address'"}, 4064fc9c5412SJohannes Schauer {"R", "QEMU_RESERVED_VA", true, handle_arg_reserved_va, 4065fc9c5412SJohannes Schauer "size", "reserve 'size' bytes for guest virtual address space"}, 4066fc9c5412SJohannes Schauer {"d", "QEMU_LOG", true, handle_arg_log, 4067989b697dSPeter Maydell "item[,...]", "enable logging of specified items " 4068989b697dSPeter Maydell "(use '-d help' for a list of items)"}, 406950171d42S陳韋任 {"D", "QEMU_LOG_FILENAME", true, handle_arg_log_filename, 4070989b697dSPeter Maydell "logfile", "write logs to 'logfile' (default stderr)"}, 4071fc9c5412SJohannes Schauer {"p", "QEMU_PAGESIZE", true, handle_arg_pagesize, 4072fc9c5412SJohannes Schauer "pagesize", "set the host page size to 'pagesize'"}, 4073fc9c5412SJohannes Schauer {"singlestep", "QEMU_SINGLESTEP", false, handle_arg_singlestep, 4074fc9c5412SJohannes Schauer "", "run in singlestep mode"}, 4075fc9c5412SJohannes Schauer {"strace", "QEMU_STRACE", false, handle_arg_strace, 4076fc9c5412SJohannes Schauer "", "log system calls"}, 4077c5e4a5a9SMagnus Reftel {"seed", "QEMU_RAND_SEED", true, handle_arg_randseed, 4078c5e4a5a9SMagnus Reftel "", "Seed for pseudo-random number generator"}, 40796533dd6eSLluís Vilanova {"trace", "QEMU_TRACE", true, handle_arg_trace, 40806533dd6eSLluís Vilanova "", "[[enable=]<pattern>][,events=<file>][,file=<file>]"}, 4081fc9c5412SJohannes Schauer {"version", "QEMU_VERSION", false, handle_arg_version, 40821386d4c0SPeter Maydell "", "display version information and exit"}, 4083fc9c5412SJohannes Schauer {NULL, NULL, false, NULL, NULL, NULL} 4084fc9c5412SJohannes Schauer }; 4085fc9c5412SJohannes Schauer 4086d03f9c32SMeador Inge static void usage(int exitcode) 4087fc9c5412SJohannes Schauer { 408842644ceeSJim Meyering const struct qemu_argument *arginfo; 4089fc9c5412SJohannes Schauer int maxarglen; 4090fc9c5412SJohannes Schauer int maxenvlen; 4091fc9c5412SJohannes Schauer 40922e59915dSPaolo Bonzini printf("usage: qemu-" TARGET_NAME " [options] program [arguments...]\n" 40932e59915dSPaolo Bonzini "Linux CPU emulator (compiled for " TARGET_NAME " emulation)\n" 4094fc9c5412SJohannes Schauer "\n" 4095fc9c5412SJohannes Schauer "Options and associated environment variables:\n" 4096fc9c5412SJohannes Schauer "\n"); 4097fc9c5412SJohannes Schauer 409863ec54d7SPeter Maydell /* Calculate column widths. We must always have at least enough space 409963ec54d7SPeter Maydell * for the column header. 410063ec54d7SPeter Maydell */ 410163ec54d7SPeter Maydell maxarglen = strlen("Argument"); 410263ec54d7SPeter Maydell maxenvlen = strlen("Env-variable"); 4103fc9c5412SJohannes Schauer 4104fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) { 410563ec54d7SPeter Maydell int arglen = strlen(arginfo->argv); 410663ec54d7SPeter Maydell if (arginfo->has_arg) { 410763ec54d7SPeter Maydell arglen += strlen(arginfo->example) + 1; 410863ec54d7SPeter Maydell } 4109fc9c5412SJohannes Schauer if (strlen(arginfo->env) > maxenvlen) { 4110fc9c5412SJohannes Schauer maxenvlen = strlen(arginfo->env); 4111fc9c5412SJohannes Schauer } 411263ec54d7SPeter Maydell if (arglen > maxarglen) { 411363ec54d7SPeter Maydell maxarglen = arglen; 4114fc9c5412SJohannes Schauer } 4115fc9c5412SJohannes Schauer } 4116fc9c5412SJohannes Schauer 411763ec54d7SPeter Maydell printf("%-*s %-*s Description\n", maxarglen+1, "Argument", 411863ec54d7SPeter Maydell maxenvlen, "Env-variable"); 4119fc9c5412SJohannes Schauer 4120fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) { 4121fc9c5412SJohannes Schauer if (arginfo->has_arg) { 4122fc9c5412SJohannes Schauer printf("-%s %-*s %-*s %s\n", arginfo->argv, 412363ec54d7SPeter Maydell (int)(maxarglen - strlen(arginfo->argv) - 1), 412463ec54d7SPeter Maydell arginfo->example, maxenvlen, arginfo->env, arginfo->help); 4125fc9c5412SJohannes Schauer } else { 412663ec54d7SPeter Maydell printf("-%-*s %-*s %s\n", maxarglen, arginfo->argv, 4127fc9c5412SJohannes Schauer maxenvlen, arginfo->env, 4128fc9c5412SJohannes Schauer arginfo->help); 4129fc9c5412SJohannes Schauer } 4130fc9c5412SJohannes Schauer } 4131fc9c5412SJohannes Schauer 4132fc9c5412SJohannes Schauer printf("\n" 4133fc9c5412SJohannes Schauer "Defaults:\n" 4134fc9c5412SJohannes Schauer "QEMU_LD_PREFIX = %s\n" 4135989b697dSPeter Maydell "QEMU_STACK_SIZE = %ld byte\n", 4136fc9c5412SJohannes Schauer interp_prefix, 4137989b697dSPeter Maydell guest_stack_size); 4138fc9c5412SJohannes Schauer 4139fc9c5412SJohannes Schauer printf("\n" 4140fc9c5412SJohannes Schauer "You can use -E and -U options or the QEMU_SET_ENV and\n" 4141fc9c5412SJohannes Schauer "QEMU_UNSET_ENV environment variables to set and unset\n" 4142fc9c5412SJohannes Schauer "environment variables for the target process.\n" 4143fc9c5412SJohannes Schauer "It is possible to provide several variables by separating them\n" 4144fc9c5412SJohannes Schauer "by commas in getsubopt(3) style. Additionally it is possible to\n" 4145fc9c5412SJohannes Schauer "provide the -E and -U options multiple times.\n" 4146fc9c5412SJohannes Schauer "The following lines are equivalent:\n" 4147fc9c5412SJohannes Schauer " -E var1=val2 -E var2=val2 -U LD_PRELOAD -U LD_DEBUG\n" 4148fc9c5412SJohannes Schauer " -E var1=val2,var2=val2 -U LD_PRELOAD,LD_DEBUG\n" 4149fc9c5412SJohannes Schauer " QEMU_SET_ENV=var1=val2,var2=val2 QEMU_UNSET_ENV=LD_PRELOAD,LD_DEBUG\n" 4150fc9c5412SJohannes Schauer "Note that if you provide several changes to a single variable\n" 4151f5048cb7SEric Blake "the last change will stay in effect.\n" 4152f5048cb7SEric Blake "\n" 4153f5048cb7SEric Blake QEMU_HELP_BOTTOM "\n"); 4154fc9c5412SJohannes Schauer 4155d03f9c32SMeador Inge exit(exitcode); 4156fc9c5412SJohannes Schauer } 4157fc9c5412SJohannes Schauer 4158fc9c5412SJohannes Schauer static int parse_args(int argc, char **argv) 4159fc9c5412SJohannes Schauer { 4160fc9c5412SJohannes Schauer const char *r; 4161fc9c5412SJohannes Schauer int optind; 416242644ceeSJim Meyering const struct qemu_argument *arginfo; 4163fc9c5412SJohannes Schauer 4164fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) { 4165fc9c5412SJohannes Schauer if (arginfo->env == NULL) { 4166fc9c5412SJohannes Schauer continue; 4167fc9c5412SJohannes Schauer } 4168fc9c5412SJohannes Schauer 4169fc9c5412SJohannes Schauer r = getenv(arginfo->env); 4170fc9c5412SJohannes Schauer if (r != NULL) { 4171fc9c5412SJohannes Schauer arginfo->handle_opt(r); 4172fc9c5412SJohannes Schauer } 4173fc9c5412SJohannes Schauer } 4174fc9c5412SJohannes Schauer 4175fc9c5412SJohannes Schauer optind = 1; 4176fc9c5412SJohannes Schauer for (;;) { 4177fc9c5412SJohannes Schauer if (optind >= argc) { 4178fc9c5412SJohannes Schauer break; 4179fc9c5412SJohannes Schauer } 4180fc9c5412SJohannes Schauer r = argv[optind]; 4181fc9c5412SJohannes Schauer if (r[0] != '-') { 4182fc9c5412SJohannes Schauer break; 4183fc9c5412SJohannes Schauer } 4184fc9c5412SJohannes Schauer optind++; 4185fc9c5412SJohannes Schauer r++; 4186fc9c5412SJohannes Schauer if (!strcmp(r, "-")) { 4187fc9c5412SJohannes Schauer break; 4188fc9c5412SJohannes Schauer } 4189ba02577cSMeador Inge /* Treat --foo the same as -foo. */ 4190ba02577cSMeador Inge if (r[0] == '-') { 4191ba02577cSMeador Inge r++; 4192ba02577cSMeador Inge } 4193fc9c5412SJohannes Schauer 4194fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) { 4195fc9c5412SJohannes Schauer if (!strcmp(r, arginfo->argv)) { 41961386d4c0SPeter Maydell if (arginfo->has_arg) { 4197fc9c5412SJohannes Schauer if (optind >= argc) { 4198138940bfSMeador Inge (void) fprintf(stderr, 4199138940bfSMeador Inge "qemu: missing argument for option '%s'\n", r); 42004d1275c2SRiku Voipio exit(EXIT_FAILURE); 4201fc9c5412SJohannes Schauer } 4202fc9c5412SJohannes Schauer arginfo->handle_opt(argv[optind]); 4203fc9c5412SJohannes Schauer optind++; 42041386d4c0SPeter Maydell } else { 42051386d4c0SPeter Maydell arginfo->handle_opt(NULL); 4206fc9c5412SJohannes Schauer } 4207fc9c5412SJohannes Schauer break; 4208fc9c5412SJohannes Schauer } 4209fc9c5412SJohannes Schauer } 4210fc9c5412SJohannes Schauer 4211fc9c5412SJohannes Schauer /* no option matched the current argv */ 4212fc9c5412SJohannes Schauer if (arginfo->handle_opt == NULL) { 4213138940bfSMeador Inge (void) fprintf(stderr, "qemu: unknown option '%s'\n", r); 42144d1275c2SRiku Voipio exit(EXIT_FAILURE); 4215fc9c5412SJohannes Schauer } 4216fc9c5412SJohannes Schauer } 4217fc9c5412SJohannes Schauer 4218fc9c5412SJohannes Schauer if (optind >= argc) { 4219138940bfSMeador Inge (void) fprintf(stderr, "qemu: no user program specified\n"); 42204d1275c2SRiku Voipio exit(EXIT_FAILURE); 4221fc9c5412SJohannes Schauer } 4222fc9c5412SJohannes Schauer 4223fc9c5412SJohannes Schauer filename = argv[optind]; 4224fc9c5412SJohannes Schauer exec_path = argv[optind]; 4225fc9c5412SJohannes Schauer 4226fc9c5412SJohannes Schauer return optind; 4227fc9c5412SJohannes Schauer } 4228fc9c5412SJohannes Schauer 4229902b3d5cSmalc int main(int argc, char **argv, char **envp) 423031e31b8aSbellard { 423101ffc75bSbellard struct target_pt_regs regs1, *regs = ®s1; 423231e31b8aSbellard struct image_info info1, *info = &info1; 4233edf8e2afSMika Westerberg struct linux_binprm bprm; 423448e15fc2SNathan Froyd TaskState *ts; 42359349b4f9SAndreas Färber CPUArchState *env; 4236db6b81d4SAndreas Färber CPUState *cpu; 4237586314f2Sbellard int optind; 423804a6dfebSaurel32 char **target_environ, **wrk; 42397d8cec95Saurel32 char **target_argv; 42407d8cec95Saurel32 int target_argc; 42417d8cec95Saurel32 int i; 4242fd4d81ddSArnaud Patard int ret; 424303cfd8faSLaurent Vivier int execfd; 424431e31b8aSbellard 4245fe4db84dSDaniel P. Berrange module_call_init(MODULE_INIT_TRACE); 4246267f685bSPaolo Bonzini qemu_init_cpu_list(); 4247ce008c1fSAndreas Färber module_call_init(MODULE_INIT_QOM); 4248ce008c1fSAndreas Färber 4249ec45bbe5SSaurav Sachidanand envlist = envlist_create(); 425004a6dfebSaurel32 425104a6dfebSaurel32 /* add current environment into the list */ 425204a6dfebSaurel32 for (wrk = environ; *wrk != NULL; wrk++) { 425304a6dfebSaurel32 (void) envlist_setenv(envlist, *wrk); 425404a6dfebSaurel32 } 425504a6dfebSaurel32 4256703e0e89SRichard Henderson /* Read the stack limit from the kernel. If it's "unlimited", 4257703e0e89SRichard Henderson then we can do little else besides use the default. */ 4258703e0e89SRichard Henderson { 4259703e0e89SRichard Henderson struct rlimit lim; 4260703e0e89SRichard Henderson if (getrlimit(RLIMIT_STACK, &lim) == 0 426181bbe906Stakasi-y@ops.dti.ne.jp && lim.rlim_cur != RLIM_INFINITY 426281bbe906Stakasi-y@ops.dti.ne.jp && lim.rlim_cur == (target_long)lim.rlim_cur) { 4263703e0e89SRichard Henderson guest_stack_size = lim.rlim_cur; 4264703e0e89SRichard Henderson } 4265703e0e89SRichard Henderson } 4266703e0e89SRichard Henderson 4267b1f9be31Sj_mayer cpu_model = NULL; 4268b5ec5ce0Sjohn cooper 4269c5e4a5a9SMagnus Reftel srand(time(NULL)); 4270c5e4a5a9SMagnus Reftel 42716533dd6eSLluís Vilanova qemu_add_opts(&qemu_trace_opts); 42726533dd6eSLluís Vilanova 4273fc9c5412SJohannes Schauer optind = parse_args(argc, argv); 42744b5dfd82SPeter Maydell 42756533dd6eSLluís Vilanova if (!trace_init_backends()) { 42766533dd6eSLluís Vilanova exit(1); 42776533dd6eSLluís Vilanova } 42786533dd6eSLluís Vilanova trace_init_file(trace_file); 42796533dd6eSLluís Vilanova 428031e31b8aSbellard /* Zero out regs */ 428101ffc75bSbellard memset(regs, 0, sizeof(struct target_pt_regs)); 428231e31b8aSbellard 428331e31b8aSbellard /* Zero out image_info */ 428431e31b8aSbellard memset(info, 0, sizeof(struct image_info)); 428531e31b8aSbellard 4286edf8e2afSMika Westerberg memset(&bprm, 0, sizeof (bprm)); 4287edf8e2afSMika Westerberg 428874cd30b8Sbellard /* Scan interp_prefix dir for replacement files. */ 428974cd30b8Sbellard init_paths(interp_prefix); 429074cd30b8Sbellard 42914a24a758SPeter Maydell init_qemu_uname_release(); 42924a24a758SPeter Maydell 429346027c07Sbellard if (cpu_model == NULL) { 4294aaed909aSbellard #if defined(TARGET_I386) 429546027c07Sbellard #ifdef TARGET_X86_64 429646027c07Sbellard cpu_model = "qemu64"; 429746027c07Sbellard #else 429846027c07Sbellard cpu_model = "qemu32"; 429946027c07Sbellard #endif 4300aaed909aSbellard #elif defined(TARGET_ARM) 4301088ab16cSpbrook cpu_model = "any"; 4302d2fbca94SGuan Xuetao #elif defined(TARGET_UNICORE32) 4303d2fbca94SGuan Xuetao cpu_model = "any"; 4304aaed909aSbellard #elif defined(TARGET_M68K) 4305aaed909aSbellard cpu_model = "any"; 4306aaed909aSbellard #elif defined(TARGET_SPARC) 4307aaed909aSbellard #ifdef TARGET_SPARC64 4308aaed909aSbellard cpu_model = "TI UltraSparc II"; 4309aaed909aSbellard #else 4310aaed909aSbellard cpu_model = "Fujitsu MB86904"; 431146027c07Sbellard #endif 4312aaed909aSbellard #elif defined(TARGET_MIPS) 4313aaed909aSbellard #if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) 431474797f40SMaciej W. Rozycki cpu_model = "5KEf"; 4315aaed909aSbellard #else 4316aaed909aSbellard cpu_model = "24Kf"; 4317aaed909aSbellard #endif 4318d962783eSJia Liu #elif defined TARGET_OPENRISC 4319d962783eSJia Liu cpu_model = "or1200"; 4320aaed909aSbellard #elif defined(TARGET_PPC) 43217ded4f52Sbellard # ifdef TARGET_PPC64 4322de3f1b98SLaurent Vivier cpu_model = "POWER8"; 43237ded4f52Sbellard # else 4324aaed909aSbellard cpu_model = "750"; 43257ded4f52Sbellard # endif 432691c45a38SRichard Henderson #elif defined TARGET_SH4 432791c45a38SRichard Henderson cpu_model = TYPE_SH7785_CPU; 4328d8923bc7SDavid Hildenbrand #elif defined TARGET_S390X 4329d8923bc7SDavid Hildenbrand cpu_model = "qemu"; 4330aaed909aSbellard #else 4331aaed909aSbellard cpu_model = "any"; 4332aaed909aSbellard #endif 4333aaed909aSbellard } 4334d5ab9713SJan Kiszka tcg_exec_init(0); 433583fb7adfSbellard /* NOTE: we need to init the CPU at this stage to get 433683fb7adfSbellard qemu_host_page_size */ 43372994fd96SEduardo Habkost cpu = cpu_init(cpu_model); 43382994fd96SEduardo Habkost env = cpu->env_ptr; 43390ac46af3SAndreas Färber cpu_reset(cpu); 4340b55a37c9SBlue Swirl 4341db6b81d4SAndreas Färber thread_cpu = cpu; 434254936004Sbellard 4343b92c47c1Sths if (getenv("QEMU_STRACE")) { 4344b92c47c1Sths do_strace = 1; 4345b92c47c1Sths } 4346b92c47c1Sths 4347c5e4a5a9SMagnus Reftel if (getenv("QEMU_RAND_SEED")) { 4348c5e4a5a9SMagnus Reftel handle_arg_randseed(getenv("QEMU_RAND_SEED")); 4349c5e4a5a9SMagnus Reftel } 4350c5e4a5a9SMagnus Reftel 435104a6dfebSaurel32 target_environ = envlist_to_environ(envlist, NULL); 435204a6dfebSaurel32 envlist_free(envlist); 4353b12b6a18Sths 4354379f6698SPaul Brook /* 4355379f6698SPaul Brook * Now that page sizes are configured in cpu_init() we can do 4356379f6698SPaul Brook * proper page alignment for guest_base. 4357379f6698SPaul Brook */ 4358379f6698SPaul Brook guest_base = HOST_PAGE_ALIGN(guest_base); 435968a1c816SPaul Brook 436097cc7560SDr. David Alan Gilbert if (reserved_va || have_guest_base) { 4361806d1021SMeador Inge guest_base = init_guest_space(guest_base, reserved_va, 0, 4362806d1021SMeador Inge have_guest_base); 4363806d1021SMeador Inge if (guest_base == (unsigned long)-1) { 4364097b8cb8SPeter Maydell fprintf(stderr, "Unable to reserve 0x%lx bytes of virtual address " 4365097b8cb8SPeter Maydell "space for use as guest address space (check your virtual " 4366097b8cb8SPeter Maydell "memory ulimit setting or reserve less using -R option)\n", 4367097b8cb8SPeter Maydell reserved_va); 43684d1275c2SRiku Voipio exit(EXIT_FAILURE); 436997cc7560SDr. David Alan Gilbert } 4370806d1021SMeador Inge 4371806d1021SMeador Inge if (reserved_va) { 4372806d1021SMeador Inge mmap_next_start = reserved_va; 4373806d1021SMeador Inge } 437497cc7560SDr. David Alan Gilbert } 4375379f6698SPaul Brook 4376379f6698SPaul Brook /* 4377379f6698SPaul Brook * Read in mmap_min_addr kernel parameter. This value is used 4378379f6698SPaul Brook * When loading the ELF image to determine whether guest_base 437914f24e14SRichard Henderson * is needed. It is also used in mmap_find_vma. 4380379f6698SPaul Brook */ 438114f24e14SRichard Henderson { 4382379f6698SPaul Brook FILE *fp; 4383379f6698SPaul Brook 4384379f6698SPaul Brook if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) { 4385379f6698SPaul Brook unsigned long tmp; 4386379f6698SPaul Brook if (fscanf(fp, "%lu", &tmp) == 1) { 4387379f6698SPaul Brook mmap_min_addr = tmp; 438813829020SPaolo Bonzini qemu_log_mask(CPU_LOG_PAGE, "host mmap_min_addr=0x%lx\n", mmap_min_addr); 4389379f6698SPaul Brook } 4390379f6698SPaul Brook fclose(fp); 4391379f6698SPaul Brook } 4392379f6698SPaul Brook } 4393379f6698SPaul Brook 43947d8cec95Saurel32 /* 43957d8cec95Saurel32 * Prepare copy of argv vector for target. 43967d8cec95Saurel32 */ 43977d8cec95Saurel32 target_argc = argc - optind; 43987d8cec95Saurel32 target_argv = calloc(target_argc + 1, sizeof (char *)); 43997d8cec95Saurel32 if (target_argv == NULL) { 44007d8cec95Saurel32 (void) fprintf(stderr, "Unable to allocate memory for target_argv\n"); 44014d1275c2SRiku Voipio exit(EXIT_FAILURE); 44027d8cec95Saurel32 } 44037d8cec95Saurel32 44047d8cec95Saurel32 /* 44057d8cec95Saurel32 * If argv0 is specified (using '-0' switch) we replace 44067d8cec95Saurel32 * argv[0] pointer with the given one. 44077d8cec95Saurel32 */ 44087d8cec95Saurel32 i = 0; 44097d8cec95Saurel32 if (argv0 != NULL) { 44107d8cec95Saurel32 target_argv[i++] = strdup(argv0); 44117d8cec95Saurel32 } 44127d8cec95Saurel32 for (; i < target_argc; i++) { 44137d8cec95Saurel32 target_argv[i] = strdup(argv[optind + i]); 44147d8cec95Saurel32 } 44157d8cec95Saurel32 target_argv[target_argc] = NULL; 44167d8cec95Saurel32 4417c78d65e8SMarkus Armbruster ts = g_new0(TaskState, 1); 4418edf8e2afSMika Westerberg init_task_state(ts); 4419edf8e2afSMika Westerberg /* build Task State */ 4420edf8e2afSMika Westerberg ts->info = info; 4421edf8e2afSMika Westerberg ts->bprm = &bprm; 44220429a971SAndreas Färber cpu->opaque = ts; 4423edf8e2afSMika Westerberg task_settid(ts); 4424edf8e2afSMika Westerberg 44250b959cf5SRichard Henderson execfd = qemu_getauxval(AT_EXECFD); 44260b959cf5SRichard Henderson if (execfd == 0) { 442703cfd8faSLaurent Vivier execfd = open(filename, O_RDONLY); 442803cfd8faSLaurent Vivier if (execfd < 0) { 44290b959cf5SRichard Henderson printf("Error while loading %s: %s\n", filename, strerror(errno)); 44304d1275c2SRiku Voipio _exit(EXIT_FAILURE); 443103cfd8faSLaurent Vivier } 44320b959cf5SRichard Henderson } 443303cfd8faSLaurent Vivier 443403cfd8faSLaurent Vivier ret = loader_exec(execfd, filename, target_argv, target_environ, regs, 4435fd4d81ddSArnaud Patard info, &bprm); 4436fd4d81ddSArnaud Patard if (ret != 0) { 4437885c1d10SPeter Maydell printf("Error while loading %s: %s\n", filename, strerror(-ret)); 44384d1275c2SRiku Voipio _exit(EXIT_FAILURE); 443931e31b8aSbellard } 444031e31b8aSbellard 4441b12b6a18Sths for (wrk = target_environ; *wrk; wrk++) { 4442ec45bbe5SSaurav Sachidanand g_free(*wrk); 4443b12b6a18Sths } 4444b12b6a18Sths 4445ec45bbe5SSaurav Sachidanand g_free(target_environ); 4446b12b6a18Sths 444713829020SPaolo Bonzini if (qemu_loglevel_mask(CPU_LOG_PAGE)) { 4448379f6698SPaul Brook qemu_log("guest_base 0x%lx\n", guest_base); 444993fcfe39Saliguori log_page_dump(); 445054936004Sbellard 445193fcfe39Saliguori qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk); 445293fcfe39Saliguori qemu_log("end_code 0x" TARGET_ABI_FMT_lx "\n", info->end_code); 44537c4ee5bcSRichard Henderson qemu_log("start_code 0x" TARGET_ABI_FMT_lx "\n", info->start_code); 44547c4ee5bcSRichard Henderson qemu_log("start_data 0x" TARGET_ABI_FMT_lx "\n", info->start_data); 445593fcfe39Saliguori qemu_log("end_data 0x" TARGET_ABI_FMT_lx "\n", info->end_data); 44567c4ee5bcSRichard Henderson qemu_log("start_stack 0x" TARGET_ABI_FMT_lx "\n", info->start_stack); 445793fcfe39Saliguori qemu_log("brk 0x" TARGET_ABI_FMT_lx "\n", info->brk); 445893fcfe39Saliguori qemu_log("entry 0x" TARGET_ABI_FMT_lx "\n", info->entry); 44597c4ee5bcSRichard Henderson qemu_log("argv_start 0x" TARGET_ABI_FMT_lx "\n", info->arg_start); 44607c4ee5bcSRichard Henderson qemu_log("env_start 0x" TARGET_ABI_FMT_lx "\n", 44617c4ee5bcSRichard Henderson info->arg_end + (abi_ulong)sizeof(abi_ulong)); 44627c4ee5bcSRichard Henderson qemu_log("auxv_start 0x" TARGET_ABI_FMT_lx "\n", info->saved_auxv); 44632e77eac6Sblueswir1 } 446431e31b8aSbellard 446553a5960aSpbrook target_set_brk(info->brk); 446631e31b8aSbellard syscall_init(); 446766fb9763Sbellard signal_init(); 446831e31b8aSbellard 44699002ec79SRichard Henderson /* Now that we've loaded the binary, GUEST_BASE is fixed. Delay 44709002ec79SRichard Henderson generating the prologue until now so that the prologue can take 44719002ec79SRichard Henderson the real value of GUEST_BASE into account. */ 44729002ec79SRichard Henderson tcg_prologue_init(&tcg_ctx); 44739002ec79SRichard Henderson 4474b346ff46Sbellard #if defined(TARGET_I386) 44753802ce26Sbellard env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK; 4476b98dbc90SPaolo Bonzini env->hflags |= HF_PE_MASK | HF_CPL_MASK; 44770514ef2fSEduardo Habkost if (env->features[FEAT_1_EDX] & CPUID_SSE) { 44781bde465eSbellard env->cr[4] |= CR4_OSFXSR_MASK; 44791bde465eSbellard env->hflags |= HF_OSFXSR_MASK; 44801bde465eSbellard } 4481d2fd1af7Sbellard #ifndef TARGET_ABI32 44824dbc422bSbellard /* enable 64 bit mode if possible */ 44830514ef2fSEduardo Habkost if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM)) { 44844dbc422bSbellard fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n"); 44854d1275c2SRiku Voipio exit(EXIT_FAILURE); 44864dbc422bSbellard } 4487d2fd1af7Sbellard env->cr[4] |= CR4_PAE_MASK; 44884dbc422bSbellard env->efer |= MSR_EFER_LMA | MSR_EFER_LME; 4489d2fd1af7Sbellard env->hflags |= HF_LMA_MASK; 4490d2fd1af7Sbellard #endif 44913802ce26Sbellard 4492415e561fSbellard /* flags setup : we activate the IRQs by default as in user mode */ 4493415e561fSbellard env->eflags |= IF_MASK; 4494415e561fSbellard 44956dbad63eSbellard /* linux register setup */ 4496d2fd1af7Sbellard #ifndef TARGET_ABI32 449784409ddbSj_mayer env->regs[R_EAX] = regs->rax; 449884409ddbSj_mayer env->regs[R_EBX] = regs->rbx; 449984409ddbSj_mayer env->regs[R_ECX] = regs->rcx; 450084409ddbSj_mayer env->regs[R_EDX] = regs->rdx; 450184409ddbSj_mayer env->regs[R_ESI] = regs->rsi; 450284409ddbSj_mayer env->regs[R_EDI] = regs->rdi; 450384409ddbSj_mayer env->regs[R_EBP] = regs->rbp; 450484409ddbSj_mayer env->regs[R_ESP] = regs->rsp; 450584409ddbSj_mayer env->eip = regs->rip; 450684409ddbSj_mayer #else 45070ecfa993Sbellard env->regs[R_EAX] = regs->eax; 45080ecfa993Sbellard env->regs[R_EBX] = regs->ebx; 45090ecfa993Sbellard env->regs[R_ECX] = regs->ecx; 45100ecfa993Sbellard env->regs[R_EDX] = regs->edx; 45110ecfa993Sbellard env->regs[R_ESI] = regs->esi; 45120ecfa993Sbellard env->regs[R_EDI] = regs->edi; 45130ecfa993Sbellard env->regs[R_EBP] = regs->ebp; 45140ecfa993Sbellard env->regs[R_ESP] = regs->esp; 4515dab2ed99Sbellard env->eip = regs->eip; 451684409ddbSj_mayer #endif 451731e31b8aSbellard 4518f4beb510Sbellard /* linux interrupt setup */ 4519e441570fSbalrog #ifndef TARGET_ABI32 4520e441570fSbalrog env->idt.limit = 511; 4521e441570fSbalrog #else 4522e441570fSbalrog env->idt.limit = 255; 4523e441570fSbalrog #endif 4524e441570fSbalrog env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1), 4525e441570fSbalrog PROT_READ|PROT_WRITE, 4526e441570fSbalrog MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); 4527e441570fSbalrog idt_table = g2h(env->idt.base); 4528f4beb510Sbellard set_idt(0, 0); 4529f4beb510Sbellard set_idt(1, 0); 4530f4beb510Sbellard set_idt(2, 0); 4531f4beb510Sbellard set_idt(3, 3); 4532f4beb510Sbellard set_idt(4, 3); 4533ec95da6cSbellard set_idt(5, 0); 4534f4beb510Sbellard set_idt(6, 0); 4535f4beb510Sbellard set_idt(7, 0); 4536f4beb510Sbellard set_idt(8, 0); 4537f4beb510Sbellard set_idt(9, 0); 4538f4beb510Sbellard set_idt(10, 0); 4539f4beb510Sbellard set_idt(11, 0); 4540f4beb510Sbellard set_idt(12, 0); 4541f4beb510Sbellard set_idt(13, 0); 4542f4beb510Sbellard set_idt(14, 0); 4543f4beb510Sbellard set_idt(15, 0); 4544f4beb510Sbellard set_idt(16, 0); 4545f4beb510Sbellard set_idt(17, 0); 4546f4beb510Sbellard set_idt(18, 0); 4547f4beb510Sbellard set_idt(19, 0); 4548f4beb510Sbellard set_idt(0x80, 3); 4549f4beb510Sbellard 45506dbad63eSbellard /* linux segment setup */ 45518d18e893Sbellard { 45528d18e893Sbellard uint64_t *gdt_table; 4553e441570fSbalrog env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES, 4554e441570fSbalrog PROT_READ|PROT_WRITE, 4555e441570fSbalrog MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); 45568d18e893Sbellard env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1; 4557e441570fSbalrog gdt_table = g2h(env->gdt.base); 4558d2fd1af7Sbellard #ifdef TARGET_ABI32 4559f4beb510Sbellard write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff, 4560f4beb510Sbellard DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | 4561f4beb510Sbellard (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT)); 4562d2fd1af7Sbellard #else 4563d2fd1af7Sbellard /* 64 bit code segment */ 4564d2fd1af7Sbellard write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff, 4565d2fd1af7Sbellard DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | 4566d2fd1af7Sbellard DESC_L_MASK | 4567d2fd1af7Sbellard (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT)); 4568d2fd1af7Sbellard #endif 4569f4beb510Sbellard write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff, 4570f4beb510Sbellard DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | 4571f4beb510Sbellard (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT)); 45728d18e893Sbellard } 45736dbad63eSbellard cpu_x86_load_seg(env, R_CS, __USER_CS); 4574d2fd1af7Sbellard cpu_x86_load_seg(env, R_SS, __USER_DS); 4575d2fd1af7Sbellard #ifdef TARGET_ABI32 45766dbad63eSbellard cpu_x86_load_seg(env, R_DS, __USER_DS); 45776dbad63eSbellard cpu_x86_load_seg(env, R_ES, __USER_DS); 45786dbad63eSbellard cpu_x86_load_seg(env, R_FS, __USER_DS); 45796dbad63eSbellard cpu_x86_load_seg(env, R_GS, __USER_DS); 4580d6eb40f6Sths /* This hack makes Wine work... */ 4581d6eb40f6Sths env->segs[R_FS].selector = 0; 4582d2fd1af7Sbellard #else 4583d2fd1af7Sbellard cpu_x86_load_seg(env, R_DS, 0); 4584d2fd1af7Sbellard cpu_x86_load_seg(env, R_ES, 0); 4585d2fd1af7Sbellard cpu_x86_load_seg(env, R_FS, 0); 4586d2fd1af7Sbellard cpu_x86_load_seg(env, R_GS, 0); 4587d2fd1af7Sbellard #endif 458899033caeSAlexander Graf #elif defined(TARGET_AARCH64) 458999033caeSAlexander Graf { 459099033caeSAlexander Graf int i; 459199033caeSAlexander Graf 459299033caeSAlexander Graf if (!(arm_feature(env, ARM_FEATURE_AARCH64))) { 459399033caeSAlexander Graf fprintf(stderr, 459499033caeSAlexander Graf "The selected ARM CPU does not support 64 bit mode\n"); 45954d1275c2SRiku Voipio exit(EXIT_FAILURE); 459699033caeSAlexander Graf } 459799033caeSAlexander Graf 459899033caeSAlexander Graf for (i = 0; i < 31; i++) { 459999033caeSAlexander Graf env->xregs[i] = regs->regs[i]; 460099033caeSAlexander Graf } 460199033caeSAlexander Graf env->pc = regs->pc; 460299033caeSAlexander Graf env->xregs[31] = regs->sp; 460399033caeSAlexander Graf } 4604b346ff46Sbellard #elif defined(TARGET_ARM) 4605b346ff46Sbellard { 4606b346ff46Sbellard int i; 4607ae087923SPeter Maydell cpsr_write(env, regs->uregs[16], CPSR_USER | CPSR_EXEC, 4608ae087923SPeter Maydell CPSRWriteByInstr); 4609b346ff46Sbellard for(i = 0; i < 16; i++) { 4610b346ff46Sbellard env->regs[i] = regs->uregs[i]; 4611b346ff46Sbellard } 4612f9fd40ebSPaolo Bonzini #ifdef TARGET_WORDS_BIGENDIAN 4613d8fd2954SPaul Brook /* Enable BE8. */ 4614d8fd2954SPaul Brook if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4 4615d8fd2954SPaul Brook && (info->elf_flags & EF_ARM_BE8)) { 46169c5a7460SPeter Crosthwaite env->uncached_cpsr |= CPSR_E; 46179c5a7460SPeter Crosthwaite env->cp15.sctlr_el[1] |= SCTLR_E0E; 4618f9fd40ebSPaolo Bonzini } else { 4619f9fd40ebSPaolo Bonzini env->cp15.sctlr_el[1] |= SCTLR_B; 4620d8fd2954SPaul Brook } 4621f9fd40ebSPaolo Bonzini #endif 4622b346ff46Sbellard } 4623d2fbca94SGuan Xuetao #elif defined(TARGET_UNICORE32) 4624d2fbca94SGuan Xuetao { 4625d2fbca94SGuan Xuetao int i; 4626d2fbca94SGuan Xuetao cpu_asr_write(env, regs->uregs[32], 0xffffffff); 4627d2fbca94SGuan Xuetao for (i = 0; i < 32; i++) { 4628d2fbca94SGuan Xuetao env->regs[i] = regs->uregs[i]; 4629d2fbca94SGuan Xuetao } 4630d2fbca94SGuan Xuetao } 463193ac68bcSbellard #elif defined(TARGET_SPARC) 4632060366c5Sbellard { 4633060366c5Sbellard int i; 4634060366c5Sbellard env->pc = regs->pc; 4635060366c5Sbellard env->npc = regs->npc; 4636060366c5Sbellard env->y = regs->y; 4637060366c5Sbellard for(i = 0; i < 8; i++) 4638060366c5Sbellard env->gregs[i] = regs->u_regs[i]; 4639060366c5Sbellard for(i = 0; i < 8; i++) 4640060366c5Sbellard env->regwptr[i] = regs->u_regs[i + 8]; 4641060366c5Sbellard } 464267867308Sbellard #elif defined(TARGET_PPC) 464367867308Sbellard { 464467867308Sbellard int i; 46453fc6c082Sbellard 46460411a972Sj_mayer #if defined(TARGET_PPC64) 4647c8361129SMichael Walle int flag = (env->insns_flags2 & PPC2_BOOKE206) ? MSR_CM : MSR_SF; 46480411a972Sj_mayer #if defined(TARGET_ABI32) 4649c8361129SMichael Walle env->msr &= ~((target_ulong)1 << flag); 4650e85e7c6eSj_mayer #else 4651c8361129SMichael Walle env->msr |= (target_ulong)1 << flag; 46520411a972Sj_mayer #endif 465384409ddbSj_mayer #endif 465467867308Sbellard env->nip = regs->nip; 465567867308Sbellard for(i = 0; i < 32; i++) { 465667867308Sbellard env->gpr[i] = regs->gpr[i]; 465767867308Sbellard } 465867867308Sbellard } 4659e6e5906bSpbrook #elif defined(TARGET_M68K) 4660e6e5906bSpbrook { 4661e6e5906bSpbrook env->pc = regs->pc; 4662e6e5906bSpbrook env->dregs[0] = regs->d0; 4663e6e5906bSpbrook env->dregs[1] = regs->d1; 4664e6e5906bSpbrook env->dregs[2] = regs->d2; 4665e6e5906bSpbrook env->dregs[3] = regs->d3; 4666e6e5906bSpbrook env->dregs[4] = regs->d4; 4667e6e5906bSpbrook env->dregs[5] = regs->d5; 4668e6e5906bSpbrook env->dregs[6] = regs->d6; 4669e6e5906bSpbrook env->dregs[7] = regs->d7; 4670e6e5906bSpbrook env->aregs[0] = regs->a0; 4671e6e5906bSpbrook env->aregs[1] = regs->a1; 4672e6e5906bSpbrook env->aregs[2] = regs->a2; 4673e6e5906bSpbrook env->aregs[3] = regs->a3; 4674e6e5906bSpbrook env->aregs[4] = regs->a4; 4675e6e5906bSpbrook env->aregs[5] = regs->a5; 4676e6e5906bSpbrook env->aregs[6] = regs->a6; 4677e6e5906bSpbrook env->aregs[7] = regs->usp; 4678e6e5906bSpbrook env->sr = regs->sr; 4679e6e5906bSpbrook ts->sim_syscalls = 1; 4680e6e5906bSpbrook } 4681b779e29eSEdgar E. Iglesias #elif defined(TARGET_MICROBLAZE) 4682b779e29eSEdgar E. Iglesias { 4683b779e29eSEdgar E. Iglesias env->regs[0] = regs->r0; 4684b779e29eSEdgar E. Iglesias env->regs[1] = regs->r1; 4685b779e29eSEdgar E. Iglesias env->regs[2] = regs->r2; 4686b779e29eSEdgar E. Iglesias env->regs[3] = regs->r3; 4687b779e29eSEdgar E. Iglesias env->regs[4] = regs->r4; 4688b779e29eSEdgar E. Iglesias env->regs[5] = regs->r5; 4689b779e29eSEdgar E. Iglesias env->regs[6] = regs->r6; 4690b779e29eSEdgar E. Iglesias env->regs[7] = regs->r7; 4691b779e29eSEdgar E. Iglesias env->regs[8] = regs->r8; 4692b779e29eSEdgar E. Iglesias env->regs[9] = regs->r9; 4693b779e29eSEdgar E. Iglesias env->regs[10] = regs->r10; 4694b779e29eSEdgar E. Iglesias env->regs[11] = regs->r11; 4695b779e29eSEdgar E. Iglesias env->regs[12] = regs->r12; 4696b779e29eSEdgar E. Iglesias env->regs[13] = regs->r13; 4697b779e29eSEdgar E. Iglesias env->regs[14] = regs->r14; 4698b779e29eSEdgar E. Iglesias env->regs[15] = regs->r15; 4699b779e29eSEdgar E. Iglesias env->regs[16] = regs->r16; 4700b779e29eSEdgar E. Iglesias env->regs[17] = regs->r17; 4701b779e29eSEdgar E. Iglesias env->regs[18] = regs->r18; 4702b779e29eSEdgar E. Iglesias env->regs[19] = regs->r19; 4703b779e29eSEdgar E. Iglesias env->regs[20] = regs->r20; 4704b779e29eSEdgar E. Iglesias env->regs[21] = regs->r21; 4705b779e29eSEdgar E. Iglesias env->regs[22] = regs->r22; 4706b779e29eSEdgar E. Iglesias env->regs[23] = regs->r23; 4707b779e29eSEdgar E. Iglesias env->regs[24] = regs->r24; 4708b779e29eSEdgar E. Iglesias env->regs[25] = regs->r25; 4709b779e29eSEdgar E. Iglesias env->regs[26] = regs->r26; 4710b779e29eSEdgar E. Iglesias env->regs[27] = regs->r27; 4711b779e29eSEdgar E. Iglesias env->regs[28] = regs->r28; 4712b779e29eSEdgar E. Iglesias env->regs[29] = regs->r29; 4713b779e29eSEdgar E. Iglesias env->regs[30] = regs->r30; 4714b779e29eSEdgar E. Iglesias env->regs[31] = regs->r31; 4715b779e29eSEdgar E. Iglesias env->sregs[SR_PC] = regs->pc; 4716b779e29eSEdgar E. Iglesias } 4717048f6b4dSbellard #elif defined(TARGET_MIPS) 4718048f6b4dSbellard { 4719048f6b4dSbellard int i; 4720048f6b4dSbellard 4721048f6b4dSbellard for(i = 0; i < 32; i++) { 4722b5dc7732Sths env->active_tc.gpr[i] = regs->regs[i]; 4723048f6b4dSbellard } 47240fddbbf2SNathan Froyd env->active_tc.PC = regs->cp0_epc & ~(target_ulong)1; 47250fddbbf2SNathan Froyd if (regs->cp0_epc & 1) { 47260fddbbf2SNathan Froyd env->hflags |= MIPS_HFLAG_M16; 47270fddbbf2SNathan Froyd } 4728599bc5e8SAleksandar Markovic if (((info->elf_flags & EF_MIPS_NAN2008) != 0) != 4729599bc5e8SAleksandar Markovic ((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) != 0)) { 4730599bc5e8SAleksandar Markovic if ((env->active_fpu.fcr31_rw_bitmask & 4731599bc5e8SAleksandar Markovic (1 << FCR31_NAN2008)) == 0) { 4732599bc5e8SAleksandar Markovic fprintf(stderr, "ELF binary's NaN mode not supported by CPU\n"); 4733599bc5e8SAleksandar Markovic exit(1); 4734599bc5e8SAleksandar Markovic } 4735599bc5e8SAleksandar Markovic if ((info->elf_flags & EF_MIPS_NAN2008) != 0) { 4736599bc5e8SAleksandar Markovic env->active_fpu.fcr31 |= (1 << FCR31_NAN2008); 4737599bc5e8SAleksandar Markovic } else { 4738599bc5e8SAleksandar Markovic env->active_fpu.fcr31 &= ~(1 << FCR31_NAN2008); 4739599bc5e8SAleksandar Markovic } 4740599bc5e8SAleksandar Markovic restore_snan_bit_mode(env); 4741599bc5e8SAleksandar Markovic } 4742048f6b4dSbellard } 4743a0a839b6SMarek Vasut #elif defined(TARGET_NIOS2) 4744a0a839b6SMarek Vasut { 4745a0a839b6SMarek Vasut env->regs[0] = 0; 4746a0a839b6SMarek Vasut env->regs[1] = regs->r1; 4747a0a839b6SMarek Vasut env->regs[2] = regs->r2; 4748a0a839b6SMarek Vasut env->regs[3] = regs->r3; 4749a0a839b6SMarek Vasut env->regs[4] = regs->r4; 4750a0a839b6SMarek Vasut env->regs[5] = regs->r5; 4751a0a839b6SMarek Vasut env->regs[6] = regs->r6; 4752a0a839b6SMarek Vasut env->regs[7] = regs->r7; 4753a0a839b6SMarek Vasut env->regs[8] = regs->r8; 4754a0a839b6SMarek Vasut env->regs[9] = regs->r9; 4755a0a839b6SMarek Vasut env->regs[10] = regs->r10; 4756a0a839b6SMarek Vasut env->regs[11] = regs->r11; 4757a0a839b6SMarek Vasut env->regs[12] = regs->r12; 4758a0a839b6SMarek Vasut env->regs[13] = regs->r13; 4759a0a839b6SMarek Vasut env->regs[14] = regs->r14; 4760a0a839b6SMarek Vasut env->regs[15] = regs->r15; 4761a0a839b6SMarek Vasut /* TODO: unsigned long orig_r2; */ 4762a0a839b6SMarek Vasut env->regs[R_RA] = regs->ra; 4763a0a839b6SMarek Vasut env->regs[R_FP] = regs->fp; 4764a0a839b6SMarek Vasut env->regs[R_SP] = regs->sp; 4765a0a839b6SMarek Vasut env->regs[R_GP] = regs->gp; 4766a0a839b6SMarek Vasut env->regs[CR_ESTATUS] = regs->estatus; 4767a0a839b6SMarek Vasut env->regs[R_EA] = regs->ea; 4768a0a839b6SMarek Vasut /* TODO: unsigned long orig_r7; */ 4769a0a839b6SMarek Vasut 4770a0a839b6SMarek Vasut /* Emulate eret when starting thread. */ 4771a0a839b6SMarek Vasut env->regs[R_PC] = regs->ea; 4772a0a839b6SMarek Vasut } 4773d962783eSJia Liu #elif defined(TARGET_OPENRISC) 4774d962783eSJia Liu { 4775d962783eSJia Liu int i; 4776d962783eSJia Liu 4777d962783eSJia Liu for (i = 0; i < 32; i++) { 4778d89e71e8SStafford Horne cpu_set_gpr(env, i, regs->gpr[i]); 4779d962783eSJia Liu } 4780d962783eSJia Liu env->pc = regs->pc; 478184775c43SRichard Henderson cpu_set_sr(env, regs->sr); 4782d962783eSJia Liu } 4783fdf9b3e8Sbellard #elif defined(TARGET_SH4) 4784fdf9b3e8Sbellard { 4785fdf9b3e8Sbellard int i; 4786fdf9b3e8Sbellard 4787fdf9b3e8Sbellard for(i = 0; i < 16; i++) { 4788fdf9b3e8Sbellard env->gregs[i] = regs->regs[i]; 4789fdf9b3e8Sbellard } 4790fdf9b3e8Sbellard env->pc = regs->pc; 4791fdf9b3e8Sbellard } 47927a3148a9Sj_mayer #elif defined(TARGET_ALPHA) 47937a3148a9Sj_mayer { 47947a3148a9Sj_mayer int i; 47957a3148a9Sj_mayer 47967a3148a9Sj_mayer for(i = 0; i < 28; i++) { 4797992f48a0Sblueswir1 env->ir[i] = ((abi_ulong *)regs)[i]; 47987a3148a9Sj_mayer } 4799dad081eeSRichard Henderson env->ir[IR_SP] = regs->usp; 48007a3148a9Sj_mayer env->pc = regs->pc; 48017a3148a9Sj_mayer } 480248733d19Sths #elif defined(TARGET_CRIS) 480348733d19Sths { 480448733d19Sths env->regs[0] = regs->r0; 480548733d19Sths env->regs[1] = regs->r1; 480648733d19Sths env->regs[2] = regs->r2; 480748733d19Sths env->regs[3] = regs->r3; 480848733d19Sths env->regs[4] = regs->r4; 480948733d19Sths env->regs[5] = regs->r5; 481048733d19Sths env->regs[6] = regs->r6; 481148733d19Sths env->regs[7] = regs->r7; 481248733d19Sths env->regs[8] = regs->r8; 481348733d19Sths env->regs[9] = regs->r9; 481448733d19Sths env->regs[10] = regs->r10; 481548733d19Sths env->regs[11] = regs->r11; 481648733d19Sths env->regs[12] = regs->r12; 481748733d19Sths env->regs[13] = regs->r13; 481848733d19Sths env->regs[14] = info->start_stack; 481948733d19Sths env->regs[15] = regs->acr; 482048733d19Sths env->pc = regs->erp; 482148733d19Sths } 4822a4c075f1SUlrich Hecht #elif defined(TARGET_S390X) 4823a4c075f1SUlrich Hecht { 4824a4c075f1SUlrich Hecht int i; 4825a4c075f1SUlrich Hecht for (i = 0; i < 16; i++) { 4826a4c075f1SUlrich Hecht env->regs[i] = regs->gprs[i]; 4827a4c075f1SUlrich Hecht } 4828a4c075f1SUlrich Hecht env->psw.mask = regs->psw.mask; 4829a4c075f1SUlrich Hecht env->psw.addr = regs->psw.addr; 4830a4c075f1SUlrich Hecht } 4831b16189b2SChen Gang #elif defined(TARGET_TILEGX) 4832b16189b2SChen Gang { 4833b16189b2SChen Gang int i; 4834b16189b2SChen Gang for (i = 0; i < TILEGX_R_COUNT; i++) { 4835b16189b2SChen Gang env->regs[i] = regs->regs[i]; 4836b16189b2SChen Gang } 4837b16189b2SChen Gang for (i = 0; i < TILEGX_SPR_COUNT; i++) { 4838b16189b2SChen Gang env->spregs[i] = 0; 4839b16189b2SChen Gang } 4840b16189b2SChen Gang env->pc = regs->pc; 4841b16189b2SChen Gang } 48427c248bcdSRichard Henderson #elif defined(TARGET_HPPA) 48437c248bcdSRichard Henderson { 48447c248bcdSRichard Henderson int i; 48457c248bcdSRichard Henderson for (i = 1; i < 32; i++) { 48467c248bcdSRichard Henderson env->gr[i] = regs->gr[i]; 48477c248bcdSRichard Henderson } 48487c248bcdSRichard Henderson env->iaoq_f = regs->iaoq[0]; 48497c248bcdSRichard Henderson env->iaoq_b = regs->iaoq[1]; 48507c248bcdSRichard Henderson } 4851b346ff46Sbellard #else 4852b346ff46Sbellard #error unsupported target CPU 4853b346ff46Sbellard #endif 485431e31b8aSbellard 4855d2fbca94SGuan Xuetao #if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32) 4856a87295e8Spbrook ts->stack_base = info->start_stack; 4857a87295e8Spbrook ts->heap_base = info->brk; 4858a87295e8Spbrook /* This will be filled in on the first SYS_HEAPINFO call. */ 4859a87295e8Spbrook ts->heap_limit = 0; 4860a87295e8Spbrook #endif 4861a87295e8Spbrook 486274c33bedSbellard if (gdbstub_port) { 4863ff7a981aSPeter Maydell if (gdbserver_start(gdbstub_port) < 0) { 4864ff7a981aSPeter Maydell fprintf(stderr, "qemu: could not open gdbserver on port %d\n", 4865ff7a981aSPeter Maydell gdbstub_port); 48664d1275c2SRiku Voipio exit(EXIT_FAILURE); 4867ff7a981aSPeter Maydell } 4868db6b81d4SAndreas Färber gdb_handlesig(cpu, 0); 48691fddef4bSbellard } 48701b6b029eSbellard cpu_loop(env); 48711b6b029eSbellard /* never exits */ 487231e31b8aSbellard return 0; 487331e31b8aSbellard } 4874