blob: 5c2f7b26b40191973785038ee9f843b6930a90bf [file] [log] [blame]
bellard31e31b82003-02-18 22:55:36 +00001/*
bellard93ac68b2003-09-30 20:57:29 +00002 * qemu user main
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard68d0f702008-01-06 17:21:48 +00004 * Copyright (c) 2003-2008 Fabrice Bellard
bellard31e31b82003-02-18 22:55:36 +00005 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * along with this program; if not, see <http://www.gnu.org/licenses/>.
bellard31e31b82003-02-18 22:55:36 +000018 */
19#include <stdlib.h>
20#include <stdio.h>
21#include <stdarg.h>
bellard04369ff2003-03-20 22:33:23 +000022#include <string.h>
bellard31e31b82003-02-18 22:55:36 +000023#include <errno.h>
bellard0ecfa992003-03-03 14:32:43 +000024#include <unistd.h>
balroge4415702008-11-10 02:55:33 +000025#include <sys/mman.h>
Mika Westerbergedf8e2a2009-04-07 09:57:11 +030026#include <sys/syscall.h>
Richard Henderson703e0e82010-03-19 14:21:13 -070027#include <sys/resource.h>
bellard31e31b82003-02-18 22:55:36 +000028
bellard3ef693a2003-03-23 20:17:16 +000029#include "qemu.h"
aurel32ca10f862008-04-11 21:35:42 +000030#include "qemu-common.h"
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010031#include "qemu/cache-utils.h"
Blue Swirl2b41f102011-06-19 20:38:22 +000032#include "cpu.h"
Richard Henderson9002ec72010-05-06 08:50:41 -070033#include "tcg.h"
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010034#include "qemu/timer.h"
35#include "qemu/envlist.h"
Paul Brookd8fd2952012-03-30 18:02:50 +010036#include "elf.h"
aurel3204a6dfe2009-01-30 19:59:17 +000037
aurel32d088d662009-01-30 20:09:01 +000038char *exec_path;
39
aurel321b530a62009-04-05 20:08:59 +000040int singlestep;
Johannes Schauerfc9c5412011-08-06 08:54:12 +020041const char *filename;
42const char *argv0;
43int gdbstub_port;
44envlist_t *envlist;
45const char *cpu_model;
Paul Brook379f6692009-07-17 12:48:08 +010046unsigned long mmap_min_addr;
Richard Henderson14f24e12010-03-10 15:39:07 -080047#if defined(CONFIG_USE_GUEST_BASE)
Paul Brook379f6692009-07-17 12:48:08 +010048unsigned long guest_base;
49int have_guest_base;
Alexander Graf288e65b2011-12-14 00:33:28 +010050#if (TARGET_LONG_BITS == 32) && (HOST_LONG_BITS == 64)
51/*
52 * When running 32-on-64 we should make sure we can fit all of the possible
53 * guest address space into a contiguous chunk of virtual host memory.
54 *
55 * This way we will never overlap with our own libraries or binaries or stack
56 * or anything else that QEMU maps.
57 */
Alexander Graf314992b2013-01-03 14:17:18 +010058# ifdef TARGET_MIPS
59/* MIPS only supports 31 bits of virtual address space for user space */
60unsigned long reserved_va = 0x77000000;
61# else
Alexander Graf288e65b2011-12-14 00:33:28 +010062unsigned long reserved_va = 0xf7000000;
Alexander Graf314992b2013-01-03 14:17:18 +010063# endif
Alexander Graf288e65b2011-12-14 00:33:28 +010064#else
Paul Brook68a1c812010-05-29 02:27:35 +010065unsigned long reserved_va;
Paul Brook379f6692009-07-17 12:48:08 +010066#endif
Alexander Graf288e65b2011-12-14 00:33:28 +010067#endif
aurel321b530a62009-04-05 20:08:59 +000068
Johannes Schauerfc9c5412011-08-06 08:54:12 +020069static void usage(void);
70
Paolo Bonzini7ee28222010-05-26 16:08:22 +020071static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
pbrookc5937222006-05-14 11:30:38 +000072const char *qemu_uname_release = CONFIG_UNAME_RELEASE;
bellard586314f2003-03-03 15:02:29 +000073
bellard9de5e442003-03-23 16:49:39 +000074/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
75 we allocate a bigger stack. Need a better solution, for example
76 by remapping the process stack directly at the right place */
Richard Henderson703e0e82010-03-19 14:21:13 -070077unsigned long guest_stack_size = 8 * 1024 * 1024UL;
bellard31e31b82003-02-18 22:55:36 +000078
79void gemu_log(const char *fmt, ...)
80{
81 va_list ap;
82
83 va_start(ap, fmt);
84 vfprintf(stderr, fmt, ap);
85 va_end(ap);
86}
87
blueswir18fcd3692008-08-17 20:26:25 +000088#if defined(TARGET_I386)
Andreas Färber05390242012-02-25 03:37:53 +010089int cpu_get_pic_interrupt(CPUX86State *env)
bellard92ccca62003-06-24 13:30:31 +000090{
91 return -1;
92}
blueswir18fcd3692008-08-17 20:26:25 +000093#endif
bellard92ccca62003-06-24 13:30:31 +000094
pbrookd5975362008-06-07 20:50:51 +000095/***********************************************************/
96/* Helper routines for implementing atomic operations. */
97
98/* To implement exclusive operations we force all cpus to syncronise.
99 We don't require a full sync, only that no cpus are executing guest code.
100 The alternative is to map target atomic ops onto host equivalents,
101 which requires quite a lot of per host/target work. */
pbrookc2764712009-03-07 15:24:59 +0000102static pthread_mutex_t cpu_list_mutex = PTHREAD_MUTEX_INITIALIZER;
pbrookd5975362008-06-07 20:50:51 +0000103static pthread_mutex_t exclusive_lock = PTHREAD_MUTEX_INITIALIZER;
104static pthread_cond_t exclusive_cond = PTHREAD_COND_INITIALIZER;
105static pthread_cond_t exclusive_resume = PTHREAD_COND_INITIALIZER;
106static int pending_cpus;
107
108/* Make sure everything is in a consistent state for calling fork(). */
109void fork_start(void)
110{
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +0700111 pthread_mutex_lock(&tcg_ctx.tb_ctx.tb_lock);
pbrookd5975362008-06-07 20:50:51 +0000112 pthread_mutex_lock(&exclusive_lock);
Riku Voipiod032d1b2009-12-04 15:16:31 +0200113 mmap_fork_start();
pbrookd5975362008-06-07 20:50:51 +0000114}
115
116void fork_end(int child)
117{
Riku Voipiod032d1b2009-12-04 15:16:31 +0200118 mmap_fork_end(child);
pbrookd5975362008-06-07 20:50:51 +0000119 if (child) {
Andreas Färberbdc44642013-06-24 23:50:24 +0200120 CPUState *cpu, *next_cpu;
pbrookd5975362008-06-07 20:50:51 +0000121 /* Child processes created by fork() only have a single thread.
122 Discard information about the parent threads. */
Andreas Färberbdc44642013-06-24 23:50:24 +0200123 CPU_FOREACH_SAFE(cpu, next_cpu) {
124 if (cpu != thread_cpu) {
125 QTAILQ_REMOVE(&cpus, thread_cpu, node);
126 }
127 }
pbrookd5975362008-06-07 20:50:51 +0000128 pending_cpus = 0;
129 pthread_mutex_init(&exclusive_lock, NULL);
pbrookc2764712009-03-07 15:24:59 +0000130 pthread_mutex_init(&cpu_list_mutex, NULL);
pbrookd5975362008-06-07 20:50:51 +0000131 pthread_cond_init(&exclusive_cond, NULL);
132 pthread_cond_init(&exclusive_resume, NULL);
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +0700133 pthread_mutex_init(&tcg_ctx.tb_ctx.tb_lock, NULL);
Andreas Färbera2247f82013-06-09 19:47:04 +0200134 gdbserver_fork((CPUArchState *)thread_cpu->env_ptr);
pbrookd5975362008-06-07 20:50:51 +0000135 } else {
136 pthread_mutex_unlock(&exclusive_lock);
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +0700137 pthread_mutex_unlock(&tcg_ctx.tb_ctx.tb_lock);
pbrookd5975362008-06-07 20:50:51 +0000138 }
pbrookd5975362008-06-07 20:50:51 +0000139}
140
141/* Wait for pending exclusive operations to complete. The exclusive lock
142 must be held. */
143static inline void exclusive_idle(void)
144{
145 while (pending_cpus) {
146 pthread_cond_wait(&exclusive_resume, &exclusive_lock);
147 }
148}
149
150/* Start an exclusive operation.
151 Must only be called from outside cpu_arm_exec. */
152static inline void start_exclusive(void)
153{
Andreas Färber0315c312012-12-17 07:34:52 +0100154 CPUState *other_cpu;
155
pbrookd5975362008-06-07 20:50:51 +0000156 pthread_mutex_lock(&exclusive_lock);
157 exclusive_idle();
158
159 pending_cpus = 1;
160 /* Make all other cpus stop executing. */
Andreas Färberbdc44642013-06-24 23:50:24 +0200161 CPU_FOREACH(other_cpu) {
Andreas Färber0315c312012-12-17 07:34:52 +0100162 if (other_cpu->running) {
pbrookd5975362008-06-07 20:50:51 +0000163 pending_cpus++;
Andreas Färber60a3e172013-05-17 18:26:54 +0200164 cpu_exit(other_cpu);
pbrookd5975362008-06-07 20:50:51 +0000165 }
166 }
167 if (pending_cpus > 1) {
168 pthread_cond_wait(&exclusive_cond, &exclusive_lock);
169 }
170}
171
172/* Finish an exclusive operation. */
173static inline void end_exclusive(void)
174{
175 pending_cpus = 0;
176 pthread_cond_broadcast(&exclusive_resume);
177 pthread_mutex_unlock(&exclusive_lock);
178}
179
180/* Wait for exclusive ops to finish, and begin cpu execution. */
Andreas Färber0315c312012-12-17 07:34:52 +0100181static inline void cpu_exec_start(CPUState *cpu)
pbrookd5975362008-06-07 20:50:51 +0000182{
183 pthread_mutex_lock(&exclusive_lock);
184 exclusive_idle();
Andreas Färber0315c312012-12-17 07:34:52 +0100185 cpu->running = true;
pbrookd5975362008-06-07 20:50:51 +0000186 pthread_mutex_unlock(&exclusive_lock);
187}
188
189/* Mark cpu as not executing, and release pending exclusive ops. */
Andreas Färber0315c312012-12-17 07:34:52 +0100190static inline void cpu_exec_end(CPUState *cpu)
pbrookd5975362008-06-07 20:50:51 +0000191{
192 pthread_mutex_lock(&exclusive_lock);
Andreas Färber0315c312012-12-17 07:34:52 +0100193 cpu->running = false;
pbrookd5975362008-06-07 20:50:51 +0000194 if (pending_cpus > 1) {
195 pending_cpus--;
196 if (pending_cpus == 1) {
197 pthread_cond_signal(&exclusive_cond);
198 }
199 }
200 exclusive_idle();
201 pthread_mutex_unlock(&exclusive_lock);
202}
pbrookc2764712009-03-07 15:24:59 +0000203
204void cpu_list_lock(void)
205{
206 pthread_mutex_lock(&cpu_list_mutex);
207}
208
209void cpu_list_unlock(void)
210{
211 pthread_mutex_unlock(&cpu_list_mutex);
212}
pbrookd5975362008-06-07 20:50:51 +0000213
214
bellarda541f292004-04-12 20:39:29 +0000215#ifdef TARGET_I386
216/***********************************************************/
217/* CPUX86 core interface */
218
Andreas Färber05390242012-02-25 03:37:53 +0100219void cpu_smm_update(CPUX86State *env)
bellard02a16022006-09-24 18:48:23 +0000220{
221}
222
bellard28ab0e22004-05-20 14:02:14 +0000223uint64_t cpu_get_tsc(CPUX86State *env)
224{
225 return cpu_get_real_ticks();
226}
227
ths5fafdf22007-09-16 21:08:06 +0000228static void write_dt(void *ptr, unsigned long addr, unsigned long limit,
bellardf4beb512003-05-27 23:28:08 +0000229 int flags)
bellard6dbad632003-03-16 18:05:05 +0000230{
bellardf4beb512003-05-27 23:28:08 +0000231 unsigned int e1, e2;
pbrook53a59602006-03-25 19:31:22 +0000232 uint32_t *p;
bellard6dbad632003-03-16 18:05:05 +0000233 e1 = (addr << 16) | (limit & 0xffff);
234 e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
bellardf4beb512003-05-27 23:28:08 +0000235 e2 |= flags;
pbrook53a59602006-03-25 19:31:22 +0000236 p = ptr;
malcd538e8f2008-08-20 22:39:26 +0000237 p[0] = tswap32(e1);
238 p[1] = tswap32(e2);
bellardf4beb512003-05-27 23:28:08 +0000239}
240
balroge4415702008-11-10 02:55:33 +0000241static uint64_t *idt_table;
blueswir1eb38c522008-09-06 17:47:39 +0000242#ifdef TARGET_X86_64
bellardd2fd1af2007-11-14 18:08:56 +0000243static void set_gate64(void *ptr, unsigned int type, unsigned int dpl,
244 uint64_t addr, unsigned int sel)
245{
bellard4dbc4222007-11-15 15:27:03 +0000246 uint32_t *p, e1, e2;
bellardd2fd1af2007-11-14 18:08:56 +0000247 e1 = (addr & 0xffff) | (sel << 16);
248 e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
249 p = ptr;
bellard4dbc4222007-11-15 15:27:03 +0000250 p[0] = tswap32(e1);
251 p[1] = tswap32(e2);
252 p[2] = tswap32(addr >> 32);
253 p[3] = 0;
bellardd2fd1af2007-11-14 18:08:56 +0000254}
255/* only dpl matters as we do only user space emulation */
256static void set_idt(int n, unsigned int dpl)
257{
258 set_gate64(idt_table + n * 2, 0, dpl, 0, 0);
259}
260#else
ths5fafdf22007-09-16 21:08:06 +0000261static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
bellardd2fd1af2007-11-14 18:08:56 +0000262 uint32_t addr, unsigned int sel)
bellardf4beb512003-05-27 23:28:08 +0000263{
bellard4dbc4222007-11-15 15:27:03 +0000264 uint32_t *p, e1, e2;
bellardf4beb512003-05-27 23:28:08 +0000265 e1 = (addr & 0xffff) | (sel << 16);
266 e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
pbrook53a59602006-03-25 19:31:22 +0000267 p = ptr;
bellard4dbc4222007-11-15 15:27:03 +0000268 p[0] = tswap32(e1);
269 p[1] = tswap32(e2);
bellard6dbad632003-03-16 18:05:05 +0000270}
271
bellardf4beb512003-05-27 23:28:08 +0000272/* only dpl matters as we do only user space emulation */
273static void set_idt(int n, unsigned int dpl)
274{
275 set_gate(idt_table + n, 0, dpl, 0, 0);
276}
bellardd2fd1af2007-11-14 18:08:56 +0000277#endif
bellard31e31b82003-02-18 22:55:36 +0000278
bellard89e957e2003-05-10 12:33:15 +0000279void cpu_loop(CPUX86State *env)
bellard1b6b0292003-03-22 17:31:38 +0000280{
Andreas Färberdb6b81d2013-06-27 19:49:31 +0200281 CPUState *cs = CPU(x86_env_get_cpu(env));
bellardbc8a22c2003-03-30 21:02:40 +0000282 int trapnr;
blueswir1992f48a2007-10-14 16:27:31 +0000283 abi_ulong pc;
Anthony Liguoric227f092009-10-01 16:12:16 -0500284 target_siginfo_t info;
bellard851e67a2003-03-29 16:53:14 +0000285
bellard1b6b0292003-03-22 17:31:38 +0000286 for(;;) {
bellardbc8a22c2003-03-30 21:02:40 +0000287 trapnr = cpu_x86_exec(env);
bellardbc8a22c2003-03-30 21:02:40 +0000288 switch(trapnr) {
bellardf4beb512003-05-27 23:28:08 +0000289 case 0x80:
bellardd2fd1af2007-11-14 18:08:56 +0000290 /* linux syscall from int $0x80 */
ths5fafdf22007-09-16 21:08:06 +0000291 env->regs[R_EAX] = do_syscall(env,
292 env->regs[R_EAX],
bellardf4beb512003-05-27 23:28:08 +0000293 env->regs[R_EBX],
294 env->regs[R_ECX],
295 env->regs[R_EDX],
296 env->regs[R_ESI],
297 env->regs[R_EDI],
Peter Maydell5945cfc2011-06-16 17:37:13 +0100298 env->regs[R_EBP],
299 0, 0);
bellardf4beb512003-05-27 23:28:08 +0000300 break;
bellardd2fd1af2007-11-14 18:08:56 +0000301#ifndef TARGET_ABI32
302 case EXCP_SYSCALL:
Stefan Weil5ba18542011-05-07 22:20:03 +0200303 /* linux syscall from syscall instruction */
bellardd2fd1af2007-11-14 18:08:56 +0000304 env->regs[R_EAX] = do_syscall(env,
305 env->regs[R_EAX],
306 env->regs[R_EDI],
307 env->regs[R_ESI],
308 env->regs[R_EDX],
309 env->regs[10],
310 env->regs[8],
Peter Maydell5945cfc2011-06-16 17:37:13 +0100311 env->regs[9],
312 0, 0);
bellardd2fd1af2007-11-14 18:08:56 +0000313 env->eip = env->exception_next_eip;
314 break;
315#endif
bellardf4beb512003-05-27 23:28:08 +0000316 case EXCP0B_NOSEG:
317 case EXCP0C_STACK:
318 info.si_signo = SIGBUS;
319 info.si_errno = 0;
320 info.si_code = TARGET_SI_KERNEL;
321 info._sifields._sigfault._addr = 0;
pbrook624f7972008-05-31 16:11:38 +0000322 queue_signal(env, info.si_signo, &info);
bellardf4beb512003-05-27 23:28:08 +0000323 break;
bellard1b6b0292003-03-22 17:31:38 +0000324 case EXCP0D_GPF:
bellardd2fd1af2007-11-14 18:08:56 +0000325 /* XXX: potential problem if ABI32 */
j_mayer84409dd2007-04-06 08:56:50 +0000326#ifndef TARGET_X86_64
bellard851e67a2003-03-29 16:53:14 +0000327 if (env->eflags & VM_MASK) {
bellard89e957e2003-05-10 12:33:15 +0000328 handle_vm86_fault(env);
j_mayer84409dd2007-04-06 08:56:50 +0000329 } else
330#endif
331 {
bellardf4beb512003-05-27 23:28:08 +0000332 info.si_signo = SIGSEGV;
333 info.si_errno = 0;
334 info.si_code = TARGET_SI_KERNEL;
335 info._sifields._sigfault._addr = 0;
pbrook624f7972008-05-31 16:11:38 +0000336 queue_signal(env, info.si_signo, &info);
bellard1b6b0292003-03-22 17:31:38 +0000337 }
338 break;
bellardb689bc52003-05-08 15:33:33 +0000339 case EXCP0E_PAGE:
340 info.si_signo = SIGSEGV;
341 info.si_errno = 0;
342 if (!(env->error_code & 1))
343 info.si_code = TARGET_SEGV_MAPERR;
344 else
345 info.si_code = TARGET_SEGV_ACCERR;
bellard970a87a2003-06-21 13:13:25 +0000346 info._sifields._sigfault._addr = env->cr[2];
pbrook624f7972008-05-31 16:11:38 +0000347 queue_signal(env, info.si_signo, &info);
bellardb689bc52003-05-08 15:33:33 +0000348 break;
bellard9de5e442003-03-23 16:49:39 +0000349 case EXCP00_DIVZ:
j_mayer84409dd2007-04-06 08:56:50 +0000350#ifndef TARGET_X86_64
bellardbc8a22c2003-03-30 21:02:40 +0000351 if (env->eflags & VM_MASK) {
bellard447db212003-05-10 15:10:36 +0000352 handle_vm86_trap(env, trapnr);
j_mayer84409dd2007-04-06 08:56:50 +0000353 } else
354#endif
355 {
bellardbc8a22c2003-03-30 21:02:40 +0000356 /* division by zero */
357 info.si_signo = SIGFPE;
358 info.si_errno = 0;
359 info.si_code = TARGET_FPE_INTDIV;
360 info._sifields._sigfault._addr = env->eip;
pbrook624f7972008-05-31 16:11:38 +0000361 queue_signal(env, info.si_signo, &info);
bellardbc8a22c2003-03-30 21:02:40 +0000362 }
bellard9de5e442003-03-23 16:49:39 +0000363 break;
aliguori01df0402008-11-18 21:08:15 +0000364 case EXCP01_DB:
bellard447db212003-05-10 15:10:36 +0000365 case EXCP03_INT3:
j_mayer84409dd2007-04-06 08:56:50 +0000366#ifndef TARGET_X86_64
bellard447db212003-05-10 15:10:36 +0000367 if (env->eflags & VM_MASK) {
368 handle_vm86_trap(env, trapnr);
j_mayer84409dd2007-04-06 08:56:50 +0000369 } else
370#endif
371 {
bellard447db212003-05-10 15:10:36 +0000372 info.si_signo = SIGTRAP;
373 info.si_errno = 0;
aliguori01df0402008-11-18 21:08:15 +0000374 if (trapnr == EXCP01_DB) {
bellard447db212003-05-10 15:10:36 +0000375 info.si_code = TARGET_TRAP_BRKPT;
376 info._sifields._sigfault._addr = env->eip;
377 } else {
378 info.si_code = TARGET_SI_KERNEL;
379 info._sifields._sigfault._addr = 0;
380 }
pbrook624f7972008-05-31 16:11:38 +0000381 queue_signal(env, info.si_signo, &info);
bellard447db212003-05-10 15:10:36 +0000382 }
383 break;
bellard9de5e442003-03-23 16:49:39 +0000384 case EXCP04_INTO:
385 case EXCP05_BOUND:
j_mayer84409dd2007-04-06 08:56:50 +0000386#ifndef TARGET_X86_64
bellardbc8a22c2003-03-30 21:02:40 +0000387 if (env->eflags & VM_MASK) {
bellard447db212003-05-10 15:10:36 +0000388 handle_vm86_trap(env, trapnr);
j_mayer84409dd2007-04-06 08:56:50 +0000389 } else
390#endif
391 {
bellardbc8a22c2003-03-30 21:02:40 +0000392 info.si_signo = SIGSEGV;
393 info.si_errno = 0;
bellardb689bc52003-05-08 15:33:33 +0000394 info.si_code = TARGET_SI_KERNEL;
bellardbc8a22c2003-03-30 21:02:40 +0000395 info._sifields._sigfault._addr = 0;
pbrook624f7972008-05-31 16:11:38 +0000396 queue_signal(env, info.si_signo, &info);
bellardbc8a22c2003-03-30 21:02:40 +0000397 }
bellard9de5e442003-03-23 16:49:39 +0000398 break;
399 case EXCP06_ILLOP:
400 info.si_signo = SIGILL;
401 info.si_errno = 0;
402 info.si_code = TARGET_ILL_ILLOPN;
403 info._sifields._sigfault._addr = env->eip;
pbrook624f7972008-05-31 16:11:38 +0000404 queue_signal(env, info.si_signo, &info);
bellard9de5e442003-03-23 16:49:39 +0000405 break;
406 case EXCP_INTERRUPT:
407 /* just indicate that signals should be handled asap */
408 break;
bellard1fddef42005-04-17 19:16:13 +0000409 case EXCP_DEBUG:
410 {
411 int sig;
412
Andreas Färberdb6b81d2013-06-27 19:49:31 +0200413 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
bellard1fddef42005-04-17 19:16:13 +0000414 if (sig)
415 {
416 info.si_signo = sig;
417 info.si_errno = 0;
418 info.si_code = TARGET_TRAP_BRKPT;
pbrook624f7972008-05-31 16:11:38 +0000419 queue_signal(env, info.si_signo, &info);
bellard1fddef42005-04-17 19:16:13 +0000420 }
421 }
422 break;
bellard1b6b0292003-03-22 17:31:38 +0000423 default:
bellard970a87a2003-06-21 13:13:25 +0000424 pc = env->segs[R_CS].base + env->eip;
ths5fafdf22007-09-16 21:08:06 +0000425 fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
bellardbc8a22c2003-03-30 21:02:40 +0000426 (long)pc, trapnr);
bellard1b6b0292003-03-22 17:31:38 +0000427 abort();
428 }
bellard66fb9762003-03-23 01:06:05 +0000429 process_pending_signals(env);
bellard1b6b0292003-03-22 17:31:38 +0000430 }
431}
bellardb346ff42003-06-15 20:05:50 +0000432#endif
433
434#ifdef TARGET_ARM
435
Paul Brookd8fd2952012-03-30 18:02:50 +0100436#define get_user_code_u32(x, gaddr, doswap) \
437 ({ abi_long __r = get_user_u32((x), (gaddr)); \
438 if (!__r && (doswap)) { \
439 (x) = bswap32(x); \
440 } \
441 __r; \
442 })
443
444#define get_user_code_u16(x, gaddr, doswap) \
445 ({ abi_long __r = get_user_u16((x), (gaddr)); \
446 if (!__r && (doswap)) { \
447 (x) = bswap16(x); \
448 } \
449 __r; \
450 })
451
Dr. David Alan Gilbert97cc7562011-08-31 17:24:34 +0100452/*
453 * See the Linux kernel's Documentation/arm/kernel_user_helpers.txt
454 * Input:
455 * r0 = pointer to oldval
456 * r1 = pointer to newval
457 * r2 = pointer to target value
458 *
459 * Output:
460 * r0 = 0 if *ptr was changed, non-0 if no exchange happened
461 * C set if *ptr was changed, clear if no exchange happened
462 *
463 * Note segv's in kernel helpers are a bit tricky, we can set the
464 * data address sensibly but the PC address is just the entry point.
465 */
466static void arm_kernel_cmpxchg64_helper(CPUARMState *env)
467{
468 uint64_t oldval, newval, val;
469 uint32_t addr, cpsr;
470 target_siginfo_t info;
471
472 /* Based on the 32 bit code in do_kernel_trap */
473
474 /* XXX: This only works between threads, not between processes.
475 It's probably possible to implement this with native host
476 operations. However things like ldrex/strex are much harder so
477 there's not much point trying. */
478 start_exclusive();
479 cpsr = cpsr_read(env);
480 addr = env->regs[2];
481
482 if (get_user_u64(oldval, env->regs[0])) {
483 env->cp15.c6_data = env->regs[0];
484 goto segv;
485 };
486
487 if (get_user_u64(newval, env->regs[1])) {
488 env->cp15.c6_data = env->regs[1];
489 goto segv;
490 };
491
492 if (get_user_u64(val, addr)) {
493 env->cp15.c6_data = addr;
494 goto segv;
495 }
496
497 if (val == oldval) {
498 val = newval;
499
500 if (put_user_u64(val, addr)) {
501 env->cp15.c6_data = addr;
502 goto segv;
503 };
504
505 env->regs[0] = 0;
506 cpsr |= CPSR_C;
507 } else {
508 env->regs[0] = -1;
509 cpsr &= ~CPSR_C;
510 }
511 cpsr_write(env, cpsr, CPSR_C);
512 end_exclusive();
513 return;
514
515segv:
516 end_exclusive();
517 /* We get the PC of the entry address - which is as good as anything,
518 on a real kernel what you get depends on which mode it uses. */
519 info.si_signo = SIGSEGV;
520 info.si_errno = 0;
521 /* XXX: check env->error_code */
522 info.si_code = TARGET_SEGV_MAPERR;
523 info._sifields._sigfault._addr = env->cp15.c6_data;
524 queue_signal(env, info.si_signo, &info);
525
526 end_exclusive();
527}
528
pbrookfbb4a2e2008-05-29 00:20:44 +0000529/* Handle a jump to the kernel code page. */
530static int
531do_kernel_trap(CPUARMState *env)
532{
533 uint32_t addr;
534 uint32_t cpsr;
535 uint32_t val;
536
537 switch (env->regs[15]) {
538 case 0xffff0fa0: /* __kernel_memory_barrier */
539 /* ??? No-op. Will need to do better for SMP. */
540 break;
541 case 0xffff0fc0: /* __kernel_cmpxchg */
pbrookd5975362008-06-07 20:50:51 +0000542 /* XXX: This only works between threads, not between processes.
543 It's probably possible to implement this with native host
544 operations. However things like ldrex/strex are much harder so
545 there's not much point trying. */
546 start_exclusive();
pbrookfbb4a2e2008-05-29 00:20:44 +0000547 cpsr = cpsr_read(env);
548 addr = env->regs[2];
549 /* FIXME: This should SEGV if the access fails. */
550 if (get_user_u32(val, addr))
551 val = ~env->regs[0];
552 if (val == env->regs[0]) {
553 val = env->regs[1];
554 /* FIXME: Check for segfaults. */
555 put_user_u32(val, addr);
556 env->regs[0] = 0;
557 cpsr |= CPSR_C;
558 } else {
559 env->regs[0] = -1;
560 cpsr &= ~CPSR_C;
561 }
562 cpsr_write(env, cpsr, CPSR_C);
pbrookd5975362008-06-07 20:50:51 +0000563 end_exclusive();
pbrookfbb4a2e2008-05-29 00:20:44 +0000564 break;
565 case 0xffff0fe0: /* __kernel_get_tls */
566 env->regs[0] = env->cp15.c13_tls2;
567 break;
Dr. David Alan Gilbert97cc7562011-08-31 17:24:34 +0100568 case 0xffff0f60: /* __kernel_cmpxchg64 */
569 arm_kernel_cmpxchg64_helper(env);
570 break;
571
pbrookfbb4a2e2008-05-29 00:20:44 +0000572 default:
573 return 1;
574 }
575 /* Jump back to the caller. */
576 addr = env->regs[14];
577 if (addr & 1) {
578 env->thumb = 1;
579 addr &= ~1;
580 }
581 env->regs[15] = addr;
582
583 return 0;
584}
585
Paul Brook426f5ab2009-11-22 21:35:13 +0000586static int do_strex(CPUARMState *env)
587{
588 uint32_t val;
589 int size;
590 int rc = 1;
591 int segv = 0;
592 uint32_t addr;
593 start_exclusive();
594 addr = env->exclusive_addr;
595 if (addr != env->exclusive_test) {
596 goto fail;
597 }
598 size = env->exclusive_info & 0xf;
599 switch (size) {
600 case 0:
601 segv = get_user_u8(val, addr);
602 break;
603 case 1:
604 segv = get_user_u16(val, addr);
605 break;
606 case 2:
607 case 3:
608 segv = get_user_u32(val, addr);
609 break;
Aurelien Jarnof7001a32009-12-24 00:17:12 +0100610 default:
611 abort();
Paul Brook426f5ab2009-11-22 21:35:13 +0000612 }
613 if (segv) {
614 env->cp15.c6_data = addr;
615 goto done;
616 }
617 if (val != env->exclusive_val) {
618 goto fail;
619 }
620 if (size == 3) {
621 segv = get_user_u32(val, addr + 4);
622 if (segv) {
623 env->cp15.c6_data = addr + 4;
624 goto done;
625 }
626 if (val != env->exclusive_high) {
627 goto fail;
628 }
629 }
630 val = env->regs[(env->exclusive_info >> 8) & 0xf];
631 switch (size) {
632 case 0:
633 segv = put_user_u8(val, addr);
634 break;
635 case 1:
636 segv = put_user_u16(val, addr);
637 break;
638 case 2:
639 case 3:
640 segv = put_user_u32(val, addr);
641 break;
642 }
643 if (segv) {
644 env->cp15.c6_data = addr;
645 goto done;
646 }
647 if (size == 3) {
648 val = env->regs[(env->exclusive_info >> 12) & 0xf];
Peter Maydell2c9adbd2010-12-07 15:37:34 +0000649 segv = put_user_u32(val, addr + 4);
Paul Brook426f5ab2009-11-22 21:35:13 +0000650 if (segv) {
651 env->cp15.c6_data = addr + 4;
652 goto done;
653 }
654 }
655 rc = 0;
656fail:
Paul Brook725b8a62009-12-11 15:38:10 +0000657 env->regs[15] += 4;
Paul Brook426f5ab2009-11-22 21:35:13 +0000658 env->regs[(env->exclusive_info >> 4) & 0xf] = rc;
659done:
660 end_exclusive();
661 return segv;
662}
663
bellardb346ff42003-06-15 20:05:50 +0000664void cpu_loop(CPUARMState *env)
665{
Andreas Färber0315c312012-12-17 07:34:52 +0100666 CPUState *cs = CPU(arm_env_get_cpu(env));
bellardb346ff42003-06-15 20:05:50 +0000667 int trapnr;
668 unsigned int n, insn;
Anthony Liguoric227f092009-10-01 16:12:16 -0500669 target_siginfo_t info;
bellardb5ff1b32005-11-26 10:38:39 +0000670 uint32_t addr;
ths3b46e622007-09-17 08:09:54 +0000671
bellardb346ff42003-06-15 20:05:50 +0000672 for(;;) {
Andreas Färber0315c312012-12-17 07:34:52 +0100673 cpu_exec_start(cs);
bellardb346ff42003-06-15 20:05:50 +0000674 trapnr = cpu_arm_exec(env);
Andreas Färber0315c312012-12-17 07:34:52 +0100675 cpu_exec_end(cs);
bellardb346ff42003-06-15 20:05:50 +0000676 switch(trapnr) {
677 case EXCP_UDEF:
bellardc6981052004-02-16 21:49:03 +0000678 {
679 TaskState *ts = env->opaque;
680 uint32_t opcode;
aurel326d9a42b2008-04-07 20:30:53 +0000681 int rc;
bellardc6981052004-02-16 21:49:03 +0000682
683 /* we handle the FPU emulation here, as Linux */
684 /* we get the opcode */
bellard2f619692007-11-16 10:46:05 +0000685 /* FIXME - what to do if get_user() fails? */
Paul Brookd8fd2952012-03-30 18:02:50 +0100686 get_user_code_u32(opcode, env->regs[15], env->bswap_code);
ths3b46e622007-09-17 08:09:54 +0000687
aurel326d9a42b2008-04-07 20:30:53 +0000688 rc = EmulateAll(opcode, &ts->fpa, env);
689 if (rc == 0) { /* illegal instruction */
bellardc6981052004-02-16 21:49:03 +0000690 info.si_signo = SIGILL;
691 info.si_errno = 0;
692 info.si_code = TARGET_ILL_ILLOPN;
693 info._sifields._sigfault._addr = env->regs[15];
pbrook624f7972008-05-31 16:11:38 +0000694 queue_signal(env, info.si_signo, &info);
aurel326d9a42b2008-04-07 20:30:53 +0000695 } else if (rc < 0) { /* FP exception */
696 int arm_fpe=0;
697
698 /* translate softfloat flags to FPSR flags */
699 if (-rc & float_flag_invalid)
700 arm_fpe |= BIT_IOC;
701 if (-rc & float_flag_divbyzero)
702 arm_fpe |= BIT_DZC;
703 if (-rc & float_flag_overflow)
704 arm_fpe |= BIT_OFC;
705 if (-rc & float_flag_underflow)
706 arm_fpe |= BIT_UFC;
707 if (-rc & float_flag_inexact)
708 arm_fpe |= BIT_IXC;
709
710 FPSR fpsr = ts->fpa.fpsr;
711 //printf("fpsr 0x%x, arm_fpe 0x%x\n",fpsr,arm_fpe);
712
713 if (fpsr & (arm_fpe << 16)) { /* exception enabled? */
714 info.si_signo = SIGFPE;
715 info.si_errno = 0;
716
717 /* ordered by priority, least first */
718 if (arm_fpe & BIT_IXC) info.si_code = TARGET_FPE_FLTRES;
719 if (arm_fpe & BIT_UFC) info.si_code = TARGET_FPE_FLTUND;
720 if (arm_fpe & BIT_OFC) info.si_code = TARGET_FPE_FLTOVF;
721 if (arm_fpe & BIT_DZC) info.si_code = TARGET_FPE_FLTDIV;
722 if (arm_fpe & BIT_IOC) info.si_code = TARGET_FPE_FLTINV;
723
724 info._sifields._sigfault._addr = env->regs[15];
pbrook624f7972008-05-31 16:11:38 +0000725 queue_signal(env, info.si_signo, &info);
aurel326d9a42b2008-04-07 20:30:53 +0000726 } else {
727 env->regs[15] += 4;
728 }
729
730 /* accumulate unenabled exceptions */
731 if ((!(fpsr & BIT_IXE)) && (arm_fpe & BIT_IXC))
732 fpsr |= BIT_IXC;
733 if ((!(fpsr & BIT_UFE)) && (arm_fpe & BIT_UFC))
734 fpsr |= BIT_UFC;
735 if ((!(fpsr & BIT_OFE)) && (arm_fpe & BIT_OFC))
736 fpsr |= BIT_OFC;
737 if ((!(fpsr & BIT_DZE)) && (arm_fpe & BIT_DZC))
738 fpsr |= BIT_DZC;
739 if ((!(fpsr & BIT_IOE)) && (arm_fpe & BIT_IOC))
740 fpsr |= BIT_IOC;
741 ts->fpa.fpsr=fpsr;
742 } else { /* everything OK */
bellardc6981052004-02-16 21:49:03 +0000743 /* increment PC */
744 env->regs[15] += 4;
745 }
746 }
bellardb346ff42003-06-15 20:05:50 +0000747 break;
748 case EXCP_SWI:
pbrook06c949e2006-02-04 19:35:26 +0000749 case EXCP_BKPT:
bellardb346ff42003-06-15 20:05:50 +0000750 {
pbrookce4defa2006-02-09 16:49:55 +0000751 env->eabi = 1;
bellardb346ff42003-06-15 20:05:50 +0000752 /* system call */
pbrook06c949e2006-02-04 19:35:26 +0000753 if (trapnr == EXCP_BKPT) {
754 if (env->thumb) {
bellard2f619692007-11-16 10:46:05 +0000755 /* FIXME - what to do if get_user() fails? */
Paul Brookd8fd2952012-03-30 18:02:50 +0100756 get_user_code_u16(insn, env->regs[15], env->bswap_code);
pbrook06c949e2006-02-04 19:35:26 +0000757 n = insn & 0xff;
758 env->regs[15] += 2;
759 } else {
bellard2f619692007-11-16 10:46:05 +0000760 /* FIXME - what to do if get_user() fails? */
Paul Brookd8fd2952012-03-30 18:02:50 +0100761 get_user_code_u32(insn, env->regs[15], env->bswap_code);
pbrook06c949e2006-02-04 19:35:26 +0000762 n = (insn & 0xf) | ((insn >> 4) & 0xff0);
763 env->regs[15] += 4;
764 }
bellard192c7bd2005-04-27 20:11:21 +0000765 } else {
pbrook06c949e2006-02-04 19:35:26 +0000766 if (env->thumb) {
bellard2f619692007-11-16 10:46:05 +0000767 /* FIXME - what to do if get_user() fails? */
Paul Brookd8fd2952012-03-30 18:02:50 +0100768 get_user_code_u16(insn, env->regs[15] - 2,
769 env->bswap_code);
pbrook06c949e2006-02-04 19:35:26 +0000770 n = insn & 0xff;
771 } else {
bellard2f619692007-11-16 10:46:05 +0000772 /* FIXME - what to do if get_user() fails? */
Paul Brookd8fd2952012-03-30 18:02:50 +0100773 get_user_code_u32(insn, env->regs[15] - 4,
774 env->bswap_code);
pbrook06c949e2006-02-04 19:35:26 +0000775 n = insn & 0xffffff;
776 }
bellard192c7bd2005-04-27 20:11:21 +0000777 }
778
bellard6f1f31c2004-04-25 18:00:45 +0000779 if (n == ARM_NR_cacheflush) {
Blue Swirldcfd14b2011-05-14 11:55:30 +0000780 /* nop */
bellarda4f81972005-04-23 18:25:41 +0000781 } else if (n == ARM_NR_semihosting
782 || n == ARM_NR_thumb_semihosting) {
783 env->regs[0] = do_arm_semihosting (env);
Alexander Graf3a1363a2012-05-29 05:30:26 +0000784 } else if (n == 0 || n >= ARM_SYSCALL_BASE || env->thumb) {
bellardb346ff42003-06-15 20:05:50 +0000785 /* linux syscall */
pbrookce4defa2006-02-09 16:49:55 +0000786 if (env->thumb || n == 0) {
bellard192c7bd2005-04-27 20:11:21 +0000787 n = env->regs[7];
788 } else {
789 n -= ARM_SYSCALL_BASE;
pbrookce4defa2006-02-09 16:49:55 +0000790 env->eabi = 0;
bellard192c7bd2005-04-27 20:11:21 +0000791 }
pbrookfbb4a2e2008-05-29 00:20:44 +0000792 if ( n > ARM_NR_BASE) {
793 switch (n) {
794 case ARM_NR_cacheflush:
Blue Swirldcfd14b2011-05-14 11:55:30 +0000795 /* nop */
pbrookfbb4a2e2008-05-29 00:20:44 +0000796 break;
797 case ARM_NR_set_tls:
798 cpu_set_tls(env, env->regs[0]);
799 env->regs[0] = 0;
800 break;
801 default:
802 gemu_log("qemu: Unsupported ARM syscall: 0x%x\n",
803 n);
804 env->regs[0] = -TARGET_ENOSYS;
805 break;
806 }
807 } else {
808 env->regs[0] = do_syscall(env,
809 n,
810 env->regs[0],
811 env->regs[1],
812 env->regs[2],
813 env->regs[3],
814 env->regs[4],
Peter Maydell5945cfc2011-06-16 17:37:13 +0100815 env->regs[5],
816 0, 0);
pbrookfbb4a2e2008-05-29 00:20:44 +0000817 }
bellardb346ff42003-06-15 20:05:50 +0000818 } else {
819 goto error;
820 }
821 }
822 break;
bellard43fff232003-07-09 19:31:39 +0000823 case EXCP_INTERRUPT:
824 /* just indicate that signals should be handled asap */
825 break;
bellard68016c62005-02-07 23:12:27 +0000826 case EXCP_PREFETCH_ABORT:
balrogeae473c2008-07-29 14:09:57 +0000827 addr = env->cp15.c6_insn;
bellardb5ff1b32005-11-26 10:38:39 +0000828 goto do_segv;
bellard68016c62005-02-07 23:12:27 +0000829 case EXCP_DATA_ABORT:
balrogeae473c2008-07-29 14:09:57 +0000830 addr = env->cp15.c6_data;
bellardb5ff1b32005-11-26 10:38:39 +0000831 do_segv:
bellard68016c62005-02-07 23:12:27 +0000832 {
833 info.si_signo = SIGSEGV;
834 info.si_errno = 0;
835 /* XXX: check env->error_code */
836 info.si_code = TARGET_SEGV_MAPERR;
bellardb5ff1b32005-11-26 10:38:39 +0000837 info._sifields._sigfault._addr = addr;
pbrook624f7972008-05-31 16:11:38 +0000838 queue_signal(env, info.si_signo, &info);
bellard68016c62005-02-07 23:12:27 +0000839 }
840 break;
bellard1fddef42005-04-17 19:16:13 +0000841 case EXCP_DEBUG:
842 {
843 int sig;
844
Andreas Färberdb6b81d2013-06-27 19:49:31 +0200845 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
bellard1fddef42005-04-17 19:16:13 +0000846 if (sig)
847 {
848 info.si_signo = sig;
849 info.si_errno = 0;
850 info.si_code = TARGET_TRAP_BRKPT;
pbrook624f7972008-05-31 16:11:38 +0000851 queue_signal(env, info.si_signo, &info);
bellard1fddef42005-04-17 19:16:13 +0000852 }
853 }
854 break;
pbrookfbb4a2e2008-05-29 00:20:44 +0000855 case EXCP_KERNEL_TRAP:
856 if (do_kernel_trap(env))
857 goto error;
858 break;
Paul Brook426f5ab2009-11-22 21:35:13 +0000859 case EXCP_STREX:
860 if (do_strex(env)) {
861 addr = env->cp15.c6_data;
862 goto do_segv;
863 }
Paul Brooke9273452009-11-24 13:10:08 +0000864 break;
bellardb346ff42003-06-15 20:05:50 +0000865 default:
866 error:
ths5fafdf22007-09-16 21:08:06 +0000867 fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
bellardb346ff42003-06-15 20:05:50 +0000868 trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +0200869 cpu_dump_state(cs, stderr, fprintf, 0);
bellardb346ff42003-06-15 20:05:50 +0000870 abort();
871 }
872 process_pending_signals(env);
873 }
874}
875
876#endif
bellard1b6b0292003-03-22 17:31:38 +0000877
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800878#ifdef TARGET_UNICORE32
879
Andreas Färber05390242012-02-25 03:37:53 +0100880void cpu_loop(CPUUniCore32State *env)
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800881{
Andreas Färber0315c312012-12-17 07:34:52 +0100882 CPUState *cs = CPU(uc32_env_get_cpu(env));
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800883 int trapnr;
884 unsigned int n, insn;
885 target_siginfo_t info;
886
887 for (;;) {
Andreas Färber0315c312012-12-17 07:34:52 +0100888 cpu_exec_start(cs);
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800889 trapnr = uc32_cpu_exec(env);
Andreas Färber0315c312012-12-17 07:34:52 +0100890 cpu_exec_end(cs);
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800891 switch (trapnr) {
892 case UC32_EXCP_PRIV:
893 {
894 /* system call */
895 get_user_u32(insn, env->regs[31] - 4);
896 n = insn & 0xffffff;
897
898 if (n >= UC32_SYSCALL_BASE) {
899 /* linux syscall */
900 n -= UC32_SYSCALL_BASE;
901 if (n == UC32_SYSCALL_NR_set_tls) {
902 cpu_set_tls(env, env->regs[0]);
903 env->regs[0] = 0;
904 } else {
905 env->regs[0] = do_syscall(env,
906 n,
907 env->regs[0],
908 env->regs[1],
909 env->regs[2],
910 env->regs[3],
911 env->regs[4],
Peter Maydell5945cfc2011-06-16 17:37:13 +0100912 env->regs[5],
913 0, 0);
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800914 }
915 } else {
916 goto error;
917 }
918 }
919 break;
Guan Xuetaod48813d2012-08-10 14:42:23 +0800920 case UC32_EXCP_DTRAP:
921 case UC32_EXCP_ITRAP:
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800922 info.si_signo = SIGSEGV;
923 info.si_errno = 0;
924 /* XXX: check env->error_code */
925 info.si_code = TARGET_SEGV_MAPERR;
926 info._sifields._sigfault._addr = env->cp0.c4_faultaddr;
927 queue_signal(env, info.si_signo, &info);
928 break;
929 case EXCP_INTERRUPT:
930 /* just indicate that signals should be handled asap */
931 break;
932 case EXCP_DEBUG:
933 {
934 int sig;
935
Andreas Färberdb6b81d2013-06-27 19:49:31 +0200936 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800937 if (sig) {
938 info.si_signo = sig;
939 info.si_errno = 0;
940 info.si_code = TARGET_TRAP_BRKPT;
941 queue_signal(env, info.si_signo, &info);
942 }
943 }
944 break;
945 default:
946 goto error;
947 }
948 process_pending_signals(env);
949 }
950
951error:
952 fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +0200953 cpu_dump_state(cs, stderr, fprintf, 0);
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800954 abort();
955}
956#endif
957
bellard93ac68b2003-09-30 20:57:29 +0000958#ifdef TARGET_SPARC
blueswir1ed23fbd2008-08-30 09:20:21 +0000959#define SPARC64_STACK_BIAS 2047
bellard93ac68b2003-09-30 20:57:29 +0000960
bellard060366c2004-01-04 15:50:01 +0000961//#define DEBUG_WIN
962
bellard2623cba2005-02-19 17:25:31 +0000963/* WARNING: dealing with register windows _is_ complicated. More info
964 can be found at http://www.sics.se/~psm/sparcstack.html */
bellard060366c2004-01-04 15:50:01 +0000965static inline int get_reg_index(CPUSPARCState *env, int cwp, int index)
966{
blueswir11a140262008-06-07 08:07:37 +0000967 index = (index + cwp * 16) % (16 * env->nwindows);
bellard060366c2004-01-04 15:50:01 +0000968 /* wrap handling : if cwp is on the last window, then we use the
969 registers 'after' the end */
blueswir11a140262008-06-07 08:07:37 +0000970 if (index < 8 && env->cwp == env->nwindows - 1)
971 index += 16 * env->nwindows;
bellard060366c2004-01-04 15:50:01 +0000972 return index;
973}
974
bellard2623cba2005-02-19 17:25:31 +0000975/* save the register window 'cwp1' */
976static inline void save_window_offset(CPUSPARCState *env, int cwp1)
bellard060366c2004-01-04 15:50:01 +0000977{
bellard2623cba2005-02-19 17:25:31 +0000978 unsigned int i;
blueswir1992f48a2007-10-14 16:27:31 +0000979 abi_ulong sp_ptr;
ths3b46e622007-09-17 08:09:54 +0000980
pbrook53a59602006-03-25 19:31:22 +0000981 sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
blueswir1ed23fbd2008-08-30 09:20:21 +0000982#ifdef TARGET_SPARC64
983 if (sp_ptr & 3)
984 sp_ptr += SPARC64_STACK_BIAS;
985#endif
bellard060366c2004-01-04 15:50:01 +0000986#if defined(DEBUG_WIN)
blueswir12daf0282008-06-15 18:02:48 +0000987 printf("win_overflow: sp_ptr=0x" TARGET_ABI_FMT_lx " save_cwp=%d\n",
988 sp_ptr, cwp1);
bellard060366c2004-01-04 15:50:01 +0000989#endif
bellard2623cba2005-02-19 17:25:31 +0000990 for(i = 0; i < 16; i++) {
bellard2f619692007-11-16 10:46:05 +0000991 /* FIXME - what to do if put_user() fails? */
992 put_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
blueswir1992f48a2007-10-14 16:27:31 +0000993 sp_ptr += sizeof(abi_ulong);
bellard2623cba2005-02-19 17:25:31 +0000994 }
bellard060366c2004-01-04 15:50:01 +0000995}
996
997static void save_window(CPUSPARCState *env)
998{
bellard5ef54112006-07-18 21:14:09 +0000999#ifndef TARGET_SPARC64
bellard2623cba2005-02-19 17:25:31 +00001000 unsigned int new_wim;
blueswir11a140262008-06-07 08:07:37 +00001001 new_wim = ((env->wim >> 1) | (env->wim << (env->nwindows - 1))) &
1002 ((1LL << env->nwindows) - 1);
1003 save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
bellard2623cba2005-02-19 17:25:31 +00001004 env->wim = new_wim;
bellard5ef54112006-07-18 21:14:09 +00001005#else
blueswir11a140262008-06-07 08:07:37 +00001006 save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
bellard5ef54112006-07-18 21:14:09 +00001007 env->cansave++;
1008 env->canrestore--;
1009#endif
bellard060366c2004-01-04 15:50:01 +00001010}
1011
1012static void restore_window(CPUSPARCState *env)
1013{
blueswir1eda52952008-08-27 19:19:44 +00001014#ifndef TARGET_SPARC64
1015 unsigned int new_wim;
1016#endif
1017 unsigned int i, cwp1;
blueswir1992f48a2007-10-14 16:27:31 +00001018 abi_ulong sp_ptr;
ths3b46e622007-09-17 08:09:54 +00001019
blueswir1eda52952008-08-27 19:19:44 +00001020#ifndef TARGET_SPARC64
blueswir11a140262008-06-07 08:07:37 +00001021 new_wim = ((env->wim << 1) | (env->wim >> (env->nwindows - 1))) &
1022 ((1LL << env->nwindows) - 1);
blueswir1eda52952008-08-27 19:19:44 +00001023#endif
ths3b46e622007-09-17 08:09:54 +00001024
bellard060366c2004-01-04 15:50:01 +00001025 /* restore the invalid window */
blueswir11a140262008-06-07 08:07:37 +00001026 cwp1 = cpu_cwp_inc(env, env->cwp + 1);
pbrook53a59602006-03-25 19:31:22 +00001027 sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
blueswir1ed23fbd2008-08-30 09:20:21 +00001028#ifdef TARGET_SPARC64
1029 if (sp_ptr & 3)
1030 sp_ptr += SPARC64_STACK_BIAS;
1031#endif
bellard060366c2004-01-04 15:50:01 +00001032#if defined(DEBUG_WIN)
blueswir12daf0282008-06-15 18:02:48 +00001033 printf("win_underflow: sp_ptr=0x" TARGET_ABI_FMT_lx " load_cwp=%d\n",
1034 sp_ptr, cwp1);
bellard060366c2004-01-04 15:50:01 +00001035#endif
bellard2623cba2005-02-19 17:25:31 +00001036 for(i = 0; i < 16; i++) {
bellard2f619692007-11-16 10:46:05 +00001037 /* FIXME - what to do if get_user() fails? */
1038 get_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
blueswir1992f48a2007-10-14 16:27:31 +00001039 sp_ptr += sizeof(abi_ulong);
bellard2623cba2005-02-19 17:25:31 +00001040 }
bellard5ef54112006-07-18 21:14:09 +00001041#ifdef TARGET_SPARC64
1042 env->canrestore++;
blueswir11a140262008-06-07 08:07:37 +00001043 if (env->cleanwin < env->nwindows - 1)
1044 env->cleanwin++;
bellard5ef54112006-07-18 21:14:09 +00001045 env->cansave--;
blueswir1eda52952008-08-27 19:19:44 +00001046#else
1047 env->wim = new_wim;
bellard5ef54112006-07-18 21:14:09 +00001048#endif
bellard060366c2004-01-04 15:50:01 +00001049}
1050
1051static void flush_windows(CPUSPARCState *env)
1052{
1053 int offset, cwp1;
bellard2623cba2005-02-19 17:25:31 +00001054
1055 offset = 1;
bellard060366c2004-01-04 15:50:01 +00001056 for(;;) {
1057 /* if restore would invoke restore_window(), then we can stop */
blueswir11a140262008-06-07 08:07:37 +00001058 cwp1 = cpu_cwp_inc(env, env->cwp + offset);
blueswir1eda52952008-08-27 19:19:44 +00001059#ifndef TARGET_SPARC64
bellard060366c2004-01-04 15:50:01 +00001060 if (env->wim & (1 << cwp1))
1061 break;
blueswir1eda52952008-08-27 19:19:44 +00001062#else
1063 if (env->canrestore == 0)
1064 break;
1065 env->cansave++;
1066 env->canrestore--;
1067#endif
bellard2623cba2005-02-19 17:25:31 +00001068 save_window_offset(env, cwp1);
bellard060366c2004-01-04 15:50:01 +00001069 offset++;
1070 }
blueswir11a140262008-06-07 08:07:37 +00001071 cwp1 = cpu_cwp_inc(env, env->cwp + 1);
blueswir1eda52952008-08-27 19:19:44 +00001072#ifndef TARGET_SPARC64
1073 /* set wim so that restore will reload the registers */
bellard2623cba2005-02-19 17:25:31 +00001074 env->wim = 1 << cwp1;
blueswir1eda52952008-08-27 19:19:44 +00001075#endif
bellard2623cba2005-02-19 17:25:31 +00001076#if defined(DEBUG_WIN)
1077 printf("flush_windows: nb=%d\n", offset - 1);
bellard80a9d032005-01-03 23:31:27 +00001078#endif
bellard2623cba2005-02-19 17:25:31 +00001079}
bellard060366c2004-01-04 15:50:01 +00001080
bellard93ac68b2003-09-30 20:57:29 +00001081void cpu_loop (CPUSPARCState *env)
1082{
Andreas Färber878096e2013-05-27 01:33:50 +02001083 CPUState *cs = CPU(sparc_env_get_cpu(env));
Richard Henderson2cc20262010-04-25 11:01:25 -07001084 int trapnr;
1085 abi_long ret;
Anthony Liguoric227f092009-10-01 16:12:16 -05001086 target_siginfo_t info;
ths3b46e622007-09-17 08:09:54 +00001087
bellard060366c2004-01-04 15:50:01 +00001088 while (1) {
1089 trapnr = cpu_sparc_exec (env);
ths3b46e622007-09-17 08:09:54 +00001090
Richard Henderson20132b92012-10-09 14:50:00 -07001091 /* Compute PSR before exposing state. */
1092 if (env->cc_op != CC_OP_FLAGS) {
1093 cpu_get_psr(env);
1094 }
1095
bellard060366c2004-01-04 15:50:01 +00001096 switch (trapnr) {
bellard5ef54112006-07-18 21:14:09 +00001097#ifndef TARGET_SPARC64
ths5fafdf22007-09-16 21:08:06 +00001098 case 0x88:
bellard060366c2004-01-04 15:50:01 +00001099 case 0x90:
bellard5ef54112006-07-18 21:14:09 +00001100#else
blueswir1cb33da52007-10-09 16:34:29 +00001101 case 0x110:
bellard5ef54112006-07-18 21:14:09 +00001102 case 0x16d:
1103#endif
bellard060366c2004-01-04 15:50:01 +00001104 ret = do_syscall (env, env->gregs[1],
ths5fafdf22007-09-16 21:08:06 +00001105 env->regwptr[0], env->regwptr[1],
1106 env->regwptr[2], env->regwptr[3],
Peter Maydell5945cfc2011-06-16 17:37:13 +01001107 env->regwptr[4], env->regwptr[5],
1108 0, 0);
Richard Henderson2cc20262010-04-25 11:01:25 -07001109 if ((abi_ulong)ret >= (abi_ulong)(-515)) {
blueswir1992f48a2007-10-14 16:27:31 +00001110#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
bellard27908722006-10-23 21:31:01 +00001111 env->xcc |= PSR_CARRY;
1112#else
bellard060366c2004-01-04 15:50:01 +00001113 env->psr |= PSR_CARRY;
bellard27908722006-10-23 21:31:01 +00001114#endif
bellard060366c2004-01-04 15:50:01 +00001115 ret = -ret;
1116 } else {
blueswir1992f48a2007-10-14 16:27:31 +00001117#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
bellard27908722006-10-23 21:31:01 +00001118 env->xcc &= ~PSR_CARRY;
1119#else
bellard060366c2004-01-04 15:50:01 +00001120 env->psr &= ~PSR_CARRY;
bellard27908722006-10-23 21:31:01 +00001121#endif
bellard060366c2004-01-04 15:50:01 +00001122 }
1123 env->regwptr[0] = ret;
1124 /* next instruction */
1125 env->pc = env->npc;
1126 env->npc = env->npc + 4;
1127 break;
1128 case 0x83: /* flush windows */
blueswir1992f48a2007-10-14 16:27:31 +00001129#ifdef TARGET_ABI32
1130 case 0x103:
1131#endif
bellard2623cba2005-02-19 17:25:31 +00001132 flush_windows(env);
bellard060366c2004-01-04 15:50:01 +00001133 /* next instruction */
1134 env->pc = env->npc;
1135 env->npc = env->npc + 4;
1136 break;
bellard34751872005-07-02 14:31:34 +00001137#ifndef TARGET_SPARC64
bellard060366c2004-01-04 15:50:01 +00001138 case TT_WIN_OVF: /* window overflow */
1139 save_window(env);
1140 break;
1141 case TT_WIN_UNF: /* window underflow */
1142 restore_window(env);
1143 break;
bellard61ff6f52005-02-15 22:54:53 +00001144 case TT_TFAULT:
1145 case TT_DFAULT:
1146 {
Richard Henderson59f71822011-10-25 10:34:07 -07001147 info.si_signo = TARGET_SIGSEGV;
bellard61ff6f52005-02-15 22:54:53 +00001148 info.si_errno = 0;
1149 /* XXX: check env->error_code */
1150 info.si_code = TARGET_SEGV_MAPERR;
1151 info._sifields._sigfault._addr = env->mmuregs[4];
pbrook624f7972008-05-31 16:11:38 +00001152 queue_signal(env, info.si_signo, &info);
bellard61ff6f52005-02-15 22:54:53 +00001153 }
1154 break;
bellard34751872005-07-02 14:31:34 +00001155#else
bellard5ef54112006-07-18 21:14:09 +00001156 case TT_SPILL: /* window overflow */
1157 save_window(env);
1158 break;
1159 case TT_FILL: /* window underflow */
1160 restore_window(env);
1161 break;
blueswir17f84a722007-07-07 20:46:41 +00001162 case TT_TFAULT:
1163 case TT_DFAULT:
1164 {
Richard Henderson59f71822011-10-25 10:34:07 -07001165 info.si_signo = TARGET_SIGSEGV;
blueswir17f84a722007-07-07 20:46:41 +00001166 info.si_errno = 0;
1167 /* XXX: check env->error_code */
1168 info.si_code = TARGET_SEGV_MAPERR;
1169 if (trapnr == TT_DFAULT)
1170 info._sifields._sigfault._addr = env->dmmuregs[4];
1171 else
Igor Kovalenko8194f352009-08-03 23:15:02 +04001172 info._sifields._sigfault._addr = cpu_tsptr(env)->tpc;
pbrook624f7972008-05-31 16:11:38 +00001173 queue_signal(env, info.si_signo, &info);
blueswir17f84a722007-07-07 20:46:41 +00001174 }
1175 break;
bellard27524dc2007-11-11 19:32:52 +00001176#ifndef TARGET_ABI32
blueswir15bfb56b2007-10-05 17:01:51 +00001177 case 0x16e:
1178 flush_windows(env);
1179 sparc64_get_context(env);
1180 break;
1181 case 0x16f:
1182 flush_windows(env);
1183 sparc64_set_context(env);
1184 break;
bellard34751872005-07-02 14:31:34 +00001185#endif
bellard27524dc2007-11-11 19:32:52 +00001186#endif
bellard48dc41e2006-06-21 18:15:50 +00001187 case EXCP_INTERRUPT:
1188 /* just indicate that signals should be handled asap */
1189 break;
Richard Henderson75f22e42011-10-25 10:34:06 -07001190 case TT_ILL_INSN:
1191 {
1192 info.si_signo = TARGET_SIGILL;
1193 info.si_errno = 0;
1194 info.si_code = TARGET_ILL_ILLOPC;
1195 info._sifields._sigfault._addr = env->pc;
1196 queue_signal(env, info.si_signo, &info);
1197 }
1198 break;
bellard1fddef42005-04-17 19:16:13 +00001199 case EXCP_DEBUG:
1200 {
1201 int sig;
1202
Andreas Färberdb6b81d2013-06-27 19:49:31 +02001203 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
bellard1fddef42005-04-17 19:16:13 +00001204 if (sig)
1205 {
1206 info.si_signo = sig;
1207 info.si_errno = 0;
1208 info.si_code = TARGET_TRAP_BRKPT;
pbrook624f7972008-05-31 16:11:38 +00001209 queue_signal(env, info.si_signo, &info);
bellard1fddef42005-04-17 19:16:13 +00001210 }
1211 }
1212 break;
bellard060366c2004-01-04 15:50:01 +00001213 default:
1214 printf ("Unhandled trap: 0x%x\n", trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +02001215 cpu_dump_state(cs, stderr, fprintf, 0);
bellard060366c2004-01-04 15:50:01 +00001216 exit (1);
1217 }
1218 process_pending_signals (env);
1219 }
bellard93ac68b2003-09-30 20:57:29 +00001220}
1221
1222#endif
1223
bellard67867302003-11-23 17:05:30 +00001224#ifdef TARGET_PPC
Andreas Färber05390242012-02-25 03:37:53 +01001225static inline uint64_t cpu_ppc_get_tb(CPUPPCState *env)
bellard9fddaa02004-05-21 12:59:32 +00001226{
1227 /* TO FIX */
1228 return 0;
1229}
ths3b46e622007-09-17 08:09:54 +00001230
Andreas Färber05390242012-02-25 03:37:53 +01001231uint64_t cpu_ppc_load_tbl(CPUPPCState *env)
bellard9fddaa02004-05-21 12:59:32 +00001232{
Alexander Grafe3ea6522009-12-21 12:24:17 +01001233 return cpu_ppc_get_tb(env);
bellard9fddaa02004-05-21 12:59:32 +00001234}
ths3b46e622007-09-17 08:09:54 +00001235
Andreas Färber05390242012-02-25 03:37:53 +01001236uint32_t cpu_ppc_load_tbu(CPUPPCState *env)
bellard9fddaa02004-05-21 12:59:32 +00001237{
1238 return cpu_ppc_get_tb(env) >> 32;
1239}
ths3b46e622007-09-17 08:09:54 +00001240
Andreas Färber05390242012-02-25 03:37:53 +01001241uint64_t cpu_ppc_load_atbl(CPUPPCState *env)
bellard9fddaa02004-05-21 12:59:32 +00001242{
Aurelien Jarnob711de92009-12-21 13:52:08 +01001243 return cpu_ppc_get_tb(env);
bellard9fddaa02004-05-21 12:59:32 +00001244}
1245
Andreas Färber05390242012-02-25 03:37:53 +01001246uint32_t cpu_ppc_load_atbu(CPUPPCState *env)
bellard9fddaa02004-05-21 12:59:32 +00001247{
j_mayera062e362007-09-30 00:38:38 +00001248 return cpu_ppc_get_tb(env) >> 32;
bellard9fddaa02004-05-21 12:59:32 +00001249}
ths5fafdf22007-09-16 21:08:06 +00001250
Andreas Färber05390242012-02-25 03:37:53 +01001251uint32_t cpu_ppc601_load_rtcu(CPUPPCState *env)
j_mayer76a66252007-03-07 08:32:30 +00001252__attribute__ (( alias ("cpu_ppc_load_tbu") ));
1253
Andreas Färber05390242012-02-25 03:37:53 +01001254uint32_t cpu_ppc601_load_rtcl(CPUPPCState *env)
bellard9fddaa02004-05-21 12:59:32 +00001255{
j_mayer76a66252007-03-07 08:32:30 +00001256 return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
bellard9fddaa02004-05-21 12:59:32 +00001257}
j_mayer76a66252007-03-07 08:32:30 +00001258
j_mayera750fc02007-09-26 23:54:22 +00001259/* XXX: to be fixed */
Alexander Graf73b01962009-12-21 14:02:39 +01001260int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp)
j_mayera750fc02007-09-26 23:54:22 +00001261{
1262 return -1;
1263}
1264
Alexander Graf73b01962009-12-21 14:02:39 +01001265int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val)
j_mayera750fc02007-09-26 23:54:22 +00001266{
1267 return -1;
1268}
1269
Blue Swirl001faf32009-05-13 17:53:17 +00001270#define EXCP_DUMP(env, fmt, ...) \
1271do { \
Andreas Färbera0762852013-06-16 07:28:50 +02001272 CPUState *cs = ENV_GET_CPU(env); \
Blue Swirl001faf32009-05-13 17:53:17 +00001273 fprintf(stderr, fmt , ## __VA_ARGS__); \
Andreas Färbera0762852013-06-16 07:28:50 +02001274 cpu_dump_state(cs, stderr, fprintf, 0); \
Blue Swirl001faf32009-05-13 17:53:17 +00001275 qemu_log(fmt, ## __VA_ARGS__); \
Blue Swirleeacee42012-06-03 16:35:32 +00001276 if (qemu_log_enabled()) { \
Andreas Färbera0762852013-06-16 07:28:50 +02001277 log_cpu_state(cs, 0); \
Blue Swirleeacee42012-06-03 16:35:32 +00001278 } \
j_mayere1833e12007-09-29 13:06:16 +00001279} while (0)
1280
Nathan Froyd56f066b2009-08-03 08:43:27 -07001281static int do_store_exclusive(CPUPPCState *env)
1282{
1283 target_ulong addr;
1284 target_ulong page_addr;
1285 target_ulong val;
1286 int flags;
1287 int segv = 0;
1288
1289 addr = env->reserve_ea;
1290 page_addr = addr & TARGET_PAGE_MASK;
1291 start_exclusive();
1292 mmap_lock();
1293 flags = page_get_flags(page_addr);
1294 if ((flags & PAGE_READ) == 0) {
1295 segv = 1;
1296 } else {
1297 int reg = env->reserve_info & 0x1f;
1298 int size = (env->reserve_info >> 5) & 0xf;
1299 int stored = 0;
1300
1301 if (addr == env->reserve_addr) {
1302 switch (size) {
1303 case 1: segv = get_user_u8(val, addr); break;
1304 case 2: segv = get_user_u16(val, addr); break;
1305 case 4: segv = get_user_u32(val, addr); break;
1306#if defined(TARGET_PPC64)
1307 case 8: segv = get_user_u64(val, addr); break;
1308#endif
1309 default: abort();
1310 }
1311 if (!segv && val == env->reserve_val) {
1312 val = env->gpr[reg];
1313 switch (size) {
1314 case 1: segv = put_user_u8(val, addr); break;
1315 case 2: segv = put_user_u16(val, addr); break;
1316 case 4: segv = put_user_u32(val, addr); break;
1317#if defined(TARGET_PPC64)
1318 case 8: segv = put_user_u64(val, addr); break;
1319#endif
1320 default: abort();
1321 }
1322 if (!segv) {
1323 stored = 1;
1324 }
1325 }
1326 }
1327 env->crf[0] = (stored << 1) | xer_so;
1328 env->reserve_addr = (target_ulong)-1;
1329 }
1330 if (!segv) {
1331 env->nip += 4;
1332 }
1333 mmap_unlock();
1334 end_exclusive();
1335 return segv;
1336}
1337
bellard67867302003-11-23 17:05:30 +00001338void cpu_loop(CPUPPCState *env)
1339{
Andreas Färber0315c312012-12-17 07:34:52 +01001340 CPUState *cs = CPU(ppc_env_get_cpu(env));
Anthony Liguoric227f092009-10-01 16:12:16 -05001341 target_siginfo_t info;
bellard61190b12004-01-04 23:54:31 +00001342 int trapnr;
Richard Henderson9e0e2f92011-10-26 09:59:18 -07001343 target_ulong ret;
ths3b46e622007-09-17 08:09:54 +00001344
bellard67867302003-11-23 17:05:30 +00001345 for(;;) {
Andreas Färber0315c312012-12-17 07:34:52 +01001346 cpu_exec_start(cs);
bellard67867302003-11-23 17:05:30 +00001347 trapnr = cpu_ppc_exec(env);
Andreas Färber0315c312012-12-17 07:34:52 +01001348 cpu_exec_end(cs);
bellard67867302003-11-23 17:05:30 +00001349 switch(trapnr) {
j_mayere1833e12007-09-29 13:06:16 +00001350 case POWERPC_EXCP_NONE:
1351 /* Just go on */
bellard67867302003-11-23 17:05:30 +00001352 break;
j_mayere1833e12007-09-29 13:06:16 +00001353 case POWERPC_EXCP_CRITICAL: /* Critical input */
1354 cpu_abort(env, "Critical interrupt while in user mode. "
1355 "Aborting\n");
1356 break;
1357 case POWERPC_EXCP_MCHECK: /* Machine check exception */
1358 cpu_abort(env, "Machine check exception while in user mode. "
1359 "Aborting\n");
1360 break;
1361 case POWERPC_EXCP_DSI: /* Data storage exception */
Blue Swirl90e189e2009-08-16 11:13:18 +00001362 EXCP_DUMP(env, "Invalid data memory access: 0x" TARGET_FMT_lx "\n",
j_mayere1833e12007-09-29 13:06:16 +00001363 env->spr[SPR_DAR]);
1364 /* XXX: check this. Seems bugged */
1365 switch (env->error_code & 0xFF000000) {
1366 case 0x40000000:
1367 info.si_signo = TARGET_SIGSEGV;
1368 info.si_errno = 0;
1369 info.si_code = TARGET_SEGV_MAPERR;
1370 break;
1371 case 0x04000000:
1372 info.si_signo = TARGET_SIGILL;
1373 info.si_errno = 0;
1374 info.si_code = TARGET_ILL_ILLADR;
1375 break;
1376 case 0x08000000:
1377 info.si_signo = TARGET_SIGSEGV;
1378 info.si_errno = 0;
1379 info.si_code = TARGET_SEGV_ACCERR;
1380 break;
1381 default:
1382 /* Let's send a regular segfault... */
1383 EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
1384 env->error_code);
1385 info.si_signo = TARGET_SIGSEGV;
1386 info.si_errno = 0;
1387 info.si_code = TARGET_SEGV_MAPERR;
1388 break;
1389 }
1390 info._sifields._sigfault._addr = env->nip;
pbrook624f7972008-05-31 16:11:38 +00001391 queue_signal(env, info.si_signo, &info);
j_mayere1833e12007-09-29 13:06:16 +00001392 break;
1393 case POWERPC_EXCP_ISI: /* Instruction storage exception */
Blue Swirl90e189e2009-08-16 11:13:18 +00001394 EXCP_DUMP(env, "Invalid instruction fetch: 0x\n" TARGET_FMT_lx
1395 "\n", env->spr[SPR_SRR0]);
j_mayere1833e12007-09-29 13:06:16 +00001396 /* XXX: check this */
1397 switch (env->error_code & 0xFF000000) {
1398 case 0x40000000:
1399 info.si_signo = TARGET_SIGSEGV;
1400 info.si_errno = 0;
1401 info.si_code = TARGET_SEGV_MAPERR;
1402 break;
1403 case 0x10000000:
1404 case 0x08000000:
1405 info.si_signo = TARGET_SIGSEGV;
1406 info.si_errno = 0;
1407 info.si_code = TARGET_SEGV_ACCERR;
1408 break;
1409 default:
1410 /* Let's send a regular segfault... */
1411 EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
1412 env->error_code);
1413 info.si_signo = TARGET_SIGSEGV;
1414 info.si_errno = 0;
1415 info.si_code = TARGET_SEGV_MAPERR;
1416 break;
1417 }
1418 info._sifields._sigfault._addr = env->nip - 4;
pbrook624f7972008-05-31 16:11:38 +00001419 queue_signal(env, info.si_signo, &info);
j_mayere1833e12007-09-29 13:06:16 +00001420 break;
1421 case POWERPC_EXCP_EXTERNAL: /* External input */
1422 cpu_abort(env, "External interrupt while in user mode. "
1423 "Aborting\n");
1424 break;
1425 case POWERPC_EXCP_ALIGN: /* Alignment exception */
1426 EXCP_DUMP(env, "Unaligned memory access\n");
1427 /* XXX: check this */
1428 info.si_signo = TARGET_SIGBUS;
1429 info.si_errno = 0;
1430 info.si_code = TARGET_BUS_ADRALN;
1431 info._sifields._sigfault._addr = env->nip - 4;
pbrook624f7972008-05-31 16:11:38 +00001432 queue_signal(env, info.si_signo, &info);
j_mayere1833e12007-09-29 13:06:16 +00001433 break;
1434 case POWERPC_EXCP_PROGRAM: /* Program exception */
1435 /* XXX: check this */
1436 switch (env->error_code & ~0xF) {
1437 case POWERPC_EXCP_FP:
1438 EXCP_DUMP(env, "Floating point program exception\n");
j_mayere1833e12007-09-29 13:06:16 +00001439 info.si_signo = TARGET_SIGFPE;
1440 info.si_errno = 0;
1441 switch (env->error_code & 0xF) {
1442 case POWERPC_EXCP_FP_OX:
1443 info.si_code = TARGET_FPE_FLTOVF;
1444 break;
1445 case POWERPC_EXCP_FP_UX:
1446 info.si_code = TARGET_FPE_FLTUND;
1447 break;
1448 case POWERPC_EXCP_FP_ZX:
1449 case POWERPC_EXCP_FP_VXZDZ:
1450 info.si_code = TARGET_FPE_FLTDIV;
1451 break;
1452 case POWERPC_EXCP_FP_XX:
1453 info.si_code = TARGET_FPE_FLTRES;
1454 break;
1455 case POWERPC_EXCP_FP_VXSOFT:
1456 info.si_code = TARGET_FPE_FLTINV;
1457 break;
j_mayer7c580442007-10-27 17:54:30 +00001458 case POWERPC_EXCP_FP_VXSNAN:
j_mayere1833e12007-09-29 13:06:16 +00001459 case POWERPC_EXCP_FP_VXISI:
1460 case POWERPC_EXCP_FP_VXIDI:
1461 case POWERPC_EXCP_FP_VXIMZ:
1462 case POWERPC_EXCP_FP_VXVC:
1463 case POWERPC_EXCP_FP_VXSQRT:
1464 case POWERPC_EXCP_FP_VXCVI:
1465 info.si_code = TARGET_FPE_FLTSUB;
1466 break;
1467 default:
1468 EXCP_DUMP(env, "Unknown floating point exception (%02x)\n",
1469 env->error_code);
1470 break;
1471 }
1472 break;
1473 case POWERPC_EXCP_INVAL:
1474 EXCP_DUMP(env, "Invalid instruction\n");
1475 info.si_signo = TARGET_SIGILL;
1476 info.si_errno = 0;
1477 switch (env->error_code & 0xF) {
1478 case POWERPC_EXCP_INVAL_INVAL:
1479 info.si_code = TARGET_ILL_ILLOPC;
1480 break;
1481 case POWERPC_EXCP_INVAL_LSWX:
1482 info.si_code = TARGET_ILL_ILLOPN;
1483 break;
1484 case POWERPC_EXCP_INVAL_SPR:
1485 info.si_code = TARGET_ILL_PRVREG;
1486 break;
1487 case POWERPC_EXCP_INVAL_FP:
1488 info.si_code = TARGET_ILL_COPROC;
1489 break;
1490 default:
1491 EXCP_DUMP(env, "Unknown invalid operation (%02x)\n",
1492 env->error_code & 0xF);
1493 info.si_code = TARGET_ILL_ILLADR;
1494 break;
1495 }
1496 break;
1497 case POWERPC_EXCP_PRIV:
1498 EXCP_DUMP(env, "Privilege violation\n");
1499 info.si_signo = TARGET_SIGILL;
1500 info.si_errno = 0;
1501 switch (env->error_code & 0xF) {
1502 case POWERPC_EXCP_PRIV_OPC:
1503 info.si_code = TARGET_ILL_PRVOPC;
1504 break;
1505 case POWERPC_EXCP_PRIV_REG:
1506 info.si_code = TARGET_ILL_PRVREG;
1507 break;
1508 default:
1509 EXCP_DUMP(env, "Unknown privilege violation (%02x)\n",
1510 env->error_code & 0xF);
1511 info.si_code = TARGET_ILL_PRVOPC;
1512 break;
1513 }
1514 break;
1515 case POWERPC_EXCP_TRAP:
1516 cpu_abort(env, "Tried to call a TRAP\n");
1517 break;
1518 default:
1519 /* Should not happen ! */
1520 cpu_abort(env, "Unknown program exception (%02x)\n",
1521 env->error_code);
1522 break;
1523 }
1524 info._sifields._sigfault._addr = env->nip - 4;
pbrook624f7972008-05-31 16:11:38 +00001525 queue_signal(env, info.si_signo, &info);
j_mayere1833e12007-09-29 13:06:16 +00001526 break;
1527 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
1528 EXCP_DUMP(env, "No floating point allowed\n");
1529 info.si_signo = TARGET_SIGILL;
1530 info.si_errno = 0;
1531 info.si_code = TARGET_ILL_COPROC;
1532 info._sifields._sigfault._addr = env->nip - 4;
pbrook624f7972008-05-31 16:11:38 +00001533 queue_signal(env, info.si_signo, &info);
j_mayere1833e12007-09-29 13:06:16 +00001534 break;
1535 case POWERPC_EXCP_SYSCALL: /* System call exception */
1536 cpu_abort(env, "Syscall exception while in user mode. "
1537 "Aborting\n");
1538 break;
1539 case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
1540 EXCP_DUMP(env, "No APU instruction allowed\n");
1541 info.si_signo = TARGET_SIGILL;
1542 info.si_errno = 0;
1543 info.si_code = TARGET_ILL_COPROC;
1544 info._sifields._sigfault._addr = env->nip - 4;
pbrook624f7972008-05-31 16:11:38 +00001545 queue_signal(env, info.si_signo, &info);
j_mayere1833e12007-09-29 13:06:16 +00001546 break;
1547 case POWERPC_EXCP_DECR: /* Decrementer exception */
1548 cpu_abort(env, "Decrementer interrupt while in user mode. "
1549 "Aborting\n");
1550 break;
1551 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
1552 cpu_abort(env, "Fix interval timer interrupt while in user mode. "
1553 "Aborting\n");
1554 break;
1555 case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
1556 cpu_abort(env, "Watchdog timer interrupt while in user mode. "
1557 "Aborting\n");
1558 break;
1559 case POWERPC_EXCP_DTLB: /* Data TLB error */
1560 cpu_abort(env, "Data TLB exception while in user mode. "
1561 "Aborting\n");
1562 break;
1563 case POWERPC_EXCP_ITLB: /* Instruction TLB error */
1564 cpu_abort(env, "Instruction TLB exception while in user mode. "
1565 "Aborting\n");
1566 break;
j_mayere1833e12007-09-29 13:06:16 +00001567 case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */
1568 EXCP_DUMP(env, "No SPE/floating-point instruction allowed\n");
1569 info.si_signo = TARGET_SIGILL;
1570 info.si_errno = 0;
1571 info.si_code = TARGET_ILL_COPROC;
1572 info._sifields._sigfault._addr = env->nip - 4;
pbrook624f7972008-05-31 16:11:38 +00001573 queue_signal(env, info.si_signo, &info);
j_mayere1833e12007-09-29 13:06:16 +00001574 break;
1575 case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */
1576 cpu_abort(env, "Embedded floating-point data IRQ not handled\n");
1577 break;
1578 case POWERPC_EXCP_EFPRI: /* Embedded floating-point round IRQ */
1579 cpu_abort(env, "Embedded floating-point round IRQ not handled\n");
1580 break;
1581 case POWERPC_EXCP_EPERFM: /* Embedded performance monitor IRQ */
1582 cpu_abort(env, "Performance monitor exception not handled\n");
1583 break;
1584 case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
1585 cpu_abort(env, "Doorbell interrupt while in user mode. "
1586 "Aborting\n");
1587 break;
1588 case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
1589 cpu_abort(env, "Doorbell critical interrupt while in user mode. "
1590 "Aborting\n");
1591 break;
1592 case POWERPC_EXCP_RESET: /* System reset exception */
1593 cpu_abort(env, "Reset interrupt while in user mode. "
1594 "Aborting\n");
1595 break;
j_mayere1833e12007-09-29 13:06:16 +00001596 case POWERPC_EXCP_DSEG: /* Data segment exception */
1597 cpu_abort(env, "Data segment exception while in user mode. "
1598 "Aborting\n");
1599 break;
1600 case POWERPC_EXCP_ISEG: /* Instruction segment exception */
1601 cpu_abort(env, "Instruction segment exception "
1602 "while in user mode. Aborting\n");
1603 break;
j_mayere85e7c62007-10-18 19:59:49 +00001604 /* PowerPC 64 with hypervisor mode support */
j_mayere1833e12007-09-29 13:06:16 +00001605 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
1606 cpu_abort(env, "Hypervisor decrementer interrupt "
1607 "while in user mode. Aborting\n");
1608 break;
j_mayere1833e12007-09-29 13:06:16 +00001609 case POWERPC_EXCP_TRACE: /* Trace exception */
1610 /* Nothing to do:
1611 * we use this exception to emulate step-by-step execution mode.
1612 */
1613 break;
j_mayere85e7c62007-10-18 19:59:49 +00001614 /* PowerPC 64 with hypervisor mode support */
j_mayere1833e12007-09-29 13:06:16 +00001615 case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
1616 cpu_abort(env, "Hypervisor data storage exception "
1617 "while in user mode. Aborting\n");
1618 break;
1619 case POWERPC_EXCP_HISI: /* Hypervisor instruction storage excp */
1620 cpu_abort(env, "Hypervisor instruction storage exception "
1621 "while in user mode. Aborting\n");
1622 break;
1623 case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
1624 cpu_abort(env, "Hypervisor data segment exception "
1625 "while in user mode. Aborting\n");
1626 break;
1627 case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment excp */
1628 cpu_abort(env, "Hypervisor instruction segment exception "
1629 "while in user mode. Aborting\n");
1630 break;
j_mayere1833e12007-09-29 13:06:16 +00001631 case POWERPC_EXCP_VPU: /* Vector unavailable exception */
1632 EXCP_DUMP(env, "No Altivec instructions allowed\n");
1633 info.si_signo = TARGET_SIGILL;
1634 info.si_errno = 0;
1635 info.si_code = TARGET_ILL_COPROC;
1636 info._sifields._sigfault._addr = env->nip - 4;
pbrook624f7972008-05-31 16:11:38 +00001637 queue_signal(env, info.si_signo, &info);
j_mayere1833e12007-09-29 13:06:16 +00001638 break;
1639 case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */
Dong Xu Wangb4916d72011-11-22 18:06:17 +08001640 cpu_abort(env, "Programmable interval timer interrupt "
j_mayere1833e12007-09-29 13:06:16 +00001641 "while in user mode. Aborting\n");
1642 break;
1643 case POWERPC_EXCP_IO: /* IO error exception */
1644 cpu_abort(env, "IO error exception while in user mode. "
1645 "Aborting\n");
1646 break;
1647 case POWERPC_EXCP_RUNM: /* Run mode exception */
1648 cpu_abort(env, "Run mode exception while in user mode. "
1649 "Aborting\n");
1650 break;
1651 case POWERPC_EXCP_EMUL: /* Emulation trap exception */
1652 cpu_abort(env, "Emulation trap exception not handled\n");
1653 break;
1654 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
1655 cpu_abort(env, "Instruction fetch TLB exception "
1656 "while in user-mode. Aborting");
1657 break;
1658 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
1659 cpu_abort(env, "Data load TLB exception while in user-mode. "
1660 "Aborting");
1661 break;
1662 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
1663 cpu_abort(env, "Data store TLB exception while in user-mode. "
1664 "Aborting");
1665 break;
1666 case POWERPC_EXCP_FPA: /* Floating-point assist exception */
1667 cpu_abort(env, "Floating-point assist exception not handled\n");
1668 break;
1669 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
1670 cpu_abort(env, "Instruction address breakpoint exception "
1671 "not handled\n");
1672 break;
1673 case POWERPC_EXCP_SMI: /* System management interrupt */
1674 cpu_abort(env, "System management interrupt while in user mode. "
1675 "Aborting\n");
1676 break;
1677 case POWERPC_EXCP_THERM: /* Thermal interrupt */
1678 cpu_abort(env, "Thermal interrupt interrupt while in user mode. "
1679 "Aborting\n");
1680 break;
1681 case POWERPC_EXCP_PERFM: /* Embedded performance monitor IRQ */
1682 cpu_abort(env, "Performance monitor exception not handled\n");
1683 break;
1684 case POWERPC_EXCP_VPUA: /* Vector assist exception */
1685 cpu_abort(env, "Vector assist exception not handled\n");
1686 break;
1687 case POWERPC_EXCP_SOFTP: /* Soft patch exception */
1688 cpu_abort(env, "Soft patch exception not handled\n");
1689 break;
1690 case POWERPC_EXCP_MAINT: /* Maintenance exception */
1691 cpu_abort(env, "Maintenance exception while in user mode. "
1692 "Aborting\n");
1693 break;
1694 case POWERPC_EXCP_STOP: /* stop translation */
1695 /* We did invalidate the instruction cache. Go on */
1696 break;
1697 case POWERPC_EXCP_BRANCH: /* branch instruction: */
1698 /* We just stopped because of a branch. Go on */
1699 break;
1700 case POWERPC_EXCP_SYSCALL_USER:
1701 /* system call in user-mode emulation */
bellard67867302003-11-23 17:05:30 +00001702 /* WARNING:
1703 * PPC ABI uses overflow flag in cr0 to signal an error
1704 * in syscalls.
1705 */
1706 env->crf[0] &= ~0x1;
1707 ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
1708 env->gpr[5], env->gpr[6], env->gpr[7],
Peter Maydell5945cfc2011-06-16 17:37:13 +01001709 env->gpr[8], 0, 0);
Richard Henderson9e0e2f92011-10-26 09:59:18 -07001710 if (ret == (target_ulong)(-TARGET_QEMU_ESIGRETURN)) {
Nathan Froydbcd49332009-05-12 19:13:18 -07001711 /* Returning from a successful sigreturn syscall.
1712 Avoid corrupting register state. */
1713 break;
1714 }
Richard Henderson9e0e2f92011-10-26 09:59:18 -07001715 if (ret > (target_ulong)(-515)) {
bellard67867302003-11-23 17:05:30 +00001716 env->crf[0] |= 0x1;
1717 ret = -ret;
1718 }
1719 env->gpr[3] = ret;
1720 break;
Nathan Froyd56f066b2009-08-03 08:43:27 -07001721 case POWERPC_EXCP_STCX:
1722 if (do_store_exclusive(env)) {
1723 info.si_signo = TARGET_SIGSEGV;
1724 info.si_errno = 0;
1725 info.si_code = TARGET_SEGV_MAPERR;
1726 info._sifields._sigfault._addr = env->nip;
1727 queue_signal(env, info.si_signo, &info);
1728 }
1729 break;
aurel3271f75752008-11-14 17:05:54 +00001730 case EXCP_DEBUG:
1731 {
1732 int sig;
1733
Andreas Färberdb6b81d2013-06-27 19:49:31 +02001734 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
aurel3271f75752008-11-14 17:05:54 +00001735 if (sig) {
1736 info.si_signo = sig;
1737 info.si_errno = 0;
1738 info.si_code = TARGET_TRAP_BRKPT;
1739 queue_signal(env, info.si_signo, &info);
1740 }
1741 }
1742 break;
j_mayer56ba31f2007-09-30 15:15:18 +00001743 case EXCP_INTERRUPT:
1744 /* just indicate that signals should be handled asap */
1745 break;
bellard67867302003-11-23 17:05:30 +00001746 default:
j_mayere1833e12007-09-29 13:06:16 +00001747 cpu_abort(env, "Unknown exception 0x%d. Aborting\n", trapnr);
1748 break;
bellard67867302003-11-23 17:05:30 +00001749 }
1750 process_pending_signals(env);
1751 }
1752}
1753#endif
1754
bellard048f6b42005-11-26 18:47:20 +00001755#ifdef TARGET_MIPS
1756
Richard Hendersonff4f7382013-02-10 10:30:45 -08001757# ifdef TARGET_ABI_MIPSO32
1758# define MIPS_SYS(name, args) args,
bellard048f6b42005-11-26 18:47:20 +00001759static const uint8_t mips_syscall_args[] = {
An-Cheng Huang29fb0f22011-08-09 12:31:41 -07001760 MIPS_SYS(sys_syscall , 8) /* 4000 */
bellard048f6b42005-11-26 18:47:20 +00001761 MIPS_SYS(sys_exit , 1)
1762 MIPS_SYS(sys_fork , 0)
1763 MIPS_SYS(sys_read , 3)
1764 MIPS_SYS(sys_write , 3)
1765 MIPS_SYS(sys_open , 3) /* 4005 */
1766 MIPS_SYS(sys_close , 1)
1767 MIPS_SYS(sys_waitpid , 3)
1768 MIPS_SYS(sys_creat , 2)
1769 MIPS_SYS(sys_link , 2)
1770 MIPS_SYS(sys_unlink , 1) /* 4010 */
1771 MIPS_SYS(sys_execve , 0)
1772 MIPS_SYS(sys_chdir , 1)
1773 MIPS_SYS(sys_time , 1)
1774 MIPS_SYS(sys_mknod , 3)
1775 MIPS_SYS(sys_chmod , 2) /* 4015 */
1776 MIPS_SYS(sys_lchown , 3)
1777 MIPS_SYS(sys_ni_syscall , 0)
1778 MIPS_SYS(sys_ni_syscall , 0) /* was sys_stat */
1779 MIPS_SYS(sys_lseek , 3)
1780 MIPS_SYS(sys_getpid , 0) /* 4020 */
1781 MIPS_SYS(sys_mount , 5)
1782 MIPS_SYS(sys_oldumount , 1)
1783 MIPS_SYS(sys_setuid , 1)
1784 MIPS_SYS(sys_getuid , 0)
1785 MIPS_SYS(sys_stime , 1) /* 4025 */
1786 MIPS_SYS(sys_ptrace , 4)
1787 MIPS_SYS(sys_alarm , 1)
1788 MIPS_SYS(sys_ni_syscall , 0) /* was sys_fstat */
1789 MIPS_SYS(sys_pause , 0)
1790 MIPS_SYS(sys_utime , 2) /* 4030 */
1791 MIPS_SYS(sys_ni_syscall , 0)
1792 MIPS_SYS(sys_ni_syscall , 0)
1793 MIPS_SYS(sys_access , 2)
1794 MIPS_SYS(sys_nice , 1)
1795 MIPS_SYS(sys_ni_syscall , 0) /* 4035 */
1796 MIPS_SYS(sys_sync , 0)
1797 MIPS_SYS(sys_kill , 2)
1798 MIPS_SYS(sys_rename , 2)
1799 MIPS_SYS(sys_mkdir , 2)
1800 MIPS_SYS(sys_rmdir , 1) /* 4040 */
1801 MIPS_SYS(sys_dup , 1)
1802 MIPS_SYS(sys_pipe , 0)
1803 MIPS_SYS(sys_times , 1)
1804 MIPS_SYS(sys_ni_syscall , 0)
1805 MIPS_SYS(sys_brk , 1) /* 4045 */
1806 MIPS_SYS(sys_setgid , 1)
1807 MIPS_SYS(sys_getgid , 0)
1808 MIPS_SYS(sys_ni_syscall , 0) /* was signal(2) */
1809 MIPS_SYS(sys_geteuid , 0)
1810 MIPS_SYS(sys_getegid , 0) /* 4050 */
1811 MIPS_SYS(sys_acct , 0)
1812 MIPS_SYS(sys_umount , 2)
1813 MIPS_SYS(sys_ni_syscall , 0)
1814 MIPS_SYS(sys_ioctl , 3)
1815 MIPS_SYS(sys_fcntl , 3) /* 4055 */
1816 MIPS_SYS(sys_ni_syscall , 2)
1817 MIPS_SYS(sys_setpgid , 2)
1818 MIPS_SYS(sys_ni_syscall , 0)
1819 MIPS_SYS(sys_olduname , 1)
1820 MIPS_SYS(sys_umask , 1) /* 4060 */
1821 MIPS_SYS(sys_chroot , 1)
1822 MIPS_SYS(sys_ustat , 2)
1823 MIPS_SYS(sys_dup2 , 2)
1824 MIPS_SYS(sys_getppid , 0)
1825 MIPS_SYS(sys_getpgrp , 0) /* 4065 */
1826 MIPS_SYS(sys_setsid , 0)
1827 MIPS_SYS(sys_sigaction , 3)
1828 MIPS_SYS(sys_sgetmask , 0)
1829 MIPS_SYS(sys_ssetmask , 1)
1830 MIPS_SYS(sys_setreuid , 2) /* 4070 */
1831 MIPS_SYS(sys_setregid , 2)
1832 MIPS_SYS(sys_sigsuspend , 0)
1833 MIPS_SYS(sys_sigpending , 1)
1834 MIPS_SYS(sys_sethostname , 2)
1835 MIPS_SYS(sys_setrlimit , 2) /* 4075 */
1836 MIPS_SYS(sys_getrlimit , 2)
1837 MIPS_SYS(sys_getrusage , 2)
1838 MIPS_SYS(sys_gettimeofday, 2)
1839 MIPS_SYS(sys_settimeofday, 2)
1840 MIPS_SYS(sys_getgroups , 2) /* 4080 */
1841 MIPS_SYS(sys_setgroups , 2)
1842 MIPS_SYS(sys_ni_syscall , 0) /* old_select */
1843 MIPS_SYS(sys_symlink , 2)
1844 MIPS_SYS(sys_ni_syscall , 0) /* was sys_lstat */
1845 MIPS_SYS(sys_readlink , 3) /* 4085 */
1846 MIPS_SYS(sys_uselib , 1)
1847 MIPS_SYS(sys_swapon , 2)
1848 MIPS_SYS(sys_reboot , 3)
1849 MIPS_SYS(old_readdir , 3)
1850 MIPS_SYS(old_mmap , 6) /* 4090 */
1851 MIPS_SYS(sys_munmap , 2)
1852 MIPS_SYS(sys_truncate , 2)
1853 MIPS_SYS(sys_ftruncate , 2)
1854 MIPS_SYS(sys_fchmod , 2)
1855 MIPS_SYS(sys_fchown , 3) /* 4095 */
1856 MIPS_SYS(sys_getpriority , 2)
1857 MIPS_SYS(sys_setpriority , 3)
1858 MIPS_SYS(sys_ni_syscall , 0)
1859 MIPS_SYS(sys_statfs , 2)
1860 MIPS_SYS(sys_fstatfs , 2) /* 4100 */
1861 MIPS_SYS(sys_ni_syscall , 0) /* was ioperm(2) */
1862 MIPS_SYS(sys_socketcall , 2)
1863 MIPS_SYS(sys_syslog , 3)
1864 MIPS_SYS(sys_setitimer , 3)
1865 MIPS_SYS(sys_getitimer , 2) /* 4105 */
1866 MIPS_SYS(sys_newstat , 2)
1867 MIPS_SYS(sys_newlstat , 2)
1868 MIPS_SYS(sys_newfstat , 2)
1869 MIPS_SYS(sys_uname , 1)
1870 MIPS_SYS(sys_ni_syscall , 0) /* 4110 was iopl(2) */
1871 MIPS_SYS(sys_vhangup , 0)
1872 MIPS_SYS(sys_ni_syscall , 0) /* was sys_idle() */
1873 MIPS_SYS(sys_ni_syscall , 0) /* was sys_vm86 */
1874 MIPS_SYS(sys_wait4 , 4)
1875 MIPS_SYS(sys_swapoff , 1) /* 4115 */
1876 MIPS_SYS(sys_sysinfo , 1)
1877 MIPS_SYS(sys_ipc , 6)
1878 MIPS_SYS(sys_fsync , 1)
1879 MIPS_SYS(sys_sigreturn , 0)
Paul Brook18113962009-07-09 13:11:52 +01001880 MIPS_SYS(sys_clone , 6) /* 4120 */
bellard048f6b42005-11-26 18:47:20 +00001881 MIPS_SYS(sys_setdomainname, 2)
1882 MIPS_SYS(sys_newuname , 1)
1883 MIPS_SYS(sys_ni_syscall , 0) /* sys_modify_ldt */
1884 MIPS_SYS(sys_adjtimex , 1)
1885 MIPS_SYS(sys_mprotect , 3) /* 4125 */
1886 MIPS_SYS(sys_sigprocmask , 3)
1887 MIPS_SYS(sys_ni_syscall , 0) /* was create_module */
1888 MIPS_SYS(sys_init_module , 5)
1889 MIPS_SYS(sys_delete_module, 1)
1890 MIPS_SYS(sys_ni_syscall , 0) /* 4130 was get_kernel_syms */
1891 MIPS_SYS(sys_quotactl , 0)
1892 MIPS_SYS(sys_getpgid , 1)
1893 MIPS_SYS(sys_fchdir , 1)
1894 MIPS_SYS(sys_bdflush , 2)
1895 MIPS_SYS(sys_sysfs , 3) /* 4135 */
1896 MIPS_SYS(sys_personality , 1)
1897 MIPS_SYS(sys_ni_syscall , 0) /* for afs_syscall */
1898 MIPS_SYS(sys_setfsuid , 1)
1899 MIPS_SYS(sys_setfsgid , 1)
1900 MIPS_SYS(sys_llseek , 5) /* 4140 */
1901 MIPS_SYS(sys_getdents , 3)
1902 MIPS_SYS(sys_select , 5)
1903 MIPS_SYS(sys_flock , 2)
1904 MIPS_SYS(sys_msync , 3)
1905 MIPS_SYS(sys_readv , 3) /* 4145 */
1906 MIPS_SYS(sys_writev , 3)
1907 MIPS_SYS(sys_cacheflush , 3)
1908 MIPS_SYS(sys_cachectl , 3)
1909 MIPS_SYS(sys_sysmips , 4)
1910 MIPS_SYS(sys_ni_syscall , 0) /* 4150 */
1911 MIPS_SYS(sys_getsid , 1)
1912 MIPS_SYS(sys_fdatasync , 0)
1913 MIPS_SYS(sys_sysctl , 1)
1914 MIPS_SYS(sys_mlock , 2)
1915 MIPS_SYS(sys_munlock , 2) /* 4155 */
1916 MIPS_SYS(sys_mlockall , 1)
1917 MIPS_SYS(sys_munlockall , 0)
1918 MIPS_SYS(sys_sched_setparam, 2)
1919 MIPS_SYS(sys_sched_getparam, 2)
1920 MIPS_SYS(sys_sched_setscheduler, 3) /* 4160 */
1921 MIPS_SYS(sys_sched_getscheduler, 1)
1922 MIPS_SYS(sys_sched_yield , 0)
1923 MIPS_SYS(sys_sched_get_priority_max, 1)
1924 MIPS_SYS(sys_sched_get_priority_min, 1)
1925 MIPS_SYS(sys_sched_rr_get_interval, 2) /* 4165 */
1926 MIPS_SYS(sys_nanosleep, 2)
Petar Jovanovicb0932e02013-07-23 19:00:10 +02001927 MIPS_SYS(sys_mremap , 5)
bellard048f6b42005-11-26 18:47:20 +00001928 MIPS_SYS(sys_accept , 3)
1929 MIPS_SYS(sys_bind , 3)
1930 MIPS_SYS(sys_connect , 3) /* 4170 */
1931 MIPS_SYS(sys_getpeername , 3)
1932 MIPS_SYS(sys_getsockname , 3)
1933 MIPS_SYS(sys_getsockopt , 5)
1934 MIPS_SYS(sys_listen , 2)
1935 MIPS_SYS(sys_recv , 4) /* 4175 */
1936 MIPS_SYS(sys_recvfrom , 6)
1937 MIPS_SYS(sys_recvmsg , 3)
1938 MIPS_SYS(sys_send , 4)
1939 MIPS_SYS(sys_sendmsg , 3)
1940 MIPS_SYS(sys_sendto , 6) /* 4180 */
1941 MIPS_SYS(sys_setsockopt , 5)
1942 MIPS_SYS(sys_shutdown , 2)
1943 MIPS_SYS(sys_socket , 3)
1944 MIPS_SYS(sys_socketpair , 4)
1945 MIPS_SYS(sys_setresuid , 3) /* 4185 */
1946 MIPS_SYS(sys_getresuid , 3)
1947 MIPS_SYS(sys_ni_syscall , 0) /* was sys_query_module */
1948 MIPS_SYS(sys_poll , 3)
1949 MIPS_SYS(sys_nfsservctl , 3)
1950 MIPS_SYS(sys_setresgid , 3) /* 4190 */
1951 MIPS_SYS(sys_getresgid , 3)
1952 MIPS_SYS(sys_prctl , 5)
1953 MIPS_SYS(sys_rt_sigreturn, 0)
1954 MIPS_SYS(sys_rt_sigaction, 4)
1955 MIPS_SYS(sys_rt_sigprocmask, 4) /* 4195 */
1956 MIPS_SYS(sys_rt_sigpending, 2)
1957 MIPS_SYS(sys_rt_sigtimedwait, 4)
1958 MIPS_SYS(sys_rt_sigqueueinfo, 3)
1959 MIPS_SYS(sys_rt_sigsuspend, 0)
1960 MIPS_SYS(sys_pread64 , 6) /* 4200 */
1961 MIPS_SYS(sys_pwrite64 , 6)
1962 MIPS_SYS(sys_chown , 3)
1963 MIPS_SYS(sys_getcwd , 2)
1964 MIPS_SYS(sys_capget , 2)
1965 MIPS_SYS(sys_capset , 2) /* 4205 */
Wesley W. Terpstra053ebb22011-07-12 14:32:31 +03001966 MIPS_SYS(sys_sigaltstack , 2)
bellard048f6b42005-11-26 18:47:20 +00001967 MIPS_SYS(sys_sendfile , 4)
1968 MIPS_SYS(sys_ni_syscall , 0)
1969 MIPS_SYS(sys_ni_syscall , 0)
1970 MIPS_SYS(sys_mmap2 , 6) /* 4210 */
1971 MIPS_SYS(sys_truncate64 , 4)
1972 MIPS_SYS(sys_ftruncate64 , 4)
1973 MIPS_SYS(sys_stat64 , 2)
1974 MIPS_SYS(sys_lstat64 , 2)
1975 MIPS_SYS(sys_fstat64 , 2) /* 4215 */
1976 MIPS_SYS(sys_pivot_root , 2)
1977 MIPS_SYS(sys_mincore , 3)
1978 MIPS_SYS(sys_madvise , 3)
1979 MIPS_SYS(sys_getdents64 , 3)
1980 MIPS_SYS(sys_fcntl64 , 3) /* 4220 */
1981 MIPS_SYS(sys_ni_syscall , 0)
1982 MIPS_SYS(sys_gettid , 0)
1983 MIPS_SYS(sys_readahead , 5)
1984 MIPS_SYS(sys_setxattr , 5)
1985 MIPS_SYS(sys_lsetxattr , 5) /* 4225 */
1986 MIPS_SYS(sys_fsetxattr , 5)
1987 MIPS_SYS(sys_getxattr , 4)
1988 MIPS_SYS(sys_lgetxattr , 4)
1989 MIPS_SYS(sys_fgetxattr , 4)
1990 MIPS_SYS(sys_listxattr , 3) /* 4230 */
1991 MIPS_SYS(sys_llistxattr , 3)
1992 MIPS_SYS(sys_flistxattr , 3)
1993 MIPS_SYS(sys_removexattr , 2)
1994 MIPS_SYS(sys_lremovexattr, 2)
1995 MIPS_SYS(sys_fremovexattr, 2) /* 4235 */
1996 MIPS_SYS(sys_tkill , 2)
1997 MIPS_SYS(sys_sendfile64 , 5)
Petar Jovanovic43be1342013-07-15 15:17:40 +02001998 MIPS_SYS(sys_futex , 6)
bellard048f6b42005-11-26 18:47:20 +00001999 MIPS_SYS(sys_sched_setaffinity, 3)
2000 MIPS_SYS(sys_sched_getaffinity, 3) /* 4240 */
2001 MIPS_SYS(sys_io_setup , 2)
2002 MIPS_SYS(sys_io_destroy , 1)
2003 MIPS_SYS(sys_io_getevents, 5)
2004 MIPS_SYS(sys_io_submit , 3)
2005 MIPS_SYS(sys_io_cancel , 3) /* 4245 */
2006 MIPS_SYS(sys_exit_group , 1)
2007 MIPS_SYS(sys_lookup_dcookie, 3)
2008 MIPS_SYS(sys_epoll_create, 1)
2009 MIPS_SYS(sys_epoll_ctl , 4)
2010 MIPS_SYS(sys_epoll_wait , 3) /* 4250 */
2011 MIPS_SYS(sys_remap_file_pages, 5)
2012 MIPS_SYS(sys_set_tid_address, 1)
2013 MIPS_SYS(sys_restart_syscall, 0)
2014 MIPS_SYS(sys_fadvise64_64, 7)
2015 MIPS_SYS(sys_statfs64 , 3) /* 4255 */
2016 MIPS_SYS(sys_fstatfs64 , 2)
2017 MIPS_SYS(sys_timer_create, 3)
2018 MIPS_SYS(sys_timer_settime, 4)
2019 MIPS_SYS(sys_timer_gettime, 2)
2020 MIPS_SYS(sys_timer_getoverrun, 1) /* 4260 */
2021 MIPS_SYS(sys_timer_delete, 1)
2022 MIPS_SYS(sys_clock_settime, 2)
2023 MIPS_SYS(sys_clock_gettime, 2)
2024 MIPS_SYS(sys_clock_getres, 2)
2025 MIPS_SYS(sys_clock_nanosleep, 4) /* 4265 */
2026 MIPS_SYS(sys_tgkill , 3)
2027 MIPS_SYS(sys_utimes , 2)
2028 MIPS_SYS(sys_mbind , 4)
2029 MIPS_SYS(sys_ni_syscall , 0) /* sys_get_mempolicy */
2030 MIPS_SYS(sys_ni_syscall , 0) /* 4270 sys_set_mempolicy */
2031 MIPS_SYS(sys_mq_open , 4)
2032 MIPS_SYS(sys_mq_unlink , 1)
2033 MIPS_SYS(sys_mq_timedsend, 5)
2034 MIPS_SYS(sys_mq_timedreceive, 5)
2035 MIPS_SYS(sys_mq_notify , 2) /* 4275 */
2036 MIPS_SYS(sys_mq_getsetattr, 3)
2037 MIPS_SYS(sys_ni_syscall , 0) /* sys_vserver */
2038 MIPS_SYS(sys_waitid , 4)
2039 MIPS_SYS(sys_ni_syscall , 0) /* available, was setaltroot */
2040 MIPS_SYS(sys_add_key , 5)
ths388bb212007-05-13 13:58:00 +00002041 MIPS_SYS(sys_request_key, 4)
bellard048f6b42005-11-26 18:47:20 +00002042 MIPS_SYS(sys_keyctl , 5)
ths6f5b89a2007-03-02 20:48:00 +00002043 MIPS_SYS(sys_set_thread_area, 1)
ths388bb212007-05-13 13:58:00 +00002044 MIPS_SYS(sys_inotify_init, 0)
2045 MIPS_SYS(sys_inotify_add_watch, 3) /* 4285 */
2046 MIPS_SYS(sys_inotify_rm_watch, 2)
2047 MIPS_SYS(sys_migrate_pages, 4)
2048 MIPS_SYS(sys_openat, 4)
2049 MIPS_SYS(sys_mkdirat, 3)
2050 MIPS_SYS(sys_mknodat, 4) /* 4290 */
2051 MIPS_SYS(sys_fchownat, 5)
2052 MIPS_SYS(sys_futimesat, 3)
2053 MIPS_SYS(sys_fstatat64, 4)
2054 MIPS_SYS(sys_unlinkat, 3)
2055 MIPS_SYS(sys_renameat, 4) /* 4295 */
2056 MIPS_SYS(sys_linkat, 5)
2057 MIPS_SYS(sys_symlinkat, 3)
2058 MIPS_SYS(sys_readlinkat, 4)
2059 MIPS_SYS(sys_fchmodat, 3)
2060 MIPS_SYS(sys_faccessat, 3) /* 4300 */
2061 MIPS_SYS(sys_pselect6, 6)
2062 MIPS_SYS(sys_ppoll, 5)
2063 MIPS_SYS(sys_unshare, 1)
Petar Jovanovicb0932e02013-07-23 19:00:10 +02002064 MIPS_SYS(sys_splice, 6)
ths388bb212007-05-13 13:58:00 +00002065 MIPS_SYS(sys_sync_file_range, 7) /* 4305 */
2066 MIPS_SYS(sys_tee, 4)
2067 MIPS_SYS(sys_vmsplice, 4)
2068 MIPS_SYS(sys_move_pages, 6)
2069 MIPS_SYS(sys_set_robust_list, 2)
2070 MIPS_SYS(sys_get_robust_list, 3) /* 4310 */
2071 MIPS_SYS(sys_kexec_load, 4)
2072 MIPS_SYS(sys_getcpu, 3)
2073 MIPS_SYS(sys_epoll_pwait, 6)
2074 MIPS_SYS(sys_ioprio_set, 3)
2075 MIPS_SYS(sys_ioprio_get, 2)
Peter Maydelld979e8e2011-06-27 17:44:51 +01002076 MIPS_SYS(sys_utimensat, 4)
2077 MIPS_SYS(sys_signalfd, 3)
2078 MIPS_SYS(sys_ni_syscall, 0) /* was timerfd */
2079 MIPS_SYS(sys_eventfd, 1)
2080 MIPS_SYS(sys_fallocate, 6) /* 4320 */
2081 MIPS_SYS(sys_timerfd_create, 2)
2082 MIPS_SYS(sys_timerfd_gettime, 2)
2083 MIPS_SYS(sys_timerfd_settime, 4)
2084 MIPS_SYS(sys_signalfd4, 4)
2085 MIPS_SYS(sys_eventfd2, 2) /* 4325 */
2086 MIPS_SYS(sys_epoll_create1, 1)
2087 MIPS_SYS(sys_dup3, 3)
2088 MIPS_SYS(sys_pipe2, 2)
2089 MIPS_SYS(sys_inotify_init1, 1)
2090 MIPS_SYS(sys_preadv, 6) /* 4330 */
2091 MIPS_SYS(sys_pwritev, 6)
2092 MIPS_SYS(sys_rt_tgsigqueueinfo, 4)
2093 MIPS_SYS(sys_perf_event_open, 5)
2094 MIPS_SYS(sys_accept4, 4)
2095 MIPS_SYS(sys_recvmmsg, 5) /* 4335 */
2096 MIPS_SYS(sys_fanotify_init, 2)
2097 MIPS_SYS(sys_fanotify_mark, 6)
2098 MIPS_SYS(sys_prlimit64, 4)
2099 MIPS_SYS(sys_name_to_handle_at, 5)
2100 MIPS_SYS(sys_open_by_handle_at, 3) /* 4340 */
2101 MIPS_SYS(sys_clock_adjtime, 2)
2102 MIPS_SYS(sys_syncfs, 1)
bellard048f6b42005-11-26 18:47:20 +00002103};
Richard Hendersonff4f7382013-02-10 10:30:45 -08002104# undef MIPS_SYS
2105# endif /* O32 */
bellard048f6b42005-11-26 18:47:20 +00002106
Paul Brook590bc602009-07-09 17:45:17 +01002107static int do_store_exclusive(CPUMIPSState *env)
2108{
2109 target_ulong addr;
2110 target_ulong page_addr;
2111 target_ulong val;
2112 int flags;
2113 int segv = 0;
2114 int reg;
2115 int d;
2116
Aurelien Jarno5499b6f2009-11-22 13:08:14 +01002117 addr = env->lladdr;
Paul Brook590bc602009-07-09 17:45:17 +01002118 page_addr = addr & TARGET_PAGE_MASK;
2119 start_exclusive();
2120 mmap_lock();
2121 flags = page_get_flags(page_addr);
2122 if ((flags & PAGE_READ) == 0) {
2123 segv = 1;
2124 } else {
2125 reg = env->llreg & 0x1f;
2126 d = (env->llreg & 0x20) != 0;
2127 if (d) {
2128 segv = get_user_s64(val, addr);
2129 } else {
2130 segv = get_user_s32(val, addr);
2131 }
2132 if (!segv) {
2133 if (val != env->llval) {
2134 env->active_tc.gpr[reg] = 0;
2135 } else {
2136 if (d) {
2137 segv = put_user_u64(env->llnewval, addr);
2138 } else {
2139 segv = put_user_u32(env->llnewval, addr);
2140 }
2141 if (!segv) {
2142 env->active_tc.gpr[reg] = 1;
2143 }
2144 }
2145 }
2146 }
Aurelien Jarno5499b6f2009-11-22 13:08:14 +01002147 env->lladdr = -1;
Paul Brook590bc602009-07-09 17:45:17 +01002148 if (!segv) {
2149 env->active_tc.PC += 4;
2150 }
2151 mmap_unlock();
2152 end_exclusive();
2153 return segv;
2154}
2155
Meador Inge54b2f422013-01-10 16:50:22 -06002156/* Break codes */
2157enum {
2158 BRK_OVERFLOW = 6,
2159 BRK_DIVZERO = 7
2160};
2161
2162static int do_break(CPUMIPSState *env, target_siginfo_t *info,
2163 unsigned int code)
2164{
2165 int ret = -1;
2166
2167 switch (code) {
2168 case BRK_OVERFLOW:
2169 case BRK_DIVZERO:
2170 info->si_signo = TARGET_SIGFPE;
2171 info->si_errno = 0;
2172 info->si_code = (code == BRK_OVERFLOW) ? FPE_INTOVF : FPE_INTDIV;
2173 queue_signal(env, info->si_signo, &*info);
2174 ret = 0;
2175 break;
2176 default:
2177 break;
2178 }
2179
2180 return ret;
2181}
2182
bellard048f6b42005-11-26 18:47:20 +00002183void cpu_loop(CPUMIPSState *env)
2184{
Andreas Färber0315c312012-12-17 07:34:52 +01002185 CPUState *cs = CPU(mips_env_get_cpu(env));
Anthony Liguoric227f092009-10-01 16:12:16 -05002186 target_siginfo_t info;
Richard Hendersonff4f7382013-02-10 10:30:45 -08002187 int trapnr;
2188 abi_long ret;
2189# ifdef TARGET_ABI_MIPSO32
bellard048f6b42005-11-26 18:47:20 +00002190 unsigned int syscall_num;
Richard Hendersonff4f7382013-02-10 10:30:45 -08002191# endif
bellard048f6b42005-11-26 18:47:20 +00002192
2193 for(;;) {
Andreas Färber0315c312012-12-17 07:34:52 +01002194 cpu_exec_start(cs);
bellard048f6b42005-11-26 18:47:20 +00002195 trapnr = cpu_mips_exec(env);
Andreas Färber0315c312012-12-17 07:34:52 +01002196 cpu_exec_end(cs);
bellard048f6b42005-11-26 18:47:20 +00002197 switch(trapnr) {
2198 case EXCP_SYSCALL:
thsb5dc7732008-06-27 10:02:35 +00002199 env->active_tc.PC += 4;
Richard Hendersonff4f7382013-02-10 10:30:45 -08002200# ifdef TARGET_ABI_MIPSO32
2201 syscall_num = env->active_tc.gpr[2] - 4000;
ths388bb212007-05-13 13:58:00 +00002202 if (syscall_num >= sizeof(mips_syscall_args)) {
Wesley W. Terpstra7c2f6152011-07-12 14:33:23 +03002203 ret = -TARGET_ENOSYS;
ths388bb212007-05-13 13:58:00 +00002204 } else {
2205 int nb_args;
blueswir1992f48a2007-10-14 16:27:31 +00002206 abi_ulong sp_reg;
2207 abi_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0;
ths388bb212007-05-13 13:58:00 +00002208
2209 nb_args = mips_syscall_args[syscall_num];
thsb5dc7732008-06-27 10:02:35 +00002210 sp_reg = env->active_tc.gpr[29];
ths388bb212007-05-13 13:58:00 +00002211 switch (nb_args) {
2212 /* these arguments are taken from the stack */
An-Cheng Huang94c19612011-08-09 12:32:38 -07002213 case 8:
2214 if ((ret = get_user_ual(arg8, sp_reg + 28)) != 0) {
2215 goto done_syscall;
2216 }
2217 case 7:
2218 if ((ret = get_user_ual(arg7, sp_reg + 24)) != 0) {
2219 goto done_syscall;
2220 }
2221 case 6:
2222 if ((ret = get_user_ual(arg6, sp_reg + 20)) != 0) {
2223 goto done_syscall;
2224 }
2225 case 5:
2226 if ((ret = get_user_ual(arg5, sp_reg + 16)) != 0) {
2227 goto done_syscall;
2228 }
ths388bb212007-05-13 13:58:00 +00002229 default:
2230 break;
bellard048f6b42005-11-26 18:47:20 +00002231 }
thsb5dc7732008-06-27 10:02:35 +00002232 ret = do_syscall(env, env->active_tc.gpr[2],
2233 env->active_tc.gpr[4],
2234 env->active_tc.gpr[5],
2235 env->active_tc.gpr[6],
2236 env->active_tc.gpr[7],
Peter Maydell5945cfc2011-06-16 17:37:13 +01002237 arg5, arg6, arg7, arg8);
bellard048f6b42005-11-26 18:47:20 +00002238 }
An-Cheng Huang94c19612011-08-09 12:32:38 -07002239done_syscall:
Richard Hendersonff4f7382013-02-10 10:30:45 -08002240# else
2241 ret = do_syscall(env, env->active_tc.gpr[2],
2242 env->active_tc.gpr[4], env->active_tc.gpr[5],
2243 env->active_tc.gpr[6], env->active_tc.gpr[7],
2244 env->active_tc.gpr[8], env->active_tc.gpr[9],
2245 env->active_tc.gpr[10], env->active_tc.gpr[11]);
2246# endif /* O32 */
pbrook0b1bcb02009-04-21 01:41:10 +00002247 if (ret == -TARGET_QEMU_ESIGRETURN) {
2248 /* Returning from a successful sigreturn syscall.
2249 Avoid clobbering register state. */
2250 break;
2251 }
Richard Hendersonff4f7382013-02-10 10:30:45 -08002252 if ((abi_ulong)ret >= (abi_ulong)-1133) {
thsb5dc7732008-06-27 10:02:35 +00002253 env->active_tc.gpr[7] = 1; /* error flag */
ths388bb212007-05-13 13:58:00 +00002254 ret = -ret;
2255 } else {
thsb5dc7732008-06-27 10:02:35 +00002256 env->active_tc.gpr[7] = 0; /* error flag */
ths388bb212007-05-13 13:58:00 +00002257 }
thsb5dc7732008-06-27 10:02:35 +00002258 env->active_tc.gpr[2] = ret;
bellard048f6b42005-11-26 18:47:20 +00002259 break;
thsca7c2b12006-12-10 22:08:10 +00002260 case EXCP_TLBL:
2261 case EXCP_TLBS:
Wesley W. Terpstrae6e5bd22011-07-12 14:34:23 +03002262 case EXCP_AdEL:
2263 case EXCP_AdES:
pbrooke4474232009-04-21 01:03:10 +00002264 info.si_signo = TARGET_SIGSEGV;
2265 info.si_errno = 0;
2266 /* XXX: check env->error_code */
2267 info.si_code = TARGET_SEGV_MAPERR;
2268 info._sifields._sigfault._addr = env->CP0_BadVAddr;
2269 queue_signal(env, info.si_signo, &info);
2270 break;
bellard6900e842005-12-05 21:04:24 +00002271 case EXCP_CpU:
bellard048f6b42005-11-26 18:47:20 +00002272 case EXCP_RI:
bellardbc1ad2d2006-06-14 13:37:55 +00002273 info.si_signo = TARGET_SIGILL;
2274 info.si_errno = 0;
2275 info.si_code = 0;
pbrook624f7972008-05-31 16:11:38 +00002276 queue_signal(env, info.si_signo, &info);
bellard048f6b42005-11-26 18:47:20 +00002277 break;
bellard106ec872006-06-27 21:08:10 +00002278 case EXCP_INTERRUPT:
2279 /* just indicate that signals should be handled asap */
2280 break;
pbrookd08b2a22006-11-04 16:46:29 +00002281 case EXCP_DEBUG:
2282 {
2283 int sig;
2284
Andreas Färberdb6b81d2013-06-27 19:49:31 +02002285 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
pbrookd08b2a22006-11-04 16:46:29 +00002286 if (sig)
2287 {
2288 info.si_signo = sig;
2289 info.si_errno = 0;
2290 info.si_code = TARGET_TRAP_BRKPT;
pbrook624f7972008-05-31 16:11:38 +00002291 queue_signal(env, info.si_signo, &info);
pbrookd08b2a22006-11-04 16:46:29 +00002292 }
2293 }
2294 break;
Paul Brook590bc602009-07-09 17:45:17 +01002295 case EXCP_SC:
2296 if (do_store_exclusive(env)) {
2297 info.si_signo = TARGET_SIGSEGV;
2298 info.si_errno = 0;
2299 info.si_code = TARGET_SEGV_MAPERR;
2300 info._sifields._sigfault._addr = env->active_tc.PC;
2301 queue_signal(env, info.si_signo, &info);
2302 }
2303 break;
Jia Liu853c3242012-10-24 22:17:02 +08002304 case EXCP_DSPDIS:
2305 info.si_signo = TARGET_SIGILL;
2306 info.si_errno = 0;
2307 info.si_code = TARGET_ILL_ILLOPC;
2308 queue_signal(env, info.si_signo, &info);
2309 break;
Meador Inge54b2f422013-01-10 16:50:22 -06002310 /* The code below was inspired by the MIPS Linux kernel trap
2311 * handling code in arch/mips/kernel/traps.c.
2312 */
2313 case EXCP_BREAK:
2314 {
2315 abi_ulong trap_instr;
2316 unsigned int code;
2317
Kwok Cheung Yeunga0333812013-07-19 09:21:44 -07002318 if (env->hflags & MIPS_HFLAG_M16) {
2319 if (env->insn_flags & ASE_MICROMIPS) {
2320 /* microMIPS mode */
2321 abi_ulong instr[2];
2322
2323 ret = get_user_u16(instr[0], env->active_tc.PC) ||
2324 get_user_u16(instr[1], env->active_tc.PC + 2);
2325
2326 trap_instr = (instr[0] << 16) | instr[1];
2327 } else {
2328 /* MIPS16e mode */
2329 ret = get_user_u16(trap_instr, env->active_tc.PC);
2330 if (ret != 0) {
2331 goto error;
2332 }
2333 code = (trap_instr >> 6) & 0x3f;
2334 if (do_break(env, &info, code) != 0) {
2335 goto error;
2336 }
2337 break;
2338 }
2339 } else {
2340 ret = get_user_ual(trap_instr, env->active_tc.PC);
2341 }
2342
Meador Inge54b2f422013-01-10 16:50:22 -06002343 if (ret != 0) {
2344 goto error;
2345 }
2346
2347 /* As described in the original Linux kernel code, the
2348 * below checks on 'code' are to work around an old
2349 * assembly bug.
2350 */
2351 code = ((trap_instr >> 6) & ((1 << 20) - 1));
2352 if (code >= (1 << 10)) {
2353 code >>= 10;
2354 }
2355
2356 if (do_break(env, &info, code) != 0) {
2357 goto error;
2358 }
2359 }
2360 break;
2361 case EXCP_TRAP:
2362 {
2363 abi_ulong trap_instr;
2364 unsigned int code = 0;
2365
Kwok Cheung Yeunga0333812013-07-19 09:21:44 -07002366 if (env->hflags & MIPS_HFLAG_M16) {
2367 /* microMIPS mode */
2368 abi_ulong instr[2];
2369
2370 ret = get_user_u16(instr[0], env->active_tc.PC) ||
2371 get_user_u16(instr[1], env->active_tc.PC + 2);
2372
2373 trap_instr = (instr[0] << 16) | instr[1];
2374 } else {
2375 ret = get_user_ual(trap_instr, env->active_tc.PC);
2376 }
2377
Meador Inge54b2f422013-01-10 16:50:22 -06002378 if (ret != 0) {
2379 goto error;
2380 }
2381
2382 /* The immediate versions don't provide a code. */
2383 if (!(trap_instr & 0xFC000000)) {
Kwok Cheung Yeunga0333812013-07-19 09:21:44 -07002384 if (env->hflags & MIPS_HFLAG_M16) {
2385 /* microMIPS mode */
2386 code = ((trap_instr >> 12) & ((1 << 4) - 1));
2387 } else {
2388 code = ((trap_instr >> 6) & ((1 << 10) - 1));
2389 }
Meador Inge54b2f422013-01-10 16:50:22 -06002390 }
2391
2392 if (do_break(env, &info, code) != 0) {
2393 goto error;
2394 }
2395 }
2396 break;
bellard048f6b42005-11-26 18:47:20 +00002397 default:
Meador Inge54b2f422013-01-10 16:50:22 -06002398error:
ths5fafdf22007-09-16 21:08:06 +00002399 fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
bellard048f6b42005-11-26 18:47:20 +00002400 trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +02002401 cpu_dump_state(cs, stderr, fprintf, 0);
bellard048f6b42005-11-26 18:47:20 +00002402 abort();
2403 }
2404 process_pending_signals(env);
2405 }
2406}
2407#endif
2408
Jia Liud9627832012-07-20 15:50:52 +08002409#ifdef TARGET_OPENRISC
2410
2411void cpu_loop(CPUOpenRISCState *env)
2412{
Andreas Färber878096e2013-05-27 01:33:50 +02002413 CPUState *cs = CPU(openrisc_env_get_cpu(env));
Jia Liud9627832012-07-20 15:50:52 +08002414 int trapnr, gdbsig;
2415
2416 for (;;) {
2417 trapnr = cpu_exec(env);
2418 gdbsig = 0;
2419
2420 switch (trapnr) {
2421 case EXCP_RESET:
2422 qemu_log("\nReset request, exit, pc is %#x\n", env->pc);
2423 exit(1);
2424 break;
2425 case EXCP_BUSERR:
2426 qemu_log("\nBus error, exit, pc is %#x\n", env->pc);
2427 gdbsig = SIGBUS;
2428 break;
2429 case EXCP_DPF:
2430 case EXCP_IPF:
Andreas Färber878096e2013-05-27 01:33:50 +02002431 cpu_dump_state(cs, stderr, fprintf, 0);
Jia Liud9627832012-07-20 15:50:52 +08002432 gdbsig = TARGET_SIGSEGV;
2433 break;
2434 case EXCP_TICK:
2435 qemu_log("\nTick time interrupt pc is %#x\n", env->pc);
2436 break;
2437 case EXCP_ALIGN:
2438 qemu_log("\nAlignment pc is %#x\n", env->pc);
2439 gdbsig = SIGBUS;
2440 break;
2441 case EXCP_ILLEGAL:
2442 qemu_log("\nIllegal instructionpc is %#x\n", env->pc);
2443 gdbsig = SIGILL;
2444 break;
2445 case EXCP_INT:
2446 qemu_log("\nExternal interruptpc is %#x\n", env->pc);
2447 break;
2448 case EXCP_DTLBMISS:
2449 case EXCP_ITLBMISS:
2450 qemu_log("\nTLB miss\n");
2451 break;
2452 case EXCP_RANGE:
2453 qemu_log("\nRange\n");
2454 gdbsig = SIGSEGV;
2455 break;
2456 case EXCP_SYSCALL:
2457 env->pc += 4; /* 0xc00; */
2458 env->gpr[11] = do_syscall(env,
2459 env->gpr[11], /* return value */
2460 env->gpr[3], /* r3 - r7 are params */
2461 env->gpr[4],
2462 env->gpr[5],
2463 env->gpr[6],
2464 env->gpr[7],
2465 env->gpr[8], 0, 0);
2466 break;
2467 case EXCP_FPE:
2468 qemu_log("\nFloating point error\n");
2469 break;
2470 case EXCP_TRAP:
2471 qemu_log("\nTrap\n");
2472 gdbsig = SIGTRAP;
2473 break;
2474 case EXCP_NR:
2475 qemu_log("\nNR\n");
2476 break;
2477 default:
2478 qemu_log("\nqemu: unhandled CPU exception %#x - aborting\n",
2479 trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +02002480 cpu_dump_state(cs, stderr, fprintf, 0);
Jia Liud9627832012-07-20 15:50:52 +08002481 gdbsig = TARGET_SIGILL;
2482 break;
2483 }
2484 if (gdbsig) {
Andreas Färberdb6b81d2013-06-27 19:49:31 +02002485 gdb_handlesig(cs, gdbsig);
Jia Liud9627832012-07-20 15:50:52 +08002486 if (gdbsig != TARGET_SIGTRAP) {
2487 exit(1);
2488 }
2489 }
2490
2491 process_pending_signals(env);
2492 }
2493}
2494
2495#endif /* TARGET_OPENRISC */
2496
bellardfdf9b3e2006-04-27 21:07:38 +00002497#ifdef TARGET_SH4
Andreas Färber05390242012-02-25 03:37:53 +01002498void cpu_loop(CPUSH4State *env)
bellardfdf9b3e2006-04-27 21:07:38 +00002499{
Andreas Färber878096e2013-05-27 01:33:50 +02002500 CPUState *cs = CPU(sh_env_get_cpu(env));
bellardfdf9b3e2006-04-27 21:07:38 +00002501 int trapnr, ret;
Anthony Liguoric227f092009-10-01 16:12:16 -05002502 target_siginfo_t info;
ths3b46e622007-09-17 08:09:54 +00002503
bellardfdf9b3e2006-04-27 21:07:38 +00002504 while (1) {
2505 trapnr = cpu_sh4_exec (env);
ths3b46e622007-09-17 08:09:54 +00002506
bellardfdf9b3e2006-04-27 21:07:38 +00002507 switch (trapnr) {
2508 case 0x160:
aurel320b6d3ae2008-09-15 07:43:43 +00002509 env->pc += 2;
ths5fafdf22007-09-16 21:08:06 +00002510 ret = do_syscall(env,
2511 env->gregs[3],
2512 env->gregs[4],
2513 env->gregs[5],
2514 env->gregs[6],
2515 env->gregs[7],
2516 env->gregs[0],
Peter Maydell5945cfc2011-06-16 17:37:13 +01002517 env->gregs[1],
2518 0, 0);
pbrook9c2a9ea2006-06-18 19:12:54 +00002519 env->gregs[0] = ret;
bellardfdf9b3e2006-04-27 21:07:38 +00002520 break;
thsc3b5bc82007-12-02 06:31:25 +00002521 case EXCP_INTERRUPT:
2522 /* just indicate that signals should be handled asap */
2523 break;
pbrook355fb232006-06-17 19:58:25 +00002524 case EXCP_DEBUG:
2525 {
2526 int sig;
2527
Andreas Färberdb6b81d2013-06-27 19:49:31 +02002528 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
pbrook355fb232006-06-17 19:58:25 +00002529 if (sig)
2530 {
2531 info.si_signo = sig;
2532 info.si_errno = 0;
2533 info.si_code = TARGET_TRAP_BRKPT;
pbrook624f7972008-05-31 16:11:38 +00002534 queue_signal(env, info.si_signo, &info);
pbrook355fb232006-06-17 19:58:25 +00002535 }
2536 }
2537 break;
thsc3b5bc82007-12-02 06:31:25 +00002538 case 0xa0:
2539 case 0xc0:
2540 info.si_signo = SIGSEGV;
2541 info.si_errno = 0;
2542 info.si_code = TARGET_SEGV_MAPERR;
2543 info._sifields._sigfault._addr = env->tea;
pbrook624f7972008-05-31 16:11:38 +00002544 queue_signal(env, info.si_signo, &info);
thsc3b5bc82007-12-02 06:31:25 +00002545 break;
2546
bellardfdf9b3e2006-04-27 21:07:38 +00002547 default:
2548 printf ("Unhandled trap: 0x%x\n", trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +02002549 cpu_dump_state(cs, stderr, fprintf, 0);
bellardfdf9b3e2006-04-27 21:07:38 +00002550 exit (1);
2551 }
2552 process_pending_signals (env);
2553 }
2554}
2555#endif
2556
ths48733d12007-10-08 13:36:46 +00002557#ifdef TARGET_CRIS
Andreas Färber05390242012-02-25 03:37:53 +01002558void cpu_loop(CPUCRISState *env)
ths48733d12007-10-08 13:36:46 +00002559{
Andreas Färber878096e2013-05-27 01:33:50 +02002560 CPUState *cs = CPU(cris_env_get_cpu(env));
ths48733d12007-10-08 13:36:46 +00002561 int trapnr, ret;
Anthony Liguoric227f092009-10-01 16:12:16 -05002562 target_siginfo_t info;
ths48733d12007-10-08 13:36:46 +00002563
2564 while (1) {
2565 trapnr = cpu_cris_exec (env);
2566 switch (trapnr) {
2567 case 0xaa:
2568 {
2569 info.si_signo = SIGSEGV;
2570 info.si_errno = 0;
2571 /* XXX: check env->error_code */
2572 info.si_code = TARGET_SEGV_MAPERR;
edgar_igle00c1e72008-05-27 21:12:09 +00002573 info._sifields._sigfault._addr = env->pregs[PR_EDA];
pbrook624f7972008-05-31 16:11:38 +00002574 queue_signal(env, info.si_signo, &info);
ths48733d12007-10-08 13:36:46 +00002575 }
2576 break;
edgar_iglb6d3abd2008-02-28 11:29:27 +00002577 case EXCP_INTERRUPT:
2578 /* just indicate that signals should be handled asap */
2579 break;
ths48733d12007-10-08 13:36:46 +00002580 case EXCP_BREAK:
2581 ret = do_syscall(env,
2582 env->regs[9],
2583 env->regs[10],
2584 env->regs[11],
2585 env->regs[12],
2586 env->regs[13],
2587 env->pregs[7],
Peter Maydell5945cfc2011-06-16 17:37:13 +01002588 env->pregs[11],
2589 0, 0);
ths48733d12007-10-08 13:36:46 +00002590 env->regs[10] = ret;
ths48733d12007-10-08 13:36:46 +00002591 break;
2592 case EXCP_DEBUG:
2593 {
2594 int sig;
2595
Andreas Färberdb6b81d2013-06-27 19:49:31 +02002596 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
ths48733d12007-10-08 13:36:46 +00002597 if (sig)
2598 {
2599 info.si_signo = sig;
2600 info.si_errno = 0;
2601 info.si_code = TARGET_TRAP_BRKPT;
pbrook624f7972008-05-31 16:11:38 +00002602 queue_signal(env, info.si_signo, &info);
ths48733d12007-10-08 13:36:46 +00002603 }
2604 }
2605 break;
2606 default:
2607 printf ("Unhandled trap: 0x%x\n", trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +02002608 cpu_dump_state(cs, stderr, fprintf, 0);
ths48733d12007-10-08 13:36:46 +00002609 exit (1);
2610 }
2611 process_pending_signals (env);
2612 }
2613}
2614#endif
2615
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02002616#ifdef TARGET_MICROBLAZE
Andreas Färber05390242012-02-25 03:37:53 +01002617void cpu_loop(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02002618{
Andreas Färber878096e2013-05-27 01:33:50 +02002619 CPUState *cs = CPU(mb_env_get_cpu(env));
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02002620 int trapnr, ret;
Anthony Liguoric227f092009-10-01 16:12:16 -05002621 target_siginfo_t info;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02002622
2623 while (1) {
2624 trapnr = cpu_mb_exec (env);
2625 switch (trapnr) {
2626 case 0xaa:
2627 {
2628 info.si_signo = SIGSEGV;
2629 info.si_errno = 0;
2630 /* XXX: check env->error_code */
2631 info.si_code = TARGET_SEGV_MAPERR;
2632 info._sifields._sigfault._addr = 0;
2633 queue_signal(env, info.si_signo, &info);
2634 }
2635 break;
2636 case EXCP_INTERRUPT:
2637 /* just indicate that signals should be handled asap */
2638 break;
2639 case EXCP_BREAK:
2640 /* Return address is 4 bytes after the call. */
2641 env->regs[14] += 4;
Edgar E. Iglesiasd7dce492012-04-26 14:18:25 +02002642 env->sregs[SR_PC] = env->regs[14];
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02002643 ret = do_syscall(env,
2644 env->regs[12],
2645 env->regs[5],
2646 env->regs[6],
2647 env->regs[7],
2648 env->regs[8],
2649 env->regs[9],
Peter Maydell5945cfc2011-06-16 17:37:13 +01002650 env->regs[10],
2651 0, 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02002652 env->regs[3] = ret;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02002653 break;
Edgar E. Iglesiasb76da7e2010-09-09 10:24:01 +02002654 case EXCP_HW_EXCP:
2655 env->regs[17] = env->sregs[SR_PC] + 4;
2656 if (env->iflags & D_FLAG) {
2657 env->sregs[SR_ESR] |= 1 << 12;
2658 env->sregs[SR_PC] -= 4;
Dong Xu Wangb4916d72011-11-22 18:06:17 +08002659 /* FIXME: if branch was immed, replay the imm as well. */
Edgar E. Iglesiasb76da7e2010-09-09 10:24:01 +02002660 }
2661
2662 env->iflags &= ~(IMM_FLAG | D_FLAG);
2663
2664 switch (env->sregs[SR_ESR] & 31) {
Edgar E. Iglesias22a78d62011-08-22 18:42:54 +02002665 case ESR_EC_DIVZERO:
2666 info.si_signo = SIGFPE;
2667 info.si_errno = 0;
2668 info.si_code = TARGET_FPE_FLTDIV;
2669 info._sifields._sigfault._addr = 0;
2670 queue_signal(env, info.si_signo, &info);
2671 break;
Edgar E. Iglesiasb76da7e2010-09-09 10:24:01 +02002672 case ESR_EC_FPU:
2673 info.si_signo = SIGFPE;
2674 info.si_errno = 0;
2675 if (env->sregs[SR_FSR] & FSR_IO) {
2676 info.si_code = TARGET_FPE_FLTINV;
2677 }
2678 if (env->sregs[SR_FSR] & FSR_DZ) {
2679 info.si_code = TARGET_FPE_FLTDIV;
2680 }
2681 info._sifields._sigfault._addr = 0;
2682 queue_signal(env, info.si_signo, &info);
2683 break;
2684 default:
2685 printf ("Unhandled hw-exception: 0x%x\n",
Edgar E. Iglesias2e42d522011-04-11 23:57:07 +02002686 env->sregs[SR_ESR] & ESR_EC_MASK);
Andreas Färber878096e2013-05-27 01:33:50 +02002687 cpu_dump_state(cs, stderr, fprintf, 0);
Edgar E. Iglesiasb76da7e2010-09-09 10:24:01 +02002688 exit (1);
2689 break;
2690 }
2691 break;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02002692 case EXCP_DEBUG:
2693 {
2694 int sig;
2695
Andreas Färberdb6b81d2013-06-27 19:49:31 +02002696 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02002697 if (sig)
2698 {
2699 info.si_signo = sig;
2700 info.si_errno = 0;
2701 info.si_code = TARGET_TRAP_BRKPT;
2702 queue_signal(env, info.si_signo, &info);
2703 }
2704 }
2705 break;
2706 default:
2707 printf ("Unhandled trap: 0x%x\n", trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +02002708 cpu_dump_state(cs, stderr, fprintf, 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02002709 exit (1);
2710 }
2711 process_pending_signals (env);
2712 }
2713}
2714#endif
2715
pbrooke6e59062006-10-22 00:18:54 +00002716#ifdef TARGET_M68K
2717
2718void cpu_loop(CPUM68KState *env)
2719{
Andreas Färber878096e2013-05-27 01:33:50 +02002720 CPUState *cs = CPU(m68k_env_get_cpu(env));
pbrooke6e59062006-10-22 00:18:54 +00002721 int trapnr;
2722 unsigned int n;
Anthony Liguoric227f092009-10-01 16:12:16 -05002723 target_siginfo_t info;
pbrooke6e59062006-10-22 00:18:54 +00002724 TaskState *ts = env->opaque;
ths3b46e622007-09-17 08:09:54 +00002725
pbrooke6e59062006-10-22 00:18:54 +00002726 for(;;) {
2727 trapnr = cpu_m68k_exec(env);
2728 switch(trapnr) {
2729 case EXCP_ILLEGAL:
2730 {
2731 if (ts->sim_syscalls) {
2732 uint16_t nr;
2733 nr = lduw(env->pc + 2);
2734 env->pc += 4;
2735 do_m68k_simcall(env, nr);
2736 } else {
2737 goto do_sigill;
2738 }
2739 }
2740 break;
pbrooka87295e2007-05-26 15:09:38 +00002741 case EXCP_HALT_INSN:
pbrooke6e59062006-10-22 00:18:54 +00002742 /* Semihosing syscall. */
pbrooka87295e2007-05-26 15:09:38 +00002743 env->pc += 4;
pbrooke6e59062006-10-22 00:18:54 +00002744 do_m68k_semihosting(env, env->dregs[0]);
2745 break;
2746 case EXCP_LINEA:
2747 case EXCP_LINEF:
2748 case EXCP_UNSUPPORTED:
2749 do_sigill:
2750 info.si_signo = SIGILL;
2751 info.si_errno = 0;
2752 info.si_code = TARGET_ILL_ILLOPN;
2753 info._sifields._sigfault._addr = env->pc;
pbrook624f7972008-05-31 16:11:38 +00002754 queue_signal(env, info.si_signo, &info);
pbrooke6e59062006-10-22 00:18:54 +00002755 break;
2756 case EXCP_TRAP0:
2757 {
2758 ts->sim_syscalls = 0;
2759 n = env->dregs[0];
2760 env->pc += 2;
ths5fafdf22007-09-16 21:08:06 +00002761 env->dregs[0] = do_syscall(env,
2762 n,
pbrooke6e59062006-10-22 00:18:54 +00002763 env->dregs[1],
2764 env->dregs[2],
2765 env->dregs[3],
2766 env->dregs[4],
2767 env->dregs[5],
Peter Maydell5945cfc2011-06-16 17:37:13 +01002768 env->aregs[0],
2769 0, 0);
pbrooke6e59062006-10-22 00:18:54 +00002770 }
2771 break;
2772 case EXCP_INTERRUPT:
2773 /* just indicate that signals should be handled asap */
2774 break;
2775 case EXCP_ACCESS:
2776 {
2777 info.si_signo = SIGSEGV;
2778 info.si_errno = 0;
2779 /* XXX: check env->error_code */
2780 info.si_code = TARGET_SEGV_MAPERR;
2781 info._sifields._sigfault._addr = env->mmu.ar;
pbrook624f7972008-05-31 16:11:38 +00002782 queue_signal(env, info.si_signo, &info);
pbrooke6e59062006-10-22 00:18:54 +00002783 }
2784 break;
2785 case EXCP_DEBUG:
2786 {
2787 int sig;
2788
Andreas Färberdb6b81d2013-06-27 19:49:31 +02002789 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
pbrooke6e59062006-10-22 00:18:54 +00002790 if (sig)
2791 {
2792 info.si_signo = sig;
2793 info.si_errno = 0;
2794 info.si_code = TARGET_TRAP_BRKPT;
pbrook624f7972008-05-31 16:11:38 +00002795 queue_signal(env, info.si_signo, &info);
pbrooke6e59062006-10-22 00:18:54 +00002796 }
2797 }
2798 break;
2799 default:
ths5fafdf22007-09-16 21:08:06 +00002800 fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
pbrooke6e59062006-10-22 00:18:54 +00002801 trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +02002802 cpu_dump_state(cs, stderr, fprintf, 0);
pbrooke6e59062006-10-22 00:18:54 +00002803 abort();
2804 }
2805 process_pending_signals(env);
2806 }
2807}
2808#endif /* TARGET_M68K */
2809
j_mayer7a3148a2007-04-05 07:13:51 +00002810#ifdef TARGET_ALPHA
Richard Henderson6910b8f2010-04-07 15:42:26 -07002811static void do_store_exclusive(CPUAlphaState *env, int reg, int quad)
2812{
2813 target_ulong addr, val, tmp;
2814 target_siginfo_t info;
2815 int ret = 0;
2816
2817 addr = env->lock_addr;
2818 tmp = env->lock_st_addr;
2819 env->lock_addr = -1;
2820 env->lock_st_addr = 0;
2821
2822 start_exclusive();
2823 mmap_lock();
2824
2825 if (addr == tmp) {
2826 if (quad ? get_user_s64(val, addr) : get_user_s32(val, addr)) {
2827 goto do_sigsegv;
2828 }
2829
2830 if (val == env->lock_value) {
2831 tmp = env->ir[reg];
2832 if (quad ? put_user_u64(tmp, addr) : put_user_u32(tmp, addr)) {
2833 goto do_sigsegv;
2834 }
2835 ret = 1;
2836 }
2837 }
2838 env->ir[reg] = ret;
2839 env->pc += 4;
2840
2841 mmap_unlock();
2842 end_exclusive();
2843 return;
2844
2845 do_sigsegv:
2846 mmap_unlock();
2847 end_exclusive();
2848
2849 info.si_signo = TARGET_SIGSEGV;
2850 info.si_errno = 0;
2851 info.si_code = TARGET_SEGV_MAPERR;
2852 info._sifields._sigfault._addr = addr;
2853 queue_signal(env, TARGET_SIGSEGV, &info);
2854}
2855
Andreas Färber05390242012-02-25 03:37:53 +01002856void cpu_loop(CPUAlphaState *env)
j_mayer7a3148a2007-04-05 07:13:51 +00002857{
Andreas Färber878096e2013-05-27 01:33:50 +02002858 CPUState *cs = CPU(alpha_env_get_cpu(env));
j_mayere96efcf2007-04-14 12:17:09 +00002859 int trapnr;
Anthony Liguoric227f092009-10-01 16:12:16 -05002860 target_siginfo_t info;
Richard Henderson6049f4f2009-12-27 18:30:03 -08002861 abi_long sysret;
ths3b46e622007-09-17 08:09:54 +00002862
j_mayer7a3148a2007-04-05 07:13:51 +00002863 while (1) {
2864 trapnr = cpu_alpha_exec (env);
ths3b46e622007-09-17 08:09:54 +00002865
Richard Hendersonac316ca2010-04-12 16:14:54 -07002866 /* All of the traps imply a transition through PALcode, which
2867 implies an REI instruction has been executed. Which means
2868 that the intr_flag should be cleared. */
2869 env->intr_flag = 0;
2870
j_mayer7a3148a2007-04-05 07:13:51 +00002871 switch (trapnr) {
2872 case EXCP_RESET:
2873 fprintf(stderr, "Reset requested. Exit\n");
2874 exit(1);
2875 break;
2876 case EXCP_MCHK:
2877 fprintf(stderr, "Machine check exception. Exit\n");
2878 exit(1);
2879 break;
Richard Henderson07b6c132011-05-20 14:04:57 -07002880 case EXCP_SMP_INTERRUPT:
2881 case EXCP_CLK_INTERRUPT:
2882 case EXCP_DEV_INTERRUPT:
ths5fafdf22007-09-16 21:08:06 +00002883 fprintf(stderr, "External interrupt. Exit\n");
j_mayer7a3148a2007-04-05 07:13:51 +00002884 exit(1);
2885 break;
Richard Henderson07b6c132011-05-20 14:04:57 -07002886 case EXCP_MMFAULT:
Richard Henderson6910b8f2010-04-07 15:42:26 -07002887 env->lock_addr = -1;
Richard Henderson6049f4f2009-12-27 18:30:03 -08002888 info.si_signo = TARGET_SIGSEGV;
2889 info.si_errno = 0;
Richard Henderson129d8aa2011-05-20 13:30:00 -07002890 info.si_code = (page_get_flags(env->trap_arg0) & PAGE_VALID
Richard Henderson0be1d072010-05-21 10:03:33 -07002891 ? TARGET_SEGV_ACCERR : TARGET_SEGV_MAPERR);
Richard Henderson129d8aa2011-05-20 13:30:00 -07002892 info._sifields._sigfault._addr = env->trap_arg0;
Richard Henderson6049f4f2009-12-27 18:30:03 -08002893 queue_signal(env, info.si_signo, &info);
j_mayer7a3148a2007-04-05 07:13:51 +00002894 break;
j_mayer7a3148a2007-04-05 07:13:51 +00002895 case EXCP_UNALIGN:
Richard Henderson6910b8f2010-04-07 15:42:26 -07002896 env->lock_addr = -1;
Richard Henderson6049f4f2009-12-27 18:30:03 -08002897 info.si_signo = TARGET_SIGBUS;
2898 info.si_errno = 0;
2899 info.si_code = TARGET_BUS_ADRALN;
Richard Henderson129d8aa2011-05-20 13:30:00 -07002900 info._sifields._sigfault._addr = env->trap_arg0;
Richard Henderson6049f4f2009-12-27 18:30:03 -08002901 queue_signal(env, info.si_signo, &info);
j_mayer7a3148a2007-04-05 07:13:51 +00002902 break;
2903 case EXCP_OPCDEC:
Richard Henderson6049f4f2009-12-27 18:30:03 -08002904 do_sigill:
Richard Henderson6910b8f2010-04-07 15:42:26 -07002905 env->lock_addr = -1;
Richard Henderson6049f4f2009-12-27 18:30:03 -08002906 info.si_signo = TARGET_SIGILL;
2907 info.si_errno = 0;
2908 info.si_code = TARGET_ILL_ILLOPC;
2909 info._sifields._sigfault._addr = env->pc;
2910 queue_signal(env, info.si_signo, &info);
j_mayer7a3148a2007-04-05 07:13:51 +00002911 break;
Richard Henderson07b6c132011-05-20 14:04:57 -07002912 case EXCP_ARITH:
2913 env->lock_addr = -1;
2914 info.si_signo = TARGET_SIGFPE;
2915 info.si_errno = 0;
2916 info.si_code = TARGET_FPE_FLTINV;
2917 info._sifields._sigfault._addr = env->pc;
2918 queue_signal(env, info.si_signo, &info);
2919 break;
j_mayer7a3148a2007-04-05 07:13:51 +00002920 case EXCP_FEN:
Richard Henderson6049f4f2009-12-27 18:30:03 -08002921 /* No-op. Linux simply re-enables the FPU. */
j_mayer7a3148a2007-04-05 07:13:51 +00002922 break;
Richard Henderson07b6c132011-05-20 14:04:57 -07002923 case EXCP_CALL_PAL:
Richard Henderson6910b8f2010-04-07 15:42:26 -07002924 env->lock_addr = -1;
Richard Henderson07b6c132011-05-20 14:04:57 -07002925 switch (env->error_code) {
Richard Henderson6049f4f2009-12-27 18:30:03 -08002926 case 0x80:
2927 /* BPT */
2928 info.si_signo = TARGET_SIGTRAP;
2929 info.si_errno = 0;
2930 info.si_code = TARGET_TRAP_BRKPT;
2931 info._sifields._sigfault._addr = env->pc;
2932 queue_signal(env, info.si_signo, &info);
2933 break;
2934 case 0x81:
2935 /* BUGCHK */
2936 info.si_signo = TARGET_SIGTRAP;
2937 info.si_errno = 0;
2938 info.si_code = 0;
2939 info._sifields._sigfault._addr = env->pc;
2940 queue_signal(env, info.si_signo, &info);
2941 break;
2942 case 0x83:
2943 /* CALLSYS */
2944 trapnr = env->ir[IR_V0];
2945 sysret = do_syscall(env, trapnr,
2946 env->ir[IR_A0], env->ir[IR_A1],
2947 env->ir[IR_A2], env->ir[IR_A3],
Peter Maydell5945cfc2011-06-16 17:37:13 +01002948 env->ir[IR_A4], env->ir[IR_A5],
2949 0, 0);
Richard Hendersona5b3b132010-05-03 10:07:55 -07002950 if (trapnr == TARGET_NR_sigreturn
2951 || trapnr == TARGET_NR_rt_sigreturn) {
2952 break;
2953 }
2954 /* Syscall writes 0 to V0 to bypass error check, similar
Richard Henderson0e141972012-06-07 14:47:41 -07002955 to how this is handled internal to Linux kernel.
2956 (Ab)use trapnr temporarily as boolean indicating error. */
2957 trapnr = (env->ir[IR_V0] != 0 && sysret < 0);
2958 env->ir[IR_V0] = (trapnr ? -sysret : sysret);
2959 env->ir[IR_A3] = trapnr;
Richard Henderson6049f4f2009-12-27 18:30:03 -08002960 break;
2961 case 0x86:
2962 /* IMB */
2963 /* ??? We can probably elide the code using page_unprotect
2964 that is checking for self-modifying code. Instead we
2965 could simply call tb_flush here. Until we work out the
2966 changes required to turn off the extra write protection,
2967 this can be a no-op. */
2968 break;
2969 case 0x9E:
2970 /* RDUNIQUE */
2971 /* Handled in the translator for usermode. */
2972 abort();
2973 case 0x9F:
2974 /* WRUNIQUE */
2975 /* Handled in the translator for usermode. */
2976 abort();
2977 case 0xAA:
2978 /* GENTRAP */
2979 info.si_signo = TARGET_SIGFPE;
2980 switch (env->ir[IR_A0]) {
2981 case TARGET_GEN_INTOVF:
2982 info.si_code = TARGET_FPE_INTOVF;
2983 break;
2984 case TARGET_GEN_INTDIV:
2985 info.si_code = TARGET_FPE_INTDIV;
2986 break;
2987 case TARGET_GEN_FLTOVF:
2988 info.si_code = TARGET_FPE_FLTOVF;
2989 break;
2990 case TARGET_GEN_FLTUND:
2991 info.si_code = TARGET_FPE_FLTUND;
2992 break;
2993 case TARGET_GEN_FLTINV:
2994 info.si_code = TARGET_FPE_FLTINV;
2995 break;
2996 case TARGET_GEN_FLTINE:
2997 info.si_code = TARGET_FPE_FLTRES;
2998 break;
2999 case TARGET_GEN_ROPRAND:
3000 info.si_code = 0;
3001 break;
3002 default:
3003 info.si_signo = TARGET_SIGTRAP;
3004 info.si_code = 0;
3005 break;
3006 }
3007 info.si_errno = 0;
3008 info._sifields._sigfault._addr = env->pc;
3009 queue_signal(env, info.si_signo, &info);
3010 break;
3011 default:
3012 goto do_sigill;
3013 }
j_mayer7a3148a2007-04-05 07:13:51 +00003014 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003015 case EXCP_DEBUG:
Andreas Färberdb6b81d2013-06-27 19:49:31 +02003016 info.si_signo = gdb_handlesig(cs, TARGET_SIGTRAP);
Richard Henderson6049f4f2009-12-27 18:30:03 -08003017 if (info.si_signo) {
Richard Henderson6910b8f2010-04-07 15:42:26 -07003018 env->lock_addr = -1;
Richard Henderson6049f4f2009-12-27 18:30:03 -08003019 info.si_errno = 0;
3020 info.si_code = TARGET_TRAP_BRKPT;
3021 queue_signal(env, info.si_signo, &info);
j_mayer7a3148a2007-04-05 07:13:51 +00003022 }
3023 break;
Richard Henderson6910b8f2010-04-07 15:42:26 -07003024 case EXCP_STL_C:
3025 case EXCP_STQ_C:
3026 do_store_exclusive(env, env->error_code, trapnr - EXCP_STL_C);
3027 break;
Richard Hendersond0f20492012-05-31 12:05:23 -07003028 case EXCP_INTERRUPT:
3029 /* Just indicate that signals should be handled asap. */
3030 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003031 default:
3032 printf ("Unhandled trap: 0x%x\n", trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +02003033 cpu_dump_state(cs, stderr, fprintf, 0);
j_mayer7a3148a2007-04-05 07:13:51 +00003034 exit (1);
3035 }
3036 process_pending_signals (env);
3037 }
3038}
3039#endif /* TARGET_ALPHA */
3040
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003041#ifdef TARGET_S390X
3042void cpu_loop(CPUS390XState *env)
3043{
Andreas Färber878096e2013-05-27 01:33:50 +02003044 CPUState *cs = CPU(s390_env_get_cpu(env));
Richard Hendersond5a103c2012-09-14 19:31:57 -07003045 int trapnr, n, sig;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003046 target_siginfo_t info;
Richard Hendersond5a103c2012-09-14 19:31:57 -07003047 target_ulong addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003048
3049 while (1) {
Richard Hendersond5a103c2012-09-14 19:31:57 -07003050 trapnr = cpu_s390x_exec(env);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003051 switch (trapnr) {
3052 case EXCP_INTERRUPT:
Richard Hendersond5a103c2012-09-14 19:31:57 -07003053 /* Just indicate that signals should be handled asap. */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003054 break;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003055
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003056 case EXCP_SVC:
Richard Hendersond5a103c2012-09-14 19:31:57 -07003057 n = env->int_svc_code;
3058 if (!n) {
3059 /* syscalls > 255 */
3060 n = env->regs[1];
3061 }
3062 env->psw.addr += env->int_svc_ilen;
3063 env->regs[2] = do_syscall(env, n, env->regs[2], env->regs[3],
3064 env->regs[4], env->regs[5],
3065 env->regs[6], env->regs[7], 0, 0);
3066 break;
3067
3068 case EXCP_DEBUG:
Andreas Färberdb6b81d2013-06-27 19:49:31 +02003069 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
Richard Hendersond5a103c2012-09-14 19:31:57 -07003070 if (sig) {
3071 n = TARGET_TRAP_BRKPT;
3072 goto do_signal_pc;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003073 }
3074 break;
Richard Hendersond5a103c2012-09-14 19:31:57 -07003075 case EXCP_PGM:
3076 n = env->int_pgm_code;
3077 switch (n) {
3078 case PGM_OPERATION:
3079 case PGM_PRIVILEGED:
3080 sig = SIGILL;
3081 n = TARGET_ILL_ILLOPC;
3082 goto do_signal_pc;
3083 case PGM_PROTECTION:
3084 case PGM_ADDRESSING:
3085 sig = SIGSEGV;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003086 /* XXX: check env->error_code */
Richard Hendersond5a103c2012-09-14 19:31:57 -07003087 n = TARGET_SEGV_MAPERR;
3088 addr = env->__excp_addr;
3089 goto do_signal;
3090 case PGM_EXECUTE:
3091 case PGM_SPECIFICATION:
3092 case PGM_SPECIAL_OP:
3093 case PGM_OPERAND:
3094 do_sigill_opn:
3095 sig = SIGILL;
3096 n = TARGET_ILL_ILLOPN;
3097 goto do_signal_pc;
3098
3099 case PGM_FIXPT_OVERFLOW:
3100 sig = SIGFPE;
3101 n = TARGET_FPE_INTOVF;
3102 goto do_signal_pc;
3103 case PGM_FIXPT_DIVIDE:
3104 sig = SIGFPE;
3105 n = TARGET_FPE_INTDIV;
3106 goto do_signal_pc;
3107
3108 case PGM_DATA:
3109 n = (env->fpc >> 8) & 0xff;
3110 if (n == 0xff) {
3111 /* compare-and-trap */
3112 goto do_sigill_opn;
3113 } else {
3114 /* An IEEE exception, simulated or otherwise. */
3115 if (n & 0x80) {
3116 n = TARGET_FPE_FLTINV;
3117 } else if (n & 0x40) {
3118 n = TARGET_FPE_FLTDIV;
3119 } else if (n & 0x20) {
3120 n = TARGET_FPE_FLTOVF;
3121 } else if (n & 0x10) {
3122 n = TARGET_FPE_FLTUND;
3123 } else if (n & 0x08) {
3124 n = TARGET_FPE_FLTRES;
3125 } else {
3126 /* ??? Quantum exception; BFP, DFP error. */
3127 goto do_sigill_opn;
3128 }
3129 sig = SIGFPE;
3130 goto do_signal_pc;
3131 }
3132
3133 default:
3134 fprintf(stderr, "Unhandled program exception: %#x\n", n);
Andreas Färber878096e2013-05-27 01:33:50 +02003135 cpu_dump_state(cs, stderr, fprintf, 0);
Richard Hendersond5a103c2012-09-14 19:31:57 -07003136 exit(1);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003137 }
3138 break;
Richard Hendersond5a103c2012-09-14 19:31:57 -07003139
3140 do_signal_pc:
3141 addr = env->psw.addr;
3142 do_signal:
3143 info.si_signo = sig;
3144 info.si_errno = 0;
3145 info.si_code = n;
3146 info._sifields._sigfault._addr = addr;
3147 queue_signal(env, info.si_signo, &info);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003148 break;
Richard Hendersond5a103c2012-09-14 19:31:57 -07003149
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003150 default:
Richard Hendersond5a103c2012-09-14 19:31:57 -07003151 fprintf(stderr, "Unhandled trap: 0x%x\n", trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +02003152 cpu_dump_state(cs, stderr, fprintf, 0);
Richard Hendersond5a103c2012-09-14 19:31:57 -07003153 exit(1);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003154 }
3155 process_pending_signals (env);
3156 }
3157}
3158
3159#endif /* TARGET_S390X */
3160
Andreas Färbera2247f82013-06-09 19:47:04 +02003161THREAD CPUState *thread_cpu;
bellard59faf6d2003-06-25 16:18:50 +00003162
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003163void task_settid(TaskState *ts)
3164{
3165 if (ts->ts_tid == 0) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003166 ts->ts_tid = (pid_t)syscall(SYS_gettid);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003167 }
3168}
3169
3170void stop_all_tasks(void)
3171{
3172 /*
3173 * We trust that when using NPTL, start_exclusive()
3174 * handles thread stopping correctly.
3175 */
3176 start_exclusive();
3177}
3178
pbrookc3a92832008-06-09 14:02:50 +00003179/* Assumes contents are already zeroed. */
pbrook624f7972008-05-31 16:11:38 +00003180void init_task_state(TaskState *ts)
3181{
3182 int i;
3183
pbrook624f7972008-05-31 16:11:38 +00003184 ts->used = 1;
3185 ts->first_free = ts->sigqueue_table;
3186 for (i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++) {
3187 ts->sigqueue_table[i].next = &ts->sigqueue_table[i + 1];
3188 }
3189 ts->sigqueue_table[i].next = NULL;
3190}
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003191
3192static void handle_arg_help(const char *arg)
3193{
3194 usage();
3195}
3196
3197static void handle_arg_log(const char *arg)
3198{
3199 int mask;
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003200
Peter Maydell4fde1eb2013-02-11 16:41:22 +00003201 mask = qemu_str_to_log_mask(arg);
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003202 if (!mask) {
Peter Maydell59a6fa62013-02-11 16:41:21 +00003203 qemu_print_log_usage(stdout);
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003204 exit(1);
3205 }
Peter Maydell24537a02013-02-11 16:41:23 +00003206 qemu_set_log(mask);
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003207}
3208
陳韋任50171d42011-11-08 17:46:44 +08003209static void handle_arg_log_filename(const char *arg)
3210{
Peter Maydell9a7e5422013-02-11 16:41:20 +00003211 qemu_set_log_filename(arg);
陳韋任50171d42011-11-08 17:46:44 +08003212}
3213
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003214static void handle_arg_set_env(const char *arg)
3215{
3216 char *r, *p, *token;
3217 r = p = strdup(arg);
3218 while ((token = strsep(&p, ",")) != NULL) {
3219 if (envlist_setenv(envlist, token) != 0) {
3220 usage();
3221 }
3222 }
3223 free(r);
3224}
3225
3226static void handle_arg_unset_env(const char *arg)
3227{
3228 char *r, *p, *token;
3229 r = p = strdup(arg);
3230 while ((token = strsep(&p, ",")) != NULL) {
3231 if (envlist_unsetenv(envlist, token) != 0) {
3232 usage();
3233 }
3234 }
3235 free(r);
3236}
3237
3238static void handle_arg_argv0(const char *arg)
3239{
3240 argv0 = strdup(arg);
3241}
3242
3243static void handle_arg_stack_size(const char *arg)
3244{
3245 char *p;
3246 guest_stack_size = strtoul(arg, &p, 0);
3247 if (guest_stack_size == 0) {
3248 usage();
3249 }
3250
3251 if (*p == 'M') {
3252 guest_stack_size *= 1024 * 1024;
3253 } else if (*p == 'k' || *p == 'K') {
3254 guest_stack_size *= 1024;
3255 }
3256}
3257
3258static void handle_arg_ld_prefix(const char *arg)
3259{
3260 interp_prefix = strdup(arg);
3261}
3262
3263static void handle_arg_pagesize(const char *arg)
3264{
3265 qemu_host_page_size = atoi(arg);
3266 if (qemu_host_page_size == 0 ||
3267 (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
3268 fprintf(stderr, "page size must be a power of two\n");
3269 exit(1);
3270 }
3271}
3272
3273static void handle_arg_gdb(const char *arg)
3274{
3275 gdbstub_port = atoi(arg);
3276}
3277
3278static void handle_arg_uname(const char *arg)
3279{
3280 qemu_uname_release = strdup(arg);
3281}
3282
3283static void handle_arg_cpu(const char *arg)
3284{
3285 cpu_model = strdup(arg);
Peter Maydellc8057f92012-08-02 13:45:54 +01003286 if (cpu_model == NULL || is_help_option(cpu_model)) {
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003287 /* XXX: implement xxx_cpu_list for targets that still miss it */
Peter Maydelle916cbf2012-09-05 17:41:08 -03003288#if defined(cpu_list)
3289 cpu_list(stdout, &fprintf);
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003290#endif
3291 exit(1);
3292 }
3293}
3294
3295#if defined(CONFIG_USE_GUEST_BASE)
3296static void handle_arg_guest_base(const char *arg)
3297{
3298 guest_base = strtol(arg, NULL, 0);
3299 have_guest_base = 1;
3300}
3301
3302static void handle_arg_reserved_va(const char *arg)
3303{
3304 char *p;
3305 int shift = 0;
3306 reserved_va = strtoul(arg, &p, 0);
3307 switch (*p) {
3308 case 'k':
3309 case 'K':
3310 shift = 10;
3311 break;
3312 case 'M':
3313 shift = 20;
3314 break;
3315 case 'G':
3316 shift = 30;
3317 break;
3318 }
3319 if (shift) {
3320 unsigned long unshifted = reserved_va;
3321 p++;
3322 reserved_va <<= shift;
3323 if (((reserved_va >> shift) != unshifted)
3324#if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS
3325 || (reserved_va > (1ul << TARGET_VIRT_ADDR_SPACE_BITS))
3326#endif
3327 ) {
3328 fprintf(stderr, "Reserved virtual address too big\n");
3329 exit(1);
3330 }
3331 }
3332 if (*p) {
3333 fprintf(stderr, "Unrecognised -R size suffix '%s'\n", p);
3334 exit(1);
3335 }
3336}
3337#endif
3338
3339static void handle_arg_singlestep(const char *arg)
3340{
3341 singlestep = 1;
3342}
3343
3344static void handle_arg_strace(const char *arg)
3345{
3346 do_strace = 1;
3347}
3348
3349static void handle_arg_version(const char *arg)
3350{
Paolo Bonzini2e599152013-06-04 14:45:27 +02003351 printf("qemu-" TARGET_NAME " version " QEMU_VERSION QEMU_PKGVERSION
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003352 ", Copyright (c) 2003-2008 Fabrice Bellard\n");
Peter Maydell1386d4c2011-09-29 15:48:12 +01003353 exit(0);
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003354}
3355
3356struct qemu_argument {
3357 const char *argv;
3358 const char *env;
3359 bool has_arg;
3360 void (*handle_opt)(const char *arg);
3361 const char *example;
3362 const char *help;
3363};
3364
Jim Meyering42644ce2012-05-21 21:56:19 +02003365static const struct qemu_argument arg_table[] = {
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003366 {"h", "", false, handle_arg_help,
3367 "", "print this help"},
3368 {"g", "QEMU_GDB", true, handle_arg_gdb,
3369 "port", "wait gdb connection to 'port'"},
3370 {"L", "QEMU_LD_PREFIX", true, handle_arg_ld_prefix,
3371 "path", "set the elf interpreter prefix to 'path'"},
3372 {"s", "QEMU_STACK_SIZE", true, handle_arg_stack_size,
3373 "size", "set the stack size to 'size' bytes"},
3374 {"cpu", "QEMU_CPU", true, handle_arg_cpu,
Peter Maydellc8057f92012-08-02 13:45:54 +01003375 "model", "select CPU (-cpu help for list)"},
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003376 {"E", "QEMU_SET_ENV", true, handle_arg_set_env,
3377 "var=value", "sets targets environment variable (see below)"},
3378 {"U", "QEMU_UNSET_ENV", true, handle_arg_unset_env,
3379 "var", "unsets targets environment variable (see below)"},
3380 {"0", "QEMU_ARGV0", true, handle_arg_argv0,
3381 "argv0", "forces target process argv[0] to be 'argv0'"},
3382 {"r", "QEMU_UNAME", true, handle_arg_uname,
3383 "uname", "set qemu uname release string to 'uname'"},
3384#if defined(CONFIG_USE_GUEST_BASE)
3385 {"B", "QEMU_GUEST_BASE", true, handle_arg_guest_base,
3386 "address", "set guest_base address to 'address'"},
3387 {"R", "QEMU_RESERVED_VA", true, handle_arg_reserved_va,
3388 "size", "reserve 'size' bytes for guest virtual address space"},
3389#endif
3390 {"d", "QEMU_LOG", true, handle_arg_log,
Peter Maydell989b6972013-02-26 17:52:40 +00003391 "item[,...]", "enable logging of specified items "
3392 "(use '-d help' for a list of items)"},
陳韋任50171d42011-11-08 17:46:44 +08003393 {"D", "QEMU_LOG_FILENAME", true, handle_arg_log_filename,
Peter Maydell989b6972013-02-26 17:52:40 +00003394 "logfile", "write logs to 'logfile' (default stderr)"},
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003395 {"p", "QEMU_PAGESIZE", true, handle_arg_pagesize,
3396 "pagesize", "set the host page size to 'pagesize'"},
3397 {"singlestep", "QEMU_SINGLESTEP", false, handle_arg_singlestep,
3398 "", "run in singlestep mode"},
3399 {"strace", "QEMU_STRACE", false, handle_arg_strace,
3400 "", "log system calls"},
3401 {"version", "QEMU_VERSION", false, handle_arg_version,
Peter Maydell1386d4c2011-09-29 15:48:12 +01003402 "", "display version information and exit"},
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003403 {NULL, NULL, false, NULL, NULL, NULL}
3404};
3405
3406static void usage(void)
3407{
Jim Meyering42644ce2012-05-21 21:56:19 +02003408 const struct qemu_argument *arginfo;
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003409 int maxarglen;
3410 int maxenvlen;
3411
Paolo Bonzini2e599152013-06-04 14:45:27 +02003412 printf("usage: qemu-" TARGET_NAME " [options] program [arguments...]\n"
3413 "Linux CPU emulator (compiled for " TARGET_NAME " emulation)\n"
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003414 "\n"
3415 "Options and associated environment variables:\n"
3416 "\n");
3417
Peter Maydell63ec54d2013-02-14 08:46:43 +00003418 /* Calculate column widths. We must always have at least enough space
3419 * for the column header.
3420 */
3421 maxarglen = strlen("Argument");
3422 maxenvlen = strlen("Env-variable");
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003423
3424 for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
Peter Maydell63ec54d2013-02-14 08:46:43 +00003425 int arglen = strlen(arginfo->argv);
3426 if (arginfo->has_arg) {
3427 arglen += strlen(arginfo->example) + 1;
3428 }
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003429 if (strlen(arginfo->env) > maxenvlen) {
3430 maxenvlen = strlen(arginfo->env);
3431 }
Peter Maydell63ec54d2013-02-14 08:46:43 +00003432 if (arglen > maxarglen) {
3433 maxarglen = arglen;
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003434 }
3435 }
3436
Peter Maydell63ec54d2013-02-14 08:46:43 +00003437 printf("%-*s %-*s Description\n", maxarglen+1, "Argument",
3438 maxenvlen, "Env-variable");
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003439
3440 for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
3441 if (arginfo->has_arg) {
3442 printf("-%s %-*s %-*s %s\n", arginfo->argv,
Peter Maydell63ec54d2013-02-14 08:46:43 +00003443 (int)(maxarglen - strlen(arginfo->argv) - 1),
3444 arginfo->example, maxenvlen, arginfo->env, arginfo->help);
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003445 } else {
Peter Maydell63ec54d2013-02-14 08:46:43 +00003446 printf("-%-*s %-*s %s\n", maxarglen, arginfo->argv,
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003447 maxenvlen, arginfo->env,
3448 arginfo->help);
3449 }
3450 }
3451
3452 printf("\n"
3453 "Defaults:\n"
3454 "QEMU_LD_PREFIX = %s\n"
Peter Maydell989b6972013-02-26 17:52:40 +00003455 "QEMU_STACK_SIZE = %ld byte\n",
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003456 interp_prefix,
Peter Maydell989b6972013-02-26 17:52:40 +00003457 guest_stack_size);
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003458
3459 printf("\n"
3460 "You can use -E and -U options or the QEMU_SET_ENV and\n"
3461 "QEMU_UNSET_ENV environment variables to set and unset\n"
3462 "environment variables for the target process.\n"
3463 "It is possible to provide several variables by separating them\n"
3464 "by commas in getsubopt(3) style. Additionally it is possible to\n"
3465 "provide the -E and -U options multiple times.\n"
3466 "The following lines are equivalent:\n"
3467 " -E var1=val2 -E var2=val2 -U LD_PRELOAD -U LD_DEBUG\n"
3468 " -E var1=val2,var2=val2 -U LD_PRELOAD,LD_DEBUG\n"
3469 " QEMU_SET_ENV=var1=val2,var2=val2 QEMU_UNSET_ENV=LD_PRELOAD,LD_DEBUG\n"
3470 "Note that if you provide several changes to a single variable\n"
3471 "the last change will stay in effect.\n");
3472
3473 exit(1);
3474}
3475
3476static int parse_args(int argc, char **argv)
3477{
3478 const char *r;
3479 int optind;
Jim Meyering42644ce2012-05-21 21:56:19 +02003480 const struct qemu_argument *arginfo;
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003481
3482 for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
3483 if (arginfo->env == NULL) {
3484 continue;
3485 }
3486
3487 r = getenv(arginfo->env);
3488 if (r != NULL) {
3489 arginfo->handle_opt(r);
3490 }
3491 }
3492
3493 optind = 1;
3494 for (;;) {
3495 if (optind >= argc) {
3496 break;
3497 }
3498 r = argv[optind];
3499 if (r[0] != '-') {
3500 break;
3501 }
3502 optind++;
3503 r++;
3504 if (!strcmp(r, "-")) {
3505 break;
3506 }
3507
3508 for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
3509 if (!strcmp(r, arginfo->argv)) {
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003510 if (arginfo->has_arg) {
Peter Maydell1386d4c2011-09-29 15:48:12 +01003511 if (optind >= argc) {
3512 usage();
3513 }
3514 arginfo->handle_opt(argv[optind]);
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003515 optind++;
Peter Maydell1386d4c2011-09-29 15:48:12 +01003516 } else {
3517 arginfo->handle_opt(NULL);
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003518 }
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003519 break;
3520 }
3521 }
3522
3523 /* no option matched the current argv */
3524 if (arginfo->handle_opt == NULL) {
3525 usage();
3526 }
3527 }
3528
3529 if (optind >= argc) {
3530 usage();
3531 }
3532
3533 filename = argv[optind];
3534 exec_path = argv[optind];
3535
3536 return optind;
3537}
3538
malc902b3d52008-12-10 19:18:40 +00003539int main(int argc, char **argv, char **envp)
bellard31e31b82003-02-18 22:55:36 +00003540{
bellard01ffc752003-02-18 23:00:51 +00003541 struct target_pt_regs regs1, *regs = &regs1;
bellard31e31b82003-02-18 22:55:36 +00003542 struct image_info info1, *info = &info1;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003543 struct linux_binprm bprm;
Nathan Froyd48e15fc2010-10-29 07:48:57 -07003544 TaskState *ts;
Andreas Färber9349b4f2012-03-14 01:38:32 +01003545 CPUArchState *env;
Andreas Färberdb6b81d2013-06-27 19:49:31 +02003546 CPUState *cpu;
bellard586314f2003-03-03 15:02:29 +00003547 int optind;
aurel3204a6dfe2009-01-30 19:59:17 +00003548 char **target_environ, **wrk;
aurel327d8cec92009-04-15 16:11:52 +00003549 char **target_argv;
3550 int target_argc;
aurel327d8cec92009-04-15 16:11:52 +00003551 int i;
Arnaud Patardfd4d81d2009-06-19 10:39:36 +03003552 int ret;
thsb12b6a12007-06-17 16:38:39 +00003553
Andreas Färberce008c12012-03-04 21:32:36 +01003554 module_call_init(MODULE_INIT_QOM);
3555
malc902b3d52008-12-10 19:18:40 +00003556 qemu_cache_utils_init(envp);
3557
aurel3204a6dfe2009-01-30 19:59:17 +00003558 if ((envlist = envlist_create()) == NULL) {
3559 (void) fprintf(stderr, "Unable to allocate envlist\n");
3560 exit(1);
3561 }
3562
3563 /* add current environment into the list */
3564 for (wrk = environ; *wrk != NULL; wrk++) {
3565 (void) envlist_setenv(envlist, *wrk);
3566 }
3567
Richard Henderson703e0e82010-03-19 14:21:13 -07003568 /* Read the stack limit from the kernel. If it's "unlimited",
3569 then we can do little else besides use the default. */
3570 {
3571 struct rlimit lim;
3572 if (getrlimit(RLIMIT_STACK, &lim) == 0
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09003573 && lim.rlim_cur != RLIM_INFINITY
3574 && lim.rlim_cur == (target_long)lim.rlim_cur) {
Richard Henderson703e0e82010-03-19 14:21:13 -07003575 guest_stack_size = lim.rlim_cur;
3576 }
3577 }
3578
j_mayerb1f9be32007-03-19 08:08:28 +00003579 cpu_model = NULL;
john cooperb5ec5ce2010-02-20 11:14:59 -06003580#if defined(cpudef_setup)
3581 cpudef_setup(); /* parse cpu definitions in target config file (TBD) */
3582#endif
3583
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003584 optind = parse_args(argc, argv);
Peter Maydell4b5dfd82011-07-18 11:44:09 +01003585
bellard31e31b82003-02-18 22:55:36 +00003586 /* Zero out regs */
bellard01ffc752003-02-18 23:00:51 +00003587 memset(regs, 0, sizeof(struct target_pt_regs));
bellard31e31b82003-02-18 22:55:36 +00003588
3589 /* Zero out image_info */
3590 memset(info, 0, sizeof(struct image_info));
3591
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003592 memset(&bprm, 0, sizeof (bprm));
3593
bellard74cd30b2003-04-11 00:13:41 +00003594 /* Scan interp_prefix dir for replacement files. */
3595 init_paths(interp_prefix);
3596
bellard46027c02007-11-08 13:56:19 +00003597 if (cpu_model == NULL) {
bellardaaed9092007-11-10 15:15:54 +00003598#if defined(TARGET_I386)
bellard46027c02007-11-08 13:56:19 +00003599#ifdef TARGET_X86_64
3600 cpu_model = "qemu64";
3601#else
3602 cpu_model = "qemu32";
3603#endif
bellardaaed9092007-11-10 15:15:54 +00003604#elif defined(TARGET_ARM)
pbrook088ab162009-04-09 15:20:50 +00003605 cpu_model = "any";
Guan Xuetaod2fbca92011-04-12 16:27:03 +08003606#elif defined(TARGET_UNICORE32)
3607 cpu_model = "any";
bellardaaed9092007-11-10 15:15:54 +00003608#elif defined(TARGET_M68K)
3609 cpu_model = "any";
3610#elif defined(TARGET_SPARC)
3611#ifdef TARGET_SPARC64
3612 cpu_model = "TI UltraSparc II";
3613#else
3614 cpu_model = "Fujitsu MB86904";
bellard46027c02007-11-08 13:56:19 +00003615#endif
bellardaaed9092007-11-10 15:15:54 +00003616#elif defined(TARGET_MIPS)
3617#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64)
3618 cpu_model = "20Kc";
3619#else
3620 cpu_model = "24Kf";
3621#endif
Jia Liud9627832012-07-20 15:50:52 +08003622#elif defined TARGET_OPENRISC
3623 cpu_model = "or1200";
bellardaaed9092007-11-10 15:15:54 +00003624#elif defined(TARGET_PPC)
bellard7ded4f52007-11-15 15:37:50 +00003625#ifdef TARGET_PPC64
Aurelien Jarnof7177932010-04-06 12:21:05 +02003626 cpu_model = "970fx";
bellard7ded4f52007-11-15 15:37:50 +00003627#else
bellardaaed9092007-11-10 15:15:54 +00003628 cpu_model = "750";
bellard7ded4f52007-11-15 15:37:50 +00003629#endif
bellardaaed9092007-11-10 15:15:54 +00003630#else
3631 cpu_model = "any";
3632#endif
3633 }
Jan Kiszkad5ab9712011-08-02 16:10:21 +02003634 tcg_exec_init(0);
3635 cpu_exec_init_all();
bellard83fb7ad2004-07-05 21:25:26 +00003636 /* NOTE: we need to init the CPU at this stage to get
3637 qemu_host_page_size */
bellardaaed9092007-11-10 15:15:54 +00003638 env = cpu_init(cpu_model);
3639 if (!env) {
3640 fprintf(stderr, "Unable to find CPU definition\n");
3641 exit(1);
3642 }
Andreas Färberdb6b81d2013-06-27 19:49:31 +02003643 cpu = ENV_GET_CPU(env);
Andreas Färber0ac46af2013-07-26 16:42:25 +02003644 cpu_reset(cpu);
Blue Swirlb55a37c2009-11-07 10:37:06 +00003645
Andreas Färberdb6b81d2013-06-27 19:49:31 +02003646 thread_cpu = cpu;
ths3b46e622007-09-17 08:09:54 +00003647
bellardb6741952007-11-11 14:46:06 +00003648 if (getenv("QEMU_STRACE")) {
3649 do_strace = 1;
thsb92c47c2007-11-01 00:07:38 +00003650 }
3651
aurel3204a6dfe2009-01-30 19:59:17 +00003652 target_environ = envlist_to_environ(envlist, NULL);
3653 envlist_free(envlist);
thsb12b6a12007-06-17 16:38:39 +00003654
Paul Brook379f6692009-07-17 12:48:08 +01003655#if defined(CONFIG_USE_GUEST_BASE)
3656 /*
3657 * Now that page sizes are configured in cpu_init() we can do
3658 * proper page alignment for guest_base.
3659 */
3660 guest_base = HOST_PAGE_ALIGN(guest_base);
Paul Brook68a1c812010-05-29 02:27:35 +01003661
Meador Inge806d1022012-07-26 16:50:02 +00003662 if (reserved_va || have_guest_base) {
3663 guest_base = init_guest_space(guest_base, reserved_va, 0,
3664 have_guest_base);
3665 if (guest_base == (unsigned long)-1) {
Peter Maydell097b8cb2012-08-20 11:36:32 +01003666 fprintf(stderr, "Unable to reserve 0x%lx bytes of virtual address "
3667 "space for use as guest address space (check your virtual "
3668 "memory ulimit setting or reserve less using -R option)\n",
3669 reserved_va);
Paul Brook68a1c812010-05-29 02:27:35 +01003670 exit(1);
3671 }
Dr. David Alan Gilbert97cc7562011-08-31 17:24:34 +01003672
Meador Inge806d1022012-07-26 16:50:02 +00003673 if (reserved_va) {
3674 mmap_next_start = reserved_va;
Dr. David Alan Gilbert97cc7562011-08-31 17:24:34 +01003675 }
3676 }
Richard Henderson14f24e12010-03-10 15:39:07 -08003677#endif /* CONFIG_USE_GUEST_BASE */
Paul Brook379f6692009-07-17 12:48:08 +01003678
3679 /*
3680 * Read in mmap_min_addr kernel parameter. This value is used
3681 * When loading the ELF image to determine whether guest_base
Richard Henderson14f24e12010-03-10 15:39:07 -08003682 * is needed. It is also used in mmap_find_vma.
Paul Brook379f6692009-07-17 12:48:08 +01003683 */
Richard Henderson14f24e12010-03-10 15:39:07 -08003684 {
Paul Brook379f6692009-07-17 12:48:08 +01003685 FILE *fp;
3686
3687 if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) {
3688 unsigned long tmp;
3689 if (fscanf(fp, "%lu", &tmp) == 1) {
3690 mmap_min_addr = tmp;
3691 qemu_log("host mmap_min_addr=0x%lx\n", mmap_min_addr);
3692 }
3693 fclose(fp);
3694 }
3695 }
Paul Brook379f6692009-07-17 12:48:08 +01003696
aurel327d8cec92009-04-15 16:11:52 +00003697 /*
3698 * Prepare copy of argv vector for target.
3699 */
3700 target_argc = argc - optind;
3701 target_argv = calloc(target_argc + 1, sizeof (char *));
3702 if (target_argv == NULL) {
3703 (void) fprintf(stderr, "Unable to allocate memory for target_argv\n");
3704 exit(1);
3705 }
3706
3707 /*
3708 * If argv0 is specified (using '-0' switch) we replace
3709 * argv[0] pointer with the given one.
3710 */
3711 i = 0;
3712 if (argv0 != NULL) {
3713 target_argv[i++] = strdup(argv0);
3714 }
3715 for (; i < target_argc; i++) {
3716 target_argv[i] = strdup(argv[optind + i]);
3717 }
3718 target_argv[target_argc] = NULL;
3719
Anthony Liguori7267c092011-08-20 22:09:37 -05003720 ts = g_malloc0 (sizeof(TaskState));
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003721 init_task_state(ts);
3722 /* build Task State */
3723 ts->info = info;
3724 ts->bprm = &bprm;
3725 env->opaque = ts;
3726 task_settid(ts);
3727
Arnaud Patardfd4d81d2009-06-19 10:39:36 +03003728 ret = loader_exec(filename, target_argv, target_environ, regs,
3729 info, &bprm);
3730 if (ret != 0) {
Peter Maydell885c1d12012-08-24 06:55:53 +00003731 printf("Error while loading %s: %s\n", filename, strerror(-ret));
thsb12b6a12007-06-17 16:38:39 +00003732 _exit(1);
3733 }
3734
3735 for (wrk = target_environ; *wrk; wrk++) {
3736 free(*wrk);
bellard31e31b82003-02-18 22:55:36 +00003737 }
ths3b46e622007-09-17 08:09:54 +00003738
thsb12b6a12007-06-17 16:38:39 +00003739 free(target_environ);
3740
blueswir12e77eac2009-01-20 16:57:34 +00003741 if (qemu_log_enabled()) {
Paul Brook379f6692009-07-17 12:48:08 +01003742#if defined(CONFIG_USE_GUEST_BASE)
3743 qemu_log("guest_base 0x%lx\n", guest_base);
3744#endif
blueswir12e77eac2009-01-20 16:57:34 +00003745 log_page_dump();
ths3b46e622007-09-17 08:09:54 +00003746
blueswir12e77eac2009-01-20 16:57:34 +00003747 qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk);
3748 qemu_log("end_code 0x" TARGET_ABI_FMT_lx "\n", info->end_code);
3749 qemu_log("start_code 0x" TARGET_ABI_FMT_lx "\n",
3750 info->start_code);
3751 qemu_log("start_data 0x" TARGET_ABI_FMT_lx "\n",
3752 info->start_data);
3753 qemu_log("end_data 0x" TARGET_ABI_FMT_lx "\n", info->end_data);
3754 qemu_log("start_stack 0x" TARGET_ABI_FMT_lx "\n",
3755 info->start_stack);
3756 qemu_log("brk 0x" TARGET_ABI_FMT_lx "\n", info->brk);
3757 qemu_log("entry 0x" TARGET_ABI_FMT_lx "\n", info->entry);
3758 }
bellard31e31b82003-02-18 22:55:36 +00003759
pbrook53a59602006-03-25 19:31:22 +00003760 target_set_brk(info->brk);
bellard31e31b82003-02-18 22:55:36 +00003761 syscall_init();
bellard66fb9762003-03-23 01:06:05 +00003762 signal_init();
bellard31e31b82003-02-18 22:55:36 +00003763
Richard Henderson9002ec72010-05-06 08:50:41 -07003764#if defined(CONFIG_USE_GUEST_BASE)
3765 /* Now that we've loaded the binary, GUEST_BASE is fixed. Delay
3766 generating the prologue until now so that the prologue can take
3767 the real value of GUEST_BASE into account. */
3768 tcg_prologue_init(&tcg_ctx);
3769#endif
3770
bellardb346ff42003-06-15 20:05:50 +00003771#if defined(TARGET_I386)
bellard2e255c62003-08-21 23:25:21 +00003772 cpu_x86_set_cpl(env, 3);
3773
bellard3802ce22003-07-26 18:02:28 +00003774 env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
bellard1bde4652005-01-12 22:34:47 +00003775 env->hflags |= HF_PE_MASK;
Eduardo Habkost0514ef22013-04-22 16:00:15 -03003776 if (env->features[FEAT_1_EDX] & CPUID_SSE) {
bellard1bde4652005-01-12 22:34:47 +00003777 env->cr[4] |= CR4_OSFXSR_MASK;
3778 env->hflags |= HF_OSFXSR_MASK;
3779 }
bellardd2fd1af2007-11-14 18:08:56 +00003780#ifndef TARGET_ABI32
bellard4dbc4222007-11-15 15:27:03 +00003781 /* enable 64 bit mode if possible */
Eduardo Habkost0514ef22013-04-22 16:00:15 -03003782 if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM)) {
bellard4dbc4222007-11-15 15:27:03 +00003783 fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n");
3784 exit(1);
3785 }
bellardd2fd1af2007-11-14 18:08:56 +00003786 env->cr[4] |= CR4_PAE_MASK;
bellard4dbc4222007-11-15 15:27:03 +00003787 env->efer |= MSR_EFER_LMA | MSR_EFER_LME;
bellardd2fd1af2007-11-14 18:08:56 +00003788 env->hflags |= HF_LMA_MASK;
3789#endif
bellard1bde4652005-01-12 22:34:47 +00003790
bellard415e5612004-02-03 23:37:12 +00003791 /* flags setup : we activate the IRQs by default as in user mode */
3792 env->eflags |= IF_MASK;
ths3b46e622007-09-17 08:09:54 +00003793
bellard6dbad632003-03-16 18:05:05 +00003794 /* linux register setup */
bellardd2fd1af2007-11-14 18:08:56 +00003795#ifndef TARGET_ABI32
j_mayer84409dd2007-04-06 08:56:50 +00003796 env->regs[R_EAX] = regs->rax;
3797 env->regs[R_EBX] = regs->rbx;
3798 env->regs[R_ECX] = regs->rcx;
3799 env->regs[R_EDX] = regs->rdx;
3800 env->regs[R_ESI] = regs->rsi;
3801 env->regs[R_EDI] = regs->rdi;
3802 env->regs[R_EBP] = regs->rbp;
3803 env->regs[R_ESP] = regs->rsp;
3804 env->eip = regs->rip;
3805#else
bellard0ecfa992003-03-03 14:32:43 +00003806 env->regs[R_EAX] = regs->eax;
3807 env->regs[R_EBX] = regs->ebx;
3808 env->regs[R_ECX] = regs->ecx;
3809 env->regs[R_EDX] = regs->edx;
3810 env->regs[R_ESI] = regs->esi;
3811 env->regs[R_EDI] = regs->edi;
3812 env->regs[R_EBP] = regs->ebp;
3813 env->regs[R_ESP] = regs->esp;
bellarddab2ed92003-03-22 15:23:14 +00003814 env->eip = regs->eip;
j_mayer84409dd2007-04-06 08:56:50 +00003815#endif
bellard31e31b82003-02-18 22:55:36 +00003816
bellardf4beb512003-05-27 23:28:08 +00003817 /* linux interrupt setup */
balroge4415702008-11-10 02:55:33 +00003818#ifndef TARGET_ABI32
3819 env->idt.limit = 511;
3820#else
3821 env->idt.limit = 255;
3822#endif
3823 env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1),
3824 PROT_READ|PROT_WRITE,
3825 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
3826 idt_table = g2h(env->idt.base);
bellardf4beb512003-05-27 23:28:08 +00003827 set_idt(0, 0);
3828 set_idt(1, 0);
3829 set_idt(2, 0);
3830 set_idt(3, 3);
3831 set_idt(4, 3);
bellardec95da62008-05-12 12:23:31 +00003832 set_idt(5, 0);
bellardf4beb512003-05-27 23:28:08 +00003833 set_idt(6, 0);
3834 set_idt(7, 0);
3835 set_idt(8, 0);
3836 set_idt(9, 0);
3837 set_idt(10, 0);
3838 set_idt(11, 0);
3839 set_idt(12, 0);
3840 set_idt(13, 0);
3841 set_idt(14, 0);
3842 set_idt(15, 0);
3843 set_idt(16, 0);
3844 set_idt(17, 0);
3845 set_idt(18, 0);
3846 set_idt(19, 0);
3847 set_idt(0x80, 3);
3848
bellard6dbad632003-03-16 18:05:05 +00003849 /* linux segment setup */
bellard8d18e892007-11-14 15:18:40 +00003850 {
3851 uint64_t *gdt_table;
balroge4415702008-11-10 02:55:33 +00003852 env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES,
3853 PROT_READ|PROT_WRITE,
3854 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
bellard8d18e892007-11-14 15:18:40 +00003855 env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1;
balroge4415702008-11-10 02:55:33 +00003856 gdt_table = g2h(env->gdt.base);
bellardd2fd1af2007-11-14 18:08:56 +00003857#ifdef TARGET_ABI32
bellard8d18e892007-11-14 15:18:40 +00003858 write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
3859 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
3860 (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
bellardd2fd1af2007-11-14 18:08:56 +00003861#else
3862 /* 64 bit code segment */
3863 write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
3864 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
3865 DESC_L_MASK |
3866 (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
3867#endif
bellard8d18e892007-11-14 15:18:40 +00003868 write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
3869 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
3870 (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
3871 }
bellard6dbad632003-03-16 18:05:05 +00003872 cpu_x86_load_seg(env, R_CS, __USER_CS);
bellardd2fd1af2007-11-14 18:08:56 +00003873 cpu_x86_load_seg(env, R_SS, __USER_DS);
3874#ifdef TARGET_ABI32
bellard6dbad632003-03-16 18:05:05 +00003875 cpu_x86_load_seg(env, R_DS, __USER_DS);
3876 cpu_x86_load_seg(env, R_ES, __USER_DS);
bellard6dbad632003-03-16 18:05:05 +00003877 cpu_x86_load_seg(env, R_FS, __USER_DS);
3878 cpu_x86_load_seg(env, R_GS, __USER_DS);
thsd6eb40f2007-06-21 22:55:02 +00003879 /* This hack makes Wine work... */
3880 env->segs[R_FS].selector = 0;
bellardd2fd1af2007-11-14 18:08:56 +00003881#else
3882 cpu_x86_load_seg(env, R_DS, 0);
3883 cpu_x86_load_seg(env, R_ES, 0);
3884 cpu_x86_load_seg(env, R_FS, 0);
3885 cpu_x86_load_seg(env, R_GS, 0);
3886#endif
bellardb346ff42003-06-15 20:05:50 +00003887#elif defined(TARGET_ARM)
3888 {
3889 int i;
bellardb5ff1b32005-11-26 10:38:39 +00003890 cpsr_write(env, regs->uregs[16], 0xffffffff);
bellardb346ff42003-06-15 20:05:50 +00003891 for(i = 0; i < 16; i++) {
3892 env->regs[i] = regs->uregs[i];
3893 }
Paul Brookd8fd2952012-03-30 18:02:50 +01003894 /* Enable BE8. */
3895 if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4
3896 && (info->elf_flags & EF_ARM_BE8)) {
3897 env->bswap_code = 1;
3898 }
bellardb346ff42003-06-15 20:05:50 +00003899 }
Guan Xuetaod2fbca92011-04-12 16:27:03 +08003900#elif defined(TARGET_UNICORE32)
3901 {
3902 int i;
3903 cpu_asr_write(env, regs->uregs[32], 0xffffffff);
3904 for (i = 0; i < 32; i++) {
3905 env->regs[i] = regs->uregs[i];
3906 }
3907 }
bellard93ac68b2003-09-30 20:57:29 +00003908#elif defined(TARGET_SPARC)
bellard060366c2004-01-04 15:50:01 +00003909 {
3910 int i;
3911 env->pc = regs->pc;
3912 env->npc = regs->npc;
3913 env->y = regs->y;
3914 for(i = 0; i < 8; i++)
3915 env->gregs[i] = regs->u_regs[i];
3916 for(i = 0; i < 8; i++)
3917 env->regwptr[i] = regs->u_regs[i + 8];
3918 }
bellard67867302003-11-23 17:05:30 +00003919#elif defined(TARGET_PPC)
3920 {
3921 int i;
bellard3fc6c082005-07-02 20:59:34 +00003922
j_mayer0411a972007-10-25 21:35:50 +00003923#if defined(TARGET_PPC64)
3924#if defined(TARGET_ABI32)
3925 env->msr &= ~((target_ulong)1 << MSR_SF);
j_mayere85e7c62007-10-18 19:59:49 +00003926#else
j_mayer0411a972007-10-25 21:35:50 +00003927 env->msr |= (target_ulong)1 << MSR_SF;
3928#endif
j_mayer84409dd2007-04-06 08:56:50 +00003929#endif
bellard67867302003-11-23 17:05:30 +00003930 env->nip = regs->nip;
3931 for(i = 0; i < 32; i++) {
3932 env->gpr[i] = regs->gpr[i];
3933 }
3934 }
pbrooke6e59062006-10-22 00:18:54 +00003935#elif defined(TARGET_M68K)
3936 {
pbrooke6e59062006-10-22 00:18:54 +00003937 env->pc = regs->pc;
3938 env->dregs[0] = regs->d0;
3939 env->dregs[1] = regs->d1;
3940 env->dregs[2] = regs->d2;
3941 env->dregs[3] = regs->d3;
3942 env->dregs[4] = regs->d4;
3943 env->dregs[5] = regs->d5;
3944 env->dregs[6] = regs->d6;
3945 env->dregs[7] = regs->d7;
3946 env->aregs[0] = regs->a0;
3947 env->aregs[1] = regs->a1;
3948 env->aregs[2] = regs->a2;
3949 env->aregs[3] = regs->a3;
3950 env->aregs[4] = regs->a4;
3951 env->aregs[5] = regs->a5;
3952 env->aregs[6] = regs->a6;
3953 env->aregs[7] = regs->usp;
3954 env->sr = regs->sr;
3955 ts->sim_syscalls = 1;
3956 }
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003957#elif defined(TARGET_MICROBLAZE)
3958 {
3959 env->regs[0] = regs->r0;
3960 env->regs[1] = regs->r1;
3961 env->regs[2] = regs->r2;
3962 env->regs[3] = regs->r3;
3963 env->regs[4] = regs->r4;
3964 env->regs[5] = regs->r5;
3965 env->regs[6] = regs->r6;
3966 env->regs[7] = regs->r7;
3967 env->regs[8] = regs->r8;
3968 env->regs[9] = regs->r9;
3969 env->regs[10] = regs->r10;
3970 env->regs[11] = regs->r11;
3971 env->regs[12] = regs->r12;
3972 env->regs[13] = regs->r13;
3973 env->regs[14] = regs->r14;
3974 env->regs[15] = regs->r15;
3975 env->regs[16] = regs->r16;
3976 env->regs[17] = regs->r17;
3977 env->regs[18] = regs->r18;
3978 env->regs[19] = regs->r19;
3979 env->regs[20] = regs->r20;
3980 env->regs[21] = regs->r21;
3981 env->regs[22] = regs->r22;
3982 env->regs[23] = regs->r23;
3983 env->regs[24] = regs->r24;
3984 env->regs[25] = regs->r25;
3985 env->regs[26] = regs->r26;
3986 env->regs[27] = regs->r27;
3987 env->regs[28] = regs->r28;
3988 env->regs[29] = regs->r29;
3989 env->regs[30] = regs->r30;
3990 env->regs[31] = regs->r31;
3991 env->sregs[SR_PC] = regs->pc;
3992 }
bellard048f6b42005-11-26 18:47:20 +00003993#elif defined(TARGET_MIPS)
3994 {
3995 int i;
3996
3997 for(i = 0; i < 32; i++) {
thsb5dc7732008-06-27 10:02:35 +00003998 env->active_tc.gpr[i] = regs->regs[i];
bellard048f6b42005-11-26 18:47:20 +00003999 }
Nathan Froyd0fddbbf2010-06-08 13:30:02 -07004000 env->active_tc.PC = regs->cp0_epc & ~(target_ulong)1;
4001 if (regs->cp0_epc & 1) {
4002 env->hflags |= MIPS_HFLAG_M16;
4003 }
bellard048f6b42005-11-26 18:47:20 +00004004 }
Jia Liud9627832012-07-20 15:50:52 +08004005#elif defined(TARGET_OPENRISC)
4006 {
4007 int i;
4008
4009 for (i = 0; i < 32; i++) {
4010 env->gpr[i] = regs->gpr[i];
4011 }
4012
4013 env->sr = regs->sr;
4014 env->pc = regs->pc;
4015 }
bellardfdf9b3e2006-04-27 21:07:38 +00004016#elif defined(TARGET_SH4)
4017 {
4018 int i;
4019
4020 for(i = 0; i < 16; i++) {
4021 env->gregs[i] = regs->regs[i];
4022 }
4023 env->pc = regs->pc;
4024 }
j_mayer7a3148a2007-04-05 07:13:51 +00004025#elif defined(TARGET_ALPHA)
4026 {
4027 int i;
4028
4029 for(i = 0; i < 28; i++) {
blueswir1992f48a2007-10-14 16:27:31 +00004030 env->ir[i] = ((abi_ulong *)regs)[i];
j_mayer7a3148a2007-04-05 07:13:51 +00004031 }
Richard Hendersondad081e2010-01-04 11:19:14 -08004032 env->ir[IR_SP] = regs->usp;
j_mayer7a3148a2007-04-05 07:13:51 +00004033 env->pc = regs->pc;
j_mayer7a3148a2007-04-05 07:13:51 +00004034 }
ths48733d12007-10-08 13:36:46 +00004035#elif defined(TARGET_CRIS)
4036 {
4037 env->regs[0] = regs->r0;
4038 env->regs[1] = regs->r1;
4039 env->regs[2] = regs->r2;
4040 env->regs[3] = regs->r3;
4041 env->regs[4] = regs->r4;
4042 env->regs[5] = regs->r5;
4043 env->regs[6] = regs->r6;
4044 env->regs[7] = regs->r7;
4045 env->regs[8] = regs->r8;
4046 env->regs[9] = regs->r9;
4047 env->regs[10] = regs->r10;
4048 env->regs[11] = regs->r11;
4049 env->regs[12] = regs->r12;
4050 env->regs[13] = regs->r13;
4051 env->regs[14] = info->start_stack;
4052 env->regs[15] = regs->acr;
4053 env->pc = regs->erp;
4054 }
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004055#elif defined(TARGET_S390X)
4056 {
4057 int i;
4058 for (i = 0; i < 16; i++) {
4059 env->regs[i] = regs->gprs[i];
4060 }
4061 env->psw.mask = regs->psw.mask;
4062 env->psw.addr = regs->psw.addr;
4063 }
bellardb346ff42003-06-15 20:05:50 +00004064#else
4065#error unsupported target CPU
4066#endif
bellard31e31b82003-02-18 22:55:36 +00004067
Guan Xuetaod2fbca92011-04-12 16:27:03 +08004068#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)
pbrooka87295e2007-05-26 15:09:38 +00004069 ts->stack_base = info->start_stack;
4070 ts->heap_base = info->brk;
4071 /* This will be filled in on the first SYS_HEAPINFO call. */
4072 ts->heap_limit = 0;
4073#endif
4074
bellard74c33be2005-10-30 21:01:05 +00004075 if (gdbstub_port) {
Peter Maydellff7a9812011-09-06 14:15:50 +01004076 if (gdbserver_start(gdbstub_port) < 0) {
4077 fprintf(stderr, "qemu: could not open gdbserver on port %d\n",
4078 gdbstub_port);
4079 exit(1);
4080 }
Andreas Färberdb6b81d2013-06-27 19:49:31 +02004081 gdb_handlesig(cpu, 0);
bellard1fddef42005-04-17 19:16:13 +00004082 }
bellard1b6b0292003-03-22 17:31:38 +00004083 cpu_loop(env);
4084 /* never exits */
bellard31e31b82003-02-18 22:55:36 +00004085 return 0;
4086}