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" 311de7afc9SPaolo Bonzini #include "qemu/cache-utils.h" 322b41f10eSBlue Swirl #include "cpu.h" 339002ec79SRichard Henderson #include "tcg.h" 341de7afc9SPaolo Bonzini #include "qemu/timer.h" 351de7afc9SPaolo Bonzini #include "qemu/envlist.h" 36d8fd2954SPaul Brook #include "elf.h" 3704a6dfebSaurel32 383ef693a0Sbellard #define DEBUG_LOGFILE "/tmp/qemu.log" 39586314f2Sbellard 40d088d664Saurel32 char *exec_path; 41d088d664Saurel32 421b530a6dSaurel32 int singlestep; 43fc9c5412SJohannes Schauer const char *filename; 44fc9c5412SJohannes Schauer const char *argv0; 45fc9c5412SJohannes Schauer int gdbstub_port; 46fc9c5412SJohannes Schauer envlist_t *envlist; 47fc9c5412SJohannes Schauer const char *cpu_model; 48379f6698SPaul Brook unsigned long mmap_min_addr; 4914f24e14SRichard Henderson #if defined(CONFIG_USE_GUEST_BASE) 50379f6698SPaul Brook unsigned long guest_base; 51379f6698SPaul Brook int have_guest_base; 52288e65b9SAlexander Graf #if (TARGET_LONG_BITS == 32) && (HOST_LONG_BITS == 64) 53288e65b9SAlexander Graf /* 54288e65b9SAlexander Graf * When running 32-on-64 we should make sure we can fit all of the possible 55288e65b9SAlexander Graf * guest address space into a contiguous chunk of virtual host memory. 56288e65b9SAlexander Graf * 57288e65b9SAlexander Graf * This way we will never overlap with our own libraries or binaries or stack 58288e65b9SAlexander Graf * or anything else that QEMU maps. 59288e65b9SAlexander Graf */ 60*314992b1SAlexander Graf # ifdef TARGET_MIPS 61*314992b1SAlexander Graf /* MIPS only supports 31 bits of virtual address space for user space */ 62*314992b1SAlexander Graf unsigned long reserved_va = 0x77000000; 63*314992b1SAlexander Graf # else 64288e65b9SAlexander Graf unsigned long reserved_va = 0xf7000000; 65*314992b1SAlexander Graf # endif 66288e65b9SAlexander Graf #else 6768a1c816SPaul Brook unsigned long reserved_va; 68379f6698SPaul Brook #endif 69288e65b9SAlexander Graf #endif 701b530a6dSaurel32 71fc9c5412SJohannes Schauer static void usage(void); 72fc9c5412SJohannes Schauer 737ee2822cSPaolo Bonzini static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX; 74c5937220Spbrook const char *qemu_uname_release = CONFIG_UNAME_RELEASE; 75586314f2Sbellard 769de5e440Sbellard /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so 779de5e440Sbellard we allocate a bigger stack. Need a better solution, for example 789de5e440Sbellard by remapping the process stack directly at the right place */ 79703e0e89SRichard Henderson unsigned long guest_stack_size = 8 * 1024 * 1024UL; 8031e31b8aSbellard 8131e31b8aSbellard void gemu_log(const char *fmt, ...) 8231e31b8aSbellard { 8331e31b8aSbellard va_list ap; 8431e31b8aSbellard 8531e31b8aSbellard va_start(ap, fmt); 8631e31b8aSbellard vfprintf(stderr, fmt, ap); 8731e31b8aSbellard va_end(ap); 8831e31b8aSbellard } 8931e31b8aSbellard 908fcd3692Sblueswir1 #if defined(TARGET_I386) 9105390248SAndreas Färber int cpu_get_pic_interrupt(CPUX86State *env) 9292ccca6aSbellard { 9392ccca6aSbellard return -1; 9492ccca6aSbellard } 958fcd3692Sblueswir1 #endif 9692ccca6aSbellard 972f7bb878SJuan Quintela #if defined(CONFIG_USE_NPTL) 98d5975363Spbrook /***********************************************************/ 99d5975363Spbrook /* Helper routines for implementing atomic operations. */ 100d5975363Spbrook 101d5975363Spbrook /* To implement exclusive operations we force all cpus to syncronise. 102d5975363Spbrook We don't require a full sync, only that no cpus are executing guest code. 103d5975363Spbrook The alternative is to map target atomic ops onto host equivalents, 104d5975363Spbrook which requires quite a lot of per host/target work. */ 105c2764719Spbrook static pthread_mutex_t cpu_list_mutex = PTHREAD_MUTEX_INITIALIZER; 106d5975363Spbrook static pthread_mutex_t exclusive_lock = PTHREAD_MUTEX_INITIALIZER; 107d5975363Spbrook static pthread_cond_t exclusive_cond = PTHREAD_COND_INITIALIZER; 108d5975363Spbrook static pthread_cond_t exclusive_resume = PTHREAD_COND_INITIALIZER; 109d5975363Spbrook static int pending_cpus; 110d5975363Spbrook 111d5975363Spbrook /* Make sure everything is in a consistent state for calling fork(). */ 112d5975363Spbrook void fork_start(void) 113d5975363Spbrook { 114d5975363Spbrook pthread_mutex_lock(&tb_lock); 115d5975363Spbrook pthread_mutex_lock(&exclusive_lock); 116d032d1b4SRiku Voipio mmap_fork_start(); 117d5975363Spbrook } 118d5975363Spbrook 119d5975363Spbrook void fork_end(int child) 120d5975363Spbrook { 121d032d1b4SRiku Voipio mmap_fork_end(child); 122d5975363Spbrook if (child) { 123d5975363Spbrook /* Child processes created by fork() only have a single thread. 124d5975363Spbrook Discard information about the parent threads. */ 125d5975363Spbrook first_cpu = thread_env; 126d5975363Spbrook thread_env->next_cpu = NULL; 127d5975363Spbrook pending_cpus = 0; 128d5975363Spbrook pthread_mutex_init(&exclusive_lock, NULL); 129c2764719Spbrook pthread_mutex_init(&cpu_list_mutex, NULL); 130d5975363Spbrook pthread_cond_init(&exclusive_cond, NULL); 131d5975363Spbrook pthread_cond_init(&exclusive_resume, NULL); 132d5975363Spbrook pthread_mutex_init(&tb_lock, NULL); 1332b1319c8Saurel32 gdbserver_fork(thread_env); 134d5975363Spbrook } else { 135d5975363Spbrook pthread_mutex_unlock(&exclusive_lock); 136d5975363Spbrook pthread_mutex_unlock(&tb_lock); 137d5975363Spbrook } 138d5975363Spbrook } 139d5975363Spbrook 140d5975363Spbrook /* Wait for pending exclusive operations to complete. The exclusive lock 141d5975363Spbrook must be held. */ 142d5975363Spbrook static inline void exclusive_idle(void) 143d5975363Spbrook { 144d5975363Spbrook while (pending_cpus) { 145d5975363Spbrook pthread_cond_wait(&exclusive_resume, &exclusive_lock); 146d5975363Spbrook } 147d5975363Spbrook } 148d5975363Spbrook 149d5975363Spbrook /* Start an exclusive operation. 150d5975363Spbrook Must only be called from outside cpu_arm_exec. */ 151d5975363Spbrook static inline void start_exclusive(void) 152d5975363Spbrook { 1539349b4f9SAndreas Färber CPUArchState *other; 154d5975363Spbrook pthread_mutex_lock(&exclusive_lock); 155d5975363Spbrook exclusive_idle(); 156d5975363Spbrook 157d5975363Spbrook pending_cpus = 1; 158d5975363Spbrook /* Make all other cpus stop executing. */ 159d5975363Spbrook for (other = first_cpu; other; other = other->next_cpu) { 160d5975363Spbrook if (other->running) { 161d5975363Spbrook pending_cpus++; 1623098dba0Saurel32 cpu_exit(other); 163d5975363Spbrook } 164d5975363Spbrook } 165d5975363Spbrook if (pending_cpus > 1) { 166d5975363Spbrook pthread_cond_wait(&exclusive_cond, &exclusive_lock); 167d5975363Spbrook } 168d5975363Spbrook } 169d5975363Spbrook 170d5975363Spbrook /* Finish an exclusive operation. */ 171d5975363Spbrook static inline void end_exclusive(void) 172d5975363Spbrook { 173d5975363Spbrook pending_cpus = 0; 174d5975363Spbrook pthread_cond_broadcast(&exclusive_resume); 175d5975363Spbrook pthread_mutex_unlock(&exclusive_lock); 176d5975363Spbrook } 177d5975363Spbrook 178d5975363Spbrook /* Wait for exclusive ops to finish, and begin cpu execution. */ 1799349b4f9SAndreas Färber static inline void cpu_exec_start(CPUArchState *env) 180d5975363Spbrook { 181d5975363Spbrook pthread_mutex_lock(&exclusive_lock); 182d5975363Spbrook exclusive_idle(); 183d5975363Spbrook env->running = 1; 184d5975363Spbrook pthread_mutex_unlock(&exclusive_lock); 185d5975363Spbrook } 186d5975363Spbrook 187d5975363Spbrook /* Mark cpu as not executing, and release pending exclusive ops. */ 1889349b4f9SAndreas Färber static inline void cpu_exec_end(CPUArchState *env) 189d5975363Spbrook { 190d5975363Spbrook pthread_mutex_lock(&exclusive_lock); 191d5975363Spbrook env->running = 0; 192d5975363Spbrook if (pending_cpus > 1) { 193d5975363Spbrook pending_cpus--; 194d5975363Spbrook if (pending_cpus == 1) { 195d5975363Spbrook pthread_cond_signal(&exclusive_cond); 196d5975363Spbrook } 197d5975363Spbrook } 198d5975363Spbrook exclusive_idle(); 199d5975363Spbrook pthread_mutex_unlock(&exclusive_lock); 200d5975363Spbrook } 201c2764719Spbrook 202c2764719Spbrook void cpu_list_lock(void) 203c2764719Spbrook { 204c2764719Spbrook pthread_mutex_lock(&cpu_list_mutex); 205c2764719Spbrook } 206c2764719Spbrook 207c2764719Spbrook void cpu_list_unlock(void) 208c2764719Spbrook { 209c2764719Spbrook pthread_mutex_unlock(&cpu_list_mutex); 210c2764719Spbrook } 2112f7bb878SJuan Quintela #else /* if !CONFIG_USE_NPTL */ 212d5975363Spbrook /* These are no-ops because we are not threadsafe. */ 2139349b4f9SAndreas Färber static inline void cpu_exec_start(CPUArchState *env) 214d5975363Spbrook { 215d5975363Spbrook } 216d5975363Spbrook 2179349b4f9SAndreas Färber static inline void cpu_exec_end(CPUArchState *env) 218d5975363Spbrook { 219d5975363Spbrook } 220d5975363Spbrook 221d5975363Spbrook static inline void start_exclusive(void) 222d5975363Spbrook { 223d5975363Spbrook } 224d5975363Spbrook 225d5975363Spbrook static inline void end_exclusive(void) 226d5975363Spbrook { 227d5975363Spbrook } 228d5975363Spbrook 229d5975363Spbrook void fork_start(void) 230d5975363Spbrook { 231d5975363Spbrook } 232d5975363Spbrook 233d5975363Spbrook void fork_end(int child) 234d5975363Spbrook { 2352b1319c8Saurel32 if (child) { 2362b1319c8Saurel32 gdbserver_fork(thread_env); 2372b1319c8Saurel32 } 238d5975363Spbrook } 239c2764719Spbrook 240c2764719Spbrook void cpu_list_lock(void) 241c2764719Spbrook { 242c2764719Spbrook } 243c2764719Spbrook 244c2764719Spbrook void cpu_list_unlock(void) 245c2764719Spbrook { 246c2764719Spbrook } 247d5975363Spbrook #endif 248d5975363Spbrook 249d5975363Spbrook 250a541f297Sbellard #ifdef TARGET_I386 251a541f297Sbellard /***********************************************************/ 252a541f297Sbellard /* CPUX86 core interface */ 253a541f297Sbellard 25405390248SAndreas Färber void cpu_smm_update(CPUX86State *env) 25502a1602eSbellard { 25602a1602eSbellard } 25702a1602eSbellard 25828ab0e2eSbellard uint64_t cpu_get_tsc(CPUX86State *env) 25928ab0e2eSbellard { 26028ab0e2eSbellard return cpu_get_real_ticks(); 26128ab0e2eSbellard } 26228ab0e2eSbellard 263f4beb510Sbellard static void write_dt(void *ptr, unsigned long addr, unsigned long limit, 264f4beb510Sbellard int flags) 2656dbad63eSbellard { 266f4beb510Sbellard unsigned int e1, e2; 26753a5960aSpbrook uint32_t *p; 2686dbad63eSbellard e1 = (addr << 16) | (limit & 0xffff); 2696dbad63eSbellard e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000); 270f4beb510Sbellard e2 |= flags; 27153a5960aSpbrook p = ptr; 272d538e8f5Smalc p[0] = tswap32(e1); 273d538e8f5Smalc p[1] = tswap32(e2); 274f4beb510Sbellard } 275f4beb510Sbellard 276e441570fSbalrog static uint64_t *idt_table; 277eb38c52cSblueswir1 #ifdef TARGET_X86_64 278d2fd1af7Sbellard static void set_gate64(void *ptr, unsigned int type, unsigned int dpl, 279d2fd1af7Sbellard uint64_t addr, unsigned int sel) 280d2fd1af7Sbellard { 2814dbc422bSbellard uint32_t *p, e1, e2; 282d2fd1af7Sbellard e1 = (addr & 0xffff) | (sel << 16); 283d2fd1af7Sbellard e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8); 284d2fd1af7Sbellard p = ptr; 2854dbc422bSbellard p[0] = tswap32(e1); 2864dbc422bSbellard p[1] = tswap32(e2); 2874dbc422bSbellard p[2] = tswap32(addr >> 32); 2884dbc422bSbellard p[3] = 0; 289d2fd1af7Sbellard } 290d2fd1af7Sbellard /* only dpl matters as we do only user space emulation */ 291d2fd1af7Sbellard static void set_idt(int n, unsigned int dpl) 292d2fd1af7Sbellard { 293d2fd1af7Sbellard set_gate64(idt_table + n * 2, 0, dpl, 0, 0); 294d2fd1af7Sbellard } 295d2fd1af7Sbellard #else 296f4beb510Sbellard static void set_gate(void *ptr, unsigned int type, unsigned int dpl, 297d2fd1af7Sbellard uint32_t addr, unsigned int sel) 298f4beb510Sbellard { 2994dbc422bSbellard uint32_t *p, e1, e2; 300f4beb510Sbellard e1 = (addr & 0xffff) | (sel << 16); 301f4beb510Sbellard e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8); 30253a5960aSpbrook p = ptr; 3034dbc422bSbellard p[0] = tswap32(e1); 3044dbc422bSbellard p[1] = tswap32(e2); 3056dbad63eSbellard } 3066dbad63eSbellard 307f4beb510Sbellard /* only dpl matters as we do only user space emulation */ 308f4beb510Sbellard static void set_idt(int n, unsigned int dpl) 309f4beb510Sbellard { 310f4beb510Sbellard set_gate(idt_table + n, 0, dpl, 0, 0); 311f4beb510Sbellard } 312d2fd1af7Sbellard #endif 31331e31b8aSbellard 31489e957e7Sbellard void cpu_loop(CPUX86State *env) 315bc8a22ccSbellard { 316bc8a22ccSbellard int trapnr; 317992f48a0Sblueswir1 abi_ulong pc; 318c227f099SAnthony Liguori target_siginfo_t info; 319bc8a22ccSbellard 320bc8a22ccSbellard for(;;) { 321bc8a22ccSbellard trapnr = cpu_x86_exec(env); 322bc8a22ccSbellard switch(trapnr) { 323f4beb510Sbellard case 0x80: 324d2fd1af7Sbellard /* linux syscall from int $0x80 */ 3251b6b029eSbellard env->regs[R_EAX] = do_syscall(env, 3261b6b029eSbellard env->regs[R_EAX], 3271b6b029eSbellard env->regs[R_EBX], 3281b6b029eSbellard env->regs[R_ECX], 3291b6b029eSbellard env->regs[R_EDX], 3301b6b029eSbellard env->regs[R_ESI], 3311b6b029eSbellard env->regs[R_EDI], 3325945cfcbSPeter Maydell env->regs[R_EBP], 3335945cfcbSPeter Maydell 0, 0); 334f4beb510Sbellard break; 335d2fd1af7Sbellard #ifndef TARGET_ABI32 336d2fd1af7Sbellard case EXCP_SYSCALL: 3375ba18547SStefan Weil /* linux syscall from syscall instruction */ 338d2fd1af7Sbellard env->regs[R_EAX] = do_syscall(env, 339d2fd1af7Sbellard env->regs[R_EAX], 340d2fd1af7Sbellard env->regs[R_EDI], 341d2fd1af7Sbellard env->regs[R_ESI], 342d2fd1af7Sbellard env->regs[R_EDX], 343d2fd1af7Sbellard env->regs[10], 344d2fd1af7Sbellard env->regs[8], 3455945cfcbSPeter Maydell env->regs[9], 3465945cfcbSPeter Maydell 0, 0); 347d2fd1af7Sbellard env->eip = env->exception_next_eip; 348d2fd1af7Sbellard break; 349d2fd1af7Sbellard #endif 350f4beb510Sbellard case EXCP0B_NOSEG: 351f4beb510Sbellard case EXCP0C_STACK: 352f4beb510Sbellard info.si_signo = SIGBUS; 353f4beb510Sbellard info.si_errno = 0; 354f4beb510Sbellard info.si_code = TARGET_SI_KERNEL; 355f4beb510Sbellard info._sifields._sigfault._addr = 0; 356624f7979Spbrook queue_signal(env, info.si_signo, &info); 357f4beb510Sbellard break; 358f4beb510Sbellard case EXCP0D_GPF: 359d2fd1af7Sbellard /* XXX: potential problem if ABI32 */ 36084409ddbSj_mayer #ifndef TARGET_X86_64 361f4beb510Sbellard if (env->eflags & VM_MASK) { 362f4beb510Sbellard handle_vm86_fault(env); 36384409ddbSj_mayer } else 36484409ddbSj_mayer #endif 36584409ddbSj_mayer { 3669de5e440Sbellard info.si_signo = SIGSEGV; 3679de5e440Sbellard info.si_errno = 0; 368b689bc57Sbellard info.si_code = TARGET_SI_KERNEL; 3699de5e440Sbellard info._sifields._sigfault._addr = 0; 370624f7979Spbrook queue_signal(env, info.si_signo, &info); 3711b6b029eSbellard } 3721b6b029eSbellard break; 373b689bc57Sbellard case EXCP0E_PAGE: 374b689bc57Sbellard info.si_signo = SIGSEGV; 375b689bc57Sbellard info.si_errno = 0; 376b689bc57Sbellard if (!(env->error_code & 1)) 377b689bc57Sbellard info.si_code = TARGET_SEGV_MAPERR; 378b689bc57Sbellard else 379b689bc57Sbellard info.si_code = TARGET_SEGV_ACCERR; 380970a87a6Sbellard info._sifields._sigfault._addr = env->cr[2]; 381624f7979Spbrook queue_signal(env, info.si_signo, &info); 382b689bc57Sbellard break; 3839de5e440Sbellard case EXCP00_DIVZ: 38484409ddbSj_mayer #ifndef TARGET_X86_64 385bc8a22ccSbellard if (env->eflags & VM_MASK) { 386447db213Sbellard handle_vm86_trap(env, trapnr); 38784409ddbSj_mayer } else 38884409ddbSj_mayer #endif 38984409ddbSj_mayer { 3909de5e440Sbellard /* division by zero */ 3919de5e440Sbellard info.si_signo = SIGFPE; 3929de5e440Sbellard info.si_errno = 0; 3939de5e440Sbellard info.si_code = TARGET_FPE_INTDIV; 3949de5e440Sbellard info._sifields._sigfault._addr = env->eip; 395624f7979Spbrook queue_signal(env, info.si_signo, &info); 396bc8a22ccSbellard } 3979de5e440Sbellard break; 39801df040bSaliguori case EXCP01_DB: 399447db213Sbellard case EXCP03_INT3: 40084409ddbSj_mayer #ifndef TARGET_X86_64 401447db213Sbellard if (env->eflags & VM_MASK) { 402447db213Sbellard handle_vm86_trap(env, trapnr); 40384409ddbSj_mayer } else 40484409ddbSj_mayer #endif 40584409ddbSj_mayer { 406447db213Sbellard info.si_signo = SIGTRAP; 407447db213Sbellard info.si_errno = 0; 40801df040bSaliguori if (trapnr == EXCP01_DB) { 409447db213Sbellard info.si_code = TARGET_TRAP_BRKPT; 410447db213Sbellard info._sifields._sigfault._addr = env->eip; 411447db213Sbellard } else { 412447db213Sbellard info.si_code = TARGET_SI_KERNEL; 413447db213Sbellard info._sifields._sigfault._addr = 0; 414447db213Sbellard } 415624f7979Spbrook queue_signal(env, info.si_signo, &info); 416447db213Sbellard } 417447db213Sbellard break; 4189de5e440Sbellard case EXCP04_INTO: 4199de5e440Sbellard case EXCP05_BOUND: 42084409ddbSj_mayer #ifndef TARGET_X86_64 421bc8a22ccSbellard if (env->eflags & VM_MASK) { 422447db213Sbellard handle_vm86_trap(env, trapnr); 42384409ddbSj_mayer } else 42484409ddbSj_mayer #endif 42584409ddbSj_mayer { 4269de5e440Sbellard info.si_signo = SIGSEGV; 4279de5e440Sbellard info.si_errno = 0; 428b689bc57Sbellard info.si_code = TARGET_SI_KERNEL; 4299de5e440Sbellard info._sifields._sigfault._addr = 0; 430624f7979Spbrook queue_signal(env, info.si_signo, &info); 431bc8a22ccSbellard } 4329de5e440Sbellard break; 4339de5e440Sbellard case EXCP06_ILLOP: 4349de5e440Sbellard info.si_signo = SIGILL; 4359de5e440Sbellard info.si_errno = 0; 4369de5e440Sbellard info.si_code = TARGET_ILL_ILLOPN; 4379de5e440Sbellard info._sifields._sigfault._addr = env->eip; 438624f7979Spbrook queue_signal(env, info.si_signo, &info); 4399de5e440Sbellard break; 4409de5e440Sbellard case EXCP_INTERRUPT: 4419de5e440Sbellard /* just indicate that signals should be handled asap */ 4429de5e440Sbellard break; 4431fddef4bSbellard case EXCP_DEBUG: 4441fddef4bSbellard { 4451fddef4bSbellard int sig; 4461fddef4bSbellard 4471fddef4bSbellard sig = gdb_handlesig (env, TARGET_SIGTRAP); 4481fddef4bSbellard if (sig) 4491fddef4bSbellard { 4501fddef4bSbellard info.si_signo = sig; 4511fddef4bSbellard info.si_errno = 0; 4521fddef4bSbellard info.si_code = TARGET_TRAP_BRKPT; 453624f7979Spbrook queue_signal(env, info.si_signo, &info); 4541fddef4bSbellard } 4551fddef4bSbellard } 4561fddef4bSbellard break; 4571b6b029eSbellard default: 458970a87a6Sbellard pc = env->segs[R_CS].base + env->eip; 459bc8a22ccSbellard fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n", 460bc8a22ccSbellard (long)pc, trapnr); 4611b6b029eSbellard abort(); 4621b6b029eSbellard } 46366fb9763Sbellard process_pending_signals(env); 4641b6b029eSbellard } 4651b6b029eSbellard } 466b346ff46Sbellard #endif 467b346ff46Sbellard 468b346ff46Sbellard #ifdef TARGET_ARM 469b346ff46Sbellard 470d8fd2954SPaul Brook #define get_user_code_u32(x, gaddr, doswap) \ 471d8fd2954SPaul Brook ({ abi_long __r = get_user_u32((x), (gaddr)); \ 472d8fd2954SPaul Brook if (!__r && (doswap)) { \ 473d8fd2954SPaul Brook (x) = bswap32(x); \ 474d8fd2954SPaul Brook } \ 475d8fd2954SPaul Brook __r; \ 476d8fd2954SPaul Brook }) 477d8fd2954SPaul Brook 478d8fd2954SPaul Brook #define get_user_code_u16(x, gaddr, doswap) \ 479d8fd2954SPaul Brook ({ abi_long __r = get_user_u16((x), (gaddr)); \ 480d8fd2954SPaul Brook if (!__r && (doswap)) { \ 481d8fd2954SPaul Brook (x) = bswap16(x); \ 482d8fd2954SPaul Brook } \ 483d8fd2954SPaul Brook __r; \ 484d8fd2954SPaul Brook }) 485d8fd2954SPaul Brook 48697cc7560SDr. David Alan Gilbert /* 48797cc7560SDr. David Alan Gilbert * See the Linux kernel's Documentation/arm/kernel_user_helpers.txt 48897cc7560SDr. David Alan Gilbert * Input: 48997cc7560SDr. David Alan Gilbert * r0 = pointer to oldval 49097cc7560SDr. David Alan Gilbert * r1 = pointer to newval 49197cc7560SDr. David Alan Gilbert * r2 = pointer to target value 49297cc7560SDr. David Alan Gilbert * 49397cc7560SDr. David Alan Gilbert * Output: 49497cc7560SDr. David Alan Gilbert * r0 = 0 if *ptr was changed, non-0 if no exchange happened 49597cc7560SDr. David Alan Gilbert * C set if *ptr was changed, clear if no exchange happened 49697cc7560SDr. David Alan Gilbert * 49797cc7560SDr. David Alan Gilbert * Note segv's in kernel helpers are a bit tricky, we can set the 49897cc7560SDr. David Alan Gilbert * data address sensibly but the PC address is just the entry point. 49997cc7560SDr. David Alan Gilbert */ 50097cc7560SDr. David Alan Gilbert static void arm_kernel_cmpxchg64_helper(CPUARMState *env) 50197cc7560SDr. David Alan Gilbert { 50297cc7560SDr. David Alan Gilbert uint64_t oldval, newval, val; 50397cc7560SDr. David Alan Gilbert uint32_t addr, cpsr; 50497cc7560SDr. David Alan Gilbert target_siginfo_t info; 50597cc7560SDr. David Alan Gilbert 50697cc7560SDr. David Alan Gilbert /* Based on the 32 bit code in do_kernel_trap */ 50797cc7560SDr. David Alan Gilbert 50897cc7560SDr. David Alan Gilbert /* XXX: This only works between threads, not between processes. 50997cc7560SDr. David Alan Gilbert It's probably possible to implement this with native host 51097cc7560SDr. David Alan Gilbert operations. However things like ldrex/strex are much harder so 51197cc7560SDr. David Alan Gilbert there's not much point trying. */ 51297cc7560SDr. David Alan Gilbert start_exclusive(); 51397cc7560SDr. David Alan Gilbert cpsr = cpsr_read(env); 51497cc7560SDr. David Alan Gilbert addr = env->regs[2]; 51597cc7560SDr. David Alan Gilbert 51697cc7560SDr. David Alan Gilbert if (get_user_u64(oldval, env->regs[0])) { 51797cc7560SDr. David Alan Gilbert env->cp15.c6_data = env->regs[0]; 51897cc7560SDr. David Alan Gilbert goto segv; 51997cc7560SDr. David Alan Gilbert }; 52097cc7560SDr. David Alan Gilbert 52197cc7560SDr. David Alan Gilbert if (get_user_u64(newval, env->regs[1])) { 52297cc7560SDr. David Alan Gilbert env->cp15.c6_data = env->regs[1]; 52397cc7560SDr. David Alan Gilbert goto segv; 52497cc7560SDr. David Alan Gilbert }; 52597cc7560SDr. David Alan Gilbert 52697cc7560SDr. David Alan Gilbert if (get_user_u64(val, addr)) { 52797cc7560SDr. David Alan Gilbert env->cp15.c6_data = addr; 52897cc7560SDr. David Alan Gilbert goto segv; 52997cc7560SDr. David Alan Gilbert } 53097cc7560SDr. David Alan Gilbert 53197cc7560SDr. David Alan Gilbert if (val == oldval) { 53297cc7560SDr. David Alan Gilbert val = newval; 53397cc7560SDr. David Alan Gilbert 53497cc7560SDr. David Alan Gilbert if (put_user_u64(val, addr)) { 53597cc7560SDr. David Alan Gilbert env->cp15.c6_data = addr; 53697cc7560SDr. David Alan Gilbert goto segv; 53797cc7560SDr. David Alan Gilbert }; 53897cc7560SDr. David Alan Gilbert 53997cc7560SDr. David Alan Gilbert env->regs[0] = 0; 54097cc7560SDr. David Alan Gilbert cpsr |= CPSR_C; 54197cc7560SDr. David Alan Gilbert } else { 54297cc7560SDr. David Alan Gilbert env->regs[0] = -1; 54397cc7560SDr. David Alan Gilbert cpsr &= ~CPSR_C; 54497cc7560SDr. David Alan Gilbert } 54597cc7560SDr. David Alan Gilbert cpsr_write(env, cpsr, CPSR_C); 54697cc7560SDr. David Alan Gilbert end_exclusive(); 54797cc7560SDr. David Alan Gilbert return; 54897cc7560SDr. David Alan Gilbert 54997cc7560SDr. David Alan Gilbert segv: 55097cc7560SDr. David Alan Gilbert end_exclusive(); 55197cc7560SDr. David Alan Gilbert /* We get the PC of the entry address - which is as good as anything, 55297cc7560SDr. David Alan Gilbert on a real kernel what you get depends on which mode it uses. */ 55397cc7560SDr. David Alan Gilbert info.si_signo = SIGSEGV; 55497cc7560SDr. David Alan Gilbert info.si_errno = 0; 55597cc7560SDr. David Alan Gilbert /* XXX: check env->error_code */ 55697cc7560SDr. David Alan Gilbert info.si_code = TARGET_SEGV_MAPERR; 55797cc7560SDr. David Alan Gilbert info._sifields._sigfault._addr = env->cp15.c6_data; 55897cc7560SDr. David Alan Gilbert queue_signal(env, info.si_signo, &info); 55997cc7560SDr. David Alan Gilbert 56097cc7560SDr. David Alan Gilbert end_exclusive(); 56197cc7560SDr. David Alan Gilbert } 56297cc7560SDr. David Alan Gilbert 563fbb4a2e3Spbrook /* Handle a jump to the kernel code page. */ 564fbb4a2e3Spbrook static int 565fbb4a2e3Spbrook do_kernel_trap(CPUARMState *env) 566fbb4a2e3Spbrook { 567fbb4a2e3Spbrook uint32_t addr; 568fbb4a2e3Spbrook uint32_t cpsr; 569fbb4a2e3Spbrook uint32_t val; 570fbb4a2e3Spbrook 571fbb4a2e3Spbrook switch (env->regs[15]) { 572fbb4a2e3Spbrook case 0xffff0fa0: /* __kernel_memory_barrier */ 573fbb4a2e3Spbrook /* ??? No-op. Will need to do better for SMP. */ 574fbb4a2e3Spbrook break; 575fbb4a2e3Spbrook case 0xffff0fc0: /* __kernel_cmpxchg */ 576d5975363Spbrook /* XXX: This only works between threads, not between processes. 577d5975363Spbrook It's probably possible to implement this with native host 578d5975363Spbrook operations. However things like ldrex/strex are much harder so 579d5975363Spbrook there's not much point trying. */ 580d5975363Spbrook start_exclusive(); 581fbb4a2e3Spbrook cpsr = cpsr_read(env); 582fbb4a2e3Spbrook addr = env->regs[2]; 583fbb4a2e3Spbrook /* FIXME: This should SEGV if the access fails. */ 584fbb4a2e3Spbrook if (get_user_u32(val, addr)) 585fbb4a2e3Spbrook val = ~env->regs[0]; 586fbb4a2e3Spbrook if (val == env->regs[0]) { 587fbb4a2e3Spbrook val = env->regs[1]; 588fbb4a2e3Spbrook /* FIXME: Check for segfaults. */ 589fbb4a2e3Spbrook put_user_u32(val, addr); 590fbb4a2e3Spbrook env->regs[0] = 0; 591fbb4a2e3Spbrook cpsr |= CPSR_C; 592fbb4a2e3Spbrook } else { 593fbb4a2e3Spbrook env->regs[0] = -1; 594fbb4a2e3Spbrook cpsr &= ~CPSR_C; 595fbb4a2e3Spbrook } 596fbb4a2e3Spbrook cpsr_write(env, cpsr, CPSR_C); 597d5975363Spbrook end_exclusive(); 598fbb4a2e3Spbrook break; 599fbb4a2e3Spbrook case 0xffff0fe0: /* __kernel_get_tls */ 600fbb4a2e3Spbrook env->regs[0] = env->cp15.c13_tls2; 601fbb4a2e3Spbrook break; 60297cc7560SDr. David Alan Gilbert case 0xffff0f60: /* __kernel_cmpxchg64 */ 60397cc7560SDr. David Alan Gilbert arm_kernel_cmpxchg64_helper(env); 60497cc7560SDr. David Alan Gilbert break; 60597cc7560SDr. David Alan Gilbert 606fbb4a2e3Spbrook default: 607fbb4a2e3Spbrook return 1; 608fbb4a2e3Spbrook } 609fbb4a2e3Spbrook /* Jump back to the caller. */ 610fbb4a2e3Spbrook addr = env->regs[14]; 611fbb4a2e3Spbrook if (addr & 1) { 612fbb4a2e3Spbrook env->thumb = 1; 613fbb4a2e3Spbrook addr &= ~1; 614fbb4a2e3Spbrook } 615fbb4a2e3Spbrook env->regs[15] = addr; 616fbb4a2e3Spbrook 617fbb4a2e3Spbrook return 0; 618fbb4a2e3Spbrook } 619fbb4a2e3Spbrook 620426f5abcSPaul Brook static int do_strex(CPUARMState *env) 621426f5abcSPaul Brook { 622426f5abcSPaul Brook uint32_t val; 623426f5abcSPaul Brook int size; 624426f5abcSPaul Brook int rc = 1; 625426f5abcSPaul Brook int segv = 0; 626426f5abcSPaul Brook uint32_t addr; 627426f5abcSPaul Brook start_exclusive(); 628426f5abcSPaul Brook addr = env->exclusive_addr; 629426f5abcSPaul Brook if (addr != env->exclusive_test) { 630426f5abcSPaul Brook goto fail; 631426f5abcSPaul Brook } 632426f5abcSPaul Brook size = env->exclusive_info & 0xf; 633426f5abcSPaul Brook switch (size) { 634426f5abcSPaul Brook case 0: 635426f5abcSPaul Brook segv = get_user_u8(val, addr); 636426f5abcSPaul Brook break; 637426f5abcSPaul Brook case 1: 638426f5abcSPaul Brook segv = get_user_u16(val, addr); 639426f5abcSPaul Brook break; 640426f5abcSPaul Brook case 2: 641426f5abcSPaul Brook case 3: 642426f5abcSPaul Brook segv = get_user_u32(val, addr); 643426f5abcSPaul Brook break; 644f7001a3bSAurelien Jarno default: 645f7001a3bSAurelien Jarno abort(); 646426f5abcSPaul Brook } 647426f5abcSPaul Brook if (segv) { 648426f5abcSPaul Brook env->cp15.c6_data = addr; 649426f5abcSPaul Brook goto done; 650426f5abcSPaul Brook } 651426f5abcSPaul Brook if (val != env->exclusive_val) { 652426f5abcSPaul Brook goto fail; 653426f5abcSPaul Brook } 654426f5abcSPaul Brook if (size == 3) { 655426f5abcSPaul Brook segv = get_user_u32(val, addr + 4); 656426f5abcSPaul Brook if (segv) { 657426f5abcSPaul Brook env->cp15.c6_data = addr + 4; 658426f5abcSPaul Brook goto done; 659426f5abcSPaul Brook } 660426f5abcSPaul Brook if (val != env->exclusive_high) { 661426f5abcSPaul Brook goto fail; 662426f5abcSPaul Brook } 663426f5abcSPaul Brook } 664426f5abcSPaul Brook val = env->regs[(env->exclusive_info >> 8) & 0xf]; 665426f5abcSPaul Brook switch (size) { 666426f5abcSPaul Brook case 0: 667426f5abcSPaul Brook segv = put_user_u8(val, addr); 668426f5abcSPaul Brook break; 669426f5abcSPaul Brook case 1: 670426f5abcSPaul Brook segv = put_user_u16(val, addr); 671426f5abcSPaul Brook break; 672426f5abcSPaul Brook case 2: 673426f5abcSPaul Brook case 3: 674426f5abcSPaul Brook segv = put_user_u32(val, addr); 675426f5abcSPaul Brook break; 676426f5abcSPaul Brook } 677426f5abcSPaul Brook if (segv) { 678426f5abcSPaul Brook env->cp15.c6_data = addr; 679426f5abcSPaul Brook goto done; 680426f5abcSPaul Brook } 681426f5abcSPaul Brook if (size == 3) { 682426f5abcSPaul Brook val = env->regs[(env->exclusive_info >> 12) & 0xf]; 6832c9adbdaSPeter Maydell segv = put_user_u32(val, addr + 4); 684426f5abcSPaul Brook if (segv) { 685426f5abcSPaul Brook env->cp15.c6_data = addr + 4; 686426f5abcSPaul Brook goto done; 687426f5abcSPaul Brook } 688426f5abcSPaul Brook } 689426f5abcSPaul Brook rc = 0; 690426f5abcSPaul Brook fail: 691725b8a69SPaul Brook env->regs[15] += 4; 692426f5abcSPaul Brook env->regs[(env->exclusive_info >> 4) & 0xf] = rc; 693426f5abcSPaul Brook done: 694426f5abcSPaul Brook end_exclusive(); 695426f5abcSPaul Brook return segv; 696426f5abcSPaul Brook } 697426f5abcSPaul Brook 698b346ff46Sbellard void cpu_loop(CPUARMState *env) 699b346ff46Sbellard { 700b346ff46Sbellard int trapnr; 701b346ff46Sbellard unsigned int n, insn; 702c227f099SAnthony Liguori target_siginfo_t info; 703b5ff1b31Sbellard uint32_t addr; 704b346ff46Sbellard 705b346ff46Sbellard for(;;) { 706d5975363Spbrook cpu_exec_start(env); 707b346ff46Sbellard trapnr = cpu_arm_exec(env); 708d5975363Spbrook cpu_exec_end(env); 709b346ff46Sbellard switch(trapnr) { 710b346ff46Sbellard case EXCP_UDEF: 711c6981055Sbellard { 712c6981055Sbellard TaskState *ts = env->opaque; 713c6981055Sbellard uint32_t opcode; 7146d9a42beSaurel32 int rc; 715c6981055Sbellard 716c6981055Sbellard /* we handle the FPU emulation here, as Linux */ 717c6981055Sbellard /* we get the opcode */ 7182f619698Sbellard /* FIXME - what to do if get_user() fails? */ 719d8fd2954SPaul Brook get_user_code_u32(opcode, env->regs[15], env->bswap_code); 720c6981055Sbellard 7216d9a42beSaurel32 rc = EmulateAll(opcode, &ts->fpa, env); 7226d9a42beSaurel32 if (rc == 0) { /* illegal instruction */ 723b346ff46Sbellard info.si_signo = SIGILL; 724b346ff46Sbellard info.si_errno = 0; 725b346ff46Sbellard info.si_code = TARGET_ILL_ILLOPN; 726b346ff46Sbellard info._sifields._sigfault._addr = env->regs[15]; 727624f7979Spbrook queue_signal(env, info.si_signo, &info); 7286d9a42beSaurel32 } else if (rc < 0) { /* FP exception */ 7296d9a42beSaurel32 int arm_fpe=0; 7306d9a42beSaurel32 7316d9a42beSaurel32 /* translate softfloat flags to FPSR flags */ 7326d9a42beSaurel32 if (-rc & float_flag_invalid) 7336d9a42beSaurel32 arm_fpe |= BIT_IOC; 7346d9a42beSaurel32 if (-rc & float_flag_divbyzero) 7356d9a42beSaurel32 arm_fpe |= BIT_DZC; 7366d9a42beSaurel32 if (-rc & float_flag_overflow) 7376d9a42beSaurel32 arm_fpe |= BIT_OFC; 7386d9a42beSaurel32 if (-rc & float_flag_underflow) 7396d9a42beSaurel32 arm_fpe |= BIT_UFC; 7406d9a42beSaurel32 if (-rc & float_flag_inexact) 7416d9a42beSaurel32 arm_fpe |= BIT_IXC; 7426d9a42beSaurel32 7436d9a42beSaurel32 FPSR fpsr = ts->fpa.fpsr; 7446d9a42beSaurel32 //printf("fpsr 0x%x, arm_fpe 0x%x\n",fpsr,arm_fpe); 7456d9a42beSaurel32 7466d9a42beSaurel32 if (fpsr & (arm_fpe << 16)) { /* exception enabled? */ 7476d9a42beSaurel32 info.si_signo = SIGFPE; 7486d9a42beSaurel32 info.si_errno = 0; 7496d9a42beSaurel32 7506d9a42beSaurel32 /* ordered by priority, least first */ 7516d9a42beSaurel32 if (arm_fpe & BIT_IXC) info.si_code = TARGET_FPE_FLTRES; 7526d9a42beSaurel32 if (arm_fpe & BIT_UFC) info.si_code = TARGET_FPE_FLTUND; 7536d9a42beSaurel32 if (arm_fpe & BIT_OFC) info.si_code = TARGET_FPE_FLTOVF; 7546d9a42beSaurel32 if (arm_fpe & BIT_DZC) info.si_code = TARGET_FPE_FLTDIV; 7556d9a42beSaurel32 if (arm_fpe & BIT_IOC) info.si_code = TARGET_FPE_FLTINV; 7566d9a42beSaurel32 7576d9a42beSaurel32 info._sifields._sigfault._addr = env->regs[15]; 758624f7979Spbrook queue_signal(env, info.si_signo, &info); 759c6981055Sbellard } else { 7606d9a42beSaurel32 env->regs[15] += 4; 7616d9a42beSaurel32 } 7626d9a42beSaurel32 7636d9a42beSaurel32 /* accumulate unenabled exceptions */ 7646d9a42beSaurel32 if ((!(fpsr & BIT_IXE)) && (arm_fpe & BIT_IXC)) 7656d9a42beSaurel32 fpsr |= BIT_IXC; 7666d9a42beSaurel32 if ((!(fpsr & BIT_UFE)) && (arm_fpe & BIT_UFC)) 7676d9a42beSaurel32 fpsr |= BIT_UFC; 7686d9a42beSaurel32 if ((!(fpsr & BIT_OFE)) && (arm_fpe & BIT_OFC)) 7696d9a42beSaurel32 fpsr |= BIT_OFC; 7706d9a42beSaurel32 if ((!(fpsr & BIT_DZE)) && (arm_fpe & BIT_DZC)) 7716d9a42beSaurel32 fpsr |= BIT_DZC; 7726d9a42beSaurel32 if ((!(fpsr & BIT_IOE)) && (arm_fpe & BIT_IOC)) 7736d9a42beSaurel32 fpsr |= BIT_IOC; 7746d9a42beSaurel32 ts->fpa.fpsr=fpsr; 7756d9a42beSaurel32 } else { /* everything OK */ 776c6981055Sbellard /* increment PC */ 777c6981055Sbellard env->regs[15] += 4; 778c6981055Sbellard } 779c6981055Sbellard } 780b346ff46Sbellard break; 781b346ff46Sbellard case EXCP_SWI: 78206c949e6Spbrook case EXCP_BKPT: 783b346ff46Sbellard { 784ce4defa0Spbrook env->eabi = 1; 785b346ff46Sbellard /* system call */ 78606c949e6Spbrook if (trapnr == EXCP_BKPT) { 78706c949e6Spbrook if (env->thumb) { 7882f619698Sbellard /* FIXME - what to do if get_user() fails? */ 789d8fd2954SPaul Brook get_user_code_u16(insn, env->regs[15], env->bswap_code); 79006c949e6Spbrook n = insn & 0xff; 79106c949e6Spbrook env->regs[15] += 2; 79206c949e6Spbrook } else { 7932f619698Sbellard /* FIXME - what to do if get_user() fails? */ 794d8fd2954SPaul Brook get_user_code_u32(insn, env->regs[15], env->bswap_code); 79506c949e6Spbrook n = (insn & 0xf) | ((insn >> 4) & 0xff0); 79606c949e6Spbrook env->regs[15] += 4; 79706c949e6Spbrook } 79806c949e6Spbrook } else { 799192c7bd9Sbellard if (env->thumb) { 8002f619698Sbellard /* FIXME - what to do if get_user() fails? */ 801d8fd2954SPaul Brook get_user_code_u16(insn, env->regs[15] - 2, 802d8fd2954SPaul Brook env->bswap_code); 803192c7bd9Sbellard n = insn & 0xff; 804192c7bd9Sbellard } else { 8052f619698Sbellard /* FIXME - what to do if get_user() fails? */ 806d8fd2954SPaul Brook get_user_code_u32(insn, env->regs[15] - 4, 807d8fd2954SPaul Brook env->bswap_code); 808b346ff46Sbellard n = insn & 0xffffff; 809192c7bd9Sbellard } 81006c949e6Spbrook } 811192c7bd9Sbellard 8126f1f31c0Sbellard if (n == ARM_NR_cacheflush) { 813dcfd14b3SBlue Swirl /* nop */ 814a4f81979Sbellard } else if (n == ARM_NR_semihosting 815a4f81979Sbellard || n == ARM_NR_thumb_semihosting) { 816a4f81979Sbellard env->regs[0] = do_arm_semihosting (env); 8173a1363acSAlexander Graf } else if (n == 0 || n >= ARM_SYSCALL_BASE || env->thumb) { 818b346ff46Sbellard /* linux syscall */ 819ce4defa0Spbrook if (env->thumb || n == 0) { 820192c7bd9Sbellard n = env->regs[7]; 821192c7bd9Sbellard } else { 822b346ff46Sbellard n -= ARM_SYSCALL_BASE; 823ce4defa0Spbrook env->eabi = 0; 824192c7bd9Sbellard } 825fbb4a2e3Spbrook if ( n > ARM_NR_BASE) { 826fbb4a2e3Spbrook switch (n) { 827fbb4a2e3Spbrook case ARM_NR_cacheflush: 828dcfd14b3SBlue Swirl /* nop */ 829fbb4a2e3Spbrook break; 830fbb4a2e3Spbrook case ARM_NR_set_tls: 831fbb4a2e3Spbrook cpu_set_tls(env, env->regs[0]); 832fbb4a2e3Spbrook env->regs[0] = 0; 833fbb4a2e3Spbrook break; 834fbb4a2e3Spbrook default: 835fbb4a2e3Spbrook gemu_log("qemu: Unsupported ARM syscall: 0x%x\n", 836fbb4a2e3Spbrook n); 837fbb4a2e3Spbrook env->regs[0] = -TARGET_ENOSYS; 838fbb4a2e3Spbrook break; 839fbb4a2e3Spbrook } 840fbb4a2e3Spbrook } else { 841b346ff46Sbellard env->regs[0] = do_syscall(env, 842b346ff46Sbellard n, 843b346ff46Sbellard env->regs[0], 844b346ff46Sbellard env->regs[1], 845b346ff46Sbellard env->regs[2], 846b346ff46Sbellard env->regs[3], 847b346ff46Sbellard env->regs[4], 8485945cfcbSPeter Maydell env->regs[5], 8495945cfcbSPeter Maydell 0, 0); 850fbb4a2e3Spbrook } 851b346ff46Sbellard } else { 852b346ff46Sbellard goto error; 853b346ff46Sbellard } 854b346ff46Sbellard } 855b346ff46Sbellard break; 85643fff238Sbellard case EXCP_INTERRUPT: 85743fff238Sbellard /* just indicate that signals should be handled asap */ 85843fff238Sbellard break; 85968016c62Sbellard case EXCP_PREFETCH_ABORT: 860eae473c1Sbalrog addr = env->cp15.c6_insn; 861b5ff1b31Sbellard goto do_segv; 86268016c62Sbellard case EXCP_DATA_ABORT: 863eae473c1Sbalrog addr = env->cp15.c6_data; 864b5ff1b31Sbellard do_segv: 86568016c62Sbellard { 86668016c62Sbellard info.si_signo = SIGSEGV; 86768016c62Sbellard info.si_errno = 0; 86868016c62Sbellard /* XXX: check env->error_code */ 86968016c62Sbellard info.si_code = TARGET_SEGV_MAPERR; 870b5ff1b31Sbellard info._sifields._sigfault._addr = addr; 871624f7979Spbrook queue_signal(env, info.si_signo, &info); 87268016c62Sbellard } 87368016c62Sbellard break; 8741fddef4bSbellard case EXCP_DEBUG: 8751fddef4bSbellard { 8761fddef4bSbellard int sig; 8771fddef4bSbellard 8781fddef4bSbellard sig = gdb_handlesig (env, TARGET_SIGTRAP); 8791fddef4bSbellard if (sig) 8801fddef4bSbellard { 8811fddef4bSbellard info.si_signo = sig; 8821fddef4bSbellard info.si_errno = 0; 8831fddef4bSbellard info.si_code = TARGET_TRAP_BRKPT; 884624f7979Spbrook queue_signal(env, info.si_signo, &info); 8851fddef4bSbellard } 8861fddef4bSbellard } 8871fddef4bSbellard break; 888fbb4a2e3Spbrook case EXCP_KERNEL_TRAP: 889fbb4a2e3Spbrook if (do_kernel_trap(env)) 890fbb4a2e3Spbrook goto error; 891fbb4a2e3Spbrook break; 892426f5abcSPaul Brook case EXCP_STREX: 893426f5abcSPaul Brook if (do_strex(env)) { 894426f5abcSPaul Brook addr = env->cp15.c6_data; 895426f5abcSPaul Brook goto do_segv; 896426f5abcSPaul Brook } 897e9273455SPaul Brook break; 898b346ff46Sbellard default: 899b346ff46Sbellard error: 900b346ff46Sbellard fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", 901b346ff46Sbellard trapnr); 9027fe48483Sbellard cpu_dump_state(env, stderr, fprintf, 0); 903b346ff46Sbellard abort(); 904b346ff46Sbellard } 905b346ff46Sbellard process_pending_signals(env); 906b346ff46Sbellard } 907b346ff46Sbellard } 908b346ff46Sbellard 909b346ff46Sbellard #endif 9101b6b029eSbellard 911d2fbca94SGuan Xuetao #ifdef TARGET_UNICORE32 912d2fbca94SGuan Xuetao 91305390248SAndreas Färber void cpu_loop(CPUUniCore32State *env) 914d2fbca94SGuan Xuetao { 915d2fbca94SGuan Xuetao int trapnr; 916d2fbca94SGuan Xuetao unsigned int n, insn; 917d2fbca94SGuan Xuetao target_siginfo_t info; 918d2fbca94SGuan Xuetao 919d2fbca94SGuan Xuetao for (;;) { 920d2fbca94SGuan Xuetao cpu_exec_start(env); 921d2fbca94SGuan Xuetao trapnr = uc32_cpu_exec(env); 922d2fbca94SGuan Xuetao cpu_exec_end(env); 923d2fbca94SGuan Xuetao switch (trapnr) { 924d2fbca94SGuan Xuetao case UC32_EXCP_PRIV: 925d2fbca94SGuan Xuetao { 926d2fbca94SGuan Xuetao /* system call */ 927d2fbca94SGuan Xuetao get_user_u32(insn, env->regs[31] - 4); 928d2fbca94SGuan Xuetao n = insn & 0xffffff; 929d2fbca94SGuan Xuetao 930d2fbca94SGuan Xuetao if (n >= UC32_SYSCALL_BASE) { 931d2fbca94SGuan Xuetao /* linux syscall */ 932d2fbca94SGuan Xuetao n -= UC32_SYSCALL_BASE; 933d2fbca94SGuan Xuetao if (n == UC32_SYSCALL_NR_set_tls) { 934d2fbca94SGuan Xuetao cpu_set_tls(env, env->regs[0]); 935d2fbca94SGuan Xuetao env->regs[0] = 0; 936d2fbca94SGuan Xuetao } else { 937d2fbca94SGuan Xuetao env->regs[0] = do_syscall(env, 938d2fbca94SGuan Xuetao n, 939d2fbca94SGuan Xuetao env->regs[0], 940d2fbca94SGuan Xuetao env->regs[1], 941d2fbca94SGuan Xuetao env->regs[2], 942d2fbca94SGuan Xuetao env->regs[3], 943d2fbca94SGuan Xuetao env->regs[4], 9445945cfcbSPeter Maydell env->regs[5], 9455945cfcbSPeter Maydell 0, 0); 946d2fbca94SGuan Xuetao } 947d2fbca94SGuan Xuetao } else { 948d2fbca94SGuan Xuetao goto error; 949d2fbca94SGuan Xuetao } 950d2fbca94SGuan Xuetao } 951d2fbca94SGuan Xuetao break; 952d48813ddSGuan Xuetao case UC32_EXCP_DTRAP: 953d48813ddSGuan Xuetao case UC32_EXCP_ITRAP: 954d2fbca94SGuan Xuetao info.si_signo = SIGSEGV; 955d2fbca94SGuan Xuetao info.si_errno = 0; 956d2fbca94SGuan Xuetao /* XXX: check env->error_code */ 957d2fbca94SGuan Xuetao info.si_code = TARGET_SEGV_MAPERR; 958d2fbca94SGuan Xuetao info._sifields._sigfault._addr = env->cp0.c4_faultaddr; 959d2fbca94SGuan Xuetao queue_signal(env, info.si_signo, &info); 960d2fbca94SGuan Xuetao break; 961d2fbca94SGuan Xuetao case EXCP_INTERRUPT: 962d2fbca94SGuan Xuetao /* just indicate that signals should be handled asap */ 963d2fbca94SGuan Xuetao break; 964d2fbca94SGuan Xuetao case EXCP_DEBUG: 965d2fbca94SGuan Xuetao { 966d2fbca94SGuan Xuetao int sig; 967d2fbca94SGuan Xuetao 968d2fbca94SGuan Xuetao sig = gdb_handlesig(env, TARGET_SIGTRAP); 969d2fbca94SGuan Xuetao if (sig) { 970d2fbca94SGuan Xuetao info.si_signo = sig; 971d2fbca94SGuan Xuetao info.si_errno = 0; 972d2fbca94SGuan Xuetao info.si_code = TARGET_TRAP_BRKPT; 973d2fbca94SGuan Xuetao queue_signal(env, info.si_signo, &info); 974d2fbca94SGuan Xuetao } 975d2fbca94SGuan Xuetao } 976d2fbca94SGuan Xuetao break; 977d2fbca94SGuan Xuetao default: 978d2fbca94SGuan Xuetao goto error; 979d2fbca94SGuan Xuetao } 980d2fbca94SGuan Xuetao process_pending_signals(env); 981d2fbca94SGuan Xuetao } 982d2fbca94SGuan Xuetao 983d2fbca94SGuan Xuetao error: 984d2fbca94SGuan Xuetao fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr); 985d2fbca94SGuan Xuetao cpu_dump_state(env, stderr, fprintf, 0); 986d2fbca94SGuan Xuetao abort(); 987d2fbca94SGuan Xuetao } 988d2fbca94SGuan Xuetao #endif 989d2fbca94SGuan Xuetao 99093ac68bcSbellard #ifdef TARGET_SPARC 991ed23fbd9Sblueswir1 #define SPARC64_STACK_BIAS 2047 99293ac68bcSbellard 993060366c5Sbellard //#define DEBUG_WIN 994060366c5Sbellard 9952623cbafSbellard /* WARNING: dealing with register windows _is_ complicated. More info 9962623cbafSbellard can be found at http://www.sics.se/~psm/sparcstack.html */ 997060366c5Sbellard static inline int get_reg_index(CPUSPARCState *env, int cwp, int index) 998060366c5Sbellard { 9991a14026eSblueswir1 index = (index + cwp * 16) % (16 * env->nwindows); 1000060366c5Sbellard /* wrap handling : if cwp is on the last window, then we use the 1001060366c5Sbellard registers 'after' the end */ 10021a14026eSblueswir1 if (index < 8 && env->cwp == env->nwindows - 1) 10031a14026eSblueswir1 index += 16 * env->nwindows; 1004060366c5Sbellard return index; 1005060366c5Sbellard } 1006060366c5Sbellard 10072623cbafSbellard /* save the register window 'cwp1' */ 10082623cbafSbellard static inline void save_window_offset(CPUSPARCState *env, int cwp1) 1009060366c5Sbellard { 10102623cbafSbellard unsigned int i; 1011992f48a0Sblueswir1 abi_ulong sp_ptr; 1012060366c5Sbellard 101353a5960aSpbrook sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)]; 1014ed23fbd9Sblueswir1 #ifdef TARGET_SPARC64 1015ed23fbd9Sblueswir1 if (sp_ptr & 3) 1016ed23fbd9Sblueswir1 sp_ptr += SPARC64_STACK_BIAS; 1017ed23fbd9Sblueswir1 #endif 1018060366c5Sbellard #if defined(DEBUG_WIN) 10192daf0284Sblueswir1 printf("win_overflow: sp_ptr=0x" TARGET_ABI_FMT_lx " save_cwp=%d\n", 10202daf0284Sblueswir1 sp_ptr, cwp1); 1021060366c5Sbellard #endif 10222623cbafSbellard for(i = 0; i < 16; i++) { 10232f619698Sbellard /* FIXME - what to do if put_user() fails? */ 10242f619698Sbellard put_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr); 1025992f48a0Sblueswir1 sp_ptr += sizeof(abi_ulong); 10262623cbafSbellard } 1027060366c5Sbellard } 1028060366c5Sbellard 1029060366c5Sbellard static void save_window(CPUSPARCState *env) 1030060366c5Sbellard { 10315ef54116Sbellard #ifndef TARGET_SPARC64 10322623cbafSbellard unsigned int new_wim; 10331a14026eSblueswir1 new_wim = ((env->wim >> 1) | (env->wim << (env->nwindows - 1))) & 10341a14026eSblueswir1 ((1LL << env->nwindows) - 1); 10351a14026eSblueswir1 save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2)); 10362623cbafSbellard env->wim = new_wim; 10375ef54116Sbellard #else 10381a14026eSblueswir1 save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2)); 10395ef54116Sbellard env->cansave++; 10405ef54116Sbellard env->canrestore--; 10415ef54116Sbellard #endif 1042060366c5Sbellard } 1043060366c5Sbellard 1044060366c5Sbellard static void restore_window(CPUSPARCState *env) 1045060366c5Sbellard { 1046eda52953Sblueswir1 #ifndef TARGET_SPARC64 1047eda52953Sblueswir1 unsigned int new_wim; 1048eda52953Sblueswir1 #endif 1049eda52953Sblueswir1 unsigned int i, cwp1; 1050992f48a0Sblueswir1 abi_ulong sp_ptr; 1051060366c5Sbellard 1052eda52953Sblueswir1 #ifndef TARGET_SPARC64 10531a14026eSblueswir1 new_wim = ((env->wim << 1) | (env->wim >> (env->nwindows - 1))) & 10541a14026eSblueswir1 ((1LL << env->nwindows) - 1); 1055eda52953Sblueswir1 #endif 1056060366c5Sbellard 1057060366c5Sbellard /* restore the invalid window */ 10581a14026eSblueswir1 cwp1 = cpu_cwp_inc(env, env->cwp + 1); 105953a5960aSpbrook sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)]; 1060ed23fbd9Sblueswir1 #ifdef TARGET_SPARC64 1061ed23fbd9Sblueswir1 if (sp_ptr & 3) 1062ed23fbd9Sblueswir1 sp_ptr += SPARC64_STACK_BIAS; 1063ed23fbd9Sblueswir1 #endif 1064060366c5Sbellard #if defined(DEBUG_WIN) 10652daf0284Sblueswir1 printf("win_underflow: sp_ptr=0x" TARGET_ABI_FMT_lx " load_cwp=%d\n", 10662daf0284Sblueswir1 sp_ptr, cwp1); 1067060366c5Sbellard #endif 10682623cbafSbellard for(i = 0; i < 16; i++) { 10692f619698Sbellard /* FIXME - what to do if get_user() fails? */ 10702f619698Sbellard get_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr); 1071992f48a0Sblueswir1 sp_ptr += sizeof(abi_ulong); 10722623cbafSbellard } 10735ef54116Sbellard #ifdef TARGET_SPARC64 10745ef54116Sbellard env->canrestore++; 10751a14026eSblueswir1 if (env->cleanwin < env->nwindows - 1) 10765ef54116Sbellard env->cleanwin++; 10775ef54116Sbellard env->cansave--; 1078eda52953Sblueswir1 #else 1079eda52953Sblueswir1 env->wim = new_wim; 10805ef54116Sbellard #endif 1081060366c5Sbellard } 1082060366c5Sbellard 1083060366c5Sbellard static void flush_windows(CPUSPARCState *env) 1084060366c5Sbellard { 1085060366c5Sbellard int offset, cwp1; 10862623cbafSbellard 10872623cbafSbellard offset = 1; 1088060366c5Sbellard for(;;) { 1089060366c5Sbellard /* if restore would invoke restore_window(), then we can stop */ 10901a14026eSblueswir1 cwp1 = cpu_cwp_inc(env, env->cwp + offset); 1091eda52953Sblueswir1 #ifndef TARGET_SPARC64 1092060366c5Sbellard if (env->wim & (1 << cwp1)) 1093060366c5Sbellard break; 1094eda52953Sblueswir1 #else 1095eda52953Sblueswir1 if (env->canrestore == 0) 1096eda52953Sblueswir1 break; 1097eda52953Sblueswir1 env->cansave++; 1098eda52953Sblueswir1 env->canrestore--; 1099eda52953Sblueswir1 #endif 11002623cbafSbellard save_window_offset(env, cwp1); 1101060366c5Sbellard offset++; 1102060366c5Sbellard } 11031a14026eSblueswir1 cwp1 = cpu_cwp_inc(env, env->cwp + 1); 1104eda52953Sblueswir1 #ifndef TARGET_SPARC64 1105eda52953Sblueswir1 /* set wim so that restore will reload the registers */ 11062623cbafSbellard env->wim = 1 << cwp1; 1107eda52953Sblueswir1 #endif 11082623cbafSbellard #if defined(DEBUG_WIN) 11092623cbafSbellard printf("flush_windows: nb=%d\n", offset - 1); 111080a9d035Sbellard #endif 11112623cbafSbellard } 1112060366c5Sbellard 111393ac68bcSbellard void cpu_loop (CPUSPARCState *env) 111493ac68bcSbellard { 11152cc20260SRichard Henderson int trapnr; 11162cc20260SRichard Henderson abi_long ret; 1117c227f099SAnthony Liguori target_siginfo_t info; 111893ac68bcSbellard 111993ac68bcSbellard while (1) { 112093ac68bcSbellard trapnr = cpu_sparc_exec (env); 112193ac68bcSbellard 112220132b96SRichard Henderson /* Compute PSR before exposing state. */ 112320132b96SRichard Henderson if (env->cc_op != CC_OP_FLAGS) { 112420132b96SRichard Henderson cpu_get_psr(env); 112520132b96SRichard Henderson } 112620132b96SRichard Henderson 112793ac68bcSbellard switch (trapnr) { 11285ef54116Sbellard #ifndef TARGET_SPARC64 1129060366c5Sbellard case 0x88: 1130060366c5Sbellard case 0x90: 11315ef54116Sbellard #else 1132cb33da57Sblueswir1 case 0x110: 11335ef54116Sbellard case 0x16d: 11345ef54116Sbellard #endif 1135060366c5Sbellard ret = do_syscall (env, env->gregs[1], 1136060366c5Sbellard env->regwptr[0], env->regwptr[1], 1137060366c5Sbellard env->regwptr[2], env->regwptr[3], 11385945cfcbSPeter Maydell env->regwptr[4], env->regwptr[5], 11395945cfcbSPeter Maydell 0, 0); 11402cc20260SRichard Henderson if ((abi_ulong)ret >= (abi_ulong)(-515)) { 1141992f48a0Sblueswir1 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) 114227908725Sbellard env->xcc |= PSR_CARRY; 114327908725Sbellard #else 114493ac68bcSbellard env->psr |= PSR_CARRY; 114527908725Sbellard #endif 1146060366c5Sbellard ret = -ret; 1147060366c5Sbellard } else { 1148992f48a0Sblueswir1 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) 114927908725Sbellard env->xcc &= ~PSR_CARRY; 115027908725Sbellard #else 1151060366c5Sbellard env->psr &= ~PSR_CARRY; 115227908725Sbellard #endif 1153060366c5Sbellard } 1154060366c5Sbellard env->regwptr[0] = ret; 1155060366c5Sbellard /* next instruction */ 1156060366c5Sbellard env->pc = env->npc; 1157060366c5Sbellard env->npc = env->npc + 4; 1158060366c5Sbellard break; 1159060366c5Sbellard case 0x83: /* flush windows */ 1160992f48a0Sblueswir1 #ifdef TARGET_ABI32 1161992f48a0Sblueswir1 case 0x103: 1162992f48a0Sblueswir1 #endif 11632623cbafSbellard flush_windows(env); 1164060366c5Sbellard /* next instruction */ 1165060366c5Sbellard env->pc = env->npc; 1166060366c5Sbellard env->npc = env->npc + 4; 1167060366c5Sbellard break; 11683475187dSbellard #ifndef TARGET_SPARC64 1169060366c5Sbellard case TT_WIN_OVF: /* window overflow */ 1170060366c5Sbellard save_window(env); 1171060366c5Sbellard break; 1172060366c5Sbellard case TT_WIN_UNF: /* window underflow */ 1173060366c5Sbellard restore_window(env); 117493ac68bcSbellard break; 117561ff6f58Sbellard case TT_TFAULT: 117661ff6f58Sbellard case TT_DFAULT: 117761ff6f58Sbellard { 117859f7182fSRichard Henderson info.si_signo = TARGET_SIGSEGV; 117961ff6f58Sbellard info.si_errno = 0; 118061ff6f58Sbellard /* XXX: check env->error_code */ 118161ff6f58Sbellard info.si_code = TARGET_SEGV_MAPERR; 118261ff6f58Sbellard info._sifields._sigfault._addr = env->mmuregs[4]; 1183624f7979Spbrook queue_signal(env, info.si_signo, &info); 118461ff6f58Sbellard } 118561ff6f58Sbellard break; 11863475187dSbellard #else 11875ef54116Sbellard case TT_SPILL: /* window overflow */ 11885ef54116Sbellard save_window(env); 11895ef54116Sbellard break; 11905ef54116Sbellard case TT_FILL: /* window underflow */ 11915ef54116Sbellard restore_window(env); 11925ef54116Sbellard break; 11937f84a729Sblueswir1 case TT_TFAULT: 11947f84a729Sblueswir1 case TT_DFAULT: 11957f84a729Sblueswir1 { 119659f7182fSRichard Henderson info.si_signo = TARGET_SIGSEGV; 11977f84a729Sblueswir1 info.si_errno = 0; 11987f84a729Sblueswir1 /* XXX: check env->error_code */ 11997f84a729Sblueswir1 info.si_code = TARGET_SEGV_MAPERR; 12007f84a729Sblueswir1 if (trapnr == TT_DFAULT) 12017f84a729Sblueswir1 info._sifields._sigfault._addr = env->dmmuregs[4]; 12027f84a729Sblueswir1 else 12038194f35aSIgor Kovalenko info._sifields._sigfault._addr = cpu_tsptr(env)->tpc; 1204624f7979Spbrook queue_signal(env, info.si_signo, &info); 12057f84a729Sblueswir1 } 12067f84a729Sblueswir1 break; 120727524dc3Sbellard #ifndef TARGET_ABI32 12085bfb56b2Sblueswir1 case 0x16e: 12095bfb56b2Sblueswir1 flush_windows(env); 12105bfb56b2Sblueswir1 sparc64_get_context(env); 12115bfb56b2Sblueswir1 break; 12125bfb56b2Sblueswir1 case 0x16f: 12135bfb56b2Sblueswir1 flush_windows(env); 12145bfb56b2Sblueswir1 sparc64_set_context(env); 12155bfb56b2Sblueswir1 break; 12163475187dSbellard #endif 121727524dc3Sbellard #endif 121848dc41ebSbellard case EXCP_INTERRUPT: 121948dc41ebSbellard /* just indicate that signals should be handled asap */ 1220e80cfcfcSbellard break; 122175f22e4eSRichard Henderson case TT_ILL_INSN: 122275f22e4eSRichard Henderson { 122375f22e4eSRichard Henderson info.si_signo = TARGET_SIGILL; 122475f22e4eSRichard Henderson info.si_errno = 0; 122575f22e4eSRichard Henderson info.si_code = TARGET_ILL_ILLOPC; 122675f22e4eSRichard Henderson info._sifields._sigfault._addr = env->pc; 122775f22e4eSRichard Henderson queue_signal(env, info.si_signo, &info); 122875f22e4eSRichard Henderson } 122975f22e4eSRichard Henderson break; 12301fddef4bSbellard case EXCP_DEBUG: 12311fddef4bSbellard { 12321fddef4bSbellard int sig; 12331fddef4bSbellard 12341fddef4bSbellard sig = gdb_handlesig (env, TARGET_SIGTRAP); 12351fddef4bSbellard if (sig) 12361fddef4bSbellard { 12371fddef4bSbellard info.si_signo = sig; 12381fddef4bSbellard info.si_errno = 0; 12391fddef4bSbellard info.si_code = TARGET_TRAP_BRKPT; 1240624f7979Spbrook queue_signal(env, info.si_signo, &info); 12411fddef4bSbellard } 12421fddef4bSbellard } 12431fddef4bSbellard break; 124493ac68bcSbellard default: 1245060366c5Sbellard printf ("Unhandled trap: 0x%x\n", trapnr); 12467fe48483Sbellard cpu_dump_state(env, stderr, fprintf, 0); 124793ac68bcSbellard exit (1); 124893ac68bcSbellard } 124993ac68bcSbellard process_pending_signals (env); 125093ac68bcSbellard } 125193ac68bcSbellard } 125293ac68bcSbellard 125393ac68bcSbellard #endif 125493ac68bcSbellard 125567867308Sbellard #ifdef TARGET_PPC 125605390248SAndreas Färber static inline uint64_t cpu_ppc_get_tb(CPUPPCState *env) 12579fddaa0cSbellard { 12589fddaa0cSbellard /* TO FIX */ 12599fddaa0cSbellard return 0; 12609fddaa0cSbellard } 12619fddaa0cSbellard 126205390248SAndreas Färber uint64_t cpu_ppc_load_tbl(CPUPPCState *env) 12639fddaa0cSbellard { 1264e3ea6529SAlexander Graf return cpu_ppc_get_tb(env); 12659fddaa0cSbellard } 12669fddaa0cSbellard 126705390248SAndreas Färber uint32_t cpu_ppc_load_tbu(CPUPPCState *env) 12689fddaa0cSbellard { 12699fddaa0cSbellard return cpu_ppc_get_tb(env) >> 32; 12709fddaa0cSbellard } 12719fddaa0cSbellard 127205390248SAndreas Färber uint64_t cpu_ppc_load_atbl(CPUPPCState *env) 12739fddaa0cSbellard { 1274b711de95SAurelien Jarno return cpu_ppc_get_tb(env); 12759fddaa0cSbellard } 12769fddaa0cSbellard 127705390248SAndreas Färber uint32_t cpu_ppc_load_atbu(CPUPPCState *env) 12789fddaa0cSbellard { 1279a062e36cSj_mayer return cpu_ppc_get_tb(env) >> 32; 12809fddaa0cSbellard } 12819fddaa0cSbellard 128205390248SAndreas Färber uint32_t cpu_ppc601_load_rtcu(CPUPPCState *env) 128376a66253Sj_mayer __attribute__ (( alias ("cpu_ppc_load_tbu") )); 128476a66253Sj_mayer 128505390248SAndreas Färber uint32_t cpu_ppc601_load_rtcl(CPUPPCState *env) 12869fddaa0cSbellard { 128776a66253Sj_mayer return cpu_ppc_load_tbl(env) & 0x3FFFFF80; 12889fddaa0cSbellard } 12899fddaa0cSbellard 1290a750fc0bSj_mayer /* XXX: to be fixed */ 129173b01960SAlexander Graf int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp) 1292a750fc0bSj_mayer { 1293a750fc0bSj_mayer return -1; 1294a750fc0bSj_mayer } 1295a750fc0bSj_mayer 129673b01960SAlexander Graf int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val) 1297a750fc0bSj_mayer { 1298a750fc0bSj_mayer return -1; 1299a750fc0bSj_mayer } 1300a750fc0bSj_mayer 1301001faf32SBlue Swirl #define EXCP_DUMP(env, fmt, ...) \ 1302e1833e1fSj_mayer do { \ 1303001faf32SBlue Swirl fprintf(stderr, fmt , ## __VA_ARGS__); \ 1304e1833e1fSj_mayer cpu_dump_state(env, stderr, fprintf, 0); \ 1305001faf32SBlue Swirl qemu_log(fmt, ## __VA_ARGS__); \ 1306eeacee4dSBlue Swirl if (qemu_log_enabled()) { \ 130793fcfe39Saliguori log_cpu_state(env, 0); \ 1308eeacee4dSBlue Swirl } \ 1309e1833e1fSj_mayer } while (0) 1310e1833e1fSj_mayer 131156f066bbSNathan Froyd static int do_store_exclusive(CPUPPCState *env) 131256f066bbSNathan Froyd { 131356f066bbSNathan Froyd target_ulong addr; 131456f066bbSNathan Froyd target_ulong page_addr; 131556f066bbSNathan Froyd target_ulong val; 131656f066bbSNathan Froyd int flags; 131756f066bbSNathan Froyd int segv = 0; 131856f066bbSNathan Froyd 131956f066bbSNathan Froyd addr = env->reserve_ea; 132056f066bbSNathan Froyd page_addr = addr & TARGET_PAGE_MASK; 132156f066bbSNathan Froyd start_exclusive(); 132256f066bbSNathan Froyd mmap_lock(); 132356f066bbSNathan Froyd flags = page_get_flags(page_addr); 132456f066bbSNathan Froyd if ((flags & PAGE_READ) == 0) { 132556f066bbSNathan Froyd segv = 1; 132656f066bbSNathan Froyd } else { 132756f066bbSNathan Froyd int reg = env->reserve_info & 0x1f; 132856f066bbSNathan Froyd int size = (env->reserve_info >> 5) & 0xf; 132956f066bbSNathan Froyd int stored = 0; 133056f066bbSNathan Froyd 133156f066bbSNathan Froyd if (addr == env->reserve_addr) { 133256f066bbSNathan Froyd switch (size) { 133356f066bbSNathan Froyd case 1: segv = get_user_u8(val, addr); break; 133456f066bbSNathan Froyd case 2: segv = get_user_u16(val, addr); break; 133556f066bbSNathan Froyd case 4: segv = get_user_u32(val, addr); break; 133656f066bbSNathan Froyd #if defined(TARGET_PPC64) 133756f066bbSNathan Froyd case 8: segv = get_user_u64(val, addr); break; 133856f066bbSNathan Froyd #endif 133956f066bbSNathan Froyd default: abort(); 134056f066bbSNathan Froyd } 134156f066bbSNathan Froyd if (!segv && val == env->reserve_val) { 134256f066bbSNathan Froyd val = env->gpr[reg]; 134356f066bbSNathan Froyd switch (size) { 134456f066bbSNathan Froyd case 1: segv = put_user_u8(val, addr); break; 134556f066bbSNathan Froyd case 2: segv = put_user_u16(val, addr); break; 134656f066bbSNathan Froyd case 4: segv = put_user_u32(val, addr); break; 134756f066bbSNathan Froyd #if defined(TARGET_PPC64) 134856f066bbSNathan Froyd case 8: segv = put_user_u64(val, addr); break; 134956f066bbSNathan Froyd #endif 135056f066bbSNathan Froyd default: abort(); 135156f066bbSNathan Froyd } 135256f066bbSNathan Froyd if (!segv) { 135356f066bbSNathan Froyd stored = 1; 135456f066bbSNathan Froyd } 135556f066bbSNathan Froyd } 135656f066bbSNathan Froyd } 135756f066bbSNathan Froyd env->crf[0] = (stored << 1) | xer_so; 135856f066bbSNathan Froyd env->reserve_addr = (target_ulong)-1; 135956f066bbSNathan Froyd } 136056f066bbSNathan Froyd if (!segv) { 136156f066bbSNathan Froyd env->nip += 4; 136256f066bbSNathan Froyd } 136356f066bbSNathan Froyd mmap_unlock(); 136456f066bbSNathan Froyd end_exclusive(); 136556f066bbSNathan Froyd return segv; 136656f066bbSNathan Froyd } 136756f066bbSNathan Froyd 136867867308Sbellard void cpu_loop(CPUPPCState *env) 136967867308Sbellard { 1370c227f099SAnthony Liguori target_siginfo_t info; 137161190b14Sbellard int trapnr; 13729e0e2f96SRichard Henderson target_ulong ret; 137367867308Sbellard 137467867308Sbellard for(;;) { 137556f066bbSNathan Froyd cpu_exec_start(env); 137667867308Sbellard trapnr = cpu_ppc_exec(env); 137756f066bbSNathan Froyd cpu_exec_end(env); 137867867308Sbellard switch(trapnr) { 1379e1833e1fSj_mayer case POWERPC_EXCP_NONE: 1380e1833e1fSj_mayer /* Just go on */ 138167867308Sbellard break; 1382e1833e1fSj_mayer case POWERPC_EXCP_CRITICAL: /* Critical input */ 1383e1833e1fSj_mayer cpu_abort(env, "Critical interrupt while in user mode. " 1384e1833e1fSj_mayer "Aborting\n"); 1385e1833e1fSj_mayer break; 1386e1833e1fSj_mayer case POWERPC_EXCP_MCHECK: /* Machine check exception */ 1387e1833e1fSj_mayer cpu_abort(env, "Machine check exception while in user mode. " 1388e1833e1fSj_mayer "Aborting\n"); 1389e1833e1fSj_mayer break; 1390e1833e1fSj_mayer case POWERPC_EXCP_DSI: /* Data storage exception */ 139190e189ecSBlue Swirl EXCP_DUMP(env, "Invalid data memory access: 0x" TARGET_FMT_lx "\n", 1392e1833e1fSj_mayer env->spr[SPR_DAR]); 1393e1833e1fSj_mayer /* XXX: check this. Seems bugged */ 1394e1833e1fSj_mayer switch (env->error_code & 0xFF000000) { 1395e1833e1fSj_mayer case 0x40000000: 1396e1833e1fSj_mayer info.si_signo = TARGET_SIGSEGV; 1397e1833e1fSj_mayer info.si_errno = 0; 1398e1833e1fSj_mayer info.si_code = TARGET_SEGV_MAPERR; 1399e1833e1fSj_mayer break; 1400e1833e1fSj_mayer case 0x04000000: 1401e1833e1fSj_mayer info.si_signo = TARGET_SIGILL; 1402e1833e1fSj_mayer info.si_errno = 0; 1403e1833e1fSj_mayer info.si_code = TARGET_ILL_ILLADR; 1404e1833e1fSj_mayer break; 1405e1833e1fSj_mayer case 0x08000000: 1406e1833e1fSj_mayer info.si_signo = TARGET_SIGSEGV; 1407e1833e1fSj_mayer info.si_errno = 0; 1408e1833e1fSj_mayer info.si_code = TARGET_SEGV_ACCERR; 1409e1833e1fSj_mayer break; 1410e1833e1fSj_mayer default: 1411e1833e1fSj_mayer /* Let's send a regular segfault... */ 1412e1833e1fSj_mayer EXCP_DUMP(env, "Invalid segfault errno (%02x)\n", 1413e1833e1fSj_mayer env->error_code); 1414e1833e1fSj_mayer info.si_signo = TARGET_SIGSEGV; 1415e1833e1fSj_mayer info.si_errno = 0; 1416e1833e1fSj_mayer info.si_code = TARGET_SEGV_MAPERR; 1417e1833e1fSj_mayer break; 1418e1833e1fSj_mayer } 1419e1833e1fSj_mayer info._sifields._sigfault._addr = env->nip; 1420624f7979Spbrook queue_signal(env, info.si_signo, &info); 1421e1833e1fSj_mayer break; 1422e1833e1fSj_mayer case POWERPC_EXCP_ISI: /* Instruction storage exception */ 142390e189ecSBlue Swirl EXCP_DUMP(env, "Invalid instruction fetch: 0x\n" TARGET_FMT_lx 142490e189ecSBlue Swirl "\n", env->spr[SPR_SRR0]); 1425e1833e1fSj_mayer /* XXX: check this */ 1426e1833e1fSj_mayer switch (env->error_code & 0xFF000000) { 1427e1833e1fSj_mayer case 0x40000000: 1428e1833e1fSj_mayer info.si_signo = TARGET_SIGSEGV; 1429e1833e1fSj_mayer info.si_errno = 0; 1430e1833e1fSj_mayer info.si_code = TARGET_SEGV_MAPERR; 1431e1833e1fSj_mayer break; 1432e1833e1fSj_mayer case 0x10000000: 1433e1833e1fSj_mayer case 0x08000000: 1434e1833e1fSj_mayer info.si_signo = TARGET_SIGSEGV; 1435e1833e1fSj_mayer info.si_errno = 0; 1436e1833e1fSj_mayer info.si_code = TARGET_SEGV_ACCERR; 1437e1833e1fSj_mayer break; 1438e1833e1fSj_mayer default: 1439e1833e1fSj_mayer /* Let's send a regular segfault... */ 1440e1833e1fSj_mayer EXCP_DUMP(env, "Invalid segfault errno (%02x)\n", 1441e1833e1fSj_mayer env->error_code); 1442e1833e1fSj_mayer info.si_signo = TARGET_SIGSEGV; 1443e1833e1fSj_mayer info.si_errno = 0; 1444e1833e1fSj_mayer info.si_code = TARGET_SEGV_MAPERR; 1445e1833e1fSj_mayer break; 1446e1833e1fSj_mayer } 1447e1833e1fSj_mayer info._sifields._sigfault._addr = env->nip - 4; 1448624f7979Spbrook queue_signal(env, info.si_signo, &info); 1449e1833e1fSj_mayer break; 1450e1833e1fSj_mayer case POWERPC_EXCP_EXTERNAL: /* External input */ 1451e1833e1fSj_mayer cpu_abort(env, "External interrupt while in user mode. " 1452e1833e1fSj_mayer "Aborting\n"); 1453e1833e1fSj_mayer break; 1454e1833e1fSj_mayer case POWERPC_EXCP_ALIGN: /* Alignment exception */ 1455e1833e1fSj_mayer EXCP_DUMP(env, "Unaligned memory access\n"); 1456e1833e1fSj_mayer /* XXX: check this */ 1457e1833e1fSj_mayer info.si_signo = TARGET_SIGBUS; 1458e1833e1fSj_mayer info.si_errno = 0; 1459e1833e1fSj_mayer info.si_code = TARGET_BUS_ADRALN; 1460e1833e1fSj_mayer info._sifields._sigfault._addr = env->nip - 4; 1461624f7979Spbrook queue_signal(env, info.si_signo, &info); 1462e1833e1fSj_mayer break; 1463e1833e1fSj_mayer case POWERPC_EXCP_PROGRAM: /* Program exception */ 1464e1833e1fSj_mayer /* XXX: check this */ 1465e1833e1fSj_mayer switch (env->error_code & ~0xF) { 1466e1833e1fSj_mayer case POWERPC_EXCP_FP: 1467e1833e1fSj_mayer EXCP_DUMP(env, "Floating point program exception\n"); 1468e1833e1fSj_mayer info.si_signo = TARGET_SIGFPE; 1469e1833e1fSj_mayer info.si_errno = 0; 1470e1833e1fSj_mayer switch (env->error_code & 0xF) { 1471e1833e1fSj_mayer case POWERPC_EXCP_FP_OX: 1472e1833e1fSj_mayer info.si_code = TARGET_FPE_FLTOVF; 1473e1833e1fSj_mayer break; 1474e1833e1fSj_mayer case POWERPC_EXCP_FP_UX: 1475e1833e1fSj_mayer info.si_code = TARGET_FPE_FLTUND; 1476e1833e1fSj_mayer break; 1477e1833e1fSj_mayer case POWERPC_EXCP_FP_ZX: 1478e1833e1fSj_mayer case POWERPC_EXCP_FP_VXZDZ: 1479e1833e1fSj_mayer info.si_code = TARGET_FPE_FLTDIV; 1480e1833e1fSj_mayer break; 1481e1833e1fSj_mayer case POWERPC_EXCP_FP_XX: 1482e1833e1fSj_mayer info.si_code = TARGET_FPE_FLTRES; 1483e1833e1fSj_mayer break; 1484e1833e1fSj_mayer case POWERPC_EXCP_FP_VXSOFT: 1485e1833e1fSj_mayer info.si_code = TARGET_FPE_FLTINV; 1486e1833e1fSj_mayer break; 14877c58044cSj_mayer case POWERPC_EXCP_FP_VXSNAN: 1488e1833e1fSj_mayer case POWERPC_EXCP_FP_VXISI: 1489e1833e1fSj_mayer case POWERPC_EXCP_FP_VXIDI: 1490e1833e1fSj_mayer case POWERPC_EXCP_FP_VXIMZ: 1491e1833e1fSj_mayer case POWERPC_EXCP_FP_VXVC: 1492e1833e1fSj_mayer case POWERPC_EXCP_FP_VXSQRT: 1493e1833e1fSj_mayer case POWERPC_EXCP_FP_VXCVI: 1494e1833e1fSj_mayer info.si_code = TARGET_FPE_FLTSUB; 1495e1833e1fSj_mayer break; 1496e1833e1fSj_mayer default: 1497e1833e1fSj_mayer EXCP_DUMP(env, "Unknown floating point exception (%02x)\n", 1498e1833e1fSj_mayer env->error_code); 1499e1833e1fSj_mayer break; 1500e1833e1fSj_mayer } 1501e1833e1fSj_mayer break; 1502e1833e1fSj_mayer case POWERPC_EXCP_INVAL: 1503e1833e1fSj_mayer EXCP_DUMP(env, "Invalid instruction\n"); 1504e1833e1fSj_mayer info.si_signo = TARGET_SIGILL; 1505e1833e1fSj_mayer info.si_errno = 0; 1506e1833e1fSj_mayer switch (env->error_code & 0xF) { 1507e1833e1fSj_mayer case POWERPC_EXCP_INVAL_INVAL: 1508e1833e1fSj_mayer info.si_code = TARGET_ILL_ILLOPC; 1509e1833e1fSj_mayer break; 1510e1833e1fSj_mayer case POWERPC_EXCP_INVAL_LSWX: 1511e1833e1fSj_mayer info.si_code = TARGET_ILL_ILLOPN; 1512e1833e1fSj_mayer break; 1513e1833e1fSj_mayer case POWERPC_EXCP_INVAL_SPR: 1514e1833e1fSj_mayer info.si_code = TARGET_ILL_PRVREG; 1515e1833e1fSj_mayer break; 1516e1833e1fSj_mayer case POWERPC_EXCP_INVAL_FP: 1517e1833e1fSj_mayer info.si_code = TARGET_ILL_COPROC; 1518e1833e1fSj_mayer break; 1519e1833e1fSj_mayer default: 1520e1833e1fSj_mayer EXCP_DUMP(env, "Unknown invalid operation (%02x)\n", 1521e1833e1fSj_mayer env->error_code & 0xF); 1522e1833e1fSj_mayer info.si_code = TARGET_ILL_ILLADR; 1523e1833e1fSj_mayer break; 1524e1833e1fSj_mayer } 1525e1833e1fSj_mayer break; 1526e1833e1fSj_mayer case POWERPC_EXCP_PRIV: 1527e1833e1fSj_mayer EXCP_DUMP(env, "Privilege violation\n"); 1528e1833e1fSj_mayer info.si_signo = TARGET_SIGILL; 1529e1833e1fSj_mayer info.si_errno = 0; 1530e1833e1fSj_mayer switch (env->error_code & 0xF) { 1531e1833e1fSj_mayer case POWERPC_EXCP_PRIV_OPC: 1532e1833e1fSj_mayer info.si_code = TARGET_ILL_PRVOPC; 1533e1833e1fSj_mayer break; 1534e1833e1fSj_mayer case POWERPC_EXCP_PRIV_REG: 1535e1833e1fSj_mayer info.si_code = TARGET_ILL_PRVREG; 1536e1833e1fSj_mayer break; 1537e1833e1fSj_mayer default: 1538e1833e1fSj_mayer EXCP_DUMP(env, "Unknown privilege violation (%02x)\n", 1539e1833e1fSj_mayer env->error_code & 0xF); 1540e1833e1fSj_mayer info.si_code = TARGET_ILL_PRVOPC; 1541e1833e1fSj_mayer break; 1542e1833e1fSj_mayer } 1543e1833e1fSj_mayer break; 1544e1833e1fSj_mayer case POWERPC_EXCP_TRAP: 1545e1833e1fSj_mayer cpu_abort(env, "Tried to call a TRAP\n"); 1546e1833e1fSj_mayer break; 1547e1833e1fSj_mayer default: 1548e1833e1fSj_mayer /* Should not happen ! */ 1549e1833e1fSj_mayer cpu_abort(env, "Unknown program exception (%02x)\n", 1550e1833e1fSj_mayer env->error_code); 1551e1833e1fSj_mayer break; 1552e1833e1fSj_mayer } 1553e1833e1fSj_mayer info._sifields._sigfault._addr = env->nip - 4; 1554624f7979Spbrook queue_signal(env, info.si_signo, &info); 1555e1833e1fSj_mayer break; 1556e1833e1fSj_mayer case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ 1557e1833e1fSj_mayer EXCP_DUMP(env, "No floating point allowed\n"); 1558e1833e1fSj_mayer info.si_signo = TARGET_SIGILL; 1559e1833e1fSj_mayer info.si_errno = 0; 1560e1833e1fSj_mayer info.si_code = TARGET_ILL_COPROC; 1561e1833e1fSj_mayer info._sifields._sigfault._addr = env->nip - 4; 1562624f7979Spbrook queue_signal(env, info.si_signo, &info); 1563e1833e1fSj_mayer break; 1564e1833e1fSj_mayer case POWERPC_EXCP_SYSCALL: /* System call exception */ 1565e1833e1fSj_mayer cpu_abort(env, "Syscall exception while in user mode. " 1566e1833e1fSj_mayer "Aborting\n"); 1567e1833e1fSj_mayer break; 1568e1833e1fSj_mayer case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */ 1569e1833e1fSj_mayer EXCP_DUMP(env, "No APU instruction allowed\n"); 1570e1833e1fSj_mayer info.si_signo = TARGET_SIGILL; 1571e1833e1fSj_mayer info.si_errno = 0; 1572e1833e1fSj_mayer info.si_code = TARGET_ILL_COPROC; 1573e1833e1fSj_mayer info._sifields._sigfault._addr = env->nip - 4; 1574624f7979Spbrook queue_signal(env, info.si_signo, &info); 1575e1833e1fSj_mayer break; 1576e1833e1fSj_mayer case POWERPC_EXCP_DECR: /* Decrementer exception */ 1577e1833e1fSj_mayer cpu_abort(env, "Decrementer interrupt while in user mode. " 1578e1833e1fSj_mayer "Aborting\n"); 1579e1833e1fSj_mayer break; 1580e1833e1fSj_mayer case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */ 1581e1833e1fSj_mayer cpu_abort(env, "Fix interval timer interrupt while in user mode. " 1582e1833e1fSj_mayer "Aborting\n"); 1583e1833e1fSj_mayer break; 1584e1833e1fSj_mayer case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */ 1585e1833e1fSj_mayer cpu_abort(env, "Watchdog timer interrupt while in user mode. " 1586e1833e1fSj_mayer "Aborting\n"); 1587e1833e1fSj_mayer break; 1588e1833e1fSj_mayer case POWERPC_EXCP_DTLB: /* Data TLB error */ 1589e1833e1fSj_mayer cpu_abort(env, "Data TLB exception while in user mode. " 1590e1833e1fSj_mayer "Aborting\n"); 1591e1833e1fSj_mayer break; 1592e1833e1fSj_mayer case POWERPC_EXCP_ITLB: /* Instruction TLB error */ 1593e1833e1fSj_mayer cpu_abort(env, "Instruction TLB exception while in user mode. " 1594e1833e1fSj_mayer "Aborting\n"); 1595e1833e1fSj_mayer break; 1596e1833e1fSj_mayer case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */ 1597e1833e1fSj_mayer EXCP_DUMP(env, "No SPE/floating-point instruction allowed\n"); 1598e1833e1fSj_mayer info.si_signo = TARGET_SIGILL; 1599e1833e1fSj_mayer info.si_errno = 0; 1600e1833e1fSj_mayer info.si_code = TARGET_ILL_COPROC; 1601e1833e1fSj_mayer info._sifields._sigfault._addr = env->nip - 4; 1602624f7979Spbrook queue_signal(env, info.si_signo, &info); 1603e1833e1fSj_mayer break; 1604e1833e1fSj_mayer case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */ 1605e1833e1fSj_mayer cpu_abort(env, "Embedded floating-point data IRQ not handled\n"); 1606e1833e1fSj_mayer break; 1607e1833e1fSj_mayer case POWERPC_EXCP_EFPRI: /* Embedded floating-point round IRQ */ 1608e1833e1fSj_mayer cpu_abort(env, "Embedded floating-point round IRQ not handled\n"); 1609e1833e1fSj_mayer break; 1610e1833e1fSj_mayer case POWERPC_EXCP_EPERFM: /* Embedded performance monitor IRQ */ 1611e1833e1fSj_mayer cpu_abort(env, "Performance monitor exception not handled\n"); 1612e1833e1fSj_mayer break; 1613e1833e1fSj_mayer case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */ 1614e1833e1fSj_mayer cpu_abort(env, "Doorbell interrupt while in user mode. " 1615e1833e1fSj_mayer "Aborting\n"); 1616e1833e1fSj_mayer break; 1617e1833e1fSj_mayer case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */ 1618e1833e1fSj_mayer cpu_abort(env, "Doorbell critical interrupt while in user mode. " 1619e1833e1fSj_mayer "Aborting\n"); 1620e1833e1fSj_mayer break; 1621e1833e1fSj_mayer case POWERPC_EXCP_RESET: /* System reset exception */ 1622e1833e1fSj_mayer cpu_abort(env, "Reset interrupt while in user mode. " 1623e1833e1fSj_mayer "Aborting\n"); 1624e1833e1fSj_mayer break; 1625e1833e1fSj_mayer case POWERPC_EXCP_DSEG: /* Data segment exception */ 1626e1833e1fSj_mayer cpu_abort(env, "Data segment exception while in user mode. " 1627e1833e1fSj_mayer "Aborting\n"); 1628e1833e1fSj_mayer break; 1629e1833e1fSj_mayer case POWERPC_EXCP_ISEG: /* Instruction segment exception */ 1630e1833e1fSj_mayer cpu_abort(env, "Instruction segment exception " 1631e1833e1fSj_mayer "while in user mode. Aborting\n"); 1632e1833e1fSj_mayer break; 1633e85e7c6eSj_mayer /* PowerPC 64 with hypervisor mode support */ 1634e1833e1fSj_mayer case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */ 1635e1833e1fSj_mayer cpu_abort(env, "Hypervisor decrementer interrupt " 1636e1833e1fSj_mayer "while in user mode. Aborting\n"); 1637e1833e1fSj_mayer break; 1638e1833e1fSj_mayer case POWERPC_EXCP_TRACE: /* Trace exception */ 1639e1833e1fSj_mayer /* Nothing to do: 1640e1833e1fSj_mayer * we use this exception to emulate step-by-step execution mode. 1641e1833e1fSj_mayer */ 1642e1833e1fSj_mayer break; 1643e85e7c6eSj_mayer /* PowerPC 64 with hypervisor mode support */ 1644e1833e1fSj_mayer case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */ 1645e1833e1fSj_mayer cpu_abort(env, "Hypervisor data storage exception " 1646e1833e1fSj_mayer "while in user mode. Aborting\n"); 1647e1833e1fSj_mayer break; 1648e1833e1fSj_mayer case POWERPC_EXCP_HISI: /* Hypervisor instruction storage excp */ 1649e1833e1fSj_mayer cpu_abort(env, "Hypervisor instruction storage exception " 1650e1833e1fSj_mayer "while in user mode. Aborting\n"); 1651e1833e1fSj_mayer break; 1652e1833e1fSj_mayer case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */ 1653e1833e1fSj_mayer cpu_abort(env, "Hypervisor data segment exception " 1654e1833e1fSj_mayer "while in user mode. Aborting\n"); 1655e1833e1fSj_mayer break; 1656e1833e1fSj_mayer case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment excp */ 1657e1833e1fSj_mayer cpu_abort(env, "Hypervisor instruction segment exception " 1658e1833e1fSj_mayer "while in user mode. Aborting\n"); 1659e1833e1fSj_mayer break; 1660e1833e1fSj_mayer case POWERPC_EXCP_VPU: /* Vector unavailable exception */ 1661e1833e1fSj_mayer EXCP_DUMP(env, "No Altivec instructions allowed\n"); 1662e1833e1fSj_mayer info.si_signo = TARGET_SIGILL; 1663e1833e1fSj_mayer info.si_errno = 0; 1664e1833e1fSj_mayer info.si_code = TARGET_ILL_COPROC; 1665e1833e1fSj_mayer info._sifields._sigfault._addr = env->nip - 4; 1666624f7979Spbrook queue_signal(env, info.si_signo, &info); 1667e1833e1fSj_mayer break; 1668e1833e1fSj_mayer case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */ 1669b4916d7bSDong Xu Wang cpu_abort(env, "Programmable interval timer interrupt " 1670e1833e1fSj_mayer "while in user mode. Aborting\n"); 1671e1833e1fSj_mayer break; 1672e1833e1fSj_mayer case POWERPC_EXCP_IO: /* IO error exception */ 1673e1833e1fSj_mayer cpu_abort(env, "IO error exception while in user mode. " 1674e1833e1fSj_mayer "Aborting\n"); 1675e1833e1fSj_mayer break; 1676e1833e1fSj_mayer case POWERPC_EXCP_RUNM: /* Run mode exception */ 1677e1833e1fSj_mayer cpu_abort(env, "Run mode exception while in user mode. " 1678e1833e1fSj_mayer "Aborting\n"); 1679e1833e1fSj_mayer break; 1680e1833e1fSj_mayer case POWERPC_EXCP_EMUL: /* Emulation trap exception */ 1681e1833e1fSj_mayer cpu_abort(env, "Emulation trap exception not handled\n"); 1682e1833e1fSj_mayer break; 1683e1833e1fSj_mayer case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */ 1684e1833e1fSj_mayer cpu_abort(env, "Instruction fetch TLB exception " 1685e1833e1fSj_mayer "while in user-mode. Aborting"); 1686e1833e1fSj_mayer break; 1687e1833e1fSj_mayer case POWERPC_EXCP_DLTLB: /* Data load TLB miss */ 1688e1833e1fSj_mayer cpu_abort(env, "Data load TLB exception while in user-mode. " 1689e1833e1fSj_mayer "Aborting"); 1690e1833e1fSj_mayer break; 1691e1833e1fSj_mayer case POWERPC_EXCP_DSTLB: /* Data store TLB miss */ 1692e1833e1fSj_mayer cpu_abort(env, "Data store TLB exception while in user-mode. " 1693e1833e1fSj_mayer "Aborting"); 1694e1833e1fSj_mayer break; 1695e1833e1fSj_mayer case POWERPC_EXCP_FPA: /* Floating-point assist exception */ 1696e1833e1fSj_mayer cpu_abort(env, "Floating-point assist exception not handled\n"); 1697e1833e1fSj_mayer break; 1698e1833e1fSj_mayer case POWERPC_EXCP_IABR: /* Instruction address breakpoint */ 1699e1833e1fSj_mayer cpu_abort(env, "Instruction address breakpoint exception " 1700e1833e1fSj_mayer "not handled\n"); 1701e1833e1fSj_mayer break; 1702e1833e1fSj_mayer case POWERPC_EXCP_SMI: /* System management interrupt */ 1703e1833e1fSj_mayer cpu_abort(env, "System management interrupt while in user mode. " 1704e1833e1fSj_mayer "Aborting\n"); 1705e1833e1fSj_mayer break; 1706e1833e1fSj_mayer case POWERPC_EXCP_THERM: /* Thermal interrupt */ 1707e1833e1fSj_mayer cpu_abort(env, "Thermal interrupt interrupt while in user mode. " 1708e1833e1fSj_mayer "Aborting\n"); 1709e1833e1fSj_mayer break; 1710e1833e1fSj_mayer case POWERPC_EXCP_PERFM: /* Embedded performance monitor IRQ */ 1711e1833e1fSj_mayer cpu_abort(env, "Performance monitor exception not handled\n"); 1712e1833e1fSj_mayer break; 1713e1833e1fSj_mayer case POWERPC_EXCP_VPUA: /* Vector assist exception */ 1714e1833e1fSj_mayer cpu_abort(env, "Vector assist exception not handled\n"); 1715e1833e1fSj_mayer break; 1716e1833e1fSj_mayer case POWERPC_EXCP_SOFTP: /* Soft patch exception */ 1717e1833e1fSj_mayer cpu_abort(env, "Soft patch exception not handled\n"); 1718e1833e1fSj_mayer break; 1719e1833e1fSj_mayer case POWERPC_EXCP_MAINT: /* Maintenance exception */ 1720e1833e1fSj_mayer cpu_abort(env, "Maintenance exception while in user mode. " 1721e1833e1fSj_mayer "Aborting\n"); 1722e1833e1fSj_mayer break; 1723e1833e1fSj_mayer case POWERPC_EXCP_STOP: /* stop translation */ 1724e1833e1fSj_mayer /* We did invalidate the instruction cache. Go on */ 1725e1833e1fSj_mayer break; 1726e1833e1fSj_mayer case POWERPC_EXCP_BRANCH: /* branch instruction: */ 1727e1833e1fSj_mayer /* We just stopped because of a branch. Go on */ 1728e1833e1fSj_mayer break; 1729e1833e1fSj_mayer case POWERPC_EXCP_SYSCALL_USER: 1730e1833e1fSj_mayer /* system call in user-mode emulation */ 173167867308Sbellard /* WARNING: 173267867308Sbellard * PPC ABI uses overflow flag in cr0 to signal an error 173367867308Sbellard * in syscalls. 173467867308Sbellard */ 173567867308Sbellard env->crf[0] &= ~0x1; 173667867308Sbellard ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4], 173767867308Sbellard env->gpr[5], env->gpr[6], env->gpr[7], 17385945cfcbSPeter Maydell env->gpr[8], 0, 0); 17399e0e2f96SRichard Henderson if (ret == (target_ulong)(-TARGET_QEMU_ESIGRETURN)) { 1740bcd4933aSNathan Froyd /* Returning from a successful sigreturn syscall. 1741bcd4933aSNathan Froyd Avoid corrupting register state. */ 1742bcd4933aSNathan Froyd break; 1743bcd4933aSNathan Froyd } 17449e0e2f96SRichard Henderson if (ret > (target_ulong)(-515)) { 174567867308Sbellard env->crf[0] |= 0x1; 174667867308Sbellard ret = -ret; 174767867308Sbellard } 174867867308Sbellard env->gpr[3] = ret; 174961190b14Sbellard break; 175056f066bbSNathan Froyd case POWERPC_EXCP_STCX: 175156f066bbSNathan Froyd if (do_store_exclusive(env)) { 175256f066bbSNathan Froyd info.si_signo = TARGET_SIGSEGV; 175356f066bbSNathan Froyd info.si_errno = 0; 175456f066bbSNathan Froyd info.si_code = TARGET_SEGV_MAPERR; 175556f066bbSNathan Froyd info._sifields._sigfault._addr = env->nip; 175656f066bbSNathan Froyd queue_signal(env, info.si_signo, &info); 175756f066bbSNathan Froyd } 175856f066bbSNathan Froyd break; 175971f75756Saurel32 case EXCP_DEBUG: 176071f75756Saurel32 { 176171f75756Saurel32 int sig; 176271f75756Saurel32 176371f75756Saurel32 sig = gdb_handlesig(env, TARGET_SIGTRAP); 176471f75756Saurel32 if (sig) { 176571f75756Saurel32 info.si_signo = sig; 176671f75756Saurel32 info.si_errno = 0; 176771f75756Saurel32 info.si_code = TARGET_TRAP_BRKPT; 176871f75756Saurel32 queue_signal(env, info.si_signo, &info); 176971f75756Saurel32 } 177071f75756Saurel32 } 177171f75756Saurel32 break; 177256ba31ffSj_mayer case EXCP_INTERRUPT: 177356ba31ffSj_mayer /* just indicate that signals should be handled asap */ 177456ba31ffSj_mayer break; 177561190b14Sbellard default: 1776e1833e1fSj_mayer cpu_abort(env, "Unknown exception 0x%d. Aborting\n", trapnr); 177767867308Sbellard break; 177867867308Sbellard } 177967867308Sbellard process_pending_signals(env); 178067867308Sbellard } 178167867308Sbellard } 178267867308Sbellard #endif 178367867308Sbellard 1784048f6b4dSbellard #ifdef TARGET_MIPS 1785048f6b4dSbellard 1786048f6b4dSbellard #define MIPS_SYS(name, args) args, 1787048f6b4dSbellard 1788048f6b4dSbellard static const uint8_t mips_syscall_args[] = { 178929fb0f25SAn-Cheng Huang MIPS_SYS(sys_syscall , 8) /* 4000 */ 1790048f6b4dSbellard MIPS_SYS(sys_exit , 1) 1791048f6b4dSbellard MIPS_SYS(sys_fork , 0) 1792048f6b4dSbellard MIPS_SYS(sys_read , 3) 1793048f6b4dSbellard MIPS_SYS(sys_write , 3) 1794048f6b4dSbellard MIPS_SYS(sys_open , 3) /* 4005 */ 1795048f6b4dSbellard MIPS_SYS(sys_close , 1) 1796048f6b4dSbellard MIPS_SYS(sys_waitpid , 3) 1797048f6b4dSbellard MIPS_SYS(sys_creat , 2) 1798048f6b4dSbellard MIPS_SYS(sys_link , 2) 1799048f6b4dSbellard MIPS_SYS(sys_unlink , 1) /* 4010 */ 1800048f6b4dSbellard MIPS_SYS(sys_execve , 0) 1801048f6b4dSbellard MIPS_SYS(sys_chdir , 1) 1802048f6b4dSbellard MIPS_SYS(sys_time , 1) 1803048f6b4dSbellard MIPS_SYS(sys_mknod , 3) 1804048f6b4dSbellard MIPS_SYS(sys_chmod , 2) /* 4015 */ 1805048f6b4dSbellard MIPS_SYS(sys_lchown , 3) 1806048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 1807048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was sys_stat */ 1808048f6b4dSbellard MIPS_SYS(sys_lseek , 3) 1809048f6b4dSbellard MIPS_SYS(sys_getpid , 0) /* 4020 */ 1810048f6b4dSbellard MIPS_SYS(sys_mount , 5) 1811048f6b4dSbellard MIPS_SYS(sys_oldumount , 1) 1812048f6b4dSbellard MIPS_SYS(sys_setuid , 1) 1813048f6b4dSbellard MIPS_SYS(sys_getuid , 0) 1814048f6b4dSbellard MIPS_SYS(sys_stime , 1) /* 4025 */ 1815048f6b4dSbellard MIPS_SYS(sys_ptrace , 4) 1816048f6b4dSbellard MIPS_SYS(sys_alarm , 1) 1817048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was sys_fstat */ 1818048f6b4dSbellard MIPS_SYS(sys_pause , 0) 1819048f6b4dSbellard MIPS_SYS(sys_utime , 2) /* 4030 */ 1820048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 1821048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 1822048f6b4dSbellard MIPS_SYS(sys_access , 2) 1823048f6b4dSbellard MIPS_SYS(sys_nice , 1) 1824048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* 4035 */ 1825048f6b4dSbellard MIPS_SYS(sys_sync , 0) 1826048f6b4dSbellard MIPS_SYS(sys_kill , 2) 1827048f6b4dSbellard MIPS_SYS(sys_rename , 2) 1828048f6b4dSbellard MIPS_SYS(sys_mkdir , 2) 1829048f6b4dSbellard MIPS_SYS(sys_rmdir , 1) /* 4040 */ 1830048f6b4dSbellard MIPS_SYS(sys_dup , 1) 1831048f6b4dSbellard MIPS_SYS(sys_pipe , 0) 1832048f6b4dSbellard MIPS_SYS(sys_times , 1) 1833048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 1834048f6b4dSbellard MIPS_SYS(sys_brk , 1) /* 4045 */ 1835048f6b4dSbellard MIPS_SYS(sys_setgid , 1) 1836048f6b4dSbellard MIPS_SYS(sys_getgid , 0) 1837048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was signal(2) */ 1838048f6b4dSbellard MIPS_SYS(sys_geteuid , 0) 1839048f6b4dSbellard MIPS_SYS(sys_getegid , 0) /* 4050 */ 1840048f6b4dSbellard MIPS_SYS(sys_acct , 0) 1841048f6b4dSbellard MIPS_SYS(sys_umount , 2) 1842048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 1843048f6b4dSbellard MIPS_SYS(sys_ioctl , 3) 1844048f6b4dSbellard MIPS_SYS(sys_fcntl , 3) /* 4055 */ 1845048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 2) 1846048f6b4dSbellard MIPS_SYS(sys_setpgid , 2) 1847048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 1848048f6b4dSbellard MIPS_SYS(sys_olduname , 1) 1849048f6b4dSbellard MIPS_SYS(sys_umask , 1) /* 4060 */ 1850048f6b4dSbellard MIPS_SYS(sys_chroot , 1) 1851048f6b4dSbellard MIPS_SYS(sys_ustat , 2) 1852048f6b4dSbellard MIPS_SYS(sys_dup2 , 2) 1853048f6b4dSbellard MIPS_SYS(sys_getppid , 0) 1854048f6b4dSbellard MIPS_SYS(sys_getpgrp , 0) /* 4065 */ 1855048f6b4dSbellard MIPS_SYS(sys_setsid , 0) 1856048f6b4dSbellard MIPS_SYS(sys_sigaction , 3) 1857048f6b4dSbellard MIPS_SYS(sys_sgetmask , 0) 1858048f6b4dSbellard MIPS_SYS(sys_ssetmask , 1) 1859048f6b4dSbellard MIPS_SYS(sys_setreuid , 2) /* 4070 */ 1860048f6b4dSbellard MIPS_SYS(sys_setregid , 2) 1861048f6b4dSbellard MIPS_SYS(sys_sigsuspend , 0) 1862048f6b4dSbellard MIPS_SYS(sys_sigpending , 1) 1863048f6b4dSbellard MIPS_SYS(sys_sethostname , 2) 1864048f6b4dSbellard MIPS_SYS(sys_setrlimit , 2) /* 4075 */ 1865048f6b4dSbellard MIPS_SYS(sys_getrlimit , 2) 1866048f6b4dSbellard MIPS_SYS(sys_getrusage , 2) 1867048f6b4dSbellard MIPS_SYS(sys_gettimeofday, 2) 1868048f6b4dSbellard MIPS_SYS(sys_settimeofday, 2) 1869048f6b4dSbellard MIPS_SYS(sys_getgroups , 2) /* 4080 */ 1870048f6b4dSbellard MIPS_SYS(sys_setgroups , 2) 1871048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* old_select */ 1872048f6b4dSbellard MIPS_SYS(sys_symlink , 2) 1873048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was sys_lstat */ 1874048f6b4dSbellard MIPS_SYS(sys_readlink , 3) /* 4085 */ 1875048f6b4dSbellard MIPS_SYS(sys_uselib , 1) 1876048f6b4dSbellard MIPS_SYS(sys_swapon , 2) 1877048f6b4dSbellard MIPS_SYS(sys_reboot , 3) 1878048f6b4dSbellard MIPS_SYS(old_readdir , 3) 1879048f6b4dSbellard MIPS_SYS(old_mmap , 6) /* 4090 */ 1880048f6b4dSbellard MIPS_SYS(sys_munmap , 2) 1881048f6b4dSbellard MIPS_SYS(sys_truncate , 2) 1882048f6b4dSbellard MIPS_SYS(sys_ftruncate , 2) 1883048f6b4dSbellard MIPS_SYS(sys_fchmod , 2) 1884048f6b4dSbellard MIPS_SYS(sys_fchown , 3) /* 4095 */ 1885048f6b4dSbellard MIPS_SYS(sys_getpriority , 2) 1886048f6b4dSbellard MIPS_SYS(sys_setpriority , 3) 1887048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 1888048f6b4dSbellard MIPS_SYS(sys_statfs , 2) 1889048f6b4dSbellard MIPS_SYS(sys_fstatfs , 2) /* 4100 */ 1890048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was ioperm(2) */ 1891048f6b4dSbellard MIPS_SYS(sys_socketcall , 2) 1892048f6b4dSbellard MIPS_SYS(sys_syslog , 3) 1893048f6b4dSbellard MIPS_SYS(sys_setitimer , 3) 1894048f6b4dSbellard MIPS_SYS(sys_getitimer , 2) /* 4105 */ 1895048f6b4dSbellard MIPS_SYS(sys_newstat , 2) 1896048f6b4dSbellard MIPS_SYS(sys_newlstat , 2) 1897048f6b4dSbellard MIPS_SYS(sys_newfstat , 2) 1898048f6b4dSbellard MIPS_SYS(sys_uname , 1) 1899048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* 4110 was iopl(2) */ 1900048f6b4dSbellard MIPS_SYS(sys_vhangup , 0) 1901048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was sys_idle() */ 1902048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was sys_vm86 */ 1903048f6b4dSbellard MIPS_SYS(sys_wait4 , 4) 1904048f6b4dSbellard MIPS_SYS(sys_swapoff , 1) /* 4115 */ 1905048f6b4dSbellard MIPS_SYS(sys_sysinfo , 1) 1906048f6b4dSbellard MIPS_SYS(sys_ipc , 6) 1907048f6b4dSbellard MIPS_SYS(sys_fsync , 1) 1908048f6b4dSbellard MIPS_SYS(sys_sigreturn , 0) 190918113962SPaul Brook MIPS_SYS(sys_clone , 6) /* 4120 */ 1910048f6b4dSbellard MIPS_SYS(sys_setdomainname, 2) 1911048f6b4dSbellard MIPS_SYS(sys_newuname , 1) 1912048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* sys_modify_ldt */ 1913048f6b4dSbellard MIPS_SYS(sys_adjtimex , 1) 1914048f6b4dSbellard MIPS_SYS(sys_mprotect , 3) /* 4125 */ 1915048f6b4dSbellard MIPS_SYS(sys_sigprocmask , 3) 1916048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was create_module */ 1917048f6b4dSbellard MIPS_SYS(sys_init_module , 5) 1918048f6b4dSbellard MIPS_SYS(sys_delete_module, 1) 1919048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* 4130 was get_kernel_syms */ 1920048f6b4dSbellard MIPS_SYS(sys_quotactl , 0) 1921048f6b4dSbellard MIPS_SYS(sys_getpgid , 1) 1922048f6b4dSbellard MIPS_SYS(sys_fchdir , 1) 1923048f6b4dSbellard MIPS_SYS(sys_bdflush , 2) 1924048f6b4dSbellard MIPS_SYS(sys_sysfs , 3) /* 4135 */ 1925048f6b4dSbellard MIPS_SYS(sys_personality , 1) 1926048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* for afs_syscall */ 1927048f6b4dSbellard MIPS_SYS(sys_setfsuid , 1) 1928048f6b4dSbellard MIPS_SYS(sys_setfsgid , 1) 1929048f6b4dSbellard MIPS_SYS(sys_llseek , 5) /* 4140 */ 1930048f6b4dSbellard MIPS_SYS(sys_getdents , 3) 1931048f6b4dSbellard MIPS_SYS(sys_select , 5) 1932048f6b4dSbellard MIPS_SYS(sys_flock , 2) 1933048f6b4dSbellard MIPS_SYS(sys_msync , 3) 1934048f6b4dSbellard MIPS_SYS(sys_readv , 3) /* 4145 */ 1935048f6b4dSbellard MIPS_SYS(sys_writev , 3) 1936048f6b4dSbellard MIPS_SYS(sys_cacheflush , 3) 1937048f6b4dSbellard MIPS_SYS(sys_cachectl , 3) 1938048f6b4dSbellard MIPS_SYS(sys_sysmips , 4) 1939048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* 4150 */ 1940048f6b4dSbellard MIPS_SYS(sys_getsid , 1) 1941048f6b4dSbellard MIPS_SYS(sys_fdatasync , 0) 1942048f6b4dSbellard MIPS_SYS(sys_sysctl , 1) 1943048f6b4dSbellard MIPS_SYS(sys_mlock , 2) 1944048f6b4dSbellard MIPS_SYS(sys_munlock , 2) /* 4155 */ 1945048f6b4dSbellard MIPS_SYS(sys_mlockall , 1) 1946048f6b4dSbellard MIPS_SYS(sys_munlockall , 0) 1947048f6b4dSbellard MIPS_SYS(sys_sched_setparam, 2) 1948048f6b4dSbellard MIPS_SYS(sys_sched_getparam, 2) 1949048f6b4dSbellard MIPS_SYS(sys_sched_setscheduler, 3) /* 4160 */ 1950048f6b4dSbellard MIPS_SYS(sys_sched_getscheduler, 1) 1951048f6b4dSbellard MIPS_SYS(sys_sched_yield , 0) 1952048f6b4dSbellard MIPS_SYS(sys_sched_get_priority_max, 1) 1953048f6b4dSbellard MIPS_SYS(sys_sched_get_priority_min, 1) 1954048f6b4dSbellard MIPS_SYS(sys_sched_rr_get_interval, 2) /* 4165 */ 1955048f6b4dSbellard MIPS_SYS(sys_nanosleep, 2) 1956048f6b4dSbellard MIPS_SYS(sys_mremap , 4) 1957048f6b4dSbellard MIPS_SYS(sys_accept , 3) 1958048f6b4dSbellard MIPS_SYS(sys_bind , 3) 1959048f6b4dSbellard MIPS_SYS(sys_connect , 3) /* 4170 */ 1960048f6b4dSbellard MIPS_SYS(sys_getpeername , 3) 1961048f6b4dSbellard MIPS_SYS(sys_getsockname , 3) 1962048f6b4dSbellard MIPS_SYS(sys_getsockopt , 5) 1963048f6b4dSbellard MIPS_SYS(sys_listen , 2) 1964048f6b4dSbellard MIPS_SYS(sys_recv , 4) /* 4175 */ 1965048f6b4dSbellard MIPS_SYS(sys_recvfrom , 6) 1966048f6b4dSbellard MIPS_SYS(sys_recvmsg , 3) 1967048f6b4dSbellard MIPS_SYS(sys_send , 4) 1968048f6b4dSbellard MIPS_SYS(sys_sendmsg , 3) 1969048f6b4dSbellard MIPS_SYS(sys_sendto , 6) /* 4180 */ 1970048f6b4dSbellard MIPS_SYS(sys_setsockopt , 5) 1971048f6b4dSbellard MIPS_SYS(sys_shutdown , 2) 1972048f6b4dSbellard MIPS_SYS(sys_socket , 3) 1973048f6b4dSbellard MIPS_SYS(sys_socketpair , 4) 1974048f6b4dSbellard MIPS_SYS(sys_setresuid , 3) /* 4185 */ 1975048f6b4dSbellard MIPS_SYS(sys_getresuid , 3) 1976048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* was sys_query_module */ 1977048f6b4dSbellard MIPS_SYS(sys_poll , 3) 1978048f6b4dSbellard MIPS_SYS(sys_nfsservctl , 3) 1979048f6b4dSbellard MIPS_SYS(sys_setresgid , 3) /* 4190 */ 1980048f6b4dSbellard MIPS_SYS(sys_getresgid , 3) 1981048f6b4dSbellard MIPS_SYS(sys_prctl , 5) 1982048f6b4dSbellard MIPS_SYS(sys_rt_sigreturn, 0) 1983048f6b4dSbellard MIPS_SYS(sys_rt_sigaction, 4) 1984048f6b4dSbellard MIPS_SYS(sys_rt_sigprocmask, 4) /* 4195 */ 1985048f6b4dSbellard MIPS_SYS(sys_rt_sigpending, 2) 1986048f6b4dSbellard MIPS_SYS(sys_rt_sigtimedwait, 4) 1987048f6b4dSbellard MIPS_SYS(sys_rt_sigqueueinfo, 3) 1988048f6b4dSbellard MIPS_SYS(sys_rt_sigsuspend, 0) 1989048f6b4dSbellard MIPS_SYS(sys_pread64 , 6) /* 4200 */ 1990048f6b4dSbellard MIPS_SYS(sys_pwrite64 , 6) 1991048f6b4dSbellard MIPS_SYS(sys_chown , 3) 1992048f6b4dSbellard MIPS_SYS(sys_getcwd , 2) 1993048f6b4dSbellard MIPS_SYS(sys_capget , 2) 1994048f6b4dSbellard MIPS_SYS(sys_capset , 2) /* 4205 */ 1995053ebb27SWesley W. Terpstra MIPS_SYS(sys_sigaltstack , 2) 1996048f6b4dSbellard MIPS_SYS(sys_sendfile , 4) 1997048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 1998048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 1999048f6b4dSbellard MIPS_SYS(sys_mmap2 , 6) /* 4210 */ 2000048f6b4dSbellard MIPS_SYS(sys_truncate64 , 4) 2001048f6b4dSbellard MIPS_SYS(sys_ftruncate64 , 4) 2002048f6b4dSbellard MIPS_SYS(sys_stat64 , 2) 2003048f6b4dSbellard MIPS_SYS(sys_lstat64 , 2) 2004048f6b4dSbellard MIPS_SYS(sys_fstat64 , 2) /* 4215 */ 2005048f6b4dSbellard MIPS_SYS(sys_pivot_root , 2) 2006048f6b4dSbellard MIPS_SYS(sys_mincore , 3) 2007048f6b4dSbellard MIPS_SYS(sys_madvise , 3) 2008048f6b4dSbellard MIPS_SYS(sys_getdents64 , 3) 2009048f6b4dSbellard MIPS_SYS(sys_fcntl64 , 3) /* 4220 */ 2010048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) 2011048f6b4dSbellard MIPS_SYS(sys_gettid , 0) 2012048f6b4dSbellard MIPS_SYS(sys_readahead , 5) 2013048f6b4dSbellard MIPS_SYS(sys_setxattr , 5) 2014048f6b4dSbellard MIPS_SYS(sys_lsetxattr , 5) /* 4225 */ 2015048f6b4dSbellard MIPS_SYS(sys_fsetxattr , 5) 2016048f6b4dSbellard MIPS_SYS(sys_getxattr , 4) 2017048f6b4dSbellard MIPS_SYS(sys_lgetxattr , 4) 2018048f6b4dSbellard MIPS_SYS(sys_fgetxattr , 4) 2019048f6b4dSbellard MIPS_SYS(sys_listxattr , 3) /* 4230 */ 2020048f6b4dSbellard MIPS_SYS(sys_llistxattr , 3) 2021048f6b4dSbellard MIPS_SYS(sys_flistxattr , 3) 2022048f6b4dSbellard MIPS_SYS(sys_removexattr , 2) 2023048f6b4dSbellard MIPS_SYS(sys_lremovexattr, 2) 2024048f6b4dSbellard MIPS_SYS(sys_fremovexattr, 2) /* 4235 */ 2025048f6b4dSbellard MIPS_SYS(sys_tkill , 2) 2026048f6b4dSbellard MIPS_SYS(sys_sendfile64 , 5) 2027048f6b4dSbellard MIPS_SYS(sys_futex , 2) 2028048f6b4dSbellard MIPS_SYS(sys_sched_setaffinity, 3) 2029048f6b4dSbellard MIPS_SYS(sys_sched_getaffinity, 3) /* 4240 */ 2030048f6b4dSbellard MIPS_SYS(sys_io_setup , 2) 2031048f6b4dSbellard MIPS_SYS(sys_io_destroy , 1) 2032048f6b4dSbellard MIPS_SYS(sys_io_getevents, 5) 2033048f6b4dSbellard MIPS_SYS(sys_io_submit , 3) 2034048f6b4dSbellard MIPS_SYS(sys_io_cancel , 3) /* 4245 */ 2035048f6b4dSbellard MIPS_SYS(sys_exit_group , 1) 2036048f6b4dSbellard MIPS_SYS(sys_lookup_dcookie, 3) 2037048f6b4dSbellard MIPS_SYS(sys_epoll_create, 1) 2038048f6b4dSbellard MIPS_SYS(sys_epoll_ctl , 4) 2039048f6b4dSbellard MIPS_SYS(sys_epoll_wait , 3) /* 4250 */ 2040048f6b4dSbellard MIPS_SYS(sys_remap_file_pages, 5) 2041048f6b4dSbellard MIPS_SYS(sys_set_tid_address, 1) 2042048f6b4dSbellard MIPS_SYS(sys_restart_syscall, 0) 2043048f6b4dSbellard MIPS_SYS(sys_fadvise64_64, 7) 2044048f6b4dSbellard MIPS_SYS(sys_statfs64 , 3) /* 4255 */ 2045048f6b4dSbellard MIPS_SYS(sys_fstatfs64 , 2) 2046048f6b4dSbellard MIPS_SYS(sys_timer_create, 3) 2047048f6b4dSbellard MIPS_SYS(sys_timer_settime, 4) 2048048f6b4dSbellard MIPS_SYS(sys_timer_gettime, 2) 2049048f6b4dSbellard MIPS_SYS(sys_timer_getoverrun, 1) /* 4260 */ 2050048f6b4dSbellard MIPS_SYS(sys_timer_delete, 1) 2051048f6b4dSbellard MIPS_SYS(sys_clock_settime, 2) 2052048f6b4dSbellard MIPS_SYS(sys_clock_gettime, 2) 2053048f6b4dSbellard MIPS_SYS(sys_clock_getres, 2) 2054048f6b4dSbellard MIPS_SYS(sys_clock_nanosleep, 4) /* 4265 */ 2055048f6b4dSbellard MIPS_SYS(sys_tgkill , 3) 2056048f6b4dSbellard MIPS_SYS(sys_utimes , 2) 2057048f6b4dSbellard MIPS_SYS(sys_mbind , 4) 2058048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* sys_get_mempolicy */ 2059048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* 4270 sys_set_mempolicy */ 2060048f6b4dSbellard MIPS_SYS(sys_mq_open , 4) 2061048f6b4dSbellard MIPS_SYS(sys_mq_unlink , 1) 2062048f6b4dSbellard MIPS_SYS(sys_mq_timedsend, 5) 2063048f6b4dSbellard MIPS_SYS(sys_mq_timedreceive, 5) 2064048f6b4dSbellard MIPS_SYS(sys_mq_notify , 2) /* 4275 */ 2065048f6b4dSbellard MIPS_SYS(sys_mq_getsetattr, 3) 2066048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* sys_vserver */ 2067048f6b4dSbellard MIPS_SYS(sys_waitid , 4) 2068048f6b4dSbellard MIPS_SYS(sys_ni_syscall , 0) /* available, was setaltroot */ 2069048f6b4dSbellard MIPS_SYS(sys_add_key , 5) 2070048f6b4dSbellard MIPS_SYS(sys_request_key, 4) 2071048f6b4dSbellard MIPS_SYS(sys_keyctl , 5) 20726f5b89a0Sths MIPS_SYS(sys_set_thread_area, 1) 2073388bb21aSths MIPS_SYS(sys_inotify_init, 0) 2074388bb21aSths MIPS_SYS(sys_inotify_add_watch, 3) /* 4285 */ 2075388bb21aSths MIPS_SYS(sys_inotify_rm_watch, 2) 2076388bb21aSths MIPS_SYS(sys_migrate_pages, 4) 2077388bb21aSths MIPS_SYS(sys_openat, 4) 2078388bb21aSths MIPS_SYS(sys_mkdirat, 3) 2079388bb21aSths MIPS_SYS(sys_mknodat, 4) /* 4290 */ 2080388bb21aSths MIPS_SYS(sys_fchownat, 5) 2081388bb21aSths MIPS_SYS(sys_futimesat, 3) 2082388bb21aSths MIPS_SYS(sys_fstatat64, 4) 2083388bb21aSths MIPS_SYS(sys_unlinkat, 3) 2084388bb21aSths MIPS_SYS(sys_renameat, 4) /* 4295 */ 2085388bb21aSths MIPS_SYS(sys_linkat, 5) 2086388bb21aSths MIPS_SYS(sys_symlinkat, 3) 2087388bb21aSths MIPS_SYS(sys_readlinkat, 4) 2088388bb21aSths MIPS_SYS(sys_fchmodat, 3) 2089388bb21aSths MIPS_SYS(sys_faccessat, 3) /* 4300 */ 2090388bb21aSths MIPS_SYS(sys_pselect6, 6) 2091388bb21aSths MIPS_SYS(sys_ppoll, 5) 2092388bb21aSths MIPS_SYS(sys_unshare, 1) 2093388bb21aSths MIPS_SYS(sys_splice, 4) 2094388bb21aSths MIPS_SYS(sys_sync_file_range, 7) /* 4305 */ 2095388bb21aSths MIPS_SYS(sys_tee, 4) 2096388bb21aSths MIPS_SYS(sys_vmsplice, 4) 2097388bb21aSths MIPS_SYS(sys_move_pages, 6) 2098388bb21aSths MIPS_SYS(sys_set_robust_list, 2) 2099388bb21aSths MIPS_SYS(sys_get_robust_list, 3) /* 4310 */ 2100388bb21aSths MIPS_SYS(sys_kexec_load, 4) 2101388bb21aSths MIPS_SYS(sys_getcpu, 3) 2102388bb21aSths MIPS_SYS(sys_epoll_pwait, 6) 2103388bb21aSths MIPS_SYS(sys_ioprio_set, 3) 2104388bb21aSths MIPS_SYS(sys_ioprio_get, 2) 2105d979e8ebSPeter Maydell MIPS_SYS(sys_utimensat, 4) 2106d979e8ebSPeter Maydell MIPS_SYS(sys_signalfd, 3) 2107d979e8ebSPeter Maydell MIPS_SYS(sys_ni_syscall, 0) /* was timerfd */ 2108d979e8ebSPeter Maydell MIPS_SYS(sys_eventfd, 1) 2109d979e8ebSPeter Maydell MIPS_SYS(sys_fallocate, 6) /* 4320 */ 2110d979e8ebSPeter Maydell MIPS_SYS(sys_timerfd_create, 2) 2111d979e8ebSPeter Maydell MIPS_SYS(sys_timerfd_gettime, 2) 2112d979e8ebSPeter Maydell MIPS_SYS(sys_timerfd_settime, 4) 2113d979e8ebSPeter Maydell MIPS_SYS(sys_signalfd4, 4) 2114d979e8ebSPeter Maydell MIPS_SYS(sys_eventfd2, 2) /* 4325 */ 2115d979e8ebSPeter Maydell MIPS_SYS(sys_epoll_create1, 1) 2116d979e8ebSPeter Maydell MIPS_SYS(sys_dup3, 3) 2117d979e8ebSPeter Maydell MIPS_SYS(sys_pipe2, 2) 2118d979e8ebSPeter Maydell MIPS_SYS(sys_inotify_init1, 1) 2119d979e8ebSPeter Maydell MIPS_SYS(sys_preadv, 6) /* 4330 */ 2120d979e8ebSPeter Maydell MIPS_SYS(sys_pwritev, 6) 2121d979e8ebSPeter Maydell MIPS_SYS(sys_rt_tgsigqueueinfo, 4) 2122d979e8ebSPeter Maydell MIPS_SYS(sys_perf_event_open, 5) 2123d979e8ebSPeter Maydell MIPS_SYS(sys_accept4, 4) 2124d979e8ebSPeter Maydell MIPS_SYS(sys_recvmmsg, 5) /* 4335 */ 2125d979e8ebSPeter Maydell MIPS_SYS(sys_fanotify_init, 2) 2126d979e8ebSPeter Maydell MIPS_SYS(sys_fanotify_mark, 6) 2127d979e8ebSPeter Maydell MIPS_SYS(sys_prlimit64, 4) 2128d979e8ebSPeter Maydell MIPS_SYS(sys_name_to_handle_at, 5) 2129d979e8ebSPeter Maydell MIPS_SYS(sys_open_by_handle_at, 3) /* 4340 */ 2130d979e8ebSPeter Maydell MIPS_SYS(sys_clock_adjtime, 2) 2131d979e8ebSPeter Maydell MIPS_SYS(sys_syncfs, 1) 2132048f6b4dSbellard }; 2133048f6b4dSbellard 2134048f6b4dSbellard #undef MIPS_SYS 2135048f6b4dSbellard 2136590bc601SPaul Brook static int do_store_exclusive(CPUMIPSState *env) 2137590bc601SPaul Brook { 2138590bc601SPaul Brook target_ulong addr; 2139590bc601SPaul Brook target_ulong page_addr; 2140590bc601SPaul Brook target_ulong val; 2141590bc601SPaul Brook int flags; 2142590bc601SPaul Brook int segv = 0; 2143590bc601SPaul Brook int reg; 2144590bc601SPaul Brook int d; 2145590bc601SPaul Brook 21465499b6ffSAurelien Jarno addr = env->lladdr; 2147590bc601SPaul Brook page_addr = addr & TARGET_PAGE_MASK; 2148590bc601SPaul Brook start_exclusive(); 2149590bc601SPaul Brook mmap_lock(); 2150590bc601SPaul Brook flags = page_get_flags(page_addr); 2151590bc601SPaul Brook if ((flags & PAGE_READ) == 0) { 2152590bc601SPaul Brook segv = 1; 2153590bc601SPaul Brook } else { 2154590bc601SPaul Brook reg = env->llreg & 0x1f; 2155590bc601SPaul Brook d = (env->llreg & 0x20) != 0; 2156590bc601SPaul Brook if (d) { 2157590bc601SPaul Brook segv = get_user_s64(val, addr); 2158590bc601SPaul Brook } else { 2159590bc601SPaul Brook segv = get_user_s32(val, addr); 2160590bc601SPaul Brook } 2161590bc601SPaul Brook if (!segv) { 2162590bc601SPaul Brook if (val != env->llval) { 2163590bc601SPaul Brook env->active_tc.gpr[reg] = 0; 2164590bc601SPaul Brook } else { 2165590bc601SPaul Brook if (d) { 2166590bc601SPaul Brook segv = put_user_u64(env->llnewval, addr); 2167590bc601SPaul Brook } else { 2168590bc601SPaul Brook segv = put_user_u32(env->llnewval, addr); 2169590bc601SPaul Brook } 2170590bc601SPaul Brook if (!segv) { 2171590bc601SPaul Brook env->active_tc.gpr[reg] = 1; 2172590bc601SPaul Brook } 2173590bc601SPaul Brook } 2174590bc601SPaul Brook } 2175590bc601SPaul Brook } 21765499b6ffSAurelien Jarno env->lladdr = -1; 2177590bc601SPaul Brook if (!segv) { 2178590bc601SPaul Brook env->active_tc.PC += 4; 2179590bc601SPaul Brook } 2180590bc601SPaul Brook mmap_unlock(); 2181590bc601SPaul Brook end_exclusive(); 2182590bc601SPaul Brook return segv; 2183590bc601SPaul Brook } 2184590bc601SPaul Brook 2185048f6b4dSbellard void cpu_loop(CPUMIPSState *env) 2186048f6b4dSbellard { 2187c227f099SAnthony Liguori target_siginfo_t info; 2188388bb21aSths int trapnr, ret; 2189048f6b4dSbellard unsigned int syscall_num; 2190048f6b4dSbellard 2191048f6b4dSbellard for(;;) { 2192590bc601SPaul Brook cpu_exec_start(env); 2193048f6b4dSbellard trapnr = cpu_mips_exec(env); 2194590bc601SPaul Brook cpu_exec_end(env); 2195048f6b4dSbellard switch(trapnr) { 2196048f6b4dSbellard case EXCP_SYSCALL: 2197b5dc7732Sths syscall_num = env->active_tc.gpr[2] - 4000; 2198b5dc7732Sths env->active_tc.PC += 4; 2199048f6b4dSbellard if (syscall_num >= sizeof(mips_syscall_args)) { 22007c2f6157SWesley W. Terpstra ret = -TARGET_ENOSYS; 2201048f6b4dSbellard } else { 2202388bb21aSths int nb_args; 2203992f48a0Sblueswir1 abi_ulong sp_reg; 2204992f48a0Sblueswir1 abi_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0; 2205388bb21aSths 2206048f6b4dSbellard nb_args = mips_syscall_args[syscall_num]; 2207b5dc7732Sths sp_reg = env->active_tc.gpr[29]; 2208388bb21aSths switch (nb_args) { 2209048f6b4dSbellard /* these arguments are taken from the stack */ 221094c19610SAn-Cheng Huang case 8: 221194c19610SAn-Cheng Huang if ((ret = get_user_ual(arg8, sp_reg + 28)) != 0) { 221294c19610SAn-Cheng Huang goto done_syscall; 221394c19610SAn-Cheng Huang } 221494c19610SAn-Cheng Huang case 7: 221594c19610SAn-Cheng Huang if ((ret = get_user_ual(arg7, sp_reg + 24)) != 0) { 221694c19610SAn-Cheng Huang goto done_syscall; 221794c19610SAn-Cheng Huang } 221894c19610SAn-Cheng Huang case 6: 221994c19610SAn-Cheng Huang if ((ret = get_user_ual(arg6, sp_reg + 20)) != 0) { 222094c19610SAn-Cheng Huang goto done_syscall; 222194c19610SAn-Cheng Huang } 222294c19610SAn-Cheng Huang case 5: 222394c19610SAn-Cheng Huang if ((ret = get_user_ual(arg5, sp_reg + 16)) != 0) { 222494c19610SAn-Cheng Huang goto done_syscall; 222594c19610SAn-Cheng Huang } 2226388bb21aSths default: 2227388bb21aSths break; 2228048f6b4dSbellard } 2229b5dc7732Sths ret = do_syscall(env, env->active_tc.gpr[2], 2230b5dc7732Sths env->active_tc.gpr[4], 2231b5dc7732Sths env->active_tc.gpr[5], 2232b5dc7732Sths env->active_tc.gpr[6], 2233b5dc7732Sths env->active_tc.gpr[7], 22345945cfcbSPeter Maydell arg5, arg6, arg7, arg8); 2235048f6b4dSbellard } 223694c19610SAn-Cheng Huang done_syscall: 22370b1bcb00Spbrook if (ret == -TARGET_QEMU_ESIGRETURN) { 22380b1bcb00Spbrook /* Returning from a successful sigreturn syscall. 22390b1bcb00Spbrook Avoid clobbering register state. */ 22400b1bcb00Spbrook break; 22410b1bcb00Spbrook } 2242048f6b4dSbellard if ((unsigned int)ret >= (unsigned int)(-1133)) { 2243b5dc7732Sths env->active_tc.gpr[7] = 1; /* error flag */ 2244048f6b4dSbellard ret = -ret; 2245048f6b4dSbellard } else { 2246b5dc7732Sths env->active_tc.gpr[7] = 0; /* error flag */ 2247388bb21aSths } 2248b5dc7732Sths env->active_tc.gpr[2] = ret; 2249048f6b4dSbellard break; 2250ca7c2b1bSths case EXCP_TLBL: 2251ca7c2b1bSths case EXCP_TLBS: 2252e6e5bd2dSWesley W. Terpstra case EXCP_AdEL: 2253e6e5bd2dSWesley W. Terpstra case EXCP_AdES: 2254e4474235Spbrook info.si_signo = TARGET_SIGSEGV; 2255e4474235Spbrook info.si_errno = 0; 2256e4474235Spbrook /* XXX: check env->error_code */ 2257e4474235Spbrook info.si_code = TARGET_SEGV_MAPERR; 2258e4474235Spbrook info._sifields._sigfault._addr = env->CP0_BadVAddr; 2259e4474235Spbrook queue_signal(env, info.si_signo, &info); 2260e4474235Spbrook break; 22616900e84bSbellard case EXCP_CpU: 2262048f6b4dSbellard case EXCP_RI: 2263048f6b4dSbellard info.si_signo = TARGET_SIGILL; 2264048f6b4dSbellard info.si_errno = 0; 2265048f6b4dSbellard info.si_code = 0; 2266624f7979Spbrook queue_signal(env, info.si_signo, &info); 2267048f6b4dSbellard break; 2268106ec879Sbellard case EXCP_INTERRUPT: 2269106ec879Sbellard /* just indicate that signals should be handled asap */ 2270106ec879Sbellard break; 2271d08b2a28Spbrook case EXCP_DEBUG: 2272d08b2a28Spbrook { 2273d08b2a28Spbrook int sig; 2274d08b2a28Spbrook 2275d08b2a28Spbrook sig = gdb_handlesig (env, TARGET_SIGTRAP); 2276d08b2a28Spbrook if (sig) 2277d08b2a28Spbrook { 2278d08b2a28Spbrook info.si_signo = sig; 2279d08b2a28Spbrook info.si_errno = 0; 2280d08b2a28Spbrook info.si_code = TARGET_TRAP_BRKPT; 2281624f7979Spbrook queue_signal(env, info.si_signo, &info); 2282d08b2a28Spbrook } 2283d08b2a28Spbrook } 2284d08b2a28Spbrook break; 2285590bc601SPaul Brook case EXCP_SC: 2286590bc601SPaul Brook if (do_store_exclusive(env)) { 2287590bc601SPaul Brook info.si_signo = TARGET_SIGSEGV; 2288590bc601SPaul Brook info.si_errno = 0; 2289590bc601SPaul Brook info.si_code = TARGET_SEGV_MAPERR; 2290590bc601SPaul Brook info._sifields._sigfault._addr = env->active_tc.PC; 2291590bc601SPaul Brook queue_signal(env, info.si_signo, &info); 2292590bc601SPaul Brook } 2293590bc601SPaul Brook break; 2294853c3240SJia Liu case EXCP_DSPDIS: 2295853c3240SJia Liu info.si_signo = TARGET_SIGILL; 2296853c3240SJia Liu info.si_errno = 0; 2297853c3240SJia Liu info.si_code = TARGET_ILL_ILLOPC; 2298853c3240SJia Liu queue_signal(env, info.si_signo, &info); 2299853c3240SJia Liu break; 2300048f6b4dSbellard default: 2301048f6b4dSbellard // error: 2302048f6b4dSbellard fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", 2303048f6b4dSbellard trapnr); 2304048f6b4dSbellard cpu_dump_state(env, stderr, fprintf, 0); 2305048f6b4dSbellard abort(); 2306048f6b4dSbellard } 2307048f6b4dSbellard process_pending_signals(env); 2308048f6b4dSbellard } 2309048f6b4dSbellard } 2310048f6b4dSbellard #endif 2311048f6b4dSbellard 2312d962783eSJia Liu #ifdef TARGET_OPENRISC 2313d962783eSJia Liu 2314d962783eSJia Liu void cpu_loop(CPUOpenRISCState *env) 2315d962783eSJia Liu { 2316d962783eSJia Liu int trapnr, gdbsig; 2317d962783eSJia Liu 2318d962783eSJia Liu for (;;) { 2319d962783eSJia Liu trapnr = cpu_exec(env); 2320d962783eSJia Liu gdbsig = 0; 2321d962783eSJia Liu 2322d962783eSJia Liu switch (trapnr) { 2323d962783eSJia Liu case EXCP_RESET: 2324d962783eSJia Liu qemu_log("\nReset request, exit, pc is %#x\n", env->pc); 2325d962783eSJia Liu exit(1); 2326d962783eSJia Liu break; 2327d962783eSJia Liu case EXCP_BUSERR: 2328d962783eSJia Liu qemu_log("\nBus error, exit, pc is %#x\n", env->pc); 2329d962783eSJia Liu gdbsig = SIGBUS; 2330d962783eSJia Liu break; 2331d962783eSJia Liu case EXCP_DPF: 2332d962783eSJia Liu case EXCP_IPF: 2333d962783eSJia Liu cpu_dump_state(env, stderr, fprintf, 0); 2334d962783eSJia Liu gdbsig = TARGET_SIGSEGV; 2335d962783eSJia Liu break; 2336d962783eSJia Liu case EXCP_TICK: 2337d962783eSJia Liu qemu_log("\nTick time interrupt pc is %#x\n", env->pc); 2338d962783eSJia Liu break; 2339d962783eSJia Liu case EXCP_ALIGN: 2340d962783eSJia Liu qemu_log("\nAlignment pc is %#x\n", env->pc); 2341d962783eSJia Liu gdbsig = SIGBUS; 2342d962783eSJia Liu break; 2343d962783eSJia Liu case EXCP_ILLEGAL: 2344d962783eSJia Liu qemu_log("\nIllegal instructionpc is %#x\n", env->pc); 2345d962783eSJia Liu gdbsig = SIGILL; 2346d962783eSJia Liu break; 2347d962783eSJia Liu case EXCP_INT: 2348d962783eSJia Liu qemu_log("\nExternal interruptpc is %#x\n", env->pc); 2349d962783eSJia Liu break; 2350d962783eSJia Liu case EXCP_DTLBMISS: 2351d962783eSJia Liu case EXCP_ITLBMISS: 2352d962783eSJia Liu qemu_log("\nTLB miss\n"); 2353d962783eSJia Liu break; 2354d962783eSJia Liu case EXCP_RANGE: 2355d962783eSJia Liu qemu_log("\nRange\n"); 2356d962783eSJia Liu gdbsig = SIGSEGV; 2357d962783eSJia Liu break; 2358d962783eSJia Liu case EXCP_SYSCALL: 2359d962783eSJia Liu env->pc += 4; /* 0xc00; */ 2360d962783eSJia Liu env->gpr[11] = do_syscall(env, 2361d962783eSJia Liu env->gpr[11], /* return value */ 2362d962783eSJia Liu env->gpr[3], /* r3 - r7 are params */ 2363d962783eSJia Liu env->gpr[4], 2364d962783eSJia Liu env->gpr[5], 2365d962783eSJia Liu env->gpr[6], 2366d962783eSJia Liu env->gpr[7], 2367d962783eSJia Liu env->gpr[8], 0, 0); 2368d962783eSJia Liu break; 2369d962783eSJia Liu case EXCP_FPE: 2370d962783eSJia Liu qemu_log("\nFloating point error\n"); 2371d962783eSJia Liu break; 2372d962783eSJia Liu case EXCP_TRAP: 2373d962783eSJia Liu qemu_log("\nTrap\n"); 2374d962783eSJia Liu gdbsig = SIGTRAP; 2375d962783eSJia Liu break; 2376d962783eSJia Liu case EXCP_NR: 2377d962783eSJia Liu qemu_log("\nNR\n"); 2378d962783eSJia Liu break; 2379d962783eSJia Liu default: 2380d962783eSJia Liu qemu_log("\nqemu: unhandled CPU exception %#x - aborting\n", 2381d962783eSJia Liu trapnr); 2382d962783eSJia Liu cpu_dump_state(env, stderr, fprintf, 0); 2383d962783eSJia Liu gdbsig = TARGET_SIGILL; 2384d962783eSJia Liu break; 2385d962783eSJia Liu } 2386d962783eSJia Liu if (gdbsig) { 2387d962783eSJia Liu gdb_handlesig(env, gdbsig); 2388d962783eSJia Liu if (gdbsig != TARGET_SIGTRAP) { 2389d962783eSJia Liu exit(1); 2390d962783eSJia Liu } 2391d962783eSJia Liu } 2392d962783eSJia Liu 2393d962783eSJia Liu process_pending_signals(env); 2394d962783eSJia Liu } 2395d962783eSJia Liu } 2396d962783eSJia Liu 2397d962783eSJia Liu #endif /* TARGET_OPENRISC */ 2398d962783eSJia Liu 2399fdf9b3e8Sbellard #ifdef TARGET_SH4 240005390248SAndreas Färber void cpu_loop(CPUSH4State *env) 2401fdf9b3e8Sbellard { 2402fdf9b3e8Sbellard int trapnr, ret; 2403c227f099SAnthony Liguori target_siginfo_t info; 2404fdf9b3e8Sbellard 2405fdf9b3e8Sbellard while (1) { 2406fdf9b3e8Sbellard trapnr = cpu_sh4_exec (env); 2407fdf9b3e8Sbellard 2408fdf9b3e8Sbellard switch (trapnr) { 2409fdf9b3e8Sbellard case 0x160: 24100b6d3ae0Saurel32 env->pc += 2; 2411fdf9b3e8Sbellard ret = do_syscall(env, 24129c2a9ea1Spbrook env->gregs[3], 24139c2a9ea1Spbrook env->gregs[4], 24149c2a9ea1Spbrook env->gregs[5], 24159c2a9ea1Spbrook env->gregs[6], 24169c2a9ea1Spbrook env->gregs[7], 24179c2a9ea1Spbrook env->gregs[0], 24185945cfcbSPeter Maydell env->gregs[1], 24195945cfcbSPeter Maydell 0, 0); 24209c2a9ea1Spbrook env->gregs[0] = ret; 2421fdf9b3e8Sbellard break; 2422c3b5bc8aSths case EXCP_INTERRUPT: 2423c3b5bc8aSths /* just indicate that signals should be handled asap */ 2424c3b5bc8aSths break; 2425355fb23dSpbrook case EXCP_DEBUG: 2426355fb23dSpbrook { 2427355fb23dSpbrook int sig; 2428355fb23dSpbrook 2429355fb23dSpbrook sig = gdb_handlesig (env, TARGET_SIGTRAP); 2430355fb23dSpbrook if (sig) 2431355fb23dSpbrook { 2432355fb23dSpbrook info.si_signo = sig; 2433355fb23dSpbrook info.si_errno = 0; 2434355fb23dSpbrook info.si_code = TARGET_TRAP_BRKPT; 2435624f7979Spbrook queue_signal(env, info.si_signo, &info); 2436355fb23dSpbrook } 2437355fb23dSpbrook } 2438355fb23dSpbrook break; 2439c3b5bc8aSths case 0xa0: 2440c3b5bc8aSths case 0xc0: 2441c3b5bc8aSths info.si_signo = SIGSEGV; 2442c3b5bc8aSths info.si_errno = 0; 2443c3b5bc8aSths info.si_code = TARGET_SEGV_MAPERR; 2444c3b5bc8aSths info._sifields._sigfault._addr = env->tea; 2445624f7979Spbrook queue_signal(env, info.si_signo, &info); 2446c3b5bc8aSths break; 2447c3b5bc8aSths 2448fdf9b3e8Sbellard default: 2449fdf9b3e8Sbellard printf ("Unhandled trap: 0x%x\n", trapnr); 2450fdf9b3e8Sbellard cpu_dump_state(env, stderr, fprintf, 0); 2451fdf9b3e8Sbellard exit (1); 2452fdf9b3e8Sbellard } 2453fdf9b3e8Sbellard process_pending_signals (env); 2454fdf9b3e8Sbellard } 2455fdf9b3e8Sbellard } 2456fdf9b3e8Sbellard #endif 2457fdf9b3e8Sbellard 245848733d19Sths #ifdef TARGET_CRIS 245905390248SAndreas Färber void cpu_loop(CPUCRISState *env) 246048733d19Sths { 246148733d19Sths int trapnr, ret; 2462c227f099SAnthony Liguori target_siginfo_t info; 246348733d19Sths 246448733d19Sths while (1) { 246548733d19Sths trapnr = cpu_cris_exec (env); 246648733d19Sths switch (trapnr) { 246748733d19Sths case 0xaa: 246848733d19Sths { 246948733d19Sths info.si_signo = SIGSEGV; 247048733d19Sths info.si_errno = 0; 247148733d19Sths /* XXX: check env->error_code */ 247248733d19Sths info.si_code = TARGET_SEGV_MAPERR; 2473e00c1e71Sedgar_igl info._sifields._sigfault._addr = env->pregs[PR_EDA]; 2474624f7979Spbrook queue_signal(env, info.si_signo, &info); 247548733d19Sths } 247648733d19Sths break; 2477b6d3abdaSedgar_igl case EXCP_INTERRUPT: 2478b6d3abdaSedgar_igl /* just indicate that signals should be handled asap */ 2479b6d3abdaSedgar_igl break; 248048733d19Sths case EXCP_BREAK: 248148733d19Sths ret = do_syscall(env, 248248733d19Sths env->regs[9], 248348733d19Sths env->regs[10], 248448733d19Sths env->regs[11], 248548733d19Sths env->regs[12], 248648733d19Sths env->regs[13], 248748733d19Sths env->pregs[7], 24885945cfcbSPeter Maydell env->pregs[11], 24895945cfcbSPeter Maydell 0, 0); 249048733d19Sths env->regs[10] = ret; 249148733d19Sths break; 249248733d19Sths case EXCP_DEBUG: 249348733d19Sths { 249448733d19Sths int sig; 249548733d19Sths 249648733d19Sths sig = gdb_handlesig (env, TARGET_SIGTRAP); 249748733d19Sths if (sig) 249848733d19Sths { 249948733d19Sths info.si_signo = sig; 250048733d19Sths info.si_errno = 0; 250148733d19Sths info.si_code = TARGET_TRAP_BRKPT; 2502624f7979Spbrook queue_signal(env, info.si_signo, &info); 250348733d19Sths } 250448733d19Sths } 250548733d19Sths break; 250648733d19Sths default: 250748733d19Sths printf ("Unhandled trap: 0x%x\n", trapnr); 250848733d19Sths cpu_dump_state(env, stderr, fprintf, 0); 250948733d19Sths exit (1); 251048733d19Sths } 251148733d19Sths process_pending_signals (env); 251248733d19Sths } 251348733d19Sths } 251448733d19Sths #endif 251548733d19Sths 2516b779e29eSEdgar E. Iglesias #ifdef TARGET_MICROBLAZE 251705390248SAndreas Färber void cpu_loop(CPUMBState *env) 2518b779e29eSEdgar E. Iglesias { 2519b779e29eSEdgar E. Iglesias int trapnr, ret; 2520c227f099SAnthony Liguori target_siginfo_t info; 2521b779e29eSEdgar E. Iglesias 2522b779e29eSEdgar E. Iglesias while (1) { 2523b779e29eSEdgar E. Iglesias trapnr = cpu_mb_exec (env); 2524b779e29eSEdgar E. Iglesias switch (trapnr) { 2525b779e29eSEdgar E. Iglesias case 0xaa: 2526b779e29eSEdgar E. Iglesias { 2527b779e29eSEdgar E. Iglesias info.si_signo = SIGSEGV; 2528b779e29eSEdgar E. Iglesias info.si_errno = 0; 2529b779e29eSEdgar E. Iglesias /* XXX: check env->error_code */ 2530b779e29eSEdgar E. Iglesias info.si_code = TARGET_SEGV_MAPERR; 2531b779e29eSEdgar E. Iglesias info._sifields._sigfault._addr = 0; 2532b779e29eSEdgar E. Iglesias queue_signal(env, info.si_signo, &info); 2533b779e29eSEdgar E. Iglesias } 2534b779e29eSEdgar E. Iglesias break; 2535b779e29eSEdgar E. Iglesias case EXCP_INTERRUPT: 2536b779e29eSEdgar E. Iglesias /* just indicate that signals should be handled asap */ 2537b779e29eSEdgar E. Iglesias break; 2538b779e29eSEdgar E. Iglesias case EXCP_BREAK: 2539b779e29eSEdgar E. Iglesias /* Return address is 4 bytes after the call. */ 2540b779e29eSEdgar E. Iglesias env->regs[14] += 4; 2541d7dce494SEdgar E. Iglesias env->sregs[SR_PC] = env->regs[14]; 2542b779e29eSEdgar E. Iglesias ret = do_syscall(env, 2543b779e29eSEdgar E. Iglesias env->regs[12], 2544b779e29eSEdgar E. Iglesias env->regs[5], 2545b779e29eSEdgar E. Iglesias env->regs[6], 2546b779e29eSEdgar E. Iglesias env->regs[7], 2547b779e29eSEdgar E. Iglesias env->regs[8], 2548b779e29eSEdgar E. Iglesias env->regs[9], 25495945cfcbSPeter Maydell env->regs[10], 25505945cfcbSPeter Maydell 0, 0); 2551b779e29eSEdgar E. Iglesias env->regs[3] = ret; 2552b779e29eSEdgar E. Iglesias break; 2553b76da7e3SEdgar E. Iglesias case EXCP_HW_EXCP: 2554b76da7e3SEdgar E. Iglesias env->regs[17] = env->sregs[SR_PC] + 4; 2555b76da7e3SEdgar E. Iglesias if (env->iflags & D_FLAG) { 2556b76da7e3SEdgar E. Iglesias env->sregs[SR_ESR] |= 1 << 12; 2557b76da7e3SEdgar E. Iglesias env->sregs[SR_PC] -= 4; 2558b76da7e3SEdgar E. Iglesias /* FIXME: if branch was immed, replay the imm as well. */ 2559b76da7e3SEdgar E. Iglesias } 2560b76da7e3SEdgar E. Iglesias 2561b76da7e3SEdgar E. Iglesias env->iflags &= ~(IMM_FLAG | D_FLAG); 2562b76da7e3SEdgar E. Iglesias 2563b76da7e3SEdgar E. Iglesias switch (env->sregs[SR_ESR] & 31) { 256422a78d64SEdgar E. Iglesias case ESR_EC_DIVZERO: 256522a78d64SEdgar E. Iglesias info.si_signo = SIGFPE; 256622a78d64SEdgar E. Iglesias info.si_errno = 0; 256722a78d64SEdgar E. Iglesias info.si_code = TARGET_FPE_FLTDIV; 256822a78d64SEdgar E. Iglesias info._sifields._sigfault._addr = 0; 256922a78d64SEdgar E. Iglesias queue_signal(env, info.si_signo, &info); 257022a78d64SEdgar E. Iglesias break; 2571b76da7e3SEdgar E. Iglesias case ESR_EC_FPU: 2572b76da7e3SEdgar E. Iglesias info.si_signo = SIGFPE; 2573b76da7e3SEdgar E. Iglesias info.si_errno = 0; 2574b76da7e3SEdgar E. Iglesias if (env->sregs[SR_FSR] & FSR_IO) { 2575b76da7e3SEdgar E. Iglesias info.si_code = TARGET_FPE_FLTINV; 2576b76da7e3SEdgar E. Iglesias } 2577b76da7e3SEdgar E. Iglesias if (env->sregs[SR_FSR] & FSR_DZ) { 2578b76da7e3SEdgar E. Iglesias info.si_code = TARGET_FPE_FLTDIV; 2579b76da7e3SEdgar E. Iglesias } 2580b76da7e3SEdgar E. Iglesias info._sifields._sigfault._addr = 0; 2581b76da7e3SEdgar E. Iglesias queue_signal(env, info.si_signo, &info); 2582b76da7e3SEdgar E. Iglesias break; 2583b76da7e3SEdgar E. Iglesias default: 2584b76da7e3SEdgar E. Iglesias printf ("Unhandled hw-exception: 0x%x\n", 25852e42d52dSEdgar E. Iglesias env->sregs[SR_ESR] & ESR_EC_MASK); 2586b76da7e3SEdgar E. Iglesias cpu_dump_state(env, stderr, fprintf, 0); 2587b76da7e3SEdgar E. Iglesias exit (1); 2588b76da7e3SEdgar E. Iglesias break; 2589b76da7e3SEdgar E. Iglesias } 2590b76da7e3SEdgar E. Iglesias break; 2591b779e29eSEdgar E. Iglesias case EXCP_DEBUG: 2592b779e29eSEdgar E. Iglesias { 2593b779e29eSEdgar E. Iglesias int sig; 2594b779e29eSEdgar E. Iglesias 2595b779e29eSEdgar E. Iglesias sig = gdb_handlesig (env, TARGET_SIGTRAP); 2596b779e29eSEdgar E. Iglesias if (sig) 2597b779e29eSEdgar E. Iglesias { 2598b779e29eSEdgar E. Iglesias info.si_signo = sig; 2599b779e29eSEdgar E. Iglesias info.si_errno = 0; 2600b779e29eSEdgar E. Iglesias info.si_code = TARGET_TRAP_BRKPT; 2601b779e29eSEdgar E. Iglesias queue_signal(env, info.si_signo, &info); 2602b779e29eSEdgar E. Iglesias } 2603b779e29eSEdgar E. Iglesias } 2604b779e29eSEdgar E. Iglesias break; 2605b779e29eSEdgar E. Iglesias default: 2606b779e29eSEdgar E. Iglesias printf ("Unhandled trap: 0x%x\n", trapnr); 2607b779e29eSEdgar E. Iglesias cpu_dump_state(env, stderr, fprintf, 0); 2608b779e29eSEdgar E. Iglesias exit (1); 2609b779e29eSEdgar E. Iglesias } 2610b779e29eSEdgar E. Iglesias process_pending_signals (env); 2611b779e29eSEdgar E. Iglesias } 2612b779e29eSEdgar E. Iglesias } 2613b779e29eSEdgar E. Iglesias #endif 2614b779e29eSEdgar E. Iglesias 2615e6e5906bSpbrook #ifdef TARGET_M68K 2616e6e5906bSpbrook 2617e6e5906bSpbrook void cpu_loop(CPUM68KState *env) 2618e6e5906bSpbrook { 2619e6e5906bSpbrook int trapnr; 2620e6e5906bSpbrook unsigned int n; 2621c227f099SAnthony Liguori target_siginfo_t info; 2622e6e5906bSpbrook TaskState *ts = env->opaque; 2623e6e5906bSpbrook 2624e6e5906bSpbrook for(;;) { 2625e6e5906bSpbrook trapnr = cpu_m68k_exec(env); 2626e6e5906bSpbrook switch(trapnr) { 2627e6e5906bSpbrook case EXCP_ILLEGAL: 2628e6e5906bSpbrook { 2629e6e5906bSpbrook if (ts->sim_syscalls) { 2630e6e5906bSpbrook uint16_t nr; 2631e6e5906bSpbrook nr = lduw(env->pc + 2); 2632e6e5906bSpbrook env->pc += 4; 2633e6e5906bSpbrook do_m68k_simcall(env, nr); 2634e6e5906bSpbrook } else { 2635e6e5906bSpbrook goto do_sigill; 2636e6e5906bSpbrook } 2637e6e5906bSpbrook } 2638e6e5906bSpbrook break; 2639a87295e8Spbrook case EXCP_HALT_INSN: 2640e6e5906bSpbrook /* Semihosing syscall. */ 2641a87295e8Spbrook env->pc += 4; 2642e6e5906bSpbrook do_m68k_semihosting(env, env->dregs[0]); 2643e6e5906bSpbrook break; 2644e6e5906bSpbrook case EXCP_LINEA: 2645e6e5906bSpbrook case EXCP_LINEF: 2646e6e5906bSpbrook case EXCP_UNSUPPORTED: 2647e6e5906bSpbrook do_sigill: 2648e6e5906bSpbrook info.si_signo = SIGILL; 2649e6e5906bSpbrook info.si_errno = 0; 2650e6e5906bSpbrook info.si_code = TARGET_ILL_ILLOPN; 2651e6e5906bSpbrook info._sifields._sigfault._addr = env->pc; 2652624f7979Spbrook queue_signal(env, info.si_signo, &info); 2653e6e5906bSpbrook break; 2654e6e5906bSpbrook case EXCP_TRAP0: 2655e6e5906bSpbrook { 2656e6e5906bSpbrook ts->sim_syscalls = 0; 2657e6e5906bSpbrook n = env->dregs[0]; 2658e6e5906bSpbrook env->pc += 2; 2659e6e5906bSpbrook env->dregs[0] = do_syscall(env, 2660e6e5906bSpbrook n, 2661e6e5906bSpbrook env->dregs[1], 2662e6e5906bSpbrook env->dregs[2], 2663e6e5906bSpbrook env->dregs[3], 2664e6e5906bSpbrook env->dregs[4], 2665e6e5906bSpbrook env->dregs[5], 26665945cfcbSPeter Maydell env->aregs[0], 26675945cfcbSPeter Maydell 0, 0); 2668e6e5906bSpbrook } 2669e6e5906bSpbrook break; 2670e6e5906bSpbrook case EXCP_INTERRUPT: 2671e6e5906bSpbrook /* just indicate that signals should be handled asap */ 2672e6e5906bSpbrook break; 2673e6e5906bSpbrook case EXCP_ACCESS: 2674e6e5906bSpbrook { 2675e6e5906bSpbrook info.si_signo = SIGSEGV; 2676e6e5906bSpbrook info.si_errno = 0; 2677e6e5906bSpbrook /* XXX: check env->error_code */ 2678e6e5906bSpbrook info.si_code = TARGET_SEGV_MAPERR; 2679e6e5906bSpbrook info._sifields._sigfault._addr = env->mmu.ar; 2680624f7979Spbrook queue_signal(env, info.si_signo, &info); 2681e6e5906bSpbrook } 2682e6e5906bSpbrook break; 2683e6e5906bSpbrook case EXCP_DEBUG: 2684e6e5906bSpbrook { 2685e6e5906bSpbrook int sig; 2686e6e5906bSpbrook 2687e6e5906bSpbrook sig = gdb_handlesig (env, TARGET_SIGTRAP); 2688e6e5906bSpbrook if (sig) 2689e6e5906bSpbrook { 2690e6e5906bSpbrook info.si_signo = sig; 2691e6e5906bSpbrook info.si_errno = 0; 2692e6e5906bSpbrook info.si_code = TARGET_TRAP_BRKPT; 2693624f7979Spbrook queue_signal(env, info.si_signo, &info); 2694e6e5906bSpbrook } 2695e6e5906bSpbrook } 2696e6e5906bSpbrook break; 2697e6e5906bSpbrook default: 2698e6e5906bSpbrook fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", 2699e6e5906bSpbrook trapnr); 2700e6e5906bSpbrook cpu_dump_state(env, stderr, fprintf, 0); 2701e6e5906bSpbrook abort(); 2702e6e5906bSpbrook } 2703e6e5906bSpbrook process_pending_signals(env); 2704e6e5906bSpbrook } 2705e6e5906bSpbrook } 2706e6e5906bSpbrook #endif /* TARGET_M68K */ 2707e6e5906bSpbrook 27087a3148a9Sj_mayer #ifdef TARGET_ALPHA 27096910b8f6SRichard Henderson static void do_store_exclusive(CPUAlphaState *env, int reg, int quad) 27106910b8f6SRichard Henderson { 27116910b8f6SRichard Henderson target_ulong addr, val, tmp; 27126910b8f6SRichard Henderson target_siginfo_t info; 27136910b8f6SRichard Henderson int ret = 0; 27146910b8f6SRichard Henderson 27156910b8f6SRichard Henderson addr = env->lock_addr; 27166910b8f6SRichard Henderson tmp = env->lock_st_addr; 27176910b8f6SRichard Henderson env->lock_addr = -1; 27186910b8f6SRichard Henderson env->lock_st_addr = 0; 27196910b8f6SRichard Henderson 27206910b8f6SRichard Henderson start_exclusive(); 27216910b8f6SRichard Henderson mmap_lock(); 27226910b8f6SRichard Henderson 27236910b8f6SRichard Henderson if (addr == tmp) { 27246910b8f6SRichard Henderson if (quad ? get_user_s64(val, addr) : get_user_s32(val, addr)) { 27256910b8f6SRichard Henderson goto do_sigsegv; 27266910b8f6SRichard Henderson } 27276910b8f6SRichard Henderson 27286910b8f6SRichard Henderson if (val == env->lock_value) { 27296910b8f6SRichard Henderson tmp = env->ir[reg]; 27306910b8f6SRichard Henderson if (quad ? put_user_u64(tmp, addr) : put_user_u32(tmp, addr)) { 27316910b8f6SRichard Henderson goto do_sigsegv; 27326910b8f6SRichard Henderson } 27336910b8f6SRichard Henderson ret = 1; 27346910b8f6SRichard Henderson } 27356910b8f6SRichard Henderson } 27366910b8f6SRichard Henderson env->ir[reg] = ret; 27376910b8f6SRichard Henderson env->pc += 4; 27386910b8f6SRichard Henderson 27396910b8f6SRichard Henderson mmap_unlock(); 27406910b8f6SRichard Henderson end_exclusive(); 27416910b8f6SRichard Henderson return; 27426910b8f6SRichard Henderson 27436910b8f6SRichard Henderson do_sigsegv: 27446910b8f6SRichard Henderson mmap_unlock(); 27456910b8f6SRichard Henderson end_exclusive(); 27466910b8f6SRichard Henderson 27476910b8f6SRichard Henderson info.si_signo = TARGET_SIGSEGV; 27486910b8f6SRichard Henderson info.si_errno = 0; 27496910b8f6SRichard Henderson info.si_code = TARGET_SEGV_MAPERR; 27506910b8f6SRichard Henderson info._sifields._sigfault._addr = addr; 27516910b8f6SRichard Henderson queue_signal(env, TARGET_SIGSEGV, &info); 27526910b8f6SRichard Henderson } 27536910b8f6SRichard Henderson 275405390248SAndreas Färber void cpu_loop(CPUAlphaState *env) 27557a3148a9Sj_mayer { 2756e96efcfcSj_mayer int trapnr; 2757c227f099SAnthony Liguori target_siginfo_t info; 27586049f4f8SRichard Henderson abi_long sysret; 27597a3148a9Sj_mayer 27607a3148a9Sj_mayer while (1) { 27617a3148a9Sj_mayer trapnr = cpu_alpha_exec (env); 27627a3148a9Sj_mayer 2763ac316ca4SRichard Henderson /* All of the traps imply a transition through PALcode, which 2764ac316ca4SRichard Henderson implies an REI instruction has been executed. Which means 2765ac316ca4SRichard Henderson that the intr_flag should be cleared. */ 2766ac316ca4SRichard Henderson env->intr_flag = 0; 2767ac316ca4SRichard Henderson 27687a3148a9Sj_mayer switch (trapnr) { 27697a3148a9Sj_mayer case EXCP_RESET: 27707a3148a9Sj_mayer fprintf(stderr, "Reset requested. Exit\n"); 27717a3148a9Sj_mayer exit(1); 27727a3148a9Sj_mayer break; 27737a3148a9Sj_mayer case EXCP_MCHK: 27747a3148a9Sj_mayer fprintf(stderr, "Machine check exception. Exit\n"); 27757a3148a9Sj_mayer exit(1); 27767a3148a9Sj_mayer break; 277707b6c13bSRichard Henderson case EXCP_SMP_INTERRUPT: 277807b6c13bSRichard Henderson case EXCP_CLK_INTERRUPT: 277907b6c13bSRichard Henderson case EXCP_DEV_INTERRUPT: 27807a3148a9Sj_mayer fprintf(stderr, "External interrupt. Exit\n"); 27817a3148a9Sj_mayer exit(1); 27827a3148a9Sj_mayer break; 278307b6c13bSRichard Henderson case EXCP_MMFAULT: 27846910b8f6SRichard Henderson env->lock_addr = -1; 27856049f4f8SRichard Henderson info.si_signo = TARGET_SIGSEGV; 27866049f4f8SRichard Henderson info.si_errno = 0; 2787129d8aa5SRichard Henderson info.si_code = (page_get_flags(env->trap_arg0) & PAGE_VALID 27880be1d07cSRichard Henderson ? TARGET_SEGV_ACCERR : TARGET_SEGV_MAPERR); 2789129d8aa5SRichard Henderson info._sifields._sigfault._addr = env->trap_arg0; 27906049f4f8SRichard Henderson queue_signal(env, info.si_signo, &info); 27917a3148a9Sj_mayer break; 27927a3148a9Sj_mayer case EXCP_UNALIGN: 27936910b8f6SRichard Henderson env->lock_addr = -1; 27946049f4f8SRichard Henderson info.si_signo = TARGET_SIGBUS; 27956049f4f8SRichard Henderson info.si_errno = 0; 27966049f4f8SRichard Henderson info.si_code = TARGET_BUS_ADRALN; 2797129d8aa5SRichard Henderson info._sifields._sigfault._addr = env->trap_arg0; 27986049f4f8SRichard Henderson queue_signal(env, info.si_signo, &info); 27997a3148a9Sj_mayer break; 28007a3148a9Sj_mayer case EXCP_OPCDEC: 28016049f4f8SRichard Henderson do_sigill: 28026910b8f6SRichard Henderson env->lock_addr = -1; 28036049f4f8SRichard Henderson info.si_signo = TARGET_SIGILL; 28046049f4f8SRichard Henderson info.si_errno = 0; 28056049f4f8SRichard Henderson info.si_code = TARGET_ILL_ILLOPC; 28066049f4f8SRichard Henderson info._sifields._sigfault._addr = env->pc; 28076049f4f8SRichard Henderson queue_signal(env, info.si_signo, &info); 28087a3148a9Sj_mayer break; 280907b6c13bSRichard Henderson case EXCP_ARITH: 281007b6c13bSRichard Henderson env->lock_addr = -1; 281107b6c13bSRichard Henderson info.si_signo = TARGET_SIGFPE; 281207b6c13bSRichard Henderson info.si_errno = 0; 281307b6c13bSRichard Henderson info.si_code = TARGET_FPE_FLTINV; 281407b6c13bSRichard Henderson info._sifields._sigfault._addr = env->pc; 281507b6c13bSRichard Henderson queue_signal(env, info.si_signo, &info); 281607b6c13bSRichard Henderson break; 28177a3148a9Sj_mayer case EXCP_FEN: 28186049f4f8SRichard Henderson /* No-op. Linux simply re-enables the FPU. */ 28197a3148a9Sj_mayer break; 282007b6c13bSRichard Henderson case EXCP_CALL_PAL: 28216910b8f6SRichard Henderson env->lock_addr = -1; 282207b6c13bSRichard Henderson switch (env->error_code) { 28236049f4f8SRichard Henderson case 0x80: 28246049f4f8SRichard Henderson /* BPT */ 28256049f4f8SRichard Henderson info.si_signo = TARGET_SIGTRAP; 28266049f4f8SRichard Henderson info.si_errno = 0; 28276049f4f8SRichard Henderson info.si_code = TARGET_TRAP_BRKPT; 28286049f4f8SRichard Henderson info._sifields._sigfault._addr = env->pc; 28296049f4f8SRichard Henderson queue_signal(env, info.si_signo, &info); 28306049f4f8SRichard Henderson break; 28316049f4f8SRichard Henderson case 0x81: 28326049f4f8SRichard Henderson /* BUGCHK */ 28336049f4f8SRichard Henderson info.si_signo = TARGET_SIGTRAP; 28346049f4f8SRichard Henderson info.si_errno = 0; 28356049f4f8SRichard Henderson info.si_code = 0; 28366049f4f8SRichard Henderson info._sifields._sigfault._addr = env->pc; 28376049f4f8SRichard Henderson queue_signal(env, info.si_signo, &info); 28386049f4f8SRichard Henderson break; 28396049f4f8SRichard Henderson case 0x83: 28406049f4f8SRichard Henderson /* CALLSYS */ 28416049f4f8SRichard Henderson trapnr = env->ir[IR_V0]; 28426049f4f8SRichard Henderson sysret = do_syscall(env, trapnr, 28436049f4f8SRichard Henderson env->ir[IR_A0], env->ir[IR_A1], 28446049f4f8SRichard Henderson env->ir[IR_A2], env->ir[IR_A3], 28455945cfcbSPeter Maydell env->ir[IR_A4], env->ir[IR_A5], 28465945cfcbSPeter Maydell 0, 0); 2847a5b3b13bSRichard Henderson if (trapnr == TARGET_NR_sigreturn 2848a5b3b13bSRichard Henderson || trapnr == TARGET_NR_rt_sigreturn) { 2849a5b3b13bSRichard Henderson break; 2850a5b3b13bSRichard Henderson } 2851a5b3b13bSRichard Henderson /* Syscall writes 0 to V0 to bypass error check, similar 28520e141977SRichard Henderson to how this is handled internal to Linux kernel. 28530e141977SRichard Henderson (Ab)use trapnr temporarily as boolean indicating error. */ 28540e141977SRichard Henderson trapnr = (env->ir[IR_V0] != 0 && sysret < 0); 28550e141977SRichard Henderson env->ir[IR_V0] = (trapnr ? -sysret : sysret); 28560e141977SRichard Henderson env->ir[IR_A3] = trapnr; 28576049f4f8SRichard Henderson break; 28586049f4f8SRichard Henderson case 0x86: 28596049f4f8SRichard Henderson /* IMB */ 28606049f4f8SRichard Henderson /* ??? We can probably elide the code using page_unprotect 28616049f4f8SRichard Henderson that is checking for self-modifying code. Instead we 28626049f4f8SRichard Henderson could simply call tb_flush here. Until we work out the 28636049f4f8SRichard Henderson changes required to turn off the extra write protection, 28646049f4f8SRichard Henderson this can be a no-op. */ 28656049f4f8SRichard Henderson break; 28666049f4f8SRichard Henderson case 0x9E: 28676049f4f8SRichard Henderson /* RDUNIQUE */ 28686049f4f8SRichard Henderson /* Handled in the translator for usermode. */ 28696049f4f8SRichard Henderson abort(); 28706049f4f8SRichard Henderson case 0x9F: 28716049f4f8SRichard Henderson /* WRUNIQUE */ 28726049f4f8SRichard Henderson /* Handled in the translator for usermode. */ 28736049f4f8SRichard Henderson abort(); 28746049f4f8SRichard Henderson case 0xAA: 28756049f4f8SRichard Henderson /* GENTRAP */ 28766049f4f8SRichard Henderson info.si_signo = TARGET_SIGFPE; 28776049f4f8SRichard Henderson switch (env->ir[IR_A0]) { 28786049f4f8SRichard Henderson case TARGET_GEN_INTOVF: 28796049f4f8SRichard Henderson info.si_code = TARGET_FPE_INTOVF; 28806049f4f8SRichard Henderson break; 28816049f4f8SRichard Henderson case TARGET_GEN_INTDIV: 28826049f4f8SRichard Henderson info.si_code = TARGET_FPE_INTDIV; 28836049f4f8SRichard Henderson break; 28846049f4f8SRichard Henderson case TARGET_GEN_FLTOVF: 28856049f4f8SRichard Henderson info.si_code = TARGET_FPE_FLTOVF; 28866049f4f8SRichard Henderson break; 28876049f4f8SRichard Henderson case TARGET_GEN_FLTUND: 28886049f4f8SRichard Henderson info.si_code = TARGET_FPE_FLTUND; 28896049f4f8SRichard Henderson break; 28906049f4f8SRichard Henderson case TARGET_GEN_FLTINV: 28916049f4f8SRichard Henderson info.si_code = TARGET_FPE_FLTINV; 28926049f4f8SRichard Henderson break; 28936049f4f8SRichard Henderson case TARGET_GEN_FLTINE: 28946049f4f8SRichard Henderson info.si_code = TARGET_FPE_FLTRES; 28956049f4f8SRichard Henderson break; 28966049f4f8SRichard Henderson case TARGET_GEN_ROPRAND: 28976049f4f8SRichard Henderson info.si_code = 0; 28986049f4f8SRichard Henderson break; 28996049f4f8SRichard Henderson default: 29006049f4f8SRichard Henderson info.si_signo = TARGET_SIGTRAP; 29016049f4f8SRichard Henderson info.si_code = 0; 29026049f4f8SRichard Henderson break; 29036049f4f8SRichard Henderson } 29046049f4f8SRichard Henderson info.si_errno = 0; 29056049f4f8SRichard Henderson info._sifields._sigfault._addr = env->pc; 29066049f4f8SRichard Henderson queue_signal(env, info.si_signo, &info); 29076049f4f8SRichard Henderson break; 29086049f4f8SRichard Henderson default: 29096049f4f8SRichard Henderson goto do_sigill; 29106049f4f8SRichard Henderson } 29117a3148a9Sj_mayer break; 29127a3148a9Sj_mayer case EXCP_DEBUG: 29136049f4f8SRichard Henderson info.si_signo = gdb_handlesig (env, TARGET_SIGTRAP); 29146049f4f8SRichard Henderson if (info.si_signo) { 29156910b8f6SRichard Henderson env->lock_addr = -1; 29167a3148a9Sj_mayer info.si_errno = 0; 29177a3148a9Sj_mayer info.si_code = TARGET_TRAP_BRKPT; 2918624f7979Spbrook queue_signal(env, info.si_signo, &info); 29197a3148a9Sj_mayer } 29207a3148a9Sj_mayer break; 29216910b8f6SRichard Henderson case EXCP_STL_C: 29226910b8f6SRichard Henderson case EXCP_STQ_C: 29236910b8f6SRichard Henderson do_store_exclusive(env, env->error_code, trapnr - EXCP_STL_C); 29246910b8f6SRichard Henderson break; 2925d0f20495SRichard Henderson case EXCP_INTERRUPT: 2926d0f20495SRichard Henderson /* Just indicate that signals should be handled asap. */ 2927d0f20495SRichard Henderson break; 29287a3148a9Sj_mayer default: 29297a3148a9Sj_mayer printf ("Unhandled trap: 0x%x\n", trapnr); 29307a3148a9Sj_mayer cpu_dump_state(env, stderr, fprintf, 0); 29317a3148a9Sj_mayer exit (1); 29327a3148a9Sj_mayer } 29337a3148a9Sj_mayer process_pending_signals (env); 29347a3148a9Sj_mayer } 29357a3148a9Sj_mayer } 29367a3148a9Sj_mayer #endif /* TARGET_ALPHA */ 29377a3148a9Sj_mayer 2938a4c075f1SUlrich Hecht #ifdef TARGET_S390X 2939a4c075f1SUlrich Hecht void cpu_loop(CPUS390XState *env) 2940a4c075f1SUlrich Hecht { 2941a4c075f1SUlrich Hecht int trapnr; 2942a4c075f1SUlrich Hecht target_siginfo_t info; 2943a4c075f1SUlrich Hecht 2944a4c075f1SUlrich Hecht while (1) { 2945a4c075f1SUlrich Hecht trapnr = cpu_s390x_exec (env); 2946a4c075f1SUlrich Hecht 2947a4c075f1SUlrich Hecht switch (trapnr) { 2948a4c075f1SUlrich Hecht case EXCP_INTERRUPT: 2949a4c075f1SUlrich Hecht /* just indicate that signals should be handled asap */ 2950a4c075f1SUlrich Hecht break; 2951a4c075f1SUlrich Hecht case EXCP_DEBUG: 2952a4c075f1SUlrich Hecht { 2953a4c075f1SUlrich Hecht int sig; 2954a4c075f1SUlrich Hecht 2955a4c075f1SUlrich Hecht sig = gdb_handlesig (env, TARGET_SIGTRAP); 2956a4c075f1SUlrich Hecht if (sig) { 2957a4c075f1SUlrich Hecht info.si_signo = sig; 2958a4c075f1SUlrich Hecht info.si_errno = 0; 2959a4c075f1SUlrich Hecht info.si_code = TARGET_TRAP_BRKPT; 2960a4c075f1SUlrich Hecht queue_signal(env, info.si_signo, &info); 2961a4c075f1SUlrich Hecht } 2962a4c075f1SUlrich Hecht } 2963a4c075f1SUlrich Hecht break; 2964a4c075f1SUlrich Hecht case EXCP_SVC: 2965a4c075f1SUlrich Hecht { 2966a4c075f1SUlrich Hecht int n = env->int_svc_code; 2967a4c075f1SUlrich Hecht if (!n) { 2968a4c075f1SUlrich Hecht /* syscalls > 255 */ 2969a4c075f1SUlrich Hecht n = env->regs[1]; 2970a4c075f1SUlrich Hecht } 2971a4c075f1SUlrich Hecht env->psw.addr += env->int_svc_ilc; 2972a4c075f1SUlrich Hecht env->regs[2] = do_syscall(env, n, 2973a4c075f1SUlrich Hecht env->regs[2], 2974a4c075f1SUlrich Hecht env->regs[3], 2975a4c075f1SUlrich Hecht env->regs[4], 2976a4c075f1SUlrich Hecht env->regs[5], 2977a4c075f1SUlrich Hecht env->regs[6], 29785945cfcbSPeter Maydell env->regs[7], 29795945cfcbSPeter Maydell 0, 0); 2980a4c075f1SUlrich Hecht } 2981a4c075f1SUlrich Hecht break; 2982a4c075f1SUlrich Hecht case EXCP_ADDR: 2983a4c075f1SUlrich Hecht { 2984a4c075f1SUlrich Hecht info.si_signo = SIGSEGV; 2985a4c075f1SUlrich Hecht info.si_errno = 0; 2986a4c075f1SUlrich Hecht /* XXX: check env->error_code */ 2987a4c075f1SUlrich Hecht info.si_code = TARGET_SEGV_MAPERR; 2988a4c075f1SUlrich Hecht info._sifields._sigfault._addr = env->__excp_addr; 2989a4c075f1SUlrich Hecht queue_signal(env, info.si_signo, &info); 2990a4c075f1SUlrich Hecht } 2991a4c075f1SUlrich Hecht break; 2992a4c075f1SUlrich Hecht case EXCP_SPEC: 2993a4c075f1SUlrich Hecht { 2994a4c075f1SUlrich Hecht fprintf(stderr,"specification exception insn 0x%08x%04x\n", ldl(env->psw.addr), lduw(env->psw.addr + 4)); 2995a4c075f1SUlrich Hecht info.si_signo = SIGILL; 2996a4c075f1SUlrich Hecht info.si_errno = 0; 2997a4c075f1SUlrich Hecht info.si_code = TARGET_ILL_ILLOPC; 2998a4c075f1SUlrich Hecht info._sifields._sigfault._addr = env->__excp_addr; 2999a4c075f1SUlrich Hecht queue_signal(env, info.si_signo, &info); 3000a4c075f1SUlrich Hecht } 3001a4c075f1SUlrich Hecht break; 3002a4c075f1SUlrich Hecht default: 3003a4c075f1SUlrich Hecht printf ("Unhandled trap: 0x%x\n", trapnr); 3004a4c075f1SUlrich Hecht cpu_dump_state(env, stderr, fprintf, 0); 3005a4c075f1SUlrich Hecht exit (1); 3006a4c075f1SUlrich Hecht } 3007a4c075f1SUlrich Hecht process_pending_signals (env); 3008a4c075f1SUlrich Hecht } 3009a4c075f1SUlrich Hecht } 3010a4c075f1SUlrich Hecht 3011a4c075f1SUlrich Hecht #endif /* TARGET_S390X */ 3012a4c075f1SUlrich Hecht 30139349b4f9SAndreas Färber THREAD CPUArchState *thread_env; 301459faf6d6Sbellard 3015edf8e2afSMika Westerberg void task_settid(TaskState *ts) 3016edf8e2afSMika Westerberg { 3017edf8e2afSMika Westerberg if (ts->ts_tid == 0) { 30182f7bb878SJuan Quintela #ifdef CONFIG_USE_NPTL 3019edf8e2afSMika Westerberg ts->ts_tid = (pid_t)syscall(SYS_gettid); 3020edf8e2afSMika Westerberg #else 3021edf8e2afSMika Westerberg /* when no threads are used, tid becomes pid */ 3022edf8e2afSMika Westerberg ts->ts_tid = getpid(); 3023edf8e2afSMika Westerberg #endif 3024edf8e2afSMika Westerberg } 3025edf8e2afSMika Westerberg } 3026edf8e2afSMika Westerberg 3027edf8e2afSMika Westerberg void stop_all_tasks(void) 3028edf8e2afSMika Westerberg { 3029edf8e2afSMika Westerberg /* 3030edf8e2afSMika Westerberg * We trust that when using NPTL, start_exclusive() 3031edf8e2afSMika Westerberg * handles thread stopping correctly. 3032edf8e2afSMika Westerberg */ 3033edf8e2afSMika Westerberg start_exclusive(); 3034edf8e2afSMika Westerberg } 3035edf8e2afSMika Westerberg 3036c3a92833Spbrook /* Assumes contents are already zeroed. */ 3037624f7979Spbrook void init_task_state(TaskState *ts) 3038624f7979Spbrook { 3039624f7979Spbrook int i; 3040624f7979Spbrook 3041624f7979Spbrook ts->used = 1; 3042624f7979Spbrook ts->first_free = ts->sigqueue_table; 3043624f7979Spbrook for (i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++) { 3044624f7979Spbrook ts->sigqueue_table[i].next = &ts->sigqueue_table[i + 1]; 3045624f7979Spbrook } 3046624f7979Spbrook ts->sigqueue_table[i].next = NULL; 3047624f7979Spbrook } 30489de5e440Sbellard 3049fc9c5412SJohannes Schauer static void handle_arg_help(const char *arg) 3050fc9c5412SJohannes Schauer { 3051fc9c5412SJohannes Schauer usage(); 3052fc9c5412SJohannes Schauer } 3053fc9c5412SJohannes Schauer 3054fc9c5412SJohannes Schauer static void handle_arg_log(const char *arg) 3055fc9c5412SJohannes Schauer { 3056fc9c5412SJohannes Schauer int mask; 3057fc9c5412SJohannes Schauer const CPULogItem *item; 3058fc9c5412SJohannes Schauer 3059fc9c5412SJohannes Schauer mask = cpu_str_to_log_mask(arg); 3060fc9c5412SJohannes Schauer if (!mask) { 3061fc9c5412SJohannes Schauer printf("Log items (comma separated):\n"); 3062fc9c5412SJohannes Schauer for (item = cpu_log_items; item->mask != 0; item++) { 3063fc9c5412SJohannes Schauer printf("%-10s %s\n", item->name, item->help); 3064fc9c5412SJohannes Schauer } 3065fc9c5412SJohannes Schauer exit(1); 3066fc9c5412SJohannes Schauer } 3067fc9c5412SJohannes Schauer cpu_set_log(mask); 3068fc9c5412SJohannes Schauer } 3069fc9c5412SJohannes Schauer 307050171d42S陳韋任 static void handle_arg_log_filename(const char *arg) 307150171d42S陳韋任 { 307250171d42S陳韋任 cpu_set_log_filename(arg); 307350171d42S陳韋任 } 307450171d42S陳韋任 3075fc9c5412SJohannes Schauer static void handle_arg_set_env(const char *arg) 3076fc9c5412SJohannes Schauer { 3077fc9c5412SJohannes Schauer char *r, *p, *token; 3078fc9c5412SJohannes Schauer r = p = strdup(arg); 3079fc9c5412SJohannes Schauer while ((token = strsep(&p, ",")) != NULL) { 3080fc9c5412SJohannes Schauer if (envlist_setenv(envlist, token) != 0) { 3081fc9c5412SJohannes Schauer usage(); 3082fc9c5412SJohannes Schauer } 3083fc9c5412SJohannes Schauer } 3084fc9c5412SJohannes Schauer free(r); 3085fc9c5412SJohannes Schauer } 3086fc9c5412SJohannes Schauer 3087fc9c5412SJohannes Schauer static void handle_arg_unset_env(const char *arg) 3088fc9c5412SJohannes Schauer { 3089fc9c5412SJohannes Schauer char *r, *p, *token; 3090fc9c5412SJohannes Schauer r = p = strdup(arg); 3091fc9c5412SJohannes Schauer while ((token = strsep(&p, ",")) != NULL) { 3092fc9c5412SJohannes Schauer if (envlist_unsetenv(envlist, token) != 0) { 3093fc9c5412SJohannes Schauer usage(); 3094fc9c5412SJohannes Schauer } 3095fc9c5412SJohannes Schauer } 3096fc9c5412SJohannes Schauer free(r); 3097fc9c5412SJohannes Schauer } 3098fc9c5412SJohannes Schauer 3099fc9c5412SJohannes Schauer static void handle_arg_argv0(const char *arg) 3100fc9c5412SJohannes Schauer { 3101fc9c5412SJohannes Schauer argv0 = strdup(arg); 3102fc9c5412SJohannes Schauer } 3103fc9c5412SJohannes Schauer 3104fc9c5412SJohannes Schauer static void handle_arg_stack_size(const char *arg) 3105fc9c5412SJohannes Schauer { 3106fc9c5412SJohannes Schauer char *p; 3107fc9c5412SJohannes Schauer guest_stack_size = strtoul(arg, &p, 0); 3108fc9c5412SJohannes Schauer if (guest_stack_size == 0) { 3109fc9c5412SJohannes Schauer usage(); 3110fc9c5412SJohannes Schauer } 3111fc9c5412SJohannes Schauer 3112fc9c5412SJohannes Schauer if (*p == 'M') { 3113fc9c5412SJohannes Schauer guest_stack_size *= 1024 * 1024; 3114fc9c5412SJohannes Schauer } else if (*p == 'k' || *p == 'K') { 3115fc9c5412SJohannes Schauer guest_stack_size *= 1024; 3116fc9c5412SJohannes Schauer } 3117fc9c5412SJohannes Schauer } 3118fc9c5412SJohannes Schauer 3119fc9c5412SJohannes Schauer static void handle_arg_ld_prefix(const char *arg) 3120fc9c5412SJohannes Schauer { 3121fc9c5412SJohannes Schauer interp_prefix = strdup(arg); 3122fc9c5412SJohannes Schauer } 3123fc9c5412SJohannes Schauer 3124fc9c5412SJohannes Schauer static void handle_arg_pagesize(const char *arg) 3125fc9c5412SJohannes Schauer { 3126fc9c5412SJohannes Schauer qemu_host_page_size = atoi(arg); 3127fc9c5412SJohannes Schauer if (qemu_host_page_size == 0 || 3128fc9c5412SJohannes Schauer (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) { 3129fc9c5412SJohannes Schauer fprintf(stderr, "page size must be a power of two\n"); 3130fc9c5412SJohannes Schauer exit(1); 3131fc9c5412SJohannes Schauer } 3132fc9c5412SJohannes Schauer } 3133fc9c5412SJohannes Schauer 3134fc9c5412SJohannes Schauer static void handle_arg_gdb(const char *arg) 3135fc9c5412SJohannes Schauer { 3136fc9c5412SJohannes Schauer gdbstub_port = atoi(arg); 3137fc9c5412SJohannes Schauer } 3138fc9c5412SJohannes Schauer 3139fc9c5412SJohannes Schauer static void handle_arg_uname(const char *arg) 3140fc9c5412SJohannes Schauer { 3141fc9c5412SJohannes Schauer qemu_uname_release = strdup(arg); 3142fc9c5412SJohannes Schauer } 3143fc9c5412SJohannes Schauer 3144fc9c5412SJohannes Schauer static void handle_arg_cpu(const char *arg) 3145fc9c5412SJohannes Schauer { 3146fc9c5412SJohannes Schauer cpu_model = strdup(arg); 3147c8057f95SPeter Maydell if (cpu_model == NULL || is_help_option(cpu_model)) { 3148fc9c5412SJohannes Schauer /* XXX: implement xxx_cpu_list for targets that still miss it */ 3149e916cbf8SPeter Maydell #if defined(cpu_list) 3150e916cbf8SPeter Maydell cpu_list(stdout, &fprintf); 3151fc9c5412SJohannes Schauer #endif 3152fc9c5412SJohannes Schauer exit(1); 3153fc9c5412SJohannes Schauer } 3154fc9c5412SJohannes Schauer } 3155fc9c5412SJohannes Schauer 3156fc9c5412SJohannes Schauer #if defined(CONFIG_USE_GUEST_BASE) 3157fc9c5412SJohannes Schauer static void handle_arg_guest_base(const char *arg) 3158fc9c5412SJohannes Schauer { 3159fc9c5412SJohannes Schauer guest_base = strtol(arg, NULL, 0); 3160fc9c5412SJohannes Schauer have_guest_base = 1; 3161fc9c5412SJohannes Schauer } 3162fc9c5412SJohannes Schauer 3163fc9c5412SJohannes Schauer static void handle_arg_reserved_va(const char *arg) 3164fc9c5412SJohannes Schauer { 3165fc9c5412SJohannes Schauer char *p; 3166fc9c5412SJohannes Schauer int shift = 0; 3167fc9c5412SJohannes Schauer reserved_va = strtoul(arg, &p, 0); 3168fc9c5412SJohannes Schauer switch (*p) { 3169fc9c5412SJohannes Schauer case 'k': 3170fc9c5412SJohannes Schauer case 'K': 3171fc9c5412SJohannes Schauer shift = 10; 3172fc9c5412SJohannes Schauer break; 3173fc9c5412SJohannes Schauer case 'M': 3174fc9c5412SJohannes Schauer shift = 20; 3175fc9c5412SJohannes Schauer break; 3176fc9c5412SJohannes Schauer case 'G': 3177fc9c5412SJohannes Schauer shift = 30; 3178fc9c5412SJohannes Schauer break; 3179fc9c5412SJohannes Schauer } 3180fc9c5412SJohannes Schauer if (shift) { 3181fc9c5412SJohannes Schauer unsigned long unshifted = reserved_va; 3182fc9c5412SJohannes Schauer p++; 3183fc9c5412SJohannes Schauer reserved_va <<= shift; 3184fc9c5412SJohannes Schauer if (((reserved_va >> shift) != unshifted) 3185fc9c5412SJohannes Schauer #if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS 3186fc9c5412SJohannes Schauer || (reserved_va > (1ul << TARGET_VIRT_ADDR_SPACE_BITS)) 3187fc9c5412SJohannes Schauer #endif 3188fc9c5412SJohannes Schauer ) { 3189fc9c5412SJohannes Schauer fprintf(stderr, "Reserved virtual address too big\n"); 3190fc9c5412SJohannes Schauer exit(1); 3191fc9c5412SJohannes Schauer } 3192fc9c5412SJohannes Schauer } 3193fc9c5412SJohannes Schauer if (*p) { 3194fc9c5412SJohannes Schauer fprintf(stderr, "Unrecognised -R size suffix '%s'\n", p); 3195fc9c5412SJohannes Schauer exit(1); 3196fc9c5412SJohannes Schauer } 3197fc9c5412SJohannes Schauer } 3198fc9c5412SJohannes Schauer #endif 3199fc9c5412SJohannes Schauer 3200fc9c5412SJohannes Schauer static void handle_arg_singlestep(const char *arg) 3201fc9c5412SJohannes Schauer { 3202fc9c5412SJohannes Schauer singlestep = 1; 3203fc9c5412SJohannes Schauer } 3204fc9c5412SJohannes Schauer 3205fc9c5412SJohannes Schauer static void handle_arg_strace(const char *arg) 3206fc9c5412SJohannes Schauer { 3207fc9c5412SJohannes Schauer do_strace = 1; 3208fc9c5412SJohannes Schauer } 3209fc9c5412SJohannes Schauer 3210fc9c5412SJohannes Schauer static void handle_arg_version(const char *arg) 3211fc9c5412SJohannes Schauer { 3212fc9c5412SJohannes Schauer printf("qemu-" TARGET_ARCH " version " QEMU_VERSION QEMU_PKGVERSION 3213fc9c5412SJohannes Schauer ", Copyright (c) 2003-2008 Fabrice Bellard\n"); 32141386d4c0SPeter Maydell exit(0); 3215fc9c5412SJohannes Schauer } 3216fc9c5412SJohannes Schauer 3217fc9c5412SJohannes Schauer struct qemu_argument { 3218fc9c5412SJohannes Schauer const char *argv; 3219fc9c5412SJohannes Schauer const char *env; 3220fc9c5412SJohannes Schauer bool has_arg; 3221fc9c5412SJohannes Schauer void (*handle_opt)(const char *arg); 3222fc9c5412SJohannes Schauer const char *example; 3223fc9c5412SJohannes Schauer const char *help; 3224fc9c5412SJohannes Schauer }; 3225fc9c5412SJohannes Schauer 322642644ceeSJim Meyering static const struct qemu_argument arg_table[] = { 3227fc9c5412SJohannes Schauer {"h", "", false, handle_arg_help, 3228fc9c5412SJohannes Schauer "", "print this help"}, 3229fc9c5412SJohannes Schauer {"g", "QEMU_GDB", true, handle_arg_gdb, 3230fc9c5412SJohannes Schauer "port", "wait gdb connection to 'port'"}, 3231fc9c5412SJohannes Schauer {"L", "QEMU_LD_PREFIX", true, handle_arg_ld_prefix, 3232fc9c5412SJohannes Schauer "path", "set the elf interpreter prefix to 'path'"}, 3233fc9c5412SJohannes Schauer {"s", "QEMU_STACK_SIZE", true, handle_arg_stack_size, 3234fc9c5412SJohannes Schauer "size", "set the stack size to 'size' bytes"}, 3235fc9c5412SJohannes Schauer {"cpu", "QEMU_CPU", true, handle_arg_cpu, 3236c8057f95SPeter Maydell "model", "select CPU (-cpu help for list)"}, 3237fc9c5412SJohannes Schauer {"E", "QEMU_SET_ENV", true, handle_arg_set_env, 3238fc9c5412SJohannes Schauer "var=value", "sets targets environment variable (see below)"}, 3239fc9c5412SJohannes Schauer {"U", "QEMU_UNSET_ENV", true, handle_arg_unset_env, 3240fc9c5412SJohannes Schauer "var", "unsets targets environment variable (see below)"}, 3241fc9c5412SJohannes Schauer {"0", "QEMU_ARGV0", true, handle_arg_argv0, 3242fc9c5412SJohannes Schauer "argv0", "forces target process argv[0] to be 'argv0'"}, 3243fc9c5412SJohannes Schauer {"r", "QEMU_UNAME", true, handle_arg_uname, 3244fc9c5412SJohannes Schauer "uname", "set qemu uname release string to 'uname'"}, 3245fc9c5412SJohannes Schauer #if defined(CONFIG_USE_GUEST_BASE) 3246fc9c5412SJohannes Schauer {"B", "QEMU_GUEST_BASE", true, handle_arg_guest_base, 3247fc9c5412SJohannes Schauer "address", "set guest_base address to 'address'"}, 3248fc9c5412SJohannes Schauer {"R", "QEMU_RESERVED_VA", true, handle_arg_reserved_va, 3249fc9c5412SJohannes Schauer "size", "reserve 'size' bytes for guest virtual address space"}, 3250fc9c5412SJohannes Schauer #endif 3251fc9c5412SJohannes Schauer {"d", "QEMU_LOG", true, handle_arg_log, 3252fc9c5412SJohannes Schauer "options", "activate log"}, 325350171d42S陳韋任 {"D", "QEMU_LOG_FILENAME", true, handle_arg_log_filename, 325450171d42S陳韋任 "logfile", "override default logfile location"}, 3255fc9c5412SJohannes Schauer {"p", "QEMU_PAGESIZE", true, handle_arg_pagesize, 3256fc9c5412SJohannes Schauer "pagesize", "set the host page size to 'pagesize'"}, 3257fc9c5412SJohannes Schauer {"singlestep", "QEMU_SINGLESTEP", false, handle_arg_singlestep, 3258fc9c5412SJohannes Schauer "", "run in singlestep mode"}, 3259fc9c5412SJohannes Schauer {"strace", "QEMU_STRACE", false, handle_arg_strace, 3260fc9c5412SJohannes Schauer "", "log system calls"}, 3261fc9c5412SJohannes Schauer {"version", "QEMU_VERSION", false, handle_arg_version, 32621386d4c0SPeter Maydell "", "display version information and exit"}, 3263fc9c5412SJohannes Schauer {NULL, NULL, false, NULL, NULL, NULL} 3264fc9c5412SJohannes Schauer }; 3265fc9c5412SJohannes Schauer 3266fc9c5412SJohannes Schauer static void usage(void) 3267fc9c5412SJohannes Schauer { 326842644ceeSJim Meyering const struct qemu_argument *arginfo; 3269fc9c5412SJohannes Schauer int maxarglen; 3270fc9c5412SJohannes Schauer int maxenvlen; 3271fc9c5412SJohannes Schauer 3272fc9c5412SJohannes Schauer printf("usage: qemu-" TARGET_ARCH " [options] program [arguments...]\n" 3273fc9c5412SJohannes Schauer "Linux CPU emulator (compiled for " TARGET_ARCH " emulation)\n" 3274fc9c5412SJohannes Schauer "\n" 3275fc9c5412SJohannes Schauer "Options and associated environment variables:\n" 3276fc9c5412SJohannes Schauer "\n"); 3277fc9c5412SJohannes Schauer 3278fc9c5412SJohannes Schauer maxarglen = maxenvlen = 0; 3279fc9c5412SJohannes Schauer 3280fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) { 3281fc9c5412SJohannes Schauer if (strlen(arginfo->env) > maxenvlen) { 3282fc9c5412SJohannes Schauer maxenvlen = strlen(arginfo->env); 3283fc9c5412SJohannes Schauer } 3284fc9c5412SJohannes Schauer if (strlen(arginfo->argv) > maxarglen) { 3285fc9c5412SJohannes Schauer maxarglen = strlen(arginfo->argv); 3286fc9c5412SJohannes Schauer } 3287fc9c5412SJohannes Schauer } 3288fc9c5412SJohannes Schauer 3289fc9c5412SJohannes Schauer printf("%-*s%-*sDescription\n", maxarglen+3, "Argument", 3290fc9c5412SJohannes Schauer maxenvlen+1, "Env-variable"); 3291fc9c5412SJohannes Schauer 3292fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) { 3293fc9c5412SJohannes Schauer if (arginfo->has_arg) { 3294fc9c5412SJohannes Schauer printf("-%s %-*s %-*s %s\n", arginfo->argv, 3295fc9c5412SJohannes Schauer (int)(maxarglen-strlen(arginfo->argv)), arginfo->example, 3296fc9c5412SJohannes Schauer maxenvlen, arginfo->env, arginfo->help); 3297fc9c5412SJohannes Schauer } else { 3298fc9c5412SJohannes Schauer printf("-%-*s %-*s %s\n", maxarglen+1, arginfo->argv, 3299fc9c5412SJohannes Schauer maxenvlen, arginfo->env, 3300fc9c5412SJohannes Schauer arginfo->help); 3301fc9c5412SJohannes Schauer } 3302fc9c5412SJohannes Schauer } 3303fc9c5412SJohannes Schauer 3304fc9c5412SJohannes Schauer printf("\n" 3305fc9c5412SJohannes Schauer "Defaults:\n" 3306fc9c5412SJohannes Schauer "QEMU_LD_PREFIX = %s\n" 3307fc9c5412SJohannes Schauer "QEMU_STACK_SIZE = %ld byte\n" 3308fc9c5412SJohannes Schauer "QEMU_LOG = %s\n", 3309fc9c5412SJohannes Schauer interp_prefix, 3310fc9c5412SJohannes Schauer guest_stack_size, 3311fc9c5412SJohannes Schauer DEBUG_LOGFILE); 3312fc9c5412SJohannes Schauer 3313fc9c5412SJohannes Schauer printf("\n" 3314fc9c5412SJohannes Schauer "You can use -E and -U options or the QEMU_SET_ENV and\n" 3315fc9c5412SJohannes Schauer "QEMU_UNSET_ENV environment variables to set and unset\n" 3316fc9c5412SJohannes Schauer "environment variables for the target process.\n" 3317fc9c5412SJohannes Schauer "It is possible to provide several variables by separating them\n" 3318fc9c5412SJohannes Schauer "by commas in getsubopt(3) style. Additionally it is possible to\n" 3319fc9c5412SJohannes Schauer "provide the -E and -U options multiple times.\n" 3320fc9c5412SJohannes Schauer "The following lines are equivalent:\n" 3321fc9c5412SJohannes Schauer " -E var1=val2 -E var2=val2 -U LD_PRELOAD -U LD_DEBUG\n" 3322fc9c5412SJohannes Schauer " -E var1=val2,var2=val2 -U LD_PRELOAD,LD_DEBUG\n" 3323fc9c5412SJohannes Schauer " QEMU_SET_ENV=var1=val2,var2=val2 QEMU_UNSET_ENV=LD_PRELOAD,LD_DEBUG\n" 3324fc9c5412SJohannes Schauer "Note that if you provide several changes to a single variable\n" 3325fc9c5412SJohannes Schauer "the last change will stay in effect.\n"); 3326fc9c5412SJohannes Schauer 3327fc9c5412SJohannes Schauer exit(1); 3328fc9c5412SJohannes Schauer } 3329fc9c5412SJohannes Schauer 3330fc9c5412SJohannes Schauer static int parse_args(int argc, char **argv) 3331fc9c5412SJohannes Schauer { 3332fc9c5412SJohannes Schauer const char *r; 3333fc9c5412SJohannes Schauer int optind; 333442644ceeSJim Meyering const struct qemu_argument *arginfo; 3335fc9c5412SJohannes Schauer 3336fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) { 3337fc9c5412SJohannes Schauer if (arginfo->env == NULL) { 3338fc9c5412SJohannes Schauer continue; 3339fc9c5412SJohannes Schauer } 3340fc9c5412SJohannes Schauer 3341fc9c5412SJohannes Schauer r = getenv(arginfo->env); 3342fc9c5412SJohannes Schauer if (r != NULL) { 3343fc9c5412SJohannes Schauer arginfo->handle_opt(r); 3344fc9c5412SJohannes Schauer } 3345fc9c5412SJohannes Schauer } 3346fc9c5412SJohannes Schauer 3347fc9c5412SJohannes Schauer optind = 1; 3348fc9c5412SJohannes Schauer for (;;) { 3349fc9c5412SJohannes Schauer if (optind >= argc) { 3350fc9c5412SJohannes Schauer break; 3351fc9c5412SJohannes Schauer } 3352fc9c5412SJohannes Schauer r = argv[optind]; 3353fc9c5412SJohannes Schauer if (r[0] != '-') { 3354fc9c5412SJohannes Schauer break; 3355fc9c5412SJohannes Schauer } 3356fc9c5412SJohannes Schauer optind++; 3357fc9c5412SJohannes Schauer r++; 3358fc9c5412SJohannes Schauer if (!strcmp(r, "-")) { 3359fc9c5412SJohannes Schauer break; 3360fc9c5412SJohannes Schauer } 3361fc9c5412SJohannes Schauer 3362fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) { 3363fc9c5412SJohannes Schauer if (!strcmp(r, arginfo->argv)) { 33641386d4c0SPeter Maydell if (arginfo->has_arg) { 3365fc9c5412SJohannes Schauer if (optind >= argc) { 3366fc9c5412SJohannes Schauer usage(); 3367fc9c5412SJohannes Schauer } 3368fc9c5412SJohannes Schauer arginfo->handle_opt(argv[optind]); 3369fc9c5412SJohannes Schauer optind++; 33701386d4c0SPeter Maydell } else { 33711386d4c0SPeter Maydell arginfo->handle_opt(NULL); 3372fc9c5412SJohannes Schauer } 3373fc9c5412SJohannes Schauer break; 3374fc9c5412SJohannes Schauer } 3375fc9c5412SJohannes Schauer } 3376fc9c5412SJohannes Schauer 3377fc9c5412SJohannes Schauer /* no option matched the current argv */ 3378fc9c5412SJohannes Schauer if (arginfo->handle_opt == NULL) { 3379fc9c5412SJohannes Schauer usage(); 3380fc9c5412SJohannes Schauer } 3381fc9c5412SJohannes Schauer } 3382fc9c5412SJohannes Schauer 3383fc9c5412SJohannes Schauer if (optind >= argc) { 3384fc9c5412SJohannes Schauer usage(); 3385fc9c5412SJohannes Schauer } 3386fc9c5412SJohannes Schauer 3387fc9c5412SJohannes Schauer filename = argv[optind]; 3388fc9c5412SJohannes Schauer exec_path = argv[optind]; 3389fc9c5412SJohannes Schauer 3390fc9c5412SJohannes Schauer return optind; 3391fc9c5412SJohannes Schauer } 3392fc9c5412SJohannes Schauer 3393902b3d5cSmalc int main(int argc, char **argv, char **envp) 339431e31b8aSbellard { 3395c235d738SMatthew Fernandez const char *log_file = DEBUG_LOGFILE; 339601ffc75bSbellard struct target_pt_regs regs1, *regs = ®s1; 339731e31b8aSbellard struct image_info info1, *info = &info1; 3398edf8e2afSMika Westerberg struct linux_binprm bprm; 339948e15fc2SNathan Froyd TaskState *ts; 34009349b4f9SAndreas Färber CPUArchState *env; 3401586314f2Sbellard int optind; 340204a6dfebSaurel32 char **target_environ, **wrk; 34037d8cec95Saurel32 char **target_argv; 34047d8cec95Saurel32 int target_argc; 34057d8cec95Saurel32 int i; 3406fd4d81ddSArnaud Patard int ret; 340731e31b8aSbellard 3408ce008c1fSAndreas Färber module_call_init(MODULE_INIT_QOM); 3409ce008c1fSAndreas Färber 3410902b3d5cSmalc qemu_cache_utils_init(envp); 3411902b3d5cSmalc 341204a6dfebSaurel32 if ((envlist = envlist_create()) == NULL) { 341304a6dfebSaurel32 (void) fprintf(stderr, "Unable to allocate envlist\n"); 341404a6dfebSaurel32 exit(1); 341504a6dfebSaurel32 } 341604a6dfebSaurel32 341704a6dfebSaurel32 /* add current environment into the list */ 341804a6dfebSaurel32 for (wrk = environ; *wrk != NULL; wrk++) { 341904a6dfebSaurel32 (void) envlist_setenv(envlist, *wrk); 342004a6dfebSaurel32 } 342104a6dfebSaurel32 3422703e0e89SRichard Henderson /* Read the stack limit from the kernel. If it's "unlimited", 3423703e0e89SRichard Henderson then we can do little else besides use the default. */ 3424703e0e89SRichard Henderson { 3425703e0e89SRichard Henderson struct rlimit lim; 3426703e0e89SRichard Henderson if (getrlimit(RLIMIT_STACK, &lim) == 0 342781bbe906Stakasi-y@ops.dti.ne.jp && lim.rlim_cur != RLIM_INFINITY 342881bbe906Stakasi-y@ops.dti.ne.jp && lim.rlim_cur == (target_long)lim.rlim_cur) { 3429703e0e89SRichard Henderson guest_stack_size = lim.rlim_cur; 3430703e0e89SRichard Henderson } 3431703e0e89SRichard Henderson } 3432703e0e89SRichard Henderson 3433b1f9be31Sj_mayer cpu_model = NULL; 3434b5ec5ce0Sjohn cooper #if defined(cpudef_setup) 3435b5ec5ce0Sjohn cooper cpudef_setup(); /* parse cpu definitions in target config file (TBD) */ 3436b5ec5ce0Sjohn cooper #endif 3437b5ec5ce0Sjohn cooper 3438c235d738SMatthew Fernandez /* init debug */ 3439c235d738SMatthew Fernandez cpu_set_log_filename(log_file); 3440fc9c5412SJohannes Schauer optind = parse_args(argc, argv); 34414b5dfd82SPeter Maydell 344231e31b8aSbellard /* Zero out regs */ 344301ffc75bSbellard memset(regs, 0, sizeof(struct target_pt_regs)); 344431e31b8aSbellard 344531e31b8aSbellard /* Zero out image_info */ 344631e31b8aSbellard memset(info, 0, sizeof(struct image_info)); 344731e31b8aSbellard 3448edf8e2afSMika Westerberg memset(&bprm, 0, sizeof (bprm)); 3449edf8e2afSMika Westerberg 345074cd30b8Sbellard /* Scan interp_prefix dir for replacement files. */ 345174cd30b8Sbellard init_paths(interp_prefix); 345274cd30b8Sbellard 345346027c07Sbellard if (cpu_model == NULL) { 3454aaed909aSbellard #if defined(TARGET_I386) 345546027c07Sbellard #ifdef TARGET_X86_64 345646027c07Sbellard cpu_model = "qemu64"; 345746027c07Sbellard #else 345846027c07Sbellard cpu_model = "qemu32"; 345946027c07Sbellard #endif 3460aaed909aSbellard #elif defined(TARGET_ARM) 3461088ab16cSpbrook cpu_model = "any"; 3462d2fbca94SGuan Xuetao #elif defined(TARGET_UNICORE32) 3463d2fbca94SGuan Xuetao cpu_model = "any"; 3464aaed909aSbellard #elif defined(TARGET_M68K) 3465aaed909aSbellard cpu_model = "any"; 3466aaed909aSbellard #elif defined(TARGET_SPARC) 3467aaed909aSbellard #ifdef TARGET_SPARC64 3468aaed909aSbellard cpu_model = "TI UltraSparc II"; 3469aaed909aSbellard #else 3470aaed909aSbellard cpu_model = "Fujitsu MB86904"; 347146027c07Sbellard #endif 3472aaed909aSbellard #elif defined(TARGET_MIPS) 3473aaed909aSbellard #if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) 3474aaed909aSbellard cpu_model = "20Kc"; 3475aaed909aSbellard #else 3476aaed909aSbellard cpu_model = "24Kf"; 3477aaed909aSbellard #endif 3478d962783eSJia Liu #elif defined TARGET_OPENRISC 3479d962783eSJia Liu cpu_model = "or1200"; 3480aaed909aSbellard #elif defined(TARGET_PPC) 34817ded4f52Sbellard #ifdef TARGET_PPC64 3482f7177937SAurelien Jarno cpu_model = "970fx"; 34837ded4f52Sbellard #else 3484aaed909aSbellard cpu_model = "750"; 34857ded4f52Sbellard #endif 3486aaed909aSbellard #else 3487aaed909aSbellard cpu_model = "any"; 3488aaed909aSbellard #endif 3489aaed909aSbellard } 3490d5ab9713SJan Kiszka tcg_exec_init(0); 3491d5ab9713SJan Kiszka cpu_exec_init_all(); 349283fb7adfSbellard /* NOTE: we need to init the CPU at this stage to get 349383fb7adfSbellard qemu_host_page_size */ 3494aaed909aSbellard env = cpu_init(cpu_model); 3495aaed909aSbellard if (!env) { 3496aaed909aSbellard fprintf(stderr, "Unable to find CPU definition\n"); 3497aaed909aSbellard exit(1); 3498aaed909aSbellard } 3499b55a37c9SBlue Swirl #if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC) 3500ff18b762SAndreas Färber cpu_reset(ENV_GET_CPU(env)); 3501b55a37c9SBlue Swirl #endif 3502b55a37c9SBlue Swirl 3503d5975363Spbrook thread_env = env; 350454936004Sbellard 3505b92c47c1Sths if (getenv("QEMU_STRACE")) { 3506b92c47c1Sths do_strace = 1; 3507b92c47c1Sths } 3508b92c47c1Sths 350904a6dfebSaurel32 target_environ = envlist_to_environ(envlist, NULL); 351004a6dfebSaurel32 envlist_free(envlist); 3511b12b6a18Sths 3512379f6698SPaul Brook #if defined(CONFIG_USE_GUEST_BASE) 3513379f6698SPaul Brook /* 3514379f6698SPaul Brook * Now that page sizes are configured in cpu_init() we can do 3515379f6698SPaul Brook * proper page alignment for guest_base. 3516379f6698SPaul Brook */ 3517379f6698SPaul Brook guest_base = HOST_PAGE_ALIGN(guest_base); 351868a1c816SPaul Brook 351997cc7560SDr. David Alan Gilbert if (reserved_va || have_guest_base) { 3520806d1021SMeador Inge guest_base = init_guest_space(guest_base, reserved_va, 0, 3521806d1021SMeador Inge have_guest_base); 3522806d1021SMeador Inge if (guest_base == (unsigned long)-1) { 3523097b8cb8SPeter Maydell fprintf(stderr, "Unable to reserve 0x%lx bytes of virtual address " 3524097b8cb8SPeter Maydell "space for use as guest address space (check your virtual " 3525097b8cb8SPeter Maydell "memory ulimit setting or reserve less using -R option)\n", 3526097b8cb8SPeter Maydell reserved_va); 352797cc7560SDr. David Alan Gilbert exit(1); 352897cc7560SDr. David Alan Gilbert } 3529806d1021SMeador Inge 3530806d1021SMeador Inge if (reserved_va) { 3531806d1021SMeador Inge mmap_next_start = reserved_va; 3532806d1021SMeador Inge } 353397cc7560SDr. David Alan Gilbert } 353414f24e14SRichard Henderson #endif /* CONFIG_USE_GUEST_BASE */ 3535379f6698SPaul Brook 3536379f6698SPaul Brook /* 3537379f6698SPaul Brook * Read in mmap_min_addr kernel parameter. This value is used 3538379f6698SPaul Brook * When loading the ELF image to determine whether guest_base 353914f24e14SRichard Henderson * is needed. It is also used in mmap_find_vma. 3540379f6698SPaul Brook */ 354114f24e14SRichard Henderson { 3542379f6698SPaul Brook FILE *fp; 3543379f6698SPaul Brook 3544379f6698SPaul Brook if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) { 3545379f6698SPaul Brook unsigned long tmp; 3546379f6698SPaul Brook if (fscanf(fp, "%lu", &tmp) == 1) { 3547379f6698SPaul Brook mmap_min_addr = tmp; 3548379f6698SPaul Brook qemu_log("host mmap_min_addr=0x%lx\n", mmap_min_addr); 3549379f6698SPaul Brook } 3550379f6698SPaul Brook fclose(fp); 3551379f6698SPaul Brook } 3552379f6698SPaul Brook } 3553379f6698SPaul Brook 35547d8cec95Saurel32 /* 35557d8cec95Saurel32 * Prepare copy of argv vector for target. 35567d8cec95Saurel32 */ 35577d8cec95Saurel32 target_argc = argc - optind; 35587d8cec95Saurel32 target_argv = calloc(target_argc + 1, sizeof (char *)); 35597d8cec95Saurel32 if (target_argv == NULL) { 35607d8cec95Saurel32 (void) fprintf(stderr, "Unable to allocate memory for target_argv\n"); 35617d8cec95Saurel32 exit(1); 35627d8cec95Saurel32 } 35637d8cec95Saurel32 35647d8cec95Saurel32 /* 35657d8cec95Saurel32 * If argv0 is specified (using '-0' switch) we replace 35667d8cec95Saurel32 * argv[0] pointer with the given one. 35677d8cec95Saurel32 */ 35687d8cec95Saurel32 i = 0; 35697d8cec95Saurel32 if (argv0 != NULL) { 35707d8cec95Saurel32 target_argv[i++] = strdup(argv0); 35717d8cec95Saurel32 } 35727d8cec95Saurel32 for (; i < target_argc; i++) { 35737d8cec95Saurel32 target_argv[i] = strdup(argv[optind + i]); 35747d8cec95Saurel32 } 35757d8cec95Saurel32 target_argv[target_argc] = NULL; 35767d8cec95Saurel32 35777267c094SAnthony Liguori ts = g_malloc0 (sizeof(TaskState)); 3578edf8e2afSMika Westerberg init_task_state(ts); 3579edf8e2afSMika Westerberg /* build Task State */ 3580edf8e2afSMika Westerberg ts->info = info; 3581edf8e2afSMika Westerberg ts->bprm = &bprm; 3582edf8e2afSMika Westerberg env->opaque = ts; 3583edf8e2afSMika Westerberg task_settid(ts); 3584edf8e2afSMika Westerberg 3585fd4d81ddSArnaud Patard ret = loader_exec(filename, target_argv, target_environ, regs, 3586fd4d81ddSArnaud Patard info, &bprm); 3587fd4d81ddSArnaud Patard if (ret != 0) { 3588885c1d10SPeter Maydell printf("Error while loading %s: %s\n", filename, strerror(-ret)); 358974cd30b8Sbellard _exit(1); 359031e31b8aSbellard } 359131e31b8aSbellard 3592b12b6a18Sths for (wrk = target_environ; *wrk; wrk++) { 3593b12b6a18Sths free(*wrk); 3594b12b6a18Sths } 3595b12b6a18Sths 3596b12b6a18Sths free(target_environ); 3597b12b6a18Sths 35982e77eac6Sblueswir1 if (qemu_log_enabled()) { 3599379f6698SPaul Brook #if defined(CONFIG_USE_GUEST_BASE) 3600379f6698SPaul Brook qemu_log("guest_base 0x%lx\n", guest_base); 3601379f6698SPaul Brook #endif 360293fcfe39Saliguori log_page_dump(); 360354936004Sbellard 360493fcfe39Saliguori qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk); 360593fcfe39Saliguori qemu_log("end_code 0x" TARGET_ABI_FMT_lx "\n", info->end_code); 360693fcfe39Saliguori qemu_log("start_code 0x" TARGET_ABI_FMT_lx "\n", 36073d177870Sj_mayer info->start_code); 360893fcfe39Saliguori qemu_log("start_data 0x" TARGET_ABI_FMT_lx "\n", 36093d177870Sj_mayer info->start_data); 361093fcfe39Saliguori qemu_log("end_data 0x" TARGET_ABI_FMT_lx "\n", info->end_data); 361193fcfe39Saliguori qemu_log("start_stack 0x" TARGET_ABI_FMT_lx "\n", 36123d177870Sj_mayer info->start_stack); 361393fcfe39Saliguori qemu_log("brk 0x" TARGET_ABI_FMT_lx "\n", info->brk); 361493fcfe39Saliguori qemu_log("entry 0x" TARGET_ABI_FMT_lx "\n", info->entry); 36152e77eac6Sblueswir1 } 361631e31b8aSbellard 361753a5960aSpbrook target_set_brk(info->brk); 361831e31b8aSbellard syscall_init(); 361966fb9763Sbellard signal_init(); 362031e31b8aSbellard 36219002ec79SRichard Henderson #if defined(CONFIG_USE_GUEST_BASE) 36229002ec79SRichard Henderson /* Now that we've loaded the binary, GUEST_BASE is fixed. Delay 36239002ec79SRichard Henderson generating the prologue until now so that the prologue can take 36249002ec79SRichard Henderson the real value of GUEST_BASE into account. */ 36259002ec79SRichard Henderson tcg_prologue_init(&tcg_ctx); 36269002ec79SRichard Henderson #endif 36279002ec79SRichard Henderson 3628b346ff46Sbellard #if defined(TARGET_I386) 36292e255c6bSbellard cpu_x86_set_cpl(env, 3); 36302e255c6bSbellard 36313802ce26Sbellard env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK; 36321bde465eSbellard env->hflags |= HF_PE_MASK; 36331bde465eSbellard if (env->cpuid_features & CPUID_SSE) { 36341bde465eSbellard env->cr[4] |= CR4_OSFXSR_MASK; 36351bde465eSbellard env->hflags |= HF_OSFXSR_MASK; 36361bde465eSbellard } 3637d2fd1af7Sbellard #ifndef TARGET_ABI32 36384dbc422bSbellard /* enable 64 bit mode if possible */ 36394dbc422bSbellard if (!(env->cpuid_ext2_features & CPUID_EXT2_LM)) { 36404dbc422bSbellard fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n"); 36414dbc422bSbellard exit(1); 36424dbc422bSbellard } 3643d2fd1af7Sbellard env->cr[4] |= CR4_PAE_MASK; 36444dbc422bSbellard env->efer |= MSR_EFER_LMA | MSR_EFER_LME; 3645d2fd1af7Sbellard env->hflags |= HF_LMA_MASK; 3646d2fd1af7Sbellard #endif 36473802ce26Sbellard 3648415e561fSbellard /* flags setup : we activate the IRQs by default as in user mode */ 3649415e561fSbellard env->eflags |= IF_MASK; 3650415e561fSbellard 36516dbad63eSbellard /* linux register setup */ 3652d2fd1af7Sbellard #ifndef TARGET_ABI32 365384409ddbSj_mayer env->regs[R_EAX] = regs->rax; 365484409ddbSj_mayer env->regs[R_EBX] = regs->rbx; 365584409ddbSj_mayer env->regs[R_ECX] = regs->rcx; 365684409ddbSj_mayer env->regs[R_EDX] = regs->rdx; 365784409ddbSj_mayer env->regs[R_ESI] = regs->rsi; 365884409ddbSj_mayer env->regs[R_EDI] = regs->rdi; 365984409ddbSj_mayer env->regs[R_EBP] = regs->rbp; 366084409ddbSj_mayer env->regs[R_ESP] = regs->rsp; 366184409ddbSj_mayer env->eip = regs->rip; 366284409ddbSj_mayer #else 36630ecfa993Sbellard env->regs[R_EAX] = regs->eax; 36640ecfa993Sbellard env->regs[R_EBX] = regs->ebx; 36650ecfa993Sbellard env->regs[R_ECX] = regs->ecx; 36660ecfa993Sbellard env->regs[R_EDX] = regs->edx; 36670ecfa993Sbellard env->regs[R_ESI] = regs->esi; 36680ecfa993Sbellard env->regs[R_EDI] = regs->edi; 36690ecfa993Sbellard env->regs[R_EBP] = regs->ebp; 36700ecfa993Sbellard env->regs[R_ESP] = regs->esp; 3671dab2ed99Sbellard env->eip = regs->eip; 367284409ddbSj_mayer #endif 367331e31b8aSbellard 3674f4beb510Sbellard /* linux interrupt setup */ 3675e441570fSbalrog #ifndef TARGET_ABI32 3676e441570fSbalrog env->idt.limit = 511; 3677e441570fSbalrog #else 3678e441570fSbalrog env->idt.limit = 255; 3679e441570fSbalrog #endif 3680e441570fSbalrog env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1), 3681e441570fSbalrog PROT_READ|PROT_WRITE, 3682e441570fSbalrog MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); 3683e441570fSbalrog idt_table = g2h(env->idt.base); 3684f4beb510Sbellard set_idt(0, 0); 3685f4beb510Sbellard set_idt(1, 0); 3686f4beb510Sbellard set_idt(2, 0); 3687f4beb510Sbellard set_idt(3, 3); 3688f4beb510Sbellard set_idt(4, 3); 3689ec95da6cSbellard set_idt(5, 0); 3690f4beb510Sbellard set_idt(6, 0); 3691f4beb510Sbellard set_idt(7, 0); 3692f4beb510Sbellard set_idt(8, 0); 3693f4beb510Sbellard set_idt(9, 0); 3694f4beb510Sbellard set_idt(10, 0); 3695f4beb510Sbellard set_idt(11, 0); 3696f4beb510Sbellard set_idt(12, 0); 3697f4beb510Sbellard set_idt(13, 0); 3698f4beb510Sbellard set_idt(14, 0); 3699f4beb510Sbellard set_idt(15, 0); 3700f4beb510Sbellard set_idt(16, 0); 3701f4beb510Sbellard set_idt(17, 0); 3702f4beb510Sbellard set_idt(18, 0); 3703f4beb510Sbellard set_idt(19, 0); 3704f4beb510Sbellard set_idt(0x80, 3); 3705f4beb510Sbellard 37066dbad63eSbellard /* linux segment setup */ 37078d18e893Sbellard { 37088d18e893Sbellard uint64_t *gdt_table; 3709e441570fSbalrog env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES, 3710e441570fSbalrog PROT_READ|PROT_WRITE, 3711e441570fSbalrog MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); 37128d18e893Sbellard env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1; 3713e441570fSbalrog gdt_table = g2h(env->gdt.base); 3714d2fd1af7Sbellard #ifdef TARGET_ABI32 3715f4beb510Sbellard write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff, 3716f4beb510Sbellard DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | 3717f4beb510Sbellard (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT)); 3718d2fd1af7Sbellard #else 3719d2fd1af7Sbellard /* 64 bit code segment */ 3720d2fd1af7Sbellard write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff, 3721d2fd1af7Sbellard DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | 3722d2fd1af7Sbellard DESC_L_MASK | 3723d2fd1af7Sbellard (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT)); 3724d2fd1af7Sbellard #endif 3725f4beb510Sbellard write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff, 3726f4beb510Sbellard DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | 3727f4beb510Sbellard (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT)); 37288d18e893Sbellard } 37296dbad63eSbellard cpu_x86_load_seg(env, R_CS, __USER_CS); 3730d2fd1af7Sbellard cpu_x86_load_seg(env, R_SS, __USER_DS); 3731d2fd1af7Sbellard #ifdef TARGET_ABI32 37326dbad63eSbellard cpu_x86_load_seg(env, R_DS, __USER_DS); 37336dbad63eSbellard cpu_x86_load_seg(env, R_ES, __USER_DS); 37346dbad63eSbellard cpu_x86_load_seg(env, R_FS, __USER_DS); 37356dbad63eSbellard cpu_x86_load_seg(env, R_GS, __USER_DS); 3736d6eb40f6Sths /* This hack makes Wine work... */ 3737d6eb40f6Sths env->segs[R_FS].selector = 0; 3738d2fd1af7Sbellard #else 3739d2fd1af7Sbellard cpu_x86_load_seg(env, R_DS, 0); 3740d2fd1af7Sbellard cpu_x86_load_seg(env, R_ES, 0); 3741d2fd1af7Sbellard cpu_x86_load_seg(env, R_FS, 0); 3742d2fd1af7Sbellard cpu_x86_load_seg(env, R_GS, 0); 3743d2fd1af7Sbellard #endif 3744b346ff46Sbellard #elif defined(TARGET_ARM) 3745b346ff46Sbellard { 3746b346ff46Sbellard int i; 3747b5ff1b31Sbellard cpsr_write(env, regs->uregs[16], 0xffffffff); 3748b346ff46Sbellard for(i = 0; i < 16; i++) { 3749b346ff46Sbellard env->regs[i] = regs->uregs[i]; 3750b346ff46Sbellard } 3751d8fd2954SPaul Brook /* Enable BE8. */ 3752d8fd2954SPaul Brook if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4 3753d8fd2954SPaul Brook && (info->elf_flags & EF_ARM_BE8)) { 3754d8fd2954SPaul Brook env->bswap_code = 1; 3755d8fd2954SPaul Brook } 3756b346ff46Sbellard } 3757d2fbca94SGuan Xuetao #elif defined(TARGET_UNICORE32) 3758d2fbca94SGuan Xuetao { 3759d2fbca94SGuan Xuetao int i; 3760d2fbca94SGuan Xuetao cpu_asr_write(env, regs->uregs[32], 0xffffffff); 3761d2fbca94SGuan Xuetao for (i = 0; i < 32; i++) { 3762d2fbca94SGuan Xuetao env->regs[i] = regs->uregs[i]; 3763d2fbca94SGuan Xuetao } 3764d2fbca94SGuan Xuetao } 376593ac68bcSbellard #elif defined(TARGET_SPARC) 3766060366c5Sbellard { 3767060366c5Sbellard int i; 3768060366c5Sbellard env->pc = regs->pc; 3769060366c5Sbellard env->npc = regs->npc; 3770060366c5Sbellard env->y = regs->y; 3771060366c5Sbellard for(i = 0; i < 8; i++) 3772060366c5Sbellard env->gregs[i] = regs->u_regs[i]; 3773060366c5Sbellard for(i = 0; i < 8; i++) 3774060366c5Sbellard env->regwptr[i] = regs->u_regs[i + 8]; 3775060366c5Sbellard } 377667867308Sbellard #elif defined(TARGET_PPC) 377767867308Sbellard { 377867867308Sbellard int i; 37793fc6c082Sbellard 37800411a972Sj_mayer #if defined(TARGET_PPC64) 37810411a972Sj_mayer #if defined(TARGET_ABI32) 37820411a972Sj_mayer env->msr &= ~((target_ulong)1 << MSR_SF); 3783e85e7c6eSj_mayer #else 37840411a972Sj_mayer env->msr |= (target_ulong)1 << MSR_SF; 37850411a972Sj_mayer #endif 378684409ddbSj_mayer #endif 378767867308Sbellard env->nip = regs->nip; 378867867308Sbellard for(i = 0; i < 32; i++) { 378967867308Sbellard env->gpr[i] = regs->gpr[i]; 379067867308Sbellard } 379167867308Sbellard } 3792e6e5906bSpbrook #elif defined(TARGET_M68K) 3793e6e5906bSpbrook { 3794e6e5906bSpbrook env->pc = regs->pc; 3795e6e5906bSpbrook env->dregs[0] = regs->d0; 3796e6e5906bSpbrook env->dregs[1] = regs->d1; 3797e6e5906bSpbrook env->dregs[2] = regs->d2; 3798e6e5906bSpbrook env->dregs[3] = regs->d3; 3799e6e5906bSpbrook env->dregs[4] = regs->d4; 3800e6e5906bSpbrook env->dregs[5] = regs->d5; 3801e6e5906bSpbrook env->dregs[6] = regs->d6; 3802e6e5906bSpbrook env->dregs[7] = regs->d7; 3803e6e5906bSpbrook env->aregs[0] = regs->a0; 3804e6e5906bSpbrook env->aregs[1] = regs->a1; 3805e6e5906bSpbrook env->aregs[2] = regs->a2; 3806e6e5906bSpbrook env->aregs[3] = regs->a3; 3807e6e5906bSpbrook env->aregs[4] = regs->a4; 3808e6e5906bSpbrook env->aregs[5] = regs->a5; 3809e6e5906bSpbrook env->aregs[6] = regs->a6; 3810e6e5906bSpbrook env->aregs[7] = regs->usp; 3811e6e5906bSpbrook env->sr = regs->sr; 3812e6e5906bSpbrook ts->sim_syscalls = 1; 3813e6e5906bSpbrook } 3814b779e29eSEdgar E. Iglesias #elif defined(TARGET_MICROBLAZE) 3815b779e29eSEdgar E. Iglesias { 3816b779e29eSEdgar E. Iglesias env->regs[0] = regs->r0; 3817b779e29eSEdgar E. Iglesias env->regs[1] = regs->r1; 3818b779e29eSEdgar E. Iglesias env->regs[2] = regs->r2; 3819b779e29eSEdgar E. Iglesias env->regs[3] = regs->r3; 3820b779e29eSEdgar E. Iglesias env->regs[4] = regs->r4; 3821b779e29eSEdgar E. Iglesias env->regs[5] = regs->r5; 3822b779e29eSEdgar E. Iglesias env->regs[6] = regs->r6; 3823b779e29eSEdgar E. Iglesias env->regs[7] = regs->r7; 3824b779e29eSEdgar E. Iglesias env->regs[8] = regs->r8; 3825b779e29eSEdgar E. Iglesias env->regs[9] = regs->r9; 3826b779e29eSEdgar E. Iglesias env->regs[10] = regs->r10; 3827b779e29eSEdgar E. Iglesias env->regs[11] = regs->r11; 3828b779e29eSEdgar E. Iglesias env->regs[12] = regs->r12; 3829b779e29eSEdgar E. Iglesias env->regs[13] = regs->r13; 3830b779e29eSEdgar E. Iglesias env->regs[14] = regs->r14; 3831b779e29eSEdgar E. Iglesias env->regs[15] = regs->r15; 3832b779e29eSEdgar E. Iglesias env->regs[16] = regs->r16; 3833b779e29eSEdgar E. Iglesias env->regs[17] = regs->r17; 3834b779e29eSEdgar E. Iglesias env->regs[18] = regs->r18; 3835b779e29eSEdgar E. Iglesias env->regs[19] = regs->r19; 3836b779e29eSEdgar E. Iglesias env->regs[20] = regs->r20; 3837b779e29eSEdgar E. Iglesias env->regs[21] = regs->r21; 3838b779e29eSEdgar E. Iglesias env->regs[22] = regs->r22; 3839b779e29eSEdgar E. Iglesias env->regs[23] = regs->r23; 3840b779e29eSEdgar E. Iglesias env->regs[24] = regs->r24; 3841b779e29eSEdgar E. Iglesias env->regs[25] = regs->r25; 3842b779e29eSEdgar E. Iglesias env->regs[26] = regs->r26; 3843b779e29eSEdgar E. Iglesias env->regs[27] = regs->r27; 3844b779e29eSEdgar E. Iglesias env->regs[28] = regs->r28; 3845b779e29eSEdgar E. Iglesias env->regs[29] = regs->r29; 3846b779e29eSEdgar E. Iglesias env->regs[30] = regs->r30; 3847b779e29eSEdgar E. Iglesias env->regs[31] = regs->r31; 3848b779e29eSEdgar E. Iglesias env->sregs[SR_PC] = regs->pc; 3849b779e29eSEdgar E. Iglesias } 3850048f6b4dSbellard #elif defined(TARGET_MIPS) 3851048f6b4dSbellard { 3852048f6b4dSbellard int i; 3853048f6b4dSbellard 3854048f6b4dSbellard for(i = 0; i < 32; i++) { 3855b5dc7732Sths env->active_tc.gpr[i] = regs->regs[i]; 3856048f6b4dSbellard } 38570fddbbf2SNathan Froyd env->active_tc.PC = regs->cp0_epc & ~(target_ulong)1; 38580fddbbf2SNathan Froyd if (regs->cp0_epc & 1) { 38590fddbbf2SNathan Froyd env->hflags |= MIPS_HFLAG_M16; 38600fddbbf2SNathan Froyd } 3861048f6b4dSbellard } 3862d962783eSJia Liu #elif defined(TARGET_OPENRISC) 3863d962783eSJia Liu { 3864d962783eSJia Liu int i; 3865d962783eSJia Liu 3866d962783eSJia Liu for (i = 0; i < 32; i++) { 3867d962783eSJia Liu env->gpr[i] = regs->gpr[i]; 3868d962783eSJia Liu } 3869d962783eSJia Liu 3870d962783eSJia Liu env->sr = regs->sr; 3871d962783eSJia Liu env->pc = regs->pc; 3872d962783eSJia Liu } 3873fdf9b3e8Sbellard #elif defined(TARGET_SH4) 3874fdf9b3e8Sbellard { 3875fdf9b3e8Sbellard int i; 3876fdf9b3e8Sbellard 3877fdf9b3e8Sbellard for(i = 0; i < 16; i++) { 3878fdf9b3e8Sbellard env->gregs[i] = regs->regs[i]; 3879fdf9b3e8Sbellard } 3880fdf9b3e8Sbellard env->pc = regs->pc; 3881fdf9b3e8Sbellard } 38827a3148a9Sj_mayer #elif defined(TARGET_ALPHA) 38837a3148a9Sj_mayer { 38847a3148a9Sj_mayer int i; 38857a3148a9Sj_mayer 38867a3148a9Sj_mayer for(i = 0; i < 28; i++) { 3887992f48a0Sblueswir1 env->ir[i] = ((abi_ulong *)regs)[i]; 38887a3148a9Sj_mayer } 3889dad081eeSRichard Henderson env->ir[IR_SP] = regs->usp; 38907a3148a9Sj_mayer env->pc = regs->pc; 38917a3148a9Sj_mayer } 389248733d19Sths #elif defined(TARGET_CRIS) 389348733d19Sths { 389448733d19Sths env->regs[0] = regs->r0; 389548733d19Sths env->regs[1] = regs->r1; 389648733d19Sths env->regs[2] = regs->r2; 389748733d19Sths env->regs[3] = regs->r3; 389848733d19Sths env->regs[4] = regs->r4; 389948733d19Sths env->regs[5] = regs->r5; 390048733d19Sths env->regs[6] = regs->r6; 390148733d19Sths env->regs[7] = regs->r7; 390248733d19Sths env->regs[8] = regs->r8; 390348733d19Sths env->regs[9] = regs->r9; 390448733d19Sths env->regs[10] = regs->r10; 390548733d19Sths env->regs[11] = regs->r11; 390648733d19Sths env->regs[12] = regs->r12; 390748733d19Sths env->regs[13] = regs->r13; 390848733d19Sths env->regs[14] = info->start_stack; 390948733d19Sths env->regs[15] = regs->acr; 391048733d19Sths env->pc = regs->erp; 391148733d19Sths } 3912a4c075f1SUlrich Hecht #elif defined(TARGET_S390X) 3913a4c075f1SUlrich Hecht { 3914a4c075f1SUlrich Hecht int i; 3915a4c075f1SUlrich Hecht for (i = 0; i < 16; i++) { 3916a4c075f1SUlrich Hecht env->regs[i] = regs->gprs[i]; 3917a4c075f1SUlrich Hecht } 3918a4c075f1SUlrich Hecht env->psw.mask = regs->psw.mask; 3919a4c075f1SUlrich Hecht env->psw.addr = regs->psw.addr; 3920a4c075f1SUlrich Hecht } 3921b346ff46Sbellard #else 3922b346ff46Sbellard #error unsupported target CPU 3923b346ff46Sbellard #endif 392431e31b8aSbellard 3925d2fbca94SGuan Xuetao #if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32) 3926a87295e8Spbrook ts->stack_base = info->start_stack; 3927a87295e8Spbrook ts->heap_base = info->brk; 3928a87295e8Spbrook /* This will be filled in on the first SYS_HEAPINFO call. */ 3929a87295e8Spbrook ts->heap_limit = 0; 3930a87295e8Spbrook #endif 3931a87295e8Spbrook 393274c33bedSbellard if (gdbstub_port) { 3933ff7a981aSPeter Maydell if (gdbserver_start(gdbstub_port) < 0) { 3934ff7a981aSPeter Maydell fprintf(stderr, "qemu: could not open gdbserver on port %d\n", 3935ff7a981aSPeter Maydell gdbstub_port); 3936ff7a981aSPeter Maydell exit(1); 3937ff7a981aSPeter Maydell } 39381fddef4bSbellard gdb_handlesig(env, 0); 39391fddef4bSbellard } 39401b6b029eSbellard cpu_loop(env); 39411b6b029eSbellard /* never exits */ 394231e31b8aSbellard return 0; 394331e31b8aSbellard } 3944