blob: 20f9832d3899a901568cacc1b716b8357e5b05e8 [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;
Andreas Färber51fb2562013-07-02 18:26:11 +020045static const 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
Peter Maydell1861c452013-09-03 20:12:13 +0100452#ifdef TARGET_ABI32
453/* Commpage handling -- there is no commpage for AArch64 */
454
Dr. David Alan Gilbert97cc7562011-08-31 17:24:34 +0100455/*
456 * See the Linux kernel's Documentation/arm/kernel_user_helpers.txt
457 * Input:
458 * r0 = pointer to oldval
459 * r1 = pointer to newval
460 * r2 = pointer to target value
461 *
462 * Output:
463 * r0 = 0 if *ptr was changed, non-0 if no exchange happened
464 * C set if *ptr was changed, clear if no exchange happened
465 *
466 * Note segv's in kernel helpers are a bit tricky, we can set the
467 * data address sensibly but the PC address is just the entry point.
468 */
469static void arm_kernel_cmpxchg64_helper(CPUARMState *env)
470{
471 uint64_t oldval, newval, val;
472 uint32_t addr, cpsr;
473 target_siginfo_t info;
474
475 /* Based on the 32 bit code in do_kernel_trap */
476
477 /* XXX: This only works between threads, not between processes.
478 It's probably possible to implement this with native host
479 operations. However things like ldrex/strex are much harder so
480 there's not much point trying. */
481 start_exclusive();
482 cpsr = cpsr_read(env);
483 addr = env->regs[2];
484
485 if (get_user_u64(oldval, env->regs[0])) {
486 env->cp15.c6_data = env->regs[0];
487 goto segv;
488 };
489
490 if (get_user_u64(newval, env->regs[1])) {
491 env->cp15.c6_data = env->regs[1];
492 goto segv;
493 };
494
495 if (get_user_u64(val, addr)) {
496 env->cp15.c6_data = addr;
497 goto segv;
498 }
499
500 if (val == oldval) {
501 val = newval;
502
503 if (put_user_u64(val, addr)) {
504 env->cp15.c6_data = addr;
505 goto segv;
506 };
507
508 env->regs[0] = 0;
509 cpsr |= CPSR_C;
510 } else {
511 env->regs[0] = -1;
512 cpsr &= ~CPSR_C;
513 }
514 cpsr_write(env, cpsr, CPSR_C);
515 end_exclusive();
516 return;
517
518segv:
519 end_exclusive();
520 /* We get the PC of the entry address - which is as good as anything,
521 on a real kernel what you get depends on which mode it uses. */
522 info.si_signo = SIGSEGV;
523 info.si_errno = 0;
524 /* XXX: check env->error_code */
525 info.si_code = TARGET_SEGV_MAPERR;
526 info._sifields._sigfault._addr = env->cp15.c6_data;
527 queue_signal(env, info.si_signo, &info);
528
529 end_exclusive();
530}
531
pbrookfbb4a2e2008-05-29 00:20:44 +0000532/* Handle a jump to the kernel code page. */
533static int
534do_kernel_trap(CPUARMState *env)
535{
536 uint32_t addr;
537 uint32_t cpsr;
538 uint32_t val;
539
540 switch (env->regs[15]) {
541 case 0xffff0fa0: /* __kernel_memory_barrier */
542 /* ??? No-op. Will need to do better for SMP. */
543 break;
544 case 0xffff0fc0: /* __kernel_cmpxchg */
pbrookd5975362008-06-07 20:50:51 +0000545 /* XXX: This only works between threads, not between processes.
546 It's probably possible to implement this with native host
547 operations. However things like ldrex/strex are much harder so
548 there's not much point trying. */
549 start_exclusive();
pbrookfbb4a2e2008-05-29 00:20:44 +0000550 cpsr = cpsr_read(env);
551 addr = env->regs[2];
552 /* FIXME: This should SEGV if the access fails. */
553 if (get_user_u32(val, addr))
554 val = ~env->regs[0];
555 if (val == env->regs[0]) {
556 val = env->regs[1];
557 /* FIXME: Check for segfaults. */
558 put_user_u32(val, addr);
559 env->regs[0] = 0;
560 cpsr |= CPSR_C;
561 } else {
562 env->regs[0] = -1;
563 cpsr &= ~CPSR_C;
564 }
565 cpsr_write(env, cpsr, CPSR_C);
pbrookd5975362008-06-07 20:50:51 +0000566 end_exclusive();
pbrookfbb4a2e2008-05-29 00:20:44 +0000567 break;
568 case 0xffff0fe0: /* __kernel_get_tls */
Peter Maydelle4fe8302014-01-04 22:15:45 +0000569 env->regs[0] = env->cp15.tpidrro_el0;
pbrookfbb4a2e2008-05-29 00:20:44 +0000570 break;
Dr. David Alan Gilbert97cc7562011-08-31 17:24:34 +0100571 case 0xffff0f60: /* __kernel_cmpxchg64 */
572 arm_kernel_cmpxchg64_helper(env);
573 break;
574
pbrookfbb4a2e2008-05-29 00:20:44 +0000575 default:
576 return 1;
577 }
578 /* Jump back to the caller. */
579 addr = env->regs[14];
580 if (addr & 1) {
581 env->thumb = 1;
582 addr &= ~1;
583 }
584 env->regs[15] = addr;
585
586 return 0;
587}
Peter Maydell1861c452013-09-03 20:12:13 +0100588#endif
pbrookfbb4a2e2008-05-29 00:20:44 +0000589
Paul Brook426f5ab2009-11-22 21:35:13 +0000590static int do_strex(CPUARMState *env)
591{
Peter Maydell03d05e22014-01-04 22:15:47 +0000592 uint64_t val;
Paul Brook426f5ab2009-11-22 21:35:13 +0000593 int size;
594 int rc = 1;
595 int segv = 0;
596 uint32_t addr;
597 start_exclusive();
Peter Maydell03d05e22014-01-04 22:15:47 +0000598 if (env->exclusive_addr != env->exclusive_test) {
Paul Brook426f5ab2009-11-22 21:35:13 +0000599 goto fail;
600 }
Peter Maydell03d05e22014-01-04 22:15:47 +0000601 /* We know we're always AArch32 so the address is in uint32_t range
602 * unless it was the -1 exclusive-monitor-lost value (which won't
603 * match exclusive_test above).
604 */
605 assert(extract64(env->exclusive_addr, 32, 32) == 0);
606 addr = env->exclusive_addr;
Paul Brook426f5ab2009-11-22 21:35:13 +0000607 size = env->exclusive_info & 0xf;
608 switch (size) {
609 case 0:
610 segv = get_user_u8(val, addr);
611 break;
612 case 1:
613 segv = get_user_u16(val, addr);
614 break;
615 case 2:
616 case 3:
617 segv = get_user_u32(val, addr);
618 break;
Aurelien Jarnof7001a32009-12-24 00:17:12 +0100619 default:
620 abort();
Paul Brook426f5ab2009-11-22 21:35:13 +0000621 }
622 if (segv) {
623 env->cp15.c6_data = addr;
624 goto done;
625 }
Paul Brook426f5ab2009-11-22 21:35:13 +0000626 if (size == 3) {
Peter Maydell03d05e22014-01-04 22:15:47 +0000627 uint32_t valhi;
628 segv = get_user_u32(valhi, addr + 4);
Paul Brook426f5ab2009-11-22 21:35:13 +0000629 if (segv) {
630 env->cp15.c6_data = addr + 4;
631 goto done;
632 }
Peter Maydell03d05e22014-01-04 22:15:47 +0000633 val = deposit64(val, 32, 32, valhi);
Paul Brook426f5ab2009-11-22 21:35:13 +0000634 }
Peter Maydell03d05e22014-01-04 22:15:47 +0000635 if (val != env->exclusive_val) {
636 goto fail;
637 }
638
Paul Brook426f5ab2009-11-22 21:35:13 +0000639 val = env->regs[(env->exclusive_info >> 8) & 0xf];
640 switch (size) {
641 case 0:
642 segv = put_user_u8(val, addr);
643 break;
644 case 1:
645 segv = put_user_u16(val, addr);
646 break;
647 case 2:
648 case 3:
649 segv = put_user_u32(val, addr);
650 break;
651 }
652 if (segv) {
653 env->cp15.c6_data = addr;
654 goto done;
655 }
656 if (size == 3) {
657 val = env->regs[(env->exclusive_info >> 12) & 0xf];
Peter Maydell2c9adbd2010-12-07 15:37:34 +0000658 segv = put_user_u32(val, addr + 4);
Paul Brook426f5ab2009-11-22 21:35:13 +0000659 if (segv) {
660 env->cp15.c6_data = addr + 4;
661 goto done;
662 }
663 }
664 rc = 0;
665fail:
Paul Brook725b8a62009-12-11 15:38:10 +0000666 env->regs[15] += 4;
Paul Brook426f5ab2009-11-22 21:35:13 +0000667 env->regs[(env->exclusive_info >> 4) & 0xf] = rc;
668done:
669 end_exclusive();
670 return segv;
671}
672
Peter Maydell1861c452013-09-03 20:12:13 +0100673#ifdef TARGET_ABI32
bellardb346ff42003-06-15 20:05:50 +0000674void cpu_loop(CPUARMState *env)
675{
Andreas Färber0315c312012-12-17 07:34:52 +0100676 CPUState *cs = CPU(arm_env_get_cpu(env));
bellardb346ff42003-06-15 20:05:50 +0000677 int trapnr;
678 unsigned int n, insn;
Anthony Liguoric227f092009-10-01 16:12:16 -0500679 target_siginfo_t info;
bellardb5ff1b32005-11-26 10:38:39 +0000680 uint32_t addr;
ths3b46e622007-09-17 08:09:54 +0000681
bellardb346ff42003-06-15 20:05:50 +0000682 for(;;) {
Andreas Färber0315c312012-12-17 07:34:52 +0100683 cpu_exec_start(cs);
bellardb346ff42003-06-15 20:05:50 +0000684 trapnr = cpu_arm_exec(env);
Andreas Färber0315c312012-12-17 07:34:52 +0100685 cpu_exec_end(cs);
bellardb346ff42003-06-15 20:05:50 +0000686 switch(trapnr) {
687 case EXCP_UDEF:
bellardc6981052004-02-16 21:49:03 +0000688 {
689 TaskState *ts = env->opaque;
690 uint32_t opcode;
aurel326d9a42b2008-04-07 20:30:53 +0000691 int rc;
bellardc6981052004-02-16 21:49:03 +0000692
693 /* we handle the FPU emulation here, as Linux */
694 /* we get the opcode */
bellard2f619692007-11-16 10:46:05 +0000695 /* FIXME - what to do if get_user() fails? */
Paul Brookd8fd2952012-03-30 18:02:50 +0100696 get_user_code_u32(opcode, env->regs[15], env->bswap_code);
ths3b46e622007-09-17 08:09:54 +0000697
aurel326d9a42b2008-04-07 20:30:53 +0000698 rc = EmulateAll(opcode, &ts->fpa, env);
699 if (rc == 0) { /* illegal instruction */
bellardc6981052004-02-16 21:49:03 +0000700 info.si_signo = SIGILL;
701 info.si_errno = 0;
702 info.si_code = TARGET_ILL_ILLOPN;
703 info._sifields._sigfault._addr = env->regs[15];
pbrook624f7972008-05-31 16:11:38 +0000704 queue_signal(env, info.si_signo, &info);
aurel326d9a42b2008-04-07 20:30:53 +0000705 } else if (rc < 0) { /* FP exception */
706 int arm_fpe=0;
707
708 /* translate softfloat flags to FPSR flags */
709 if (-rc & float_flag_invalid)
710 arm_fpe |= BIT_IOC;
711 if (-rc & float_flag_divbyzero)
712 arm_fpe |= BIT_DZC;
713 if (-rc & float_flag_overflow)
714 arm_fpe |= BIT_OFC;
715 if (-rc & float_flag_underflow)
716 arm_fpe |= BIT_UFC;
717 if (-rc & float_flag_inexact)
718 arm_fpe |= BIT_IXC;
719
720 FPSR fpsr = ts->fpa.fpsr;
721 //printf("fpsr 0x%x, arm_fpe 0x%x\n",fpsr,arm_fpe);
722
723 if (fpsr & (arm_fpe << 16)) { /* exception enabled? */
724 info.si_signo = SIGFPE;
725 info.si_errno = 0;
726
727 /* ordered by priority, least first */
728 if (arm_fpe & BIT_IXC) info.si_code = TARGET_FPE_FLTRES;
729 if (arm_fpe & BIT_UFC) info.si_code = TARGET_FPE_FLTUND;
730 if (arm_fpe & BIT_OFC) info.si_code = TARGET_FPE_FLTOVF;
731 if (arm_fpe & BIT_DZC) info.si_code = TARGET_FPE_FLTDIV;
732 if (arm_fpe & BIT_IOC) info.si_code = TARGET_FPE_FLTINV;
733
734 info._sifields._sigfault._addr = env->regs[15];
pbrook624f7972008-05-31 16:11:38 +0000735 queue_signal(env, info.si_signo, &info);
aurel326d9a42b2008-04-07 20:30:53 +0000736 } else {
737 env->regs[15] += 4;
738 }
739
740 /* accumulate unenabled exceptions */
741 if ((!(fpsr & BIT_IXE)) && (arm_fpe & BIT_IXC))
742 fpsr |= BIT_IXC;
743 if ((!(fpsr & BIT_UFE)) && (arm_fpe & BIT_UFC))
744 fpsr |= BIT_UFC;
745 if ((!(fpsr & BIT_OFE)) && (arm_fpe & BIT_OFC))
746 fpsr |= BIT_OFC;
747 if ((!(fpsr & BIT_DZE)) && (arm_fpe & BIT_DZC))
748 fpsr |= BIT_DZC;
749 if ((!(fpsr & BIT_IOE)) && (arm_fpe & BIT_IOC))
750 fpsr |= BIT_IOC;
751 ts->fpa.fpsr=fpsr;
752 } else { /* everything OK */
bellardc6981052004-02-16 21:49:03 +0000753 /* increment PC */
754 env->regs[15] += 4;
755 }
756 }
bellardb346ff42003-06-15 20:05:50 +0000757 break;
758 case EXCP_SWI:
pbrook06c949e2006-02-04 19:35:26 +0000759 case EXCP_BKPT:
bellardb346ff42003-06-15 20:05:50 +0000760 {
pbrookce4defa2006-02-09 16:49:55 +0000761 env->eabi = 1;
bellardb346ff42003-06-15 20:05:50 +0000762 /* system call */
pbrook06c949e2006-02-04 19:35:26 +0000763 if (trapnr == EXCP_BKPT) {
764 if (env->thumb) {
bellard2f619692007-11-16 10:46:05 +0000765 /* FIXME - what to do if get_user() fails? */
Paul Brookd8fd2952012-03-30 18:02:50 +0100766 get_user_code_u16(insn, env->regs[15], env->bswap_code);
pbrook06c949e2006-02-04 19:35:26 +0000767 n = insn & 0xff;
768 env->regs[15] += 2;
769 } else {
bellard2f619692007-11-16 10:46:05 +0000770 /* FIXME - what to do if get_user() fails? */
Paul Brookd8fd2952012-03-30 18:02:50 +0100771 get_user_code_u32(insn, env->regs[15], env->bswap_code);
pbrook06c949e2006-02-04 19:35:26 +0000772 n = (insn & 0xf) | ((insn >> 4) & 0xff0);
773 env->regs[15] += 4;
774 }
bellard192c7bd2005-04-27 20:11:21 +0000775 } else {
pbrook06c949e2006-02-04 19:35:26 +0000776 if (env->thumb) {
bellard2f619692007-11-16 10:46:05 +0000777 /* FIXME - what to do if get_user() fails? */
Paul Brookd8fd2952012-03-30 18:02:50 +0100778 get_user_code_u16(insn, env->regs[15] - 2,
779 env->bswap_code);
pbrook06c949e2006-02-04 19:35:26 +0000780 n = insn & 0xff;
781 } else {
bellard2f619692007-11-16 10:46:05 +0000782 /* FIXME - what to do if get_user() fails? */
Paul Brookd8fd2952012-03-30 18:02:50 +0100783 get_user_code_u32(insn, env->regs[15] - 4,
784 env->bswap_code);
pbrook06c949e2006-02-04 19:35:26 +0000785 n = insn & 0xffffff;
786 }
bellard192c7bd2005-04-27 20:11:21 +0000787 }
788
bellard6f1f31c2004-04-25 18:00:45 +0000789 if (n == ARM_NR_cacheflush) {
Blue Swirldcfd14b2011-05-14 11:55:30 +0000790 /* nop */
bellarda4f81972005-04-23 18:25:41 +0000791 } else if (n == ARM_NR_semihosting
792 || n == ARM_NR_thumb_semihosting) {
793 env->regs[0] = do_arm_semihosting (env);
Alexander Graf3a1363a2012-05-29 05:30:26 +0000794 } else if (n == 0 || n >= ARM_SYSCALL_BASE || env->thumb) {
bellardb346ff42003-06-15 20:05:50 +0000795 /* linux syscall */
pbrookce4defa2006-02-09 16:49:55 +0000796 if (env->thumb || n == 0) {
bellard192c7bd2005-04-27 20:11:21 +0000797 n = env->regs[7];
798 } else {
799 n -= ARM_SYSCALL_BASE;
pbrookce4defa2006-02-09 16:49:55 +0000800 env->eabi = 0;
bellard192c7bd2005-04-27 20:11:21 +0000801 }
pbrookfbb4a2e2008-05-29 00:20:44 +0000802 if ( n > ARM_NR_BASE) {
803 switch (n) {
804 case ARM_NR_cacheflush:
Blue Swirldcfd14b2011-05-14 11:55:30 +0000805 /* nop */
pbrookfbb4a2e2008-05-29 00:20:44 +0000806 break;
807 case ARM_NR_set_tls:
808 cpu_set_tls(env, env->regs[0]);
809 env->regs[0] = 0;
810 break;
811 default:
812 gemu_log("qemu: Unsupported ARM syscall: 0x%x\n",
813 n);
814 env->regs[0] = -TARGET_ENOSYS;
815 break;
816 }
817 } else {
818 env->regs[0] = do_syscall(env,
819 n,
820 env->regs[0],
821 env->regs[1],
822 env->regs[2],
823 env->regs[3],
824 env->regs[4],
Peter Maydell5945cfc2011-06-16 17:37:13 +0100825 env->regs[5],
826 0, 0);
pbrookfbb4a2e2008-05-29 00:20:44 +0000827 }
bellardb346ff42003-06-15 20:05:50 +0000828 } else {
829 goto error;
830 }
831 }
832 break;
bellard43fff232003-07-09 19:31:39 +0000833 case EXCP_INTERRUPT:
834 /* just indicate that signals should be handled asap */
835 break;
bellard68016c62005-02-07 23:12:27 +0000836 case EXCP_PREFETCH_ABORT:
balrogeae473c2008-07-29 14:09:57 +0000837 addr = env->cp15.c6_insn;
bellardb5ff1b32005-11-26 10:38:39 +0000838 goto do_segv;
bellard68016c62005-02-07 23:12:27 +0000839 case EXCP_DATA_ABORT:
balrogeae473c2008-07-29 14:09:57 +0000840 addr = env->cp15.c6_data;
bellardb5ff1b32005-11-26 10:38:39 +0000841 do_segv:
bellard68016c62005-02-07 23:12:27 +0000842 {
843 info.si_signo = SIGSEGV;
844 info.si_errno = 0;
845 /* XXX: check env->error_code */
846 info.si_code = TARGET_SEGV_MAPERR;
bellardb5ff1b32005-11-26 10:38:39 +0000847 info._sifields._sigfault._addr = addr;
pbrook624f7972008-05-31 16:11:38 +0000848 queue_signal(env, info.si_signo, &info);
bellard68016c62005-02-07 23:12:27 +0000849 }
850 break;
bellard1fddef42005-04-17 19:16:13 +0000851 case EXCP_DEBUG:
852 {
853 int sig;
854
Andreas Färberdb6b81d2013-06-27 19:49:31 +0200855 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
bellard1fddef42005-04-17 19:16:13 +0000856 if (sig)
857 {
858 info.si_signo = sig;
859 info.si_errno = 0;
860 info.si_code = TARGET_TRAP_BRKPT;
pbrook624f7972008-05-31 16:11:38 +0000861 queue_signal(env, info.si_signo, &info);
bellard1fddef42005-04-17 19:16:13 +0000862 }
863 }
864 break;
pbrookfbb4a2e2008-05-29 00:20:44 +0000865 case EXCP_KERNEL_TRAP:
866 if (do_kernel_trap(env))
867 goto error;
868 break;
Paul Brook426f5ab2009-11-22 21:35:13 +0000869 case EXCP_STREX:
870 if (do_strex(env)) {
871 addr = env->cp15.c6_data;
872 goto do_segv;
873 }
Paul Brooke9273452009-11-24 13:10:08 +0000874 break;
bellardb346ff42003-06-15 20:05:50 +0000875 default:
876 error:
ths5fafdf22007-09-16 21:08:06 +0000877 fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
bellardb346ff42003-06-15 20:05:50 +0000878 trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +0200879 cpu_dump_state(cs, stderr, fprintf, 0);
bellardb346ff42003-06-15 20:05:50 +0000880 abort();
881 }
882 process_pending_signals(env);
883 }
884}
885
Peter Maydell1861c452013-09-03 20:12:13 +0100886#else
887
888/* AArch64 main loop */
889void cpu_loop(CPUARMState *env)
890{
891 CPUState *cs = CPU(arm_env_get_cpu(env));
892 int trapnr, sig;
893 target_siginfo_t info;
894 uint32_t addr;
895
896 for (;;) {
897 cpu_exec_start(cs);
898 trapnr = cpu_arm_exec(env);
899 cpu_exec_end(cs);
900
901 switch (trapnr) {
902 case EXCP_SWI:
903 env->xregs[0] = do_syscall(env,
904 env->xregs[8],
905 env->xregs[0],
906 env->xregs[1],
907 env->xregs[2],
908 env->xregs[3],
909 env->xregs[4],
910 env->xregs[5],
911 0, 0);
912 break;
913 case EXCP_INTERRUPT:
914 /* just indicate that signals should be handled asap */
915 break;
916 case EXCP_UDEF:
917 info.si_signo = SIGILL;
918 info.si_errno = 0;
919 info.si_code = TARGET_ILL_ILLOPN;
920 info._sifields._sigfault._addr = env->pc;
921 queue_signal(env, info.si_signo, &info);
922 break;
923 case EXCP_PREFETCH_ABORT:
924 addr = env->cp15.c6_insn;
925 goto do_segv;
926 case EXCP_DATA_ABORT:
927 addr = env->cp15.c6_data;
928 do_segv:
929 info.si_signo = SIGSEGV;
930 info.si_errno = 0;
931 /* XXX: check env->error_code */
932 info.si_code = TARGET_SEGV_MAPERR;
933 info._sifields._sigfault._addr = addr;
934 queue_signal(env, info.si_signo, &info);
935 break;
936 case EXCP_DEBUG:
937 case EXCP_BKPT:
938 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
939 if (sig) {
940 info.si_signo = sig;
941 info.si_errno = 0;
942 info.si_code = TARGET_TRAP_BRKPT;
943 queue_signal(env, info.si_signo, &info);
944 }
945 break;
946 case EXCP_STREX:
947 if (do_strex(env)) {
948 addr = env->cp15.c6_data;
949 goto do_segv;
950 }
951 break;
952 default:
953 fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
954 trapnr);
955 cpu_dump_state(cs, stderr, fprintf, 0);
956 abort();
957 }
958 process_pending_signals(env);
959 }
960}
961#endif /* ndef TARGET_ABI32 */
962
bellardb346ff42003-06-15 20:05:50 +0000963#endif
bellard1b6b0292003-03-22 17:31:38 +0000964
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800965#ifdef TARGET_UNICORE32
966
Andreas Färber05390242012-02-25 03:37:53 +0100967void cpu_loop(CPUUniCore32State *env)
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800968{
Andreas Färber0315c312012-12-17 07:34:52 +0100969 CPUState *cs = CPU(uc32_env_get_cpu(env));
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800970 int trapnr;
971 unsigned int n, insn;
972 target_siginfo_t info;
973
974 for (;;) {
Andreas Färber0315c312012-12-17 07:34:52 +0100975 cpu_exec_start(cs);
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800976 trapnr = uc32_cpu_exec(env);
Andreas Färber0315c312012-12-17 07:34:52 +0100977 cpu_exec_end(cs);
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800978 switch (trapnr) {
979 case UC32_EXCP_PRIV:
980 {
981 /* system call */
982 get_user_u32(insn, env->regs[31] - 4);
983 n = insn & 0xffffff;
984
985 if (n >= UC32_SYSCALL_BASE) {
986 /* linux syscall */
987 n -= UC32_SYSCALL_BASE;
988 if (n == UC32_SYSCALL_NR_set_tls) {
989 cpu_set_tls(env, env->regs[0]);
990 env->regs[0] = 0;
991 } else {
992 env->regs[0] = do_syscall(env,
993 n,
994 env->regs[0],
995 env->regs[1],
996 env->regs[2],
997 env->regs[3],
998 env->regs[4],
Peter Maydell5945cfc2011-06-16 17:37:13 +0100999 env->regs[5],
1000 0, 0);
Guan Xuetaod2fbca92011-04-12 16:27:03 +08001001 }
1002 } else {
1003 goto error;
1004 }
1005 }
1006 break;
Guan Xuetaod48813d2012-08-10 14:42:23 +08001007 case UC32_EXCP_DTRAP:
1008 case UC32_EXCP_ITRAP:
Guan Xuetaod2fbca92011-04-12 16:27:03 +08001009 info.si_signo = SIGSEGV;
1010 info.si_errno = 0;
1011 /* XXX: check env->error_code */
1012 info.si_code = TARGET_SEGV_MAPERR;
1013 info._sifields._sigfault._addr = env->cp0.c4_faultaddr;
1014 queue_signal(env, info.si_signo, &info);
1015 break;
1016 case EXCP_INTERRUPT:
1017 /* just indicate that signals should be handled asap */
1018 break;
1019 case EXCP_DEBUG:
1020 {
1021 int sig;
1022
Andreas Färberdb6b81d2013-06-27 19:49:31 +02001023 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
Guan Xuetaod2fbca92011-04-12 16:27:03 +08001024 if (sig) {
1025 info.si_signo = sig;
1026 info.si_errno = 0;
1027 info.si_code = TARGET_TRAP_BRKPT;
1028 queue_signal(env, info.si_signo, &info);
1029 }
1030 }
1031 break;
1032 default:
1033 goto error;
1034 }
1035 process_pending_signals(env);
1036 }
1037
1038error:
1039 fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +02001040 cpu_dump_state(cs, stderr, fprintf, 0);
Guan Xuetaod2fbca92011-04-12 16:27:03 +08001041 abort();
1042}
1043#endif
1044
bellard93ac68b2003-09-30 20:57:29 +00001045#ifdef TARGET_SPARC
blueswir1ed23fbd2008-08-30 09:20:21 +00001046#define SPARC64_STACK_BIAS 2047
bellard93ac68b2003-09-30 20:57:29 +00001047
bellard060366c2004-01-04 15:50:01 +00001048//#define DEBUG_WIN
1049
bellard2623cba2005-02-19 17:25:31 +00001050/* WARNING: dealing with register windows _is_ complicated. More info
1051 can be found at http://www.sics.se/~psm/sparcstack.html */
bellard060366c2004-01-04 15:50:01 +00001052static inline int get_reg_index(CPUSPARCState *env, int cwp, int index)
1053{
blueswir11a140262008-06-07 08:07:37 +00001054 index = (index + cwp * 16) % (16 * env->nwindows);
bellard060366c2004-01-04 15:50:01 +00001055 /* wrap handling : if cwp is on the last window, then we use the
1056 registers 'after' the end */
blueswir11a140262008-06-07 08:07:37 +00001057 if (index < 8 && env->cwp == env->nwindows - 1)
1058 index += 16 * env->nwindows;
bellard060366c2004-01-04 15:50:01 +00001059 return index;
1060}
1061
bellard2623cba2005-02-19 17:25:31 +00001062/* save the register window 'cwp1' */
1063static inline void save_window_offset(CPUSPARCState *env, int cwp1)
bellard060366c2004-01-04 15:50:01 +00001064{
bellard2623cba2005-02-19 17:25:31 +00001065 unsigned int i;
blueswir1992f48a2007-10-14 16:27:31 +00001066 abi_ulong sp_ptr;
ths3b46e622007-09-17 08:09:54 +00001067
pbrook53a59602006-03-25 19:31:22 +00001068 sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
blueswir1ed23fbd2008-08-30 09:20:21 +00001069#ifdef TARGET_SPARC64
1070 if (sp_ptr & 3)
1071 sp_ptr += SPARC64_STACK_BIAS;
1072#endif
bellard060366c2004-01-04 15:50:01 +00001073#if defined(DEBUG_WIN)
blueswir12daf0282008-06-15 18:02:48 +00001074 printf("win_overflow: sp_ptr=0x" TARGET_ABI_FMT_lx " save_cwp=%d\n",
1075 sp_ptr, cwp1);
bellard060366c2004-01-04 15:50:01 +00001076#endif
bellard2623cba2005-02-19 17:25:31 +00001077 for(i = 0; i < 16; i++) {
bellard2f619692007-11-16 10:46:05 +00001078 /* FIXME - what to do if put_user() fails? */
1079 put_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
blueswir1992f48a2007-10-14 16:27:31 +00001080 sp_ptr += sizeof(abi_ulong);
bellard2623cba2005-02-19 17:25:31 +00001081 }
bellard060366c2004-01-04 15:50:01 +00001082}
1083
1084static void save_window(CPUSPARCState *env)
1085{
bellard5ef54112006-07-18 21:14:09 +00001086#ifndef TARGET_SPARC64
bellard2623cba2005-02-19 17:25:31 +00001087 unsigned int new_wim;
blueswir11a140262008-06-07 08:07:37 +00001088 new_wim = ((env->wim >> 1) | (env->wim << (env->nwindows - 1))) &
1089 ((1LL << env->nwindows) - 1);
1090 save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
bellard2623cba2005-02-19 17:25:31 +00001091 env->wim = new_wim;
bellard5ef54112006-07-18 21:14:09 +00001092#else
blueswir11a140262008-06-07 08:07:37 +00001093 save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
bellard5ef54112006-07-18 21:14:09 +00001094 env->cansave++;
1095 env->canrestore--;
1096#endif
bellard060366c2004-01-04 15:50:01 +00001097}
1098
1099static void restore_window(CPUSPARCState *env)
1100{
blueswir1eda52952008-08-27 19:19:44 +00001101#ifndef TARGET_SPARC64
1102 unsigned int new_wim;
1103#endif
1104 unsigned int i, cwp1;
blueswir1992f48a2007-10-14 16:27:31 +00001105 abi_ulong sp_ptr;
ths3b46e622007-09-17 08:09:54 +00001106
blueswir1eda52952008-08-27 19:19:44 +00001107#ifndef TARGET_SPARC64
blueswir11a140262008-06-07 08:07:37 +00001108 new_wim = ((env->wim << 1) | (env->wim >> (env->nwindows - 1))) &
1109 ((1LL << env->nwindows) - 1);
blueswir1eda52952008-08-27 19:19:44 +00001110#endif
ths3b46e622007-09-17 08:09:54 +00001111
bellard060366c2004-01-04 15:50:01 +00001112 /* restore the invalid window */
blueswir11a140262008-06-07 08:07:37 +00001113 cwp1 = cpu_cwp_inc(env, env->cwp + 1);
pbrook53a59602006-03-25 19:31:22 +00001114 sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
blueswir1ed23fbd2008-08-30 09:20:21 +00001115#ifdef TARGET_SPARC64
1116 if (sp_ptr & 3)
1117 sp_ptr += SPARC64_STACK_BIAS;
1118#endif
bellard060366c2004-01-04 15:50:01 +00001119#if defined(DEBUG_WIN)
blueswir12daf0282008-06-15 18:02:48 +00001120 printf("win_underflow: sp_ptr=0x" TARGET_ABI_FMT_lx " load_cwp=%d\n",
1121 sp_ptr, cwp1);
bellard060366c2004-01-04 15:50:01 +00001122#endif
bellard2623cba2005-02-19 17:25:31 +00001123 for(i = 0; i < 16; i++) {
bellard2f619692007-11-16 10:46:05 +00001124 /* FIXME - what to do if get_user() fails? */
1125 get_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
blueswir1992f48a2007-10-14 16:27:31 +00001126 sp_ptr += sizeof(abi_ulong);
bellard2623cba2005-02-19 17:25:31 +00001127 }
bellard5ef54112006-07-18 21:14:09 +00001128#ifdef TARGET_SPARC64
1129 env->canrestore++;
blueswir11a140262008-06-07 08:07:37 +00001130 if (env->cleanwin < env->nwindows - 1)
1131 env->cleanwin++;
bellard5ef54112006-07-18 21:14:09 +00001132 env->cansave--;
blueswir1eda52952008-08-27 19:19:44 +00001133#else
1134 env->wim = new_wim;
bellard5ef54112006-07-18 21:14:09 +00001135#endif
bellard060366c2004-01-04 15:50:01 +00001136}
1137
1138static void flush_windows(CPUSPARCState *env)
1139{
1140 int offset, cwp1;
bellard2623cba2005-02-19 17:25:31 +00001141
1142 offset = 1;
bellard060366c2004-01-04 15:50:01 +00001143 for(;;) {
1144 /* if restore would invoke restore_window(), then we can stop */
blueswir11a140262008-06-07 08:07:37 +00001145 cwp1 = cpu_cwp_inc(env, env->cwp + offset);
blueswir1eda52952008-08-27 19:19:44 +00001146#ifndef TARGET_SPARC64
bellard060366c2004-01-04 15:50:01 +00001147 if (env->wim & (1 << cwp1))
1148 break;
blueswir1eda52952008-08-27 19:19:44 +00001149#else
1150 if (env->canrestore == 0)
1151 break;
1152 env->cansave++;
1153 env->canrestore--;
1154#endif
bellard2623cba2005-02-19 17:25:31 +00001155 save_window_offset(env, cwp1);
bellard060366c2004-01-04 15:50:01 +00001156 offset++;
1157 }
blueswir11a140262008-06-07 08:07:37 +00001158 cwp1 = cpu_cwp_inc(env, env->cwp + 1);
blueswir1eda52952008-08-27 19:19:44 +00001159#ifndef TARGET_SPARC64
1160 /* set wim so that restore will reload the registers */
bellard2623cba2005-02-19 17:25:31 +00001161 env->wim = 1 << cwp1;
blueswir1eda52952008-08-27 19:19:44 +00001162#endif
bellard2623cba2005-02-19 17:25:31 +00001163#if defined(DEBUG_WIN)
1164 printf("flush_windows: nb=%d\n", offset - 1);
bellard80a9d032005-01-03 23:31:27 +00001165#endif
bellard2623cba2005-02-19 17:25:31 +00001166}
bellard060366c2004-01-04 15:50:01 +00001167
bellard93ac68b2003-09-30 20:57:29 +00001168void cpu_loop (CPUSPARCState *env)
1169{
Andreas Färber878096e2013-05-27 01:33:50 +02001170 CPUState *cs = CPU(sparc_env_get_cpu(env));
Richard Henderson2cc20262010-04-25 11:01:25 -07001171 int trapnr;
1172 abi_long ret;
Anthony Liguoric227f092009-10-01 16:12:16 -05001173 target_siginfo_t info;
ths3b46e622007-09-17 08:09:54 +00001174
bellard060366c2004-01-04 15:50:01 +00001175 while (1) {
1176 trapnr = cpu_sparc_exec (env);
ths3b46e622007-09-17 08:09:54 +00001177
Richard Henderson20132b92012-10-09 14:50:00 -07001178 /* Compute PSR before exposing state. */
1179 if (env->cc_op != CC_OP_FLAGS) {
1180 cpu_get_psr(env);
1181 }
1182
bellard060366c2004-01-04 15:50:01 +00001183 switch (trapnr) {
bellard5ef54112006-07-18 21:14:09 +00001184#ifndef TARGET_SPARC64
ths5fafdf22007-09-16 21:08:06 +00001185 case 0x88:
bellard060366c2004-01-04 15:50:01 +00001186 case 0x90:
bellard5ef54112006-07-18 21:14:09 +00001187#else
blueswir1cb33da52007-10-09 16:34:29 +00001188 case 0x110:
bellard5ef54112006-07-18 21:14:09 +00001189 case 0x16d:
1190#endif
bellard060366c2004-01-04 15:50:01 +00001191 ret = do_syscall (env, env->gregs[1],
ths5fafdf22007-09-16 21:08:06 +00001192 env->regwptr[0], env->regwptr[1],
1193 env->regwptr[2], env->regwptr[3],
Peter Maydell5945cfc2011-06-16 17:37:13 +01001194 env->regwptr[4], env->regwptr[5],
1195 0, 0);
Richard Henderson2cc20262010-04-25 11:01:25 -07001196 if ((abi_ulong)ret >= (abi_ulong)(-515)) {
blueswir1992f48a2007-10-14 16:27:31 +00001197#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
bellard27908722006-10-23 21:31:01 +00001198 env->xcc |= PSR_CARRY;
1199#else
bellard060366c2004-01-04 15:50:01 +00001200 env->psr |= PSR_CARRY;
bellard27908722006-10-23 21:31:01 +00001201#endif
bellard060366c2004-01-04 15:50:01 +00001202 ret = -ret;
1203 } else {
blueswir1992f48a2007-10-14 16:27:31 +00001204#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
bellard27908722006-10-23 21:31:01 +00001205 env->xcc &= ~PSR_CARRY;
1206#else
bellard060366c2004-01-04 15:50:01 +00001207 env->psr &= ~PSR_CARRY;
bellard27908722006-10-23 21:31:01 +00001208#endif
bellard060366c2004-01-04 15:50:01 +00001209 }
1210 env->regwptr[0] = ret;
1211 /* next instruction */
1212 env->pc = env->npc;
1213 env->npc = env->npc + 4;
1214 break;
1215 case 0x83: /* flush windows */
blueswir1992f48a2007-10-14 16:27:31 +00001216#ifdef TARGET_ABI32
1217 case 0x103:
1218#endif
bellard2623cba2005-02-19 17:25:31 +00001219 flush_windows(env);
bellard060366c2004-01-04 15:50:01 +00001220 /* next instruction */
1221 env->pc = env->npc;
1222 env->npc = env->npc + 4;
1223 break;
bellard34751872005-07-02 14:31:34 +00001224#ifndef TARGET_SPARC64
bellard060366c2004-01-04 15:50:01 +00001225 case TT_WIN_OVF: /* window overflow */
1226 save_window(env);
1227 break;
1228 case TT_WIN_UNF: /* window underflow */
1229 restore_window(env);
1230 break;
bellard61ff6f52005-02-15 22:54:53 +00001231 case TT_TFAULT:
1232 case TT_DFAULT:
1233 {
Richard Henderson59f71822011-10-25 10:34:07 -07001234 info.si_signo = TARGET_SIGSEGV;
bellard61ff6f52005-02-15 22:54:53 +00001235 info.si_errno = 0;
1236 /* XXX: check env->error_code */
1237 info.si_code = TARGET_SEGV_MAPERR;
1238 info._sifields._sigfault._addr = env->mmuregs[4];
pbrook624f7972008-05-31 16:11:38 +00001239 queue_signal(env, info.si_signo, &info);
bellard61ff6f52005-02-15 22:54:53 +00001240 }
1241 break;
bellard34751872005-07-02 14:31:34 +00001242#else
bellard5ef54112006-07-18 21:14:09 +00001243 case TT_SPILL: /* window overflow */
1244 save_window(env);
1245 break;
1246 case TT_FILL: /* window underflow */
1247 restore_window(env);
1248 break;
blueswir17f84a722007-07-07 20:46:41 +00001249 case TT_TFAULT:
1250 case TT_DFAULT:
1251 {
Richard Henderson59f71822011-10-25 10:34:07 -07001252 info.si_signo = TARGET_SIGSEGV;
blueswir17f84a722007-07-07 20:46:41 +00001253 info.si_errno = 0;
1254 /* XXX: check env->error_code */
1255 info.si_code = TARGET_SEGV_MAPERR;
1256 if (trapnr == TT_DFAULT)
1257 info._sifields._sigfault._addr = env->dmmuregs[4];
1258 else
Igor Kovalenko8194f352009-08-03 23:15:02 +04001259 info._sifields._sigfault._addr = cpu_tsptr(env)->tpc;
pbrook624f7972008-05-31 16:11:38 +00001260 queue_signal(env, info.si_signo, &info);
blueswir17f84a722007-07-07 20:46:41 +00001261 }
1262 break;
bellard27524dc2007-11-11 19:32:52 +00001263#ifndef TARGET_ABI32
blueswir15bfb56b2007-10-05 17:01:51 +00001264 case 0x16e:
1265 flush_windows(env);
1266 sparc64_get_context(env);
1267 break;
1268 case 0x16f:
1269 flush_windows(env);
1270 sparc64_set_context(env);
1271 break;
bellard34751872005-07-02 14:31:34 +00001272#endif
bellard27524dc2007-11-11 19:32:52 +00001273#endif
bellard48dc41e2006-06-21 18:15:50 +00001274 case EXCP_INTERRUPT:
1275 /* just indicate that signals should be handled asap */
1276 break;
Richard Henderson75f22e42011-10-25 10:34:06 -07001277 case TT_ILL_INSN:
1278 {
1279 info.si_signo = TARGET_SIGILL;
1280 info.si_errno = 0;
1281 info.si_code = TARGET_ILL_ILLOPC;
1282 info._sifields._sigfault._addr = env->pc;
1283 queue_signal(env, info.si_signo, &info);
1284 }
1285 break;
bellard1fddef42005-04-17 19:16:13 +00001286 case EXCP_DEBUG:
1287 {
1288 int sig;
1289
Andreas Färberdb6b81d2013-06-27 19:49:31 +02001290 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
bellard1fddef42005-04-17 19:16:13 +00001291 if (sig)
1292 {
1293 info.si_signo = sig;
1294 info.si_errno = 0;
1295 info.si_code = TARGET_TRAP_BRKPT;
pbrook624f7972008-05-31 16:11:38 +00001296 queue_signal(env, info.si_signo, &info);
bellard1fddef42005-04-17 19:16:13 +00001297 }
1298 }
1299 break;
bellard060366c2004-01-04 15:50:01 +00001300 default:
1301 printf ("Unhandled trap: 0x%x\n", trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +02001302 cpu_dump_state(cs, stderr, fprintf, 0);
bellard060366c2004-01-04 15:50:01 +00001303 exit (1);
1304 }
1305 process_pending_signals (env);
1306 }
bellard93ac68b2003-09-30 20:57:29 +00001307}
1308
1309#endif
1310
bellard67867302003-11-23 17:05:30 +00001311#ifdef TARGET_PPC
Andreas Färber05390242012-02-25 03:37:53 +01001312static inline uint64_t cpu_ppc_get_tb(CPUPPCState *env)
bellard9fddaa02004-05-21 12:59:32 +00001313{
1314 /* TO FIX */
1315 return 0;
1316}
ths3b46e622007-09-17 08:09:54 +00001317
Andreas Färber05390242012-02-25 03:37:53 +01001318uint64_t cpu_ppc_load_tbl(CPUPPCState *env)
bellard9fddaa02004-05-21 12:59:32 +00001319{
Alexander Grafe3ea6522009-12-21 12:24:17 +01001320 return cpu_ppc_get_tb(env);
bellard9fddaa02004-05-21 12:59:32 +00001321}
ths3b46e622007-09-17 08:09:54 +00001322
Andreas Färber05390242012-02-25 03:37:53 +01001323uint32_t cpu_ppc_load_tbu(CPUPPCState *env)
bellard9fddaa02004-05-21 12:59:32 +00001324{
1325 return cpu_ppc_get_tb(env) >> 32;
1326}
ths3b46e622007-09-17 08:09:54 +00001327
Andreas Färber05390242012-02-25 03:37:53 +01001328uint64_t cpu_ppc_load_atbl(CPUPPCState *env)
bellard9fddaa02004-05-21 12:59:32 +00001329{
Aurelien Jarnob711de92009-12-21 13:52:08 +01001330 return cpu_ppc_get_tb(env);
bellard9fddaa02004-05-21 12:59:32 +00001331}
1332
Andreas Färber05390242012-02-25 03:37:53 +01001333uint32_t cpu_ppc_load_atbu(CPUPPCState *env)
bellard9fddaa02004-05-21 12:59:32 +00001334{
j_mayera062e362007-09-30 00:38:38 +00001335 return cpu_ppc_get_tb(env) >> 32;
bellard9fddaa02004-05-21 12:59:32 +00001336}
ths5fafdf22007-09-16 21:08:06 +00001337
Andreas Färber05390242012-02-25 03:37:53 +01001338uint32_t cpu_ppc601_load_rtcu(CPUPPCState *env)
j_mayer76a66252007-03-07 08:32:30 +00001339__attribute__ (( alias ("cpu_ppc_load_tbu") ));
1340
Andreas Färber05390242012-02-25 03:37:53 +01001341uint32_t cpu_ppc601_load_rtcl(CPUPPCState *env)
bellard9fddaa02004-05-21 12:59:32 +00001342{
j_mayer76a66252007-03-07 08:32:30 +00001343 return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
bellard9fddaa02004-05-21 12:59:32 +00001344}
j_mayer76a66252007-03-07 08:32:30 +00001345
j_mayera750fc02007-09-26 23:54:22 +00001346/* XXX: to be fixed */
Alexander Graf73b01962009-12-21 14:02:39 +01001347int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp)
j_mayera750fc02007-09-26 23:54:22 +00001348{
1349 return -1;
1350}
1351
Alexander Graf73b01962009-12-21 14:02:39 +01001352int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val)
j_mayera750fc02007-09-26 23:54:22 +00001353{
1354 return -1;
1355}
1356
Blue Swirl001faf32009-05-13 17:53:17 +00001357#define EXCP_DUMP(env, fmt, ...) \
1358do { \
Andreas Färbera0762852013-06-16 07:28:50 +02001359 CPUState *cs = ENV_GET_CPU(env); \
Blue Swirl001faf32009-05-13 17:53:17 +00001360 fprintf(stderr, fmt , ## __VA_ARGS__); \
Andreas Färbera0762852013-06-16 07:28:50 +02001361 cpu_dump_state(cs, stderr, fprintf, 0); \
Blue Swirl001faf32009-05-13 17:53:17 +00001362 qemu_log(fmt, ## __VA_ARGS__); \
Blue Swirleeacee42012-06-03 16:35:32 +00001363 if (qemu_log_enabled()) { \
Andreas Färbera0762852013-06-16 07:28:50 +02001364 log_cpu_state(cs, 0); \
Blue Swirleeacee42012-06-03 16:35:32 +00001365 } \
j_mayere1833e12007-09-29 13:06:16 +00001366} while (0)
1367
Nathan Froyd56f066b2009-08-03 08:43:27 -07001368static int do_store_exclusive(CPUPPCState *env)
1369{
1370 target_ulong addr;
1371 target_ulong page_addr;
1372 target_ulong val;
1373 int flags;
1374 int segv = 0;
1375
1376 addr = env->reserve_ea;
1377 page_addr = addr & TARGET_PAGE_MASK;
1378 start_exclusive();
1379 mmap_lock();
1380 flags = page_get_flags(page_addr);
1381 if ((flags & PAGE_READ) == 0) {
1382 segv = 1;
1383 } else {
1384 int reg = env->reserve_info & 0x1f;
1385 int size = (env->reserve_info >> 5) & 0xf;
1386 int stored = 0;
1387
1388 if (addr == env->reserve_addr) {
1389 switch (size) {
1390 case 1: segv = get_user_u8(val, addr); break;
1391 case 2: segv = get_user_u16(val, addr); break;
1392 case 4: segv = get_user_u32(val, addr); break;
1393#if defined(TARGET_PPC64)
1394 case 8: segv = get_user_u64(val, addr); break;
1395#endif
1396 default: abort();
1397 }
1398 if (!segv && val == env->reserve_val) {
1399 val = env->gpr[reg];
1400 switch (size) {
1401 case 1: segv = put_user_u8(val, addr); break;
1402 case 2: segv = put_user_u16(val, addr); break;
1403 case 4: segv = put_user_u32(val, addr); break;
1404#if defined(TARGET_PPC64)
1405 case 8: segv = put_user_u64(val, addr); break;
1406#endif
1407 default: abort();
1408 }
1409 if (!segv) {
1410 stored = 1;
1411 }
1412 }
1413 }
1414 env->crf[0] = (stored << 1) | xer_so;
1415 env->reserve_addr = (target_ulong)-1;
1416 }
1417 if (!segv) {
1418 env->nip += 4;
1419 }
1420 mmap_unlock();
1421 end_exclusive();
1422 return segv;
1423}
1424
bellard67867302003-11-23 17:05:30 +00001425void cpu_loop(CPUPPCState *env)
1426{
Andreas Färber0315c312012-12-17 07:34:52 +01001427 CPUState *cs = CPU(ppc_env_get_cpu(env));
Anthony Liguoric227f092009-10-01 16:12:16 -05001428 target_siginfo_t info;
bellard61190b12004-01-04 23:54:31 +00001429 int trapnr;
Richard Henderson9e0e2f92011-10-26 09:59:18 -07001430 target_ulong ret;
ths3b46e622007-09-17 08:09:54 +00001431
bellard67867302003-11-23 17:05:30 +00001432 for(;;) {
Andreas Färber0315c312012-12-17 07:34:52 +01001433 cpu_exec_start(cs);
bellard67867302003-11-23 17:05:30 +00001434 trapnr = cpu_ppc_exec(env);
Andreas Färber0315c312012-12-17 07:34:52 +01001435 cpu_exec_end(cs);
bellard67867302003-11-23 17:05:30 +00001436 switch(trapnr) {
j_mayere1833e12007-09-29 13:06:16 +00001437 case POWERPC_EXCP_NONE:
1438 /* Just go on */
bellard67867302003-11-23 17:05:30 +00001439 break;
j_mayere1833e12007-09-29 13:06:16 +00001440 case POWERPC_EXCP_CRITICAL: /* Critical input */
1441 cpu_abort(env, "Critical interrupt while in user mode. "
1442 "Aborting\n");
1443 break;
1444 case POWERPC_EXCP_MCHECK: /* Machine check exception */
1445 cpu_abort(env, "Machine check exception while in user mode. "
1446 "Aborting\n");
1447 break;
1448 case POWERPC_EXCP_DSI: /* Data storage exception */
Blue Swirl90e189e2009-08-16 11:13:18 +00001449 EXCP_DUMP(env, "Invalid data memory access: 0x" TARGET_FMT_lx "\n",
j_mayere1833e12007-09-29 13:06:16 +00001450 env->spr[SPR_DAR]);
1451 /* XXX: check this. Seems bugged */
1452 switch (env->error_code & 0xFF000000) {
1453 case 0x40000000:
1454 info.si_signo = TARGET_SIGSEGV;
1455 info.si_errno = 0;
1456 info.si_code = TARGET_SEGV_MAPERR;
1457 break;
1458 case 0x04000000:
1459 info.si_signo = TARGET_SIGILL;
1460 info.si_errno = 0;
1461 info.si_code = TARGET_ILL_ILLADR;
1462 break;
1463 case 0x08000000:
1464 info.si_signo = TARGET_SIGSEGV;
1465 info.si_errno = 0;
1466 info.si_code = TARGET_SEGV_ACCERR;
1467 break;
1468 default:
1469 /* Let's send a regular segfault... */
1470 EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
1471 env->error_code);
1472 info.si_signo = TARGET_SIGSEGV;
1473 info.si_errno = 0;
1474 info.si_code = TARGET_SEGV_MAPERR;
1475 break;
1476 }
1477 info._sifields._sigfault._addr = env->nip;
pbrook624f7972008-05-31 16:11:38 +00001478 queue_signal(env, info.si_signo, &info);
j_mayere1833e12007-09-29 13:06:16 +00001479 break;
1480 case POWERPC_EXCP_ISI: /* Instruction storage exception */
Blue Swirl90e189e2009-08-16 11:13:18 +00001481 EXCP_DUMP(env, "Invalid instruction fetch: 0x\n" TARGET_FMT_lx
1482 "\n", env->spr[SPR_SRR0]);
j_mayere1833e12007-09-29 13:06:16 +00001483 /* XXX: check this */
1484 switch (env->error_code & 0xFF000000) {
1485 case 0x40000000:
1486 info.si_signo = TARGET_SIGSEGV;
1487 info.si_errno = 0;
1488 info.si_code = TARGET_SEGV_MAPERR;
1489 break;
1490 case 0x10000000:
1491 case 0x08000000:
1492 info.si_signo = TARGET_SIGSEGV;
1493 info.si_errno = 0;
1494 info.si_code = TARGET_SEGV_ACCERR;
1495 break;
1496 default:
1497 /* Let's send a regular segfault... */
1498 EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
1499 env->error_code);
1500 info.si_signo = TARGET_SIGSEGV;
1501 info.si_errno = 0;
1502 info.si_code = TARGET_SEGV_MAPERR;
1503 break;
1504 }
1505 info._sifields._sigfault._addr = env->nip - 4;
pbrook624f7972008-05-31 16:11:38 +00001506 queue_signal(env, info.si_signo, &info);
j_mayere1833e12007-09-29 13:06:16 +00001507 break;
1508 case POWERPC_EXCP_EXTERNAL: /* External input */
1509 cpu_abort(env, "External interrupt while in user mode. "
1510 "Aborting\n");
1511 break;
1512 case POWERPC_EXCP_ALIGN: /* Alignment exception */
1513 EXCP_DUMP(env, "Unaligned memory access\n");
1514 /* XXX: check this */
1515 info.si_signo = TARGET_SIGBUS;
1516 info.si_errno = 0;
1517 info.si_code = TARGET_BUS_ADRALN;
1518 info._sifields._sigfault._addr = env->nip - 4;
pbrook624f7972008-05-31 16:11:38 +00001519 queue_signal(env, info.si_signo, &info);
j_mayere1833e12007-09-29 13:06:16 +00001520 break;
1521 case POWERPC_EXCP_PROGRAM: /* Program exception */
1522 /* XXX: check this */
1523 switch (env->error_code & ~0xF) {
1524 case POWERPC_EXCP_FP:
1525 EXCP_DUMP(env, "Floating point program exception\n");
j_mayere1833e12007-09-29 13:06:16 +00001526 info.si_signo = TARGET_SIGFPE;
1527 info.si_errno = 0;
1528 switch (env->error_code & 0xF) {
1529 case POWERPC_EXCP_FP_OX:
1530 info.si_code = TARGET_FPE_FLTOVF;
1531 break;
1532 case POWERPC_EXCP_FP_UX:
1533 info.si_code = TARGET_FPE_FLTUND;
1534 break;
1535 case POWERPC_EXCP_FP_ZX:
1536 case POWERPC_EXCP_FP_VXZDZ:
1537 info.si_code = TARGET_FPE_FLTDIV;
1538 break;
1539 case POWERPC_EXCP_FP_XX:
1540 info.si_code = TARGET_FPE_FLTRES;
1541 break;
1542 case POWERPC_EXCP_FP_VXSOFT:
1543 info.si_code = TARGET_FPE_FLTINV;
1544 break;
j_mayer7c580442007-10-27 17:54:30 +00001545 case POWERPC_EXCP_FP_VXSNAN:
j_mayere1833e12007-09-29 13:06:16 +00001546 case POWERPC_EXCP_FP_VXISI:
1547 case POWERPC_EXCP_FP_VXIDI:
1548 case POWERPC_EXCP_FP_VXIMZ:
1549 case POWERPC_EXCP_FP_VXVC:
1550 case POWERPC_EXCP_FP_VXSQRT:
1551 case POWERPC_EXCP_FP_VXCVI:
1552 info.si_code = TARGET_FPE_FLTSUB;
1553 break;
1554 default:
1555 EXCP_DUMP(env, "Unknown floating point exception (%02x)\n",
1556 env->error_code);
1557 break;
1558 }
1559 break;
1560 case POWERPC_EXCP_INVAL:
1561 EXCP_DUMP(env, "Invalid instruction\n");
1562 info.si_signo = TARGET_SIGILL;
1563 info.si_errno = 0;
1564 switch (env->error_code & 0xF) {
1565 case POWERPC_EXCP_INVAL_INVAL:
1566 info.si_code = TARGET_ILL_ILLOPC;
1567 break;
1568 case POWERPC_EXCP_INVAL_LSWX:
1569 info.si_code = TARGET_ILL_ILLOPN;
1570 break;
1571 case POWERPC_EXCP_INVAL_SPR:
1572 info.si_code = TARGET_ILL_PRVREG;
1573 break;
1574 case POWERPC_EXCP_INVAL_FP:
1575 info.si_code = TARGET_ILL_COPROC;
1576 break;
1577 default:
1578 EXCP_DUMP(env, "Unknown invalid operation (%02x)\n",
1579 env->error_code & 0xF);
1580 info.si_code = TARGET_ILL_ILLADR;
1581 break;
1582 }
1583 break;
1584 case POWERPC_EXCP_PRIV:
1585 EXCP_DUMP(env, "Privilege violation\n");
1586 info.si_signo = TARGET_SIGILL;
1587 info.si_errno = 0;
1588 switch (env->error_code & 0xF) {
1589 case POWERPC_EXCP_PRIV_OPC:
1590 info.si_code = TARGET_ILL_PRVOPC;
1591 break;
1592 case POWERPC_EXCP_PRIV_REG:
1593 info.si_code = TARGET_ILL_PRVREG;
1594 break;
1595 default:
1596 EXCP_DUMP(env, "Unknown privilege violation (%02x)\n",
1597 env->error_code & 0xF);
1598 info.si_code = TARGET_ILL_PRVOPC;
1599 break;
1600 }
1601 break;
1602 case POWERPC_EXCP_TRAP:
1603 cpu_abort(env, "Tried to call a TRAP\n");
1604 break;
1605 default:
1606 /* Should not happen ! */
1607 cpu_abort(env, "Unknown program exception (%02x)\n",
1608 env->error_code);
1609 break;
1610 }
1611 info._sifields._sigfault._addr = env->nip - 4;
pbrook624f7972008-05-31 16:11:38 +00001612 queue_signal(env, info.si_signo, &info);
j_mayere1833e12007-09-29 13:06:16 +00001613 break;
1614 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
1615 EXCP_DUMP(env, "No floating point allowed\n");
1616 info.si_signo = TARGET_SIGILL;
1617 info.si_errno = 0;
1618 info.si_code = TARGET_ILL_COPROC;
1619 info._sifields._sigfault._addr = env->nip - 4;
pbrook624f7972008-05-31 16:11:38 +00001620 queue_signal(env, info.si_signo, &info);
j_mayere1833e12007-09-29 13:06:16 +00001621 break;
1622 case POWERPC_EXCP_SYSCALL: /* System call exception */
1623 cpu_abort(env, "Syscall exception while in user mode. "
1624 "Aborting\n");
1625 break;
1626 case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
1627 EXCP_DUMP(env, "No APU instruction allowed\n");
1628 info.si_signo = TARGET_SIGILL;
1629 info.si_errno = 0;
1630 info.si_code = TARGET_ILL_COPROC;
1631 info._sifields._sigfault._addr = env->nip - 4;
pbrook624f7972008-05-31 16:11:38 +00001632 queue_signal(env, info.si_signo, &info);
j_mayere1833e12007-09-29 13:06:16 +00001633 break;
1634 case POWERPC_EXCP_DECR: /* Decrementer exception */
1635 cpu_abort(env, "Decrementer interrupt while in user mode. "
1636 "Aborting\n");
1637 break;
1638 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
1639 cpu_abort(env, "Fix interval timer interrupt while in user mode. "
1640 "Aborting\n");
1641 break;
1642 case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
1643 cpu_abort(env, "Watchdog timer interrupt while in user mode. "
1644 "Aborting\n");
1645 break;
1646 case POWERPC_EXCP_DTLB: /* Data TLB error */
1647 cpu_abort(env, "Data TLB exception while in user mode. "
1648 "Aborting\n");
1649 break;
1650 case POWERPC_EXCP_ITLB: /* Instruction TLB error */
1651 cpu_abort(env, "Instruction TLB exception while in user mode. "
1652 "Aborting\n");
1653 break;
j_mayere1833e12007-09-29 13:06:16 +00001654 case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */
1655 EXCP_DUMP(env, "No SPE/floating-point instruction allowed\n");
1656 info.si_signo = TARGET_SIGILL;
1657 info.si_errno = 0;
1658 info.si_code = TARGET_ILL_COPROC;
1659 info._sifields._sigfault._addr = env->nip - 4;
pbrook624f7972008-05-31 16:11:38 +00001660 queue_signal(env, info.si_signo, &info);
j_mayere1833e12007-09-29 13:06:16 +00001661 break;
1662 case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */
1663 cpu_abort(env, "Embedded floating-point data IRQ not handled\n");
1664 break;
1665 case POWERPC_EXCP_EFPRI: /* Embedded floating-point round IRQ */
1666 cpu_abort(env, "Embedded floating-point round IRQ not handled\n");
1667 break;
1668 case POWERPC_EXCP_EPERFM: /* Embedded performance monitor IRQ */
1669 cpu_abort(env, "Performance monitor exception not handled\n");
1670 break;
1671 case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
1672 cpu_abort(env, "Doorbell interrupt while in user mode. "
1673 "Aborting\n");
1674 break;
1675 case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
1676 cpu_abort(env, "Doorbell critical interrupt while in user mode. "
1677 "Aborting\n");
1678 break;
1679 case POWERPC_EXCP_RESET: /* System reset exception */
1680 cpu_abort(env, "Reset interrupt while in user mode. "
1681 "Aborting\n");
1682 break;
j_mayere1833e12007-09-29 13:06:16 +00001683 case POWERPC_EXCP_DSEG: /* Data segment exception */
1684 cpu_abort(env, "Data segment exception while in user mode. "
1685 "Aborting\n");
1686 break;
1687 case POWERPC_EXCP_ISEG: /* Instruction segment exception */
1688 cpu_abort(env, "Instruction segment exception "
1689 "while in user mode. Aborting\n");
1690 break;
j_mayere85e7c62007-10-18 19:59:49 +00001691 /* PowerPC 64 with hypervisor mode support */
j_mayere1833e12007-09-29 13:06:16 +00001692 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
1693 cpu_abort(env, "Hypervisor decrementer interrupt "
1694 "while in user mode. Aborting\n");
1695 break;
j_mayere1833e12007-09-29 13:06:16 +00001696 case POWERPC_EXCP_TRACE: /* Trace exception */
1697 /* Nothing to do:
1698 * we use this exception to emulate step-by-step execution mode.
1699 */
1700 break;
j_mayere85e7c62007-10-18 19:59:49 +00001701 /* PowerPC 64 with hypervisor mode support */
j_mayere1833e12007-09-29 13:06:16 +00001702 case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
1703 cpu_abort(env, "Hypervisor data storage exception "
1704 "while in user mode. Aborting\n");
1705 break;
1706 case POWERPC_EXCP_HISI: /* Hypervisor instruction storage excp */
1707 cpu_abort(env, "Hypervisor instruction storage exception "
1708 "while in user mode. Aborting\n");
1709 break;
1710 case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
1711 cpu_abort(env, "Hypervisor data segment exception "
1712 "while in user mode. Aborting\n");
1713 break;
1714 case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment excp */
1715 cpu_abort(env, "Hypervisor instruction segment exception "
1716 "while in user mode. Aborting\n");
1717 break;
j_mayere1833e12007-09-29 13:06:16 +00001718 case POWERPC_EXCP_VPU: /* Vector unavailable exception */
1719 EXCP_DUMP(env, "No Altivec instructions allowed\n");
1720 info.si_signo = TARGET_SIGILL;
1721 info.si_errno = 0;
1722 info.si_code = TARGET_ILL_COPROC;
1723 info._sifields._sigfault._addr = env->nip - 4;
pbrook624f7972008-05-31 16:11:38 +00001724 queue_signal(env, info.si_signo, &info);
j_mayere1833e12007-09-29 13:06:16 +00001725 break;
1726 case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */
Dong Xu Wangb4916d72011-11-22 18:06:17 +08001727 cpu_abort(env, "Programmable interval timer interrupt "
j_mayere1833e12007-09-29 13:06:16 +00001728 "while in user mode. Aborting\n");
1729 break;
1730 case POWERPC_EXCP_IO: /* IO error exception */
1731 cpu_abort(env, "IO error exception while in user mode. "
1732 "Aborting\n");
1733 break;
1734 case POWERPC_EXCP_RUNM: /* Run mode exception */
1735 cpu_abort(env, "Run mode exception while in user mode. "
1736 "Aborting\n");
1737 break;
1738 case POWERPC_EXCP_EMUL: /* Emulation trap exception */
1739 cpu_abort(env, "Emulation trap exception not handled\n");
1740 break;
1741 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
1742 cpu_abort(env, "Instruction fetch TLB exception "
1743 "while in user-mode. Aborting");
1744 break;
1745 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
1746 cpu_abort(env, "Data load TLB exception while in user-mode. "
1747 "Aborting");
1748 break;
1749 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
1750 cpu_abort(env, "Data store TLB exception while in user-mode. "
1751 "Aborting");
1752 break;
1753 case POWERPC_EXCP_FPA: /* Floating-point assist exception */
1754 cpu_abort(env, "Floating-point assist exception not handled\n");
1755 break;
1756 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
1757 cpu_abort(env, "Instruction address breakpoint exception "
1758 "not handled\n");
1759 break;
1760 case POWERPC_EXCP_SMI: /* System management interrupt */
1761 cpu_abort(env, "System management interrupt while in user mode. "
1762 "Aborting\n");
1763 break;
1764 case POWERPC_EXCP_THERM: /* Thermal interrupt */
1765 cpu_abort(env, "Thermal interrupt interrupt while in user mode. "
1766 "Aborting\n");
1767 break;
1768 case POWERPC_EXCP_PERFM: /* Embedded performance monitor IRQ */
1769 cpu_abort(env, "Performance monitor exception not handled\n");
1770 break;
1771 case POWERPC_EXCP_VPUA: /* Vector assist exception */
1772 cpu_abort(env, "Vector assist exception not handled\n");
1773 break;
1774 case POWERPC_EXCP_SOFTP: /* Soft patch exception */
1775 cpu_abort(env, "Soft patch exception not handled\n");
1776 break;
1777 case POWERPC_EXCP_MAINT: /* Maintenance exception */
1778 cpu_abort(env, "Maintenance exception while in user mode. "
1779 "Aborting\n");
1780 break;
1781 case POWERPC_EXCP_STOP: /* stop translation */
1782 /* We did invalidate the instruction cache. Go on */
1783 break;
1784 case POWERPC_EXCP_BRANCH: /* branch instruction: */
1785 /* We just stopped because of a branch. Go on */
1786 break;
1787 case POWERPC_EXCP_SYSCALL_USER:
1788 /* system call in user-mode emulation */
bellard67867302003-11-23 17:05:30 +00001789 /* WARNING:
1790 * PPC ABI uses overflow flag in cr0 to signal an error
1791 * in syscalls.
1792 */
1793 env->crf[0] &= ~0x1;
1794 ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
1795 env->gpr[5], env->gpr[6], env->gpr[7],
Peter Maydell5945cfc2011-06-16 17:37:13 +01001796 env->gpr[8], 0, 0);
Richard Henderson9e0e2f92011-10-26 09:59:18 -07001797 if (ret == (target_ulong)(-TARGET_QEMU_ESIGRETURN)) {
Nathan Froydbcd49332009-05-12 19:13:18 -07001798 /* Returning from a successful sigreturn syscall.
1799 Avoid corrupting register state. */
1800 break;
1801 }
Richard Henderson9e0e2f92011-10-26 09:59:18 -07001802 if (ret > (target_ulong)(-515)) {
bellard67867302003-11-23 17:05:30 +00001803 env->crf[0] |= 0x1;
1804 ret = -ret;
1805 }
1806 env->gpr[3] = ret;
1807 break;
Nathan Froyd56f066b2009-08-03 08:43:27 -07001808 case POWERPC_EXCP_STCX:
1809 if (do_store_exclusive(env)) {
1810 info.si_signo = TARGET_SIGSEGV;
1811 info.si_errno = 0;
1812 info.si_code = TARGET_SEGV_MAPERR;
1813 info._sifields._sigfault._addr = env->nip;
1814 queue_signal(env, info.si_signo, &info);
1815 }
1816 break;
aurel3271f75752008-11-14 17:05:54 +00001817 case EXCP_DEBUG:
1818 {
1819 int sig;
1820
Andreas Färberdb6b81d2013-06-27 19:49:31 +02001821 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
aurel3271f75752008-11-14 17:05:54 +00001822 if (sig) {
1823 info.si_signo = sig;
1824 info.si_errno = 0;
1825 info.si_code = TARGET_TRAP_BRKPT;
1826 queue_signal(env, info.si_signo, &info);
1827 }
1828 }
1829 break;
j_mayer56ba31f2007-09-30 15:15:18 +00001830 case EXCP_INTERRUPT:
1831 /* just indicate that signals should be handled asap */
1832 break;
bellard67867302003-11-23 17:05:30 +00001833 default:
j_mayere1833e12007-09-29 13:06:16 +00001834 cpu_abort(env, "Unknown exception 0x%d. Aborting\n", trapnr);
1835 break;
bellard67867302003-11-23 17:05:30 +00001836 }
1837 process_pending_signals(env);
1838 }
1839}
1840#endif
1841
bellard048f6b42005-11-26 18:47:20 +00001842#ifdef TARGET_MIPS
1843
Richard Hendersonff4f7382013-02-10 10:30:45 -08001844# ifdef TARGET_ABI_MIPSO32
1845# define MIPS_SYS(name, args) args,
bellard048f6b42005-11-26 18:47:20 +00001846static const uint8_t mips_syscall_args[] = {
An-Cheng Huang29fb0f22011-08-09 12:31:41 -07001847 MIPS_SYS(sys_syscall , 8) /* 4000 */
bellard048f6b42005-11-26 18:47:20 +00001848 MIPS_SYS(sys_exit , 1)
1849 MIPS_SYS(sys_fork , 0)
1850 MIPS_SYS(sys_read , 3)
1851 MIPS_SYS(sys_write , 3)
1852 MIPS_SYS(sys_open , 3) /* 4005 */
1853 MIPS_SYS(sys_close , 1)
1854 MIPS_SYS(sys_waitpid , 3)
1855 MIPS_SYS(sys_creat , 2)
1856 MIPS_SYS(sys_link , 2)
1857 MIPS_SYS(sys_unlink , 1) /* 4010 */
1858 MIPS_SYS(sys_execve , 0)
1859 MIPS_SYS(sys_chdir , 1)
1860 MIPS_SYS(sys_time , 1)
1861 MIPS_SYS(sys_mknod , 3)
1862 MIPS_SYS(sys_chmod , 2) /* 4015 */
1863 MIPS_SYS(sys_lchown , 3)
1864 MIPS_SYS(sys_ni_syscall , 0)
1865 MIPS_SYS(sys_ni_syscall , 0) /* was sys_stat */
1866 MIPS_SYS(sys_lseek , 3)
1867 MIPS_SYS(sys_getpid , 0) /* 4020 */
1868 MIPS_SYS(sys_mount , 5)
Richard Henderson868e34d2013-07-24 09:50:01 -10001869 MIPS_SYS(sys_umount , 1)
bellard048f6b42005-11-26 18:47:20 +00001870 MIPS_SYS(sys_setuid , 1)
1871 MIPS_SYS(sys_getuid , 0)
1872 MIPS_SYS(sys_stime , 1) /* 4025 */
1873 MIPS_SYS(sys_ptrace , 4)
1874 MIPS_SYS(sys_alarm , 1)
1875 MIPS_SYS(sys_ni_syscall , 0) /* was sys_fstat */
1876 MIPS_SYS(sys_pause , 0)
1877 MIPS_SYS(sys_utime , 2) /* 4030 */
1878 MIPS_SYS(sys_ni_syscall , 0)
1879 MIPS_SYS(sys_ni_syscall , 0)
1880 MIPS_SYS(sys_access , 2)
1881 MIPS_SYS(sys_nice , 1)
1882 MIPS_SYS(sys_ni_syscall , 0) /* 4035 */
1883 MIPS_SYS(sys_sync , 0)
1884 MIPS_SYS(sys_kill , 2)
1885 MIPS_SYS(sys_rename , 2)
1886 MIPS_SYS(sys_mkdir , 2)
1887 MIPS_SYS(sys_rmdir , 1) /* 4040 */
1888 MIPS_SYS(sys_dup , 1)
1889 MIPS_SYS(sys_pipe , 0)
1890 MIPS_SYS(sys_times , 1)
1891 MIPS_SYS(sys_ni_syscall , 0)
1892 MIPS_SYS(sys_brk , 1) /* 4045 */
1893 MIPS_SYS(sys_setgid , 1)
1894 MIPS_SYS(sys_getgid , 0)
1895 MIPS_SYS(sys_ni_syscall , 0) /* was signal(2) */
1896 MIPS_SYS(sys_geteuid , 0)
1897 MIPS_SYS(sys_getegid , 0) /* 4050 */
1898 MIPS_SYS(sys_acct , 0)
Richard Henderson868e34d2013-07-24 09:50:01 -10001899 MIPS_SYS(sys_umount2 , 2)
bellard048f6b42005-11-26 18:47:20 +00001900 MIPS_SYS(sys_ni_syscall , 0)
1901 MIPS_SYS(sys_ioctl , 3)
1902 MIPS_SYS(sys_fcntl , 3) /* 4055 */
1903 MIPS_SYS(sys_ni_syscall , 2)
1904 MIPS_SYS(sys_setpgid , 2)
1905 MIPS_SYS(sys_ni_syscall , 0)
1906 MIPS_SYS(sys_olduname , 1)
1907 MIPS_SYS(sys_umask , 1) /* 4060 */
1908 MIPS_SYS(sys_chroot , 1)
1909 MIPS_SYS(sys_ustat , 2)
1910 MIPS_SYS(sys_dup2 , 2)
1911 MIPS_SYS(sys_getppid , 0)
1912 MIPS_SYS(sys_getpgrp , 0) /* 4065 */
1913 MIPS_SYS(sys_setsid , 0)
1914 MIPS_SYS(sys_sigaction , 3)
1915 MIPS_SYS(sys_sgetmask , 0)
1916 MIPS_SYS(sys_ssetmask , 1)
1917 MIPS_SYS(sys_setreuid , 2) /* 4070 */
1918 MIPS_SYS(sys_setregid , 2)
1919 MIPS_SYS(sys_sigsuspend , 0)
1920 MIPS_SYS(sys_sigpending , 1)
1921 MIPS_SYS(sys_sethostname , 2)
1922 MIPS_SYS(sys_setrlimit , 2) /* 4075 */
1923 MIPS_SYS(sys_getrlimit , 2)
1924 MIPS_SYS(sys_getrusage , 2)
1925 MIPS_SYS(sys_gettimeofday, 2)
1926 MIPS_SYS(sys_settimeofday, 2)
1927 MIPS_SYS(sys_getgroups , 2) /* 4080 */
1928 MIPS_SYS(sys_setgroups , 2)
1929 MIPS_SYS(sys_ni_syscall , 0) /* old_select */
1930 MIPS_SYS(sys_symlink , 2)
1931 MIPS_SYS(sys_ni_syscall , 0) /* was sys_lstat */
1932 MIPS_SYS(sys_readlink , 3) /* 4085 */
1933 MIPS_SYS(sys_uselib , 1)
1934 MIPS_SYS(sys_swapon , 2)
1935 MIPS_SYS(sys_reboot , 3)
1936 MIPS_SYS(old_readdir , 3)
1937 MIPS_SYS(old_mmap , 6) /* 4090 */
1938 MIPS_SYS(sys_munmap , 2)
1939 MIPS_SYS(sys_truncate , 2)
1940 MIPS_SYS(sys_ftruncate , 2)
1941 MIPS_SYS(sys_fchmod , 2)
1942 MIPS_SYS(sys_fchown , 3) /* 4095 */
1943 MIPS_SYS(sys_getpriority , 2)
1944 MIPS_SYS(sys_setpriority , 3)
1945 MIPS_SYS(sys_ni_syscall , 0)
1946 MIPS_SYS(sys_statfs , 2)
1947 MIPS_SYS(sys_fstatfs , 2) /* 4100 */
1948 MIPS_SYS(sys_ni_syscall , 0) /* was ioperm(2) */
1949 MIPS_SYS(sys_socketcall , 2)
1950 MIPS_SYS(sys_syslog , 3)
1951 MIPS_SYS(sys_setitimer , 3)
1952 MIPS_SYS(sys_getitimer , 2) /* 4105 */
1953 MIPS_SYS(sys_newstat , 2)
1954 MIPS_SYS(sys_newlstat , 2)
1955 MIPS_SYS(sys_newfstat , 2)
1956 MIPS_SYS(sys_uname , 1)
1957 MIPS_SYS(sys_ni_syscall , 0) /* 4110 was iopl(2) */
1958 MIPS_SYS(sys_vhangup , 0)
1959 MIPS_SYS(sys_ni_syscall , 0) /* was sys_idle() */
1960 MIPS_SYS(sys_ni_syscall , 0) /* was sys_vm86 */
1961 MIPS_SYS(sys_wait4 , 4)
1962 MIPS_SYS(sys_swapoff , 1) /* 4115 */
1963 MIPS_SYS(sys_sysinfo , 1)
1964 MIPS_SYS(sys_ipc , 6)
1965 MIPS_SYS(sys_fsync , 1)
1966 MIPS_SYS(sys_sigreturn , 0)
Paul Brook18113962009-07-09 13:11:52 +01001967 MIPS_SYS(sys_clone , 6) /* 4120 */
bellard048f6b42005-11-26 18:47:20 +00001968 MIPS_SYS(sys_setdomainname, 2)
1969 MIPS_SYS(sys_newuname , 1)
1970 MIPS_SYS(sys_ni_syscall , 0) /* sys_modify_ldt */
1971 MIPS_SYS(sys_adjtimex , 1)
1972 MIPS_SYS(sys_mprotect , 3) /* 4125 */
1973 MIPS_SYS(sys_sigprocmask , 3)
1974 MIPS_SYS(sys_ni_syscall , 0) /* was create_module */
1975 MIPS_SYS(sys_init_module , 5)
1976 MIPS_SYS(sys_delete_module, 1)
1977 MIPS_SYS(sys_ni_syscall , 0) /* 4130 was get_kernel_syms */
1978 MIPS_SYS(sys_quotactl , 0)
1979 MIPS_SYS(sys_getpgid , 1)
1980 MIPS_SYS(sys_fchdir , 1)
1981 MIPS_SYS(sys_bdflush , 2)
1982 MIPS_SYS(sys_sysfs , 3) /* 4135 */
1983 MIPS_SYS(sys_personality , 1)
1984 MIPS_SYS(sys_ni_syscall , 0) /* for afs_syscall */
1985 MIPS_SYS(sys_setfsuid , 1)
1986 MIPS_SYS(sys_setfsgid , 1)
1987 MIPS_SYS(sys_llseek , 5) /* 4140 */
1988 MIPS_SYS(sys_getdents , 3)
1989 MIPS_SYS(sys_select , 5)
1990 MIPS_SYS(sys_flock , 2)
1991 MIPS_SYS(sys_msync , 3)
1992 MIPS_SYS(sys_readv , 3) /* 4145 */
1993 MIPS_SYS(sys_writev , 3)
1994 MIPS_SYS(sys_cacheflush , 3)
1995 MIPS_SYS(sys_cachectl , 3)
1996 MIPS_SYS(sys_sysmips , 4)
1997 MIPS_SYS(sys_ni_syscall , 0) /* 4150 */
1998 MIPS_SYS(sys_getsid , 1)
1999 MIPS_SYS(sys_fdatasync , 0)
2000 MIPS_SYS(sys_sysctl , 1)
2001 MIPS_SYS(sys_mlock , 2)
2002 MIPS_SYS(sys_munlock , 2) /* 4155 */
2003 MIPS_SYS(sys_mlockall , 1)
2004 MIPS_SYS(sys_munlockall , 0)
2005 MIPS_SYS(sys_sched_setparam, 2)
2006 MIPS_SYS(sys_sched_getparam, 2)
2007 MIPS_SYS(sys_sched_setscheduler, 3) /* 4160 */
2008 MIPS_SYS(sys_sched_getscheduler, 1)
2009 MIPS_SYS(sys_sched_yield , 0)
2010 MIPS_SYS(sys_sched_get_priority_max, 1)
2011 MIPS_SYS(sys_sched_get_priority_min, 1)
2012 MIPS_SYS(sys_sched_rr_get_interval, 2) /* 4165 */
2013 MIPS_SYS(sys_nanosleep, 2)
Petar Jovanovicb0932e02013-07-23 19:00:10 +02002014 MIPS_SYS(sys_mremap , 5)
bellard048f6b42005-11-26 18:47:20 +00002015 MIPS_SYS(sys_accept , 3)
2016 MIPS_SYS(sys_bind , 3)
2017 MIPS_SYS(sys_connect , 3) /* 4170 */
2018 MIPS_SYS(sys_getpeername , 3)
2019 MIPS_SYS(sys_getsockname , 3)
2020 MIPS_SYS(sys_getsockopt , 5)
2021 MIPS_SYS(sys_listen , 2)
2022 MIPS_SYS(sys_recv , 4) /* 4175 */
2023 MIPS_SYS(sys_recvfrom , 6)
2024 MIPS_SYS(sys_recvmsg , 3)
2025 MIPS_SYS(sys_send , 4)
2026 MIPS_SYS(sys_sendmsg , 3)
2027 MIPS_SYS(sys_sendto , 6) /* 4180 */
2028 MIPS_SYS(sys_setsockopt , 5)
2029 MIPS_SYS(sys_shutdown , 2)
2030 MIPS_SYS(sys_socket , 3)
2031 MIPS_SYS(sys_socketpair , 4)
2032 MIPS_SYS(sys_setresuid , 3) /* 4185 */
2033 MIPS_SYS(sys_getresuid , 3)
2034 MIPS_SYS(sys_ni_syscall , 0) /* was sys_query_module */
2035 MIPS_SYS(sys_poll , 3)
2036 MIPS_SYS(sys_nfsservctl , 3)
2037 MIPS_SYS(sys_setresgid , 3) /* 4190 */
2038 MIPS_SYS(sys_getresgid , 3)
2039 MIPS_SYS(sys_prctl , 5)
2040 MIPS_SYS(sys_rt_sigreturn, 0)
2041 MIPS_SYS(sys_rt_sigaction, 4)
2042 MIPS_SYS(sys_rt_sigprocmask, 4) /* 4195 */
2043 MIPS_SYS(sys_rt_sigpending, 2)
2044 MIPS_SYS(sys_rt_sigtimedwait, 4)
2045 MIPS_SYS(sys_rt_sigqueueinfo, 3)
2046 MIPS_SYS(sys_rt_sigsuspend, 0)
2047 MIPS_SYS(sys_pread64 , 6) /* 4200 */
2048 MIPS_SYS(sys_pwrite64 , 6)
2049 MIPS_SYS(sys_chown , 3)
2050 MIPS_SYS(sys_getcwd , 2)
2051 MIPS_SYS(sys_capget , 2)
2052 MIPS_SYS(sys_capset , 2) /* 4205 */
Wesley W. Terpstra053ebb22011-07-12 14:32:31 +03002053 MIPS_SYS(sys_sigaltstack , 2)
bellard048f6b42005-11-26 18:47:20 +00002054 MIPS_SYS(sys_sendfile , 4)
2055 MIPS_SYS(sys_ni_syscall , 0)
2056 MIPS_SYS(sys_ni_syscall , 0)
2057 MIPS_SYS(sys_mmap2 , 6) /* 4210 */
2058 MIPS_SYS(sys_truncate64 , 4)
2059 MIPS_SYS(sys_ftruncate64 , 4)
2060 MIPS_SYS(sys_stat64 , 2)
2061 MIPS_SYS(sys_lstat64 , 2)
2062 MIPS_SYS(sys_fstat64 , 2) /* 4215 */
2063 MIPS_SYS(sys_pivot_root , 2)
2064 MIPS_SYS(sys_mincore , 3)
2065 MIPS_SYS(sys_madvise , 3)
2066 MIPS_SYS(sys_getdents64 , 3)
2067 MIPS_SYS(sys_fcntl64 , 3) /* 4220 */
2068 MIPS_SYS(sys_ni_syscall , 0)
2069 MIPS_SYS(sys_gettid , 0)
2070 MIPS_SYS(sys_readahead , 5)
2071 MIPS_SYS(sys_setxattr , 5)
2072 MIPS_SYS(sys_lsetxattr , 5) /* 4225 */
2073 MIPS_SYS(sys_fsetxattr , 5)
2074 MIPS_SYS(sys_getxattr , 4)
2075 MIPS_SYS(sys_lgetxattr , 4)
2076 MIPS_SYS(sys_fgetxattr , 4)
2077 MIPS_SYS(sys_listxattr , 3) /* 4230 */
2078 MIPS_SYS(sys_llistxattr , 3)
2079 MIPS_SYS(sys_flistxattr , 3)
2080 MIPS_SYS(sys_removexattr , 2)
2081 MIPS_SYS(sys_lremovexattr, 2)
2082 MIPS_SYS(sys_fremovexattr, 2) /* 4235 */
2083 MIPS_SYS(sys_tkill , 2)
2084 MIPS_SYS(sys_sendfile64 , 5)
Petar Jovanovic43be1342013-07-15 15:17:40 +02002085 MIPS_SYS(sys_futex , 6)
bellard048f6b42005-11-26 18:47:20 +00002086 MIPS_SYS(sys_sched_setaffinity, 3)
2087 MIPS_SYS(sys_sched_getaffinity, 3) /* 4240 */
2088 MIPS_SYS(sys_io_setup , 2)
2089 MIPS_SYS(sys_io_destroy , 1)
2090 MIPS_SYS(sys_io_getevents, 5)
2091 MIPS_SYS(sys_io_submit , 3)
2092 MIPS_SYS(sys_io_cancel , 3) /* 4245 */
2093 MIPS_SYS(sys_exit_group , 1)
2094 MIPS_SYS(sys_lookup_dcookie, 3)
2095 MIPS_SYS(sys_epoll_create, 1)
2096 MIPS_SYS(sys_epoll_ctl , 4)
2097 MIPS_SYS(sys_epoll_wait , 3) /* 4250 */
2098 MIPS_SYS(sys_remap_file_pages, 5)
2099 MIPS_SYS(sys_set_tid_address, 1)
2100 MIPS_SYS(sys_restart_syscall, 0)
2101 MIPS_SYS(sys_fadvise64_64, 7)
2102 MIPS_SYS(sys_statfs64 , 3) /* 4255 */
2103 MIPS_SYS(sys_fstatfs64 , 2)
2104 MIPS_SYS(sys_timer_create, 3)
2105 MIPS_SYS(sys_timer_settime, 4)
2106 MIPS_SYS(sys_timer_gettime, 2)
2107 MIPS_SYS(sys_timer_getoverrun, 1) /* 4260 */
2108 MIPS_SYS(sys_timer_delete, 1)
2109 MIPS_SYS(sys_clock_settime, 2)
2110 MIPS_SYS(sys_clock_gettime, 2)
2111 MIPS_SYS(sys_clock_getres, 2)
2112 MIPS_SYS(sys_clock_nanosleep, 4) /* 4265 */
2113 MIPS_SYS(sys_tgkill , 3)
2114 MIPS_SYS(sys_utimes , 2)
2115 MIPS_SYS(sys_mbind , 4)
2116 MIPS_SYS(sys_ni_syscall , 0) /* sys_get_mempolicy */
2117 MIPS_SYS(sys_ni_syscall , 0) /* 4270 sys_set_mempolicy */
2118 MIPS_SYS(sys_mq_open , 4)
2119 MIPS_SYS(sys_mq_unlink , 1)
2120 MIPS_SYS(sys_mq_timedsend, 5)
2121 MIPS_SYS(sys_mq_timedreceive, 5)
2122 MIPS_SYS(sys_mq_notify , 2) /* 4275 */
2123 MIPS_SYS(sys_mq_getsetattr, 3)
2124 MIPS_SYS(sys_ni_syscall , 0) /* sys_vserver */
2125 MIPS_SYS(sys_waitid , 4)
2126 MIPS_SYS(sys_ni_syscall , 0) /* available, was setaltroot */
2127 MIPS_SYS(sys_add_key , 5)
ths388bb212007-05-13 13:58:00 +00002128 MIPS_SYS(sys_request_key, 4)
bellard048f6b42005-11-26 18:47:20 +00002129 MIPS_SYS(sys_keyctl , 5)
ths6f5b89a2007-03-02 20:48:00 +00002130 MIPS_SYS(sys_set_thread_area, 1)
ths388bb212007-05-13 13:58:00 +00002131 MIPS_SYS(sys_inotify_init, 0)
2132 MIPS_SYS(sys_inotify_add_watch, 3) /* 4285 */
2133 MIPS_SYS(sys_inotify_rm_watch, 2)
2134 MIPS_SYS(sys_migrate_pages, 4)
2135 MIPS_SYS(sys_openat, 4)
2136 MIPS_SYS(sys_mkdirat, 3)
2137 MIPS_SYS(sys_mknodat, 4) /* 4290 */
2138 MIPS_SYS(sys_fchownat, 5)
2139 MIPS_SYS(sys_futimesat, 3)
2140 MIPS_SYS(sys_fstatat64, 4)
2141 MIPS_SYS(sys_unlinkat, 3)
2142 MIPS_SYS(sys_renameat, 4) /* 4295 */
2143 MIPS_SYS(sys_linkat, 5)
2144 MIPS_SYS(sys_symlinkat, 3)
2145 MIPS_SYS(sys_readlinkat, 4)
2146 MIPS_SYS(sys_fchmodat, 3)
2147 MIPS_SYS(sys_faccessat, 3) /* 4300 */
2148 MIPS_SYS(sys_pselect6, 6)
2149 MIPS_SYS(sys_ppoll, 5)
2150 MIPS_SYS(sys_unshare, 1)
Petar Jovanovicb0932e02013-07-23 19:00:10 +02002151 MIPS_SYS(sys_splice, 6)
ths388bb212007-05-13 13:58:00 +00002152 MIPS_SYS(sys_sync_file_range, 7) /* 4305 */
2153 MIPS_SYS(sys_tee, 4)
2154 MIPS_SYS(sys_vmsplice, 4)
2155 MIPS_SYS(sys_move_pages, 6)
2156 MIPS_SYS(sys_set_robust_list, 2)
2157 MIPS_SYS(sys_get_robust_list, 3) /* 4310 */
2158 MIPS_SYS(sys_kexec_load, 4)
2159 MIPS_SYS(sys_getcpu, 3)
2160 MIPS_SYS(sys_epoll_pwait, 6)
2161 MIPS_SYS(sys_ioprio_set, 3)
2162 MIPS_SYS(sys_ioprio_get, 2)
Peter Maydelld979e8e2011-06-27 17:44:51 +01002163 MIPS_SYS(sys_utimensat, 4)
2164 MIPS_SYS(sys_signalfd, 3)
2165 MIPS_SYS(sys_ni_syscall, 0) /* was timerfd */
2166 MIPS_SYS(sys_eventfd, 1)
2167 MIPS_SYS(sys_fallocate, 6) /* 4320 */
2168 MIPS_SYS(sys_timerfd_create, 2)
2169 MIPS_SYS(sys_timerfd_gettime, 2)
2170 MIPS_SYS(sys_timerfd_settime, 4)
2171 MIPS_SYS(sys_signalfd4, 4)
2172 MIPS_SYS(sys_eventfd2, 2) /* 4325 */
2173 MIPS_SYS(sys_epoll_create1, 1)
2174 MIPS_SYS(sys_dup3, 3)
2175 MIPS_SYS(sys_pipe2, 2)
2176 MIPS_SYS(sys_inotify_init1, 1)
2177 MIPS_SYS(sys_preadv, 6) /* 4330 */
2178 MIPS_SYS(sys_pwritev, 6)
2179 MIPS_SYS(sys_rt_tgsigqueueinfo, 4)
2180 MIPS_SYS(sys_perf_event_open, 5)
2181 MIPS_SYS(sys_accept4, 4)
2182 MIPS_SYS(sys_recvmmsg, 5) /* 4335 */
2183 MIPS_SYS(sys_fanotify_init, 2)
2184 MIPS_SYS(sys_fanotify_mark, 6)
2185 MIPS_SYS(sys_prlimit64, 4)
2186 MIPS_SYS(sys_name_to_handle_at, 5)
2187 MIPS_SYS(sys_open_by_handle_at, 3) /* 4340 */
2188 MIPS_SYS(sys_clock_adjtime, 2)
2189 MIPS_SYS(sys_syncfs, 1)
bellard048f6b42005-11-26 18:47:20 +00002190};
Richard Hendersonff4f7382013-02-10 10:30:45 -08002191# undef MIPS_SYS
2192# endif /* O32 */
bellard048f6b42005-11-26 18:47:20 +00002193
Paul Brook590bc602009-07-09 17:45:17 +01002194static int do_store_exclusive(CPUMIPSState *env)
2195{
2196 target_ulong addr;
2197 target_ulong page_addr;
2198 target_ulong val;
2199 int flags;
2200 int segv = 0;
2201 int reg;
2202 int d;
2203
Aurelien Jarno5499b6f2009-11-22 13:08:14 +01002204 addr = env->lladdr;
Paul Brook590bc602009-07-09 17:45:17 +01002205 page_addr = addr & TARGET_PAGE_MASK;
2206 start_exclusive();
2207 mmap_lock();
2208 flags = page_get_flags(page_addr);
2209 if ((flags & PAGE_READ) == 0) {
2210 segv = 1;
2211 } else {
2212 reg = env->llreg & 0x1f;
2213 d = (env->llreg & 0x20) != 0;
2214 if (d) {
2215 segv = get_user_s64(val, addr);
2216 } else {
2217 segv = get_user_s32(val, addr);
2218 }
2219 if (!segv) {
2220 if (val != env->llval) {
2221 env->active_tc.gpr[reg] = 0;
2222 } else {
2223 if (d) {
2224 segv = put_user_u64(env->llnewval, addr);
2225 } else {
2226 segv = put_user_u32(env->llnewval, addr);
2227 }
2228 if (!segv) {
2229 env->active_tc.gpr[reg] = 1;
2230 }
2231 }
2232 }
2233 }
Aurelien Jarno5499b6f2009-11-22 13:08:14 +01002234 env->lladdr = -1;
Paul Brook590bc602009-07-09 17:45:17 +01002235 if (!segv) {
2236 env->active_tc.PC += 4;
2237 }
2238 mmap_unlock();
2239 end_exclusive();
2240 return segv;
2241}
2242
Meador Inge54b2f422013-01-10 16:50:22 -06002243/* Break codes */
2244enum {
2245 BRK_OVERFLOW = 6,
2246 BRK_DIVZERO = 7
2247};
2248
2249static int do_break(CPUMIPSState *env, target_siginfo_t *info,
2250 unsigned int code)
2251{
2252 int ret = -1;
2253
2254 switch (code) {
2255 case BRK_OVERFLOW:
2256 case BRK_DIVZERO:
2257 info->si_signo = TARGET_SIGFPE;
2258 info->si_errno = 0;
2259 info->si_code = (code == BRK_OVERFLOW) ? FPE_INTOVF : FPE_INTDIV;
2260 queue_signal(env, info->si_signo, &*info);
2261 ret = 0;
2262 break;
2263 default:
2264 break;
2265 }
2266
2267 return ret;
2268}
2269
bellard048f6b42005-11-26 18:47:20 +00002270void cpu_loop(CPUMIPSState *env)
2271{
Andreas Färber0315c312012-12-17 07:34:52 +01002272 CPUState *cs = CPU(mips_env_get_cpu(env));
Anthony Liguoric227f092009-10-01 16:12:16 -05002273 target_siginfo_t info;
Richard Hendersonff4f7382013-02-10 10:30:45 -08002274 int trapnr;
2275 abi_long ret;
2276# ifdef TARGET_ABI_MIPSO32
bellard048f6b42005-11-26 18:47:20 +00002277 unsigned int syscall_num;
Richard Hendersonff4f7382013-02-10 10:30:45 -08002278# endif
bellard048f6b42005-11-26 18:47:20 +00002279
2280 for(;;) {
Andreas Färber0315c312012-12-17 07:34:52 +01002281 cpu_exec_start(cs);
bellard048f6b42005-11-26 18:47:20 +00002282 trapnr = cpu_mips_exec(env);
Andreas Färber0315c312012-12-17 07:34:52 +01002283 cpu_exec_end(cs);
bellard048f6b42005-11-26 18:47:20 +00002284 switch(trapnr) {
2285 case EXCP_SYSCALL:
thsb5dc7732008-06-27 10:02:35 +00002286 env->active_tc.PC += 4;
Richard Hendersonff4f7382013-02-10 10:30:45 -08002287# ifdef TARGET_ABI_MIPSO32
2288 syscall_num = env->active_tc.gpr[2] - 4000;
ths388bb212007-05-13 13:58:00 +00002289 if (syscall_num >= sizeof(mips_syscall_args)) {
Wesley W. Terpstra7c2f6152011-07-12 14:33:23 +03002290 ret = -TARGET_ENOSYS;
ths388bb212007-05-13 13:58:00 +00002291 } else {
2292 int nb_args;
blueswir1992f48a2007-10-14 16:27:31 +00002293 abi_ulong sp_reg;
2294 abi_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0;
ths388bb212007-05-13 13:58:00 +00002295
2296 nb_args = mips_syscall_args[syscall_num];
thsb5dc7732008-06-27 10:02:35 +00002297 sp_reg = env->active_tc.gpr[29];
ths388bb212007-05-13 13:58:00 +00002298 switch (nb_args) {
2299 /* these arguments are taken from the stack */
An-Cheng Huang94c19612011-08-09 12:32:38 -07002300 case 8:
2301 if ((ret = get_user_ual(arg8, sp_reg + 28)) != 0) {
2302 goto done_syscall;
2303 }
2304 case 7:
2305 if ((ret = get_user_ual(arg7, sp_reg + 24)) != 0) {
2306 goto done_syscall;
2307 }
2308 case 6:
2309 if ((ret = get_user_ual(arg6, sp_reg + 20)) != 0) {
2310 goto done_syscall;
2311 }
2312 case 5:
2313 if ((ret = get_user_ual(arg5, sp_reg + 16)) != 0) {
2314 goto done_syscall;
2315 }
ths388bb212007-05-13 13:58:00 +00002316 default:
2317 break;
bellard048f6b42005-11-26 18:47:20 +00002318 }
thsb5dc7732008-06-27 10:02:35 +00002319 ret = do_syscall(env, env->active_tc.gpr[2],
2320 env->active_tc.gpr[4],
2321 env->active_tc.gpr[5],
2322 env->active_tc.gpr[6],
2323 env->active_tc.gpr[7],
Peter Maydell5945cfc2011-06-16 17:37:13 +01002324 arg5, arg6, arg7, arg8);
bellard048f6b42005-11-26 18:47:20 +00002325 }
An-Cheng Huang94c19612011-08-09 12:32:38 -07002326done_syscall:
Richard Hendersonff4f7382013-02-10 10:30:45 -08002327# else
2328 ret = do_syscall(env, env->active_tc.gpr[2],
2329 env->active_tc.gpr[4], env->active_tc.gpr[5],
2330 env->active_tc.gpr[6], env->active_tc.gpr[7],
2331 env->active_tc.gpr[8], env->active_tc.gpr[9],
2332 env->active_tc.gpr[10], env->active_tc.gpr[11]);
2333# endif /* O32 */
pbrook0b1bcb02009-04-21 01:41:10 +00002334 if (ret == -TARGET_QEMU_ESIGRETURN) {
2335 /* Returning from a successful sigreturn syscall.
2336 Avoid clobbering register state. */
2337 break;
2338 }
Richard Hendersonff4f7382013-02-10 10:30:45 -08002339 if ((abi_ulong)ret >= (abi_ulong)-1133) {
thsb5dc7732008-06-27 10:02:35 +00002340 env->active_tc.gpr[7] = 1; /* error flag */
ths388bb212007-05-13 13:58:00 +00002341 ret = -ret;
2342 } else {
thsb5dc7732008-06-27 10:02:35 +00002343 env->active_tc.gpr[7] = 0; /* error flag */
ths388bb212007-05-13 13:58:00 +00002344 }
thsb5dc7732008-06-27 10:02:35 +00002345 env->active_tc.gpr[2] = ret;
bellard048f6b42005-11-26 18:47:20 +00002346 break;
thsca7c2b12006-12-10 22:08:10 +00002347 case EXCP_TLBL:
2348 case EXCP_TLBS:
Wesley W. Terpstrae6e5bd22011-07-12 14:34:23 +03002349 case EXCP_AdEL:
2350 case EXCP_AdES:
pbrooke4474232009-04-21 01:03:10 +00002351 info.si_signo = TARGET_SIGSEGV;
2352 info.si_errno = 0;
2353 /* XXX: check env->error_code */
2354 info.si_code = TARGET_SEGV_MAPERR;
2355 info._sifields._sigfault._addr = env->CP0_BadVAddr;
2356 queue_signal(env, info.si_signo, &info);
2357 break;
bellard6900e842005-12-05 21:04:24 +00002358 case EXCP_CpU:
bellard048f6b42005-11-26 18:47:20 +00002359 case EXCP_RI:
bellardbc1ad2d2006-06-14 13:37:55 +00002360 info.si_signo = TARGET_SIGILL;
2361 info.si_errno = 0;
2362 info.si_code = 0;
pbrook624f7972008-05-31 16:11:38 +00002363 queue_signal(env, info.si_signo, &info);
bellard048f6b42005-11-26 18:47:20 +00002364 break;
bellard106ec872006-06-27 21:08:10 +00002365 case EXCP_INTERRUPT:
2366 /* just indicate that signals should be handled asap */
2367 break;
pbrookd08b2a22006-11-04 16:46:29 +00002368 case EXCP_DEBUG:
2369 {
2370 int sig;
2371
Andreas Färberdb6b81d2013-06-27 19:49:31 +02002372 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
pbrookd08b2a22006-11-04 16:46:29 +00002373 if (sig)
2374 {
2375 info.si_signo = sig;
2376 info.si_errno = 0;
2377 info.si_code = TARGET_TRAP_BRKPT;
pbrook624f7972008-05-31 16:11:38 +00002378 queue_signal(env, info.si_signo, &info);
pbrookd08b2a22006-11-04 16:46:29 +00002379 }
2380 }
2381 break;
Paul Brook590bc602009-07-09 17:45:17 +01002382 case EXCP_SC:
2383 if (do_store_exclusive(env)) {
2384 info.si_signo = TARGET_SIGSEGV;
2385 info.si_errno = 0;
2386 info.si_code = TARGET_SEGV_MAPERR;
2387 info._sifields._sigfault._addr = env->active_tc.PC;
2388 queue_signal(env, info.si_signo, &info);
2389 }
2390 break;
Jia Liu853c3242012-10-24 22:17:02 +08002391 case EXCP_DSPDIS:
2392 info.si_signo = TARGET_SIGILL;
2393 info.si_errno = 0;
2394 info.si_code = TARGET_ILL_ILLOPC;
2395 queue_signal(env, info.si_signo, &info);
2396 break;
Meador Inge54b2f422013-01-10 16:50:22 -06002397 /* The code below was inspired by the MIPS Linux kernel trap
2398 * handling code in arch/mips/kernel/traps.c.
2399 */
2400 case EXCP_BREAK:
2401 {
2402 abi_ulong trap_instr;
2403 unsigned int code;
2404
Kwok Cheung Yeunga0333812013-07-19 09:21:44 -07002405 if (env->hflags & MIPS_HFLAG_M16) {
2406 if (env->insn_flags & ASE_MICROMIPS) {
2407 /* microMIPS mode */
Kwok Cheung Yeung1308c462013-09-09 17:36:40 -07002408 ret = get_user_u16(trap_instr, env->active_tc.PC);
2409 if (ret != 0) {
2410 goto error;
2411 }
Kwok Cheung Yeunga0333812013-07-19 09:21:44 -07002412
Kwok Cheung Yeung1308c462013-09-09 17:36:40 -07002413 if ((trap_instr >> 10) == 0x11) {
2414 /* 16-bit instruction */
2415 code = trap_instr & 0xf;
2416 } else {
2417 /* 32-bit instruction */
2418 abi_ulong instr_lo;
Kwok Cheung Yeunga0333812013-07-19 09:21:44 -07002419
Kwok Cheung Yeung1308c462013-09-09 17:36:40 -07002420 ret = get_user_u16(instr_lo,
2421 env->active_tc.PC + 2);
2422 if (ret != 0) {
2423 goto error;
2424 }
2425 trap_instr = (trap_instr << 16) | instr_lo;
2426 code = ((trap_instr >> 6) & ((1 << 20) - 1));
2427 /* Unfortunately, microMIPS also suffers from
2428 the old assembler bug... */
2429 if (code >= (1 << 10)) {
2430 code >>= 10;
2431 }
2432 }
Kwok Cheung Yeunga0333812013-07-19 09:21:44 -07002433 } else {
2434 /* MIPS16e mode */
2435 ret = get_user_u16(trap_instr, env->active_tc.PC);
2436 if (ret != 0) {
2437 goto error;
2438 }
2439 code = (trap_instr >> 6) & 0x3f;
Kwok Cheung Yeunga0333812013-07-19 09:21:44 -07002440 }
2441 } else {
2442 ret = get_user_ual(trap_instr, env->active_tc.PC);
Kwok Cheung Yeung1308c462013-09-09 17:36:40 -07002443 if (ret != 0) {
2444 goto error;
2445 }
Kwok Cheung Yeunga0333812013-07-19 09:21:44 -07002446
Kwok Cheung Yeung1308c462013-09-09 17:36:40 -07002447 /* As described in the original Linux kernel code, the
2448 * below checks on 'code' are to work around an old
2449 * assembly bug.
2450 */
2451 code = ((trap_instr >> 6) & ((1 << 20) - 1));
2452 if (code >= (1 << 10)) {
2453 code >>= 10;
2454 }
Meador Inge54b2f422013-01-10 16:50:22 -06002455 }
2456
2457 if (do_break(env, &info, code) != 0) {
2458 goto error;
2459 }
2460 }
2461 break;
2462 case EXCP_TRAP:
2463 {
2464 abi_ulong trap_instr;
2465 unsigned int code = 0;
2466
Kwok Cheung Yeunga0333812013-07-19 09:21:44 -07002467 if (env->hflags & MIPS_HFLAG_M16) {
2468 /* microMIPS mode */
2469 abi_ulong instr[2];
2470
2471 ret = get_user_u16(instr[0], env->active_tc.PC) ||
2472 get_user_u16(instr[1], env->active_tc.PC + 2);
2473
2474 trap_instr = (instr[0] << 16) | instr[1];
2475 } else {
2476 ret = get_user_ual(trap_instr, env->active_tc.PC);
2477 }
2478
Meador Inge54b2f422013-01-10 16:50:22 -06002479 if (ret != 0) {
2480 goto error;
2481 }
2482
2483 /* The immediate versions don't provide a code. */
2484 if (!(trap_instr & 0xFC000000)) {
Kwok Cheung Yeunga0333812013-07-19 09:21:44 -07002485 if (env->hflags & MIPS_HFLAG_M16) {
2486 /* microMIPS mode */
2487 code = ((trap_instr >> 12) & ((1 << 4) - 1));
2488 } else {
2489 code = ((trap_instr >> 6) & ((1 << 10) - 1));
2490 }
Meador Inge54b2f422013-01-10 16:50:22 -06002491 }
2492
2493 if (do_break(env, &info, code) != 0) {
2494 goto error;
2495 }
2496 }
2497 break;
bellard048f6b42005-11-26 18:47:20 +00002498 default:
Meador Inge54b2f422013-01-10 16:50:22 -06002499error:
ths5fafdf22007-09-16 21:08:06 +00002500 fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
bellard048f6b42005-11-26 18:47:20 +00002501 trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +02002502 cpu_dump_state(cs, stderr, fprintf, 0);
bellard048f6b42005-11-26 18:47:20 +00002503 abort();
2504 }
2505 process_pending_signals(env);
2506 }
2507}
2508#endif
2509
Jia Liud9627832012-07-20 15:50:52 +08002510#ifdef TARGET_OPENRISC
2511
2512void cpu_loop(CPUOpenRISCState *env)
2513{
Andreas Färber878096e2013-05-27 01:33:50 +02002514 CPUState *cs = CPU(openrisc_env_get_cpu(env));
Jia Liud9627832012-07-20 15:50:52 +08002515 int trapnr, gdbsig;
2516
2517 for (;;) {
2518 trapnr = cpu_exec(env);
2519 gdbsig = 0;
2520
2521 switch (trapnr) {
2522 case EXCP_RESET:
2523 qemu_log("\nReset request, exit, pc is %#x\n", env->pc);
2524 exit(1);
2525 break;
2526 case EXCP_BUSERR:
2527 qemu_log("\nBus error, exit, pc is %#x\n", env->pc);
2528 gdbsig = SIGBUS;
2529 break;
2530 case EXCP_DPF:
2531 case EXCP_IPF:
Andreas Färber878096e2013-05-27 01:33:50 +02002532 cpu_dump_state(cs, stderr, fprintf, 0);
Jia Liud9627832012-07-20 15:50:52 +08002533 gdbsig = TARGET_SIGSEGV;
2534 break;
2535 case EXCP_TICK:
2536 qemu_log("\nTick time interrupt pc is %#x\n", env->pc);
2537 break;
2538 case EXCP_ALIGN:
2539 qemu_log("\nAlignment pc is %#x\n", env->pc);
2540 gdbsig = SIGBUS;
2541 break;
2542 case EXCP_ILLEGAL:
2543 qemu_log("\nIllegal instructionpc is %#x\n", env->pc);
2544 gdbsig = SIGILL;
2545 break;
2546 case EXCP_INT:
2547 qemu_log("\nExternal interruptpc is %#x\n", env->pc);
2548 break;
2549 case EXCP_DTLBMISS:
2550 case EXCP_ITLBMISS:
2551 qemu_log("\nTLB miss\n");
2552 break;
2553 case EXCP_RANGE:
2554 qemu_log("\nRange\n");
2555 gdbsig = SIGSEGV;
2556 break;
2557 case EXCP_SYSCALL:
2558 env->pc += 4; /* 0xc00; */
2559 env->gpr[11] = do_syscall(env,
2560 env->gpr[11], /* return value */
2561 env->gpr[3], /* r3 - r7 are params */
2562 env->gpr[4],
2563 env->gpr[5],
2564 env->gpr[6],
2565 env->gpr[7],
2566 env->gpr[8], 0, 0);
2567 break;
2568 case EXCP_FPE:
2569 qemu_log("\nFloating point error\n");
2570 break;
2571 case EXCP_TRAP:
2572 qemu_log("\nTrap\n");
2573 gdbsig = SIGTRAP;
2574 break;
2575 case EXCP_NR:
2576 qemu_log("\nNR\n");
2577 break;
2578 default:
2579 qemu_log("\nqemu: unhandled CPU exception %#x - aborting\n",
2580 trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +02002581 cpu_dump_state(cs, stderr, fprintf, 0);
Jia Liud9627832012-07-20 15:50:52 +08002582 gdbsig = TARGET_SIGILL;
2583 break;
2584 }
2585 if (gdbsig) {
Andreas Färberdb6b81d2013-06-27 19:49:31 +02002586 gdb_handlesig(cs, gdbsig);
Jia Liud9627832012-07-20 15:50:52 +08002587 if (gdbsig != TARGET_SIGTRAP) {
2588 exit(1);
2589 }
2590 }
2591
2592 process_pending_signals(env);
2593 }
2594}
2595
2596#endif /* TARGET_OPENRISC */
2597
bellardfdf9b3e2006-04-27 21:07:38 +00002598#ifdef TARGET_SH4
Andreas Färber05390242012-02-25 03:37:53 +01002599void cpu_loop(CPUSH4State *env)
bellardfdf9b3e2006-04-27 21:07:38 +00002600{
Andreas Färber878096e2013-05-27 01:33:50 +02002601 CPUState *cs = CPU(sh_env_get_cpu(env));
bellardfdf9b3e2006-04-27 21:07:38 +00002602 int trapnr, ret;
Anthony Liguoric227f092009-10-01 16:12:16 -05002603 target_siginfo_t info;
ths3b46e622007-09-17 08:09:54 +00002604
bellardfdf9b3e2006-04-27 21:07:38 +00002605 while (1) {
2606 trapnr = cpu_sh4_exec (env);
ths3b46e622007-09-17 08:09:54 +00002607
bellardfdf9b3e2006-04-27 21:07:38 +00002608 switch (trapnr) {
2609 case 0x160:
aurel320b6d3ae2008-09-15 07:43:43 +00002610 env->pc += 2;
ths5fafdf22007-09-16 21:08:06 +00002611 ret = do_syscall(env,
2612 env->gregs[3],
2613 env->gregs[4],
2614 env->gregs[5],
2615 env->gregs[6],
2616 env->gregs[7],
2617 env->gregs[0],
Peter Maydell5945cfc2011-06-16 17:37:13 +01002618 env->gregs[1],
2619 0, 0);
pbrook9c2a9ea2006-06-18 19:12:54 +00002620 env->gregs[0] = ret;
bellardfdf9b3e2006-04-27 21:07:38 +00002621 break;
thsc3b5bc82007-12-02 06:31:25 +00002622 case EXCP_INTERRUPT:
2623 /* just indicate that signals should be handled asap */
2624 break;
pbrook355fb232006-06-17 19:58:25 +00002625 case EXCP_DEBUG:
2626 {
2627 int sig;
2628
Andreas Färberdb6b81d2013-06-27 19:49:31 +02002629 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
pbrook355fb232006-06-17 19:58:25 +00002630 if (sig)
2631 {
2632 info.si_signo = sig;
2633 info.si_errno = 0;
2634 info.si_code = TARGET_TRAP_BRKPT;
pbrook624f7972008-05-31 16:11:38 +00002635 queue_signal(env, info.si_signo, &info);
pbrook355fb232006-06-17 19:58:25 +00002636 }
2637 }
2638 break;
thsc3b5bc82007-12-02 06:31:25 +00002639 case 0xa0:
2640 case 0xc0:
2641 info.si_signo = SIGSEGV;
2642 info.si_errno = 0;
2643 info.si_code = TARGET_SEGV_MAPERR;
2644 info._sifields._sigfault._addr = env->tea;
pbrook624f7972008-05-31 16:11:38 +00002645 queue_signal(env, info.si_signo, &info);
thsc3b5bc82007-12-02 06:31:25 +00002646 break;
2647
bellardfdf9b3e2006-04-27 21:07:38 +00002648 default:
2649 printf ("Unhandled trap: 0x%x\n", trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +02002650 cpu_dump_state(cs, stderr, fprintf, 0);
bellardfdf9b3e2006-04-27 21:07:38 +00002651 exit (1);
2652 }
2653 process_pending_signals (env);
2654 }
2655}
2656#endif
2657
ths48733d12007-10-08 13:36:46 +00002658#ifdef TARGET_CRIS
Andreas Färber05390242012-02-25 03:37:53 +01002659void cpu_loop(CPUCRISState *env)
ths48733d12007-10-08 13:36:46 +00002660{
Andreas Färber878096e2013-05-27 01:33:50 +02002661 CPUState *cs = CPU(cris_env_get_cpu(env));
ths48733d12007-10-08 13:36:46 +00002662 int trapnr, ret;
Anthony Liguoric227f092009-10-01 16:12:16 -05002663 target_siginfo_t info;
ths48733d12007-10-08 13:36:46 +00002664
2665 while (1) {
2666 trapnr = cpu_cris_exec (env);
2667 switch (trapnr) {
2668 case 0xaa:
2669 {
2670 info.si_signo = SIGSEGV;
2671 info.si_errno = 0;
2672 /* XXX: check env->error_code */
2673 info.si_code = TARGET_SEGV_MAPERR;
edgar_igle00c1e72008-05-27 21:12:09 +00002674 info._sifields._sigfault._addr = env->pregs[PR_EDA];
pbrook624f7972008-05-31 16:11:38 +00002675 queue_signal(env, info.si_signo, &info);
ths48733d12007-10-08 13:36:46 +00002676 }
2677 break;
edgar_iglb6d3abd2008-02-28 11:29:27 +00002678 case EXCP_INTERRUPT:
2679 /* just indicate that signals should be handled asap */
2680 break;
ths48733d12007-10-08 13:36:46 +00002681 case EXCP_BREAK:
2682 ret = do_syscall(env,
2683 env->regs[9],
2684 env->regs[10],
2685 env->regs[11],
2686 env->regs[12],
2687 env->regs[13],
2688 env->pregs[7],
Peter Maydell5945cfc2011-06-16 17:37:13 +01002689 env->pregs[11],
2690 0, 0);
ths48733d12007-10-08 13:36:46 +00002691 env->regs[10] = ret;
ths48733d12007-10-08 13:36:46 +00002692 break;
2693 case EXCP_DEBUG:
2694 {
2695 int sig;
2696
Andreas Färberdb6b81d2013-06-27 19:49:31 +02002697 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
ths48733d12007-10-08 13:36:46 +00002698 if (sig)
2699 {
2700 info.si_signo = sig;
2701 info.si_errno = 0;
2702 info.si_code = TARGET_TRAP_BRKPT;
pbrook624f7972008-05-31 16:11:38 +00002703 queue_signal(env, info.si_signo, &info);
ths48733d12007-10-08 13:36:46 +00002704 }
2705 }
2706 break;
2707 default:
2708 printf ("Unhandled trap: 0x%x\n", trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +02002709 cpu_dump_state(cs, stderr, fprintf, 0);
ths48733d12007-10-08 13:36:46 +00002710 exit (1);
2711 }
2712 process_pending_signals (env);
2713 }
2714}
2715#endif
2716
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02002717#ifdef TARGET_MICROBLAZE
Andreas Färber05390242012-02-25 03:37:53 +01002718void cpu_loop(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02002719{
Andreas Färber878096e2013-05-27 01:33:50 +02002720 CPUState *cs = CPU(mb_env_get_cpu(env));
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02002721 int trapnr, ret;
Anthony Liguoric227f092009-10-01 16:12:16 -05002722 target_siginfo_t info;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02002723
2724 while (1) {
2725 trapnr = cpu_mb_exec (env);
2726 switch (trapnr) {
2727 case 0xaa:
2728 {
2729 info.si_signo = SIGSEGV;
2730 info.si_errno = 0;
2731 /* XXX: check env->error_code */
2732 info.si_code = TARGET_SEGV_MAPERR;
2733 info._sifields._sigfault._addr = 0;
2734 queue_signal(env, info.si_signo, &info);
2735 }
2736 break;
2737 case EXCP_INTERRUPT:
2738 /* just indicate that signals should be handled asap */
2739 break;
2740 case EXCP_BREAK:
2741 /* Return address is 4 bytes after the call. */
2742 env->regs[14] += 4;
Edgar E. Iglesiasd7dce492012-04-26 14:18:25 +02002743 env->sregs[SR_PC] = env->regs[14];
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02002744 ret = do_syscall(env,
2745 env->regs[12],
2746 env->regs[5],
2747 env->regs[6],
2748 env->regs[7],
2749 env->regs[8],
2750 env->regs[9],
Peter Maydell5945cfc2011-06-16 17:37:13 +01002751 env->regs[10],
2752 0, 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02002753 env->regs[3] = ret;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02002754 break;
Edgar E. Iglesiasb76da7e2010-09-09 10:24:01 +02002755 case EXCP_HW_EXCP:
2756 env->regs[17] = env->sregs[SR_PC] + 4;
2757 if (env->iflags & D_FLAG) {
2758 env->sregs[SR_ESR] |= 1 << 12;
2759 env->sregs[SR_PC] -= 4;
Dong Xu Wangb4916d72011-11-22 18:06:17 +08002760 /* FIXME: if branch was immed, replay the imm as well. */
Edgar E. Iglesiasb76da7e2010-09-09 10:24:01 +02002761 }
2762
2763 env->iflags &= ~(IMM_FLAG | D_FLAG);
2764
2765 switch (env->sregs[SR_ESR] & 31) {
Edgar E. Iglesias22a78d62011-08-22 18:42:54 +02002766 case ESR_EC_DIVZERO:
2767 info.si_signo = SIGFPE;
2768 info.si_errno = 0;
2769 info.si_code = TARGET_FPE_FLTDIV;
2770 info._sifields._sigfault._addr = 0;
2771 queue_signal(env, info.si_signo, &info);
2772 break;
Edgar E. Iglesiasb76da7e2010-09-09 10:24:01 +02002773 case ESR_EC_FPU:
2774 info.si_signo = SIGFPE;
2775 info.si_errno = 0;
2776 if (env->sregs[SR_FSR] & FSR_IO) {
2777 info.si_code = TARGET_FPE_FLTINV;
2778 }
2779 if (env->sregs[SR_FSR] & FSR_DZ) {
2780 info.si_code = TARGET_FPE_FLTDIV;
2781 }
2782 info._sifields._sigfault._addr = 0;
2783 queue_signal(env, info.si_signo, &info);
2784 break;
2785 default:
2786 printf ("Unhandled hw-exception: 0x%x\n",
Edgar E. Iglesias2e42d522011-04-11 23:57:07 +02002787 env->sregs[SR_ESR] & ESR_EC_MASK);
Andreas Färber878096e2013-05-27 01:33:50 +02002788 cpu_dump_state(cs, stderr, fprintf, 0);
Edgar E. Iglesiasb76da7e2010-09-09 10:24:01 +02002789 exit (1);
2790 break;
2791 }
2792 break;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02002793 case EXCP_DEBUG:
2794 {
2795 int sig;
2796
Andreas Färberdb6b81d2013-06-27 19:49:31 +02002797 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02002798 if (sig)
2799 {
2800 info.si_signo = sig;
2801 info.si_errno = 0;
2802 info.si_code = TARGET_TRAP_BRKPT;
2803 queue_signal(env, info.si_signo, &info);
2804 }
2805 }
2806 break;
2807 default:
2808 printf ("Unhandled trap: 0x%x\n", trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +02002809 cpu_dump_state(cs, stderr, fprintf, 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02002810 exit (1);
2811 }
2812 process_pending_signals (env);
2813 }
2814}
2815#endif
2816
pbrooke6e59062006-10-22 00:18:54 +00002817#ifdef TARGET_M68K
2818
2819void cpu_loop(CPUM68KState *env)
2820{
Andreas Färber878096e2013-05-27 01:33:50 +02002821 CPUState *cs = CPU(m68k_env_get_cpu(env));
pbrooke6e59062006-10-22 00:18:54 +00002822 int trapnr;
2823 unsigned int n;
Anthony Liguoric227f092009-10-01 16:12:16 -05002824 target_siginfo_t info;
pbrooke6e59062006-10-22 00:18:54 +00002825 TaskState *ts = env->opaque;
ths3b46e622007-09-17 08:09:54 +00002826
pbrooke6e59062006-10-22 00:18:54 +00002827 for(;;) {
2828 trapnr = cpu_m68k_exec(env);
2829 switch(trapnr) {
2830 case EXCP_ILLEGAL:
2831 {
2832 if (ts->sim_syscalls) {
2833 uint16_t nr;
2834 nr = lduw(env->pc + 2);
2835 env->pc += 4;
2836 do_m68k_simcall(env, nr);
2837 } else {
2838 goto do_sigill;
2839 }
2840 }
2841 break;
pbrooka87295e2007-05-26 15:09:38 +00002842 case EXCP_HALT_INSN:
pbrooke6e59062006-10-22 00:18:54 +00002843 /* Semihosing syscall. */
pbrooka87295e2007-05-26 15:09:38 +00002844 env->pc += 4;
pbrooke6e59062006-10-22 00:18:54 +00002845 do_m68k_semihosting(env, env->dregs[0]);
2846 break;
2847 case EXCP_LINEA:
2848 case EXCP_LINEF:
2849 case EXCP_UNSUPPORTED:
2850 do_sigill:
2851 info.si_signo = SIGILL;
2852 info.si_errno = 0;
2853 info.si_code = TARGET_ILL_ILLOPN;
2854 info._sifields._sigfault._addr = env->pc;
pbrook624f7972008-05-31 16:11:38 +00002855 queue_signal(env, info.si_signo, &info);
pbrooke6e59062006-10-22 00:18:54 +00002856 break;
2857 case EXCP_TRAP0:
2858 {
2859 ts->sim_syscalls = 0;
2860 n = env->dregs[0];
2861 env->pc += 2;
ths5fafdf22007-09-16 21:08:06 +00002862 env->dregs[0] = do_syscall(env,
2863 n,
pbrooke6e59062006-10-22 00:18:54 +00002864 env->dregs[1],
2865 env->dregs[2],
2866 env->dregs[3],
2867 env->dregs[4],
2868 env->dregs[5],
Peter Maydell5945cfc2011-06-16 17:37:13 +01002869 env->aregs[0],
2870 0, 0);
pbrooke6e59062006-10-22 00:18:54 +00002871 }
2872 break;
2873 case EXCP_INTERRUPT:
2874 /* just indicate that signals should be handled asap */
2875 break;
2876 case EXCP_ACCESS:
2877 {
2878 info.si_signo = SIGSEGV;
2879 info.si_errno = 0;
2880 /* XXX: check env->error_code */
2881 info.si_code = TARGET_SEGV_MAPERR;
2882 info._sifields._sigfault._addr = env->mmu.ar;
pbrook624f7972008-05-31 16:11:38 +00002883 queue_signal(env, info.si_signo, &info);
pbrooke6e59062006-10-22 00:18:54 +00002884 }
2885 break;
2886 case EXCP_DEBUG:
2887 {
2888 int sig;
2889
Andreas Färberdb6b81d2013-06-27 19:49:31 +02002890 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
pbrooke6e59062006-10-22 00:18:54 +00002891 if (sig)
2892 {
2893 info.si_signo = sig;
2894 info.si_errno = 0;
2895 info.si_code = TARGET_TRAP_BRKPT;
pbrook624f7972008-05-31 16:11:38 +00002896 queue_signal(env, info.si_signo, &info);
pbrooke6e59062006-10-22 00:18:54 +00002897 }
2898 }
2899 break;
2900 default:
ths5fafdf22007-09-16 21:08:06 +00002901 fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
pbrooke6e59062006-10-22 00:18:54 +00002902 trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +02002903 cpu_dump_state(cs, stderr, fprintf, 0);
pbrooke6e59062006-10-22 00:18:54 +00002904 abort();
2905 }
2906 process_pending_signals(env);
2907 }
2908}
2909#endif /* TARGET_M68K */
2910
j_mayer7a3148a2007-04-05 07:13:51 +00002911#ifdef TARGET_ALPHA
Richard Henderson6910b8f2010-04-07 15:42:26 -07002912static void do_store_exclusive(CPUAlphaState *env, int reg, int quad)
2913{
2914 target_ulong addr, val, tmp;
2915 target_siginfo_t info;
2916 int ret = 0;
2917
2918 addr = env->lock_addr;
2919 tmp = env->lock_st_addr;
2920 env->lock_addr = -1;
2921 env->lock_st_addr = 0;
2922
2923 start_exclusive();
2924 mmap_lock();
2925
2926 if (addr == tmp) {
2927 if (quad ? get_user_s64(val, addr) : get_user_s32(val, addr)) {
2928 goto do_sigsegv;
2929 }
2930
2931 if (val == env->lock_value) {
2932 tmp = env->ir[reg];
2933 if (quad ? put_user_u64(tmp, addr) : put_user_u32(tmp, addr)) {
2934 goto do_sigsegv;
2935 }
2936 ret = 1;
2937 }
2938 }
2939 env->ir[reg] = ret;
2940 env->pc += 4;
2941
2942 mmap_unlock();
2943 end_exclusive();
2944 return;
2945
2946 do_sigsegv:
2947 mmap_unlock();
2948 end_exclusive();
2949
2950 info.si_signo = TARGET_SIGSEGV;
2951 info.si_errno = 0;
2952 info.si_code = TARGET_SEGV_MAPERR;
2953 info._sifields._sigfault._addr = addr;
2954 queue_signal(env, TARGET_SIGSEGV, &info);
2955}
2956
Andreas Färber05390242012-02-25 03:37:53 +01002957void cpu_loop(CPUAlphaState *env)
j_mayer7a3148a2007-04-05 07:13:51 +00002958{
Andreas Färber878096e2013-05-27 01:33:50 +02002959 CPUState *cs = CPU(alpha_env_get_cpu(env));
j_mayere96efcf2007-04-14 12:17:09 +00002960 int trapnr;
Anthony Liguoric227f092009-10-01 16:12:16 -05002961 target_siginfo_t info;
Richard Henderson6049f4f2009-12-27 18:30:03 -08002962 abi_long sysret;
ths3b46e622007-09-17 08:09:54 +00002963
j_mayer7a3148a2007-04-05 07:13:51 +00002964 while (1) {
2965 trapnr = cpu_alpha_exec (env);
ths3b46e622007-09-17 08:09:54 +00002966
Richard Hendersonac316ca2010-04-12 16:14:54 -07002967 /* All of the traps imply a transition through PALcode, which
2968 implies an REI instruction has been executed. Which means
2969 that the intr_flag should be cleared. */
2970 env->intr_flag = 0;
2971
j_mayer7a3148a2007-04-05 07:13:51 +00002972 switch (trapnr) {
2973 case EXCP_RESET:
2974 fprintf(stderr, "Reset requested. Exit\n");
2975 exit(1);
2976 break;
2977 case EXCP_MCHK:
2978 fprintf(stderr, "Machine check exception. Exit\n");
2979 exit(1);
2980 break;
Richard Henderson07b6c132011-05-20 14:04:57 -07002981 case EXCP_SMP_INTERRUPT:
2982 case EXCP_CLK_INTERRUPT:
2983 case EXCP_DEV_INTERRUPT:
ths5fafdf22007-09-16 21:08:06 +00002984 fprintf(stderr, "External interrupt. Exit\n");
j_mayer7a3148a2007-04-05 07:13:51 +00002985 exit(1);
2986 break;
Richard Henderson07b6c132011-05-20 14:04:57 -07002987 case EXCP_MMFAULT:
Richard Henderson6910b8f2010-04-07 15:42:26 -07002988 env->lock_addr = -1;
Richard Henderson6049f4f2009-12-27 18:30:03 -08002989 info.si_signo = TARGET_SIGSEGV;
2990 info.si_errno = 0;
Richard Henderson129d8aa2011-05-20 13:30:00 -07002991 info.si_code = (page_get_flags(env->trap_arg0) & PAGE_VALID
Richard Henderson0be1d072010-05-21 10:03:33 -07002992 ? TARGET_SEGV_ACCERR : TARGET_SEGV_MAPERR);
Richard Henderson129d8aa2011-05-20 13:30:00 -07002993 info._sifields._sigfault._addr = env->trap_arg0;
Richard Henderson6049f4f2009-12-27 18:30:03 -08002994 queue_signal(env, info.si_signo, &info);
j_mayer7a3148a2007-04-05 07:13:51 +00002995 break;
j_mayer7a3148a2007-04-05 07:13:51 +00002996 case EXCP_UNALIGN:
Richard Henderson6910b8f2010-04-07 15:42:26 -07002997 env->lock_addr = -1;
Richard Henderson6049f4f2009-12-27 18:30:03 -08002998 info.si_signo = TARGET_SIGBUS;
2999 info.si_errno = 0;
3000 info.si_code = TARGET_BUS_ADRALN;
Richard Henderson129d8aa2011-05-20 13:30:00 -07003001 info._sifields._sigfault._addr = env->trap_arg0;
Richard Henderson6049f4f2009-12-27 18:30:03 -08003002 queue_signal(env, info.si_signo, &info);
j_mayer7a3148a2007-04-05 07:13:51 +00003003 break;
3004 case EXCP_OPCDEC:
Richard Henderson6049f4f2009-12-27 18:30:03 -08003005 do_sigill:
Richard Henderson6910b8f2010-04-07 15:42:26 -07003006 env->lock_addr = -1;
Richard Henderson6049f4f2009-12-27 18:30:03 -08003007 info.si_signo = TARGET_SIGILL;
3008 info.si_errno = 0;
3009 info.si_code = TARGET_ILL_ILLOPC;
3010 info._sifields._sigfault._addr = env->pc;
3011 queue_signal(env, info.si_signo, &info);
j_mayer7a3148a2007-04-05 07:13:51 +00003012 break;
Richard Henderson07b6c132011-05-20 14:04:57 -07003013 case EXCP_ARITH:
3014 env->lock_addr = -1;
3015 info.si_signo = TARGET_SIGFPE;
3016 info.si_errno = 0;
3017 info.si_code = TARGET_FPE_FLTINV;
3018 info._sifields._sigfault._addr = env->pc;
3019 queue_signal(env, info.si_signo, &info);
3020 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003021 case EXCP_FEN:
Richard Henderson6049f4f2009-12-27 18:30:03 -08003022 /* No-op. Linux simply re-enables the FPU. */
j_mayer7a3148a2007-04-05 07:13:51 +00003023 break;
Richard Henderson07b6c132011-05-20 14:04:57 -07003024 case EXCP_CALL_PAL:
Richard Henderson6910b8f2010-04-07 15:42:26 -07003025 env->lock_addr = -1;
Richard Henderson07b6c132011-05-20 14:04:57 -07003026 switch (env->error_code) {
Richard Henderson6049f4f2009-12-27 18:30:03 -08003027 case 0x80:
3028 /* BPT */
3029 info.si_signo = TARGET_SIGTRAP;
3030 info.si_errno = 0;
3031 info.si_code = TARGET_TRAP_BRKPT;
3032 info._sifields._sigfault._addr = env->pc;
3033 queue_signal(env, info.si_signo, &info);
3034 break;
3035 case 0x81:
3036 /* BUGCHK */
3037 info.si_signo = TARGET_SIGTRAP;
3038 info.si_errno = 0;
3039 info.si_code = 0;
3040 info._sifields._sigfault._addr = env->pc;
3041 queue_signal(env, info.si_signo, &info);
3042 break;
3043 case 0x83:
3044 /* CALLSYS */
3045 trapnr = env->ir[IR_V0];
3046 sysret = do_syscall(env, trapnr,
3047 env->ir[IR_A0], env->ir[IR_A1],
3048 env->ir[IR_A2], env->ir[IR_A3],
Peter Maydell5945cfc2011-06-16 17:37:13 +01003049 env->ir[IR_A4], env->ir[IR_A5],
3050 0, 0);
Richard Hendersona5b3b132010-05-03 10:07:55 -07003051 if (trapnr == TARGET_NR_sigreturn
3052 || trapnr == TARGET_NR_rt_sigreturn) {
3053 break;
3054 }
3055 /* Syscall writes 0 to V0 to bypass error check, similar
Richard Henderson0e141972012-06-07 14:47:41 -07003056 to how this is handled internal to Linux kernel.
3057 (Ab)use trapnr temporarily as boolean indicating error. */
3058 trapnr = (env->ir[IR_V0] != 0 && sysret < 0);
3059 env->ir[IR_V0] = (trapnr ? -sysret : sysret);
3060 env->ir[IR_A3] = trapnr;
Richard Henderson6049f4f2009-12-27 18:30:03 -08003061 break;
3062 case 0x86:
3063 /* IMB */
3064 /* ??? We can probably elide the code using page_unprotect
3065 that is checking for self-modifying code. Instead we
3066 could simply call tb_flush here. Until we work out the
3067 changes required to turn off the extra write protection,
3068 this can be a no-op. */
3069 break;
3070 case 0x9E:
3071 /* RDUNIQUE */
3072 /* Handled in the translator for usermode. */
3073 abort();
3074 case 0x9F:
3075 /* WRUNIQUE */
3076 /* Handled in the translator for usermode. */
3077 abort();
3078 case 0xAA:
3079 /* GENTRAP */
3080 info.si_signo = TARGET_SIGFPE;
3081 switch (env->ir[IR_A0]) {
3082 case TARGET_GEN_INTOVF:
3083 info.si_code = TARGET_FPE_INTOVF;
3084 break;
3085 case TARGET_GEN_INTDIV:
3086 info.si_code = TARGET_FPE_INTDIV;
3087 break;
3088 case TARGET_GEN_FLTOVF:
3089 info.si_code = TARGET_FPE_FLTOVF;
3090 break;
3091 case TARGET_GEN_FLTUND:
3092 info.si_code = TARGET_FPE_FLTUND;
3093 break;
3094 case TARGET_GEN_FLTINV:
3095 info.si_code = TARGET_FPE_FLTINV;
3096 break;
3097 case TARGET_GEN_FLTINE:
3098 info.si_code = TARGET_FPE_FLTRES;
3099 break;
3100 case TARGET_GEN_ROPRAND:
3101 info.si_code = 0;
3102 break;
3103 default:
3104 info.si_signo = TARGET_SIGTRAP;
3105 info.si_code = 0;
3106 break;
3107 }
3108 info.si_errno = 0;
3109 info._sifields._sigfault._addr = env->pc;
3110 queue_signal(env, info.si_signo, &info);
3111 break;
3112 default:
3113 goto do_sigill;
3114 }
j_mayer7a3148a2007-04-05 07:13:51 +00003115 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003116 case EXCP_DEBUG:
Andreas Färberdb6b81d2013-06-27 19:49:31 +02003117 info.si_signo = gdb_handlesig(cs, TARGET_SIGTRAP);
Richard Henderson6049f4f2009-12-27 18:30:03 -08003118 if (info.si_signo) {
Richard Henderson6910b8f2010-04-07 15:42:26 -07003119 env->lock_addr = -1;
Richard Henderson6049f4f2009-12-27 18:30:03 -08003120 info.si_errno = 0;
3121 info.si_code = TARGET_TRAP_BRKPT;
3122 queue_signal(env, info.si_signo, &info);
j_mayer7a3148a2007-04-05 07:13:51 +00003123 }
3124 break;
Richard Henderson6910b8f2010-04-07 15:42:26 -07003125 case EXCP_STL_C:
3126 case EXCP_STQ_C:
3127 do_store_exclusive(env, env->error_code, trapnr - EXCP_STL_C);
3128 break;
Richard Hendersond0f20492012-05-31 12:05:23 -07003129 case EXCP_INTERRUPT:
3130 /* Just indicate that signals should be handled asap. */
3131 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003132 default:
3133 printf ("Unhandled trap: 0x%x\n", trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +02003134 cpu_dump_state(cs, stderr, fprintf, 0);
j_mayer7a3148a2007-04-05 07:13:51 +00003135 exit (1);
3136 }
3137 process_pending_signals (env);
3138 }
3139}
3140#endif /* TARGET_ALPHA */
3141
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003142#ifdef TARGET_S390X
3143void cpu_loop(CPUS390XState *env)
3144{
Andreas Färber878096e2013-05-27 01:33:50 +02003145 CPUState *cs = CPU(s390_env_get_cpu(env));
Richard Hendersond5a103c2012-09-14 19:31:57 -07003146 int trapnr, n, sig;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003147 target_siginfo_t info;
Richard Hendersond5a103c2012-09-14 19:31:57 -07003148 target_ulong addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003149
3150 while (1) {
Richard Hendersond5a103c2012-09-14 19:31:57 -07003151 trapnr = cpu_s390x_exec(env);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003152 switch (trapnr) {
3153 case EXCP_INTERRUPT:
Richard Hendersond5a103c2012-09-14 19:31:57 -07003154 /* Just indicate that signals should be handled asap. */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003155 break;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003156
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003157 case EXCP_SVC:
Richard Hendersond5a103c2012-09-14 19:31:57 -07003158 n = env->int_svc_code;
3159 if (!n) {
3160 /* syscalls > 255 */
3161 n = env->regs[1];
3162 }
3163 env->psw.addr += env->int_svc_ilen;
3164 env->regs[2] = do_syscall(env, n, env->regs[2], env->regs[3],
3165 env->regs[4], env->regs[5],
3166 env->regs[6], env->regs[7], 0, 0);
3167 break;
3168
3169 case EXCP_DEBUG:
Andreas Färberdb6b81d2013-06-27 19:49:31 +02003170 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
Richard Hendersond5a103c2012-09-14 19:31:57 -07003171 if (sig) {
3172 n = TARGET_TRAP_BRKPT;
3173 goto do_signal_pc;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003174 }
3175 break;
Richard Hendersond5a103c2012-09-14 19:31:57 -07003176 case EXCP_PGM:
3177 n = env->int_pgm_code;
3178 switch (n) {
3179 case PGM_OPERATION:
3180 case PGM_PRIVILEGED:
3181 sig = SIGILL;
3182 n = TARGET_ILL_ILLOPC;
3183 goto do_signal_pc;
3184 case PGM_PROTECTION:
3185 case PGM_ADDRESSING:
3186 sig = SIGSEGV;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003187 /* XXX: check env->error_code */
Richard Hendersond5a103c2012-09-14 19:31:57 -07003188 n = TARGET_SEGV_MAPERR;
3189 addr = env->__excp_addr;
3190 goto do_signal;
3191 case PGM_EXECUTE:
3192 case PGM_SPECIFICATION:
3193 case PGM_SPECIAL_OP:
3194 case PGM_OPERAND:
3195 do_sigill_opn:
3196 sig = SIGILL;
3197 n = TARGET_ILL_ILLOPN;
3198 goto do_signal_pc;
3199
3200 case PGM_FIXPT_OVERFLOW:
3201 sig = SIGFPE;
3202 n = TARGET_FPE_INTOVF;
3203 goto do_signal_pc;
3204 case PGM_FIXPT_DIVIDE:
3205 sig = SIGFPE;
3206 n = TARGET_FPE_INTDIV;
3207 goto do_signal_pc;
3208
3209 case PGM_DATA:
3210 n = (env->fpc >> 8) & 0xff;
3211 if (n == 0xff) {
3212 /* compare-and-trap */
3213 goto do_sigill_opn;
3214 } else {
3215 /* An IEEE exception, simulated or otherwise. */
3216 if (n & 0x80) {
3217 n = TARGET_FPE_FLTINV;
3218 } else if (n & 0x40) {
3219 n = TARGET_FPE_FLTDIV;
3220 } else if (n & 0x20) {
3221 n = TARGET_FPE_FLTOVF;
3222 } else if (n & 0x10) {
3223 n = TARGET_FPE_FLTUND;
3224 } else if (n & 0x08) {
3225 n = TARGET_FPE_FLTRES;
3226 } else {
3227 /* ??? Quantum exception; BFP, DFP error. */
3228 goto do_sigill_opn;
3229 }
3230 sig = SIGFPE;
3231 goto do_signal_pc;
3232 }
3233
3234 default:
3235 fprintf(stderr, "Unhandled program exception: %#x\n", n);
Andreas Färber878096e2013-05-27 01:33:50 +02003236 cpu_dump_state(cs, stderr, fprintf, 0);
Richard Hendersond5a103c2012-09-14 19:31:57 -07003237 exit(1);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003238 }
3239 break;
Richard Hendersond5a103c2012-09-14 19:31:57 -07003240
3241 do_signal_pc:
3242 addr = env->psw.addr;
3243 do_signal:
3244 info.si_signo = sig;
3245 info.si_errno = 0;
3246 info.si_code = n;
3247 info._sifields._sigfault._addr = addr;
3248 queue_signal(env, info.si_signo, &info);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003249 break;
Richard Hendersond5a103c2012-09-14 19:31:57 -07003250
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003251 default:
Richard Hendersond5a103c2012-09-14 19:31:57 -07003252 fprintf(stderr, "Unhandled trap: 0x%x\n", trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +02003253 cpu_dump_state(cs, stderr, fprintf, 0);
Richard Hendersond5a103c2012-09-14 19:31:57 -07003254 exit(1);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003255 }
3256 process_pending_signals (env);
3257 }
3258}
3259
3260#endif /* TARGET_S390X */
3261
Andreas Färbera2247f82013-06-09 19:47:04 +02003262THREAD CPUState *thread_cpu;
bellard59faf6d2003-06-25 16:18:50 +00003263
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003264void task_settid(TaskState *ts)
3265{
3266 if (ts->ts_tid == 0) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003267 ts->ts_tid = (pid_t)syscall(SYS_gettid);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003268 }
3269}
3270
3271void stop_all_tasks(void)
3272{
3273 /*
3274 * We trust that when using NPTL, start_exclusive()
3275 * handles thread stopping correctly.
3276 */
3277 start_exclusive();
3278}
3279
pbrookc3a92832008-06-09 14:02:50 +00003280/* Assumes contents are already zeroed. */
pbrook624f7972008-05-31 16:11:38 +00003281void init_task_state(TaskState *ts)
3282{
3283 int i;
3284
pbrook624f7972008-05-31 16:11:38 +00003285 ts->used = 1;
3286 ts->first_free = ts->sigqueue_table;
3287 for (i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++) {
3288 ts->sigqueue_table[i].next = &ts->sigqueue_table[i + 1];
3289 }
3290 ts->sigqueue_table[i].next = NULL;
3291}
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003292
Andreas Färber30ba0ee2013-07-02 17:43:21 +02003293CPUArchState *cpu_copy(CPUArchState *env)
3294{
Andreas Färber51fb2562013-07-02 18:26:11 +02003295 CPUArchState *new_env = cpu_init(cpu_model);
Andreas Färber30ba0ee2013-07-02 17:43:21 +02003296#if defined(TARGET_HAS_ICE)
3297 CPUBreakpoint *bp;
3298 CPUWatchpoint *wp;
3299#endif
3300
3301 /* Reset non arch specific state */
3302 cpu_reset(ENV_GET_CPU(new_env));
3303
3304 memcpy(new_env, env, sizeof(CPUArchState));
3305
3306 /* Clone all break/watchpoints.
3307 Note: Once we support ptrace with hw-debug register access, make sure
3308 BP_CPU break/watchpoints are handled correctly on clone. */
3309 QTAILQ_INIT(&env->breakpoints);
3310 QTAILQ_INIT(&env->watchpoints);
3311#if defined(TARGET_HAS_ICE)
3312 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
3313 cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL);
3314 }
3315 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
3316 cpu_watchpoint_insert(new_env, wp->vaddr, (~wp->len_mask) + 1,
3317 wp->flags, NULL);
3318 }
3319#endif
3320
3321 return new_env;
3322}
3323
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003324static void handle_arg_help(const char *arg)
3325{
3326 usage();
3327}
3328
3329static void handle_arg_log(const char *arg)
3330{
3331 int mask;
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003332
Peter Maydell4fde1eb2013-02-11 16:41:22 +00003333 mask = qemu_str_to_log_mask(arg);
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003334 if (!mask) {
Peter Maydell59a6fa62013-02-11 16:41:21 +00003335 qemu_print_log_usage(stdout);
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003336 exit(1);
3337 }
Peter Maydell24537a02013-02-11 16:41:23 +00003338 qemu_set_log(mask);
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003339}
3340
陳韋任50171d42011-11-08 17:46:44 +08003341static void handle_arg_log_filename(const char *arg)
3342{
Peter Maydell9a7e5422013-02-11 16:41:20 +00003343 qemu_set_log_filename(arg);
陳韋任50171d42011-11-08 17:46:44 +08003344}
3345
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003346static void handle_arg_set_env(const char *arg)
3347{
3348 char *r, *p, *token;
3349 r = p = strdup(arg);
3350 while ((token = strsep(&p, ",")) != NULL) {
3351 if (envlist_setenv(envlist, token) != 0) {
3352 usage();
3353 }
3354 }
3355 free(r);
3356}
3357
3358static void handle_arg_unset_env(const char *arg)
3359{
3360 char *r, *p, *token;
3361 r = p = strdup(arg);
3362 while ((token = strsep(&p, ",")) != NULL) {
3363 if (envlist_unsetenv(envlist, token) != 0) {
3364 usage();
3365 }
3366 }
3367 free(r);
3368}
3369
3370static void handle_arg_argv0(const char *arg)
3371{
3372 argv0 = strdup(arg);
3373}
3374
3375static void handle_arg_stack_size(const char *arg)
3376{
3377 char *p;
3378 guest_stack_size = strtoul(arg, &p, 0);
3379 if (guest_stack_size == 0) {
3380 usage();
3381 }
3382
3383 if (*p == 'M') {
3384 guest_stack_size *= 1024 * 1024;
3385 } else if (*p == 'k' || *p == 'K') {
3386 guest_stack_size *= 1024;
3387 }
3388}
3389
3390static void handle_arg_ld_prefix(const char *arg)
3391{
3392 interp_prefix = strdup(arg);
3393}
3394
3395static void handle_arg_pagesize(const char *arg)
3396{
3397 qemu_host_page_size = atoi(arg);
3398 if (qemu_host_page_size == 0 ||
3399 (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
3400 fprintf(stderr, "page size must be a power of two\n");
3401 exit(1);
3402 }
3403}
3404
3405static void handle_arg_gdb(const char *arg)
3406{
3407 gdbstub_port = atoi(arg);
3408}
3409
3410static void handle_arg_uname(const char *arg)
3411{
3412 qemu_uname_release = strdup(arg);
3413}
3414
3415static void handle_arg_cpu(const char *arg)
3416{
3417 cpu_model = strdup(arg);
Peter Maydellc8057f92012-08-02 13:45:54 +01003418 if (cpu_model == NULL || is_help_option(cpu_model)) {
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003419 /* XXX: implement xxx_cpu_list for targets that still miss it */
Peter Maydelle916cbf2012-09-05 17:41:08 -03003420#if defined(cpu_list)
3421 cpu_list(stdout, &fprintf);
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003422#endif
3423 exit(1);
3424 }
3425}
3426
3427#if defined(CONFIG_USE_GUEST_BASE)
3428static void handle_arg_guest_base(const char *arg)
3429{
3430 guest_base = strtol(arg, NULL, 0);
3431 have_guest_base = 1;
3432}
3433
3434static void handle_arg_reserved_va(const char *arg)
3435{
3436 char *p;
3437 int shift = 0;
3438 reserved_va = strtoul(arg, &p, 0);
3439 switch (*p) {
3440 case 'k':
3441 case 'K':
3442 shift = 10;
3443 break;
3444 case 'M':
3445 shift = 20;
3446 break;
3447 case 'G':
3448 shift = 30;
3449 break;
3450 }
3451 if (shift) {
3452 unsigned long unshifted = reserved_va;
3453 p++;
3454 reserved_va <<= shift;
3455 if (((reserved_va >> shift) != unshifted)
3456#if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS
3457 || (reserved_va > (1ul << TARGET_VIRT_ADDR_SPACE_BITS))
3458#endif
3459 ) {
3460 fprintf(stderr, "Reserved virtual address too big\n");
3461 exit(1);
3462 }
3463 }
3464 if (*p) {
3465 fprintf(stderr, "Unrecognised -R size suffix '%s'\n", p);
3466 exit(1);
3467 }
3468}
3469#endif
3470
3471static void handle_arg_singlestep(const char *arg)
3472{
3473 singlestep = 1;
3474}
3475
3476static void handle_arg_strace(const char *arg)
3477{
3478 do_strace = 1;
3479}
3480
3481static void handle_arg_version(const char *arg)
3482{
Paolo Bonzini2e599152013-06-04 14:45:27 +02003483 printf("qemu-" TARGET_NAME " version " QEMU_VERSION QEMU_PKGVERSION
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003484 ", Copyright (c) 2003-2008 Fabrice Bellard\n");
Peter Maydell1386d4c2011-09-29 15:48:12 +01003485 exit(0);
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003486}
3487
3488struct qemu_argument {
3489 const char *argv;
3490 const char *env;
3491 bool has_arg;
3492 void (*handle_opt)(const char *arg);
3493 const char *example;
3494 const char *help;
3495};
3496
Jim Meyering42644ce2012-05-21 21:56:19 +02003497static const struct qemu_argument arg_table[] = {
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003498 {"h", "", false, handle_arg_help,
3499 "", "print this help"},
3500 {"g", "QEMU_GDB", true, handle_arg_gdb,
3501 "port", "wait gdb connection to 'port'"},
3502 {"L", "QEMU_LD_PREFIX", true, handle_arg_ld_prefix,
3503 "path", "set the elf interpreter prefix to 'path'"},
3504 {"s", "QEMU_STACK_SIZE", true, handle_arg_stack_size,
3505 "size", "set the stack size to 'size' bytes"},
3506 {"cpu", "QEMU_CPU", true, handle_arg_cpu,
Peter Maydellc8057f92012-08-02 13:45:54 +01003507 "model", "select CPU (-cpu help for list)"},
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003508 {"E", "QEMU_SET_ENV", true, handle_arg_set_env,
3509 "var=value", "sets targets environment variable (see below)"},
3510 {"U", "QEMU_UNSET_ENV", true, handle_arg_unset_env,
3511 "var", "unsets targets environment variable (see below)"},
3512 {"0", "QEMU_ARGV0", true, handle_arg_argv0,
3513 "argv0", "forces target process argv[0] to be 'argv0'"},
3514 {"r", "QEMU_UNAME", true, handle_arg_uname,
3515 "uname", "set qemu uname release string to 'uname'"},
3516#if defined(CONFIG_USE_GUEST_BASE)
3517 {"B", "QEMU_GUEST_BASE", true, handle_arg_guest_base,
3518 "address", "set guest_base address to 'address'"},
3519 {"R", "QEMU_RESERVED_VA", true, handle_arg_reserved_va,
3520 "size", "reserve 'size' bytes for guest virtual address space"},
3521#endif
3522 {"d", "QEMU_LOG", true, handle_arg_log,
Peter Maydell989b6972013-02-26 17:52:40 +00003523 "item[,...]", "enable logging of specified items "
3524 "(use '-d help' for a list of items)"},
陳韋任50171d42011-11-08 17:46:44 +08003525 {"D", "QEMU_LOG_FILENAME", true, handle_arg_log_filename,
Peter Maydell989b6972013-02-26 17:52:40 +00003526 "logfile", "write logs to 'logfile' (default stderr)"},
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003527 {"p", "QEMU_PAGESIZE", true, handle_arg_pagesize,
3528 "pagesize", "set the host page size to 'pagesize'"},
3529 {"singlestep", "QEMU_SINGLESTEP", false, handle_arg_singlestep,
3530 "", "run in singlestep mode"},
3531 {"strace", "QEMU_STRACE", false, handle_arg_strace,
3532 "", "log system calls"},
3533 {"version", "QEMU_VERSION", false, handle_arg_version,
Peter Maydell1386d4c2011-09-29 15:48:12 +01003534 "", "display version information and exit"},
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003535 {NULL, NULL, false, NULL, NULL, NULL}
3536};
3537
3538static void usage(void)
3539{
Jim Meyering42644ce2012-05-21 21:56:19 +02003540 const struct qemu_argument *arginfo;
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003541 int maxarglen;
3542 int maxenvlen;
3543
Paolo Bonzini2e599152013-06-04 14:45:27 +02003544 printf("usage: qemu-" TARGET_NAME " [options] program [arguments...]\n"
3545 "Linux CPU emulator (compiled for " TARGET_NAME " emulation)\n"
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003546 "\n"
3547 "Options and associated environment variables:\n"
3548 "\n");
3549
Peter Maydell63ec54d2013-02-14 08:46:43 +00003550 /* Calculate column widths. We must always have at least enough space
3551 * for the column header.
3552 */
3553 maxarglen = strlen("Argument");
3554 maxenvlen = strlen("Env-variable");
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003555
3556 for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
Peter Maydell63ec54d2013-02-14 08:46:43 +00003557 int arglen = strlen(arginfo->argv);
3558 if (arginfo->has_arg) {
3559 arglen += strlen(arginfo->example) + 1;
3560 }
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003561 if (strlen(arginfo->env) > maxenvlen) {
3562 maxenvlen = strlen(arginfo->env);
3563 }
Peter Maydell63ec54d2013-02-14 08:46:43 +00003564 if (arglen > maxarglen) {
3565 maxarglen = arglen;
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003566 }
3567 }
3568
Peter Maydell63ec54d2013-02-14 08:46:43 +00003569 printf("%-*s %-*s Description\n", maxarglen+1, "Argument",
3570 maxenvlen, "Env-variable");
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003571
3572 for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
3573 if (arginfo->has_arg) {
3574 printf("-%s %-*s %-*s %s\n", arginfo->argv,
Peter Maydell63ec54d2013-02-14 08:46:43 +00003575 (int)(maxarglen - strlen(arginfo->argv) - 1),
3576 arginfo->example, maxenvlen, arginfo->env, arginfo->help);
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003577 } else {
Peter Maydell63ec54d2013-02-14 08:46:43 +00003578 printf("-%-*s %-*s %s\n", maxarglen, arginfo->argv,
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003579 maxenvlen, arginfo->env,
3580 arginfo->help);
3581 }
3582 }
3583
3584 printf("\n"
3585 "Defaults:\n"
3586 "QEMU_LD_PREFIX = %s\n"
Peter Maydell989b6972013-02-26 17:52:40 +00003587 "QEMU_STACK_SIZE = %ld byte\n",
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003588 interp_prefix,
Peter Maydell989b6972013-02-26 17:52:40 +00003589 guest_stack_size);
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003590
3591 printf("\n"
3592 "You can use -E and -U options or the QEMU_SET_ENV and\n"
3593 "QEMU_UNSET_ENV environment variables to set and unset\n"
3594 "environment variables for the target process.\n"
3595 "It is possible to provide several variables by separating them\n"
3596 "by commas in getsubopt(3) style. Additionally it is possible to\n"
3597 "provide the -E and -U options multiple times.\n"
3598 "The following lines are equivalent:\n"
3599 " -E var1=val2 -E var2=val2 -U LD_PRELOAD -U LD_DEBUG\n"
3600 " -E var1=val2,var2=val2 -U LD_PRELOAD,LD_DEBUG\n"
3601 " QEMU_SET_ENV=var1=val2,var2=val2 QEMU_UNSET_ENV=LD_PRELOAD,LD_DEBUG\n"
3602 "Note that if you provide several changes to a single variable\n"
3603 "the last change will stay in effect.\n");
3604
3605 exit(1);
3606}
3607
3608static int parse_args(int argc, char **argv)
3609{
3610 const char *r;
3611 int optind;
Jim Meyering42644ce2012-05-21 21:56:19 +02003612 const struct qemu_argument *arginfo;
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003613
3614 for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
3615 if (arginfo->env == NULL) {
3616 continue;
3617 }
3618
3619 r = getenv(arginfo->env);
3620 if (r != NULL) {
3621 arginfo->handle_opt(r);
3622 }
3623 }
3624
3625 optind = 1;
3626 for (;;) {
3627 if (optind >= argc) {
3628 break;
3629 }
3630 r = argv[optind];
3631 if (r[0] != '-') {
3632 break;
3633 }
3634 optind++;
3635 r++;
3636 if (!strcmp(r, "-")) {
3637 break;
3638 }
3639
3640 for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
3641 if (!strcmp(r, arginfo->argv)) {
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003642 if (arginfo->has_arg) {
Peter Maydell1386d4c2011-09-29 15:48:12 +01003643 if (optind >= argc) {
3644 usage();
3645 }
3646 arginfo->handle_opt(argv[optind]);
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003647 optind++;
Peter Maydell1386d4c2011-09-29 15:48:12 +01003648 } else {
3649 arginfo->handle_opt(NULL);
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003650 }
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003651 break;
3652 }
3653 }
3654
3655 /* no option matched the current argv */
3656 if (arginfo->handle_opt == NULL) {
3657 usage();
3658 }
3659 }
3660
3661 if (optind >= argc) {
3662 usage();
3663 }
3664
3665 filename = argv[optind];
3666 exec_path = argv[optind];
3667
3668 return optind;
3669}
3670
malc902b3d52008-12-10 19:18:40 +00003671int main(int argc, char **argv, char **envp)
bellard31e31b82003-02-18 22:55:36 +00003672{
bellard01ffc752003-02-18 23:00:51 +00003673 struct target_pt_regs regs1, *regs = &regs1;
bellard31e31b82003-02-18 22:55:36 +00003674 struct image_info info1, *info = &info1;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003675 struct linux_binprm bprm;
Nathan Froyd48e15fc2010-10-29 07:48:57 -07003676 TaskState *ts;
Andreas Färber9349b4f2012-03-14 01:38:32 +01003677 CPUArchState *env;
Andreas Färberdb6b81d2013-06-27 19:49:31 +02003678 CPUState *cpu;
bellard586314f2003-03-03 15:02:29 +00003679 int optind;
aurel3204a6dfe2009-01-30 19:59:17 +00003680 char **target_environ, **wrk;
aurel327d8cec92009-04-15 16:11:52 +00003681 char **target_argv;
3682 int target_argc;
aurel327d8cec92009-04-15 16:11:52 +00003683 int i;
Arnaud Patardfd4d81d2009-06-19 10:39:36 +03003684 int ret;
Laurent Vivier03cfd8f2013-08-30 01:46:44 +02003685 int execfd;
thsb12b6a12007-06-17 16:38:39 +00003686
Andreas Färberce008c12012-03-04 21:32:36 +01003687 module_call_init(MODULE_INIT_QOM);
3688
Richard Hendersonb6a3e692013-06-04 11:24:49 -07003689 qemu_init_auxval(envp);
Richard Henderson664d2c42013-06-10 09:05:09 -07003690 qemu_cache_utils_init();
malc902b3d52008-12-10 19:18:40 +00003691
aurel3204a6dfe2009-01-30 19:59:17 +00003692 if ((envlist = envlist_create()) == NULL) {
3693 (void) fprintf(stderr, "Unable to allocate envlist\n");
3694 exit(1);
3695 }
3696
3697 /* add current environment into the list */
3698 for (wrk = environ; *wrk != NULL; wrk++) {
3699 (void) envlist_setenv(envlist, *wrk);
3700 }
3701
Richard Henderson703e0e82010-03-19 14:21:13 -07003702 /* Read the stack limit from the kernel. If it's "unlimited",
3703 then we can do little else besides use the default. */
3704 {
3705 struct rlimit lim;
3706 if (getrlimit(RLIMIT_STACK, &lim) == 0
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09003707 && lim.rlim_cur != RLIM_INFINITY
3708 && lim.rlim_cur == (target_long)lim.rlim_cur) {
Richard Henderson703e0e82010-03-19 14:21:13 -07003709 guest_stack_size = lim.rlim_cur;
3710 }
3711 }
3712
j_mayerb1f9be32007-03-19 08:08:28 +00003713 cpu_model = NULL;
john cooperb5ec5ce2010-02-20 11:14:59 -06003714#if defined(cpudef_setup)
3715 cpudef_setup(); /* parse cpu definitions in target config file (TBD) */
3716#endif
3717
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003718 optind = parse_args(argc, argv);
Peter Maydell4b5dfd82011-07-18 11:44:09 +01003719
bellard31e31b82003-02-18 22:55:36 +00003720 /* Zero out regs */
bellard01ffc752003-02-18 23:00:51 +00003721 memset(regs, 0, sizeof(struct target_pt_regs));
bellard31e31b82003-02-18 22:55:36 +00003722
3723 /* Zero out image_info */
3724 memset(info, 0, sizeof(struct image_info));
3725
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003726 memset(&bprm, 0, sizeof (bprm));
3727
bellard74cd30b2003-04-11 00:13:41 +00003728 /* Scan interp_prefix dir for replacement files. */
3729 init_paths(interp_prefix);
3730
Peter Maydell4a24a752013-09-03 20:12:20 +01003731 init_qemu_uname_release();
3732
bellard46027c02007-11-08 13:56:19 +00003733 if (cpu_model == NULL) {
bellardaaed9092007-11-10 15:15:54 +00003734#if defined(TARGET_I386)
bellard46027c02007-11-08 13:56:19 +00003735#ifdef TARGET_X86_64
3736 cpu_model = "qemu64";
3737#else
3738 cpu_model = "qemu32";
3739#endif
bellardaaed9092007-11-10 15:15:54 +00003740#elif defined(TARGET_ARM)
pbrook088ab162009-04-09 15:20:50 +00003741 cpu_model = "any";
Guan Xuetaod2fbca92011-04-12 16:27:03 +08003742#elif defined(TARGET_UNICORE32)
3743 cpu_model = "any";
bellardaaed9092007-11-10 15:15:54 +00003744#elif defined(TARGET_M68K)
3745 cpu_model = "any";
3746#elif defined(TARGET_SPARC)
3747#ifdef TARGET_SPARC64
3748 cpu_model = "TI UltraSparc II";
3749#else
3750 cpu_model = "Fujitsu MB86904";
bellard46027c02007-11-08 13:56:19 +00003751#endif
bellardaaed9092007-11-10 15:15:54 +00003752#elif defined(TARGET_MIPS)
3753#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64)
3754 cpu_model = "20Kc";
3755#else
3756 cpu_model = "24Kf";
3757#endif
Jia Liud9627832012-07-20 15:50:52 +08003758#elif defined TARGET_OPENRISC
3759 cpu_model = "or1200";
bellardaaed9092007-11-10 15:15:54 +00003760#elif defined(TARGET_PPC)
bellard7ded4f52007-11-15 15:37:50 +00003761#ifdef TARGET_PPC64
Aurelien Jarnof7177932010-04-06 12:21:05 +02003762 cpu_model = "970fx";
bellard7ded4f52007-11-15 15:37:50 +00003763#else
bellardaaed9092007-11-10 15:15:54 +00003764 cpu_model = "750";
bellard7ded4f52007-11-15 15:37:50 +00003765#endif
bellardaaed9092007-11-10 15:15:54 +00003766#else
3767 cpu_model = "any";
3768#endif
3769 }
Jan Kiszkad5ab9712011-08-02 16:10:21 +02003770 tcg_exec_init(0);
3771 cpu_exec_init_all();
bellard83fb7ad2004-07-05 21:25:26 +00003772 /* NOTE: we need to init the CPU at this stage to get
3773 qemu_host_page_size */
bellardaaed9092007-11-10 15:15:54 +00003774 env = cpu_init(cpu_model);
3775 if (!env) {
3776 fprintf(stderr, "Unable to find CPU definition\n");
3777 exit(1);
3778 }
Andreas Färberdb6b81d2013-06-27 19:49:31 +02003779 cpu = ENV_GET_CPU(env);
Andreas Färber0ac46af2013-07-26 16:42:25 +02003780 cpu_reset(cpu);
Blue Swirlb55a37c2009-11-07 10:37:06 +00003781
Andreas Färberdb6b81d2013-06-27 19:49:31 +02003782 thread_cpu = cpu;
ths3b46e622007-09-17 08:09:54 +00003783
bellardb6741952007-11-11 14:46:06 +00003784 if (getenv("QEMU_STRACE")) {
3785 do_strace = 1;
thsb92c47c2007-11-01 00:07:38 +00003786 }
3787
aurel3204a6dfe2009-01-30 19:59:17 +00003788 target_environ = envlist_to_environ(envlist, NULL);
3789 envlist_free(envlist);
thsb12b6a12007-06-17 16:38:39 +00003790
Paul Brook379f6692009-07-17 12:48:08 +01003791#if defined(CONFIG_USE_GUEST_BASE)
3792 /*
3793 * Now that page sizes are configured in cpu_init() we can do
3794 * proper page alignment for guest_base.
3795 */
3796 guest_base = HOST_PAGE_ALIGN(guest_base);
Paul Brook68a1c812010-05-29 02:27:35 +01003797
Meador Inge806d1022012-07-26 16:50:02 +00003798 if (reserved_va || have_guest_base) {
3799 guest_base = init_guest_space(guest_base, reserved_va, 0,
3800 have_guest_base);
3801 if (guest_base == (unsigned long)-1) {
Peter Maydell097b8cb2012-08-20 11:36:32 +01003802 fprintf(stderr, "Unable to reserve 0x%lx bytes of virtual address "
3803 "space for use as guest address space (check your virtual "
3804 "memory ulimit setting or reserve less using -R option)\n",
3805 reserved_va);
Paul Brook68a1c812010-05-29 02:27:35 +01003806 exit(1);
3807 }
Dr. David Alan Gilbert97cc7562011-08-31 17:24:34 +01003808
Meador Inge806d1022012-07-26 16:50:02 +00003809 if (reserved_va) {
3810 mmap_next_start = reserved_va;
Dr. David Alan Gilbert97cc7562011-08-31 17:24:34 +01003811 }
3812 }
Richard Henderson14f24e12010-03-10 15:39:07 -08003813#endif /* CONFIG_USE_GUEST_BASE */
Paul Brook379f6692009-07-17 12:48:08 +01003814
3815 /*
3816 * Read in mmap_min_addr kernel parameter. This value is used
3817 * When loading the ELF image to determine whether guest_base
Richard Henderson14f24e12010-03-10 15:39:07 -08003818 * is needed. It is also used in mmap_find_vma.
Paul Brook379f6692009-07-17 12:48:08 +01003819 */
Richard Henderson14f24e12010-03-10 15:39:07 -08003820 {
Paul Brook379f6692009-07-17 12:48:08 +01003821 FILE *fp;
3822
3823 if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) {
3824 unsigned long tmp;
3825 if (fscanf(fp, "%lu", &tmp) == 1) {
3826 mmap_min_addr = tmp;
3827 qemu_log("host mmap_min_addr=0x%lx\n", mmap_min_addr);
3828 }
3829 fclose(fp);
3830 }
3831 }
Paul Brook379f6692009-07-17 12:48:08 +01003832
aurel327d8cec92009-04-15 16:11:52 +00003833 /*
3834 * Prepare copy of argv vector for target.
3835 */
3836 target_argc = argc - optind;
3837 target_argv = calloc(target_argc + 1, sizeof (char *));
3838 if (target_argv == NULL) {
3839 (void) fprintf(stderr, "Unable to allocate memory for target_argv\n");
3840 exit(1);
3841 }
3842
3843 /*
3844 * If argv0 is specified (using '-0' switch) we replace
3845 * argv[0] pointer with the given one.
3846 */
3847 i = 0;
3848 if (argv0 != NULL) {
3849 target_argv[i++] = strdup(argv0);
3850 }
3851 for (; i < target_argc; i++) {
3852 target_argv[i] = strdup(argv[optind + i]);
3853 }
3854 target_argv[target_argc] = NULL;
3855
Anthony Liguori7267c092011-08-20 22:09:37 -05003856 ts = g_malloc0 (sizeof(TaskState));
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003857 init_task_state(ts);
3858 /* build Task State */
3859 ts->info = info;
3860 ts->bprm = &bprm;
3861 env->opaque = ts;
3862 task_settid(ts);
3863
Richard Henderson0b959cf2013-10-15 15:00:36 -07003864 execfd = qemu_getauxval(AT_EXECFD);
3865 if (execfd == 0) {
Laurent Vivier03cfd8f2013-08-30 01:46:44 +02003866 execfd = open(filename, O_RDONLY);
Richard Henderson0b959cf2013-10-15 15:00:36 -07003867 if (execfd < 0) {
3868 printf("Error while loading %s: %s\n", filename, strerror(errno));
3869 _exit(1);
3870 }
Laurent Vivier03cfd8f2013-08-30 01:46:44 +02003871 }
3872
3873 ret = loader_exec(execfd, filename, target_argv, target_environ, regs,
Arnaud Patardfd4d81d2009-06-19 10:39:36 +03003874 info, &bprm);
3875 if (ret != 0) {
Peter Maydell885c1d12012-08-24 06:55:53 +00003876 printf("Error while loading %s: %s\n", filename, strerror(-ret));
thsb12b6a12007-06-17 16:38:39 +00003877 _exit(1);
3878 }
3879
3880 for (wrk = target_environ; *wrk; wrk++) {
3881 free(*wrk);
bellard31e31b82003-02-18 22:55:36 +00003882 }
ths3b46e622007-09-17 08:09:54 +00003883
thsb12b6a12007-06-17 16:38:39 +00003884 free(target_environ);
3885
blueswir12e77eac2009-01-20 16:57:34 +00003886 if (qemu_log_enabled()) {
Paul Brook379f6692009-07-17 12:48:08 +01003887#if defined(CONFIG_USE_GUEST_BASE)
3888 qemu_log("guest_base 0x%lx\n", guest_base);
3889#endif
blueswir12e77eac2009-01-20 16:57:34 +00003890 log_page_dump();
ths3b46e622007-09-17 08:09:54 +00003891
blueswir12e77eac2009-01-20 16:57:34 +00003892 qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk);
3893 qemu_log("end_code 0x" TARGET_ABI_FMT_lx "\n", info->end_code);
3894 qemu_log("start_code 0x" TARGET_ABI_FMT_lx "\n",
3895 info->start_code);
3896 qemu_log("start_data 0x" TARGET_ABI_FMT_lx "\n",
3897 info->start_data);
3898 qemu_log("end_data 0x" TARGET_ABI_FMT_lx "\n", info->end_data);
3899 qemu_log("start_stack 0x" TARGET_ABI_FMT_lx "\n",
3900 info->start_stack);
3901 qemu_log("brk 0x" TARGET_ABI_FMT_lx "\n", info->brk);
3902 qemu_log("entry 0x" TARGET_ABI_FMT_lx "\n", info->entry);
3903 }
bellard31e31b82003-02-18 22:55:36 +00003904
pbrook53a59602006-03-25 19:31:22 +00003905 target_set_brk(info->brk);
bellard31e31b82003-02-18 22:55:36 +00003906 syscall_init();
bellard66fb9762003-03-23 01:06:05 +00003907 signal_init();
bellard31e31b82003-02-18 22:55:36 +00003908
Richard Henderson9002ec72010-05-06 08:50:41 -07003909#if defined(CONFIG_USE_GUEST_BASE)
3910 /* Now that we've loaded the binary, GUEST_BASE is fixed. Delay
3911 generating the prologue until now so that the prologue can take
3912 the real value of GUEST_BASE into account. */
3913 tcg_prologue_init(&tcg_ctx);
3914#endif
3915
bellardb346ff42003-06-15 20:05:50 +00003916#if defined(TARGET_I386)
bellard2e255c62003-08-21 23:25:21 +00003917 cpu_x86_set_cpl(env, 3);
3918
bellard3802ce22003-07-26 18:02:28 +00003919 env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
bellard1bde4652005-01-12 22:34:47 +00003920 env->hflags |= HF_PE_MASK;
Eduardo Habkost0514ef22013-04-22 16:00:15 -03003921 if (env->features[FEAT_1_EDX] & CPUID_SSE) {
bellard1bde4652005-01-12 22:34:47 +00003922 env->cr[4] |= CR4_OSFXSR_MASK;
3923 env->hflags |= HF_OSFXSR_MASK;
3924 }
bellardd2fd1af2007-11-14 18:08:56 +00003925#ifndef TARGET_ABI32
bellard4dbc4222007-11-15 15:27:03 +00003926 /* enable 64 bit mode if possible */
Eduardo Habkost0514ef22013-04-22 16:00:15 -03003927 if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM)) {
bellard4dbc4222007-11-15 15:27:03 +00003928 fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n");
3929 exit(1);
3930 }
bellardd2fd1af2007-11-14 18:08:56 +00003931 env->cr[4] |= CR4_PAE_MASK;
bellard4dbc4222007-11-15 15:27:03 +00003932 env->efer |= MSR_EFER_LMA | MSR_EFER_LME;
bellardd2fd1af2007-11-14 18:08:56 +00003933 env->hflags |= HF_LMA_MASK;
3934#endif
bellard1bde4652005-01-12 22:34:47 +00003935
bellard415e5612004-02-03 23:37:12 +00003936 /* flags setup : we activate the IRQs by default as in user mode */
3937 env->eflags |= IF_MASK;
ths3b46e622007-09-17 08:09:54 +00003938
bellard6dbad632003-03-16 18:05:05 +00003939 /* linux register setup */
bellardd2fd1af2007-11-14 18:08:56 +00003940#ifndef TARGET_ABI32
j_mayer84409dd2007-04-06 08:56:50 +00003941 env->regs[R_EAX] = regs->rax;
3942 env->regs[R_EBX] = regs->rbx;
3943 env->regs[R_ECX] = regs->rcx;
3944 env->regs[R_EDX] = regs->rdx;
3945 env->regs[R_ESI] = regs->rsi;
3946 env->regs[R_EDI] = regs->rdi;
3947 env->regs[R_EBP] = regs->rbp;
3948 env->regs[R_ESP] = regs->rsp;
3949 env->eip = regs->rip;
3950#else
bellard0ecfa992003-03-03 14:32:43 +00003951 env->regs[R_EAX] = regs->eax;
3952 env->regs[R_EBX] = regs->ebx;
3953 env->regs[R_ECX] = regs->ecx;
3954 env->regs[R_EDX] = regs->edx;
3955 env->regs[R_ESI] = regs->esi;
3956 env->regs[R_EDI] = regs->edi;
3957 env->regs[R_EBP] = regs->ebp;
3958 env->regs[R_ESP] = regs->esp;
bellarddab2ed92003-03-22 15:23:14 +00003959 env->eip = regs->eip;
j_mayer84409dd2007-04-06 08:56:50 +00003960#endif
bellard31e31b82003-02-18 22:55:36 +00003961
bellardf4beb512003-05-27 23:28:08 +00003962 /* linux interrupt setup */
balroge4415702008-11-10 02:55:33 +00003963#ifndef TARGET_ABI32
3964 env->idt.limit = 511;
3965#else
3966 env->idt.limit = 255;
3967#endif
3968 env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1),
3969 PROT_READ|PROT_WRITE,
3970 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
3971 idt_table = g2h(env->idt.base);
bellardf4beb512003-05-27 23:28:08 +00003972 set_idt(0, 0);
3973 set_idt(1, 0);
3974 set_idt(2, 0);
3975 set_idt(3, 3);
3976 set_idt(4, 3);
bellardec95da62008-05-12 12:23:31 +00003977 set_idt(5, 0);
bellardf4beb512003-05-27 23:28:08 +00003978 set_idt(6, 0);
3979 set_idt(7, 0);
3980 set_idt(8, 0);
3981 set_idt(9, 0);
3982 set_idt(10, 0);
3983 set_idt(11, 0);
3984 set_idt(12, 0);
3985 set_idt(13, 0);
3986 set_idt(14, 0);
3987 set_idt(15, 0);
3988 set_idt(16, 0);
3989 set_idt(17, 0);
3990 set_idt(18, 0);
3991 set_idt(19, 0);
3992 set_idt(0x80, 3);
3993
bellard6dbad632003-03-16 18:05:05 +00003994 /* linux segment setup */
bellard8d18e892007-11-14 15:18:40 +00003995 {
3996 uint64_t *gdt_table;
balroge4415702008-11-10 02:55:33 +00003997 env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES,
3998 PROT_READ|PROT_WRITE,
3999 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
bellard8d18e892007-11-14 15:18:40 +00004000 env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1;
balroge4415702008-11-10 02:55:33 +00004001 gdt_table = g2h(env->gdt.base);
bellardd2fd1af2007-11-14 18:08:56 +00004002#ifdef TARGET_ABI32
bellard8d18e892007-11-14 15:18:40 +00004003 write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
4004 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
4005 (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
bellardd2fd1af2007-11-14 18:08:56 +00004006#else
4007 /* 64 bit code segment */
4008 write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
4009 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
4010 DESC_L_MASK |
4011 (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
4012#endif
bellard8d18e892007-11-14 15:18:40 +00004013 write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
4014 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
4015 (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
4016 }
bellard6dbad632003-03-16 18:05:05 +00004017 cpu_x86_load_seg(env, R_CS, __USER_CS);
bellardd2fd1af2007-11-14 18:08:56 +00004018 cpu_x86_load_seg(env, R_SS, __USER_DS);
4019#ifdef TARGET_ABI32
bellard6dbad632003-03-16 18:05:05 +00004020 cpu_x86_load_seg(env, R_DS, __USER_DS);
4021 cpu_x86_load_seg(env, R_ES, __USER_DS);
bellard6dbad632003-03-16 18:05:05 +00004022 cpu_x86_load_seg(env, R_FS, __USER_DS);
4023 cpu_x86_load_seg(env, R_GS, __USER_DS);
thsd6eb40f2007-06-21 22:55:02 +00004024 /* This hack makes Wine work... */
4025 env->segs[R_FS].selector = 0;
bellardd2fd1af2007-11-14 18:08:56 +00004026#else
4027 cpu_x86_load_seg(env, R_DS, 0);
4028 cpu_x86_load_seg(env, R_ES, 0);
4029 cpu_x86_load_seg(env, R_FS, 0);
4030 cpu_x86_load_seg(env, R_GS, 0);
4031#endif
Alexander Graf99033ca2013-09-03 20:12:21 +01004032#elif defined(TARGET_AARCH64)
4033 {
4034 int i;
4035
4036 if (!(arm_feature(env, ARM_FEATURE_AARCH64))) {
4037 fprintf(stderr,
4038 "The selected ARM CPU does not support 64 bit mode\n");
4039 exit(1);
4040 }
4041
4042 for (i = 0; i < 31; i++) {
4043 env->xregs[i] = regs->regs[i];
4044 }
4045 env->pc = regs->pc;
4046 env->xregs[31] = regs->sp;
4047 }
bellardb346ff42003-06-15 20:05:50 +00004048#elif defined(TARGET_ARM)
4049 {
4050 int i;
bellardb5ff1b32005-11-26 10:38:39 +00004051 cpsr_write(env, regs->uregs[16], 0xffffffff);
bellardb346ff42003-06-15 20:05:50 +00004052 for(i = 0; i < 16; i++) {
4053 env->regs[i] = regs->uregs[i];
4054 }
Paul Brookd8fd2952012-03-30 18:02:50 +01004055 /* Enable BE8. */
4056 if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4
4057 && (info->elf_flags & EF_ARM_BE8)) {
4058 env->bswap_code = 1;
4059 }
bellardb346ff42003-06-15 20:05:50 +00004060 }
Guan Xuetaod2fbca92011-04-12 16:27:03 +08004061#elif defined(TARGET_UNICORE32)
4062 {
4063 int i;
4064 cpu_asr_write(env, regs->uregs[32], 0xffffffff);
4065 for (i = 0; i < 32; i++) {
4066 env->regs[i] = regs->uregs[i];
4067 }
4068 }
bellard93ac68b2003-09-30 20:57:29 +00004069#elif defined(TARGET_SPARC)
bellard060366c2004-01-04 15:50:01 +00004070 {
4071 int i;
4072 env->pc = regs->pc;
4073 env->npc = regs->npc;
4074 env->y = regs->y;
4075 for(i = 0; i < 8; i++)
4076 env->gregs[i] = regs->u_regs[i];
4077 for(i = 0; i < 8; i++)
4078 env->regwptr[i] = regs->u_regs[i + 8];
4079 }
bellard67867302003-11-23 17:05:30 +00004080#elif defined(TARGET_PPC)
4081 {
4082 int i;
bellard3fc6c082005-07-02 20:59:34 +00004083
j_mayer0411a972007-10-25 21:35:50 +00004084#if defined(TARGET_PPC64)
4085#if defined(TARGET_ABI32)
4086 env->msr &= ~((target_ulong)1 << MSR_SF);
j_mayere85e7c62007-10-18 19:59:49 +00004087#else
j_mayer0411a972007-10-25 21:35:50 +00004088 env->msr |= (target_ulong)1 << MSR_SF;
4089#endif
j_mayer84409dd2007-04-06 08:56:50 +00004090#endif
bellard67867302003-11-23 17:05:30 +00004091 env->nip = regs->nip;
4092 for(i = 0; i < 32; i++) {
4093 env->gpr[i] = regs->gpr[i];
4094 }
4095 }
pbrooke6e59062006-10-22 00:18:54 +00004096#elif defined(TARGET_M68K)
4097 {
pbrooke6e59062006-10-22 00:18:54 +00004098 env->pc = regs->pc;
4099 env->dregs[0] = regs->d0;
4100 env->dregs[1] = regs->d1;
4101 env->dregs[2] = regs->d2;
4102 env->dregs[3] = regs->d3;
4103 env->dregs[4] = regs->d4;
4104 env->dregs[5] = regs->d5;
4105 env->dregs[6] = regs->d6;
4106 env->dregs[7] = regs->d7;
4107 env->aregs[0] = regs->a0;
4108 env->aregs[1] = regs->a1;
4109 env->aregs[2] = regs->a2;
4110 env->aregs[3] = regs->a3;
4111 env->aregs[4] = regs->a4;
4112 env->aregs[5] = regs->a5;
4113 env->aregs[6] = regs->a6;
4114 env->aregs[7] = regs->usp;
4115 env->sr = regs->sr;
4116 ts->sim_syscalls = 1;
4117 }
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02004118#elif defined(TARGET_MICROBLAZE)
4119 {
4120 env->regs[0] = regs->r0;
4121 env->regs[1] = regs->r1;
4122 env->regs[2] = regs->r2;
4123 env->regs[3] = regs->r3;
4124 env->regs[4] = regs->r4;
4125 env->regs[5] = regs->r5;
4126 env->regs[6] = regs->r6;
4127 env->regs[7] = regs->r7;
4128 env->regs[8] = regs->r8;
4129 env->regs[9] = regs->r9;
4130 env->regs[10] = regs->r10;
4131 env->regs[11] = regs->r11;
4132 env->regs[12] = regs->r12;
4133 env->regs[13] = regs->r13;
4134 env->regs[14] = regs->r14;
4135 env->regs[15] = regs->r15;
4136 env->regs[16] = regs->r16;
4137 env->regs[17] = regs->r17;
4138 env->regs[18] = regs->r18;
4139 env->regs[19] = regs->r19;
4140 env->regs[20] = regs->r20;
4141 env->regs[21] = regs->r21;
4142 env->regs[22] = regs->r22;
4143 env->regs[23] = regs->r23;
4144 env->regs[24] = regs->r24;
4145 env->regs[25] = regs->r25;
4146 env->regs[26] = regs->r26;
4147 env->regs[27] = regs->r27;
4148 env->regs[28] = regs->r28;
4149 env->regs[29] = regs->r29;
4150 env->regs[30] = regs->r30;
4151 env->regs[31] = regs->r31;
4152 env->sregs[SR_PC] = regs->pc;
4153 }
bellard048f6b42005-11-26 18:47:20 +00004154#elif defined(TARGET_MIPS)
4155 {
4156 int i;
4157
4158 for(i = 0; i < 32; i++) {
thsb5dc7732008-06-27 10:02:35 +00004159 env->active_tc.gpr[i] = regs->regs[i];
bellard048f6b42005-11-26 18:47:20 +00004160 }
Nathan Froyd0fddbbf2010-06-08 13:30:02 -07004161 env->active_tc.PC = regs->cp0_epc & ~(target_ulong)1;
4162 if (regs->cp0_epc & 1) {
4163 env->hflags |= MIPS_HFLAG_M16;
4164 }
bellard048f6b42005-11-26 18:47:20 +00004165 }
Jia Liud9627832012-07-20 15:50:52 +08004166#elif defined(TARGET_OPENRISC)
4167 {
4168 int i;
4169
4170 for (i = 0; i < 32; i++) {
4171 env->gpr[i] = regs->gpr[i];
4172 }
4173
4174 env->sr = regs->sr;
4175 env->pc = regs->pc;
4176 }
bellardfdf9b3e2006-04-27 21:07:38 +00004177#elif defined(TARGET_SH4)
4178 {
4179 int i;
4180
4181 for(i = 0; i < 16; i++) {
4182 env->gregs[i] = regs->regs[i];
4183 }
4184 env->pc = regs->pc;
4185 }
j_mayer7a3148a2007-04-05 07:13:51 +00004186#elif defined(TARGET_ALPHA)
4187 {
4188 int i;
4189
4190 for(i = 0; i < 28; i++) {
blueswir1992f48a2007-10-14 16:27:31 +00004191 env->ir[i] = ((abi_ulong *)regs)[i];
j_mayer7a3148a2007-04-05 07:13:51 +00004192 }
Richard Hendersondad081e2010-01-04 11:19:14 -08004193 env->ir[IR_SP] = regs->usp;
j_mayer7a3148a2007-04-05 07:13:51 +00004194 env->pc = regs->pc;
j_mayer7a3148a2007-04-05 07:13:51 +00004195 }
ths48733d12007-10-08 13:36:46 +00004196#elif defined(TARGET_CRIS)
4197 {
4198 env->regs[0] = regs->r0;
4199 env->regs[1] = regs->r1;
4200 env->regs[2] = regs->r2;
4201 env->regs[3] = regs->r3;
4202 env->regs[4] = regs->r4;
4203 env->regs[5] = regs->r5;
4204 env->regs[6] = regs->r6;
4205 env->regs[7] = regs->r7;
4206 env->regs[8] = regs->r8;
4207 env->regs[9] = regs->r9;
4208 env->regs[10] = regs->r10;
4209 env->regs[11] = regs->r11;
4210 env->regs[12] = regs->r12;
4211 env->regs[13] = regs->r13;
4212 env->regs[14] = info->start_stack;
4213 env->regs[15] = regs->acr;
4214 env->pc = regs->erp;
4215 }
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004216#elif defined(TARGET_S390X)
4217 {
4218 int i;
4219 for (i = 0; i < 16; i++) {
4220 env->regs[i] = regs->gprs[i];
4221 }
4222 env->psw.mask = regs->psw.mask;
4223 env->psw.addr = regs->psw.addr;
4224 }
bellardb346ff42003-06-15 20:05:50 +00004225#else
4226#error unsupported target CPU
4227#endif
bellard31e31b82003-02-18 22:55:36 +00004228
Guan Xuetaod2fbca92011-04-12 16:27:03 +08004229#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)
pbrooka87295e2007-05-26 15:09:38 +00004230 ts->stack_base = info->start_stack;
4231 ts->heap_base = info->brk;
4232 /* This will be filled in on the first SYS_HEAPINFO call. */
4233 ts->heap_limit = 0;
4234#endif
4235
bellard74c33be2005-10-30 21:01:05 +00004236 if (gdbstub_port) {
Peter Maydellff7a9812011-09-06 14:15:50 +01004237 if (gdbserver_start(gdbstub_port) < 0) {
4238 fprintf(stderr, "qemu: could not open gdbserver on port %d\n",
4239 gdbstub_port);
4240 exit(1);
4241 }
Andreas Färberdb6b81d2013-06-27 19:49:31 +02004242 gdb_handlesig(cpu, 0);
bellard1fddef42005-04-17 19:16:13 +00004243 }
bellard1b6b0292003-03-22 17:31:38 +00004244 cpu_loop(env);
4245 /* never exits */
bellard31e31b82003-02-18 22:55:36 +00004246 return 0;
4247}