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 */ 1931e31b8aSbellard #include <stdlib.h> 2031e31b8aSbellard #include <stdio.h> 2131e31b8aSbellard #include <stdarg.h> 2204369ff2Sbellard #include <string.h> 2331e31b8aSbellard #include <errno.h> 240ecfa993Sbellard #include <unistd.h> 25e441570fSbalrog #include <sys/mman.h> 26edf8e2afSMika Westerberg #include <sys/syscall.h> 27703e0e89SRichard Henderson #include <sys/resource.h> 2831e31b8aSbellard 293ef693a0Sbellard #include "qemu.h" 30ca10f867Saurel32 #include "qemu-common.h" 312b41f10eSBlue Swirl #include "cpu.h" 329002ec79SRichard Henderson #include "tcg.h" 331de7afc9SPaolo Bonzini #include "qemu/timer.h" 341de7afc9SPaolo Bonzini #include "qemu/envlist.h" 35d8fd2954SPaul Brook #include "elf.h" 3604a6dfebSaurel32 37d088d664Saurel32 char *exec_path; 38d088d664Saurel32 391b530a6dSaurel32 int singlestep; 408cb76755SStefan Weil static const char *filename; 418cb76755SStefan Weil static const char *argv0; 428cb76755SStefan Weil static int gdbstub_port; 438cb76755SStefan Weil static envlist_t *envlist; 4451fb256aSAndreas Färber static const char *cpu_model; 45379f6698SPaul Brook unsigned long mmap_min_addr; 46379f6698SPaul Brook unsigned long guest_base; 47379f6698SPaul Brook int have_guest_base; 48288e65b9SAlexander Graf #if (TARGET_LONG_BITS == 32) && (HOST_LONG_BITS == 64) 49288e65b9SAlexander Graf /* 50288e65b9SAlexander Graf * When running 32-on-64 we should make sure we can fit all of the possible 51288e65b9SAlexander Graf * guest address space into a contiguous chunk of virtual host memory. 52288e65b9SAlexander Graf * 53288e65b9SAlexander Graf * This way we will never overlap with our own libraries or binaries or stack 54288e65b9SAlexander Graf * or anything else that QEMU maps. 55288e65b9SAlexander Graf */ 56314992b1SAlexander Graf # ifdef TARGET_MIPS 57314992b1SAlexander Graf /* MIPS only supports 31 bits of virtual address space for user space */ 58314992b1SAlexander Graf unsigned long reserved_va = 0x77000000; 59314992b1SAlexander Graf # else 60288e65b9SAlexander Graf unsigned long reserved_va = 0xf7000000; 61314992b1SAlexander Graf # endif 62288e65b9SAlexander Graf #else 6368a1c816SPaul Brook unsigned long reserved_va; 64379f6698SPaul Brook #endif 651b530a6dSaurel32 66d03f9c32SMeador Inge static void usage(int exitcode); 67fc9c5412SJohannes Schauer 687ee2822cSPaolo Bonzini static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX; 69e586822aSRiku Voipio const char *qemu_uname_release; 70586314f2Sbellard 719de5e440Sbellard /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so 729de5e440Sbellard we allocate a bigger stack. Need a better solution, for example 739de5e440Sbellard by remapping the process stack directly at the right place */ 74703e0e89SRichard Henderson unsigned long guest_stack_size = 8 * 1024 * 1024UL; 7531e31b8aSbellard 7631e31b8aSbellard void gemu_log(const char *fmt, ...) 7731e31b8aSbellard { 7831e31b8aSbellard va_list ap; 7931e31b8aSbellard 8031e31b8aSbellard va_start(ap, fmt); 8131e31b8aSbellard vfprintf(stderr, fmt, ap); 8231e31b8aSbellard va_end(ap); 8331e31b8aSbellard } 8431e31b8aSbellard 858fcd3692Sblueswir1 #if defined(TARGET_I386) 8605390248SAndreas Färber int cpu_get_pic_interrupt(CPUX86State *env) 8792ccca6aSbellard { 8892ccca6aSbellard return -1; 8992ccca6aSbellard } 908fcd3692Sblueswir1 #endif 9192ccca6aSbellard 92d5975363Spbrook /***********************************************************/ 93d5975363Spbrook /* Helper routines for implementing atomic operations. */ 94d5975363Spbrook 95d5975363Spbrook /* To implement exclusive operations we force all cpus to syncronise. 96d5975363Spbrook We don't require a full sync, only that no cpus are executing guest code. 97d5975363Spbrook The alternative is to map target atomic ops onto host equivalents, 98d5975363Spbrook which requires quite a lot of per host/target work. */ 99c2764719Spbrook static pthread_mutex_t cpu_list_mutex = PTHREAD_MUTEX_INITIALIZER; 100d5975363Spbrook static pthread_mutex_t exclusive_lock = PTHREAD_MUTEX_INITIALIZER; 101d5975363Spbrook static pthread_cond_t exclusive_cond = PTHREAD_COND_INITIALIZER; 102d5975363Spbrook static pthread_cond_t exclusive_resume = PTHREAD_COND_INITIALIZER; 103d5975363Spbrook static int pending_cpus; 104d5975363Spbrook 105d5975363Spbrook /* Make sure everything is in a consistent state for calling fork(). */ 106d5975363Spbrook void fork_start(void) 107d5975363Spbrook { 108677ef623SKONRAD Frederic qemu_mutex_lock(&tcg_ctx.tb_ctx.tb_lock); 109d5975363Spbrook pthread_mutex_lock(&exclusive_lock); 110d032d1b4SRiku Voipio mmap_fork_start(); 111d5975363Spbrook } 112d5975363Spbrook 113d5975363Spbrook void fork_end(int child) 114d5975363Spbrook { 115d032d1b4SRiku Voipio mmap_fork_end(child); 116d5975363Spbrook if (child) { 117bdc44640SAndreas Färber CPUState *cpu, *next_cpu; 118d5975363Spbrook /* Child processes created by fork() only have a single thread. 119d5975363Spbrook Discard information about the parent threads. */ 120bdc44640SAndreas Färber CPU_FOREACH_SAFE(cpu, next_cpu) { 121bdc44640SAndreas Färber if (cpu != thread_cpu) { 122bdc44640SAndreas Färber QTAILQ_REMOVE(&cpus, thread_cpu, node); 123bdc44640SAndreas Färber } 124bdc44640SAndreas Färber } 125d5975363Spbrook pending_cpus = 0; 126d5975363Spbrook pthread_mutex_init(&exclusive_lock, NULL); 127c2764719Spbrook pthread_mutex_init(&cpu_list_mutex, NULL); 128d5975363Spbrook pthread_cond_init(&exclusive_cond, NULL); 129d5975363Spbrook pthread_cond_init(&exclusive_resume, NULL); 130677ef623SKONRAD Frederic qemu_mutex_init(&tcg_ctx.tb_ctx.tb_lock); 131f7ec7f7bSPeter Crosthwaite gdbserver_fork(thread_cpu); 132d5975363Spbrook } else { 133d5975363Spbrook pthread_mutex_unlock(&exclusive_lock); 134677ef623SKONRAD Frederic qemu_mutex_unlock(&tcg_ctx.tb_ctx.tb_lock); 135d5975363Spbrook } 136d5975363Spbrook } 137d5975363Spbrook 138d5975363Spbrook /* Wait for pending exclusive operations to complete. The exclusive lock 139d5975363Spbrook must be held. */ 140d5975363Spbrook static inline void exclusive_idle(void) 141d5975363Spbrook { 142d5975363Spbrook while (pending_cpus) { 143d5975363Spbrook pthread_cond_wait(&exclusive_resume, &exclusive_lock); 144d5975363Spbrook } 145d5975363Spbrook } 146d5975363Spbrook 147d5975363Spbrook /* Start an exclusive operation. 148d5975363Spbrook Must only be called from outside cpu_arm_exec. */ 149d5975363Spbrook static inline void start_exclusive(void) 150d5975363Spbrook { 1510315c31cSAndreas Färber CPUState *other_cpu; 1520315c31cSAndreas Färber 153d5975363Spbrook pthread_mutex_lock(&exclusive_lock); 154d5975363Spbrook exclusive_idle(); 155d5975363Spbrook 156d5975363Spbrook pending_cpus = 1; 157d5975363Spbrook /* Make all other cpus stop executing. */ 158bdc44640SAndreas Färber CPU_FOREACH(other_cpu) { 1590315c31cSAndreas Färber if (other_cpu->running) { 160d5975363Spbrook pending_cpus++; 16160a3e17aSAndreas Färber cpu_exit(other_cpu); 162d5975363Spbrook } 163d5975363Spbrook } 164d5975363Spbrook if (pending_cpus > 1) { 165d5975363Spbrook pthread_cond_wait(&exclusive_cond, &exclusive_lock); 166d5975363Spbrook } 167d5975363Spbrook } 168d5975363Spbrook 169d5975363Spbrook /* Finish an exclusive operation. */ 170f7e61b22SPeter Maydell static inline void __attribute__((unused)) end_exclusive(void) 171d5975363Spbrook { 172d5975363Spbrook pending_cpus = 0; 173d5975363Spbrook pthread_cond_broadcast(&exclusive_resume); 174d5975363Spbrook pthread_mutex_unlock(&exclusive_lock); 175d5975363Spbrook } 176d5975363Spbrook 177d5975363Spbrook /* Wait for exclusive ops to finish, and begin cpu execution. */ 1780315c31cSAndreas Färber static inline void cpu_exec_start(CPUState *cpu) 179d5975363Spbrook { 180d5975363Spbrook pthread_mutex_lock(&exclusive_lock); 181d5975363Spbrook exclusive_idle(); 1820315c31cSAndreas Färber cpu->running = true; 183d5975363Spbrook pthread_mutex_unlock(&exclusive_lock); 184d5975363Spbrook } 185d5975363Spbrook 186d5975363Spbrook /* Mark cpu as not executing, and release pending exclusive ops. */ 1870315c31cSAndreas Färber static inline void cpu_exec_end(CPUState *cpu) 188d5975363Spbrook { 189d5975363Spbrook pthread_mutex_lock(&exclusive_lock); 1900315c31cSAndreas Färber cpu->running = false; 191d5975363Spbrook if (pending_cpus > 1) { 192d5975363Spbrook pending_cpus--; 193d5975363Spbrook if (pending_cpus == 1) { 194d5975363Spbrook pthread_cond_signal(&exclusive_cond); 195d5975363Spbrook } 196d5975363Spbrook } 197d5975363Spbrook exclusive_idle(); 198d5975363Spbrook pthread_mutex_unlock(&exclusive_lock); 199d5975363Spbrook } 200c2764719Spbrook 201c2764719Spbrook void cpu_list_lock(void) 202c2764719Spbrook { 203c2764719Spbrook pthread_mutex_lock(&cpu_list_mutex); 204c2764719Spbrook } 205c2764719Spbrook 206c2764719Spbrook void cpu_list_unlock(void) 207c2764719Spbrook { 208c2764719Spbrook pthread_mutex_unlock(&cpu_list_mutex); 209c2764719Spbrook } 210d5975363Spbrook 211d5975363Spbrook 212a541f297Sbellard #ifdef TARGET_I386 213a541f297Sbellard /***********************************************************/ 214a541f297Sbellard /* CPUX86 core interface */ 215a541f297Sbellard 21628ab0e2eSbellard uint64_t cpu_get_tsc(CPUX86State *env) 21728ab0e2eSbellard { 21828ab0e2eSbellard return cpu_get_real_ticks(); 21928ab0e2eSbellard } 22028ab0e2eSbellard 221f4beb510Sbellard static void write_dt(void *ptr, unsigned long addr, unsigned long limit, 222f4beb510Sbellard int flags) 2236dbad63eSbellard { 224f4beb510Sbellard unsigned int e1, e2; 22553a5960aSpbrook uint32_t *p; 2266dbad63eSbellard e1 = (addr << 16) | (limit & 0xffff); 2276dbad63eSbellard e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000); 228f4beb510Sbellard e2 |= flags; 22953a5960aSpbrook p = ptr; 230d538e8f5Smalc p[0] = tswap32(e1); 231d538e8f5Smalc p[1] = tswap32(e2); 232f4beb510Sbellard } 233f4beb510Sbellard 234e441570fSbalrog static uint64_t *idt_table; 235eb38c52cSblueswir1 #ifdef TARGET_X86_64 236d2fd1af7Sbellard static void set_gate64(void *ptr, unsigned int type, unsigned int dpl, 237d2fd1af7Sbellard uint64_t addr, unsigned int sel) 238d2fd1af7Sbellard { 2394dbc422bSbellard uint32_t *p, e1, e2; 240d2fd1af7Sbellard e1 = (addr & 0xffff) | (sel << 16); 241d2fd1af7Sbellard e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8); 242d2fd1af7Sbellard p = ptr; 2434dbc422bSbellard p[0] = tswap32(e1); 2444dbc422bSbellard p[1] = tswap32(e2); 2454dbc422bSbellard p[2] = tswap32(addr >> 32); 2464dbc422bSbellard p[3] = 0; 247d2fd1af7Sbellard } 248d2fd1af7Sbellard /* only dpl matters as we do only user space emulation */ 249d2fd1af7Sbellard static void set_idt(int n, unsigned int dpl) 250d2fd1af7Sbellard { 251d2fd1af7Sbellard set_gate64(idt_table + n * 2, 0, dpl, 0, 0); 252d2fd1af7Sbellard } 253d2fd1af7Sbellard #else 254f4beb510Sbellard static void set_gate(void *ptr, unsigned int type, unsigned int dpl, 255d2fd1af7Sbellard uint32_t addr, unsigned int sel) 256f4beb510Sbellard { 2574dbc422bSbellard uint32_t *p, e1, e2; 258f4beb510Sbellard e1 = (addr & 0xffff) | (sel << 16); 259f4beb510Sbellard e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8); 26053a5960aSpbrook p = ptr; 2614dbc422bSbellard p[0] = tswap32(e1); 2624dbc422bSbellard p[1] = tswap32(e2); 2636dbad63eSbellard } 2646dbad63eSbellard 265f4beb510Sbellard /* only dpl matters as we do only user space emulation */ 266f4beb510Sbellard static void set_idt(int n, unsigned int dpl) 267f4beb510Sbellard { 268f4beb510Sbellard set_gate(idt_table + n, 0, dpl, 0, 0); 269f4beb510Sbellard } 270d2fd1af7Sbellard #endif 27131e31b8aSbellard 27289e957e7Sbellard void cpu_loop(CPUX86State *env) 273bc8a22ccSbellard { 274db6b81d4SAndreas Färber CPUState *cs = CPU(x86_env_get_cpu(env)); 275bc8a22ccSbellard int trapnr; 276992f48a0Sblueswir1 abi_ulong pc; 277c227f099SAnthony Liguori target_siginfo_t info; 278bc8a22ccSbellard 279bc8a22ccSbellard for(;;) { 280b040bc9cSPeter Maydell cpu_exec_start(cs); 281ea3e9847SPeter Crosthwaite trapnr = cpu_x86_exec(cs); 282b040bc9cSPeter Maydell cpu_exec_end(cs); 283bc8a22ccSbellard switch(trapnr) { 284f4beb510Sbellard case 0x80: 285d2fd1af7Sbellard /* linux syscall from int $0x80 */ 2861b6b029eSbellard env->regs[R_EAX] = do_syscall(env, 2871b6b029eSbellard env->regs[R_EAX], 2881b6b029eSbellard env->regs[R_EBX], 2891b6b029eSbellard env->regs[R_ECX], 2901b6b029eSbellard env->regs[R_EDX], 2911b6b029eSbellard env->regs[R_ESI], 2921b6b029eSbellard env->regs[R_EDI], 2935945cfcbSPeter Maydell env->regs[R_EBP], 2945945cfcbSPeter Maydell 0, 0); 295f4beb510Sbellard break; 296d2fd1af7Sbellard #ifndef TARGET_ABI32 297d2fd1af7Sbellard case EXCP_SYSCALL: 2985ba18547SStefan Weil /* linux syscall from syscall instruction */ 299d2fd1af7Sbellard env->regs[R_EAX] = do_syscall(env, 300d2fd1af7Sbellard env->regs[R_EAX], 301d2fd1af7Sbellard env->regs[R_EDI], 302d2fd1af7Sbellard env->regs[R_ESI], 303d2fd1af7Sbellard env->regs[R_EDX], 304d2fd1af7Sbellard env->regs[10], 305d2fd1af7Sbellard env->regs[8], 3065945cfcbSPeter Maydell env->regs[9], 3075945cfcbSPeter Maydell 0, 0); 308d2fd1af7Sbellard break; 309d2fd1af7Sbellard #endif 310f4beb510Sbellard case EXCP0B_NOSEG: 311f4beb510Sbellard case EXCP0C_STACK: 312a86b3c64SChen Gang S info.si_signo = TARGET_SIGBUS; 313f4beb510Sbellard info.si_errno = 0; 314f4beb510Sbellard info.si_code = TARGET_SI_KERNEL; 315f4beb510Sbellard info._sifields._sigfault._addr = 0; 316624f7979Spbrook queue_signal(env, info.si_signo, &info); 317f4beb510Sbellard break; 318f4beb510Sbellard case EXCP0D_GPF: 319d2fd1af7Sbellard /* XXX: potential problem if ABI32 */ 32084409ddbSj_mayer #ifndef TARGET_X86_64 321f4beb510Sbellard if (env->eflags & VM_MASK) { 322f4beb510Sbellard handle_vm86_fault(env); 32384409ddbSj_mayer } else 32484409ddbSj_mayer #endif 32584409ddbSj_mayer { 326a86b3c64SChen Gang S info.si_signo = TARGET_SIGSEGV; 3279de5e440Sbellard info.si_errno = 0; 328b689bc57Sbellard info.si_code = TARGET_SI_KERNEL; 3299de5e440Sbellard info._sifields._sigfault._addr = 0; 330624f7979Spbrook queue_signal(env, info.si_signo, &info); 3311b6b029eSbellard } 3321b6b029eSbellard break; 333b689bc57Sbellard case EXCP0E_PAGE: 334a86b3c64SChen Gang S info.si_signo = TARGET_SIGSEGV; 335b689bc57Sbellard info.si_errno = 0; 336b689bc57Sbellard if (!(env->error_code & 1)) 337b689bc57Sbellard info.si_code = TARGET_SEGV_MAPERR; 338b689bc57Sbellard else 339b689bc57Sbellard info.si_code = TARGET_SEGV_ACCERR; 340970a87a6Sbellard info._sifields._sigfault._addr = env->cr[2]; 341624f7979Spbrook queue_signal(env, info.si_signo, &info); 342b689bc57Sbellard break; 3439de5e440Sbellard case EXCP00_DIVZ: 34484409ddbSj_mayer #ifndef TARGET_X86_64 345bc8a22ccSbellard if (env->eflags & VM_MASK) { 346447db213Sbellard handle_vm86_trap(env, trapnr); 34784409ddbSj_mayer } else 34884409ddbSj_mayer #endif 34984409ddbSj_mayer { 3509de5e440Sbellard /* division by zero */ 351a86b3c64SChen Gang S info.si_signo = TARGET_SIGFPE; 3529de5e440Sbellard info.si_errno = 0; 3539de5e440Sbellard info.si_code = TARGET_FPE_INTDIV; 3549de5e440Sbellard info._sifields._sigfault._addr = env->eip; 355624f7979Spbrook queue_signal(env, info.si_signo, &info); 356bc8a22ccSbellard } 3579de5e440Sbellard break; 35801df040bSaliguori case EXCP01_DB: 359447db213Sbellard case EXCP03_INT3: 36084409ddbSj_mayer #ifndef TARGET_X86_64 361447db213Sbellard if (env->eflags & VM_MASK) { 362447db213Sbellard handle_vm86_trap(env, trapnr); 36384409ddbSj_mayer } else 36484409ddbSj_mayer #endif 36584409ddbSj_mayer { 366a86b3c64SChen Gang S info.si_signo = TARGET_SIGTRAP; 367447db213Sbellard info.si_errno = 0; 36801df040bSaliguori if (trapnr == EXCP01_DB) { 369447db213Sbellard info.si_code = TARGET_TRAP_BRKPT; 370447db213Sbellard info._sifields._sigfault._addr = env->eip; 371447db213Sbellard } else { 372447db213Sbellard info.si_code = TARGET_SI_KERNEL; 373447db213Sbellard info._sifields._sigfault._addr = 0; 374447db213Sbellard } 375624f7979Spbrook queue_signal(env, info.si_signo, &info); 376447db213Sbellard } 377447db213Sbellard break; 3789de5e440Sbellard case EXCP04_INTO: 3799de5e440Sbellard case EXCP05_BOUND: 38084409ddbSj_mayer #ifndef TARGET_X86_64 381bc8a22ccSbellard if (env->eflags & VM_MASK) { 382447db213Sbellard handle_vm86_trap(env, trapnr); 38384409ddbSj_mayer } else 38484409ddbSj_mayer #endif 38584409ddbSj_mayer { 386a86b3c64SChen Gang S info.si_signo = TARGET_SIGSEGV; 3879de5e440Sbellard info.si_errno = 0; 388b689bc57Sbellard info.si_code = TARGET_SI_KERNEL; 3899de5e440Sbellard info._sifields._sigfault._addr = 0; 390624f7979Spbrook queue_signal(env, info.si_signo, &info); 391bc8a22ccSbellard } 3929de5e440Sbellard break; 3939de5e440Sbellard case EXCP06_ILLOP: 394a86b3c64SChen Gang S info.si_signo = TARGET_SIGILL; 3959de5e440Sbellard info.si_errno = 0; 3969de5e440Sbellard info.si_code = TARGET_ILL_ILLOPN; 3979de5e440Sbellard info._sifields._sigfault._addr = env->eip; 398624f7979Spbrook queue_signal(env, info.si_signo, &info); 3999de5e440Sbellard break; 4009de5e440Sbellard case EXCP_INTERRUPT: 4019de5e440Sbellard /* just indicate that signals should be handled asap */ 4029de5e440Sbellard break; 4031fddef4bSbellard case EXCP_DEBUG: 4041fddef4bSbellard { 4051fddef4bSbellard int sig; 4061fddef4bSbellard 407db6b81d4SAndreas Färber sig = gdb_handlesig(cs, TARGET_SIGTRAP); 4081fddef4bSbellard if (sig) 4091fddef4bSbellard { 4101fddef4bSbellard info.si_signo = sig; 4111fddef4bSbellard info.si_errno = 0; 4121fddef4bSbellard info.si_code = TARGET_TRAP_BRKPT; 413624f7979Spbrook queue_signal(env, info.si_signo, &info); 4141fddef4bSbellard } 4151fddef4bSbellard } 4161fddef4bSbellard break; 4171b6b029eSbellard default: 418970a87a6Sbellard pc = env->segs[R_CS].base + env->eip; 419bc8a22ccSbellard fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n", 420bc8a22ccSbellard (long)pc, trapnr); 4211b6b029eSbellard abort(); 4221b6b029eSbellard } 42366fb9763Sbellard process_pending_signals(env); 4241b6b029eSbellard } 4251b6b029eSbellard } 426b346ff46Sbellard #endif 427b346ff46Sbellard 428b346ff46Sbellard #ifdef TARGET_ARM 429b346ff46Sbellard 430d8fd2954SPaul Brook #define get_user_code_u32(x, gaddr, doswap) \ 431d8fd2954SPaul Brook ({ abi_long __r = get_user_u32((x), (gaddr)); \ 432d8fd2954SPaul Brook if (!__r && (doswap)) { \ 433d8fd2954SPaul Brook (x) = bswap32(x); \ 434d8fd2954SPaul Brook } \ 435d8fd2954SPaul Brook __r; \ 436d8fd2954SPaul Brook }) 437d8fd2954SPaul Brook 438d8fd2954SPaul Brook #define get_user_code_u16(x, gaddr, doswap) \ 439d8fd2954SPaul Brook ({ abi_long __r = get_user_u16((x), (gaddr)); \ 440d8fd2954SPaul Brook if (!__r && (doswap)) { \ 441d8fd2954SPaul Brook (x) = bswap16(x); \ 442d8fd2954SPaul Brook } \ 443d8fd2954SPaul Brook __r; \ 444d8fd2954SPaul Brook }) 445d8fd2954SPaul Brook 4461861c454SPeter Maydell #ifdef TARGET_ABI32 4471861c454SPeter Maydell /* Commpage handling -- there is no commpage for AArch64 */ 4481861c454SPeter Maydell 44997cc7560SDr. David Alan Gilbert /* 45097cc7560SDr. David Alan Gilbert * See the Linux kernel's Documentation/arm/kernel_user_helpers.txt 45197cc7560SDr. David Alan Gilbert * Input: 45297cc7560SDr. David Alan Gilbert * r0 = pointer to oldval 45397cc7560SDr. David Alan Gilbert * r1 = pointer to newval 45497cc7560SDr. David Alan Gilbert * r2 = pointer to target value 45597cc7560SDr. David Alan Gilbert * 45697cc7560SDr. David Alan Gilbert * Output: 45797cc7560SDr. David Alan Gilbert * r0 = 0 if *ptr was changed, non-0 if no exchange happened 45897cc7560SDr. David Alan Gilbert * C set if *ptr was changed, clear if no exchange happened 45997cc7560SDr. David Alan Gilbert * 46097cc7560SDr. David Alan Gilbert * Note segv's in kernel helpers are a bit tricky, we can set the 46197cc7560SDr. David Alan Gilbert * data address sensibly but the PC address is just the entry point. 46297cc7560SDr. David Alan Gilbert */ 46397cc7560SDr. David Alan Gilbert static void arm_kernel_cmpxchg64_helper(CPUARMState *env) 46497cc7560SDr. David Alan Gilbert { 46597cc7560SDr. David Alan Gilbert uint64_t oldval, newval, val; 46697cc7560SDr. David Alan Gilbert uint32_t addr, cpsr; 46797cc7560SDr. David Alan Gilbert target_siginfo_t info; 46897cc7560SDr. David Alan Gilbert 46997cc7560SDr. David Alan Gilbert /* Based on the 32 bit code in do_kernel_trap */ 47097cc7560SDr. David Alan Gilbert 47197cc7560SDr. David Alan Gilbert /* XXX: This only works between threads, not between processes. 47297cc7560SDr. David Alan Gilbert It's probably possible to implement this with native host 47397cc7560SDr. David Alan Gilbert operations. However things like ldrex/strex are much harder so 47497cc7560SDr. David Alan Gilbert there's not much point trying. */ 47597cc7560SDr. David Alan Gilbert start_exclusive(); 47697cc7560SDr. David Alan Gilbert cpsr = cpsr_read(env); 47797cc7560SDr. David Alan Gilbert addr = env->regs[2]; 47897cc7560SDr. David Alan Gilbert 47997cc7560SDr. David Alan Gilbert if (get_user_u64(oldval, env->regs[0])) { 480abf1172fSPeter Maydell env->exception.vaddress = env->regs[0]; 48197cc7560SDr. David Alan Gilbert goto segv; 48297cc7560SDr. David Alan Gilbert }; 48397cc7560SDr. David Alan Gilbert 48497cc7560SDr. David Alan Gilbert if (get_user_u64(newval, env->regs[1])) { 485abf1172fSPeter Maydell env->exception.vaddress = env->regs[1]; 48697cc7560SDr. David Alan Gilbert goto segv; 48797cc7560SDr. David Alan Gilbert }; 48897cc7560SDr. David Alan Gilbert 48997cc7560SDr. David Alan Gilbert if (get_user_u64(val, addr)) { 490abf1172fSPeter Maydell env->exception.vaddress = addr; 49197cc7560SDr. David Alan Gilbert goto segv; 49297cc7560SDr. David Alan Gilbert } 49397cc7560SDr. David Alan Gilbert 49497cc7560SDr. David Alan Gilbert if (val == oldval) { 49597cc7560SDr. David Alan Gilbert val = newval; 49697cc7560SDr. David Alan Gilbert 49797cc7560SDr. David Alan Gilbert if (put_user_u64(val, addr)) { 498abf1172fSPeter Maydell env->exception.vaddress = addr; 49997cc7560SDr. David Alan Gilbert goto segv; 50097cc7560SDr. David Alan Gilbert }; 50197cc7560SDr. David Alan Gilbert 50297cc7560SDr. David Alan Gilbert env->regs[0] = 0; 50397cc7560SDr. David Alan Gilbert cpsr |= CPSR_C; 50497cc7560SDr. David Alan Gilbert } else { 50597cc7560SDr. David Alan Gilbert env->regs[0] = -1; 50697cc7560SDr. David Alan Gilbert cpsr &= ~CPSR_C; 50797cc7560SDr. David Alan Gilbert } 50897cc7560SDr. David Alan Gilbert cpsr_write(env, cpsr, CPSR_C); 50997cc7560SDr. David Alan Gilbert end_exclusive(); 51097cc7560SDr. David Alan Gilbert return; 51197cc7560SDr. David Alan Gilbert 51297cc7560SDr. David Alan Gilbert segv: 51397cc7560SDr. David Alan Gilbert end_exclusive(); 51497cc7560SDr. David Alan Gilbert /* We get the PC of the entry address - which is as good as anything, 51597cc7560SDr. David Alan Gilbert on a real kernel what you get depends on which mode it uses. */ 516a86b3c64SChen Gang S info.si_signo = TARGET_SIGSEGV; 51797cc7560SDr. David Alan Gilbert info.si_errno = 0; 51897cc7560SDr. David Alan Gilbert /* XXX: check env->error_code */ 51997cc7560SDr. David Alan Gilbert info.si_code = TARGET_SEGV_MAPERR; 520abf1172fSPeter Maydell info._sifields._sigfault._addr = env->exception.vaddress; 52197cc7560SDr. David Alan Gilbert queue_signal(env, info.si_signo, &info); 52297cc7560SDr. David Alan Gilbert } 52397cc7560SDr. David Alan Gilbert 524fbb4a2e3Spbrook /* Handle a jump to the kernel code page. */ 525fbb4a2e3Spbrook static int 526fbb4a2e3Spbrook do_kernel_trap(CPUARMState *env) 527fbb4a2e3Spbrook { 528fbb4a2e3Spbrook uint32_t addr; 529fbb4a2e3Spbrook uint32_t cpsr; 530fbb4a2e3Spbrook uint32_t val; 531fbb4a2e3Spbrook 532fbb4a2e3Spbrook switch (env->regs[15]) { 533fbb4a2e3Spbrook case 0xffff0fa0: /* __kernel_memory_barrier */ 534fbb4a2e3Spbrook /* ??? No-op. Will need to do better for SMP. */ 535fbb4a2e3Spbrook break; 536fbb4a2e3Spbrook case 0xffff0fc0: /* __kernel_cmpxchg */ 537d5975363Spbrook /* XXX: This only works between threads, not between processes. 538d5975363Spbrook It's probably possible to implement this with native host 539d5975363Spbrook operations. However things like ldrex/strex are much harder so 540d5975363Spbrook there's not much point trying. */ 541d5975363Spbrook start_exclusive(); 542fbb4a2e3Spbrook cpsr = cpsr_read(env); 543fbb4a2e3Spbrook addr = env->regs[2]; 544fbb4a2e3Spbrook /* FIXME: This should SEGV if the access fails. */ 545fbb4a2e3Spbrook if (get_user_u32(val, addr)) 546fbb4a2e3Spbrook val = ~env->regs[0]; 547fbb4a2e3Spbrook if (val == env->regs[0]) { 548fbb4a2e3Spbrook val = env->regs[1]; 549fbb4a2e3Spbrook /* FIXME: Check for segfaults. */ 550fbb4a2e3Spbrook put_user_u32(val, addr); 551fbb4a2e3Spbrook env->regs[0] = 0; 552fbb4a2e3Spbrook cpsr |= CPSR_C; 553fbb4a2e3Spbrook } else { 554fbb4a2e3Spbrook env->regs[0] = -1; 555fbb4a2e3Spbrook cpsr &= ~CPSR_C; 556fbb4a2e3Spbrook } 557fbb4a2e3Spbrook cpsr_write(env, cpsr, CPSR_C); 558d5975363Spbrook end_exclusive(); 559fbb4a2e3Spbrook break; 560fbb4a2e3Spbrook case 0xffff0fe0: /* __kernel_get_tls */ 561b8d43285SMikhail Ilyin env->regs[0] = cpu_get_tls(env); 562fbb4a2e3Spbrook break; 56397cc7560SDr. David Alan Gilbert case 0xffff0f60: /* __kernel_cmpxchg64 */ 56497cc7560SDr. David Alan Gilbert arm_kernel_cmpxchg64_helper(env); 56597cc7560SDr. David Alan Gilbert break; 56697cc7560SDr. David Alan Gilbert 567fbb4a2e3Spbrook default: 568fbb4a2e3Spbrook return 1; 569fbb4a2e3Spbrook } 570fbb4a2e3Spbrook /* Jump back to the caller. */ 571fbb4a2e3Spbrook addr = env->regs[14]; 572fbb4a2e3Spbrook if (addr & 1) { 573fbb4a2e3Spbrook env->thumb = 1; 574fbb4a2e3Spbrook addr &= ~1; 575fbb4a2e3Spbrook } 576fbb4a2e3Spbrook env->regs[15] = addr; 577fbb4a2e3Spbrook 578fbb4a2e3Spbrook return 0; 579fbb4a2e3Spbrook } 580fbb4a2e3Spbrook 581fa2ef212SMichael Matz /* Store exclusive handling for AArch32 */ 582426f5abcSPaul Brook static int do_strex(CPUARMState *env) 583426f5abcSPaul Brook { 58403d05e2dSPeter Maydell uint64_t val; 585426f5abcSPaul Brook int size; 586426f5abcSPaul Brook int rc = 1; 587426f5abcSPaul Brook int segv = 0; 588426f5abcSPaul Brook uint32_t addr; 589426f5abcSPaul Brook start_exclusive(); 59003d05e2dSPeter Maydell if (env->exclusive_addr != env->exclusive_test) { 591426f5abcSPaul Brook goto fail; 592426f5abcSPaul Brook } 59303d05e2dSPeter Maydell /* We know we're always AArch32 so the address is in uint32_t range 59403d05e2dSPeter Maydell * unless it was the -1 exclusive-monitor-lost value (which won't 59503d05e2dSPeter Maydell * match exclusive_test above). 59603d05e2dSPeter Maydell */ 59703d05e2dSPeter Maydell assert(extract64(env->exclusive_addr, 32, 32) == 0); 59803d05e2dSPeter Maydell addr = env->exclusive_addr; 599426f5abcSPaul Brook size = env->exclusive_info & 0xf; 600426f5abcSPaul Brook switch (size) { 601426f5abcSPaul Brook case 0: 602426f5abcSPaul Brook segv = get_user_u8(val, addr); 603426f5abcSPaul Brook break; 604426f5abcSPaul Brook case 1: 605426f5abcSPaul Brook segv = get_user_u16(val, addr); 606426f5abcSPaul Brook break; 607426f5abcSPaul Brook case 2: 608426f5abcSPaul Brook case 3: 609426f5abcSPaul Brook segv = get_user_u32(val, addr); 610426f5abcSPaul Brook break; 611f7001a3bSAurelien Jarno default: 612f7001a3bSAurelien Jarno abort(); 613426f5abcSPaul Brook } 614426f5abcSPaul Brook if (segv) { 615abf1172fSPeter Maydell env->exception.vaddress = addr; 616426f5abcSPaul Brook goto done; 617426f5abcSPaul Brook } 618426f5abcSPaul Brook if (size == 3) { 61903d05e2dSPeter Maydell uint32_t valhi; 62003d05e2dSPeter Maydell segv = get_user_u32(valhi, addr + 4); 621426f5abcSPaul Brook if (segv) { 622abf1172fSPeter Maydell env->exception.vaddress = addr + 4; 623426f5abcSPaul Brook goto done; 624426f5abcSPaul Brook } 62503d05e2dSPeter Maydell val = deposit64(val, 32, 32, valhi); 62603d05e2dSPeter Maydell } 62703d05e2dSPeter Maydell if (val != env->exclusive_val) { 628426f5abcSPaul Brook goto fail; 629426f5abcSPaul Brook } 63003d05e2dSPeter Maydell 631426f5abcSPaul Brook val = env->regs[(env->exclusive_info >> 8) & 0xf]; 632426f5abcSPaul Brook switch (size) { 633426f5abcSPaul Brook case 0: 634426f5abcSPaul Brook segv = put_user_u8(val, addr); 635426f5abcSPaul Brook break; 636426f5abcSPaul Brook case 1: 637426f5abcSPaul Brook segv = put_user_u16(val, addr); 638426f5abcSPaul Brook break; 639426f5abcSPaul Brook case 2: 640426f5abcSPaul Brook case 3: 641426f5abcSPaul Brook segv = put_user_u32(val, addr); 642426f5abcSPaul Brook break; 643426f5abcSPaul Brook } 644426f5abcSPaul Brook if (segv) { 645abf1172fSPeter Maydell env->exception.vaddress = addr; 646426f5abcSPaul Brook goto done; 647426f5abcSPaul Brook } 648426f5abcSPaul Brook if (size == 3) { 649426f5abcSPaul Brook val = env->regs[(env->exclusive_info >> 12) & 0xf]; 6502c9adbdaSPeter Maydell segv = put_user_u32(val, addr + 4); 651426f5abcSPaul Brook if (segv) { 652abf1172fSPeter Maydell env->exception.vaddress = addr + 4; 653426f5abcSPaul Brook goto done; 654426f5abcSPaul Brook } 655426f5abcSPaul Brook } 656426f5abcSPaul Brook rc = 0; 657426f5abcSPaul Brook fail: 658725b8a69SPaul Brook env->regs[15] += 4; 659426f5abcSPaul Brook env->regs[(env->exclusive_info >> 4) & 0xf] = rc; 660426f5abcSPaul Brook done: 661426f5abcSPaul Brook end_exclusive(); 662426f5abcSPaul Brook return segv; 663426f5abcSPaul Brook } 664426f5abcSPaul Brook 665b346ff46Sbellard void cpu_loop(CPUARMState *env) 666b346ff46Sbellard { 6670315c31cSAndreas Färber CPUState *cs = CPU(arm_env_get_cpu(env)); 668b346ff46Sbellard int trapnr; 669b346ff46Sbellard unsigned int n, insn; 670c227f099SAnthony Liguori target_siginfo_t info; 671b5ff1b31Sbellard uint32_t addr; 672b346ff46Sbellard 673b346ff46Sbellard for(;;) { 6740315c31cSAndreas Färber cpu_exec_start(cs); 675ea3e9847SPeter Crosthwaite trapnr = cpu_arm_exec(cs); 6760315c31cSAndreas Färber cpu_exec_end(cs); 677b346ff46Sbellard switch(trapnr) { 678b346ff46Sbellard case EXCP_UDEF: 679c6981055Sbellard { 6800429a971SAndreas Färber TaskState *ts = cs->opaque; 681c6981055Sbellard uint32_t opcode; 6826d9a42beSaurel32 int rc; 683c6981055Sbellard 684c6981055Sbellard /* we handle the FPU emulation here, as Linux */ 685c6981055Sbellard /* we get the opcode */ 6862f619698Sbellard /* FIXME - what to do if get_user() fails? */ 687d8fd2954SPaul Brook get_user_code_u32(opcode, env->regs[15], env->bswap_code); 688c6981055Sbellard 6896d9a42beSaurel32 rc = EmulateAll(opcode, &ts->fpa, env); 6906d9a42beSaurel32 if (rc == 0) { /* illegal instruction */ 691a86b3c64SChen Gang S info.si_signo = TARGET_SIGILL; 692b346ff46Sbellard info.si_errno = 0; 693b346ff46Sbellard info.si_code = TARGET_ILL_ILLOPN; 694b346ff46Sbellard info._sifields._sigfault._addr = env->regs[15]; 695624f7979Spbrook queue_signal(env, info.si_signo, &info); 6966d9a42beSaurel32 } else if (rc < 0) { /* FP exception */ 6976d9a42beSaurel32 int arm_fpe=0; 6986d9a42beSaurel32 6996d9a42beSaurel32 /* translate softfloat flags to FPSR flags */ 7006d9a42beSaurel32 if (-rc & float_flag_invalid) 7016d9a42beSaurel32 arm_fpe |= BIT_IOC; 7026d9a42beSaurel32 if (-rc & float_flag_divbyzero) 7036d9a42beSaurel32 arm_fpe |= BIT_DZC; 7046d9a42beSaurel32 if (-rc & float_flag_overflow) 7056d9a42beSaurel32 arm_fpe |= BIT_OFC; 7066d9a42beSaurel32 if (-rc & float_flag_underflow) 7076d9a42beSaurel32 arm_fpe |= BIT_UFC; 7086d9a42beSaurel32 if (-rc & float_flag_inexact) 7096d9a42beSaurel32 arm_fpe |= BIT_IXC; 7106d9a42beSaurel32 7116d9a42beSaurel32 FPSR fpsr = ts->fpa.fpsr; 7126d9a42beSaurel32 //printf("fpsr 0x%x, arm_fpe 0x%x\n",fpsr,arm_fpe); 7136d9a42beSaurel32 7146d9a42beSaurel32 if (fpsr & (arm_fpe << 16)) { /* exception enabled? */ 715a86b3c64SChen Gang S info.si_signo = TARGET_SIGFPE; 7166d9a42beSaurel32 info.si_errno = 0; 7176d9a42beSaurel32 7186d9a42beSaurel32 /* ordered by priority, least first */ 7196d9a42beSaurel32 if (arm_fpe & BIT_IXC) info.si_code = TARGET_FPE_FLTRES; 7206d9a42beSaurel32 if (arm_fpe & BIT_UFC) info.si_code = TARGET_FPE_FLTUND; 7216d9a42beSaurel32 if (arm_fpe & BIT_OFC) info.si_code = TARGET_FPE_FLTOVF; 7226d9a42beSaurel32 if (arm_fpe & BIT_DZC) info.si_code = TARGET_FPE_FLTDIV; 7236d9a42beSaurel32 if (arm_fpe & BIT_IOC) info.si_code = TARGET_FPE_FLTINV; 7246d9a42beSaurel32 7256d9a42beSaurel32 info._sifields._sigfault._addr = env->regs[15]; 726624f7979Spbrook queue_signal(env, info.si_signo, &info); 727c6981055Sbellard } else { 7286d9a42beSaurel32 env->regs[15] += 4; 7296d9a42beSaurel32 } 7306d9a42beSaurel32 7316d9a42beSaurel32 /* accumulate unenabled exceptions */ 7326d9a42beSaurel32 if ((!(fpsr & BIT_IXE)) && (arm_fpe & BIT_IXC)) 7336d9a42beSaurel32 fpsr |= BIT_IXC; 7346d9a42beSaurel32 if ((!(fpsr & BIT_UFE)) && (arm_fpe & BIT_UFC)) 7356d9a42beSaurel32 fpsr |= BIT_UFC; 7366d9a42beSaurel32 if ((!(fpsr & BIT_OFE)) && (arm_fpe & BIT_OFC)) 7376d9a42beSaurel32 fpsr |= BIT_OFC; 7386d9a42beSaurel32 if ((!(fpsr & BIT_DZE)) && (arm_fpe & BIT_DZC)) 7396d9a42beSaurel32 fpsr |= BIT_DZC; 7406d9a42beSaurel32 if ((!(fpsr & BIT_IOE)) && (arm_fpe & BIT_IOC)) 7416d9a42beSaurel32 fpsr |= BIT_IOC; 7426d9a42beSaurel32 ts->fpa.fpsr=fpsr; 7436d9a42beSaurel32 } else { /* everything OK */ 744c6981055Sbellard /* increment PC */ 745c6981055Sbellard env->regs[15] += 4; 746c6981055Sbellard } 747c6981055Sbellard } 748b346ff46Sbellard break; 749b346ff46Sbellard case EXCP_SWI: 75006c949e6Spbrook case EXCP_BKPT: 751b346ff46Sbellard { 752ce4defa0Spbrook env->eabi = 1; 753b346ff46Sbellard /* system call */ 75406c949e6Spbrook if (trapnr == EXCP_BKPT) { 75506c949e6Spbrook if (env->thumb) { 7562f619698Sbellard /* FIXME - what to do if get_user() fails? */ 757d8fd2954SPaul Brook get_user_code_u16(insn, env->regs[15], env->bswap_code); 75806c949e6Spbrook n = insn & 0xff; 75906c949e6Spbrook env->regs[15] += 2; 76006c949e6Spbrook } else { 7612f619698Sbellard /* FIXME - what to do if get_user() fails? */ 762d8fd2954SPaul Brook get_user_code_u32(insn, env->regs[15], env->bswap_code); 76306c949e6Spbrook n = (insn & 0xf) | ((insn >> 4) & 0xff0); 76406c949e6Spbrook env->regs[15] += 4; 76506c949e6Spbrook } 76606c949e6Spbrook } else { 767192c7bd9Sbellard if (env->thumb) { 7682f619698Sbellard /* FIXME - what to do if get_user() fails? */ 769d8fd2954SPaul Brook get_user_code_u16(insn, env->regs[15] - 2, 770d8fd2954SPaul Brook env->bswap_code); 771192c7bd9Sbellard n = insn & 0xff; 772192c7bd9Sbellard } else { 7732f619698Sbellard /* FIXME - what to do if get_user() fails? */ 774d8fd2954SPaul Brook get_user_code_u32(insn, env->regs[15] - 4, 775d8fd2954SPaul Brook env->bswap_code); 776b346ff46Sbellard n = insn & 0xffffff; 777192c7bd9Sbellard } 77806c949e6Spbrook } 779192c7bd9Sbellard 7806f1f31c0Sbellard if (n == ARM_NR_cacheflush) { 781dcfd14b3SBlue Swirl /* nop */ 782a4f81979Sbellard } else if (n == ARM_NR_semihosting 783a4f81979Sbellard || n == ARM_NR_thumb_semihosting) { 784a4f81979Sbellard env->regs[0] = do_arm_semihosting (env); 7853a1363acSAlexander Graf } else if (n == 0 || n >= ARM_SYSCALL_BASE || env->thumb) { 786b346ff46Sbellard /* linux syscall */ 787ce4defa0Spbrook if (env->thumb || n == 0) { 788192c7bd9Sbellard n = env->regs[7]; 789192c7bd9Sbellard } else { 790b346ff46Sbellard n -= ARM_SYSCALL_BASE; 791ce4defa0Spbrook env->eabi = 0; 792192c7bd9Sbellard } 793fbb4a2e3Spbrook if ( n > ARM_NR_BASE) { 794fbb4a2e3Spbrook switch (n) { 795fbb4a2e3Spbrook case ARM_NR_cacheflush: 796dcfd14b3SBlue Swirl /* nop */ 797fbb4a2e3Spbrook break; 798fbb4a2e3Spbrook case ARM_NR_set_tls: 799fbb4a2e3Spbrook cpu_set_tls(env, env->regs[0]); 800fbb4a2e3Spbrook env->regs[0] = 0; 801fbb4a2e3Spbrook break; 802d5355087SHunter Laux case ARM_NR_breakpoint: 803d5355087SHunter Laux env->regs[15] -= env->thumb ? 2 : 4; 804d5355087SHunter Laux goto excp_debug; 805fbb4a2e3Spbrook default: 806fbb4a2e3Spbrook gemu_log("qemu: Unsupported ARM syscall: 0x%x\n", 807fbb4a2e3Spbrook n); 808fbb4a2e3Spbrook env->regs[0] = -TARGET_ENOSYS; 809fbb4a2e3Spbrook break; 810fbb4a2e3Spbrook } 811fbb4a2e3Spbrook } else { 812b346ff46Sbellard env->regs[0] = do_syscall(env, 813b346ff46Sbellard n, 814b346ff46Sbellard env->regs[0], 815b346ff46Sbellard env->regs[1], 816b346ff46Sbellard env->regs[2], 817b346ff46Sbellard env->regs[3], 818b346ff46Sbellard env->regs[4], 8195945cfcbSPeter Maydell env->regs[5], 8205945cfcbSPeter Maydell 0, 0); 821fbb4a2e3Spbrook } 822b346ff46Sbellard } else { 823b346ff46Sbellard goto error; 824b346ff46Sbellard } 825b346ff46Sbellard } 826b346ff46Sbellard break; 82743fff238Sbellard case EXCP_INTERRUPT: 82843fff238Sbellard /* just indicate that signals should be handled asap */ 82943fff238Sbellard break; 830abf1172fSPeter Maydell case EXCP_STREX: 831abf1172fSPeter Maydell if (!do_strex(env)) { 832abf1172fSPeter Maydell break; 833abf1172fSPeter Maydell } 834abf1172fSPeter Maydell /* fall through for segv */ 83568016c62Sbellard case EXCP_PREFETCH_ABORT: 83668016c62Sbellard case EXCP_DATA_ABORT: 837abf1172fSPeter Maydell addr = env->exception.vaddress; 83868016c62Sbellard { 839a86b3c64SChen Gang S info.si_signo = TARGET_SIGSEGV; 84068016c62Sbellard info.si_errno = 0; 84168016c62Sbellard /* XXX: check env->error_code */ 84268016c62Sbellard info.si_code = TARGET_SEGV_MAPERR; 843b5ff1b31Sbellard info._sifields._sigfault._addr = addr; 844624f7979Spbrook queue_signal(env, info.si_signo, &info); 84568016c62Sbellard } 84668016c62Sbellard break; 8471fddef4bSbellard case EXCP_DEBUG: 848d5355087SHunter Laux excp_debug: 8491fddef4bSbellard { 8501fddef4bSbellard int sig; 8511fddef4bSbellard 852db6b81d4SAndreas Färber sig = gdb_handlesig(cs, TARGET_SIGTRAP); 8531fddef4bSbellard if (sig) 8541fddef4bSbellard { 8551fddef4bSbellard info.si_signo = sig; 8561fddef4bSbellard info.si_errno = 0; 8571fddef4bSbellard info.si_code = TARGET_TRAP_BRKPT; 858624f7979Spbrook queue_signal(env, info.si_signo, &info); 8591fddef4bSbellard } 8601fddef4bSbellard } 8611fddef4bSbellard break; 862fbb4a2e3Spbrook case EXCP_KERNEL_TRAP: 863fbb4a2e3Spbrook if (do_kernel_trap(env)) 864fbb4a2e3Spbrook goto error; 865fbb4a2e3Spbrook break; 866b346ff46Sbellard default: 867b346ff46Sbellard error: 868b346ff46Sbellard fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", 869b346ff46Sbellard trapnr); 870878096eeSAndreas Färber cpu_dump_state(cs, stderr, fprintf, 0); 871b346ff46Sbellard abort(); 872b346ff46Sbellard } 873b346ff46Sbellard process_pending_signals(env); 874b346ff46Sbellard } 875b346ff46Sbellard } 876b346ff46Sbellard 8771861c454SPeter Maydell #else 8781861c454SPeter Maydell 879fa2ef212SMichael Matz /* 880fa2ef212SMichael Matz * Handle AArch64 store-release exclusive 881fa2ef212SMichael Matz * 882fa2ef212SMichael Matz * rs = gets the status result of store exclusive 883fa2ef212SMichael Matz * rt = is the register that is stored 884fa2ef212SMichael Matz * rt2 = is the second register store (in STP) 885fa2ef212SMichael Matz * 886fa2ef212SMichael Matz */ 887fa2ef212SMichael Matz static int do_strex_a64(CPUARMState *env) 888fa2ef212SMichael Matz { 889fa2ef212SMichael Matz uint64_t val; 890fa2ef212SMichael Matz int size; 891fa2ef212SMichael Matz bool is_pair; 892fa2ef212SMichael Matz int rc = 1; 893fa2ef212SMichael Matz int segv = 0; 894fa2ef212SMichael Matz uint64_t addr; 895fa2ef212SMichael Matz int rs, rt, rt2; 896fa2ef212SMichael Matz 897fa2ef212SMichael Matz start_exclusive(); 898fa2ef212SMichael Matz /* size | is_pair << 2 | (rs << 4) | (rt << 9) | (rt2 << 14)); */ 899fa2ef212SMichael Matz size = extract32(env->exclusive_info, 0, 2); 900fa2ef212SMichael Matz is_pair = extract32(env->exclusive_info, 2, 1); 901fa2ef212SMichael Matz rs = extract32(env->exclusive_info, 4, 5); 902fa2ef212SMichael Matz rt = extract32(env->exclusive_info, 9, 5); 903fa2ef212SMichael Matz rt2 = extract32(env->exclusive_info, 14, 5); 904fa2ef212SMichael Matz 905fa2ef212SMichael Matz addr = env->exclusive_addr; 906fa2ef212SMichael Matz 907fa2ef212SMichael Matz if (addr != env->exclusive_test) { 908fa2ef212SMichael Matz goto finish; 909fa2ef212SMichael Matz } 910fa2ef212SMichael Matz 911fa2ef212SMichael Matz switch (size) { 912fa2ef212SMichael Matz case 0: 913fa2ef212SMichael Matz segv = get_user_u8(val, addr); 914fa2ef212SMichael Matz break; 915fa2ef212SMichael Matz case 1: 916fa2ef212SMichael Matz segv = get_user_u16(val, addr); 917fa2ef212SMichael Matz break; 918fa2ef212SMichael Matz case 2: 919fa2ef212SMichael Matz segv = get_user_u32(val, addr); 920fa2ef212SMichael Matz break; 921fa2ef212SMichael Matz case 3: 922fa2ef212SMichael Matz segv = get_user_u64(val, addr); 923fa2ef212SMichael Matz break; 924fa2ef212SMichael Matz default: 925fa2ef212SMichael Matz abort(); 926fa2ef212SMichael Matz } 927fa2ef212SMichael Matz if (segv) { 928abf1172fSPeter Maydell env->exception.vaddress = addr; 929fa2ef212SMichael Matz goto error; 930fa2ef212SMichael Matz } 931fa2ef212SMichael Matz if (val != env->exclusive_val) { 932fa2ef212SMichael Matz goto finish; 933fa2ef212SMichael Matz } 934fa2ef212SMichael Matz if (is_pair) { 935fa2ef212SMichael Matz if (size == 2) { 936fa2ef212SMichael Matz segv = get_user_u32(val, addr + 4); 937fa2ef212SMichael Matz } else { 938fa2ef212SMichael Matz segv = get_user_u64(val, addr + 8); 939fa2ef212SMichael Matz } 940fa2ef212SMichael Matz if (segv) { 941abf1172fSPeter Maydell env->exception.vaddress = addr + (size == 2 ? 4 : 8); 942fa2ef212SMichael Matz goto error; 943fa2ef212SMichael Matz } 944fa2ef212SMichael Matz if (val != env->exclusive_high) { 945fa2ef212SMichael Matz goto finish; 946fa2ef212SMichael Matz } 947fa2ef212SMichael Matz } 9482ea5a2caSJanne Grunau /* handle the zero register */ 9492ea5a2caSJanne Grunau val = rt == 31 ? 0 : env->xregs[rt]; 950fa2ef212SMichael Matz switch (size) { 951fa2ef212SMichael Matz case 0: 952fa2ef212SMichael Matz segv = put_user_u8(val, addr); 953fa2ef212SMichael Matz break; 954fa2ef212SMichael Matz case 1: 955fa2ef212SMichael Matz segv = put_user_u16(val, addr); 956fa2ef212SMichael Matz break; 957fa2ef212SMichael Matz case 2: 958fa2ef212SMichael Matz segv = put_user_u32(val, addr); 959fa2ef212SMichael Matz break; 960fa2ef212SMichael Matz case 3: 961fa2ef212SMichael Matz segv = put_user_u64(val, addr); 962fa2ef212SMichael Matz break; 963fa2ef212SMichael Matz } 964fa2ef212SMichael Matz if (segv) { 965fa2ef212SMichael Matz goto error; 966fa2ef212SMichael Matz } 967fa2ef212SMichael Matz if (is_pair) { 9682ea5a2caSJanne Grunau /* handle the zero register */ 9692ea5a2caSJanne Grunau val = rt2 == 31 ? 0 : env->xregs[rt2]; 970fa2ef212SMichael Matz if (size == 2) { 971fa2ef212SMichael Matz segv = put_user_u32(val, addr + 4); 972fa2ef212SMichael Matz } else { 973fa2ef212SMichael Matz segv = put_user_u64(val, addr + 8); 974fa2ef212SMichael Matz } 975fa2ef212SMichael Matz if (segv) { 976abf1172fSPeter Maydell env->exception.vaddress = addr + (size == 2 ? 4 : 8); 977fa2ef212SMichael Matz goto error; 978fa2ef212SMichael Matz } 979fa2ef212SMichael Matz } 980fa2ef212SMichael Matz rc = 0; 981fa2ef212SMichael Matz finish: 982fa2ef212SMichael Matz env->pc += 4; 983fa2ef212SMichael Matz /* rs == 31 encodes a write to the ZR, thus throwing away 984fa2ef212SMichael Matz * the status return. This is rather silly but valid. 985fa2ef212SMichael Matz */ 986fa2ef212SMichael Matz if (rs < 31) { 987fa2ef212SMichael Matz env->xregs[rs] = rc; 988fa2ef212SMichael Matz } 989fa2ef212SMichael Matz error: 990fa2ef212SMichael Matz /* instruction faulted, PC does not advance */ 991fa2ef212SMichael Matz /* either way a strex releases any exclusive lock we have */ 992fa2ef212SMichael Matz env->exclusive_addr = -1; 993fa2ef212SMichael Matz end_exclusive(); 994fa2ef212SMichael Matz return segv; 995fa2ef212SMichael Matz } 996fa2ef212SMichael Matz 9971861c454SPeter Maydell /* AArch64 main loop */ 9981861c454SPeter Maydell void cpu_loop(CPUARMState *env) 9991861c454SPeter Maydell { 10001861c454SPeter Maydell CPUState *cs = CPU(arm_env_get_cpu(env)); 10011861c454SPeter Maydell int trapnr, sig; 10021861c454SPeter Maydell target_siginfo_t info; 10031861c454SPeter Maydell 10041861c454SPeter Maydell for (;;) { 10051861c454SPeter Maydell cpu_exec_start(cs); 1006ea3e9847SPeter Crosthwaite trapnr = cpu_arm_exec(cs); 10071861c454SPeter Maydell cpu_exec_end(cs); 10081861c454SPeter Maydell 10091861c454SPeter Maydell switch (trapnr) { 10101861c454SPeter Maydell case EXCP_SWI: 10111861c454SPeter Maydell env->xregs[0] = do_syscall(env, 10121861c454SPeter Maydell env->xregs[8], 10131861c454SPeter Maydell env->xregs[0], 10141861c454SPeter Maydell env->xregs[1], 10151861c454SPeter Maydell env->xregs[2], 10161861c454SPeter Maydell env->xregs[3], 10171861c454SPeter Maydell env->xregs[4], 10181861c454SPeter Maydell env->xregs[5], 10191861c454SPeter Maydell 0, 0); 10201861c454SPeter Maydell break; 10211861c454SPeter Maydell case EXCP_INTERRUPT: 10221861c454SPeter Maydell /* just indicate that signals should be handled asap */ 10231861c454SPeter Maydell break; 10241861c454SPeter Maydell case EXCP_UDEF: 1025a86b3c64SChen Gang S info.si_signo = TARGET_SIGILL; 10261861c454SPeter Maydell info.si_errno = 0; 10271861c454SPeter Maydell info.si_code = TARGET_ILL_ILLOPN; 10281861c454SPeter Maydell info._sifields._sigfault._addr = env->pc; 10291861c454SPeter Maydell queue_signal(env, info.si_signo, &info); 10301861c454SPeter Maydell break; 1031abf1172fSPeter Maydell case EXCP_STREX: 1032abf1172fSPeter Maydell if (!do_strex_a64(env)) { 1033abf1172fSPeter Maydell break; 1034abf1172fSPeter Maydell } 1035abf1172fSPeter Maydell /* fall through for segv */ 10361861c454SPeter Maydell case EXCP_PREFETCH_ABORT: 10371861c454SPeter Maydell case EXCP_DATA_ABORT: 1038a86b3c64SChen Gang S info.si_signo = TARGET_SIGSEGV; 10391861c454SPeter Maydell info.si_errno = 0; 10401861c454SPeter Maydell /* XXX: check env->error_code */ 10411861c454SPeter Maydell info.si_code = TARGET_SEGV_MAPERR; 1042686581adSRiku Voipio info._sifields._sigfault._addr = env->exception.vaddress; 10431861c454SPeter Maydell queue_signal(env, info.si_signo, &info); 10441861c454SPeter Maydell break; 10451861c454SPeter Maydell case EXCP_DEBUG: 10461861c454SPeter Maydell case EXCP_BKPT: 10471861c454SPeter Maydell sig = gdb_handlesig(cs, TARGET_SIGTRAP); 10481861c454SPeter Maydell if (sig) { 10491861c454SPeter Maydell info.si_signo = sig; 10501861c454SPeter Maydell info.si_errno = 0; 10511861c454SPeter Maydell info.si_code = TARGET_TRAP_BRKPT; 10521861c454SPeter Maydell queue_signal(env, info.si_signo, &info); 10531861c454SPeter Maydell } 10541861c454SPeter Maydell break; 10558012c84fSPeter Maydell case EXCP_SEMIHOST: 10568012c84fSPeter Maydell env->xregs[0] = do_arm_semihosting(env); 10578012c84fSPeter Maydell break; 10581861c454SPeter Maydell default: 10591861c454SPeter Maydell fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", 10601861c454SPeter Maydell trapnr); 10611861c454SPeter Maydell cpu_dump_state(cs, stderr, fprintf, 0); 10621861c454SPeter Maydell abort(); 10631861c454SPeter Maydell } 10641861c454SPeter Maydell process_pending_signals(env); 1065fa2ef212SMichael Matz /* Exception return on AArch64 always clears the exclusive monitor, 1066fa2ef212SMichael Matz * so any return to running guest code implies this. 1067fa2ef212SMichael Matz * A strex (successful or otherwise) also clears the monitor, so 1068fa2ef212SMichael Matz * we don't need to specialcase EXCP_STREX. 1069fa2ef212SMichael Matz */ 1070fa2ef212SMichael Matz env->exclusive_addr = -1; 10711861c454SPeter Maydell } 10721861c454SPeter Maydell } 10731861c454SPeter Maydell #endif /* ndef TARGET_ABI32 */ 10741861c454SPeter Maydell 1075b346ff46Sbellard #endif 10761b6b029eSbellard 1077d2fbca94SGuan Xuetao #ifdef TARGET_UNICORE32 1078d2fbca94SGuan Xuetao 107905390248SAndreas Färber void cpu_loop(CPUUniCore32State *env) 1080d2fbca94SGuan Xuetao { 10810315c31cSAndreas Färber CPUState *cs = CPU(uc32_env_get_cpu(env)); 1082d2fbca94SGuan Xuetao int trapnr; 1083d2fbca94SGuan Xuetao unsigned int n, insn; 1084d2fbca94SGuan Xuetao target_siginfo_t info; 1085d2fbca94SGuan Xuetao 1086d2fbca94SGuan Xuetao for (;;) { 10870315c31cSAndreas Färber cpu_exec_start(cs); 1088ea3e9847SPeter Crosthwaite trapnr = uc32_cpu_exec(cs); 10890315c31cSAndreas Färber cpu_exec_end(cs); 1090d2fbca94SGuan Xuetao switch (trapnr) { 1091d2fbca94SGuan Xuetao case UC32_EXCP_PRIV: 1092d2fbca94SGuan Xuetao { 1093d2fbca94SGuan Xuetao /* system call */ 1094d2fbca94SGuan Xuetao get_user_u32(insn, env->regs[31] - 4); 1095d2fbca94SGuan Xuetao n = insn & 0xffffff; 1096d2fbca94SGuan Xuetao 1097d2fbca94SGuan Xuetao if (n >= UC32_SYSCALL_BASE) { 1098d2fbca94SGuan Xuetao /* linux syscall */ 1099d2fbca94SGuan Xuetao n -= UC32_SYSCALL_BASE; 1100d2fbca94SGuan Xuetao if (n == UC32_SYSCALL_NR_set_tls) { 1101d2fbca94SGuan Xuetao cpu_set_tls(env, env->regs[0]); 1102d2fbca94SGuan Xuetao env->regs[0] = 0; 1103d2fbca94SGuan Xuetao } else { 1104d2fbca94SGuan Xuetao env->regs[0] = do_syscall(env, 1105d2fbca94SGuan Xuetao n, 1106d2fbca94SGuan Xuetao env->regs[0], 1107d2fbca94SGuan Xuetao env->regs[1], 1108d2fbca94SGuan Xuetao env->regs[2], 1109d2fbca94SGuan Xuetao env->regs[3], 1110d2fbca94SGuan Xuetao env->regs[4], 11115945cfcbSPeter Maydell env->regs[5], 11125945cfcbSPeter Maydell 0, 0); 1113d2fbca94SGuan Xuetao } 1114d2fbca94SGuan Xuetao } else { 1115d2fbca94SGuan Xuetao goto error; 1116d2fbca94SGuan Xuetao } 1117d2fbca94SGuan Xuetao } 1118d2fbca94SGuan Xuetao break; 1119d48813ddSGuan Xuetao case UC32_EXCP_DTRAP: 1120d48813ddSGuan Xuetao case UC32_EXCP_ITRAP: 1121a86b3c64SChen Gang S info.si_signo = TARGET_SIGSEGV; 1122d2fbca94SGuan Xuetao info.si_errno = 0; 1123d2fbca94SGuan Xuetao /* XXX: check env->error_code */ 1124d2fbca94SGuan Xuetao info.si_code = TARGET_SEGV_MAPERR; 1125d2fbca94SGuan Xuetao info._sifields._sigfault._addr = env->cp0.c4_faultaddr; 1126d2fbca94SGuan Xuetao queue_signal(env, info.si_signo, &info); 1127d2fbca94SGuan Xuetao break; 1128d2fbca94SGuan Xuetao case EXCP_INTERRUPT: 1129d2fbca94SGuan Xuetao /* just indicate that signals should be handled asap */ 1130d2fbca94SGuan Xuetao break; 1131d2fbca94SGuan Xuetao case EXCP_DEBUG: 1132d2fbca94SGuan Xuetao { 1133d2fbca94SGuan Xuetao int sig; 1134d2fbca94SGuan Xuetao 1135db6b81d4SAndreas Färber sig = gdb_handlesig(cs, TARGET_SIGTRAP); 1136d2fbca94SGuan Xuetao if (sig) { 1137d2fbca94SGuan Xuetao info.si_signo = sig; 1138d2fbca94SGuan Xuetao info.si_errno = 0; 1139d2fbca94SGuan Xuetao info.si_code = TARGET_TRAP_BRKPT; 1140d2fbca94SGuan Xuetao queue_signal(env, info.si_signo, &info); 1141d2fbca94SGuan Xuetao } 1142d2fbca94SGuan Xuetao } 1143d2fbca94SGuan Xuetao break; 1144d2fbca94SGuan Xuetao default: 1145d2fbca94SGuan Xuetao goto error; 1146d2fbca94SGuan Xuetao } 1147d2fbca94SGuan Xuetao process_pending_signals(env); 1148d2fbca94SGuan Xuetao } 1149d2fbca94SGuan Xuetao 1150d2fbca94SGuan Xuetao error: 1151d2fbca94SGuan Xuetao fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr); 1152878096eeSAndreas Färber cpu_dump_state(cs, stderr, fprintf, 0); 1153d2fbca94SGuan Xuetao abort(); 1154d2fbca94SGuan Xuetao } 1155d2fbca94SGuan Xuetao #endif 1156d2fbca94SGuan Xuetao 115793ac68bcSbellard #ifdef TARGET_SPARC 1158ed23fbd9Sblueswir1 #define SPARC64_STACK_BIAS 2047 115993ac68bcSbellard 1160060366c5Sbellard //#define DEBUG_WIN 1161060366c5Sbellard 11622623cbafSbellard /* WARNING: dealing with register windows _is_ complicated. More info 11632623cbafSbellard can be found at http://www.sics.se/~psm/sparcstack.html */ 1164060366c5Sbellard static inline int get_reg_index(CPUSPARCState *env, int cwp, int index) 1165060366c5Sbellard { 11661a14026eSblueswir1 index = (index + cwp * 16) % (16 * env->nwindows); 1167060366c5Sbellard /* wrap handling : if cwp is on the last window, then we use the 1168060366c5Sbellard registers 'after' the end */ 11691a14026eSblueswir1 if (index < 8 && env->cwp == env->nwindows - 1) 11701a14026eSblueswir1 index += 16 * env->nwindows; 1171060366c5Sbellard return index; 1172060366c5Sbellard } 1173060366c5Sbellard 11742623cbafSbellard /* save the register window 'cwp1' */ 11752623cbafSbellard static inline void save_window_offset(CPUSPARCState *env, int cwp1) 1176060366c5Sbellard { 11772623cbafSbellard unsigned int i; 1178992f48a0Sblueswir1 abi_ulong sp_ptr; 1179060366c5Sbellard 118053a5960aSpbrook sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)]; 1181ed23fbd9Sblueswir1 #ifdef TARGET_SPARC64 1182ed23fbd9Sblueswir1 if (sp_ptr & 3) 1183ed23fbd9Sblueswir1 sp_ptr += SPARC64_STACK_BIAS; 1184ed23fbd9Sblueswir1 #endif 1185060366c5Sbellard #if defined(DEBUG_WIN) 11862daf0284Sblueswir1 printf("win_overflow: sp_ptr=0x" TARGET_ABI_FMT_lx " save_cwp=%d\n", 11872daf0284Sblueswir1 sp_ptr, cwp1); 1188060366c5Sbellard #endif 11892623cbafSbellard for(i = 0; i < 16; i++) { 11902f619698Sbellard /* FIXME - what to do if put_user() fails? */ 11912f619698Sbellard put_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr); 1192992f48a0Sblueswir1 sp_ptr += sizeof(abi_ulong); 11932623cbafSbellard } 1194060366c5Sbellard } 1195060366c5Sbellard 1196060366c5Sbellard static void save_window(CPUSPARCState *env) 1197060366c5Sbellard { 11985ef54116Sbellard #ifndef TARGET_SPARC64 11992623cbafSbellard unsigned int new_wim; 12001a14026eSblueswir1 new_wim = ((env->wim >> 1) | (env->wim << (env->nwindows - 1))) & 12011a14026eSblueswir1 ((1LL << env->nwindows) - 1); 12021a14026eSblueswir1 save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2)); 12032623cbafSbellard env->wim = new_wim; 12045ef54116Sbellard #else 12051a14026eSblueswir1 save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2)); 12065ef54116Sbellard env->cansave++; 12075ef54116Sbellard env->canrestore--; 12085ef54116Sbellard #endif 1209060366c5Sbellard } 1210060366c5Sbellard 1211060366c5Sbellard static void restore_window(CPUSPARCState *env) 1212060366c5Sbellard { 1213eda52953Sblueswir1 #ifndef TARGET_SPARC64 1214eda52953Sblueswir1 unsigned int new_wim; 1215eda52953Sblueswir1 #endif 1216eda52953Sblueswir1 unsigned int i, cwp1; 1217992f48a0Sblueswir1 abi_ulong sp_ptr; 1218060366c5Sbellard 1219eda52953Sblueswir1 #ifndef TARGET_SPARC64 12201a14026eSblueswir1 new_wim = ((env->wim << 1) | (env->wim >> (env->nwindows - 1))) & 12211a14026eSblueswir1 ((1LL << env->nwindows) - 1); 1222eda52953Sblueswir1 #endif 1223060366c5Sbellard 1224060366c5Sbellard /* restore the invalid window */ 12251a14026eSblueswir1 cwp1 = cpu_cwp_inc(env, env->cwp + 1); 122653a5960aSpbrook sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)]; 1227ed23fbd9Sblueswir1 #ifdef TARGET_SPARC64 1228ed23fbd9Sblueswir1 if (sp_ptr & 3) 1229ed23fbd9Sblueswir1 sp_ptr += SPARC64_STACK_BIAS; 1230ed23fbd9Sblueswir1 #endif 1231060366c5Sbellard #if defined(DEBUG_WIN) 12322daf0284Sblueswir1 printf("win_underflow: sp_ptr=0x" TARGET_ABI_FMT_lx " load_cwp=%d\n", 12332daf0284Sblueswir1 sp_ptr, cwp1); 1234060366c5Sbellard #endif 12352623cbafSbellard for(i = 0; i < 16; i++) { 12362f619698Sbellard /* FIXME - what to do if get_user() fails? */ 12372f619698Sbellard get_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr); 1238992f48a0Sblueswir1 sp_ptr += sizeof(abi_ulong); 12392623cbafSbellard } 12405ef54116Sbellard #ifdef TARGET_SPARC64 12415ef54116Sbellard env->canrestore++; 12421a14026eSblueswir1 if (env->cleanwin < env->nwindows - 1) 12435ef54116Sbellard env->cleanwin++; 12445ef54116Sbellard env->cansave--; 1245eda52953Sblueswir1 #else 1246eda52953Sblueswir1 env->wim = new_wim; 12475ef54116Sbellard #endif 1248060366c5Sbellard } 1249060366c5Sbellard 1250060366c5Sbellard static void flush_windows(CPUSPARCState *env) 1251060366c5Sbellard { 1252060366c5Sbellard int offset, cwp1; 12532623cbafSbellard 12542623cbafSbellard offset = 1; 1255060366c5Sbellard for(;;) { 1256060366c5Sbellard /* if restore would invoke restore_window(), then we can stop */ 12571a14026eSblueswir1 cwp1 = cpu_cwp_inc(env, env->cwp + offset); 1258eda52953Sblueswir1 #ifndef TARGET_SPARC64 1259060366c5Sbellard if (env->wim & (1 << cwp1)) 1260060366c5Sbellard break; 1261eda52953Sblueswir1 #else 1262eda52953Sblueswir1 if (env->canrestore == 0) 1263eda52953Sblueswir1 break; 1264eda52953Sblueswir1 env->cansave++; 1265eda52953Sblueswir1 env->canrestore--; 1266eda52953Sblueswir1 #endif 12672623cbafSbellard save_window_offset(env, cwp1); 1268060366c5Sbellard offset++; 1269060366c5Sbellard } 12701a14026eSblueswir1 cwp1 = cpu_cwp_inc(env, env->cwp + 1); 1271eda52953Sblueswir1 #ifndef TARGET_SPARC64 1272eda52953Sblueswir1 /* set wim so that restore will reload the registers */ 12732623cbafSbellard env->wim = 1 << cwp1; 1274eda52953Sblueswir1 #endif 12752623cbafSbellard #if defined(DEBUG_WIN) 12762623cbafSbellard printf("flush_windows: nb=%d\n", offset - 1); 127780a9d035Sbellard #endif 12782623cbafSbellard } 1279060366c5Sbellard 128093ac68bcSbellard void cpu_loop (CPUSPARCState *env) 128193ac68bcSbellard { 1282878096eeSAndreas Färber CPUState *cs = CPU(sparc_env_get_cpu(env)); 12832cc20260SRichard Henderson int trapnr; 12842cc20260SRichard Henderson abi_long ret; 1285c227f099SAnthony Liguori target_siginfo_t info; 128693ac68bcSbellard 128793ac68bcSbellard while (1) { 1288b040bc9cSPeter Maydell cpu_exec_start(cs); 1289ea3e9847SPeter Crosthwaite trapnr = cpu_sparc_exec(cs); 1290b040bc9cSPeter Maydell cpu_exec_end(cs); 129193ac68bcSbellard 129220132b96SRichard Henderson /* Compute PSR before exposing state. */ 129320132b96SRichard Henderson if (env->cc_op != CC_OP_FLAGS) { 129420132b96SRichard Henderson cpu_get_psr(env); 129520132b96SRichard Henderson } 129620132b96SRichard Henderson 129793ac68bcSbellard switch (trapnr) { 12985ef54116Sbellard #ifndef TARGET_SPARC64 1299060366c5Sbellard case 0x88: 1300060366c5Sbellard case 0x90: 13015ef54116Sbellard #else 1302cb33da57Sblueswir1 case 0x110: 13035ef54116Sbellard case 0x16d: 13045ef54116Sbellard #endif 1305060366c5Sbellard ret = do_syscall (env, env->gregs[1], 1306060366c5Sbellard env->regwptr[0], env->regwptr[1], 1307060366c5Sbellard env->regwptr[2], env->regwptr[3], 13085945cfcbSPeter Maydell env->regwptr[4], env->regwptr[5], 13095945cfcbSPeter Maydell 0, 0); 13102cc20260SRichard Henderson if ((abi_ulong)ret >= (abi_ulong)(-515)) { 1311992f48a0Sblueswir1 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) 131227908725Sbellard env->xcc |= PSR_CARRY; 131327908725Sbellard #else 131493ac68bcSbellard env->psr |= PSR_CARRY; 131527908725Sbellard #endif 1316060366c5Sbellard ret = -ret; 1317060366c5Sbellard } else { 1318992f48a0Sblueswir1 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) 131927908725Sbellard env->xcc &= ~PSR_CARRY; 132027908725Sbellard #else 1321060366c5Sbellard env->psr &= ~PSR_CARRY; 132227908725Sbellard #endif 1323060366c5Sbellard } 1324060366c5Sbellard env->regwptr[0] = ret; 1325060366c5Sbellard /* next instruction */ 1326060366c5Sbellard env->pc = env->npc; 1327060366c5Sbellard env->npc = env->npc + 4; 1328060366c5Sbellard break; 1329060366c5Sbellard case 0x83: /* flush windows */ 1330992f48a0Sblueswir1 #ifdef TARGET_ABI32 1331992f48a0Sblueswir1 case 0x103: 1332992f48a0Sblueswir1 #endif 13332623cbafSbellard flush_windows(env); 1334060366c5Sbellard /* next instruction */ 1335060366c5Sbellard env->pc = env->npc; 1336060366c5Sbellard env->npc = env->npc + 4; 1337060366c5Sbellard break; 13383475187dSbellard #ifndef TARGET_SPARC64 1339060366c5Sbellard case TT_WIN_OVF: /* window overflow */ 1340060366c5Sbellard save_window(env); 1341060366c5Sbellard break; 1342060366c5Sbellard case TT_WIN_UNF: /* window underflow */ 1343060366c5Sbellard restore_window(env); 134493ac68bcSbellard break; 134561ff6f58Sbellard case TT_TFAULT: 134661ff6f58Sbellard case TT_DFAULT: 134761ff6f58Sbellard { 134859f7182fSRichard Henderson info.si_signo = TARGET_SIGSEGV; 134961ff6f58Sbellard info.si_errno = 0; 135061ff6f58Sbellard /* XXX: check env->error_code */ 135161ff6f58Sbellard info.si_code = TARGET_SEGV_MAPERR; 135261ff6f58Sbellard info._sifields._sigfault._addr = env->mmuregs[4]; 1353624f7979Spbrook queue_signal(env, info.si_signo, &info); 135461ff6f58Sbellard } 135561ff6f58Sbellard break; 13563475187dSbellard #else 13575ef54116Sbellard case TT_SPILL: /* window overflow */ 13585ef54116Sbellard save_window(env); 13595ef54116Sbellard break; 13605ef54116Sbellard case TT_FILL: /* window underflow */ 13615ef54116Sbellard restore_window(env); 13625ef54116Sbellard break; 13637f84a729Sblueswir1 case TT_TFAULT: 13647f84a729Sblueswir1 case TT_DFAULT: 13657f84a729Sblueswir1 { 136659f7182fSRichard Henderson info.si_signo = TARGET_SIGSEGV; 13677f84a729Sblueswir1 info.si_errno = 0; 13687f84a729Sblueswir1 /* XXX: check env->error_code */ 13697f84a729Sblueswir1 info.si_code = TARGET_SEGV_MAPERR; 13707f84a729Sblueswir1 if (trapnr == TT_DFAULT) 13717f84a729Sblueswir1 info._sifields._sigfault._addr = env->dmmuregs[4]; 13727f84a729Sblueswir1 else 13738194f35aSIgor Kovalenko info._sifields._sigfault._addr = cpu_tsptr(env)->tpc; 1374624f7979Spbrook queue_signal(env, info.si_signo, &info); 13757f84a729Sblueswir1 } 13767f84a729Sblueswir1 break; 137727524dc3Sbellard #ifndef TARGET_ABI32 13785bfb56b2Sblueswir1 case 0x16e: 13795bfb56b2Sblueswir1 flush_windows(env); 13805bfb56b2Sblueswir1 sparc64_get_context(env); 13815bfb56b2Sblueswir1 break; 13825bfb56b2Sblueswir1 case 0x16f: 13835bfb56b2Sblueswir1 flush_windows(env); 13845bfb56b2Sblueswir1 sparc64_set_context(env); 13855bfb56b2Sblueswir1 break; 13863475187dSbellard #endif 138727524dc3Sbellard #endif 138848dc41ebSbellard case EXCP_INTERRUPT: 138948dc41ebSbellard /* just indicate that signals should be handled asap */ 1390e80cfcfcSbellard break; 139175f22e4eSRichard Henderson case TT_ILL_INSN: 139275f22e4eSRichard Henderson { 139375f22e4eSRichard Henderson info.si_signo = TARGET_SIGILL; 139475f22e4eSRichard Henderson info.si_errno = 0; 139575f22e4eSRichard Henderson info.si_code = TARGET_ILL_ILLOPC; 139675f22e4eSRichard Henderson info._sifields._sigfault._addr = env->pc; 139775f22e4eSRichard Henderson queue_signal(env, info.si_signo, &info); 139875f22e4eSRichard Henderson } 139975f22e4eSRichard Henderson break; 14001fddef4bSbellard case EXCP_DEBUG: 14011fddef4bSbellard { 14021fddef4bSbellard int sig; 14031fddef4bSbellard 1404db6b81d4SAndreas Färber sig = gdb_handlesig(cs, TARGET_SIGTRAP); 14051fddef4bSbellard if (sig) 14061fddef4bSbellard { 14071fddef4bSbellard info.si_signo = sig; 14081fddef4bSbellard info.si_errno = 0; 14091fddef4bSbellard info.si_code = TARGET_TRAP_BRKPT; 1410624f7979Spbrook queue_signal(env, info.si_signo, &info); 14111fddef4bSbellard } 14121fddef4bSbellard } 14131fddef4bSbellard break; 141493ac68bcSbellard default: 1415060366c5Sbellard printf ("Unhandled trap: 0x%x\n", trapnr); 1416878096eeSAndreas Färber cpu_dump_state(cs, stderr, fprintf, 0); 14174d1275c2SRiku Voipio exit(EXIT_FAILURE); 141893ac68bcSbellard } 141993ac68bcSbellard process_pending_signals (env); 142093ac68bcSbellard } 142193ac68bcSbellard } 142293ac68bcSbellard 142393ac68bcSbellard #endif 142493ac68bcSbellard 142567867308Sbellard #ifdef TARGET_PPC 142605390248SAndreas Färber static inline uint64_t cpu_ppc_get_tb(CPUPPCState *env) 14279fddaa0cSbellard { 14287d6b1daeSLaurent Vivier return cpu_get_real_ticks(); 14299fddaa0cSbellard } 14309fddaa0cSbellard 143105390248SAndreas Färber uint64_t cpu_ppc_load_tbl(CPUPPCState *env) 14329fddaa0cSbellard { 1433e3ea6529SAlexander Graf return cpu_ppc_get_tb(env); 14349fddaa0cSbellard } 14359fddaa0cSbellard 143605390248SAndreas Färber uint32_t cpu_ppc_load_tbu(CPUPPCState *env) 14379fddaa0cSbellard { 14389fddaa0cSbellard return cpu_ppc_get_tb(env) >> 32; 14399fddaa0cSbellard } 14409fddaa0cSbellard 144105390248SAndreas Färber uint64_t cpu_ppc_load_atbl(CPUPPCState *env) 14429fddaa0cSbellard { 1443b711de95SAurelien Jarno return cpu_ppc_get_tb(env); 14449fddaa0cSbellard } 14459fddaa0cSbellard 144605390248SAndreas Färber uint32_t cpu_ppc_load_atbu(CPUPPCState *env) 14479fddaa0cSbellard { 1448a062e36cSj_mayer return cpu_ppc_get_tb(env) >> 32; 14499fddaa0cSbellard } 14509fddaa0cSbellard 145105390248SAndreas Färber uint32_t cpu_ppc601_load_rtcu(CPUPPCState *env) 145276a66253Sj_mayer __attribute__ (( alias ("cpu_ppc_load_tbu") )); 145376a66253Sj_mayer 145405390248SAndreas Färber uint32_t cpu_ppc601_load_rtcl(CPUPPCState *env) 14559fddaa0cSbellard { 145676a66253Sj_mayer return cpu_ppc_load_tbl(env) & 0x3FFFFF80; 14579fddaa0cSbellard } 14589fddaa0cSbellard 1459a750fc0bSj_mayer /* XXX: to be fixed */ 146073b01960SAlexander Graf int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp) 1461a750fc0bSj_mayer { 1462a750fc0bSj_mayer return -1; 1463a750fc0bSj_mayer } 1464a750fc0bSj_mayer 146573b01960SAlexander Graf int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val) 1466a750fc0bSj_mayer { 1467a750fc0bSj_mayer return -1; 1468a750fc0bSj_mayer } 1469a750fc0bSj_mayer 1470001faf32SBlue Swirl #define EXCP_DUMP(env, fmt, ...) \ 1471e1833e1fSj_mayer do { \ 1472a0762859SAndreas Färber CPUState *cs = ENV_GET_CPU(env); \ 1473001faf32SBlue Swirl fprintf(stderr, fmt , ## __VA_ARGS__); \ 1474a0762859SAndreas Färber cpu_dump_state(cs, stderr, fprintf, 0); \ 1475001faf32SBlue Swirl qemu_log(fmt, ## __VA_ARGS__); \ 1476eeacee4dSBlue Swirl if (qemu_log_enabled()) { \ 1477a0762859SAndreas Färber log_cpu_state(cs, 0); \ 1478eeacee4dSBlue Swirl } \ 1479e1833e1fSj_mayer } while (0) 1480e1833e1fSj_mayer 148156f066bbSNathan Froyd static int do_store_exclusive(CPUPPCState *env) 148256f066bbSNathan Froyd { 148356f066bbSNathan Froyd target_ulong addr; 148456f066bbSNathan Froyd target_ulong page_addr; 1485e22c357bSDoug Kwan target_ulong val, val2 __attribute__((unused)) = 0; 148656f066bbSNathan Froyd int flags; 148756f066bbSNathan Froyd int segv = 0; 148856f066bbSNathan Froyd 148956f066bbSNathan Froyd addr = env->reserve_ea; 149056f066bbSNathan Froyd page_addr = addr & TARGET_PAGE_MASK; 149156f066bbSNathan Froyd start_exclusive(); 149256f066bbSNathan Froyd mmap_lock(); 149356f066bbSNathan Froyd flags = page_get_flags(page_addr); 149456f066bbSNathan Froyd if ((flags & PAGE_READ) == 0) { 149556f066bbSNathan Froyd segv = 1; 149656f066bbSNathan Froyd } else { 149756f066bbSNathan Froyd int reg = env->reserve_info & 0x1f; 14984b1daa72STom Musta int size = env->reserve_info >> 5; 149956f066bbSNathan Froyd int stored = 0; 150056f066bbSNathan Froyd 150156f066bbSNathan Froyd if (addr == env->reserve_addr) { 150256f066bbSNathan Froyd switch (size) { 150356f066bbSNathan Froyd case 1: segv = get_user_u8(val, addr); break; 150456f066bbSNathan Froyd case 2: segv = get_user_u16(val, addr); break; 150556f066bbSNathan Froyd case 4: segv = get_user_u32(val, addr); break; 150656f066bbSNathan Froyd #if defined(TARGET_PPC64) 150756f066bbSNathan Froyd case 8: segv = get_user_u64(val, addr); break; 150827b95bfeSTom Musta case 16: { 150927b95bfeSTom Musta segv = get_user_u64(val, addr); 151027b95bfeSTom Musta if (!segv) { 151127b95bfeSTom Musta segv = get_user_u64(val2, addr + 8); 151227b95bfeSTom Musta } 151327b95bfeSTom Musta break; 151427b95bfeSTom Musta } 151556f066bbSNathan Froyd #endif 151656f066bbSNathan Froyd default: abort(); 151756f066bbSNathan Froyd } 151856f066bbSNathan Froyd if (!segv && val == env->reserve_val) { 151956f066bbSNathan Froyd val = env->gpr[reg]; 152056f066bbSNathan Froyd switch (size) { 152156f066bbSNathan Froyd case 1: segv = put_user_u8(val, addr); break; 152256f066bbSNathan Froyd case 2: segv = put_user_u16(val, addr); break; 152356f066bbSNathan Froyd case 4: segv = put_user_u32(val, addr); break; 152456f066bbSNathan Froyd #if defined(TARGET_PPC64) 152556f066bbSNathan Froyd case 8: segv = put_user_u64(val, addr); break; 152627b95bfeSTom Musta case 16: { 152727b95bfeSTom Musta if (val2 == env->reserve_val2) { 1528e22c357bSDoug Kwan if (msr_le) { 1529e22c357bSDoug Kwan val2 = val; 1530e22c357bSDoug Kwan val = env->gpr[reg+1]; 1531e22c357bSDoug Kwan } else { 1532e22c357bSDoug Kwan val2 = env->gpr[reg+1]; 1533e22c357bSDoug Kwan } 153427b95bfeSTom Musta segv = put_user_u64(val, addr); 153527b95bfeSTom Musta if (!segv) { 153627b95bfeSTom Musta segv = put_user_u64(val2, addr + 8); 153727b95bfeSTom Musta } 153827b95bfeSTom Musta } 153927b95bfeSTom Musta break; 154027b95bfeSTom Musta } 154156f066bbSNathan Froyd #endif 154256f066bbSNathan Froyd default: abort(); 154356f066bbSNathan Froyd } 154456f066bbSNathan Froyd if (!segv) { 154556f066bbSNathan Froyd stored = 1; 154656f066bbSNathan Froyd } 154756f066bbSNathan Froyd } 154856f066bbSNathan Froyd } 154956f066bbSNathan Froyd env->crf[0] = (stored << 1) | xer_so; 155056f066bbSNathan Froyd env->reserve_addr = (target_ulong)-1; 155156f066bbSNathan Froyd } 155256f066bbSNathan Froyd if (!segv) { 155356f066bbSNathan Froyd env->nip += 4; 155456f066bbSNathan Froyd } 155556f066bbSNathan Froyd mmap_unlock(); 155656f066bbSNathan Froyd end_exclusive(); 155756f066bbSNathan Froyd return segv; 155856f066bbSNathan Froyd } 155956f066bbSNathan Froyd 156067867308Sbellard void cpu_loop(CPUPPCState *env) 156167867308Sbellard { 15620315c31cSAndreas Färber CPUState *cs = CPU(ppc_env_get_cpu(env)); 1563c227f099SAnthony Liguori target_siginfo_t info; 156461190b14Sbellard int trapnr; 15659e0e2f96SRichard Henderson target_ulong ret; 156667867308Sbellard 156767867308Sbellard for(;;) { 15680315c31cSAndreas Färber cpu_exec_start(cs); 1569ea3e9847SPeter Crosthwaite trapnr = cpu_ppc_exec(cs); 15700315c31cSAndreas Färber cpu_exec_end(cs); 157167867308Sbellard switch(trapnr) { 1572e1833e1fSj_mayer case POWERPC_EXCP_NONE: 1573e1833e1fSj_mayer /* Just go on */ 157467867308Sbellard break; 1575e1833e1fSj_mayer case POWERPC_EXCP_CRITICAL: /* Critical input */ 1576a47dddd7SAndreas Färber cpu_abort(cs, "Critical interrupt while in user mode. " 1577e1833e1fSj_mayer "Aborting\n"); 1578e1833e1fSj_mayer break; 1579e1833e1fSj_mayer case POWERPC_EXCP_MCHECK: /* Machine check exception */ 1580a47dddd7SAndreas Färber cpu_abort(cs, "Machine check exception while in user mode. " 1581e1833e1fSj_mayer "Aborting\n"); 1582e1833e1fSj_mayer break; 1583e1833e1fSj_mayer case POWERPC_EXCP_DSI: /* Data storage exception */ 158490e189ecSBlue Swirl EXCP_DUMP(env, "Invalid data memory access: 0x" TARGET_FMT_lx "\n", 1585e1833e1fSj_mayer env->spr[SPR_DAR]); 1586e1833e1fSj_mayer /* XXX: check this. Seems bugged */ 1587e1833e1fSj_mayer switch (env->error_code & 0xFF000000) { 1588e1833e1fSj_mayer case 0x40000000: 1589e1833e1fSj_mayer info.si_signo = TARGET_SIGSEGV; 1590e1833e1fSj_mayer info.si_errno = 0; 1591e1833e1fSj_mayer info.si_code = TARGET_SEGV_MAPERR; 1592e1833e1fSj_mayer break; 1593e1833e1fSj_mayer case 0x04000000: 1594e1833e1fSj_mayer info.si_signo = TARGET_SIGILL; 1595e1833e1fSj_mayer info.si_errno = 0; 1596e1833e1fSj_mayer info.si_code = TARGET_ILL_ILLADR; 1597e1833e1fSj_mayer break; 1598e1833e1fSj_mayer case 0x08000000: 1599e1833e1fSj_mayer info.si_signo = TARGET_SIGSEGV; 1600e1833e1fSj_mayer info.si_errno = 0; 1601e1833e1fSj_mayer info.si_code = TARGET_SEGV_ACCERR; 1602e1833e1fSj_mayer break; 1603e1833e1fSj_mayer default: 1604e1833e1fSj_mayer /* Let's send a regular segfault... */ 1605e1833e1fSj_mayer EXCP_DUMP(env, "Invalid segfault errno (%02x)\n", 1606e1833e1fSj_mayer env->error_code); 1607e1833e1fSj_mayer info.si_signo = TARGET_SIGSEGV; 1608e1833e1fSj_mayer info.si_errno = 0; 1609e1833e1fSj_mayer info.si_code = TARGET_SEGV_MAPERR; 1610e1833e1fSj_mayer break; 1611e1833e1fSj_mayer } 1612e1833e1fSj_mayer info._sifields._sigfault._addr = env->nip; 1613624f7979Spbrook queue_signal(env, info.si_signo, &info); 1614e1833e1fSj_mayer break; 1615e1833e1fSj_mayer case POWERPC_EXCP_ISI: /* Instruction storage exception */ 161690e189ecSBlue Swirl EXCP_DUMP(env, "Invalid instruction fetch: 0x\n" TARGET_FMT_lx 161790e189ecSBlue Swirl "\n", env->spr[SPR_SRR0]); 1618e1833e1fSj_mayer /* XXX: check this */ 1619e1833e1fSj_mayer switch (env->error_code & 0xFF000000) { 1620e1833e1fSj_mayer case 0x40000000: 1621e1833e1fSj_mayer info.si_signo = TARGET_SIGSEGV; 1622e1833e1fSj_mayer info.si_errno = 0; 1623e1833e1fSj_mayer info.si_code = TARGET_SEGV_MAPERR; 1624e1833e1fSj_mayer break; 1625e1833e1fSj_mayer case 0x10000000: 1626e1833e1fSj_mayer case 0x08000000: 1627e1833e1fSj_mayer info.si_signo = TARGET_SIGSEGV; 1628e1833e1fSj_mayer info.si_errno = 0; 1629e1833e1fSj_mayer info.si_code = TARGET_SEGV_ACCERR; 1630e1833e1fSj_mayer break; 1631e1833e1fSj_mayer default: 1632e1833e1fSj_mayer /* Let's send a regular segfault... */ 1633e1833e1fSj_mayer EXCP_DUMP(env, "Invalid segfault errno (%02x)\n", 1634e1833e1fSj_mayer env->error_code); 1635e1833e1fSj_mayer info.si_signo = TARGET_SIGSEGV; 1636e1833e1fSj_mayer info.si_errno = 0; 1637e1833e1fSj_mayer info.si_code = TARGET_SEGV_MAPERR; 1638e1833e1fSj_mayer break; 1639e1833e1fSj_mayer } 1640e1833e1fSj_mayer info._sifields._sigfault._addr = env->nip - 4; 1641624f7979Spbrook queue_signal(env, info.si_signo, &info); 1642e1833e1fSj_mayer break; 1643e1833e1fSj_mayer case POWERPC_EXCP_EXTERNAL: /* External input */ 1644a47dddd7SAndreas Färber cpu_abort(cs, "External interrupt while in user mode. " 1645e1833e1fSj_mayer "Aborting\n"); 1646e1833e1fSj_mayer break; 1647e1833e1fSj_mayer case POWERPC_EXCP_ALIGN: /* Alignment exception */ 1648e1833e1fSj_mayer EXCP_DUMP(env, "Unaligned memory access\n"); 1649e1833e1fSj_mayer /* XXX: check this */ 1650e1833e1fSj_mayer info.si_signo = TARGET_SIGBUS; 1651e1833e1fSj_mayer info.si_errno = 0; 1652e1833e1fSj_mayer info.si_code = TARGET_BUS_ADRALN; 16536bb9a0a9SAnton Blanchard info._sifields._sigfault._addr = env->nip; 1654624f7979Spbrook queue_signal(env, info.si_signo, &info); 1655e1833e1fSj_mayer break; 1656e1833e1fSj_mayer case POWERPC_EXCP_PROGRAM: /* Program exception */ 1657e1833e1fSj_mayer /* XXX: check this */ 1658e1833e1fSj_mayer switch (env->error_code & ~0xF) { 1659e1833e1fSj_mayer case POWERPC_EXCP_FP: 1660e1833e1fSj_mayer EXCP_DUMP(env, "Floating point program exception\n"); 1661e1833e1fSj_mayer info.si_signo = TARGET_SIGFPE; 1662e1833e1fSj_mayer info.si_errno = 0; 1663e1833e1fSj_mayer switch (env->error_code & 0xF) { 1664e1833e1fSj_mayer case POWERPC_EXCP_FP_OX: 1665e1833e1fSj_mayer info.si_code = TARGET_FPE_FLTOVF; 1666e1833e1fSj_mayer break; 1667e1833e1fSj_mayer case POWERPC_EXCP_FP_UX: 1668e1833e1fSj_mayer info.si_code = TARGET_FPE_FLTUND; 1669e1833e1fSj_mayer break; 1670e1833e1fSj_mayer case POWERPC_EXCP_FP_ZX: 1671e1833e1fSj_mayer case POWERPC_EXCP_FP_VXZDZ: 1672e1833e1fSj_mayer info.si_code = TARGET_FPE_FLTDIV; 1673e1833e1fSj_mayer break; 1674e1833e1fSj_mayer case POWERPC_EXCP_FP_XX: 1675e1833e1fSj_mayer info.si_code = TARGET_FPE_FLTRES; 1676e1833e1fSj_mayer break; 1677e1833e1fSj_mayer case POWERPC_EXCP_FP_VXSOFT: 1678e1833e1fSj_mayer info.si_code = TARGET_FPE_FLTINV; 1679e1833e1fSj_mayer break; 16807c58044cSj_mayer case POWERPC_EXCP_FP_VXSNAN: 1681e1833e1fSj_mayer case POWERPC_EXCP_FP_VXISI: 1682e1833e1fSj_mayer case POWERPC_EXCP_FP_VXIDI: 1683e1833e1fSj_mayer case POWERPC_EXCP_FP_VXIMZ: 1684e1833e1fSj_mayer case POWERPC_EXCP_FP_VXVC: 1685e1833e1fSj_mayer case POWERPC_EXCP_FP_VXSQRT: 1686e1833e1fSj_mayer case POWERPC_EXCP_FP_VXCVI: 1687e1833e1fSj_mayer info.si_code = TARGET_FPE_FLTSUB; 1688e1833e1fSj_mayer break; 1689e1833e1fSj_mayer default: 1690e1833e1fSj_mayer EXCP_DUMP(env, "Unknown floating point exception (%02x)\n", 1691e1833e1fSj_mayer env->error_code); 1692e1833e1fSj_mayer break; 1693e1833e1fSj_mayer } 1694e1833e1fSj_mayer break; 1695e1833e1fSj_mayer case POWERPC_EXCP_INVAL: 1696e1833e1fSj_mayer EXCP_DUMP(env, "Invalid instruction\n"); 1697e1833e1fSj_mayer info.si_signo = TARGET_SIGILL; 1698e1833e1fSj_mayer info.si_errno = 0; 1699e1833e1fSj_mayer switch (env->error_code & 0xF) { 1700e1833e1fSj_mayer case POWERPC_EXCP_INVAL_INVAL: 1701e1833e1fSj_mayer info.si_code = TARGET_ILL_ILLOPC; 1702e1833e1fSj_mayer break; 1703e1833e1fSj_mayer case POWERPC_EXCP_INVAL_LSWX: 1704e1833e1fSj_mayer info.si_code = TARGET_ILL_ILLOPN; 1705e1833e1fSj_mayer break; 1706e1833e1fSj_mayer case POWERPC_EXCP_INVAL_SPR: 1707e1833e1fSj_mayer info.si_code = TARGET_ILL_PRVREG; 1708e1833e1fSj_mayer break; 1709e1833e1fSj_mayer case POWERPC_EXCP_INVAL_FP: 1710e1833e1fSj_mayer info.si_code = TARGET_ILL_COPROC; 1711e1833e1fSj_mayer break; 1712e1833e1fSj_mayer default: 1713e1833e1fSj_mayer EXCP_DUMP(env, "Unknown invalid operation (%02x)\n", 1714e1833e1fSj_mayer env->error_code & 0xF); 1715e1833e1fSj_mayer info.si_code = TARGET_ILL_ILLADR; 1716e1833e1fSj_mayer break; 1717e1833e1fSj_mayer } 1718e1833e1fSj_mayer break; 1719e1833e1fSj_mayer case POWERPC_EXCP_PRIV: 1720e1833e1fSj_mayer EXCP_DUMP(env, "Privilege violation\n"); 1721e1833e1fSj_mayer info.si_signo = TARGET_SIGILL; 1722e1833e1fSj_mayer info.si_errno = 0; 1723e1833e1fSj_mayer switch (env->error_code & 0xF) { 1724e1833e1fSj_mayer case POWERPC_EXCP_PRIV_OPC: 1725e1833e1fSj_mayer info.si_code = TARGET_ILL_PRVOPC; 1726e1833e1fSj_mayer break; 1727e1833e1fSj_mayer case POWERPC_EXCP_PRIV_REG: 1728e1833e1fSj_mayer info.si_code = TARGET_ILL_PRVREG; 1729e1833e1fSj_mayer break; 1730e1833e1fSj_mayer default: 1731e1833e1fSj_mayer EXCP_DUMP(env, "Unknown privilege violation (%02x)\n", 1732e1833e1fSj_mayer env->error_code & 0xF); 1733e1833e1fSj_mayer info.si_code = TARGET_ILL_PRVOPC; 1734e1833e1fSj_mayer break; 1735e1833e1fSj_mayer } 1736e1833e1fSj_mayer break; 1737e1833e1fSj_mayer case POWERPC_EXCP_TRAP: 1738a47dddd7SAndreas Färber cpu_abort(cs, "Tried to call a TRAP\n"); 1739e1833e1fSj_mayer break; 1740e1833e1fSj_mayer default: 1741e1833e1fSj_mayer /* Should not happen ! */ 1742a47dddd7SAndreas Färber cpu_abort(cs, "Unknown program exception (%02x)\n", 1743e1833e1fSj_mayer env->error_code); 1744e1833e1fSj_mayer break; 1745e1833e1fSj_mayer } 1746e1833e1fSj_mayer info._sifields._sigfault._addr = env->nip - 4; 1747624f7979Spbrook queue_signal(env, info.si_signo, &info); 1748e1833e1fSj_mayer break; 1749e1833e1fSj_mayer case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ 1750e1833e1fSj_mayer EXCP_DUMP(env, "No floating point allowed\n"); 1751e1833e1fSj_mayer info.si_signo = TARGET_SIGILL; 1752e1833e1fSj_mayer info.si_errno = 0; 1753e1833e1fSj_mayer info.si_code = TARGET_ILL_COPROC; 1754e1833e1fSj_mayer info._sifields._sigfault._addr = env->nip - 4; 1755624f7979Spbrook queue_signal(env, info.si_signo, &info); 1756e1833e1fSj_mayer break; 1757e1833e1fSj_mayer case POWERPC_EXCP_SYSCALL: /* System call exception */ 1758a47dddd7SAndreas Färber cpu_abort(cs, "Syscall exception while in user mode. " 1759e1833e1fSj_mayer "Aborting\n"); 1760e1833e1fSj_mayer break; 1761e1833e1fSj_mayer case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */ 1762e1833e1fSj_mayer EXCP_DUMP(env, "No APU instruction allowed\n"); 1763e1833e1fSj_mayer info.si_signo = TARGET_SIGILL; 1764e1833e1fSj_mayer info.si_errno = 0; 1765e1833e1fSj_mayer info.si_code = TARGET_ILL_COPROC; 1766e1833e1fSj_mayer info._sifields._sigfault._addr = env->nip - 4; 1767624f7979Spbrook queue_signal(env, info.si_signo, &info); 1768e1833e1fSj_mayer break; 1769e1833e1fSj_mayer case POWERPC_EXCP_DECR: /* Decrementer exception */ 1770a47dddd7SAndreas Färber cpu_abort(cs, "Decrementer interrupt while in user mode. " 1771e1833e1fSj_mayer "Aborting\n"); 1772e1833e1fSj_mayer break; 1773e1833e1fSj_mayer case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */ 1774a47dddd7SAndreas Färber cpu_abort(cs, "Fix interval timer interrupt while in user mode. " 1775e1833e1fSj_mayer "Aborting\n"); 1776e1833e1fSj_mayer break; 1777e1833e1fSj_mayer case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */ 1778a47dddd7SAndreas Färber cpu_abort(cs, "Watchdog timer interrupt while in user mode. " 1779e1833e1fSj_mayer "Aborting\n"); 1780e1833e1fSj_mayer break; 1781e1833e1fSj_mayer case POWERPC_EXCP_DTLB: /* Data TLB error */ 1782a47dddd7SAndreas Färber cpu_abort(cs, "Data TLB exception while in user mode. " 1783e1833e1fSj_mayer "Aborting\n"); 1784e1833e1fSj_mayer break; 1785e1833e1fSj_mayer case POWERPC_EXCP_ITLB: /* Instruction TLB error */ 1786a47dddd7SAndreas Färber cpu_abort(cs, "Instruction TLB exception while in user mode. " 1787e1833e1fSj_mayer "Aborting\n"); 1788e1833e1fSj_mayer break; 1789e1833e1fSj_mayer case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */ 1790e1833e1fSj_mayer EXCP_DUMP(env, "No SPE/floating-point instruction allowed\n"); 1791e1833e1fSj_mayer info.si_signo = TARGET_SIGILL; 1792e1833e1fSj_mayer info.si_errno = 0; 1793e1833e1fSj_mayer info.si_code = TARGET_ILL_COPROC; 1794e1833e1fSj_mayer info._sifields._sigfault._addr = env->nip - 4; 1795624f7979Spbrook queue_signal(env, info.si_signo, &info); 1796e1833e1fSj_mayer break; 1797e1833e1fSj_mayer case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */ 1798a47dddd7SAndreas Färber cpu_abort(cs, "Embedded floating-point data IRQ not handled\n"); 1799e1833e1fSj_mayer break; 1800e1833e1fSj_mayer case POWERPC_EXCP_EFPRI: /* Embedded floating-point round IRQ */ 1801a47dddd7SAndreas Färber cpu_abort(cs, "Embedded floating-point round IRQ not handled\n"); 1802e1833e1fSj_mayer break; 1803e1833e1fSj_mayer case POWERPC_EXCP_EPERFM: /* Embedded performance monitor IRQ */ 1804a47dddd7SAndreas Färber cpu_abort(cs, "Performance monitor exception not handled\n"); 1805e1833e1fSj_mayer break; 1806e1833e1fSj_mayer case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */ 1807a47dddd7SAndreas Färber cpu_abort(cs, "Doorbell interrupt while in user mode. " 1808e1833e1fSj_mayer "Aborting\n"); 1809e1833e1fSj_mayer break; 1810e1833e1fSj_mayer case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */ 1811a47dddd7SAndreas Färber cpu_abort(cs, "Doorbell critical interrupt while in user mode. " 1812e1833e1fSj_mayer "Aborting\n"); 1813e1833e1fSj_mayer break; 1814e1833e1fSj_mayer case POWERPC_EXCP_RESET: /* System reset exception */ 1815a47dddd7SAndreas Färber cpu_abort(cs, "Reset interrupt while in user mode. " 1816e1833e1fSj_mayer "Aborting\n"); 1817e1833e1fSj_mayer break; 1818e1833e1fSj_mayer case POWERPC_EXCP_DSEG: /* Data segment exception */ 1819a47dddd7SAndreas Färber cpu_abort(cs, "Data segment exception while in user mode. " 1820e1833e1fSj_mayer "Aborting\n"); 1821e1833e1fSj_mayer break; 1822e1833e1fSj_mayer case POWERPC_EXCP_ISEG: /* Instruction segment exception */ 1823a47dddd7SAndreas Färber cpu_abort(cs, "Instruction segment exception " 1824e1833e1fSj_mayer "while in user mode. Aborting\n"); 1825e1833e1fSj_mayer break; 1826e85e7c6eSj_mayer /* PowerPC 64 with hypervisor mode support */ 1827e1833e1fSj_mayer case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */ 1828a47dddd7SAndreas Färber cpu_abort(cs, "Hypervisor decrementer interrupt " 1829e1833e1fSj_mayer "while in user mode. Aborting\n"); 1830e1833e1fSj_mayer break; 1831e1833e1fSj_mayer case POWERPC_EXCP_TRACE: /* Trace exception */ 1832e1833e1fSj_mayer /* Nothing to do: 1833e1833e1fSj_mayer * we use this exception to emulate step-by-step execution mode. 1834e1833e1fSj_mayer */ 1835e1833e1fSj_mayer break; 1836e85e7c6eSj_mayer /* PowerPC 64 with hypervisor mode support */ 1837e1833e1fSj_mayer case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */ 1838a47dddd7SAndreas Färber cpu_abort(cs, "Hypervisor data storage exception " 1839e1833e1fSj_mayer "while in user mode. Aborting\n"); 1840e1833e1fSj_mayer break; 1841e1833e1fSj_mayer case POWERPC_EXCP_HISI: /* Hypervisor instruction storage excp */ 1842a47dddd7SAndreas Färber cpu_abort(cs, "Hypervisor instruction storage exception " 1843e1833e1fSj_mayer "while in user mode. Aborting\n"); 1844e1833e1fSj_mayer break; 1845e1833e1fSj_mayer case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */ 1846a47dddd7SAndreas Färber cpu_abort(cs, "Hypervisor data segment exception " 1847e1833e1fSj_mayer "while in user mode. Aborting\n"); 1848e1833e1fSj_mayer break; 1849e1833e1fSj_mayer case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment excp */ 1850a47dddd7SAndreas Färber cpu_abort(cs, "Hypervisor instruction segment exception " 1851e1833e1fSj_mayer "while in user mode. Aborting\n"); 1852e1833e1fSj_mayer break; 1853e1833e1fSj_mayer case POWERPC_EXCP_VPU: /* Vector unavailable exception */ 1854e1833e1fSj_mayer EXCP_DUMP(env, "No Altivec instructions allowed\n"); 1855e1833e1fSj_mayer info.si_signo = TARGET_SIGILL; 1856e1833e1fSj_mayer info.si_errno = 0; 1857e1833e1fSj_mayer info.si_code = TARGET_ILL_COPROC; 1858e1833e1fSj_mayer info._sifields._sigfault._addr = env->nip - 4; 1859624f7979Spbrook queue_signal(env, info.si_signo, &info); 1860e1833e1fSj_mayer break; 1861e1833e1fSj_mayer case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */ 1862a47dddd7SAndreas Färber cpu_abort(cs, "Programmable interval timer interrupt " 1863e1833e1fSj_mayer "while in user mode. Aborting\n"); 1864e1833e1fSj_mayer break; 1865e1833e1fSj_mayer case POWERPC_EXCP_IO: /* IO error exception */ 1866a47dddd7SAndreas Färber cpu_abort(cs, "IO error exception while in user mode. " 1867e1833e1fSj_mayer "Aborting\n"); 1868e1833e1fSj_mayer break; 1869e1833e1fSj_mayer case POWERPC_EXCP_RUNM: /* Run mode exception */ 1870a47dddd7SAndreas Färber cpu_abort(cs, "Run mode exception while in user mode. " 1871e1833e1fSj_mayer "Aborting\n"); 1872e1833e1fSj_mayer break; 1873e1833e1fSj_mayer case POWERPC_EXCP_EMUL: /* Emulation trap exception */ 1874a47dddd7SAndreas Färber cpu_abort(cs, "Emulation trap exception not handled\n"); 1875e1833e1fSj_mayer break; 1876e1833e1fSj_mayer case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */ 1877a47dddd7SAndreas Färber cpu_abort(cs, "Instruction fetch TLB exception " 1878e1833e1fSj_mayer "while in user-mode. Aborting"); 1879e1833e1fSj_mayer break; 1880e1833e1fSj_mayer case POWERPC_EXCP_DLTLB: /* Data load TLB miss */ 1881a47dddd7SAndreas Färber cpu_abort(cs, "Data load TLB exception while in user-mode. " 1882e1833e1fSj_mayer "Aborting"); 1883e1833e1fSj_mayer break; 1884e1833e1fSj_mayer case POWERPC_EXCP_DSTLB: /* Data store TLB miss */ 1885a47dddd7SAndreas Färber cpu_abort(cs, "Data store TLB exception while in user-mode. " 1886e1833e1fSj_mayer "Aborting"); 1887e1833e1fSj_mayer break; 1888e1833e1fSj_mayer case POWERPC_EXCP_FPA: /* Floating-point assist exception */ 1889a47dddd7SAndreas Färber cpu_abort(cs, "Floating-point assist exception not handled\n"); 1890e1833e1fSj_mayer break; 1891e1833e1fSj_mayer case POWERPC_EXCP_IABR: /* Instruction address breakpoint */ 1892a47dddd7SAndreas Färber cpu_abort(cs, "Instruction address breakpoint exception " 1893e1833e1fSj_mayer "not handled\n"); 1894e1833e1fSj_mayer break; 1895e1833e1fSj_mayer case POWERPC_EXCP_SMI: /* System management interrupt */ 1896a47dddd7SAndreas Färber cpu_abort(cs, "System management interrupt while in user mode. " 1897e1833e1fSj_mayer "Aborting\n"); 1898e1833e1fSj_mayer break; 1899e1833e1fSj_mayer case POWERPC_EXCP_THERM: /* Thermal interrupt */ 1900a47dddd7SAndreas Färber cpu_abort(cs, "Thermal interrupt interrupt while in user mode. " 1901e1833e1fSj_mayer "Aborting\n"); 1902e1833e1fSj_mayer break; 1903e1833e1fSj_mayer case POWERPC_EXCP_PERFM: /* Embedded performance monitor IRQ */ 1904a47dddd7SAndreas Färber cpu_abort(cs, "Performance monitor exception not handled\n"); 1905e1833e1fSj_mayer break; 1906e1833e1fSj_mayer case POWERPC_EXCP_VPUA: /* Vector assist exception */ 1907a47dddd7SAndreas Färber cpu_abort(cs, "Vector assist exception not handled\n"); 1908e1833e1fSj_mayer break; 1909e1833e1fSj_mayer case POWERPC_EXCP_SOFTP: /* Soft patch exception */ 1910a47dddd7SAndreas Färber cpu_abort(cs, "Soft patch exception not handled\n"); 1911e1833e1fSj_mayer break; 1912e1833e1fSj_mayer case POWERPC_EXCP_MAINT: /* Maintenance exception */ 1913a47dddd7SAndreas Färber cpu_abort(cs, "Maintenance exception while in user mode. " 1914e1833e1fSj_mayer "Aborting\n"); 1915e1833e1fSj_mayer break; 1916e1833e1fSj_mayer case POWERPC_EXCP_STOP: /* stop translation */ 1917e1833e1fSj_mayer /* We did invalidate the instruction cache. Go on */ 1918e1833e1fSj_mayer break; 1919e1833e1fSj_mayer case POWERPC_EXCP_BRANCH: /* branch instruction: */ 1920e1833e1fSj_mayer /* We just stopped because of a branch. Go on */ 1921e1833e1fSj_mayer break; 1922e1833e1fSj_mayer case POWERPC_EXCP_SYSCALL_USER: 1923e1833e1fSj_mayer /* system call in user-mode emulation */ 192467867308Sbellard /* WARNING: 192567867308Sbellard * PPC ABI uses overflow flag in cr0 to signal an error 192667867308Sbellard * in syscalls. 192767867308Sbellard */ 192867867308Sbellard env->crf[0] &= ~0x1; 192967867308Sbellard ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4], 193067867308Sbellard env->gpr[5], env->gpr[6], env->gpr[7], 19315945cfcbSPeter Maydell env->gpr[8], 0, 0); 19329e0e2f96SRichard Henderson if (ret == (target_ulong)(-TARGET_QEMU_ESIGRETURN)) { 1933bcd4933aSNathan Froyd /* Returning from a successful sigreturn syscall. 1934bcd4933aSNathan Froyd Avoid corrupting register state. */ 1935bcd4933aSNathan Froyd break; 1936bcd4933aSNathan Froyd } 19379e0e2f96SRichard Henderson if (ret > (target_ulong)(-515)) { 193867867308Sbellard env->crf[0] |= 0x1; 193967867308Sbellard ret = -ret; 194067867308Sbellard } 194167867308Sbellard env->gpr[3] = ret; 194261190b14Sbellard break; 194356f066bbSNathan Froyd case POWERPC_EXCP_STCX: 194456f066bbSNathan Froyd if (do_store_exclusive(env)) { 194556f066bbSNathan Froyd info.si_signo = TARGET_SIGSEGV; 194656f066bbSNathan Froyd info.si_errno = 0; 194756f066bbSNathan Froyd info.si_code = TARGET_SEGV_MAPERR; 194856f066bbSNathan Froyd info._sifields._sigfault._addr = env->nip; 194956f066bbSNathan Froyd queue_signal(env, info.si_signo, &info); 195056f066bbSNathan Froyd } 195156f066bbSNathan Froyd break; 195271f75756Saurel32 case EXCP_DEBUG: 195371f75756Saurel32 { 195471f75756Saurel32 int sig; 195571f75756Saurel32 1956db6b81d4SAndreas Färber sig = gdb_handlesig(cs, TARGET_SIGTRAP); 195771f75756Saurel32 if (sig) { 195871f75756Saurel32 info.si_signo = sig; 195971f75756Saurel32 info.si_errno = 0; 196071f75756Saurel32 info.si_code = TARGET_TRAP_BRKPT; 196171f75756Saurel32 queue_signal(env, info.si_signo, &info); 196271f75756Saurel32 } 196371f75756Saurel32 } 196471f75756Saurel32 break; 196556ba31ffSj_mayer case EXCP_INTERRUPT: 196656ba31ffSj_mayer /* just indicate that signals should be handled asap */ 196756ba31ffSj_mayer break; 196861190b14Sbellard default: 1969a47dddd7SAndreas Färber cpu_abort(cs, "Unknown exception 0x%d. Aborting\n", trapnr); 197067867308Sbellard break; 197167867308Sbellard } 197267867308Sbellard process_pending_signals(env); 197367867308Sbellard } 197467867308Sbellard } 197567867308Sbellard #endif 197667867308Sbellard 1977048f6b4dSbellard #ifdef TARGET_MIPS 1978048f6b4dSbellard 1979ff4f7382SRichard Henderson # ifdef TARGET_ABI_MIPSO32 1980048f6b4dSbellard # define MIPS_SYS(name, args) args, 1981048f6b4dSbellard static const uint8_t mips_syscall_args[] = { 198229fb0f25SAn-Cheng Huang MIPS_SYS(sys_syscall , 8) /* 4000 */ 1983048f6b4dSbellard MIPS_SYS(sys_exit , 1) 1984048f6b4dSbellard MIPS_SYS(sys_fork , 0) 1985048f6b4dSbellard MIPS_SYS(sys_read , 3) 1986048f6b4dSbellard MIPS_SYS(sys_write , 3) 1987048f6b4dSbellard MIPS_SYS(sys_open , 3) /* 4005 */ 1988048f6b4dSbellard MIPS_SYS(sys_close , 1) 1989048f6b4dSbellard MIPS_SYS(sys_waitpid , 3) 1990048f6b4dSbellard MIPS_SYS(sys_creat , 2) 1991048f6b4dSbellard MIPS_SYS(sys_link , 2) 1992048f6b4dSbellard MIPS_SYS(sys_unlink , 1) /* 4010 */ 1993048f6b4dSbellard MIPS_SYS(sys_execve , 0) 1994048f6b4dSbellard MIPS_SYS(sys_chdir , 1) 1995048f6b4dSbellard MIPS_SYS(sys_time , 1) 1996048f6b4dSbellard MIPS_SYS(sys_mknod , 3) 1997048f6b4dSbellard MIPS_SYS(sys_chmod , 2) /* 4015 */ 1998048f6b4dSbellard MIPS_SYS(sys_lchown , 3) 1999048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 2000048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was sys_stat */ 2001048f6b4dSbellard MIPS_SYS(sys_lseek , 3) 2002048f6b4dSbellard MIPS_SYS(sys_getpid , 0) /* 4020 */ 2003048f6b4dSbellard MIPS_SYS(sys_mount , 5) 2004868e34d7SRichard Henderson MIPS_SYS(sys_umount , 1) 2005048f6b4dSbellard MIPS_SYS(sys_setuid , 1) 2006048f6b4dSbellard MIPS_SYS(sys_getuid , 0) 2007048f6b4dSbellard MIPS_SYS(sys_stime , 1) /* 4025 */ 2008048f6b4dSbellard MIPS_SYS(sys_ptrace , 4) 2009048f6b4dSbellard MIPS_SYS(sys_alarm , 1) 2010048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was sys_fstat */ 2011048f6b4dSbellard MIPS_SYS(sys_pause , 0) 2012048f6b4dSbellard MIPS_SYS(sys_utime , 2) /* 4030 */ 2013048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 2014048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 2015048f6b4dSbellard MIPS_SYS(sys_access , 2) 2016048f6b4dSbellard MIPS_SYS(sys_nice , 1) 2017048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* 4035 */ 2018048f6b4dSbellard MIPS_SYS(sys_sync , 0) 2019048f6b4dSbellard MIPS_SYS(sys_kill , 2) 2020048f6b4dSbellard MIPS_SYS(sys_rename , 2) 2021048f6b4dSbellard MIPS_SYS(sys_mkdir , 2) 2022048f6b4dSbellard MIPS_SYS(sys_rmdir , 1) /* 4040 */ 2023048f6b4dSbellard MIPS_SYS(sys_dup , 1) 2024048f6b4dSbellard MIPS_SYS(sys_pipe , 0) 2025048f6b4dSbellard MIPS_SYS(sys_times , 1) 2026048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 2027048f6b4dSbellard MIPS_SYS(sys_brk , 1) /* 4045 */ 2028048f6b4dSbellard MIPS_SYS(sys_setgid , 1) 2029048f6b4dSbellard MIPS_SYS(sys_getgid , 0) 2030048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was signal(2) */ 2031048f6b4dSbellard MIPS_SYS(sys_geteuid , 0) 2032048f6b4dSbellard MIPS_SYS(sys_getegid , 0) /* 4050 */ 2033048f6b4dSbellard MIPS_SYS(sys_acct , 0) 2034868e34d7SRichard Henderson MIPS_SYS(sys_umount2 , 2) 2035048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 2036048f6b4dSbellard MIPS_SYS(sys_ioctl , 3) 2037048f6b4dSbellard MIPS_SYS(sys_fcntl , 3) /* 4055 */ 2038048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 2) 2039048f6b4dSbellard MIPS_SYS(sys_setpgid , 2) 2040048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 2041048f6b4dSbellard MIPS_SYS(sys_olduname , 1) 2042048f6b4dSbellard MIPS_SYS(sys_umask , 1) /* 4060 */ 2043048f6b4dSbellard MIPS_SYS(sys_chroot , 1) 2044048f6b4dSbellard MIPS_SYS(sys_ustat , 2) 2045048f6b4dSbellard MIPS_SYS(sys_dup2 , 2) 2046048f6b4dSbellard MIPS_SYS(sys_getppid , 0) 2047048f6b4dSbellard MIPS_SYS(sys_getpgrp , 0) /* 4065 */ 2048048f6b4dSbellard MIPS_SYS(sys_setsid , 0) 2049048f6b4dSbellard MIPS_SYS(sys_sigaction , 3) 2050048f6b4dSbellard MIPS_SYS(sys_sgetmask , 0) 2051048f6b4dSbellard MIPS_SYS(sys_ssetmask , 1) 2052048f6b4dSbellard MIPS_SYS(sys_setreuid , 2) /* 4070 */ 2053048f6b4dSbellard MIPS_SYS(sys_setregid , 2) 2054048f6b4dSbellard MIPS_SYS(sys_sigsuspend , 0) 2055048f6b4dSbellard MIPS_SYS(sys_sigpending , 1) 2056048f6b4dSbellard MIPS_SYS(sys_sethostname , 2) 2057048f6b4dSbellard MIPS_SYS(sys_setrlimit , 2) /* 4075 */ 2058048f6b4dSbellard MIPS_SYS(sys_getrlimit , 2) 2059048f6b4dSbellard MIPS_SYS(sys_getrusage , 2) 2060048f6b4dSbellard MIPS_SYS(sys_gettimeofday, 2) 2061048f6b4dSbellard MIPS_SYS(sys_settimeofday, 2) 2062048f6b4dSbellard MIPS_SYS(sys_getgroups , 2) /* 4080 */ 2063048f6b4dSbellard MIPS_SYS(sys_setgroups , 2) 2064048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* old_select */ 2065048f6b4dSbellard MIPS_SYS(sys_symlink , 2) 2066048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was sys_lstat */ 2067048f6b4dSbellard MIPS_SYS(sys_readlink , 3) /* 4085 */ 2068048f6b4dSbellard MIPS_SYS(sys_uselib , 1) 2069048f6b4dSbellard MIPS_SYS(sys_swapon , 2) 2070048f6b4dSbellard MIPS_SYS(sys_reboot , 3) 2071048f6b4dSbellard MIPS_SYS(old_readdir , 3) 2072048f6b4dSbellard MIPS_SYS(old_mmap , 6) /* 4090 */ 2073048f6b4dSbellard MIPS_SYS(sys_munmap , 2) 2074048f6b4dSbellard MIPS_SYS(sys_truncate , 2) 2075048f6b4dSbellard MIPS_SYS(sys_ftruncate , 2) 2076048f6b4dSbellard MIPS_SYS(sys_fchmod , 2) 2077048f6b4dSbellard MIPS_SYS(sys_fchown , 3) /* 4095 */ 2078048f6b4dSbellard MIPS_SYS(sys_getpriority , 2) 2079048f6b4dSbellard MIPS_SYS(sys_setpriority , 3) 2080048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 2081048f6b4dSbellard MIPS_SYS(sys_statfs , 2) 2082048f6b4dSbellard MIPS_SYS(sys_fstatfs , 2) /* 4100 */ 2083048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was ioperm(2) */ 2084048f6b4dSbellard MIPS_SYS(sys_socketcall , 2) 2085048f6b4dSbellard MIPS_SYS(sys_syslog , 3) 2086048f6b4dSbellard MIPS_SYS(sys_setitimer , 3) 2087048f6b4dSbellard MIPS_SYS(sys_getitimer , 2) /* 4105 */ 2088048f6b4dSbellard MIPS_SYS(sys_newstat , 2) 2089048f6b4dSbellard MIPS_SYS(sys_newlstat , 2) 2090048f6b4dSbellard MIPS_SYS(sys_newfstat , 2) 2091048f6b4dSbellard MIPS_SYS(sys_uname , 1) 2092048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* 4110 was iopl(2) */ 2093048f6b4dSbellard MIPS_SYS(sys_vhangup , 0) 2094048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was sys_idle() */ 2095048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was sys_vm86 */ 2096048f6b4dSbellard MIPS_SYS(sys_wait4 , 4) 2097048f6b4dSbellard MIPS_SYS(sys_swapoff , 1) /* 4115 */ 2098048f6b4dSbellard MIPS_SYS(sys_sysinfo , 1) 2099048f6b4dSbellard MIPS_SYS(sys_ipc , 6) 2100048f6b4dSbellard MIPS_SYS(sys_fsync , 1) 2101048f6b4dSbellard MIPS_SYS(sys_sigreturn , 0) 210218113962SPaul Brook MIPS_SYS(sys_clone , 6) /* 4120 */ 2103048f6b4dSbellard MIPS_SYS(sys_setdomainname, 2) 2104048f6b4dSbellard MIPS_SYS(sys_newuname , 1) 2105048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* sys_modify_ldt */ 2106048f6b4dSbellard MIPS_SYS(sys_adjtimex , 1) 2107048f6b4dSbellard MIPS_SYS(sys_mprotect , 3) /* 4125 */ 2108048f6b4dSbellard MIPS_SYS(sys_sigprocmask , 3) 2109048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was create_module */ 2110048f6b4dSbellard MIPS_SYS(sys_init_module , 5) 2111048f6b4dSbellard MIPS_SYS(sys_delete_module, 1) 2112048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* 4130 was get_kernel_syms */ 2113048f6b4dSbellard MIPS_SYS(sys_quotactl , 0) 2114048f6b4dSbellard MIPS_SYS(sys_getpgid , 1) 2115048f6b4dSbellard MIPS_SYS(sys_fchdir , 1) 2116048f6b4dSbellard MIPS_SYS(sys_bdflush , 2) 2117048f6b4dSbellard MIPS_SYS(sys_sysfs , 3) /* 4135 */ 2118048f6b4dSbellard MIPS_SYS(sys_personality , 1) 2119048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* for afs_syscall */ 2120048f6b4dSbellard MIPS_SYS(sys_setfsuid , 1) 2121048f6b4dSbellard MIPS_SYS(sys_setfsgid , 1) 2122048f6b4dSbellard MIPS_SYS(sys_llseek , 5) /* 4140 */ 2123048f6b4dSbellard MIPS_SYS(sys_getdents , 3) 2124048f6b4dSbellard MIPS_SYS(sys_select , 5) 2125048f6b4dSbellard MIPS_SYS(sys_flock , 2) 2126048f6b4dSbellard MIPS_SYS(sys_msync , 3) 2127048f6b4dSbellard MIPS_SYS(sys_readv , 3) /* 4145 */ 2128048f6b4dSbellard MIPS_SYS(sys_writev , 3) 2129048f6b4dSbellard MIPS_SYS(sys_cacheflush , 3) 2130048f6b4dSbellard MIPS_SYS(sys_cachectl , 3) 2131048f6b4dSbellard MIPS_SYS(sys_sysmips , 4) 2132048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* 4150 */ 2133048f6b4dSbellard MIPS_SYS(sys_getsid , 1) 2134048f6b4dSbellard MIPS_SYS(sys_fdatasync , 0) 2135048f6b4dSbellard MIPS_SYS(sys_sysctl , 1) 2136048f6b4dSbellard MIPS_SYS(sys_mlock , 2) 2137048f6b4dSbellard MIPS_SYS(sys_munlock , 2) /* 4155 */ 2138048f6b4dSbellard MIPS_SYS(sys_mlockall , 1) 2139048f6b4dSbellard MIPS_SYS(sys_munlockall , 0) 2140048f6b4dSbellard MIPS_SYS(sys_sched_setparam, 2) 2141048f6b4dSbellard MIPS_SYS(sys_sched_getparam, 2) 2142048f6b4dSbellard MIPS_SYS(sys_sched_setscheduler, 3) /* 4160 */ 2143048f6b4dSbellard MIPS_SYS(sys_sched_getscheduler, 1) 2144048f6b4dSbellard MIPS_SYS(sys_sched_yield , 0) 2145048f6b4dSbellard MIPS_SYS(sys_sched_get_priority_max, 1) 2146048f6b4dSbellard MIPS_SYS(sys_sched_get_priority_min, 1) 2147048f6b4dSbellard MIPS_SYS(sys_sched_rr_get_interval, 2) /* 4165 */ 2148048f6b4dSbellard MIPS_SYS(sys_nanosleep, 2) 2149b0932e06SPetar Jovanovic MIPS_SYS(sys_mremap , 5) 2150048f6b4dSbellard MIPS_SYS(sys_accept , 3) 2151048f6b4dSbellard MIPS_SYS(sys_bind , 3) 2152048f6b4dSbellard MIPS_SYS(sys_connect , 3) /* 4170 */ 2153048f6b4dSbellard MIPS_SYS(sys_getpeername , 3) 2154048f6b4dSbellard MIPS_SYS(sys_getsockname , 3) 2155048f6b4dSbellard MIPS_SYS(sys_getsockopt , 5) 2156048f6b4dSbellard MIPS_SYS(sys_listen , 2) 2157048f6b4dSbellard MIPS_SYS(sys_recv , 4) /* 4175 */ 2158048f6b4dSbellard MIPS_SYS(sys_recvfrom , 6) 2159048f6b4dSbellard MIPS_SYS(sys_recvmsg , 3) 2160048f6b4dSbellard MIPS_SYS(sys_send , 4) 2161048f6b4dSbellard MIPS_SYS(sys_sendmsg , 3) 2162048f6b4dSbellard MIPS_SYS(sys_sendto , 6) /* 4180 */ 2163048f6b4dSbellard MIPS_SYS(sys_setsockopt , 5) 2164048f6b4dSbellard MIPS_SYS(sys_shutdown , 2) 2165048f6b4dSbellard MIPS_SYS(sys_socket , 3) 2166048f6b4dSbellard MIPS_SYS(sys_socketpair , 4) 2167048f6b4dSbellard MIPS_SYS(sys_setresuid , 3) /* 4185 */ 2168048f6b4dSbellard MIPS_SYS(sys_getresuid , 3) 2169048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was sys_query_module */ 2170048f6b4dSbellard MIPS_SYS(sys_poll , 3) 2171048f6b4dSbellard MIPS_SYS(sys_nfsservctl , 3) 2172048f6b4dSbellard MIPS_SYS(sys_setresgid , 3) /* 4190 */ 2173048f6b4dSbellard MIPS_SYS(sys_getresgid , 3) 2174048f6b4dSbellard MIPS_SYS(sys_prctl , 5) 2175048f6b4dSbellard MIPS_SYS(sys_rt_sigreturn, 0) 2176048f6b4dSbellard MIPS_SYS(sys_rt_sigaction, 4) 2177048f6b4dSbellard MIPS_SYS(sys_rt_sigprocmask, 4) /* 4195 */ 2178048f6b4dSbellard MIPS_SYS(sys_rt_sigpending, 2) 2179048f6b4dSbellard MIPS_SYS(sys_rt_sigtimedwait, 4) 2180048f6b4dSbellard MIPS_SYS(sys_rt_sigqueueinfo, 3) 2181048f6b4dSbellard MIPS_SYS(sys_rt_sigsuspend, 0) 2182048f6b4dSbellard MIPS_SYS(sys_pread64 , 6) /* 4200 */ 2183048f6b4dSbellard MIPS_SYS(sys_pwrite64 , 6) 2184048f6b4dSbellard MIPS_SYS(sys_chown , 3) 2185048f6b4dSbellard MIPS_SYS(sys_getcwd , 2) 2186048f6b4dSbellard MIPS_SYS(sys_capget , 2) 2187048f6b4dSbellard MIPS_SYS(sys_capset , 2) /* 4205 */ 2188053ebb27SWesley W. Terpstra MIPS_SYS(sys_sigaltstack , 2) 2189048f6b4dSbellard MIPS_SYS(sys_sendfile , 4) 2190048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 2191048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 2192048f6b4dSbellard MIPS_SYS(sys_mmap2 , 6) /* 4210 */ 2193048f6b4dSbellard MIPS_SYS(sys_truncate64 , 4) 2194048f6b4dSbellard MIPS_SYS(sys_ftruncate64 , 4) 2195048f6b4dSbellard MIPS_SYS(sys_stat64 , 2) 2196048f6b4dSbellard MIPS_SYS(sys_lstat64 , 2) 2197048f6b4dSbellard MIPS_SYS(sys_fstat64 , 2) /* 4215 */ 2198048f6b4dSbellard MIPS_SYS(sys_pivot_root , 2) 2199048f6b4dSbellard MIPS_SYS(sys_mincore , 3) 2200048f6b4dSbellard MIPS_SYS(sys_madvise , 3) 2201048f6b4dSbellard MIPS_SYS(sys_getdents64 , 3) 2202048f6b4dSbellard MIPS_SYS(sys_fcntl64 , 3) /* 4220 */ 2203048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 2204048f6b4dSbellard MIPS_SYS(sys_gettid , 0) 2205048f6b4dSbellard MIPS_SYS(sys_readahead , 5) 2206048f6b4dSbellard MIPS_SYS(sys_setxattr , 5) 2207048f6b4dSbellard MIPS_SYS(sys_lsetxattr , 5) /* 4225 */ 2208048f6b4dSbellard MIPS_SYS(sys_fsetxattr , 5) 2209048f6b4dSbellard MIPS_SYS(sys_getxattr , 4) 2210048f6b4dSbellard MIPS_SYS(sys_lgetxattr , 4) 2211048f6b4dSbellard MIPS_SYS(sys_fgetxattr , 4) 2212048f6b4dSbellard MIPS_SYS(sys_listxattr , 3) /* 4230 */ 2213048f6b4dSbellard MIPS_SYS(sys_llistxattr , 3) 2214048f6b4dSbellard MIPS_SYS(sys_flistxattr , 3) 2215048f6b4dSbellard MIPS_SYS(sys_removexattr , 2) 2216048f6b4dSbellard MIPS_SYS(sys_lremovexattr, 2) 2217048f6b4dSbellard MIPS_SYS(sys_fremovexattr, 2) /* 4235 */ 2218048f6b4dSbellard MIPS_SYS(sys_tkill , 2) 2219048f6b4dSbellard MIPS_SYS(sys_sendfile64 , 5) 222043be1343SPetar Jovanovic MIPS_SYS(sys_futex , 6) 2221048f6b4dSbellard MIPS_SYS(sys_sched_setaffinity, 3) 2222048f6b4dSbellard MIPS_SYS(sys_sched_getaffinity, 3) /* 4240 */ 2223048f6b4dSbellard MIPS_SYS(sys_io_setup , 2) 2224048f6b4dSbellard MIPS_SYS(sys_io_destroy , 1) 2225048f6b4dSbellard MIPS_SYS(sys_io_getevents, 5) 2226048f6b4dSbellard MIPS_SYS(sys_io_submit , 3) 2227048f6b4dSbellard MIPS_SYS(sys_io_cancel , 3) /* 4245 */ 2228048f6b4dSbellard MIPS_SYS(sys_exit_group , 1) 2229048f6b4dSbellard MIPS_SYS(sys_lookup_dcookie, 3) 2230048f6b4dSbellard MIPS_SYS(sys_epoll_create, 1) 2231048f6b4dSbellard MIPS_SYS(sys_epoll_ctl , 4) 2232048f6b4dSbellard MIPS_SYS(sys_epoll_wait , 3) /* 4250 */ 2233048f6b4dSbellard MIPS_SYS(sys_remap_file_pages, 5) 2234048f6b4dSbellard MIPS_SYS(sys_set_tid_address, 1) 2235048f6b4dSbellard MIPS_SYS(sys_restart_syscall, 0) 2236048f6b4dSbellard MIPS_SYS(sys_fadvise64_64, 7) 2237048f6b4dSbellard MIPS_SYS(sys_statfs64 , 3) /* 4255 */ 2238048f6b4dSbellard MIPS_SYS(sys_fstatfs64 , 2) 2239048f6b4dSbellard MIPS_SYS(sys_timer_create, 3) 2240048f6b4dSbellard MIPS_SYS(sys_timer_settime, 4) 2241048f6b4dSbellard MIPS_SYS(sys_timer_gettime, 2) 2242048f6b4dSbellard MIPS_SYS(sys_timer_getoverrun, 1) /* 4260 */ 2243048f6b4dSbellard MIPS_SYS(sys_timer_delete, 1) 2244048f6b4dSbellard MIPS_SYS(sys_clock_settime, 2) 2245048f6b4dSbellard MIPS_SYS(sys_clock_gettime, 2) 2246048f6b4dSbellard MIPS_SYS(sys_clock_getres, 2) 2247048f6b4dSbellard MIPS_SYS(sys_clock_nanosleep, 4) /* 4265 */ 2248048f6b4dSbellard MIPS_SYS(sys_tgkill , 3) 2249048f6b4dSbellard MIPS_SYS(sys_utimes , 2) 2250048f6b4dSbellard MIPS_SYS(sys_mbind , 4) 2251048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* sys_get_mempolicy */ 2252048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* 4270 sys_set_mempolicy */ 2253048f6b4dSbellard MIPS_SYS(sys_mq_open , 4) 2254048f6b4dSbellard MIPS_SYS(sys_mq_unlink , 1) 2255048f6b4dSbellard MIPS_SYS(sys_mq_timedsend, 5) 2256048f6b4dSbellard MIPS_SYS(sys_mq_timedreceive, 5) 2257048f6b4dSbellard MIPS_SYS(sys_mq_notify , 2) /* 4275 */ 2258048f6b4dSbellard MIPS_SYS(sys_mq_getsetattr, 3) 2259048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* sys_vserver */ 2260048f6b4dSbellard MIPS_SYS(sys_waitid , 4) 2261048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* available, was setaltroot */ 2262048f6b4dSbellard MIPS_SYS(sys_add_key , 5) 2263048f6b4dSbellard MIPS_SYS(sys_request_key, 4) 2264048f6b4dSbellard MIPS_SYS(sys_keyctl , 5) 22656f5b89a0Sths MIPS_SYS(sys_set_thread_area, 1) 2266388bb21aSths MIPS_SYS(sys_inotify_init, 0) 2267388bb21aSths MIPS_SYS(sys_inotify_add_watch, 3) /* 4285 */ 2268388bb21aSths MIPS_SYS(sys_inotify_rm_watch, 2) 2269388bb21aSths MIPS_SYS(sys_migrate_pages, 4) 2270388bb21aSths MIPS_SYS(sys_openat, 4) 2271388bb21aSths MIPS_SYS(sys_mkdirat, 3) 2272388bb21aSths MIPS_SYS(sys_mknodat, 4) /* 4290 */ 2273388bb21aSths MIPS_SYS(sys_fchownat, 5) 2274388bb21aSths MIPS_SYS(sys_futimesat, 3) 2275388bb21aSths MIPS_SYS(sys_fstatat64, 4) 2276388bb21aSths MIPS_SYS(sys_unlinkat, 3) 2277388bb21aSths MIPS_SYS(sys_renameat, 4) /* 4295 */ 2278388bb21aSths MIPS_SYS(sys_linkat, 5) 2279388bb21aSths MIPS_SYS(sys_symlinkat, 3) 2280388bb21aSths MIPS_SYS(sys_readlinkat, 4) 2281388bb21aSths MIPS_SYS(sys_fchmodat, 3) 2282388bb21aSths MIPS_SYS(sys_faccessat, 3) /* 4300 */ 2283388bb21aSths MIPS_SYS(sys_pselect6, 6) 2284388bb21aSths MIPS_SYS(sys_ppoll, 5) 2285388bb21aSths MIPS_SYS(sys_unshare, 1) 2286b0932e06SPetar Jovanovic MIPS_SYS(sys_splice, 6) 2287388bb21aSths MIPS_SYS(sys_sync_file_range, 7) /* 4305 */ 2288388bb21aSths MIPS_SYS(sys_tee, 4) 2289388bb21aSths MIPS_SYS(sys_vmsplice, 4) 2290388bb21aSths MIPS_SYS(sys_move_pages, 6) 2291388bb21aSths MIPS_SYS(sys_set_robust_list, 2) 2292388bb21aSths MIPS_SYS(sys_get_robust_list, 3) /* 4310 */ 2293388bb21aSths MIPS_SYS(sys_kexec_load, 4) 2294388bb21aSths MIPS_SYS(sys_getcpu, 3) 2295388bb21aSths MIPS_SYS(sys_epoll_pwait, 6) 2296388bb21aSths MIPS_SYS(sys_ioprio_set, 3) 2297388bb21aSths MIPS_SYS(sys_ioprio_get, 2) 2298d979e8ebSPeter Maydell MIPS_SYS(sys_utimensat, 4) 2299d979e8ebSPeter Maydell MIPS_SYS(sys_signalfd, 3) 2300d979e8ebSPeter Maydell MIPS_SYS(sys_ni_syscall, 0) /* was timerfd */ 2301d979e8ebSPeter Maydell MIPS_SYS(sys_eventfd, 1) 2302d979e8ebSPeter Maydell MIPS_SYS(sys_fallocate, 6) /* 4320 */ 2303d979e8ebSPeter Maydell MIPS_SYS(sys_timerfd_create, 2) 2304d979e8ebSPeter Maydell MIPS_SYS(sys_timerfd_gettime, 2) 2305d979e8ebSPeter Maydell MIPS_SYS(sys_timerfd_settime, 4) 2306d979e8ebSPeter Maydell MIPS_SYS(sys_signalfd4, 4) 2307d979e8ebSPeter Maydell MIPS_SYS(sys_eventfd2, 2) /* 4325 */ 2308d979e8ebSPeter Maydell MIPS_SYS(sys_epoll_create1, 1) 2309d979e8ebSPeter Maydell MIPS_SYS(sys_dup3, 3) 2310d979e8ebSPeter Maydell MIPS_SYS(sys_pipe2, 2) 2311d979e8ebSPeter Maydell MIPS_SYS(sys_inotify_init1, 1) 2312d979e8ebSPeter Maydell MIPS_SYS(sys_preadv, 6) /* 4330 */ 2313d979e8ebSPeter Maydell MIPS_SYS(sys_pwritev, 6) 2314d979e8ebSPeter Maydell MIPS_SYS(sys_rt_tgsigqueueinfo, 4) 2315d979e8ebSPeter Maydell MIPS_SYS(sys_perf_event_open, 5) 2316d979e8ebSPeter Maydell MIPS_SYS(sys_accept4, 4) 2317d979e8ebSPeter Maydell MIPS_SYS(sys_recvmmsg, 5) /* 4335 */ 2318d979e8ebSPeter Maydell MIPS_SYS(sys_fanotify_init, 2) 2319d979e8ebSPeter Maydell MIPS_SYS(sys_fanotify_mark, 6) 2320d979e8ebSPeter Maydell MIPS_SYS(sys_prlimit64, 4) 2321d979e8ebSPeter Maydell MIPS_SYS(sys_name_to_handle_at, 5) 2322d979e8ebSPeter Maydell MIPS_SYS(sys_open_by_handle_at, 3) /* 4340 */ 2323d979e8ebSPeter Maydell MIPS_SYS(sys_clock_adjtime, 2) 2324d979e8ebSPeter Maydell MIPS_SYS(sys_syncfs, 1) 2325048f6b4dSbellard }; 2326048f6b4dSbellard # undef MIPS_SYS 2327ff4f7382SRichard Henderson # endif /* O32 */ 2328048f6b4dSbellard 2329590bc601SPaul Brook static int do_store_exclusive(CPUMIPSState *env) 2330590bc601SPaul Brook { 2331590bc601SPaul Brook target_ulong addr; 2332590bc601SPaul Brook target_ulong page_addr; 2333590bc601SPaul Brook target_ulong val; 2334590bc601SPaul Brook int flags; 2335590bc601SPaul Brook int segv = 0; 2336590bc601SPaul Brook int reg; 2337590bc601SPaul Brook int d; 2338590bc601SPaul Brook 23395499b6ffSAurelien Jarno addr = env->lladdr; 2340590bc601SPaul Brook page_addr = addr & TARGET_PAGE_MASK; 2341590bc601SPaul Brook start_exclusive(); 2342590bc601SPaul Brook mmap_lock(); 2343590bc601SPaul Brook flags = page_get_flags(page_addr); 2344590bc601SPaul Brook if ((flags & PAGE_READ) == 0) { 2345590bc601SPaul Brook segv = 1; 2346590bc601SPaul Brook } else { 2347590bc601SPaul Brook reg = env->llreg & 0x1f; 2348590bc601SPaul Brook d = (env->llreg & 0x20) != 0; 2349590bc601SPaul Brook if (d) { 2350590bc601SPaul Brook segv = get_user_s64(val, addr); 2351590bc601SPaul Brook } else { 2352590bc601SPaul Brook segv = get_user_s32(val, addr); 2353590bc601SPaul Brook } 2354590bc601SPaul Brook if (!segv) { 2355590bc601SPaul Brook if (val != env->llval) { 2356590bc601SPaul Brook env->active_tc.gpr[reg] = 0; 2357590bc601SPaul Brook } else { 2358590bc601SPaul Brook if (d) { 2359590bc601SPaul Brook segv = put_user_u64(env->llnewval, addr); 2360590bc601SPaul Brook } else { 2361590bc601SPaul Brook segv = put_user_u32(env->llnewval, addr); 2362590bc601SPaul Brook } 2363590bc601SPaul Brook if (!segv) { 2364590bc601SPaul Brook env->active_tc.gpr[reg] = 1; 2365590bc601SPaul Brook } 2366590bc601SPaul Brook } 2367590bc601SPaul Brook } 2368590bc601SPaul Brook } 23695499b6ffSAurelien Jarno env->lladdr = -1; 2370590bc601SPaul Brook if (!segv) { 2371590bc601SPaul Brook env->active_tc.PC += 4; 2372590bc601SPaul Brook } 2373590bc601SPaul Brook mmap_unlock(); 2374590bc601SPaul Brook end_exclusive(); 2375590bc601SPaul Brook return segv; 2376590bc601SPaul Brook } 2377590bc601SPaul Brook 237854b2f42cSMeador Inge /* Break codes */ 237954b2f42cSMeador Inge enum { 238054b2f42cSMeador Inge BRK_OVERFLOW = 6, 238154b2f42cSMeador Inge BRK_DIVZERO = 7 238254b2f42cSMeador Inge }; 238354b2f42cSMeador Inge 238454b2f42cSMeador Inge static int do_break(CPUMIPSState *env, target_siginfo_t *info, 238554b2f42cSMeador Inge unsigned int code) 238654b2f42cSMeador Inge { 238754b2f42cSMeador Inge int ret = -1; 238854b2f42cSMeador Inge 238954b2f42cSMeador Inge switch (code) { 239054b2f42cSMeador Inge case BRK_OVERFLOW: 239154b2f42cSMeador Inge case BRK_DIVZERO: 239254b2f42cSMeador Inge info->si_signo = TARGET_SIGFPE; 239354b2f42cSMeador Inge info->si_errno = 0; 239454b2f42cSMeador Inge info->si_code = (code == BRK_OVERFLOW) ? FPE_INTOVF : FPE_INTDIV; 239554b2f42cSMeador Inge queue_signal(env, info->si_signo, &*info); 239654b2f42cSMeador Inge ret = 0; 239754b2f42cSMeador Inge break; 239854b2f42cSMeador Inge default: 2399b51910baSPetar Jovanovic info->si_signo = TARGET_SIGTRAP; 2400b51910baSPetar Jovanovic info->si_errno = 0; 2401b51910baSPetar Jovanovic queue_signal(env, info->si_signo, &*info); 2402b51910baSPetar Jovanovic ret = 0; 240354b2f42cSMeador Inge break; 240454b2f42cSMeador Inge } 240554b2f42cSMeador Inge 240654b2f42cSMeador Inge return ret; 240754b2f42cSMeador Inge } 240854b2f42cSMeador Inge 2409048f6b4dSbellard void cpu_loop(CPUMIPSState *env) 2410048f6b4dSbellard { 24110315c31cSAndreas Färber CPUState *cs = CPU(mips_env_get_cpu(env)); 2412c227f099SAnthony Liguori target_siginfo_t info; 2413ff4f7382SRichard Henderson int trapnr; 2414ff4f7382SRichard Henderson abi_long ret; 2415ff4f7382SRichard Henderson # ifdef TARGET_ABI_MIPSO32 2416048f6b4dSbellard unsigned int syscall_num; 2417ff4f7382SRichard Henderson # endif 2418048f6b4dSbellard 2419048f6b4dSbellard for(;;) { 24200315c31cSAndreas Färber cpu_exec_start(cs); 2421ea3e9847SPeter Crosthwaite trapnr = cpu_mips_exec(cs); 24220315c31cSAndreas Färber cpu_exec_end(cs); 2423048f6b4dSbellard switch(trapnr) { 2424048f6b4dSbellard case EXCP_SYSCALL: 2425b5dc7732Sths env->active_tc.PC += 4; 2426ff4f7382SRichard Henderson # ifdef TARGET_ABI_MIPSO32 2427ff4f7382SRichard Henderson syscall_num = env->active_tc.gpr[2] - 4000; 2428048f6b4dSbellard if (syscall_num >= sizeof(mips_syscall_args)) { 24297c2f6157SWesley W. Terpstra ret = -TARGET_ENOSYS; 2430048f6b4dSbellard } else { 2431388bb21aSths int nb_args; 2432992f48a0Sblueswir1 abi_ulong sp_reg; 2433992f48a0Sblueswir1 abi_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0; 2434388bb21aSths 2435048f6b4dSbellard nb_args = mips_syscall_args[syscall_num]; 2436b5dc7732Sths sp_reg = env->active_tc.gpr[29]; 2437388bb21aSths switch (nb_args) { 2438048f6b4dSbellard /* these arguments are taken from the stack */ 243994c19610SAn-Cheng Huang case 8: 244094c19610SAn-Cheng Huang if ((ret = get_user_ual(arg8, sp_reg + 28)) != 0) { 244194c19610SAn-Cheng Huang goto done_syscall; 244294c19610SAn-Cheng Huang } 244394c19610SAn-Cheng Huang case 7: 244494c19610SAn-Cheng Huang if ((ret = get_user_ual(arg7, sp_reg + 24)) != 0) { 244594c19610SAn-Cheng Huang goto done_syscall; 244694c19610SAn-Cheng Huang } 244794c19610SAn-Cheng Huang case 6: 244894c19610SAn-Cheng Huang if ((ret = get_user_ual(arg6, sp_reg + 20)) != 0) { 244994c19610SAn-Cheng Huang goto done_syscall; 245094c19610SAn-Cheng Huang } 245194c19610SAn-Cheng Huang case 5: 245294c19610SAn-Cheng Huang if ((ret = get_user_ual(arg5, sp_reg + 16)) != 0) { 245394c19610SAn-Cheng Huang goto done_syscall; 245494c19610SAn-Cheng Huang } 2455388bb21aSths default: 2456388bb21aSths break; 2457048f6b4dSbellard } 2458b5dc7732Sths ret = do_syscall(env, env->active_tc.gpr[2], 2459b5dc7732Sths env->active_tc.gpr[4], 2460b5dc7732Sths env->active_tc.gpr[5], 2461b5dc7732Sths env->active_tc.gpr[6], 2462b5dc7732Sths env->active_tc.gpr[7], 24635945cfcbSPeter Maydell arg5, arg6, arg7, arg8); 2464048f6b4dSbellard } 246594c19610SAn-Cheng Huang done_syscall: 2466ff4f7382SRichard Henderson # else 2467ff4f7382SRichard Henderson ret = do_syscall(env, env->active_tc.gpr[2], 2468ff4f7382SRichard Henderson env->active_tc.gpr[4], env->active_tc.gpr[5], 2469ff4f7382SRichard Henderson env->active_tc.gpr[6], env->active_tc.gpr[7], 2470ff4f7382SRichard Henderson env->active_tc.gpr[8], env->active_tc.gpr[9], 2471ff4f7382SRichard Henderson env->active_tc.gpr[10], env->active_tc.gpr[11]); 2472ff4f7382SRichard Henderson # endif /* O32 */ 24730b1bcb00Spbrook if (ret == -TARGET_QEMU_ESIGRETURN) { 24740b1bcb00Spbrook /* Returning from a successful sigreturn syscall. 24750b1bcb00Spbrook Avoid clobbering register state. */ 24760b1bcb00Spbrook break; 24770b1bcb00Spbrook } 2478ff4f7382SRichard Henderson if ((abi_ulong)ret >= (abi_ulong)-1133) { 2479b5dc7732Sths env->active_tc.gpr[7] = 1; /* error flag */ 2480048f6b4dSbellard ret = -ret; 2481048f6b4dSbellard } else { 2482b5dc7732Sths env->active_tc.gpr[7] = 0; /* error flag */ 2483388bb21aSths } 2484b5dc7732Sths env->active_tc.gpr[2] = ret; 2485048f6b4dSbellard break; 2486ca7c2b1bSths case EXCP_TLBL: 2487ca7c2b1bSths case EXCP_TLBS: 2488e6e5bd2dSWesley W. Terpstra case EXCP_AdEL: 2489e6e5bd2dSWesley W. Terpstra case EXCP_AdES: 2490e4474235Spbrook info.si_signo = TARGET_SIGSEGV; 2491e4474235Spbrook info.si_errno = 0; 2492e4474235Spbrook /* XXX: check env->error_code */ 2493e4474235Spbrook info.si_code = TARGET_SEGV_MAPERR; 2494e4474235Spbrook info._sifields._sigfault._addr = env->CP0_BadVAddr; 2495e4474235Spbrook queue_signal(env, info.si_signo, &info); 2496e4474235Spbrook break; 24976900e84bSbellard case EXCP_CpU: 2498048f6b4dSbellard case EXCP_RI: 2499048f6b4dSbellard info.si_signo = TARGET_SIGILL; 2500048f6b4dSbellard info.si_errno = 0; 2501048f6b4dSbellard info.si_code = 0; 2502624f7979Spbrook queue_signal(env, info.si_signo, &info); 2503048f6b4dSbellard break; 2504106ec879Sbellard case EXCP_INTERRUPT: 2505106ec879Sbellard /* just indicate that signals should be handled asap */ 2506106ec879Sbellard break; 2507d08b2a28Spbrook case EXCP_DEBUG: 2508d08b2a28Spbrook { 2509d08b2a28Spbrook int sig; 2510d08b2a28Spbrook 2511db6b81d4SAndreas Färber sig = gdb_handlesig(cs, TARGET_SIGTRAP); 2512d08b2a28Spbrook if (sig) 2513d08b2a28Spbrook { 2514d08b2a28Spbrook info.si_signo = sig; 2515d08b2a28Spbrook info.si_errno = 0; 2516d08b2a28Spbrook info.si_code = TARGET_TRAP_BRKPT; 2517624f7979Spbrook queue_signal(env, info.si_signo, &info); 2518d08b2a28Spbrook } 2519d08b2a28Spbrook } 2520d08b2a28Spbrook break; 2521590bc601SPaul Brook case EXCP_SC: 2522590bc601SPaul Brook if (do_store_exclusive(env)) { 2523590bc601SPaul Brook info.si_signo = TARGET_SIGSEGV; 2524590bc601SPaul Brook info.si_errno = 0; 2525590bc601SPaul Brook info.si_code = TARGET_SEGV_MAPERR; 2526590bc601SPaul Brook info._sifields._sigfault._addr = env->active_tc.PC; 2527590bc601SPaul Brook queue_signal(env, info.si_signo, &info); 2528590bc601SPaul Brook } 2529590bc601SPaul Brook break; 2530853c3240SJia Liu case EXCP_DSPDIS: 2531853c3240SJia Liu info.si_signo = TARGET_SIGILL; 2532853c3240SJia Liu info.si_errno = 0; 2533853c3240SJia Liu info.si_code = TARGET_ILL_ILLOPC; 2534853c3240SJia Liu queue_signal(env, info.si_signo, &info); 2535853c3240SJia Liu break; 253654b2f42cSMeador Inge /* The code below was inspired by the MIPS Linux kernel trap 253754b2f42cSMeador Inge * handling code in arch/mips/kernel/traps.c. 253854b2f42cSMeador Inge */ 253954b2f42cSMeador Inge case EXCP_BREAK: 254054b2f42cSMeador Inge { 254154b2f42cSMeador Inge abi_ulong trap_instr; 254254b2f42cSMeador Inge unsigned int code; 254354b2f42cSMeador Inge 2544a0333817SKwok Cheung Yeung if (env->hflags & MIPS_HFLAG_M16) { 2545a0333817SKwok Cheung Yeung if (env->insn_flags & ASE_MICROMIPS) { 2546a0333817SKwok Cheung Yeung /* microMIPS mode */ 25471308c464SKwok Cheung Yeung ret = get_user_u16(trap_instr, env->active_tc.PC); 25481308c464SKwok Cheung Yeung if (ret != 0) { 25491308c464SKwok Cheung Yeung goto error; 25501308c464SKwok Cheung Yeung } 2551a0333817SKwok Cheung Yeung 25521308c464SKwok Cheung Yeung if ((trap_instr >> 10) == 0x11) { 25531308c464SKwok Cheung Yeung /* 16-bit instruction */ 25541308c464SKwok Cheung Yeung code = trap_instr & 0xf; 25551308c464SKwok Cheung Yeung } else { 25561308c464SKwok Cheung Yeung /* 32-bit instruction */ 25571308c464SKwok Cheung Yeung abi_ulong instr_lo; 2558a0333817SKwok Cheung Yeung 25591308c464SKwok Cheung Yeung ret = get_user_u16(instr_lo, 25601308c464SKwok Cheung Yeung env->active_tc.PC + 2); 25611308c464SKwok Cheung Yeung if (ret != 0) { 25621308c464SKwok Cheung Yeung goto error; 25631308c464SKwok Cheung Yeung } 25641308c464SKwok Cheung Yeung trap_instr = (trap_instr << 16) | instr_lo; 25651308c464SKwok Cheung Yeung code = ((trap_instr >> 6) & ((1 << 20) - 1)); 25661308c464SKwok Cheung Yeung /* Unfortunately, microMIPS also suffers from 25671308c464SKwok Cheung Yeung the old assembler bug... */ 25681308c464SKwok Cheung Yeung if (code >= (1 << 10)) { 25691308c464SKwok Cheung Yeung code >>= 10; 25701308c464SKwok Cheung Yeung } 25711308c464SKwok Cheung Yeung } 2572a0333817SKwok Cheung Yeung } else { 2573a0333817SKwok Cheung Yeung /* MIPS16e mode */ 2574a0333817SKwok Cheung Yeung ret = get_user_u16(trap_instr, env->active_tc.PC); 2575a0333817SKwok Cheung Yeung if (ret != 0) { 2576a0333817SKwok Cheung Yeung goto error; 2577a0333817SKwok Cheung Yeung } 2578a0333817SKwok Cheung Yeung code = (trap_instr >> 6) & 0x3f; 2579a0333817SKwok Cheung Yeung } 2580a0333817SKwok Cheung Yeung } else { 2581f01a361bSAndrew Bennett ret = get_user_u32(trap_instr, env->active_tc.PC); 258254b2f42cSMeador Inge if (ret != 0) { 258354b2f42cSMeador Inge goto error; 258454b2f42cSMeador Inge } 258554b2f42cSMeador Inge 258654b2f42cSMeador Inge /* As described in the original Linux kernel code, the 258754b2f42cSMeador Inge * below checks on 'code' are to work around an old 258854b2f42cSMeador Inge * assembly bug. 258954b2f42cSMeador Inge */ 259054b2f42cSMeador Inge code = ((trap_instr >> 6) & ((1 << 20) - 1)); 259154b2f42cSMeador Inge if (code >= (1 << 10)) { 259254b2f42cSMeador Inge code >>= 10; 259354b2f42cSMeador Inge } 25941308c464SKwok Cheung Yeung } 259554b2f42cSMeador Inge 259654b2f42cSMeador Inge if (do_break(env, &info, code) != 0) { 259754b2f42cSMeador Inge goto error; 259854b2f42cSMeador Inge } 259954b2f42cSMeador Inge } 260054b2f42cSMeador Inge break; 260154b2f42cSMeador Inge case EXCP_TRAP: 260254b2f42cSMeador Inge { 260354b2f42cSMeador Inge abi_ulong trap_instr; 260454b2f42cSMeador Inge unsigned int code = 0; 260554b2f42cSMeador Inge 2606a0333817SKwok Cheung Yeung if (env->hflags & MIPS_HFLAG_M16) { 2607a0333817SKwok Cheung Yeung /* microMIPS mode */ 2608a0333817SKwok Cheung Yeung abi_ulong instr[2]; 2609a0333817SKwok Cheung Yeung 2610a0333817SKwok Cheung Yeung ret = get_user_u16(instr[0], env->active_tc.PC) || 2611a0333817SKwok Cheung Yeung get_user_u16(instr[1], env->active_tc.PC + 2); 2612a0333817SKwok Cheung Yeung 2613a0333817SKwok Cheung Yeung trap_instr = (instr[0] << 16) | instr[1]; 2614a0333817SKwok Cheung Yeung } else { 2615f01a361bSAndrew Bennett ret = get_user_u32(trap_instr, env->active_tc.PC); 2616a0333817SKwok Cheung Yeung } 2617a0333817SKwok Cheung Yeung 261854b2f42cSMeador Inge if (ret != 0) { 261954b2f42cSMeador Inge goto error; 262054b2f42cSMeador Inge } 262154b2f42cSMeador Inge 262254b2f42cSMeador Inge /* The immediate versions don't provide a code. */ 262354b2f42cSMeador Inge if (!(trap_instr & 0xFC000000)) { 2624a0333817SKwok Cheung Yeung if (env->hflags & MIPS_HFLAG_M16) { 2625a0333817SKwok Cheung Yeung /* microMIPS mode */ 2626a0333817SKwok Cheung Yeung code = ((trap_instr >> 12) & ((1 << 4) - 1)); 2627a0333817SKwok Cheung Yeung } else { 262854b2f42cSMeador Inge code = ((trap_instr >> 6) & ((1 << 10) - 1)); 262954b2f42cSMeador Inge } 2630a0333817SKwok Cheung Yeung } 263154b2f42cSMeador Inge 263254b2f42cSMeador Inge if (do_break(env, &info, code) != 0) { 263354b2f42cSMeador Inge goto error; 263454b2f42cSMeador Inge } 263554b2f42cSMeador Inge } 263654b2f42cSMeador Inge break; 2637048f6b4dSbellard default: 263854b2f42cSMeador Inge error: 2639048f6b4dSbellard fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", 2640048f6b4dSbellard trapnr); 2641878096eeSAndreas Färber cpu_dump_state(cs, stderr, fprintf, 0); 2642048f6b4dSbellard abort(); 2643048f6b4dSbellard } 2644048f6b4dSbellard process_pending_signals(env); 2645048f6b4dSbellard } 2646048f6b4dSbellard } 2647048f6b4dSbellard #endif 2648048f6b4dSbellard 2649d962783eSJia Liu #ifdef TARGET_OPENRISC 2650d962783eSJia Liu 2651d962783eSJia Liu void cpu_loop(CPUOpenRISCState *env) 2652d962783eSJia Liu { 2653878096eeSAndreas Färber CPUState *cs = CPU(openrisc_env_get_cpu(env)); 2654d962783eSJia Liu int trapnr, gdbsig; 2655d962783eSJia Liu 2656d962783eSJia Liu for (;;) { 2657b040bc9cSPeter Maydell cpu_exec_start(cs); 2658ea3e9847SPeter Crosthwaite trapnr = cpu_openrisc_exec(cs); 2659b040bc9cSPeter Maydell cpu_exec_end(cs); 2660d962783eSJia Liu gdbsig = 0; 2661d962783eSJia Liu 2662d962783eSJia Liu switch (trapnr) { 2663d962783eSJia Liu case EXCP_RESET: 2664d962783eSJia Liu qemu_log("\nReset request, exit, pc is %#x\n", env->pc); 26654d1275c2SRiku Voipio exit(EXIT_FAILURE); 2666d962783eSJia Liu break; 2667d962783eSJia Liu case EXCP_BUSERR: 2668d962783eSJia Liu qemu_log("\nBus error, exit, pc is %#x\n", env->pc); 2669a86b3c64SChen Gang S gdbsig = TARGET_SIGBUS; 2670d962783eSJia Liu break; 2671d962783eSJia Liu case EXCP_DPF: 2672d962783eSJia Liu case EXCP_IPF: 2673878096eeSAndreas Färber cpu_dump_state(cs, stderr, fprintf, 0); 2674d962783eSJia Liu gdbsig = TARGET_SIGSEGV; 2675d962783eSJia Liu break; 2676d962783eSJia Liu case EXCP_TICK: 2677d962783eSJia Liu qemu_log("\nTick time interrupt pc is %#x\n", env->pc); 2678d962783eSJia Liu break; 2679d962783eSJia Liu case EXCP_ALIGN: 2680d962783eSJia Liu qemu_log("\nAlignment pc is %#x\n", env->pc); 2681a86b3c64SChen Gang S gdbsig = TARGET_SIGBUS; 2682d962783eSJia Liu break; 2683d962783eSJia Liu case EXCP_ILLEGAL: 2684d962783eSJia Liu qemu_log("\nIllegal instructionpc is %#x\n", env->pc); 2685a86b3c64SChen Gang S gdbsig = TARGET_SIGILL; 2686d962783eSJia Liu break; 2687d962783eSJia Liu case EXCP_INT: 2688d962783eSJia Liu qemu_log("\nExternal interruptpc is %#x\n", env->pc); 2689d962783eSJia Liu break; 2690d962783eSJia Liu case EXCP_DTLBMISS: 2691d962783eSJia Liu case EXCP_ITLBMISS: 2692d962783eSJia Liu qemu_log("\nTLB miss\n"); 2693d962783eSJia Liu break; 2694d962783eSJia Liu case EXCP_RANGE: 2695d962783eSJia Liu qemu_log("\nRange\n"); 2696a86b3c64SChen Gang S gdbsig = TARGET_SIGSEGV; 2697d962783eSJia Liu break; 2698d962783eSJia Liu case EXCP_SYSCALL: 2699d962783eSJia Liu env->pc += 4; /* 0xc00; */ 2700d962783eSJia Liu env->gpr[11] = do_syscall(env, 2701d962783eSJia Liu env->gpr[11], /* return value */ 2702d962783eSJia Liu env->gpr[3], /* r3 - r7 are params */ 2703d962783eSJia Liu env->gpr[4], 2704d962783eSJia Liu env->gpr[5], 2705d962783eSJia Liu env->gpr[6], 2706d962783eSJia Liu env->gpr[7], 2707d962783eSJia Liu env->gpr[8], 0, 0); 2708d962783eSJia Liu break; 2709d962783eSJia Liu case EXCP_FPE: 2710d962783eSJia Liu qemu_log("\nFloating point error\n"); 2711d962783eSJia Liu break; 2712d962783eSJia Liu case EXCP_TRAP: 2713d962783eSJia Liu qemu_log("\nTrap\n"); 2714a86b3c64SChen Gang S gdbsig = TARGET_SIGTRAP; 2715d962783eSJia Liu break; 2716d962783eSJia Liu case EXCP_NR: 2717d962783eSJia Liu qemu_log("\nNR\n"); 2718d962783eSJia Liu break; 2719d962783eSJia Liu default: 2720d962783eSJia Liu qemu_log("\nqemu: unhandled CPU exception %#x - aborting\n", 2721d962783eSJia Liu trapnr); 2722878096eeSAndreas Färber cpu_dump_state(cs, stderr, fprintf, 0); 2723d962783eSJia Liu gdbsig = TARGET_SIGILL; 2724d962783eSJia Liu break; 2725d962783eSJia Liu } 2726d962783eSJia Liu if (gdbsig) { 2727db6b81d4SAndreas Färber gdb_handlesig(cs, gdbsig); 2728d962783eSJia Liu if (gdbsig != TARGET_SIGTRAP) { 27294d1275c2SRiku Voipio exit(EXIT_FAILURE); 2730d962783eSJia Liu } 2731d962783eSJia Liu } 2732d962783eSJia Liu 2733d962783eSJia Liu process_pending_signals(env); 2734d962783eSJia Liu } 2735d962783eSJia Liu } 2736d962783eSJia Liu 2737d962783eSJia Liu #endif /* TARGET_OPENRISC */ 2738d962783eSJia Liu 2739fdf9b3e8Sbellard #ifdef TARGET_SH4 274005390248SAndreas Färber void cpu_loop(CPUSH4State *env) 2741fdf9b3e8Sbellard { 2742878096eeSAndreas Färber CPUState *cs = CPU(sh_env_get_cpu(env)); 2743fdf9b3e8Sbellard int trapnr, ret; 2744c227f099SAnthony Liguori target_siginfo_t info; 2745fdf9b3e8Sbellard 2746fdf9b3e8Sbellard while (1) { 2747b040bc9cSPeter Maydell cpu_exec_start(cs); 2748ea3e9847SPeter Crosthwaite trapnr = cpu_sh4_exec(cs); 2749b040bc9cSPeter Maydell cpu_exec_end(cs); 2750fdf9b3e8Sbellard 2751fdf9b3e8Sbellard switch (trapnr) { 2752fdf9b3e8Sbellard case 0x160: 27530b6d3ae0Saurel32 env->pc += 2; 2754fdf9b3e8Sbellard ret = do_syscall(env, 27559c2a9ea1Spbrook env->gregs[3], 27569c2a9ea1Spbrook env->gregs[4], 27579c2a9ea1Spbrook env->gregs[5], 27589c2a9ea1Spbrook env->gregs[6], 27599c2a9ea1Spbrook env->gregs[7], 27609c2a9ea1Spbrook env->gregs[0], 27615945cfcbSPeter Maydell env->gregs[1], 27625945cfcbSPeter Maydell 0, 0); 27639c2a9ea1Spbrook env->gregs[0] = ret; 2764fdf9b3e8Sbellard break; 2765c3b5bc8aSths case EXCP_INTERRUPT: 2766c3b5bc8aSths /* just indicate that signals should be handled asap */ 2767c3b5bc8aSths break; 2768355fb23dSpbrook case EXCP_DEBUG: 2769355fb23dSpbrook { 2770355fb23dSpbrook int sig; 2771355fb23dSpbrook 2772db6b81d4SAndreas Färber sig = gdb_handlesig(cs, TARGET_SIGTRAP); 2773355fb23dSpbrook if (sig) 2774355fb23dSpbrook { 2775355fb23dSpbrook info.si_signo = sig; 2776355fb23dSpbrook info.si_errno = 0; 2777355fb23dSpbrook info.si_code = TARGET_TRAP_BRKPT; 2778624f7979Spbrook queue_signal(env, info.si_signo, &info); 2779355fb23dSpbrook } 2780355fb23dSpbrook } 2781355fb23dSpbrook break; 2782c3b5bc8aSths case 0xa0: 2783c3b5bc8aSths case 0xc0: 2784a86b3c64SChen Gang S info.si_signo = TARGET_SIGSEGV; 2785c3b5bc8aSths info.si_errno = 0; 2786c3b5bc8aSths info.si_code = TARGET_SEGV_MAPERR; 2787c3b5bc8aSths info._sifields._sigfault._addr = env->tea; 2788624f7979Spbrook queue_signal(env, info.si_signo, &info); 2789c3b5bc8aSths break; 2790c3b5bc8aSths 2791fdf9b3e8Sbellard default: 2792fdf9b3e8Sbellard printf ("Unhandled trap: 0x%x\n", trapnr); 2793878096eeSAndreas Färber cpu_dump_state(cs, stderr, fprintf, 0); 27944d1275c2SRiku Voipio exit(EXIT_FAILURE); 2795fdf9b3e8Sbellard } 2796fdf9b3e8Sbellard process_pending_signals (env); 2797fdf9b3e8Sbellard } 2798fdf9b3e8Sbellard } 2799fdf9b3e8Sbellard #endif 2800fdf9b3e8Sbellard 280148733d19Sths #ifdef TARGET_CRIS 280205390248SAndreas Färber void cpu_loop(CPUCRISState *env) 280348733d19Sths { 2804878096eeSAndreas Färber CPUState *cs = CPU(cris_env_get_cpu(env)); 280548733d19Sths int trapnr, ret; 2806c227f099SAnthony Liguori target_siginfo_t info; 280748733d19Sths 280848733d19Sths while (1) { 2809b040bc9cSPeter Maydell cpu_exec_start(cs); 2810ea3e9847SPeter Crosthwaite trapnr = cpu_cris_exec(cs); 2811b040bc9cSPeter Maydell cpu_exec_end(cs); 281248733d19Sths switch (trapnr) { 281348733d19Sths case 0xaa: 281448733d19Sths { 2815a86b3c64SChen Gang S info.si_signo = TARGET_SIGSEGV; 281648733d19Sths info.si_errno = 0; 281748733d19Sths /* XXX: check env->error_code */ 281848733d19Sths info.si_code = TARGET_SEGV_MAPERR; 2819e00c1e71Sedgar_igl info._sifields._sigfault._addr = env->pregs[PR_EDA]; 2820624f7979Spbrook queue_signal(env, info.si_signo, &info); 282148733d19Sths } 282248733d19Sths break; 2823b6d3abdaSedgar_igl case EXCP_INTERRUPT: 2824b6d3abdaSedgar_igl /* just indicate that signals should be handled asap */ 2825b6d3abdaSedgar_igl break; 282648733d19Sths case EXCP_BREAK: 282748733d19Sths ret = do_syscall(env, 282848733d19Sths env->regs[9], 282948733d19Sths env->regs[10], 283048733d19Sths env->regs[11], 283148733d19Sths env->regs[12], 283248733d19Sths env->regs[13], 283348733d19Sths env->pregs[7], 28345945cfcbSPeter Maydell env->pregs[11], 28355945cfcbSPeter Maydell 0, 0); 283648733d19Sths env->regs[10] = ret; 283748733d19Sths break; 283848733d19Sths case EXCP_DEBUG: 283948733d19Sths { 284048733d19Sths int sig; 284148733d19Sths 2842db6b81d4SAndreas Färber sig = gdb_handlesig(cs, TARGET_SIGTRAP); 284348733d19Sths if (sig) 284448733d19Sths { 284548733d19Sths info.si_signo = sig; 284648733d19Sths info.si_errno = 0; 284748733d19Sths info.si_code = TARGET_TRAP_BRKPT; 2848624f7979Spbrook queue_signal(env, info.si_signo, &info); 284948733d19Sths } 285048733d19Sths } 285148733d19Sths break; 285248733d19Sths default: 285348733d19Sths printf ("Unhandled trap: 0x%x\n", trapnr); 2854878096eeSAndreas Färber cpu_dump_state(cs, stderr, fprintf, 0); 28554d1275c2SRiku Voipio exit(EXIT_FAILURE); 285648733d19Sths } 285748733d19Sths process_pending_signals (env); 285848733d19Sths } 285948733d19Sths } 286048733d19Sths #endif 286148733d19Sths 2862b779e29eSEdgar E. Iglesias #ifdef TARGET_MICROBLAZE 286305390248SAndreas Färber void cpu_loop(CPUMBState *env) 2864b779e29eSEdgar E. Iglesias { 2865878096eeSAndreas Färber CPUState *cs = CPU(mb_env_get_cpu(env)); 2866b779e29eSEdgar E. Iglesias int trapnr, ret; 2867c227f099SAnthony Liguori target_siginfo_t info; 2868b779e29eSEdgar E. Iglesias 2869b779e29eSEdgar E. Iglesias while (1) { 2870b040bc9cSPeter Maydell cpu_exec_start(cs); 2871ea3e9847SPeter Crosthwaite trapnr = cpu_mb_exec(cs); 2872b040bc9cSPeter Maydell cpu_exec_end(cs); 2873b779e29eSEdgar E. Iglesias switch (trapnr) { 2874b779e29eSEdgar E. Iglesias case 0xaa: 2875b779e29eSEdgar E. Iglesias { 2876a86b3c64SChen Gang S info.si_signo = TARGET_SIGSEGV; 2877b779e29eSEdgar E. Iglesias info.si_errno = 0; 2878b779e29eSEdgar E. Iglesias /* XXX: check env->error_code */ 2879b779e29eSEdgar E. Iglesias info.si_code = TARGET_SEGV_MAPERR; 2880b779e29eSEdgar E. Iglesias info._sifields._sigfault._addr = 0; 2881b779e29eSEdgar E. Iglesias queue_signal(env, info.si_signo, &info); 2882b779e29eSEdgar E. Iglesias } 2883b779e29eSEdgar E. Iglesias break; 2884b779e29eSEdgar E. Iglesias case EXCP_INTERRUPT: 2885b779e29eSEdgar E. Iglesias /* just indicate that signals should be handled asap */ 2886b779e29eSEdgar E. Iglesias break; 2887b779e29eSEdgar E. Iglesias case EXCP_BREAK: 2888b779e29eSEdgar E. Iglesias /* Return address is 4 bytes after the call. */ 2889b779e29eSEdgar E. Iglesias env->regs[14] += 4; 2890d7dce494SEdgar E. Iglesias env->sregs[SR_PC] = env->regs[14]; 2891b779e29eSEdgar E. Iglesias ret = do_syscall(env, 2892b779e29eSEdgar E. Iglesias env->regs[12], 2893b779e29eSEdgar E. Iglesias env->regs[5], 2894b779e29eSEdgar E. Iglesias env->regs[6], 2895b779e29eSEdgar E. Iglesias env->regs[7], 2896b779e29eSEdgar E. Iglesias env->regs[8], 2897b779e29eSEdgar E. Iglesias env->regs[9], 28985945cfcbSPeter Maydell env->regs[10], 28995945cfcbSPeter Maydell 0, 0); 2900b779e29eSEdgar E. Iglesias env->regs[3] = ret; 2901b779e29eSEdgar E. Iglesias break; 2902b76da7e3SEdgar E. Iglesias case EXCP_HW_EXCP: 2903b76da7e3SEdgar E. Iglesias env->regs[17] = env->sregs[SR_PC] + 4; 2904b76da7e3SEdgar E. Iglesias if (env->iflags & D_FLAG) { 2905b76da7e3SEdgar E. Iglesias env->sregs[SR_ESR] |= 1 << 12; 2906b76da7e3SEdgar E. Iglesias env->sregs[SR_PC] -= 4; 2907b76da7e3SEdgar E. Iglesias /* FIXME: if branch was immed, replay the imm as well. */ 2908b76da7e3SEdgar E. Iglesias } 2909b76da7e3SEdgar E. Iglesias 2910b76da7e3SEdgar E. Iglesias env->iflags &= ~(IMM_FLAG | D_FLAG); 2911b76da7e3SEdgar E. Iglesias 2912b76da7e3SEdgar E. Iglesias switch (env->sregs[SR_ESR] & 31) { 291322a78d64SEdgar E. Iglesias case ESR_EC_DIVZERO: 2914a86b3c64SChen Gang S info.si_signo = TARGET_SIGFPE; 291522a78d64SEdgar E. Iglesias info.si_errno = 0; 291622a78d64SEdgar E. Iglesias info.si_code = TARGET_FPE_FLTDIV; 291722a78d64SEdgar E. Iglesias info._sifields._sigfault._addr = 0; 291822a78d64SEdgar E. Iglesias queue_signal(env, info.si_signo, &info); 291922a78d64SEdgar E. Iglesias break; 2920b76da7e3SEdgar E. Iglesias case ESR_EC_FPU: 2921a86b3c64SChen Gang S info.si_signo = TARGET_SIGFPE; 2922b76da7e3SEdgar E. Iglesias info.si_errno = 0; 2923b76da7e3SEdgar E. Iglesias if (env->sregs[SR_FSR] & FSR_IO) { 2924b76da7e3SEdgar E. Iglesias info.si_code = TARGET_FPE_FLTINV; 2925b76da7e3SEdgar E. Iglesias } 2926b76da7e3SEdgar E. Iglesias if (env->sregs[SR_FSR] & FSR_DZ) { 2927b76da7e3SEdgar E. Iglesias info.si_code = TARGET_FPE_FLTDIV; 2928b76da7e3SEdgar E. Iglesias } 2929b76da7e3SEdgar E. Iglesias info._sifields._sigfault._addr = 0; 2930b76da7e3SEdgar E. Iglesias queue_signal(env, info.si_signo, &info); 2931b76da7e3SEdgar E. Iglesias break; 2932b76da7e3SEdgar E. Iglesias default: 2933b76da7e3SEdgar E. Iglesias printf ("Unhandled hw-exception: 0x%x\n", 29342e42d52dSEdgar E. Iglesias env->sregs[SR_ESR] & ESR_EC_MASK); 2935878096eeSAndreas Färber cpu_dump_state(cs, stderr, fprintf, 0); 29364d1275c2SRiku Voipio exit(EXIT_FAILURE); 2937b76da7e3SEdgar E. Iglesias break; 2938b76da7e3SEdgar E. Iglesias } 2939b76da7e3SEdgar E. Iglesias break; 2940b779e29eSEdgar E. Iglesias case EXCP_DEBUG: 2941b779e29eSEdgar E. Iglesias { 2942b779e29eSEdgar E. Iglesias int sig; 2943b779e29eSEdgar E. Iglesias 2944db6b81d4SAndreas Färber sig = gdb_handlesig(cs, TARGET_SIGTRAP); 2945b779e29eSEdgar E. Iglesias if (sig) 2946b779e29eSEdgar E. Iglesias { 2947b779e29eSEdgar E. Iglesias info.si_signo = sig; 2948b779e29eSEdgar E. Iglesias info.si_errno = 0; 2949b779e29eSEdgar E. Iglesias info.si_code = TARGET_TRAP_BRKPT; 2950b779e29eSEdgar E. Iglesias queue_signal(env, info.si_signo, &info); 2951b779e29eSEdgar E. Iglesias } 2952b779e29eSEdgar E. Iglesias } 2953b779e29eSEdgar E. Iglesias break; 2954b779e29eSEdgar E. Iglesias default: 2955b779e29eSEdgar E. Iglesias printf ("Unhandled trap: 0x%x\n", trapnr); 2956878096eeSAndreas Färber cpu_dump_state(cs, stderr, fprintf, 0); 29574d1275c2SRiku Voipio exit(EXIT_FAILURE); 2958b779e29eSEdgar E. Iglesias } 2959b779e29eSEdgar E. Iglesias process_pending_signals (env); 2960b779e29eSEdgar E. Iglesias } 2961b779e29eSEdgar E. Iglesias } 2962b779e29eSEdgar E. Iglesias #endif 2963b779e29eSEdgar E. Iglesias 2964e6e5906bSpbrook #ifdef TARGET_M68K 2965e6e5906bSpbrook 2966e6e5906bSpbrook void cpu_loop(CPUM68KState *env) 2967e6e5906bSpbrook { 2968878096eeSAndreas Färber CPUState *cs = CPU(m68k_env_get_cpu(env)); 2969e6e5906bSpbrook int trapnr; 2970e6e5906bSpbrook unsigned int n; 2971c227f099SAnthony Liguori target_siginfo_t info; 29720429a971SAndreas Färber TaskState *ts = cs->opaque; 2973e6e5906bSpbrook 2974e6e5906bSpbrook for(;;) { 2975b040bc9cSPeter Maydell cpu_exec_start(cs); 2976ea3e9847SPeter Crosthwaite trapnr = cpu_m68k_exec(cs); 2977b040bc9cSPeter Maydell cpu_exec_end(cs); 2978e6e5906bSpbrook switch(trapnr) { 2979e6e5906bSpbrook case EXCP_ILLEGAL: 2980e6e5906bSpbrook { 2981e6e5906bSpbrook if (ts->sim_syscalls) { 2982e6e5906bSpbrook uint16_t nr; 2983d8d5119cSPeter Maydell get_user_u16(nr, env->pc + 2); 2984e6e5906bSpbrook env->pc += 4; 2985e6e5906bSpbrook do_m68k_simcall(env, nr); 2986e6e5906bSpbrook } else { 2987e6e5906bSpbrook goto do_sigill; 2988e6e5906bSpbrook } 2989e6e5906bSpbrook } 2990e6e5906bSpbrook break; 2991a87295e8Spbrook case EXCP_HALT_INSN: 2992e6e5906bSpbrook /* Semihosing syscall. */ 2993a87295e8Spbrook env->pc += 4; 2994e6e5906bSpbrook do_m68k_semihosting(env, env->dregs[0]); 2995e6e5906bSpbrook break; 2996e6e5906bSpbrook case EXCP_LINEA: 2997e6e5906bSpbrook case EXCP_LINEF: 2998e6e5906bSpbrook case EXCP_UNSUPPORTED: 2999e6e5906bSpbrook do_sigill: 3000a86b3c64SChen Gang S info.si_signo = TARGET_SIGILL; 3001e6e5906bSpbrook info.si_errno = 0; 3002e6e5906bSpbrook info.si_code = TARGET_ILL_ILLOPN; 3003e6e5906bSpbrook info._sifields._sigfault._addr = env->pc; 3004624f7979Spbrook queue_signal(env, info.si_signo, &info); 3005e6e5906bSpbrook break; 3006e6e5906bSpbrook case EXCP_TRAP0: 3007e6e5906bSpbrook { 3008e6e5906bSpbrook ts->sim_syscalls = 0; 3009e6e5906bSpbrook n = env->dregs[0]; 3010e6e5906bSpbrook env->pc += 2; 3011e6e5906bSpbrook env->dregs[0] = do_syscall(env, 3012e6e5906bSpbrook n, 3013e6e5906bSpbrook env->dregs[1], 3014e6e5906bSpbrook env->dregs[2], 3015e6e5906bSpbrook env->dregs[3], 3016e6e5906bSpbrook env->dregs[4], 3017e6e5906bSpbrook env->dregs[5], 30185945cfcbSPeter Maydell env->aregs[0], 30195945cfcbSPeter Maydell 0, 0); 3020e6e5906bSpbrook } 3021e6e5906bSpbrook break; 3022e6e5906bSpbrook case EXCP_INTERRUPT: 3023e6e5906bSpbrook /* just indicate that signals should be handled asap */ 3024e6e5906bSpbrook break; 3025e6e5906bSpbrook case EXCP_ACCESS: 3026e6e5906bSpbrook { 3027a86b3c64SChen Gang S info.si_signo = TARGET_SIGSEGV; 3028e6e5906bSpbrook info.si_errno = 0; 3029e6e5906bSpbrook /* XXX: check env->error_code */ 3030e6e5906bSpbrook info.si_code = TARGET_SEGV_MAPERR; 3031e6e5906bSpbrook info._sifields._sigfault._addr = env->mmu.ar; 3032624f7979Spbrook queue_signal(env, info.si_signo, &info); 3033e6e5906bSpbrook } 3034e6e5906bSpbrook break; 3035e6e5906bSpbrook case EXCP_DEBUG: 3036e6e5906bSpbrook { 3037e6e5906bSpbrook int sig; 3038e6e5906bSpbrook 3039db6b81d4SAndreas Färber sig = gdb_handlesig(cs, TARGET_SIGTRAP); 3040e6e5906bSpbrook if (sig) 3041e6e5906bSpbrook { 3042e6e5906bSpbrook info.si_signo = sig; 3043e6e5906bSpbrook info.si_errno = 0; 3044e6e5906bSpbrook info.si_code = TARGET_TRAP_BRKPT; 3045624f7979Spbrook queue_signal(env, info.si_signo, &info); 3046e6e5906bSpbrook } 3047e6e5906bSpbrook } 3048e6e5906bSpbrook break; 3049e6e5906bSpbrook default: 3050e6e5906bSpbrook fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", 3051e6e5906bSpbrook trapnr); 3052878096eeSAndreas Färber cpu_dump_state(cs, stderr, fprintf, 0); 3053e6e5906bSpbrook abort(); 3054e6e5906bSpbrook } 3055e6e5906bSpbrook process_pending_signals(env); 3056e6e5906bSpbrook } 3057e6e5906bSpbrook } 3058e6e5906bSpbrook #endif /* TARGET_M68K */ 3059e6e5906bSpbrook 30607a3148a9Sj_mayer #ifdef TARGET_ALPHA 30616910b8f6SRichard Henderson static void do_store_exclusive(CPUAlphaState *env, int reg, int quad) 30626910b8f6SRichard Henderson { 30636910b8f6SRichard Henderson target_ulong addr, val, tmp; 30646910b8f6SRichard Henderson target_siginfo_t info; 30656910b8f6SRichard Henderson int ret = 0; 30666910b8f6SRichard Henderson 30676910b8f6SRichard Henderson addr = env->lock_addr; 30686910b8f6SRichard Henderson tmp = env->lock_st_addr; 30696910b8f6SRichard Henderson env->lock_addr = -1; 30706910b8f6SRichard Henderson env->lock_st_addr = 0; 30716910b8f6SRichard Henderson 30726910b8f6SRichard Henderson start_exclusive(); 30736910b8f6SRichard Henderson mmap_lock(); 30746910b8f6SRichard Henderson 30756910b8f6SRichard Henderson if (addr == tmp) { 30766910b8f6SRichard Henderson if (quad ? get_user_s64(val, addr) : get_user_s32(val, addr)) { 30776910b8f6SRichard Henderson goto do_sigsegv; 30786910b8f6SRichard Henderson } 30796910b8f6SRichard Henderson 30806910b8f6SRichard Henderson if (val == env->lock_value) { 30816910b8f6SRichard Henderson tmp = env->ir[reg]; 30826910b8f6SRichard Henderson if (quad ? put_user_u64(tmp, addr) : put_user_u32(tmp, addr)) { 30836910b8f6SRichard Henderson goto do_sigsegv; 30846910b8f6SRichard Henderson } 30856910b8f6SRichard Henderson ret = 1; 30866910b8f6SRichard Henderson } 30876910b8f6SRichard Henderson } 30886910b8f6SRichard Henderson env->ir[reg] = ret; 30896910b8f6SRichard Henderson env->pc += 4; 30906910b8f6SRichard Henderson 30916910b8f6SRichard Henderson mmap_unlock(); 30926910b8f6SRichard Henderson end_exclusive(); 30936910b8f6SRichard Henderson return; 30946910b8f6SRichard Henderson 30956910b8f6SRichard Henderson do_sigsegv: 30966910b8f6SRichard Henderson mmap_unlock(); 30976910b8f6SRichard Henderson end_exclusive(); 30986910b8f6SRichard Henderson 30996910b8f6SRichard Henderson info.si_signo = TARGET_SIGSEGV; 31006910b8f6SRichard Henderson info.si_errno = 0; 31016910b8f6SRichard Henderson info.si_code = TARGET_SEGV_MAPERR; 31026910b8f6SRichard Henderson info._sifields._sigfault._addr = addr; 31036910b8f6SRichard Henderson queue_signal(env, TARGET_SIGSEGV, &info); 31046910b8f6SRichard Henderson } 31056910b8f6SRichard Henderson 310605390248SAndreas Färber void cpu_loop(CPUAlphaState *env) 31077a3148a9Sj_mayer { 3108878096eeSAndreas Färber CPUState *cs = CPU(alpha_env_get_cpu(env)); 3109e96efcfcSj_mayer int trapnr; 3110c227f099SAnthony Liguori target_siginfo_t info; 31116049f4f8SRichard Henderson abi_long sysret; 31127a3148a9Sj_mayer 31137a3148a9Sj_mayer while (1) { 3114b040bc9cSPeter Maydell cpu_exec_start(cs); 3115ea3e9847SPeter Crosthwaite trapnr = cpu_alpha_exec(cs); 3116b040bc9cSPeter Maydell cpu_exec_end(cs); 31177a3148a9Sj_mayer 3118ac316ca4SRichard Henderson /* All of the traps imply a transition through PALcode, which 3119ac316ca4SRichard Henderson implies an REI instruction has been executed. Which means 3120ac316ca4SRichard Henderson that the intr_flag should be cleared. */ 3121ac316ca4SRichard Henderson env->intr_flag = 0; 3122ac316ca4SRichard Henderson 31237a3148a9Sj_mayer switch (trapnr) { 31247a3148a9Sj_mayer case EXCP_RESET: 31257a3148a9Sj_mayer fprintf(stderr, "Reset requested. Exit\n"); 31264d1275c2SRiku Voipio exit(EXIT_FAILURE); 31277a3148a9Sj_mayer break; 31287a3148a9Sj_mayer case EXCP_MCHK: 31297a3148a9Sj_mayer fprintf(stderr, "Machine check exception. Exit\n"); 31304d1275c2SRiku Voipio exit(EXIT_FAILURE); 31317a3148a9Sj_mayer break; 313207b6c13bSRichard Henderson case EXCP_SMP_INTERRUPT: 313307b6c13bSRichard Henderson case EXCP_CLK_INTERRUPT: 313407b6c13bSRichard Henderson case EXCP_DEV_INTERRUPT: 31357a3148a9Sj_mayer fprintf(stderr, "External interrupt. Exit\n"); 31364d1275c2SRiku Voipio exit(EXIT_FAILURE); 31377a3148a9Sj_mayer break; 313807b6c13bSRichard Henderson case EXCP_MMFAULT: 31396910b8f6SRichard Henderson env->lock_addr = -1; 31406049f4f8SRichard Henderson info.si_signo = TARGET_SIGSEGV; 31416049f4f8SRichard Henderson info.si_errno = 0; 3142129d8aa5SRichard Henderson info.si_code = (page_get_flags(env->trap_arg0) & PAGE_VALID 31430be1d07cSRichard Henderson ? TARGET_SEGV_ACCERR : TARGET_SEGV_MAPERR); 3144129d8aa5SRichard Henderson info._sifields._sigfault._addr = env->trap_arg0; 31456049f4f8SRichard Henderson queue_signal(env, info.si_signo, &info); 31467a3148a9Sj_mayer break; 31477a3148a9Sj_mayer case EXCP_UNALIGN: 31486910b8f6SRichard Henderson env->lock_addr = -1; 31496049f4f8SRichard Henderson info.si_signo = TARGET_SIGBUS; 31506049f4f8SRichard Henderson info.si_errno = 0; 31516049f4f8SRichard Henderson info.si_code = TARGET_BUS_ADRALN; 3152129d8aa5SRichard Henderson info._sifields._sigfault._addr = env->trap_arg0; 31536049f4f8SRichard Henderson queue_signal(env, info.si_signo, &info); 31547a3148a9Sj_mayer break; 31557a3148a9Sj_mayer case EXCP_OPCDEC: 31566049f4f8SRichard Henderson do_sigill: 31576910b8f6SRichard Henderson env->lock_addr = -1; 31586049f4f8SRichard Henderson info.si_signo = TARGET_SIGILL; 31596049f4f8SRichard Henderson info.si_errno = 0; 31606049f4f8SRichard Henderson info.si_code = TARGET_ILL_ILLOPC; 31616049f4f8SRichard Henderson info._sifields._sigfault._addr = env->pc; 31626049f4f8SRichard Henderson queue_signal(env, info.si_signo, &info); 31637a3148a9Sj_mayer break; 316407b6c13bSRichard Henderson case EXCP_ARITH: 316507b6c13bSRichard Henderson env->lock_addr = -1; 316607b6c13bSRichard Henderson info.si_signo = TARGET_SIGFPE; 316707b6c13bSRichard Henderson info.si_errno = 0; 316807b6c13bSRichard Henderson info.si_code = TARGET_FPE_FLTINV; 316907b6c13bSRichard Henderson info._sifields._sigfault._addr = env->pc; 317007b6c13bSRichard Henderson queue_signal(env, info.si_signo, &info); 317107b6c13bSRichard Henderson break; 31727a3148a9Sj_mayer case EXCP_FEN: 31736049f4f8SRichard Henderson /* No-op. Linux simply re-enables the FPU. */ 31747a3148a9Sj_mayer break; 317507b6c13bSRichard Henderson case EXCP_CALL_PAL: 31766910b8f6SRichard Henderson env->lock_addr = -1; 317707b6c13bSRichard Henderson switch (env->error_code) { 31786049f4f8SRichard Henderson case 0x80: 31796049f4f8SRichard Henderson /* BPT */ 31806049f4f8SRichard Henderson info.si_signo = TARGET_SIGTRAP; 31816049f4f8SRichard Henderson info.si_errno = 0; 31826049f4f8SRichard Henderson info.si_code = TARGET_TRAP_BRKPT; 31836049f4f8SRichard Henderson info._sifields._sigfault._addr = env->pc; 31846049f4f8SRichard Henderson queue_signal(env, info.si_signo, &info); 31856049f4f8SRichard Henderson break; 31866049f4f8SRichard Henderson case 0x81: 31876049f4f8SRichard Henderson /* BUGCHK */ 31886049f4f8SRichard Henderson info.si_signo = TARGET_SIGTRAP; 31896049f4f8SRichard Henderson info.si_errno = 0; 31906049f4f8SRichard Henderson info.si_code = 0; 31916049f4f8SRichard Henderson info._sifields._sigfault._addr = env->pc; 31926049f4f8SRichard Henderson queue_signal(env, info.si_signo, &info); 31936049f4f8SRichard Henderson break; 31946049f4f8SRichard Henderson case 0x83: 31956049f4f8SRichard Henderson /* CALLSYS */ 31966049f4f8SRichard Henderson trapnr = env->ir[IR_V0]; 31976049f4f8SRichard Henderson sysret = do_syscall(env, trapnr, 31986049f4f8SRichard Henderson env->ir[IR_A0], env->ir[IR_A1], 31996049f4f8SRichard Henderson env->ir[IR_A2], env->ir[IR_A3], 32005945cfcbSPeter Maydell env->ir[IR_A4], env->ir[IR_A5], 32015945cfcbSPeter Maydell 0, 0); 3202a5b3b13bSRichard Henderson if (trapnr == TARGET_NR_sigreturn 3203a5b3b13bSRichard Henderson || trapnr == TARGET_NR_rt_sigreturn) { 3204a5b3b13bSRichard Henderson break; 3205a5b3b13bSRichard Henderson } 3206a5b3b13bSRichard Henderson /* Syscall writes 0 to V0 to bypass error check, similar 32070e141977SRichard Henderson to how this is handled internal to Linux kernel. 32080e141977SRichard Henderson (Ab)use trapnr temporarily as boolean indicating error. */ 32090e141977SRichard Henderson trapnr = (env->ir[IR_V0] != 0 && sysret < 0); 32100e141977SRichard Henderson env->ir[IR_V0] = (trapnr ? -sysret : sysret); 32110e141977SRichard Henderson env->ir[IR_A3] = trapnr; 32126049f4f8SRichard Henderson break; 32136049f4f8SRichard Henderson case 0x86: 32146049f4f8SRichard Henderson /* IMB */ 32156049f4f8SRichard Henderson /* ??? We can probably elide the code using page_unprotect 32166049f4f8SRichard Henderson that is checking for self-modifying code. Instead we 32176049f4f8SRichard Henderson could simply call tb_flush here. Until we work out the 32186049f4f8SRichard Henderson changes required to turn off the extra write protection, 32196049f4f8SRichard Henderson this can be a no-op. */ 32206049f4f8SRichard Henderson break; 32216049f4f8SRichard Henderson case 0x9E: 32226049f4f8SRichard Henderson /* RDUNIQUE */ 32236049f4f8SRichard Henderson /* Handled in the translator for usermode. */ 32246049f4f8SRichard Henderson abort(); 32256049f4f8SRichard Henderson case 0x9F: 32266049f4f8SRichard Henderson /* WRUNIQUE */ 32276049f4f8SRichard Henderson /* Handled in the translator for usermode. */ 32286049f4f8SRichard Henderson abort(); 32296049f4f8SRichard Henderson case 0xAA: 32306049f4f8SRichard Henderson /* GENTRAP */ 32316049f4f8SRichard Henderson info.si_signo = TARGET_SIGFPE; 32326049f4f8SRichard Henderson switch (env->ir[IR_A0]) { 32336049f4f8SRichard Henderson case TARGET_GEN_INTOVF: 32346049f4f8SRichard Henderson info.si_code = TARGET_FPE_INTOVF; 32356049f4f8SRichard Henderson break; 32366049f4f8SRichard Henderson case TARGET_GEN_INTDIV: 32376049f4f8SRichard Henderson info.si_code = TARGET_FPE_INTDIV; 32386049f4f8SRichard Henderson break; 32396049f4f8SRichard Henderson case TARGET_GEN_FLTOVF: 32406049f4f8SRichard Henderson info.si_code = TARGET_FPE_FLTOVF; 32416049f4f8SRichard Henderson break; 32426049f4f8SRichard Henderson case TARGET_GEN_FLTUND: 32436049f4f8SRichard Henderson info.si_code = TARGET_FPE_FLTUND; 32446049f4f8SRichard Henderson break; 32456049f4f8SRichard Henderson case TARGET_GEN_FLTINV: 32466049f4f8SRichard Henderson info.si_code = TARGET_FPE_FLTINV; 32476049f4f8SRichard Henderson break; 32486049f4f8SRichard Henderson case TARGET_GEN_FLTINE: 32496049f4f8SRichard Henderson info.si_code = TARGET_FPE_FLTRES; 32506049f4f8SRichard Henderson break; 32516049f4f8SRichard Henderson case TARGET_GEN_ROPRAND: 32526049f4f8SRichard Henderson info.si_code = 0; 32536049f4f8SRichard Henderson break; 32546049f4f8SRichard Henderson default: 32556049f4f8SRichard Henderson info.si_signo = TARGET_SIGTRAP; 32566049f4f8SRichard Henderson info.si_code = 0; 32576049f4f8SRichard Henderson break; 32586049f4f8SRichard Henderson } 32596049f4f8SRichard Henderson info.si_errno = 0; 32606049f4f8SRichard Henderson info._sifields._sigfault._addr = env->pc; 32616049f4f8SRichard Henderson queue_signal(env, info.si_signo, &info); 32626049f4f8SRichard Henderson break; 32636049f4f8SRichard Henderson default: 32646049f4f8SRichard Henderson goto do_sigill; 32656049f4f8SRichard Henderson } 32667a3148a9Sj_mayer break; 32677a3148a9Sj_mayer case EXCP_DEBUG: 3268db6b81d4SAndreas Färber info.si_signo = gdb_handlesig(cs, TARGET_SIGTRAP); 32696049f4f8SRichard Henderson if (info.si_signo) { 32706910b8f6SRichard Henderson env->lock_addr = -1; 32717a3148a9Sj_mayer info.si_errno = 0; 32727a3148a9Sj_mayer info.si_code = TARGET_TRAP_BRKPT; 3273624f7979Spbrook queue_signal(env, info.si_signo, &info); 32747a3148a9Sj_mayer } 32757a3148a9Sj_mayer break; 32766910b8f6SRichard Henderson case EXCP_STL_C: 32776910b8f6SRichard Henderson case EXCP_STQ_C: 32786910b8f6SRichard Henderson do_store_exclusive(env, env->error_code, trapnr - EXCP_STL_C); 32796910b8f6SRichard Henderson break; 3280d0f20495SRichard Henderson case EXCP_INTERRUPT: 3281d0f20495SRichard Henderson /* Just indicate that signals should be handled asap. */ 3282d0f20495SRichard Henderson break; 32837a3148a9Sj_mayer default: 32847a3148a9Sj_mayer printf ("Unhandled trap: 0x%x\n", trapnr); 3285878096eeSAndreas Färber cpu_dump_state(cs, stderr, fprintf, 0); 32864d1275c2SRiku Voipio exit(EXIT_FAILURE); 32877a3148a9Sj_mayer } 32887a3148a9Sj_mayer process_pending_signals (env); 32897a3148a9Sj_mayer } 32907a3148a9Sj_mayer } 32917a3148a9Sj_mayer #endif /* TARGET_ALPHA */ 32927a3148a9Sj_mayer 3293a4c075f1SUlrich Hecht #ifdef TARGET_S390X 3294a4c075f1SUlrich Hecht void cpu_loop(CPUS390XState *env) 3295a4c075f1SUlrich Hecht { 3296878096eeSAndreas Färber CPUState *cs = CPU(s390_env_get_cpu(env)); 3297d5a103cdSRichard Henderson int trapnr, n, sig; 3298a4c075f1SUlrich Hecht target_siginfo_t info; 3299d5a103cdSRichard Henderson target_ulong addr; 3300a4c075f1SUlrich Hecht 3301a4c075f1SUlrich Hecht while (1) { 3302b040bc9cSPeter Maydell cpu_exec_start(cs); 3303ea3e9847SPeter Crosthwaite trapnr = cpu_s390x_exec(cs); 3304b040bc9cSPeter Maydell cpu_exec_end(cs); 3305a4c075f1SUlrich Hecht switch (trapnr) { 3306a4c075f1SUlrich Hecht case EXCP_INTERRUPT: 3307d5a103cdSRichard Henderson /* Just indicate that signals should be handled asap. */ 3308a4c075f1SUlrich Hecht break; 3309a4c075f1SUlrich Hecht 3310a4c075f1SUlrich Hecht case EXCP_SVC: 3311d5a103cdSRichard Henderson n = env->int_svc_code; 3312a4c075f1SUlrich Hecht if (!n) { 3313a4c075f1SUlrich Hecht /* syscalls > 255 */ 3314a4c075f1SUlrich Hecht n = env->regs[1]; 3315a4c075f1SUlrich Hecht } 3316d5a103cdSRichard Henderson env->psw.addr += env->int_svc_ilen; 3317d5a103cdSRichard Henderson env->regs[2] = do_syscall(env, n, env->regs[2], env->regs[3], 3318d5a103cdSRichard Henderson env->regs[4], env->regs[5], 3319d5a103cdSRichard Henderson env->regs[6], env->regs[7], 0, 0); 3320d5a103cdSRichard Henderson break; 3321d5a103cdSRichard Henderson 3322d5a103cdSRichard Henderson case EXCP_DEBUG: 3323db6b81d4SAndreas Färber sig = gdb_handlesig(cs, TARGET_SIGTRAP); 3324d5a103cdSRichard Henderson if (sig) { 3325d5a103cdSRichard Henderson n = TARGET_TRAP_BRKPT; 3326d5a103cdSRichard Henderson goto do_signal_pc; 3327a4c075f1SUlrich Hecht } 3328a4c075f1SUlrich Hecht break; 3329d5a103cdSRichard Henderson case EXCP_PGM: 3330d5a103cdSRichard Henderson n = env->int_pgm_code; 3331d5a103cdSRichard Henderson switch (n) { 3332d5a103cdSRichard Henderson case PGM_OPERATION: 3333d5a103cdSRichard Henderson case PGM_PRIVILEGED: 3334a86b3c64SChen Gang S sig = TARGET_SIGILL; 3335d5a103cdSRichard Henderson n = TARGET_ILL_ILLOPC; 3336d5a103cdSRichard Henderson goto do_signal_pc; 3337d5a103cdSRichard Henderson case PGM_PROTECTION: 3338d5a103cdSRichard Henderson case PGM_ADDRESSING: 3339a86b3c64SChen Gang S sig = TARGET_SIGSEGV; 3340a4c075f1SUlrich Hecht /* XXX: check env->error_code */ 3341d5a103cdSRichard Henderson n = TARGET_SEGV_MAPERR; 3342d5a103cdSRichard Henderson addr = env->__excp_addr; 3343d5a103cdSRichard Henderson goto do_signal; 3344d5a103cdSRichard Henderson case PGM_EXECUTE: 3345d5a103cdSRichard Henderson case PGM_SPECIFICATION: 3346d5a103cdSRichard Henderson case PGM_SPECIAL_OP: 3347d5a103cdSRichard Henderson case PGM_OPERAND: 3348d5a103cdSRichard Henderson do_sigill_opn: 3349a86b3c64SChen Gang S sig = TARGET_SIGILL; 3350d5a103cdSRichard Henderson n = TARGET_ILL_ILLOPN; 3351d5a103cdSRichard Henderson goto do_signal_pc; 3352d5a103cdSRichard Henderson 3353d5a103cdSRichard Henderson case PGM_FIXPT_OVERFLOW: 3354a86b3c64SChen Gang S sig = TARGET_SIGFPE; 3355d5a103cdSRichard Henderson n = TARGET_FPE_INTOVF; 3356d5a103cdSRichard Henderson goto do_signal_pc; 3357d5a103cdSRichard Henderson case PGM_FIXPT_DIVIDE: 3358a86b3c64SChen Gang S sig = TARGET_SIGFPE; 3359d5a103cdSRichard Henderson n = TARGET_FPE_INTDIV; 3360d5a103cdSRichard Henderson goto do_signal_pc; 3361d5a103cdSRichard Henderson 3362d5a103cdSRichard Henderson case PGM_DATA: 3363d5a103cdSRichard Henderson n = (env->fpc >> 8) & 0xff; 3364d5a103cdSRichard Henderson if (n == 0xff) { 3365d5a103cdSRichard Henderson /* compare-and-trap */ 3366d5a103cdSRichard Henderson goto do_sigill_opn; 3367d5a103cdSRichard Henderson } else { 3368d5a103cdSRichard Henderson /* An IEEE exception, simulated or otherwise. */ 3369d5a103cdSRichard Henderson if (n & 0x80) { 3370d5a103cdSRichard Henderson n = TARGET_FPE_FLTINV; 3371d5a103cdSRichard Henderson } else if (n & 0x40) { 3372d5a103cdSRichard Henderson n = TARGET_FPE_FLTDIV; 3373d5a103cdSRichard Henderson } else if (n & 0x20) { 3374d5a103cdSRichard Henderson n = TARGET_FPE_FLTOVF; 3375d5a103cdSRichard Henderson } else if (n & 0x10) { 3376d5a103cdSRichard Henderson n = TARGET_FPE_FLTUND; 3377d5a103cdSRichard Henderson } else if (n & 0x08) { 3378d5a103cdSRichard Henderson n = TARGET_FPE_FLTRES; 3379d5a103cdSRichard Henderson } else { 3380d5a103cdSRichard Henderson /* ??? Quantum exception; BFP, DFP error. */ 3381d5a103cdSRichard Henderson goto do_sigill_opn; 3382a4c075f1SUlrich Hecht } 3383a86b3c64SChen Gang S sig = TARGET_SIGFPE; 3384d5a103cdSRichard Henderson goto do_signal_pc; 3385a4c075f1SUlrich Hecht } 3386d5a103cdSRichard Henderson 3387a4c075f1SUlrich Hecht default: 3388d5a103cdSRichard Henderson fprintf(stderr, "Unhandled program exception: %#x\n", n); 3389878096eeSAndreas Färber cpu_dump_state(cs, stderr, fprintf, 0); 33904d1275c2SRiku Voipio exit(EXIT_FAILURE); 3391d5a103cdSRichard Henderson } 3392d5a103cdSRichard Henderson break; 3393d5a103cdSRichard Henderson 3394d5a103cdSRichard Henderson do_signal_pc: 3395d5a103cdSRichard Henderson addr = env->psw.addr; 3396d5a103cdSRichard Henderson do_signal: 3397d5a103cdSRichard Henderson info.si_signo = sig; 3398d5a103cdSRichard Henderson info.si_errno = 0; 3399d5a103cdSRichard Henderson info.si_code = n; 3400d5a103cdSRichard Henderson info._sifields._sigfault._addr = addr; 3401d5a103cdSRichard Henderson queue_signal(env, info.si_signo, &info); 3402d5a103cdSRichard Henderson break; 3403d5a103cdSRichard Henderson 3404d5a103cdSRichard Henderson default: 3405d5a103cdSRichard Henderson fprintf(stderr, "Unhandled trap: 0x%x\n", trapnr); 3406878096eeSAndreas Färber cpu_dump_state(cs, stderr, fprintf, 0); 34074d1275c2SRiku Voipio exit(EXIT_FAILURE); 3408a4c075f1SUlrich Hecht } 3409a4c075f1SUlrich Hecht process_pending_signals (env); 3410a4c075f1SUlrich Hecht } 3411a4c075f1SUlrich Hecht } 3412a4c075f1SUlrich Hecht 3413a4c075f1SUlrich Hecht #endif /* TARGET_S390X */ 3414a4c075f1SUlrich Hecht 3415b16189b2SChen Gang #ifdef TARGET_TILEGX 3416b16189b2SChen Gang 3417b16189b2SChen Gang static void gen_sigsegv_maperr(CPUTLGState *env, target_ulong addr) 3418b16189b2SChen Gang { 3419b16189b2SChen Gang target_siginfo_t info; 3420b16189b2SChen Gang 3421b16189b2SChen Gang info.si_signo = TARGET_SIGSEGV; 3422b16189b2SChen Gang info.si_errno = 0; 3423b16189b2SChen Gang info.si_code = TARGET_SEGV_MAPERR; 3424b16189b2SChen Gang info._sifields._sigfault._addr = addr; 3425b16189b2SChen Gang queue_signal(env, info.si_signo, &info); 3426b16189b2SChen Gang } 3427b16189b2SChen Gang 3428b16189b2SChen Gang static void gen_sigill_reg(CPUTLGState *env) 3429b16189b2SChen Gang { 3430b16189b2SChen Gang target_siginfo_t info; 3431b16189b2SChen Gang 3432b16189b2SChen Gang info.si_signo = TARGET_SIGILL; 3433b16189b2SChen Gang info.si_errno = 0; 3434b16189b2SChen Gang info.si_code = TARGET_ILL_PRVREG; 3435b16189b2SChen Gang info._sifields._sigfault._addr = env->pc; 3436b16189b2SChen Gang queue_signal(env, info.si_signo, &info); 3437b16189b2SChen Gang } 3438b16189b2SChen Gang 34390583b233SRichard Henderson static void set_regval(CPUTLGState *env, uint8_t reg, uint64_t val) 34400583b233SRichard Henderson { 34410583b233SRichard Henderson if (unlikely(reg >= TILEGX_R_COUNT)) { 34420583b233SRichard Henderson switch (reg) { 34430583b233SRichard Henderson case TILEGX_R_SN: 34440583b233SRichard Henderson case TILEGX_R_ZERO: 34450583b233SRichard Henderson return; 34460583b233SRichard Henderson case TILEGX_R_IDN0: 34470583b233SRichard Henderson case TILEGX_R_IDN1: 34480583b233SRichard Henderson case TILEGX_R_UDN0: 34490583b233SRichard Henderson case TILEGX_R_UDN1: 34500583b233SRichard Henderson case TILEGX_R_UDN2: 34510583b233SRichard Henderson case TILEGX_R_UDN3: 34520583b233SRichard Henderson gen_sigill_reg(env); 34530583b233SRichard Henderson return; 34540583b233SRichard Henderson default: 34550583b233SRichard Henderson g_assert_not_reached(); 34560583b233SRichard Henderson } 34570583b233SRichard Henderson } 34580583b233SRichard Henderson env->regs[reg] = val; 34590583b233SRichard Henderson } 34600583b233SRichard Henderson 34610583b233SRichard Henderson /* 34620583b233SRichard Henderson * Compare the 8-byte contents of the CmpValue SPR with the 8-byte value in 34630583b233SRichard Henderson * memory at the address held in the first source register. If the values are 34640583b233SRichard Henderson * not equal, then no memory operation is performed. If the values are equal, 34650583b233SRichard Henderson * the 8-byte quantity from the second source register is written into memory 34660583b233SRichard Henderson * at the address held in the first source register. In either case, the result 34670583b233SRichard Henderson * of the instruction is the value read from memory. The compare and write to 34680583b233SRichard Henderson * memory are atomic and thus can be used for synchronization purposes. This 34690583b233SRichard Henderson * instruction only operates for addresses aligned to a 8-byte boundary. 34700583b233SRichard Henderson * Unaligned memory access causes an Unaligned Data Reference interrupt. 34710583b233SRichard Henderson * 34720583b233SRichard Henderson * Functional Description (64-bit) 34730583b233SRichard Henderson * uint64_t memVal = memoryReadDoubleWord (rf[SrcA]); 34740583b233SRichard Henderson * rf[Dest] = memVal; 34750583b233SRichard Henderson * if (memVal == SPR[CmpValueSPR]) 34760583b233SRichard Henderson * memoryWriteDoubleWord (rf[SrcA], rf[SrcB]); 34770583b233SRichard Henderson * 34780583b233SRichard Henderson * Functional Description (32-bit) 34790583b233SRichard Henderson * uint64_t memVal = signExtend32 (memoryReadWord (rf[SrcA])); 34800583b233SRichard Henderson * rf[Dest] = memVal; 34810583b233SRichard Henderson * if (memVal == signExtend32 (SPR[CmpValueSPR])) 34820583b233SRichard Henderson * memoryWriteWord (rf[SrcA], rf[SrcB]); 34830583b233SRichard Henderson * 34840583b233SRichard Henderson * 34850583b233SRichard Henderson * This function also processes exch and exch4 which need not process SPR. 34860583b233SRichard Henderson */ 34870583b233SRichard Henderson static void do_exch(CPUTLGState *env, bool quad, bool cmp) 34880583b233SRichard Henderson { 34890583b233SRichard Henderson target_ulong addr; 34900583b233SRichard Henderson target_long val, sprval; 34910583b233SRichard Henderson 34920583b233SRichard Henderson start_exclusive(); 34930583b233SRichard Henderson 34940583b233SRichard Henderson addr = env->atomic_srca; 34950583b233SRichard Henderson if (quad ? get_user_s64(val, addr) : get_user_s32(val, addr)) { 34960583b233SRichard Henderson goto sigsegv_maperr; 34970583b233SRichard Henderson } 34980583b233SRichard Henderson 34990583b233SRichard Henderson if (cmp) { 35000583b233SRichard Henderson if (quad) { 35010583b233SRichard Henderson sprval = env->spregs[TILEGX_SPR_CMPEXCH]; 35020583b233SRichard Henderson } else { 35030583b233SRichard Henderson sprval = sextract64(env->spregs[TILEGX_SPR_CMPEXCH], 0, 32); 35040583b233SRichard Henderson } 35050583b233SRichard Henderson } 35060583b233SRichard Henderson 35070583b233SRichard Henderson if (!cmp || val == sprval) { 35080583b233SRichard Henderson target_long valb = env->atomic_srcb; 35090583b233SRichard Henderson if (quad ? put_user_u64(valb, addr) : put_user_u32(valb, addr)) { 35100583b233SRichard Henderson goto sigsegv_maperr; 35110583b233SRichard Henderson } 35120583b233SRichard Henderson } 35130583b233SRichard Henderson 35140583b233SRichard Henderson set_regval(env, env->atomic_dstr, val); 35150583b233SRichard Henderson end_exclusive(); 35160583b233SRichard Henderson return; 35170583b233SRichard Henderson 35180583b233SRichard Henderson sigsegv_maperr: 35190583b233SRichard Henderson end_exclusive(); 35200583b233SRichard Henderson gen_sigsegv_maperr(env, addr); 35210583b233SRichard Henderson } 35220583b233SRichard Henderson 35230583b233SRichard Henderson static void do_fetch(CPUTLGState *env, int trapnr, bool quad) 35240583b233SRichard Henderson { 35250583b233SRichard Henderson int8_t write = 1; 35260583b233SRichard Henderson target_ulong addr; 35270583b233SRichard Henderson target_long val, valb; 35280583b233SRichard Henderson 35290583b233SRichard Henderson start_exclusive(); 35300583b233SRichard Henderson 35310583b233SRichard Henderson addr = env->atomic_srca; 35320583b233SRichard Henderson valb = env->atomic_srcb; 35330583b233SRichard Henderson if (quad ? get_user_s64(val, addr) : get_user_s32(val, addr)) { 35340583b233SRichard Henderson goto sigsegv_maperr; 35350583b233SRichard Henderson } 35360583b233SRichard Henderson 35370583b233SRichard Henderson switch (trapnr) { 35380583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHADD: 35390583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHADD4: 35400583b233SRichard Henderson valb += val; 35410583b233SRichard Henderson break; 35420583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHADDGEZ: 35430583b233SRichard Henderson valb += val; 35440583b233SRichard Henderson if (valb < 0) { 35450583b233SRichard Henderson write = 0; 35460583b233SRichard Henderson } 35470583b233SRichard Henderson break; 35480583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHADDGEZ4: 35490583b233SRichard Henderson valb += val; 35500583b233SRichard Henderson if ((int32_t)valb < 0) { 35510583b233SRichard Henderson write = 0; 35520583b233SRichard Henderson } 35530583b233SRichard Henderson break; 35540583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHAND: 35550583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHAND4: 35560583b233SRichard Henderson valb &= val; 35570583b233SRichard Henderson break; 35580583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHOR: 35590583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHOR4: 35600583b233SRichard Henderson valb |= val; 35610583b233SRichard Henderson break; 35620583b233SRichard Henderson default: 35630583b233SRichard Henderson g_assert_not_reached(); 35640583b233SRichard Henderson } 35650583b233SRichard Henderson 35660583b233SRichard Henderson if (write) { 35670583b233SRichard Henderson if (quad ? put_user_u64(valb, addr) : put_user_u32(valb, addr)) { 35680583b233SRichard Henderson goto sigsegv_maperr; 35690583b233SRichard Henderson } 35700583b233SRichard Henderson } 35710583b233SRichard Henderson 35720583b233SRichard Henderson set_regval(env, env->atomic_dstr, val); 35730583b233SRichard Henderson end_exclusive(); 35740583b233SRichard Henderson return; 35750583b233SRichard Henderson 35760583b233SRichard Henderson sigsegv_maperr: 35770583b233SRichard Henderson end_exclusive(); 35780583b233SRichard Henderson gen_sigsegv_maperr(env, addr); 35790583b233SRichard Henderson } 35800583b233SRichard Henderson 3581b16189b2SChen Gang void cpu_loop(CPUTLGState *env) 3582b16189b2SChen Gang { 3583b16189b2SChen Gang CPUState *cs = CPU(tilegx_env_get_cpu(env)); 3584b16189b2SChen Gang int trapnr; 3585b16189b2SChen Gang 3586b16189b2SChen Gang while (1) { 3587b16189b2SChen Gang cpu_exec_start(cs); 3588b16189b2SChen Gang trapnr = cpu_tilegx_exec(cs); 3589b16189b2SChen Gang cpu_exec_end(cs); 3590b16189b2SChen Gang switch (trapnr) { 3591b16189b2SChen Gang case TILEGX_EXCP_SYSCALL: 3592b16189b2SChen Gang env->regs[TILEGX_R_RE] = do_syscall(env, env->regs[TILEGX_R_NR], 3593b16189b2SChen Gang env->regs[0], env->regs[1], 3594b16189b2SChen Gang env->regs[2], env->regs[3], 3595b16189b2SChen Gang env->regs[4], env->regs[5], 3596b16189b2SChen Gang env->regs[6], env->regs[7]); 3597b16189b2SChen Gang env->regs[TILEGX_R_ERR] = TILEGX_IS_ERRNO(env->regs[TILEGX_R_RE]) 3598b16189b2SChen Gang ? - env->regs[TILEGX_R_RE] 3599b16189b2SChen Gang : 0; 3600b16189b2SChen Gang break; 36010583b233SRichard Henderson case TILEGX_EXCP_OPCODE_EXCH: 36020583b233SRichard Henderson do_exch(env, true, false); 36030583b233SRichard Henderson break; 36040583b233SRichard Henderson case TILEGX_EXCP_OPCODE_EXCH4: 36050583b233SRichard Henderson do_exch(env, false, false); 36060583b233SRichard Henderson break; 36070583b233SRichard Henderson case TILEGX_EXCP_OPCODE_CMPEXCH: 36080583b233SRichard Henderson do_exch(env, true, true); 36090583b233SRichard Henderson break; 36100583b233SRichard Henderson case TILEGX_EXCP_OPCODE_CMPEXCH4: 36110583b233SRichard Henderson do_exch(env, false, true); 36120583b233SRichard Henderson break; 36130583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHADD: 36140583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHADDGEZ: 36150583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHAND: 36160583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHOR: 36170583b233SRichard Henderson do_fetch(env, trapnr, true); 36180583b233SRichard Henderson break; 36190583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHADD4: 36200583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHADDGEZ4: 36210583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHAND4: 36220583b233SRichard Henderson case TILEGX_EXCP_OPCODE_FETCHOR4: 36230583b233SRichard Henderson do_fetch(env, trapnr, false); 36240583b233SRichard Henderson break; 3625b16189b2SChen Gang case TILEGX_EXCP_REG_IDN_ACCESS: 3626b16189b2SChen Gang case TILEGX_EXCP_REG_UDN_ACCESS: 3627b16189b2SChen Gang gen_sigill_reg(env); 3628b16189b2SChen Gang break; 36299b9dc7acSRichard Henderson case TILEGX_EXCP_SEGV: 36309b9dc7acSRichard Henderson gen_sigsegv_maperr(env, env->excaddr); 36319b9dc7acSRichard Henderson break; 3632b16189b2SChen Gang default: 3633b16189b2SChen Gang fprintf(stderr, "trapnr is %d[0x%x].\n", trapnr, trapnr); 3634b16189b2SChen Gang g_assert_not_reached(); 3635b16189b2SChen Gang } 3636b16189b2SChen Gang process_pending_signals(env); 3637b16189b2SChen Gang } 3638b16189b2SChen Gang } 3639b16189b2SChen Gang 3640b16189b2SChen Gang #endif 3641b16189b2SChen Gang 3642a2247f8eSAndreas Färber THREAD CPUState *thread_cpu; 364359faf6d6Sbellard 3644edf8e2afSMika Westerberg void task_settid(TaskState *ts) 3645edf8e2afSMika Westerberg { 3646edf8e2afSMika Westerberg if (ts->ts_tid == 0) { 3647edf8e2afSMika Westerberg ts->ts_tid = (pid_t)syscall(SYS_gettid); 3648edf8e2afSMika Westerberg } 3649edf8e2afSMika Westerberg } 3650edf8e2afSMika Westerberg 3651edf8e2afSMika Westerberg void stop_all_tasks(void) 3652edf8e2afSMika Westerberg { 3653edf8e2afSMika Westerberg /* 3654edf8e2afSMika Westerberg * We trust that when using NPTL, start_exclusive() 3655edf8e2afSMika Westerberg * handles thread stopping correctly. 3656edf8e2afSMika Westerberg */ 3657edf8e2afSMika Westerberg start_exclusive(); 3658edf8e2afSMika Westerberg } 3659edf8e2afSMika Westerberg 3660c3a92833Spbrook /* Assumes contents are already zeroed. */ 3661624f7979Spbrook void init_task_state(TaskState *ts) 3662624f7979Spbrook { 3663624f7979Spbrook int i; 3664624f7979Spbrook 3665624f7979Spbrook ts->used = 1; 3666624f7979Spbrook ts->first_free = ts->sigqueue_table; 3667624f7979Spbrook for (i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++) { 3668624f7979Spbrook ts->sigqueue_table[i].next = &ts->sigqueue_table[i + 1]; 3669624f7979Spbrook } 3670624f7979Spbrook ts->sigqueue_table[i].next = NULL; 3671624f7979Spbrook } 36729de5e440Sbellard 367330ba0ee5SAndreas Färber CPUArchState *cpu_copy(CPUArchState *env) 367430ba0ee5SAndreas Färber { 3675ff4700b0SAndreas Färber CPUState *cpu = ENV_GET_CPU(env); 36762994fd96SEduardo Habkost CPUState *new_cpu = cpu_init(cpu_model); 367761c7480fSLeon Alrae CPUArchState *new_env = new_cpu->env_ptr; 367830ba0ee5SAndreas Färber CPUBreakpoint *bp; 367930ba0ee5SAndreas Färber CPUWatchpoint *wp; 368030ba0ee5SAndreas Färber 368130ba0ee5SAndreas Färber /* Reset non arch specific state */ 368275a34036SAndreas Färber cpu_reset(new_cpu); 368330ba0ee5SAndreas Färber 368430ba0ee5SAndreas Färber memcpy(new_env, env, sizeof(CPUArchState)); 368530ba0ee5SAndreas Färber 368630ba0ee5SAndreas Färber /* Clone all break/watchpoints. 368730ba0ee5SAndreas Färber Note: Once we support ptrace with hw-debug register access, make sure 368830ba0ee5SAndreas Färber BP_CPU break/watchpoints are handled correctly on clone. */ 36891d085f6cSThierry Bultel QTAILQ_INIT(&new_cpu->breakpoints); 36901d085f6cSThierry Bultel QTAILQ_INIT(&new_cpu->watchpoints); 3691f0c3c505SAndreas Färber QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) { 3692b3310ab3SAndreas Färber cpu_breakpoint_insert(new_cpu, bp->pc, bp->flags, NULL); 369330ba0ee5SAndreas Färber } 3694ff4700b0SAndreas Färber QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { 369505068c0dSPeter Maydell cpu_watchpoint_insert(new_cpu, wp->vaddr, wp->len, wp->flags, NULL); 369630ba0ee5SAndreas Färber } 369730ba0ee5SAndreas Färber 369830ba0ee5SAndreas Färber return new_env; 369930ba0ee5SAndreas Färber } 370030ba0ee5SAndreas Färber 3701fc9c5412SJohannes Schauer static void handle_arg_help(const char *arg) 3702fc9c5412SJohannes Schauer { 37034d1275c2SRiku Voipio usage(EXIT_SUCCESS); 3704fc9c5412SJohannes Schauer } 3705fc9c5412SJohannes Schauer 3706fc9c5412SJohannes Schauer static void handle_arg_log(const char *arg) 3707fc9c5412SJohannes Schauer { 3708fc9c5412SJohannes Schauer int mask; 3709fc9c5412SJohannes Schauer 37104fde1ebaSPeter Maydell mask = qemu_str_to_log_mask(arg); 3711fc9c5412SJohannes Schauer if (!mask) { 371259a6fa6eSPeter Maydell qemu_print_log_usage(stdout); 37134d1275c2SRiku Voipio exit(EXIT_FAILURE); 3714fc9c5412SJohannes Schauer } 371524537a01SPeter Maydell qemu_set_log(mask); 3716fc9c5412SJohannes Schauer } 3717fc9c5412SJohannes Schauer 371850171d42S陳韋任 static void handle_arg_log_filename(const char *arg) 371950171d42S陳韋任 { 37209a7e5424SPeter Maydell qemu_set_log_filename(arg); 372150171d42S陳韋任 } 372250171d42S陳韋任 3723fc9c5412SJohannes Schauer static void handle_arg_set_env(const char *arg) 3724fc9c5412SJohannes Schauer { 3725fc9c5412SJohannes Schauer char *r, *p, *token; 3726fc9c5412SJohannes Schauer r = p = strdup(arg); 3727fc9c5412SJohannes Schauer while ((token = strsep(&p, ",")) != NULL) { 3728fc9c5412SJohannes Schauer if (envlist_setenv(envlist, token) != 0) { 37294d1275c2SRiku Voipio usage(EXIT_FAILURE); 3730fc9c5412SJohannes Schauer } 3731fc9c5412SJohannes Schauer } 3732fc9c5412SJohannes Schauer free(r); 3733fc9c5412SJohannes Schauer } 3734fc9c5412SJohannes Schauer 3735fc9c5412SJohannes Schauer static void handle_arg_unset_env(const char *arg) 3736fc9c5412SJohannes Schauer { 3737fc9c5412SJohannes Schauer char *r, *p, *token; 3738fc9c5412SJohannes Schauer r = p = strdup(arg); 3739fc9c5412SJohannes Schauer while ((token = strsep(&p, ",")) != NULL) { 3740fc9c5412SJohannes Schauer if (envlist_unsetenv(envlist, token) != 0) { 37414d1275c2SRiku Voipio usage(EXIT_FAILURE); 3742fc9c5412SJohannes Schauer } 3743fc9c5412SJohannes Schauer } 3744fc9c5412SJohannes Schauer free(r); 3745fc9c5412SJohannes Schauer } 3746fc9c5412SJohannes Schauer 3747fc9c5412SJohannes Schauer static void handle_arg_argv0(const char *arg) 3748fc9c5412SJohannes Schauer { 3749fc9c5412SJohannes Schauer argv0 = strdup(arg); 3750fc9c5412SJohannes Schauer } 3751fc9c5412SJohannes Schauer 3752fc9c5412SJohannes Schauer static void handle_arg_stack_size(const char *arg) 3753fc9c5412SJohannes Schauer { 3754fc9c5412SJohannes Schauer char *p; 3755fc9c5412SJohannes Schauer guest_stack_size = strtoul(arg, &p, 0); 3756fc9c5412SJohannes Schauer if (guest_stack_size == 0) { 37574d1275c2SRiku Voipio usage(EXIT_FAILURE); 3758fc9c5412SJohannes Schauer } 3759fc9c5412SJohannes Schauer 3760fc9c5412SJohannes Schauer if (*p == 'M') { 3761fc9c5412SJohannes Schauer guest_stack_size *= 1024 * 1024; 3762fc9c5412SJohannes Schauer } else if (*p == 'k' || *p == 'K') { 3763fc9c5412SJohannes Schauer guest_stack_size *= 1024; 3764fc9c5412SJohannes Schauer } 3765fc9c5412SJohannes Schauer } 3766fc9c5412SJohannes Schauer 3767fc9c5412SJohannes Schauer static void handle_arg_ld_prefix(const char *arg) 3768fc9c5412SJohannes Schauer { 3769fc9c5412SJohannes Schauer interp_prefix = strdup(arg); 3770fc9c5412SJohannes Schauer } 3771fc9c5412SJohannes Schauer 3772fc9c5412SJohannes Schauer static void handle_arg_pagesize(const char *arg) 3773fc9c5412SJohannes Schauer { 3774fc9c5412SJohannes Schauer qemu_host_page_size = atoi(arg); 3775fc9c5412SJohannes Schauer if (qemu_host_page_size == 0 || 3776fc9c5412SJohannes Schauer (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) { 3777fc9c5412SJohannes Schauer fprintf(stderr, "page size must be a power of two\n"); 37784d1275c2SRiku Voipio exit(EXIT_FAILURE); 3779fc9c5412SJohannes Schauer } 3780fc9c5412SJohannes Schauer } 3781fc9c5412SJohannes Schauer 3782c5e4a5a9SMagnus Reftel static void handle_arg_randseed(const char *arg) 3783c5e4a5a9SMagnus Reftel { 3784c5e4a5a9SMagnus Reftel unsigned long long seed; 3785c5e4a5a9SMagnus Reftel 3786c5e4a5a9SMagnus Reftel if (parse_uint_full(arg, &seed, 0) != 0 || seed > UINT_MAX) { 3787c5e4a5a9SMagnus Reftel fprintf(stderr, "Invalid seed number: %s\n", arg); 37884d1275c2SRiku Voipio exit(EXIT_FAILURE); 3789c5e4a5a9SMagnus Reftel } 3790c5e4a5a9SMagnus Reftel srand(seed); 3791c5e4a5a9SMagnus Reftel } 3792c5e4a5a9SMagnus Reftel 3793fc9c5412SJohannes Schauer static void handle_arg_gdb(const char *arg) 3794fc9c5412SJohannes Schauer { 3795fc9c5412SJohannes Schauer gdbstub_port = atoi(arg); 3796fc9c5412SJohannes Schauer } 3797fc9c5412SJohannes Schauer 3798fc9c5412SJohannes Schauer static void handle_arg_uname(const char *arg) 3799fc9c5412SJohannes Schauer { 3800fc9c5412SJohannes Schauer qemu_uname_release = strdup(arg); 3801fc9c5412SJohannes Schauer } 3802fc9c5412SJohannes Schauer 3803fc9c5412SJohannes Schauer static void handle_arg_cpu(const char *arg) 3804fc9c5412SJohannes Schauer { 3805fc9c5412SJohannes Schauer cpu_model = strdup(arg); 3806c8057f95SPeter Maydell if (cpu_model == NULL || is_help_option(cpu_model)) { 3807fc9c5412SJohannes Schauer /* XXX: implement xxx_cpu_list for targets that still miss it */ 3808e916cbf8SPeter Maydell #if defined(cpu_list) 3809e916cbf8SPeter Maydell cpu_list(stdout, &fprintf); 3810fc9c5412SJohannes Schauer #endif 38114d1275c2SRiku Voipio exit(EXIT_FAILURE); 3812fc9c5412SJohannes Schauer } 3813fc9c5412SJohannes Schauer } 3814fc9c5412SJohannes Schauer 3815fc9c5412SJohannes Schauer static void handle_arg_guest_base(const char *arg) 3816fc9c5412SJohannes Schauer { 3817fc9c5412SJohannes Schauer guest_base = strtol(arg, NULL, 0); 3818fc9c5412SJohannes Schauer have_guest_base = 1; 3819fc9c5412SJohannes Schauer } 3820fc9c5412SJohannes Schauer 3821fc9c5412SJohannes Schauer static void handle_arg_reserved_va(const char *arg) 3822fc9c5412SJohannes Schauer { 3823fc9c5412SJohannes Schauer char *p; 3824fc9c5412SJohannes Schauer int shift = 0; 3825fc9c5412SJohannes Schauer reserved_va = strtoul(arg, &p, 0); 3826fc9c5412SJohannes Schauer switch (*p) { 3827fc9c5412SJohannes Schauer case 'k': 3828fc9c5412SJohannes Schauer case 'K': 3829fc9c5412SJohannes Schauer shift = 10; 3830fc9c5412SJohannes Schauer break; 3831fc9c5412SJohannes Schauer case 'M': 3832fc9c5412SJohannes Schauer shift = 20; 3833fc9c5412SJohannes Schauer break; 3834fc9c5412SJohannes Schauer case 'G': 3835fc9c5412SJohannes Schauer shift = 30; 3836fc9c5412SJohannes Schauer break; 3837fc9c5412SJohannes Schauer } 3838fc9c5412SJohannes Schauer if (shift) { 3839fc9c5412SJohannes Schauer unsigned long unshifted = reserved_va; 3840fc9c5412SJohannes Schauer p++; 3841fc9c5412SJohannes Schauer reserved_va <<= shift; 3842fc9c5412SJohannes Schauer if (((reserved_va >> shift) != unshifted) 3843fc9c5412SJohannes Schauer #if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS 3844fc9c5412SJohannes Schauer || (reserved_va > (1ul << TARGET_VIRT_ADDR_SPACE_BITS)) 3845fc9c5412SJohannes Schauer #endif 3846fc9c5412SJohannes Schauer ) { 3847fc9c5412SJohannes Schauer fprintf(stderr, "Reserved virtual address too big\n"); 38484d1275c2SRiku Voipio exit(EXIT_FAILURE); 3849fc9c5412SJohannes Schauer } 3850fc9c5412SJohannes Schauer } 3851fc9c5412SJohannes Schauer if (*p) { 3852fc9c5412SJohannes Schauer fprintf(stderr, "Unrecognised -R size suffix '%s'\n", p); 38534d1275c2SRiku Voipio exit(EXIT_FAILURE); 3854fc9c5412SJohannes Schauer } 3855fc9c5412SJohannes Schauer } 3856fc9c5412SJohannes Schauer 3857fc9c5412SJohannes Schauer static void handle_arg_singlestep(const char *arg) 3858fc9c5412SJohannes Schauer { 3859fc9c5412SJohannes Schauer singlestep = 1; 3860fc9c5412SJohannes Schauer } 3861fc9c5412SJohannes Schauer 3862fc9c5412SJohannes Schauer static void handle_arg_strace(const char *arg) 3863fc9c5412SJohannes Schauer { 3864fc9c5412SJohannes Schauer do_strace = 1; 3865fc9c5412SJohannes Schauer } 3866fc9c5412SJohannes Schauer 3867fc9c5412SJohannes Schauer static void handle_arg_version(const char *arg) 3868fc9c5412SJohannes Schauer { 38692e59915dSPaolo Bonzini printf("qemu-" TARGET_NAME " version " QEMU_VERSION QEMU_PKGVERSION 3870fc9c5412SJohannes Schauer ", Copyright (c) 2003-2008 Fabrice Bellard\n"); 38714d1275c2SRiku Voipio exit(EXIT_SUCCESS); 3872fc9c5412SJohannes Schauer } 3873fc9c5412SJohannes Schauer 3874fc9c5412SJohannes Schauer struct qemu_argument { 3875fc9c5412SJohannes Schauer const char *argv; 3876fc9c5412SJohannes Schauer const char *env; 3877fc9c5412SJohannes Schauer bool has_arg; 3878fc9c5412SJohannes Schauer void (*handle_opt)(const char *arg); 3879fc9c5412SJohannes Schauer const char *example; 3880fc9c5412SJohannes Schauer const char *help; 3881fc9c5412SJohannes Schauer }; 3882fc9c5412SJohannes Schauer 388342644ceeSJim Meyering static const struct qemu_argument arg_table[] = { 3884fc9c5412SJohannes Schauer {"h", "", false, handle_arg_help, 3885fc9c5412SJohannes Schauer "", "print this help"}, 3886daaf8c8eSMeador Inge {"help", "", false, handle_arg_help, 3887daaf8c8eSMeador Inge "", ""}, 3888fc9c5412SJohannes Schauer {"g", "QEMU_GDB", true, handle_arg_gdb, 3889fc9c5412SJohannes Schauer "port", "wait gdb connection to 'port'"}, 3890fc9c5412SJohannes Schauer {"L", "QEMU_LD_PREFIX", true, handle_arg_ld_prefix, 3891fc9c5412SJohannes Schauer "path", "set the elf interpreter prefix to 'path'"}, 3892fc9c5412SJohannes Schauer {"s", "QEMU_STACK_SIZE", true, handle_arg_stack_size, 3893fc9c5412SJohannes Schauer "size", "set the stack size to 'size' bytes"}, 3894fc9c5412SJohannes Schauer {"cpu", "QEMU_CPU", true, handle_arg_cpu, 3895c8057f95SPeter Maydell "model", "select CPU (-cpu help for list)"}, 3896fc9c5412SJohannes Schauer {"E", "QEMU_SET_ENV", true, handle_arg_set_env, 3897fc9c5412SJohannes Schauer "var=value", "sets targets environment variable (see below)"}, 3898fc9c5412SJohannes Schauer {"U", "QEMU_UNSET_ENV", true, handle_arg_unset_env, 3899fc9c5412SJohannes Schauer "var", "unsets targets environment variable (see below)"}, 3900fc9c5412SJohannes Schauer {"0", "QEMU_ARGV0", true, handle_arg_argv0, 3901fc9c5412SJohannes Schauer "argv0", "forces target process argv[0] to be 'argv0'"}, 3902fc9c5412SJohannes Schauer {"r", "QEMU_UNAME", true, handle_arg_uname, 3903fc9c5412SJohannes Schauer "uname", "set qemu uname release string to 'uname'"}, 3904fc9c5412SJohannes Schauer {"B", "QEMU_GUEST_BASE", true, handle_arg_guest_base, 3905fc9c5412SJohannes Schauer "address", "set guest_base address to 'address'"}, 3906fc9c5412SJohannes Schauer {"R", "QEMU_RESERVED_VA", true, handle_arg_reserved_va, 3907fc9c5412SJohannes Schauer "size", "reserve 'size' bytes for guest virtual address space"}, 3908fc9c5412SJohannes Schauer {"d", "QEMU_LOG", true, handle_arg_log, 3909989b697dSPeter Maydell "item[,...]", "enable logging of specified items " 3910989b697dSPeter Maydell "(use '-d help' for a list of items)"}, 391150171d42S陳韋任 {"D", "QEMU_LOG_FILENAME", true, handle_arg_log_filename, 3912989b697dSPeter Maydell "logfile", "write logs to 'logfile' (default stderr)"}, 3913fc9c5412SJohannes Schauer {"p", "QEMU_PAGESIZE", true, handle_arg_pagesize, 3914fc9c5412SJohannes Schauer "pagesize", "set the host page size to 'pagesize'"}, 3915fc9c5412SJohannes Schauer {"singlestep", "QEMU_SINGLESTEP", false, handle_arg_singlestep, 3916fc9c5412SJohannes Schauer "", "run in singlestep mode"}, 3917fc9c5412SJohannes Schauer {"strace", "QEMU_STRACE", false, handle_arg_strace, 3918fc9c5412SJohannes Schauer "", "log system calls"}, 3919c5e4a5a9SMagnus Reftel {"seed", "QEMU_RAND_SEED", true, handle_arg_randseed, 3920c5e4a5a9SMagnus Reftel "", "Seed for pseudo-random number generator"}, 3921fc9c5412SJohannes Schauer {"version", "QEMU_VERSION", false, handle_arg_version, 39221386d4c0SPeter Maydell "", "display version information and exit"}, 3923fc9c5412SJohannes Schauer {NULL, NULL, false, NULL, NULL, NULL} 3924fc9c5412SJohannes Schauer }; 3925fc9c5412SJohannes Schauer 3926d03f9c32SMeador Inge static void usage(int exitcode) 3927fc9c5412SJohannes Schauer { 392842644ceeSJim Meyering const struct qemu_argument *arginfo; 3929fc9c5412SJohannes Schauer int maxarglen; 3930fc9c5412SJohannes Schauer int maxenvlen; 3931fc9c5412SJohannes Schauer 39322e59915dSPaolo Bonzini printf("usage: qemu-" TARGET_NAME " [options] program [arguments...]\n" 39332e59915dSPaolo Bonzini "Linux CPU emulator (compiled for " TARGET_NAME " emulation)\n" 3934fc9c5412SJohannes Schauer "\n" 3935fc9c5412SJohannes Schauer "Options and associated environment variables:\n" 3936fc9c5412SJohannes Schauer "\n"); 3937fc9c5412SJohannes Schauer 393863ec54d7SPeter Maydell /* Calculate column widths. We must always have at least enough space 393963ec54d7SPeter Maydell * for the column header. 394063ec54d7SPeter Maydell */ 394163ec54d7SPeter Maydell maxarglen = strlen("Argument"); 394263ec54d7SPeter Maydell maxenvlen = strlen("Env-variable"); 3943fc9c5412SJohannes Schauer 3944fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) { 394563ec54d7SPeter Maydell int arglen = strlen(arginfo->argv); 394663ec54d7SPeter Maydell if (arginfo->has_arg) { 394763ec54d7SPeter Maydell arglen += strlen(arginfo->example) + 1; 394863ec54d7SPeter Maydell } 3949fc9c5412SJohannes Schauer if (strlen(arginfo->env) > maxenvlen) { 3950fc9c5412SJohannes Schauer maxenvlen = strlen(arginfo->env); 3951fc9c5412SJohannes Schauer } 395263ec54d7SPeter Maydell if (arglen > maxarglen) { 395363ec54d7SPeter Maydell maxarglen = arglen; 3954fc9c5412SJohannes Schauer } 3955fc9c5412SJohannes Schauer } 3956fc9c5412SJohannes Schauer 395763ec54d7SPeter Maydell printf("%-*s %-*s Description\n", maxarglen+1, "Argument", 395863ec54d7SPeter Maydell maxenvlen, "Env-variable"); 3959fc9c5412SJohannes Schauer 3960fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) { 3961fc9c5412SJohannes Schauer if (arginfo->has_arg) { 3962fc9c5412SJohannes Schauer printf("-%s %-*s %-*s %s\n", arginfo->argv, 396363ec54d7SPeter Maydell (int)(maxarglen - strlen(arginfo->argv) - 1), 396463ec54d7SPeter Maydell arginfo->example, maxenvlen, arginfo->env, arginfo->help); 3965fc9c5412SJohannes Schauer } else { 396663ec54d7SPeter Maydell printf("-%-*s %-*s %s\n", maxarglen, arginfo->argv, 3967fc9c5412SJohannes Schauer maxenvlen, arginfo->env, 3968fc9c5412SJohannes Schauer arginfo->help); 3969fc9c5412SJohannes Schauer } 3970fc9c5412SJohannes Schauer } 3971fc9c5412SJohannes Schauer 3972fc9c5412SJohannes Schauer printf("\n" 3973fc9c5412SJohannes Schauer "Defaults:\n" 3974fc9c5412SJohannes Schauer "QEMU_LD_PREFIX = %s\n" 3975989b697dSPeter Maydell "QEMU_STACK_SIZE = %ld byte\n", 3976fc9c5412SJohannes Schauer interp_prefix, 3977989b697dSPeter Maydell guest_stack_size); 3978fc9c5412SJohannes Schauer 3979fc9c5412SJohannes Schauer printf("\n" 3980fc9c5412SJohannes Schauer "You can use -E and -U options or the QEMU_SET_ENV and\n" 3981fc9c5412SJohannes Schauer "QEMU_UNSET_ENV environment variables to set and unset\n" 3982fc9c5412SJohannes Schauer "environment variables for the target process.\n" 3983fc9c5412SJohannes Schauer "It is possible to provide several variables by separating them\n" 3984fc9c5412SJohannes Schauer "by commas in getsubopt(3) style. Additionally it is possible to\n" 3985fc9c5412SJohannes Schauer "provide the -E and -U options multiple times.\n" 3986fc9c5412SJohannes Schauer "The following lines are equivalent:\n" 3987fc9c5412SJohannes Schauer " -E var1=val2 -E var2=val2 -U LD_PRELOAD -U LD_DEBUG\n" 3988fc9c5412SJohannes Schauer " -E var1=val2,var2=val2 -U LD_PRELOAD,LD_DEBUG\n" 3989fc9c5412SJohannes Schauer " QEMU_SET_ENV=var1=val2,var2=val2 QEMU_UNSET_ENV=LD_PRELOAD,LD_DEBUG\n" 3990fc9c5412SJohannes Schauer "Note that if you provide several changes to a single variable\n" 3991fc9c5412SJohannes Schauer "the last change will stay in effect.\n"); 3992fc9c5412SJohannes Schauer 3993d03f9c32SMeador Inge exit(exitcode); 3994fc9c5412SJohannes Schauer } 3995fc9c5412SJohannes Schauer 3996fc9c5412SJohannes Schauer static int parse_args(int argc, char **argv) 3997fc9c5412SJohannes Schauer { 3998fc9c5412SJohannes Schauer const char *r; 3999fc9c5412SJohannes Schauer int optind; 400042644ceeSJim Meyering const struct qemu_argument *arginfo; 4001fc9c5412SJohannes Schauer 4002fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) { 4003fc9c5412SJohannes Schauer if (arginfo->env == NULL) { 4004fc9c5412SJohannes Schauer continue; 4005fc9c5412SJohannes Schauer } 4006fc9c5412SJohannes Schauer 4007fc9c5412SJohannes Schauer r = getenv(arginfo->env); 4008fc9c5412SJohannes Schauer if (r != NULL) { 4009fc9c5412SJohannes Schauer arginfo->handle_opt(r); 4010fc9c5412SJohannes Schauer } 4011fc9c5412SJohannes Schauer } 4012fc9c5412SJohannes Schauer 4013fc9c5412SJohannes Schauer optind = 1; 4014fc9c5412SJohannes Schauer for (;;) { 4015fc9c5412SJohannes Schauer if (optind >= argc) { 4016fc9c5412SJohannes Schauer break; 4017fc9c5412SJohannes Schauer } 4018fc9c5412SJohannes Schauer r = argv[optind]; 4019fc9c5412SJohannes Schauer if (r[0] != '-') { 4020fc9c5412SJohannes Schauer break; 4021fc9c5412SJohannes Schauer } 4022fc9c5412SJohannes Schauer optind++; 4023fc9c5412SJohannes Schauer r++; 4024fc9c5412SJohannes Schauer if (!strcmp(r, "-")) { 4025fc9c5412SJohannes Schauer break; 4026fc9c5412SJohannes Schauer } 4027*ba02577cSMeador Inge /* Treat --foo the same as -foo. */ 4028*ba02577cSMeador Inge if (r[0] == '-') { 4029*ba02577cSMeador Inge r++; 4030*ba02577cSMeador Inge } 4031fc9c5412SJohannes Schauer 4032fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) { 4033fc9c5412SJohannes Schauer if (!strcmp(r, arginfo->argv)) { 40341386d4c0SPeter Maydell if (arginfo->has_arg) { 4035fc9c5412SJohannes Schauer if (optind >= argc) { 4036138940bfSMeador Inge (void) fprintf(stderr, 4037138940bfSMeador Inge "qemu: missing argument for option '%s'\n", r); 40384d1275c2SRiku Voipio exit(EXIT_FAILURE); 4039fc9c5412SJohannes Schauer } 4040fc9c5412SJohannes Schauer arginfo->handle_opt(argv[optind]); 4041fc9c5412SJohannes Schauer optind++; 40421386d4c0SPeter Maydell } else { 40431386d4c0SPeter Maydell arginfo->handle_opt(NULL); 4044fc9c5412SJohannes Schauer } 4045fc9c5412SJohannes Schauer break; 4046fc9c5412SJohannes Schauer } 4047fc9c5412SJohannes Schauer } 4048fc9c5412SJohannes Schauer 4049fc9c5412SJohannes Schauer /* no option matched the current argv */ 4050fc9c5412SJohannes Schauer if (arginfo->handle_opt == NULL) { 4051138940bfSMeador Inge (void) fprintf(stderr, "qemu: unknown option '%s'\n", r); 40524d1275c2SRiku Voipio exit(EXIT_FAILURE); 4053fc9c5412SJohannes Schauer } 4054fc9c5412SJohannes Schauer } 4055fc9c5412SJohannes Schauer 4056fc9c5412SJohannes Schauer if (optind >= argc) { 4057138940bfSMeador Inge (void) fprintf(stderr, "qemu: no user program specified\n"); 40584d1275c2SRiku Voipio exit(EXIT_FAILURE); 4059fc9c5412SJohannes Schauer } 4060fc9c5412SJohannes Schauer 4061fc9c5412SJohannes Schauer filename = argv[optind]; 4062fc9c5412SJohannes Schauer exec_path = argv[optind]; 4063fc9c5412SJohannes Schauer 4064fc9c5412SJohannes Schauer return optind; 4065fc9c5412SJohannes Schauer } 4066fc9c5412SJohannes Schauer 4067902b3d5cSmalc int main(int argc, char **argv, char **envp) 406831e31b8aSbellard { 406901ffc75bSbellard struct target_pt_regs regs1, *regs = ®s1; 407031e31b8aSbellard struct image_info info1, *info = &info1; 4071edf8e2afSMika Westerberg struct linux_binprm bprm; 407248e15fc2SNathan Froyd TaskState *ts; 40739349b4f9SAndreas Färber CPUArchState *env; 4074db6b81d4SAndreas Färber CPUState *cpu; 4075586314f2Sbellard int optind; 407604a6dfebSaurel32 char **target_environ, **wrk; 40777d8cec95Saurel32 char **target_argv; 40787d8cec95Saurel32 int target_argc; 40797d8cec95Saurel32 int i; 4080fd4d81ddSArnaud Patard int ret; 408103cfd8faSLaurent Vivier int execfd; 408231e31b8aSbellard 4083ce008c1fSAndreas Färber module_call_init(MODULE_INIT_QOM); 4084ce008c1fSAndreas Färber 408504a6dfebSaurel32 if ((envlist = envlist_create()) == NULL) { 408604a6dfebSaurel32 (void) fprintf(stderr, "Unable to allocate envlist\n"); 40874d1275c2SRiku Voipio exit(EXIT_FAILURE); 408804a6dfebSaurel32 } 408904a6dfebSaurel32 409004a6dfebSaurel32 /* add current environment into the list */ 409104a6dfebSaurel32 for (wrk = environ; *wrk != NULL; wrk++) { 409204a6dfebSaurel32 (void) envlist_setenv(envlist, *wrk); 409304a6dfebSaurel32 } 409404a6dfebSaurel32 4095703e0e89SRichard Henderson /* Read the stack limit from the kernel. If it's "unlimited", 4096703e0e89SRichard Henderson then we can do little else besides use the default. */ 4097703e0e89SRichard Henderson { 4098703e0e89SRichard Henderson struct rlimit lim; 4099703e0e89SRichard Henderson if (getrlimit(RLIMIT_STACK, &lim) == 0 410081bbe906Stakasi-y@ops.dti.ne.jp && lim.rlim_cur != RLIM_INFINITY 410181bbe906Stakasi-y@ops.dti.ne.jp && lim.rlim_cur == (target_long)lim.rlim_cur) { 4102703e0e89SRichard Henderson guest_stack_size = lim.rlim_cur; 4103703e0e89SRichard Henderson } 4104703e0e89SRichard Henderson } 4105703e0e89SRichard Henderson 4106b1f9be31Sj_mayer cpu_model = NULL; 4107b5ec5ce0Sjohn cooper #if defined(cpudef_setup) 4108b5ec5ce0Sjohn cooper cpudef_setup(); /* parse cpu definitions in target config file (TBD) */ 4109b5ec5ce0Sjohn cooper #endif 4110b5ec5ce0Sjohn cooper 4111c5e4a5a9SMagnus Reftel srand(time(NULL)); 4112c5e4a5a9SMagnus Reftel 4113fc9c5412SJohannes Schauer optind = parse_args(argc, argv); 41144b5dfd82SPeter Maydell 411531e31b8aSbellard /* Zero out regs */ 411601ffc75bSbellard memset(regs, 0, sizeof(struct target_pt_regs)); 411731e31b8aSbellard 411831e31b8aSbellard /* Zero out image_info */ 411931e31b8aSbellard memset(info, 0, sizeof(struct image_info)); 412031e31b8aSbellard 4121edf8e2afSMika Westerberg memset(&bprm, 0, sizeof (bprm)); 4122edf8e2afSMika Westerberg 412374cd30b8Sbellard /* Scan interp_prefix dir for replacement files. */ 412474cd30b8Sbellard init_paths(interp_prefix); 412574cd30b8Sbellard 41264a24a758SPeter Maydell init_qemu_uname_release(); 41274a24a758SPeter Maydell 412846027c07Sbellard if (cpu_model == NULL) { 4129aaed909aSbellard #if defined(TARGET_I386) 413046027c07Sbellard #ifdef TARGET_X86_64 413146027c07Sbellard cpu_model = "qemu64"; 413246027c07Sbellard #else 413346027c07Sbellard cpu_model = "qemu32"; 413446027c07Sbellard #endif 4135aaed909aSbellard #elif defined(TARGET_ARM) 4136088ab16cSpbrook cpu_model = "any"; 4137d2fbca94SGuan Xuetao #elif defined(TARGET_UNICORE32) 4138d2fbca94SGuan Xuetao cpu_model = "any"; 4139aaed909aSbellard #elif defined(TARGET_M68K) 4140aaed909aSbellard cpu_model = "any"; 4141aaed909aSbellard #elif defined(TARGET_SPARC) 4142aaed909aSbellard #ifdef TARGET_SPARC64 4143aaed909aSbellard cpu_model = "TI UltraSparc II"; 4144aaed909aSbellard #else 4145aaed909aSbellard cpu_model = "Fujitsu MB86904"; 414646027c07Sbellard #endif 4147aaed909aSbellard #elif defined(TARGET_MIPS) 4148aaed909aSbellard #if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) 414974797f40SMaciej W. Rozycki cpu_model = "5KEf"; 4150aaed909aSbellard #else 4151aaed909aSbellard cpu_model = "24Kf"; 4152aaed909aSbellard #endif 4153d962783eSJia Liu #elif defined TARGET_OPENRISC 4154d962783eSJia Liu cpu_model = "or1200"; 4155aaed909aSbellard #elif defined(TARGET_PPC) 41567ded4f52Sbellard # ifdef TARGET_PPC64 4157a74029f6SRichard Henderson cpu_model = "POWER7"; 41587ded4f52Sbellard # else 4159aaed909aSbellard cpu_model = "750"; 41607ded4f52Sbellard # endif 416191c45a38SRichard Henderson #elif defined TARGET_SH4 416291c45a38SRichard Henderson cpu_model = TYPE_SH7785_CPU; 4163aaed909aSbellard #else 4164aaed909aSbellard cpu_model = "any"; 4165aaed909aSbellard #endif 4166aaed909aSbellard } 4167d5ab9713SJan Kiszka tcg_exec_init(0); 416883fb7adfSbellard /* NOTE: we need to init the CPU at this stage to get 416983fb7adfSbellard qemu_host_page_size */ 41702994fd96SEduardo Habkost cpu = cpu_init(cpu_model); 41712994fd96SEduardo Habkost if (!cpu) { 4172aaed909aSbellard fprintf(stderr, "Unable to find CPU definition\n"); 41734d1275c2SRiku Voipio exit(EXIT_FAILURE); 4174aaed909aSbellard } 41752994fd96SEduardo Habkost env = cpu->env_ptr; 41760ac46af3SAndreas Färber cpu_reset(cpu); 4177b55a37c9SBlue Swirl 4178db6b81d4SAndreas Färber thread_cpu = cpu; 417954936004Sbellard 4180b92c47c1Sths if (getenv("QEMU_STRACE")) { 4181b92c47c1Sths do_strace = 1; 4182b92c47c1Sths } 4183b92c47c1Sths 4184c5e4a5a9SMagnus Reftel if (getenv("QEMU_RAND_SEED")) { 4185c5e4a5a9SMagnus Reftel handle_arg_randseed(getenv("QEMU_RAND_SEED")); 4186c5e4a5a9SMagnus Reftel } 4187c5e4a5a9SMagnus Reftel 418804a6dfebSaurel32 target_environ = envlist_to_environ(envlist, NULL); 418904a6dfebSaurel32 envlist_free(envlist); 4190b12b6a18Sths 4191379f6698SPaul Brook /* 4192379f6698SPaul Brook * Now that page sizes are configured in cpu_init() we can do 4193379f6698SPaul Brook * proper page alignment for guest_base. 4194379f6698SPaul Brook */ 4195379f6698SPaul Brook guest_base = HOST_PAGE_ALIGN(guest_base); 419668a1c816SPaul Brook 419797cc7560SDr. David Alan Gilbert if (reserved_va || have_guest_base) { 4198806d1021SMeador Inge guest_base = init_guest_space(guest_base, reserved_va, 0, 4199806d1021SMeador Inge have_guest_base); 4200806d1021SMeador Inge if (guest_base == (unsigned long)-1) { 4201097b8cb8SPeter Maydell fprintf(stderr, "Unable to reserve 0x%lx bytes of virtual address " 4202097b8cb8SPeter Maydell "space for use as guest address space (check your virtual " 4203097b8cb8SPeter Maydell "memory ulimit setting or reserve less using -R option)\n", 4204097b8cb8SPeter Maydell reserved_va); 42054d1275c2SRiku Voipio exit(EXIT_FAILURE); 420697cc7560SDr. David Alan Gilbert } 4207806d1021SMeador Inge 4208806d1021SMeador Inge if (reserved_va) { 4209806d1021SMeador Inge mmap_next_start = reserved_va; 4210806d1021SMeador Inge } 421197cc7560SDr. David Alan Gilbert } 4212379f6698SPaul Brook 4213379f6698SPaul Brook /* 4214379f6698SPaul Brook * Read in mmap_min_addr kernel parameter. This value is used 4215379f6698SPaul Brook * When loading the ELF image to determine whether guest_base 421614f24e14SRichard Henderson * is needed. It is also used in mmap_find_vma. 4217379f6698SPaul Brook */ 421814f24e14SRichard Henderson { 4219379f6698SPaul Brook FILE *fp; 4220379f6698SPaul Brook 4221379f6698SPaul Brook if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) { 4222379f6698SPaul Brook unsigned long tmp; 4223379f6698SPaul Brook if (fscanf(fp, "%lu", &tmp) == 1) { 4224379f6698SPaul Brook mmap_min_addr = tmp; 4225379f6698SPaul Brook qemu_log("host mmap_min_addr=0x%lx\n", mmap_min_addr); 4226379f6698SPaul Brook } 4227379f6698SPaul Brook fclose(fp); 4228379f6698SPaul Brook } 4229379f6698SPaul Brook } 4230379f6698SPaul Brook 42317d8cec95Saurel32 /* 42327d8cec95Saurel32 * Prepare copy of argv vector for target. 42337d8cec95Saurel32 */ 42347d8cec95Saurel32 target_argc = argc - optind; 42357d8cec95Saurel32 target_argv = calloc(target_argc + 1, sizeof (char *)); 42367d8cec95Saurel32 if (target_argv == NULL) { 42377d8cec95Saurel32 (void) fprintf(stderr, "Unable to allocate memory for target_argv\n"); 42384d1275c2SRiku Voipio exit(EXIT_FAILURE); 42397d8cec95Saurel32 } 42407d8cec95Saurel32 42417d8cec95Saurel32 /* 42427d8cec95Saurel32 * If argv0 is specified (using '-0' switch) we replace 42437d8cec95Saurel32 * argv[0] pointer with the given one. 42447d8cec95Saurel32 */ 42457d8cec95Saurel32 i = 0; 42467d8cec95Saurel32 if (argv0 != NULL) { 42477d8cec95Saurel32 target_argv[i++] = strdup(argv0); 42487d8cec95Saurel32 } 42497d8cec95Saurel32 for (; i < target_argc; i++) { 42507d8cec95Saurel32 target_argv[i] = strdup(argv[optind + i]); 42517d8cec95Saurel32 } 42527d8cec95Saurel32 target_argv[target_argc] = NULL; 42537d8cec95Saurel32 42547267c094SAnthony Liguori ts = g_malloc0 (sizeof(TaskState)); 4255edf8e2afSMika Westerberg init_task_state(ts); 4256edf8e2afSMika Westerberg /* build Task State */ 4257edf8e2afSMika Westerberg ts->info = info; 4258edf8e2afSMika Westerberg ts->bprm = &bprm; 42590429a971SAndreas Färber cpu->opaque = ts; 4260edf8e2afSMika Westerberg task_settid(ts); 4261edf8e2afSMika Westerberg 42620b959cf5SRichard Henderson execfd = qemu_getauxval(AT_EXECFD); 42630b959cf5SRichard Henderson if (execfd == 0) { 426403cfd8faSLaurent Vivier execfd = open(filename, O_RDONLY); 426503cfd8faSLaurent Vivier if (execfd < 0) { 42660b959cf5SRichard Henderson printf("Error while loading %s: %s\n", filename, strerror(errno)); 42674d1275c2SRiku Voipio _exit(EXIT_FAILURE); 426803cfd8faSLaurent Vivier } 42690b959cf5SRichard Henderson } 427003cfd8faSLaurent Vivier 427103cfd8faSLaurent Vivier ret = loader_exec(execfd, filename, target_argv, target_environ, regs, 4272fd4d81ddSArnaud Patard info, &bprm); 4273fd4d81ddSArnaud Patard if (ret != 0) { 4274885c1d10SPeter Maydell printf("Error while loading %s: %s\n", filename, strerror(-ret)); 42754d1275c2SRiku Voipio _exit(EXIT_FAILURE); 427631e31b8aSbellard } 427731e31b8aSbellard 4278b12b6a18Sths for (wrk = target_environ; *wrk; wrk++) { 4279b12b6a18Sths free(*wrk); 4280b12b6a18Sths } 4281b12b6a18Sths 4282b12b6a18Sths free(target_environ); 4283b12b6a18Sths 42842e77eac6Sblueswir1 if (qemu_log_enabled()) { 4285379f6698SPaul Brook qemu_log("guest_base 0x%lx\n", guest_base); 428693fcfe39Saliguori log_page_dump(); 428754936004Sbellard 428893fcfe39Saliguori qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk); 428993fcfe39Saliguori qemu_log("end_code 0x" TARGET_ABI_FMT_lx "\n", info->end_code); 429093fcfe39Saliguori qemu_log("start_code 0x" TARGET_ABI_FMT_lx "\n", 42913d177870Sj_mayer info->start_code); 429293fcfe39Saliguori qemu_log("start_data 0x" TARGET_ABI_FMT_lx "\n", 42933d177870Sj_mayer info->start_data); 429493fcfe39Saliguori qemu_log("end_data 0x" TARGET_ABI_FMT_lx "\n", info->end_data); 429593fcfe39Saliguori qemu_log("start_stack 0x" TARGET_ABI_FMT_lx "\n", 42963d177870Sj_mayer info->start_stack); 429793fcfe39Saliguori qemu_log("brk 0x" TARGET_ABI_FMT_lx "\n", info->brk); 429893fcfe39Saliguori qemu_log("entry 0x" TARGET_ABI_FMT_lx "\n", info->entry); 42992e77eac6Sblueswir1 } 430031e31b8aSbellard 430153a5960aSpbrook target_set_brk(info->brk); 430231e31b8aSbellard syscall_init(); 430366fb9763Sbellard signal_init(); 430431e31b8aSbellard 43059002ec79SRichard Henderson /* Now that we've loaded the binary, GUEST_BASE is fixed. Delay 43069002ec79SRichard Henderson generating the prologue until now so that the prologue can take 43079002ec79SRichard Henderson the real value of GUEST_BASE into account. */ 43089002ec79SRichard Henderson tcg_prologue_init(&tcg_ctx); 43099002ec79SRichard Henderson 4310b346ff46Sbellard #if defined(TARGET_I386) 43113802ce26Sbellard env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK; 4312b98dbc90SPaolo Bonzini env->hflags |= HF_PE_MASK | HF_CPL_MASK; 43130514ef2fSEduardo Habkost if (env->features[FEAT_1_EDX] & CPUID_SSE) { 43141bde465eSbellard env->cr[4] |= CR4_OSFXSR_MASK; 43151bde465eSbellard env->hflags |= HF_OSFXSR_MASK; 43161bde465eSbellard } 4317d2fd1af7Sbellard #ifndef TARGET_ABI32 43184dbc422bSbellard /* enable 64 bit mode if possible */ 43190514ef2fSEduardo Habkost if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM)) { 43204dbc422bSbellard fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n"); 43214d1275c2SRiku Voipio exit(EXIT_FAILURE); 43224dbc422bSbellard } 4323d2fd1af7Sbellard env->cr[4] |= CR4_PAE_MASK; 43244dbc422bSbellard env->efer |= MSR_EFER_LMA | MSR_EFER_LME; 4325d2fd1af7Sbellard env->hflags |= HF_LMA_MASK; 4326d2fd1af7Sbellard #endif 43273802ce26Sbellard 4328415e561fSbellard /* flags setup : we activate the IRQs by default as in user mode */ 4329415e561fSbellard env->eflags |= IF_MASK; 4330415e561fSbellard 43316dbad63eSbellard /* linux register setup */ 4332d2fd1af7Sbellard #ifndef TARGET_ABI32 433384409ddbSj_mayer env->regs[R_EAX] = regs->rax; 433484409ddbSj_mayer env->regs[R_EBX] = regs->rbx; 433584409ddbSj_mayer env->regs[R_ECX] = regs->rcx; 433684409ddbSj_mayer env->regs[R_EDX] = regs->rdx; 433784409ddbSj_mayer env->regs[R_ESI] = regs->rsi; 433884409ddbSj_mayer env->regs[R_EDI] = regs->rdi; 433984409ddbSj_mayer env->regs[R_EBP] = regs->rbp; 434084409ddbSj_mayer env->regs[R_ESP] = regs->rsp; 434184409ddbSj_mayer env->eip = regs->rip; 434284409ddbSj_mayer #else 43430ecfa993Sbellard env->regs[R_EAX] = regs->eax; 43440ecfa993Sbellard env->regs[R_EBX] = regs->ebx; 43450ecfa993Sbellard env->regs[R_ECX] = regs->ecx; 43460ecfa993Sbellard env->regs[R_EDX] = regs->edx; 43470ecfa993Sbellard env->regs[R_ESI] = regs->esi; 43480ecfa993Sbellard env->regs[R_EDI] = regs->edi; 43490ecfa993Sbellard env->regs[R_EBP] = regs->ebp; 43500ecfa993Sbellard env->regs[R_ESP] = regs->esp; 4351dab2ed99Sbellard env->eip = regs->eip; 435284409ddbSj_mayer #endif 435331e31b8aSbellard 4354f4beb510Sbellard /* linux interrupt setup */ 4355e441570fSbalrog #ifndef TARGET_ABI32 4356e441570fSbalrog env->idt.limit = 511; 4357e441570fSbalrog #else 4358e441570fSbalrog env->idt.limit = 255; 4359e441570fSbalrog #endif 4360e441570fSbalrog env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1), 4361e441570fSbalrog PROT_READ|PROT_WRITE, 4362e441570fSbalrog MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); 4363e441570fSbalrog idt_table = g2h(env->idt.base); 4364f4beb510Sbellard set_idt(0, 0); 4365f4beb510Sbellard set_idt(1, 0); 4366f4beb510Sbellard set_idt(2, 0); 4367f4beb510Sbellard set_idt(3, 3); 4368f4beb510Sbellard set_idt(4, 3); 4369ec95da6cSbellard set_idt(5, 0); 4370f4beb510Sbellard set_idt(6, 0); 4371f4beb510Sbellard set_idt(7, 0); 4372f4beb510Sbellard set_idt(8, 0); 4373f4beb510Sbellard set_idt(9, 0); 4374f4beb510Sbellard set_idt(10, 0); 4375f4beb510Sbellard set_idt(11, 0); 4376f4beb510Sbellard set_idt(12, 0); 4377f4beb510Sbellard set_idt(13, 0); 4378f4beb510Sbellard set_idt(14, 0); 4379f4beb510Sbellard set_idt(15, 0); 4380f4beb510Sbellard set_idt(16, 0); 4381f4beb510Sbellard set_idt(17, 0); 4382f4beb510Sbellard set_idt(18, 0); 4383f4beb510Sbellard set_idt(19, 0); 4384f4beb510Sbellard set_idt(0x80, 3); 4385f4beb510Sbellard 43866dbad63eSbellard /* linux segment setup */ 43878d18e893Sbellard { 43888d18e893Sbellard uint64_t *gdt_table; 4389e441570fSbalrog env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES, 4390e441570fSbalrog PROT_READ|PROT_WRITE, 4391e441570fSbalrog MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); 43928d18e893Sbellard env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1; 4393e441570fSbalrog gdt_table = g2h(env->gdt.base); 4394d2fd1af7Sbellard #ifdef TARGET_ABI32 4395f4beb510Sbellard write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff, 4396f4beb510Sbellard DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | 4397f4beb510Sbellard (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT)); 4398d2fd1af7Sbellard #else 4399d2fd1af7Sbellard /* 64 bit code segment */ 4400d2fd1af7Sbellard write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff, 4401d2fd1af7Sbellard DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | 4402d2fd1af7Sbellard DESC_L_MASK | 4403d2fd1af7Sbellard (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT)); 4404d2fd1af7Sbellard #endif 4405f4beb510Sbellard write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff, 4406f4beb510Sbellard DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | 4407f4beb510Sbellard (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT)); 44088d18e893Sbellard } 44096dbad63eSbellard cpu_x86_load_seg(env, R_CS, __USER_CS); 4410d2fd1af7Sbellard cpu_x86_load_seg(env, R_SS, __USER_DS); 4411d2fd1af7Sbellard #ifdef TARGET_ABI32 44126dbad63eSbellard cpu_x86_load_seg(env, R_DS, __USER_DS); 44136dbad63eSbellard cpu_x86_load_seg(env, R_ES, __USER_DS); 44146dbad63eSbellard cpu_x86_load_seg(env, R_FS, __USER_DS); 44156dbad63eSbellard cpu_x86_load_seg(env, R_GS, __USER_DS); 4416d6eb40f6Sths /* This hack makes Wine work... */ 4417d6eb40f6Sths env->segs[R_FS].selector = 0; 4418d2fd1af7Sbellard #else 4419d2fd1af7Sbellard cpu_x86_load_seg(env, R_DS, 0); 4420d2fd1af7Sbellard cpu_x86_load_seg(env, R_ES, 0); 4421d2fd1af7Sbellard cpu_x86_load_seg(env, R_FS, 0); 4422d2fd1af7Sbellard cpu_x86_load_seg(env, R_GS, 0); 4423d2fd1af7Sbellard #endif 442499033caeSAlexander Graf #elif defined(TARGET_AARCH64) 442599033caeSAlexander Graf { 442699033caeSAlexander Graf int i; 442799033caeSAlexander Graf 442899033caeSAlexander Graf if (!(arm_feature(env, ARM_FEATURE_AARCH64))) { 442999033caeSAlexander Graf fprintf(stderr, 443099033caeSAlexander Graf "The selected ARM CPU does not support 64 bit mode\n"); 44314d1275c2SRiku Voipio exit(EXIT_FAILURE); 443299033caeSAlexander Graf } 443399033caeSAlexander Graf 443499033caeSAlexander Graf for (i = 0; i < 31; i++) { 443599033caeSAlexander Graf env->xregs[i] = regs->regs[i]; 443699033caeSAlexander Graf } 443799033caeSAlexander Graf env->pc = regs->pc; 443899033caeSAlexander Graf env->xregs[31] = regs->sp; 443999033caeSAlexander Graf } 4440b346ff46Sbellard #elif defined(TARGET_ARM) 4441b346ff46Sbellard { 4442b346ff46Sbellard int i; 4443b5ff1b31Sbellard cpsr_write(env, regs->uregs[16], 0xffffffff); 4444b346ff46Sbellard for(i = 0; i < 16; i++) { 4445b346ff46Sbellard env->regs[i] = regs->uregs[i]; 4446b346ff46Sbellard } 4447d8fd2954SPaul Brook /* Enable BE8. */ 4448d8fd2954SPaul Brook if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4 4449d8fd2954SPaul Brook && (info->elf_flags & EF_ARM_BE8)) { 4450d8fd2954SPaul Brook env->bswap_code = 1; 4451d8fd2954SPaul Brook } 4452b346ff46Sbellard } 4453d2fbca94SGuan Xuetao #elif defined(TARGET_UNICORE32) 4454d2fbca94SGuan Xuetao { 4455d2fbca94SGuan Xuetao int i; 4456d2fbca94SGuan Xuetao cpu_asr_write(env, regs->uregs[32], 0xffffffff); 4457d2fbca94SGuan Xuetao for (i = 0; i < 32; i++) { 4458d2fbca94SGuan Xuetao env->regs[i] = regs->uregs[i]; 4459d2fbca94SGuan Xuetao } 4460d2fbca94SGuan Xuetao } 446193ac68bcSbellard #elif defined(TARGET_SPARC) 4462060366c5Sbellard { 4463060366c5Sbellard int i; 4464060366c5Sbellard env->pc = regs->pc; 4465060366c5Sbellard env->npc = regs->npc; 4466060366c5Sbellard env->y = regs->y; 4467060366c5Sbellard for(i = 0; i < 8; i++) 4468060366c5Sbellard env->gregs[i] = regs->u_regs[i]; 4469060366c5Sbellard for(i = 0; i < 8; i++) 4470060366c5Sbellard env->regwptr[i] = regs->u_regs[i + 8]; 4471060366c5Sbellard } 447267867308Sbellard #elif defined(TARGET_PPC) 447367867308Sbellard { 447467867308Sbellard int i; 44753fc6c082Sbellard 44760411a972Sj_mayer #if defined(TARGET_PPC64) 44770411a972Sj_mayer #if defined(TARGET_ABI32) 44780411a972Sj_mayer env->msr &= ~((target_ulong)1 << MSR_SF); 4479e85e7c6eSj_mayer #else 44800411a972Sj_mayer env->msr |= (target_ulong)1 << MSR_SF; 44810411a972Sj_mayer #endif 448284409ddbSj_mayer #endif 448367867308Sbellard env->nip = regs->nip; 448467867308Sbellard for(i = 0; i < 32; i++) { 448567867308Sbellard env->gpr[i] = regs->gpr[i]; 448667867308Sbellard } 448767867308Sbellard } 4488e6e5906bSpbrook #elif defined(TARGET_M68K) 4489e6e5906bSpbrook { 4490e6e5906bSpbrook env->pc = regs->pc; 4491e6e5906bSpbrook env->dregs[0] = regs->d0; 4492e6e5906bSpbrook env->dregs[1] = regs->d1; 4493e6e5906bSpbrook env->dregs[2] = regs->d2; 4494e6e5906bSpbrook env->dregs[3] = regs->d3; 4495e6e5906bSpbrook env->dregs[4] = regs->d4; 4496e6e5906bSpbrook env->dregs[5] = regs->d5; 4497e6e5906bSpbrook env->dregs[6] = regs->d6; 4498e6e5906bSpbrook env->dregs[7] = regs->d7; 4499e6e5906bSpbrook env->aregs[0] = regs->a0; 4500e6e5906bSpbrook env->aregs[1] = regs->a1; 4501e6e5906bSpbrook env->aregs[2] = regs->a2; 4502e6e5906bSpbrook env->aregs[3] = regs->a3; 4503e6e5906bSpbrook env->aregs[4] = regs->a4; 4504e6e5906bSpbrook env->aregs[5] = regs->a5; 4505e6e5906bSpbrook env->aregs[6] = regs->a6; 4506e6e5906bSpbrook env->aregs[7] = regs->usp; 4507e6e5906bSpbrook env->sr = regs->sr; 4508e6e5906bSpbrook ts->sim_syscalls = 1; 4509e6e5906bSpbrook } 4510b779e29eSEdgar E. Iglesias #elif defined(TARGET_MICROBLAZE) 4511b779e29eSEdgar E. Iglesias { 4512b779e29eSEdgar E. Iglesias env->regs[0] = regs->r0; 4513b779e29eSEdgar E. Iglesias env->regs[1] = regs->r1; 4514b779e29eSEdgar E. Iglesias env->regs[2] = regs->r2; 4515b779e29eSEdgar E. Iglesias env->regs[3] = regs->r3; 4516b779e29eSEdgar E. Iglesias env->regs[4] = regs->r4; 4517b779e29eSEdgar E. Iglesias env->regs[5] = regs->r5; 4518b779e29eSEdgar E. Iglesias env->regs[6] = regs->r6; 4519b779e29eSEdgar E. Iglesias env->regs[7] = regs->r7; 4520b779e29eSEdgar E. Iglesias env->regs[8] = regs->r8; 4521b779e29eSEdgar E. Iglesias env->regs[9] = regs->r9; 4522b779e29eSEdgar E. Iglesias env->regs[10] = regs->r10; 4523b779e29eSEdgar E. Iglesias env->regs[11] = regs->r11; 4524b779e29eSEdgar E. Iglesias env->regs[12] = regs->r12; 4525b779e29eSEdgar E. Iglesias env->regs[13] = regs->r13; 4526b779e29eSEdgar E. Iglesias env->regs[14] = regs->r14; 4527b779e29eSEdgar E. Iglesias env->regs[15] = regs->r15; 4528b779e29eSEdgar E. Iglesias env->regs[16] = regs->r16; 4529b779e29eSEdgar E. Iglesias env->regs[17] = regs->r17; 4530b779e29eSEdgar E. Iglesias env->regs[18] = regs->r18; 4531b779e29eSEdgar E. Iglesias env->regs[19] = regs->r19; 4532b779e29eSEdgar E. Iglesias env->regs[20] = regs->r20; 4533b779e29eSEdgar E. Iglesias env->regs[21] = regs->r21; 4534b779e29eSEdgar E. Iglesias env->regs[22] = regs->r22; 4535b779e29eSEdgar E. Iglesias env->regs[23] = regs->r23; 4536b779e29eSEdgar E. Iglesias env->regs[24] = regs->r24; 4537b779e29eSEdgar E. Iglesias env->regs[25] = regs->r25; 4538b779e29eSEdgar E. Iglesias env->regs[26] = regs->r26; 4539b779e29eSEdgar E. Iglesias env->regs[27] = regs->r27; 4540b779e29eSEdgar E. Iglesias env->regs[28] = regs->r28; 4541b779e29eSEdgar E. Iglesias env->regs[29] = regs->r29; 4542b779e29eSEdgar E. Iglesias env->regs[30] = regs->r30; 4543b779e29eSEdgar E. Iglesias env->regs[31] = regs->r31; 4544b779e29eSEdgar E. Iglesias env->sregs[SR_PC] = regs->pc; 4545b779e29eSEdgar E. Iglesias } 4546048f6b4dSbellard #elif defined(TARGET_MIPS) 4547048f6b4dSbellard { 4548048f6b4dSbellard int i; 4549048f6b4dSbellard 4550048f6b4dSbellard for(i = 0; i < 32; i++) { 4551b5dc7732Sths env->active_tc.gpr[i] = regs->regs[i]; 4552048f6b4dSbellard } 45530fddbbf2SNathan Froyd env->active_tc.PC = regs->cp0_epc & ~(target_ulong)1; 45540fddbbf2SNathan Froyd if (regs->cp0_epc & 1) { 45550fddbbf2SNathan Froyd env->hflags |= MIPS_HFLAG_M16; 45560fddbbf2SNathan Froyd } 4557048f6b4dSbellard } 4558d962783eSJia Liu #elif defined(TARGET_OPENRISC) 4559d962783eSJia Liu { 4560d962783eSJia Liu int i; 4561d962783eSJia Liu 4562d962783eSJia Liu for (i = 0; i < 32; i++) { 4563d962783eSJia Liu env->gpr[i] = regs->gpr[i]; 4564d962783eSJia Liu } 4565d962783eSJia Liu 4566d962783eSJia Liu env->sr = regs->sr; 4567d962783eSJia Liu env->pc = regs->pc; 4568d962783eSJia Liu } 4569fdf9b3e8Sbellard #elif defined(TARGET_SH4) 4570fdf9b3e8Sbellard { 4571fdf9b3e8Sbellard int i; 4572fdf9b3e8Sbellard 4573fdf9b3e8Sbellard for(i = 0; i < 16; i++) { 4574fdf9b3e8Sbellard env->gregs[i] = regs->regs[i]; 4575fdf9b3e8Sbellard } 4576fdf9b3e8Sbellard env->pc = regs->pc; 4577fdf9b3e8Sbellard } 45787a3148a9Sj_mayer #elif defined(TARGET_ALPHA) 45797a3148a9Sj_mayer { 45807a3148a9Sj_mayer int i; 45817a3148a9Sj_mayer 45827a3148a9Sj_mayer for(i = 0; i < 28; i++) { 4583992f48a0Sblueswir1 env->ir[i] = ((abi_ulong *)regs)[i]; 45847a3148a9Sj_mayer } 4585dad081eeSRichard Henderson env->ir[IR_SP] = regs->usp; 45867a3148a9Sj_mayer env->pc = regs->pc; 45877a3148a9Sj_mayer } 458848733d19Sths #elif defined(TARGET_CRIS) 458948733d19Sths { 459048733d19Sths env->regs[0] = regs->r0; 459148733d19Sths env->regs[1] = regs->r1; 459248733d19Sths env->regs[2] = regs->r2; 459348733d19Sths env->regs[3] = regs->r3; 459448733d19Sths env->regs[4] = regs->r4; 459548733d19Sths env->regs[5] = regs->r5; 459648733d19Sths env->regs[6] = regs->r6; 459748733d19Sths env->regs[7] = regs->r7; 459848733d19Sths env->regs[8] = regs->r8; 459948733d19Sths env->regs[9] = regs->r9; 460048733d19Sths env->regs[10] = regs->r10; 460148733d19Sths env->regs[11] = regs->r11; 460248733d19Sths env->regs[12] = regs->r12; 460348733d19Sths env->regs[13] = regs->r13; 460448733d19Sths env->regs[14] = info->start_stack; 460548733d19Sths env->regs[15] = regs->acr; 460648733d19Sths env->pc = regs->erp; 460748733d19Sths } 4608a4c075f1SUlrich Hecht #elif defined(TARGET_S390X) 4609a4c075f1SUlrich Hecht { 4610a4c075f1SUlrich Hecht int i; 4611a4c075f1SUlrich Hecht for (i = 0; i < 16; i++) { 4612a4c075f1SUlrich Hecht env->regs[i] = regs->gprs[i]; 4613a4c075f1SUlrich Hecht } 4614a4c075f1SUlrich Hecht env->psw.mask = regs->psw.mask; 4615a4c075f1SUlrich Hecht env->psw.addr = regs->psw.addr; 4616a4c075f1SUlrich Hecht } 4617b16189b2SChen Gang #elif defined(TARGET_TILEGX) 4618b16189b2SChen Gang { 4619b16189b2SChen Gang int i; 4620b16189b2SChen Gang for (i = 0; i < TILEGX_R_COUNT; i++) { 4621b16189b2SChen Gang env->regs[i] = regs->regs[i]; 4622b16189b2SChen Gang } 4623b16189b2SChen Gang for (i = 0; i < TILEGX_SPR_COUNT; i++) { 4624b16189b2SChen Gang env->spregs[i] = 0; 4625b16189b2SChen Gang } 4626b16189b2SChen Gang env->pc = regs->pc; 4627b16189b2SChen Gang } 4628b346ff46Sbellard #else 4629b346ff46Sbellard #error unsupported target CPU 4630b346ff46Sbellard #endif 463131e31b8aSbellard 4632d2fbca94SGuan Xuetao #if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32) 4633a87295e8Spbrook ts->stack_base = info->start_stack; 4634a87295e8Spbrook ts->heap_base = info->brk; 4635a87295e8Spbrook /* This will be filled in on the first SYS_HEAPINFO call. */ 4636a87295e8Spbrook ts->heap_limit = 0; 4637a87295e8Spbrook #endif 4638a87295e8Spbrook 463974c33bedSbellard if (gdbstub_port) { 4640ff7a981aSPeter Maydell if (gdbserver_start(gdbstub_port) < 0) { 4641ff7a981aSPeter Maydell fprintf(stderr, "qemu: could not open gdbserver on port %d\n", 4642ff7a981aSPeter Maydell gdbstub_port); 46434d1275c2SRiku Voipio exit(EXIT_FAILURE); 4644ff7a981aSPeter Maydell } 4645db6b81d4SAndreas Färber gdb_handlesig(cpu, 0); 46461fddef4bSbellard } 46471b6b029eSbellard cpu_loop(env); 46481b6b029eSbellard /* never exits */ 464931e31b8aSbellard return 0; 465031e31b8aSbellard } 4651