blob: 67ea9ba8417316e60183ddbaf7e15f4996e0c8ae [file] [log] [blame]
bellard31e31b82003-02-18 22:55:36 +00001/*
bellard93ac68b2003-09-30 20:57:29 +00002 * qemu user main
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard68d0f702008-01-06 17:21:48 +00004 * Copyright (c) 2003-2008 Fabrice Bellard
bellard31e31b82003-02-18 22:55:36 +00005 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * along with this program; if not, see <http://www.gnu.org/licenses/>.
bellard31e31b82003-02-18 22:55:36 +000018 */
19#include <stdlib.h>
20#include <stdio.h>
21#include <stdarg.h>
bellard04369ff2003-03-20 22:33:23 +000022#include <string.h>
bellard31e31b82003-02-18 22:55:36 +000023#include <errno.h>
bellard0ecfa992003-03-03 14:32:43 +000024#include <unistd.h>
balroge4415702008-11-10 02:55:33 +000025#include <sys/mman.h>
Mika Westerbergedf8e2a2009-04-07 09:57:11 +030026#include <sys/syscall.h>
Richard Henderson703e0e82010-03-19 14:21:13 -070027#include <sys/resource.h>
bellard31e31b82003-02-18 22:55:36 +000028
bellard3ef693a2003-03-23 20:17:16 +000029#include "qemu.h"
aurel32ca10f862008-04-11 21:35:42 +000030#include "qemu-common.h"
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010031#include "qemu/cache-utils.h"
Blue Swirl2b41f102011-06-19 20:38:22 +000032#include "cpu.h"
Richard Henderson9002ec72010-05-06 08:50:41 -070033#include "tcg.h"
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010034#include "qemu/timer.h"
35#include "qemu/envlist.h"
Paul Brookd8fd2952012-03-30 18:02:50 +010036#include "elf.h"
aurel3204a6dfe2009-01-30 19:59:17 +000037
aurel32d088d662009-01-30 20:09:01 +000038char *exec_path;
39
aurel321b530a62009-04-05 20:08:59 +000040int singlestep;
Johannes Schauerfc9c5412011-08-06 08:54:12 +020041const char *filename;
42const char *argv0;
43int gdbstub_port;
44envlist_t *envlist;
45const char *cpu_model;
Paul Brook379f6692009-07-17 12:48:08 +010046unsigned long mmap_min_addr;
Richard Henderson14f24e12010-03-10 15:39:07 -080047#if defined(CONFIG_USE_GUEST_BASE)
Paul Brook379f6692009-07-17 12:48:08 +010048unsigned long guest_base;
49int have_guest_base;
Alexander Graf288e65b2011-12-14 00:33:28 +010050#if (TARGET_LONG_BITS == 32) && (HOST_LONG_BITS == 64)
51/*
52 * When running 32-on-64 we should make sure we can fit all of the possible
53 * guest address space into a contiguous chunk of virtual host memory.
54 *
55 * This way we will never overlap with our own libraries or binaries or stack
56 * or anything else that QEMU maps.
57 */
Alexander Graf314992b2013-01-03 14:17:18 +010058# ifdef TARGET_MIPS
59/* MIPS only supports 31 bits of virtual address space for user space */
60unsigned long reserved_va = 0x77000000;
61# else
Alexander Graf288e65b2011-12-14 00:33:28 +010062unsigned long reserved_va = 0xf7000000;
Alexander Graf314992b2013-01-03 14:17:18 +010063# endif
Alexander Graf288e65b2011-12-14 00:33:28 +010064#else
Paul Brook68a1c812010-05-29 02:27:35 +010065unsigned long reserved_va;
Paul Brook379f6692009-07-17 12:48:08 +010066#endif
Alexander Graf288e65b2011-12-14 00:33:28 +010067#endif
aurel321b530a62009-04-05 20:08:59 +000068
Johannes Schauerfc9c5412011-08-06 08:54:12 +020069static void usage(void);
70
Paolo Bonzini7ee28222010-05-26 16:08:22 +020071static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
pbrookc5937222006-05-14 11:30:38 +000072const char *qemu_uname_release = CONFIG_UNAME_RELEASE;
bellard586314f2003-03-03 15:02:29 +000073
bellard9de5e442003-03-23 16:49:39 +000074/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
75 we allocate a bigger stack. Need a better solution, for example
76 by remapping the process stack directly at the right place */
Richard Henderson703e0e82010-03-19 14:21:13 -070077unsigned long guest_stack_size = 8 * 1024 * 1024UL;
bellard31e31b82003-02-18 22:55:36 +000078
79void gemu_log(const char *fmt, ...)
80{
81 va_list ap;
82
83 va_start(ap, fmt);
84 vfprintf(stderr, fmt, ap);
85 va_end(ap);
86}
87
blueswir18fcd3692008-08-17 20:26:25 +000088#if defined(TARGET_I386)
Andreas Färber05390242012-02-25 03:37:53 +010089int cpu_get_pic_interrupt(CPUX86State *env)
bellard92ccca62003-06-24 13:30:31 +000090{
91 return -1;
92}
blueswir18fcd3692008-08-17 20:26:25 +000093#endif
bellard92ccca62003-06-24 13:30:31 +000094
Juan Quintela2f7bb872009-07-27 16:13:24 +020095#if defined(CONFIG_USE_NPTL)
pbrookd5975362008-06-07 20:50:51 +000096/***********************************************************/
97/* Helper routines for implementing atomic operations. */
98
99/* To implement exclusive operations we force all cpus to syncronise.
100 We don't require a full sync, only that no cpus are executing guest code.
101 The alternative is to map target atomic ops onto host equivalents,
102 which requires quite a lot of per host/target work. */
pbrookc2764712009-03-07 15:24:59 +0000103static pthread_mutex_t cpu_list_mutex = PTHREAD_MUTEX_INITIALIZER;
pbrookd5975362008-06-07 20:50:51 +0000104static pthread_mutex_t exclusive_lock = PTHREAD_MUTEX_INITIALIZER;
105static pthread_cond_t exclusive_cond = PTHREAD_COND_INITIALIZER;
106static pthread_cond_t exclusive_resume = PTHREAD_COND_INITIALIZER;
107static int pending_cpus;
108
109/* Make sure everything is in a consistent state for calling fork(). */
110void fork_start(void)
111{
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +0700112 pthread_mutex_lock(&tcg_ctx.tb_ctx.tb_lock);
pbrookd5975362008-06-07 20:50:51 +0000113 pthread_mutex_lock(&exclusive_lock);
Riku Voipiod032d1b2009-12-04 15:16:31 +0200114 mmap_fork_start();
pbrookd5975362008-06-07 20:50:51 +0000115}
116
117void fork_end(int child)
118{
Riku Voipiod032d1b2009-12-04 15:16:31 +0200119 mmap_fork_end(child);
pbrookd5975362008-06-07 20:50:51 +0000120 if (child) {
121 /* Child processes created by fork() only have a single thread.
122 Discard information about the parent threads. */
Andreas Färbera2247f82013-06-09 19:47:04 +0200123 first_cpu = thread_cpu;
Andreas Färber182735e2013-05-29 22:29:20 +0200124 first_cpu->next_cpu = NULL;
pbrookd5975362008-06-07 20:50:51 +0000125 pending_cpus = 0;
126 pthread_mutex_init(&exclusive_lock, NULL);
pbrookc2764712009-03-07 15:24:59 +0000127 pthread_mutex_init(&cpu_list_mutex, NULL);
pbrookd5975362008-06-07 20:50:51 +0000128 pthread_cond_init(&exclusive_cond, NULL);
129 pthread_cond_init(&exclusive_resume, NULL);
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +0700130 pthread_mutex_init(&tcg_ctx.tb_ctx.tb_lock, NULL);
Andreas Färbera2247f82013-06-09 19:47:04 +0200131 gdbserver_fork((CPUArchState *)thread_cpu->env_ptr);
pbrookd5975362008-06-07 20:50:51 +0000132 } else {
133 pthread_mutex_unlock(&exclusive_lock);
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +0700134 pthread_mutex_unlock(&tcg_ctx.tb_ctx.tb_lock);
pbrookd5975362008-06-07 20:50:51 +0000135 }
pbrookd5975362008-06-07 20:50:51 +0000136}
137
138/* Wait for pending exclusive operations to complete. The exclusive lock
139 must be held. */
140static inline void exclusive_idle(void)
141{
142 while (pending_cpus) {
143 pthread_cond_wait(&exclusive_resume, &exclusive_lock);
144 }
145}
146
147/* Start an exclusive operation.
148 Must only be called from outside cpu_arm_exec. */
149static inline void start_exclusive(void)
150{
Andreas Färber0315c312012-12-17 07:34:52 +0100151 CPUState *other_cpu;
152
pbrookd5975362008-06-07 20:50:51 +0000153 pthread_mutex_lock(&exclusive_lock);
154 exclusive_idle();
155
156 pending_cpus = 1;
157 /* Make all other cpus stop executing. */
Andreas Färber182735e2013-05-29 22:29:20 +0200158 for (other_cpu = first_cpu; other_cpu; other_cpu = other_cpu->next_cpu) {
Andreas Färber0315c312012-12-17 07:34:52 +0100159 if (other_cpu->running) {
pbrookd5975362008-06-07 20:50:51 +0000160 pending_cpus++;
Andreas Färber60a3e172013-05-17 18:26:54 +0200161 cpu_exit(other_cpu);
pbrookd5975362008-06-07 20:50:51 +0000162 }
163 }
164 if (pending_cpus > 1) {
165 pthread_cond_wait(&exclusive_cond, &exclusive_lock);
166 }
167}
168
169/* Finish an exclusive operation. */
170static inline void end_exclusive(void)
171{
172 pending_cpus = 0;
173 pthread_cond_broadcast(&exclusive_resume);
174 pthread_mutex_unlock(&exclusive_lock);
175}
176
177/* Wait for exclusive ops to finish, and begin cpu execution. */
Andreas Färber0315c312012-12-17 07:34:52 +0100178static inline void cpu_exec_start(CPUState *cpu)
pbrookd5975362008-06-07 20:50:51 +0000179{
180 pthread_mutex_lock(&exclusive_lock);
181 exclusive_idle();
Andreas Färber0315c312012-12-17 07:34:52 +0100182 cpu->running = true;
pbrookd5975362008-06-07 20:50:51 +0000183 pthread_mutex_unlock(&exclusive_lock);
184}
185
186/* Mark cpu as not executing, and release pending exclusive ops. */
Andreas Färber0315c312012-12-17 07:34:52 +0100187static inline void cpu_exec_end(CPUState *cpu)
pbrookd5975362008-06-07 20:50:51 +0000188{
189 pthread_mutex_lock(&exclusive_lock);
Andreas Färber0315c312012-12-17 07:34:52 +0100190 cpu->running = false;
pbrookd5975362008-06-07 20:50:51 +0000191 if (pending_cpus > 1) {
192 pending_cpus--;
193 if (pending_cpus == 1) {
194 pthread_cond_signal(&exclusive_cond);
195 }
196 }
197 exclusive_idle();
198 pthread_mutex_unlock(&exclusive_lock);
199}
pbrookc2764712009-03-07 15:24:59 +0000200
201void cpu_list_lock(void)
202{
203 pthread_mutex_lock(&cpu_list_mutex);
204}
205
206void cpu_list_unlock(void)
207{
208 pthread_mutex_unlock(&cpu_list_mutex);
209}
Juan Quintela2f7bb872009-07-27 16:13:24 +0200210#else /* if !CONFIG_USE_NPTL */
pbrookd5975362008-06-07 20:50:51 +0000211/* These are no-ops because we are not threadsafe. */
Andreas Färber0315c312012-12-17 07:34:52 +0100212static inline void cpu_exec_start(CPUState *cpu)
pbrookd5975362008-06-07 20:50:51 +0000213{
214}
215
Andreas Färber0315c312012-12-17 07:34:52 +0100216static inline void cpu_exec_end(CPUState *cpu)
pbrookd5975362008-06-07 20:50:51 +0000217{
218}
219
220static inline void start_exclusive(void)
221{
222}
223
224static inline void end_exclusive(void)
225{
226}
227
228void fork_start(void)
229{
230}
231
232void fork_end(int child)
233{
aurel322b1319c2008-12-18 22:44:04 +0000234 if (child) {
Andreas Färbera2247f82013-06-09 19:47:04 +0200235 gdbserver_fork((CPUArchState *)thread_cpu->env_ptr);
aurel322b1319c2008-12-18 22:44:04 +0000236 }
pbrookd5975362008-06-07 20:50:51 +0000237}
pbrookc2764712009-03-07 15:24:59 +0000238
239void cpu_list_lock(void)
240{
241}
242
243void cpu_list_unlock(void)
244{
245}
pbrookd5975362008-06-07 20:50:51 +0000246#endif
247
248
bellarda541f292004-04-12 20:39:29 +0000249#ifdef TARGET_I386
250/***********************************************************/
251/* CPUX86 core interface */
252
Andreas Färber05390242012-02-25 03:37:53 +0100253void cpu_smm_update(CPUX86State *env)
bellard02a16022006-09-24 18:48:23 +0000254{
255}
256
bellard28ab0e22004-05-20 14:02:14 +0000257uint64_t cpu_get_tsc(CPUX86State *env)
258{
259 return cpu_get_real_ticks();
260}
261
ths5fafdf22007-09-16 21:08:06 +0000262static void write_dt(void *ptr, unsigned long addr, unsigned long limit,
bellardf4beb512003-05-27 23:28:08 +0000263 int flags)
bellard6dbad632003-03-16 18:05:05 +0000264{
bellardf4beb512003-05-27 23:28:08 +0000265 unsigned int e1, e2;
pbrook53a59602006-03-25 19:31:22 +0000266 uint32_t *p;
bellard6dbad632003-03-16 18:05:05 +0000267 e1 = (addr << 16) | (limit & 0xffff);
268 e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
bellardf4beb512003-05-27 23:28:08 +0000269 e2 |= flags;
pbrook53a59602006-03-25 19:31:22 +0000270 p = ptr;
malcd538e8f2008-08-20 22:39:26 +0000271 p[0] = tswap32(e1);
272 p[1] = tswap32(e2);
bellardf4beb512003-05-27 23:28:08 +0000273}
274
balroge4415702008-11-10 02:55:33 +0000275static uint64_t *idt_table;
blueswir1eb38c522008-09-06 17:47:39 +0000276#ifdef TARGET_X86_64
bellardd2fd1af2007-11-14 18:08:56 +0000277static void set_gate64(void *ptr, unsigned int type, unsigned int dpl,
278 uint64_t addr, unsigned int sel)
279{
bellard4dbc4222007-11-15 15:27:03 +0000280 uint32_t *p, e1, e2;
bellardd2fd1af2007-11-14 18:08:56 +0000281 e1 = (addr & 0xffff) | (sel << 16);
282 e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
283 p = ptr;
bellard4dbc4222007-11-15 15:27:03 +0000284 p[0] = tswap32(e1);
285 p[1] = tswap32(e2);
286 p[2] = tswap32(addr >> 32);
287 p[3] = 0;
bellardd2fd1af2007-11-14 18:08:56 +0000288}
289/* only dpl matters as we do only user space emulation */
290static void set_idt(int n, unsigned int dpl)
291{
292 set_gate64(idt_table + n * 2, 0, dpl, 0, 0);
293}
294#else
ths5fafdf22007-09-16 21:08:06 +0000295static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
bellardd2fd1af2007-11-14 18:08:56 +0000296 uint32_t addr, unsigned int sel)
bellardf4beb512003-05-27 23:28:08 +0000297{
bellard4dbc4222007-11-15 15:27:03 +0000298 uint32_t *p, e1, e2;
bellardf4beb512003-05-27 23:28:08 +0000299 e1 = (addr & 0xffff) | (sel << 16);
300 e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
pbrook53a59602006-03-25 19:31:22 +0000301 p = ptr;
bellard4dbc4222007-11-15 15:27:03 +0000302 p[0] = tswap32(e1);
303 p[1] = tswap32(e2);
bellard6dbad632003-03-16 18:05:05 +0000304}
305
bellardf4beb512003-05-27 23:28:08 +0000306/* only dpl matters as we do only user space emulation */
307static void set_idt(int n, unsigned int dpl)
308{
309 set_gate(idt_table + n, 0, dpl, 0, 0);
310}
bellardd2fd1af2007-11-14 18:08:56 +0000311#endif
bellard31e31b82003-02-18 22:55:36 +0000312
bellard89e957e2003-05-10 12:33:15 +0000313void cpu_loop(CPUX86State *env)
bellard1b6b0292003-03-22 17:31:38 +0000314{
bellardbc8a22c2003-03-30 21:02:40 +0000315 int trapnr;
blueswir1992f48a2007-10-14 16:27:31 +0000316 abi_ulong pc;
Anthony Liguoric227f092009-10-01 16:12:16 -0500317 target_siginfo_t info;
bellard851e67a2003-03-29 16:53:14 +0000318
bellard1b6b0292003-03-22 17:31:38 +0000319 for(;;) {
bellardbc8a22c2003-03-30 21:02:40 +0000320 trapnr = cpu_x86_exec(env);
bellardbc8a22c2003-03-30 21:02:40 +0000321 switch(trapnr) {
bellardf4beb512003-05-27 23:28:08 +0000322 case 0x80:
bellardd2fd1af2007-11-14 18:08:56 +0000323 /* linux syscall from int $0x80 */
ths5fafdf22007-09-16 21:08:06 +0000324 env->regs[R_EAX] = do_syscall(env,
325 env->regs[R_EAX],
bellardf4beb512003-05-27 23:28:08 +0000326 env->regs[R_EBX],
327 env->regs[R_ECX],
328 env->regs[R_EDX],
329 env->regs[R_ESI],
330 env->regs[R_EDI],
Peter Maydell5945cfc2011-06-16 17:37:13 +0100331 env->regs[R_EBP],
332 0, 0);
bellardf4beb512003-05-27 23:28:08 +0000333 break;
bellardd2fd1af2007-11-14 18:08:56 +0000334#ifndef TARGET_ABI32
335 case EXCP_SYSCALL:
Stefan Weil5ba18542011-05-07 22:20:03 +0200336 /* linux syscall from syscall instruction */
bellardd2fd1af2007-11-14 18:08:56 +0000337 env->regs[R_EAX] = do_syscall(env,
338 env->regs[R_EAX],
339 env->regs[R_EDI],
340 env->regs[R_ESI],
341 env->regs[R_EDX],
342 env->regs[10],
343 env->regs[8],
Peter Maydell5945cfc2011-06-16 17:37:13 +0100344 env->regs[9],
345 0, 0);
bellardd2fd1af2007-11-14 18:08:56 +0000346 env->eip = env->exception_next_eip;
347 break;
348#endif
bellardf4beb512003-05-27 23:28:08 +0000349 case EXCP0B_NOSEG:
350 case EXCP0C_STACK:
351 info.si_signo = SIGBUS;
352 info.si_errno = 0;
353 info.si_code = TARGET_SI_KERNEL;
354 info._sifields._sigfault._addr = 0;
pbrook624f7972008-05-31 16:11:38 +0000355 queue_signal(env, info.si_signo, &info);
bellardf4beb512003-05-27 23:28:08 +0000356 break;
bellard1b6b0292003-03-22 17:31:38 +0000357 case EXCP0D_GPF:
bellardd2fd1af2007-11-14 18:08:56 +0000358 /* XXX: potential problem if ABI32 */
j_mayer84409dd2007-04-06 08:56:50 +0000359#ifndef TARGET_X86_64
bellard851e67a2003-03-29 16:53:14 +0000360 if (env->eflags & VM_MASK) {
bellard89e957e2003-05-10 12:33:15 +0000361 handle_vm86_fault(env);
j_mayer84409dd2007-04-06 08:56:50 +0000362 } else
363#endif
364 {
bellardf4beb512003-05-27 23:28:08 +0000365 info.si_signo = SIGSEGV;
366 info.si_errno = 0;
367 info.si_code = TARGET_SI_KERNEL;
368 info._sifields._sigfault._addr = 0;
pbrook624f7972008-05-31 16:11:38 +0000369 queue_signal(env, info.si_signo, &info);
bellard1b6b0292003-03-22 17:31:38 +0000370 }
371 break;
bellardb689bc52003-05-08 15:33:33 +0000372 case EXCP0E_PAGE:
373 info.si_signo = SIGSEGV;
374 info.si_errno = 0;
375 if (!(env->error_code & 1))
376 info.si_code = TARGET_SEGV_MAPERR;
377 else
378 info.si_code = TARGET_SEGV_ACCERR;
bellard970a87a2003-06-21 13:13:25 +0000379 info._sifields._sigfault._addr = env->cr[2];
pbrook624f7972008-05-31 16:11:38 +0000380 queue_signal(env, info.si_signo, &info);
bellardb689bc52003-05-08 15:33:33 +0000381 break;
bellard9de5e442003-03-23 16:49:39 +0000382 case EXCP00_DIVZ:
j_mayer84409dd2007-04-06 08:56:50 +0000383#ifndef TARGET_X86_64
bellardbc8a22c2003-03-30 21:02:40 +0000384 if (env->eflags & VM_MASK) {
bellard447db212003-05-10 15:10:36 +0000385 handle_vm86_trap(env, trapnr);
j_mayer84409dd2007-04-06 08:56:50 +0000386 } else
387#endif
388 {
bellardbc8a22c2003-03-30 21:02:40 +0000389 /* division by zero */
390 info.si_signo = SIGFPE;
391 info.si_errno = 0;
392 info.si_code = TARGET_FPE_INTDIV;
393 info._sifields._sigfault._addr = env->eip;
pbrook624f7972008-05-31 16:11:38 +0000394 queue_signal(env, info.si_signo, &info);
bellardbc8a22c2003-03-30 21:02:40 +0000395 }
bellard9de5e442003-03-23 16:49:39 +0000396 break;
aliguori01df0402008-11-18 21:08:15 +0000397 case EXCP01_DB:
bellard447db212003-05-10 15:10:36 +0000398 case EXCP03_INT3:
j_mayer84409dd2007-04-06 08:56:50 +0000399#ifndef TARGET_X86_64
bellard447db212003-05-10 15:10:36 +0000400 if (env->eflags & VM_MASK) {
401 handle_vm86_trap(env, trapnr);
j_mayer84409dd2007-04-06 08:56:50 +0000402 } else
403#endif
404 {
bellard447db212003-05-10 15:10:36 +0000405 info.si_signo = SIGTRAP;
406 info.si_errno = 0;
aliguori01df0402008-11-18 21:08:15 +0000407 if (trapnr == EXCP01_DB) {
bellard447db212003-05-10 15:10:36 +0000408 info.si_code = TARGET_TRAP_BRKPT;
409 info._sifields._sigfault._addr = env->eip;
410 } else {
411 info.si_code = TARGET_SI_KERNEL;
412 info._sifields._sigfault._addr = 0;
413 }
pbrook624f7972008-05-31 16:11:38 +0000414 queue_signal(env, info.si_signo, &info);
bellard447db212003-05-10 15:10:36 +0000415 }
416 break;
bellard9de5e442003-03-23 16:49:39 +0000417 case EXCP04_INTO:
418 case EXCP05_BOUND:
j_mayer84409dd2007-04-06 08:56:50 +0000419#ifndef TARGET_X86_64
bellardbc8a22c2003-03-30 21:02:40 +0000420 if (env->eflags & VM_MASK) {
bellard447db212003-05-10 15:10:36 +0000421 handle_vm86_trap(env, trapnr);
j_mayer84409dd2007-04-06 08:56:50 +0000422 } else
423#endif
424 {
bellardbc8a22c2003-03-30 21:02:40 +0000425 info.si_signo = SIGSEGV;
426 info.si_errno = 0;
bellardb689bc52003-05-08 15:33:33 +0000427 info.si_code = TARGET_SI_KERNEL;
bellardbc8a22c2003-03-30 21:02:40 +0000428 info._sifields._sigfault._addr = 0;
pbrook624f7972008-05-31 16:11:38 +0000429 queue_signal(env, info.si_signo, &info);
bellardbc8a22c2003-03-30 21:02:40 +0000430 }
bellard9de5e442003-03-23 16:49:39 +0000431 break;
432 case EXCP06_ILLOP:
433 info.si_signo = SIGILL;
434 info.si_errno = 0;
435 info.si_code = TARGET_ILL_ILLOPN;
436 info._sifields._sigfault._addr = env->eip;
pbrook624f7972008-05-31 16:11:38 +0000437 queue_signal(env, info.si_signo, &info);
bellard9de5e442003-03-23 16:49:39 +0000438 break;
439 case EXCP_INTERRUPT:
440 /* just indicate that signals should be handled asap */
441 break;
bellard1fddef42005-04-17 19:16:13 +0000442 case EXCP_DEBUG:
443 {
444 int sig;
445
446 sig = gdb_handlesig (env, TARGET_SIGTRAP);
447 if (sig)
448 {
449 info.si_signo = sig;
450 info.si_errno = 0;
451 info.si_code = TARGET_TRAP_BRKPT;
pbrook624f7972008-05-31 16:11:38 +0000452 queue_signal(env, info.si_signo, &info);
bellard1fddef42005-04-17 19:16:13 +0000453 }
454 }
455 break;
bellard1b6b0292003-03-22 17:31:38 +0000456 default:
bellard970a87a2003-06-21 13:13:25 +0000457 pc = env->segs[R_CS].base + env->eip;
ths5fafdf22007-09-16 21:08:06 +0000458 fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
bellardbc8a22c2003-03-30 21:02:40 +0000459 (long)pc, trapnr);
bellard1b6b0292003-03-22 17:31:38 +0000460 abort();
461 }
bellard66fb9762003-03-23 01:06:05 +0000462 process_pending_signals(env);
bellard1b6b0292003-03-22 17:31:38 +0000463 }
464}
bellardb346ff42003-06-15 20:05:50 +0000465#endif
466
467#ifdef TARGET_ARM
468
Paul Brookd8fd2952012-03-30 18:02:50 +0100469#define get_user_code_u32(x, gaddr, doswap) \
470 ({ abi_long __r = get_user_u32((x), (gaddr)); \
471 if (!__r && (doswap)) { \
472 (x) = bswap32(x); \
473 } \
474 __r; \
475 })
476
477#define get_user_code_u16(x, gaddr, doswap) \
478 ({ abi_long __r = get_user_u16((x), (gaddr)); \
479 if (!__r && (doswap)) { \
480 (x) = bswap16(x); \
481 } \
482 __r; \
483 })
484
Dr. David Alan Gilbert97cc7562011-08-31 17:24:34 +0100485/*
486 * See the Linux kernel's Documentation/arm/kernel_user_helpers.txt
487 * Input:
488 * r0 = pointer to oldval
489 * r1 = pointer to newval
490 * r2 = pointer to target value
491 *
492 * Output:
493 * r0 = 0 if *ptr was changed, non-0 if no exchange happened
494 * C set if *ptr was changed, clear if no exchange happened
495 *
496 * Note segv's in kernel helpers are a bit tricky, we can set the
497 * data address sensibly but the PC address is just the entry point.
498 */
499static void arm_kernel_cmpxchg64_helper(CPUARMState *env)
500{
501 uint64_t oldval, newval, val;
502 uint32_t addr, cpsr;
503 target_siginfo_t info;
504
505 /* Based on the 32 bit code in do_kernel_trap */
506
507 /* XXX: This only works between threads, not between processes.
508 It's probably possible to implement this with native host
509 operations. However things like ldrex/strex are much harder so
510 there's not much point trying. */
511 start_exclusive();
512 cpsr = cpsr_read(env);
513 addr = env->regs[2];
514
515 if (get_user_u64(oldval, env->regs[0])) {
516 env->cp15.c6_data = env->regs[0];
517 goto segv;
518 };
519
520 if (get_user_u64(newval, env->regs[1])) {
521 env->cp15.c6_data = env->regs[1];
522 goto segv;
523 };
524
525 if (get_user_u64(val, addr)) {
526 env->cp15.c6_data = addr;
527 goto segv;
528 }
529
530 if (val == oldval) {
531 val = newval;
532
533 if (put_user_u64(val, addr)) {
534 env->cp15.c6_data = addr;
535 goto segv;
536 };
537
538 env->regs[0] = 0;
539 cpsr |= CPSR_C;
540 } else {
541 env->regs[0] = -1;
542 cpsr &= ~CPSR_C;
543 }
544 cpsr_write(env, cpsr, CPSR_C);
545 end_exclusive();
546 return;
547
548segv:
549 end_exclusive();
550 /* We get the PC of the entry address - which is as good as anything,
551 on a real kernel what you get depends on which mode it uses. */
552 info.si_signo = SIGSEGV;
553 info.si_errno = 0;
554 /* XXX: check env->error_code */
555 info.si_code = TARGET_SEGV_MAPERR;
556 info._sifields._sigfault._addr = env->cp15.c6_data;
557 queue_signal(env, info.si_signo, &info);
558
559 end_exclusive();
560}
561
pbrookfbb4a2e2008-05-29 00:20:44 +0000562/* Handle a jump to the kernel code page. */
563static int
564do_kernel_trap(CPUARMState *env)
565{
566 uint32_t addr;
567 uint32_t cpsr;
568 uint32_t val;
569
570 switch (env->regs[15]) {
571 case 0xffff0fa0: /* __kernel_memory_barrier */
572 /* ??? No-op. Will need to do better for SMP. */
573 break;
574 case 0xffff0fc0: /* __kernel_cmpxchg */
pbrookd5975362008-06-07 20:50:51 +0000575 /* XXX: This only works between threads, not between processes.
576 It's probably possible to implement this with native host
577 operations. However things like ldrex/strex are much harder so
578 there's not much point trying. */
579 start_exclusive();
pbrookfbb4a2e2008-05-29 00:20:44 +0000580 cpsr = cpsr_read(env);
581 addr = env->regs[2];
582 /* FIXME: This should SEGV if the access fails. */
583 if (get_user_u32(val, addr))
584 val = ~env->regs[0];
585 if (val == env->regs[0]) {
586 val = env->regs[1];
587 /* FIXME: Check for segfaults. */
588 put_user_u32(val, addr);
589 env->regs[0] = 0;
590 cpsr |= CPSR_C;
591 } else {
592 env->regs[0] = -1;
593 cpsr &= ~CPSR_C;
594 }
595 cpsr_write(env, cpsr, CPSR_C);
pbrookd5975362008-06-07 20:50:51 +0000596 end_exclusive();
pbrookfbb4a2e2008-05-29 00:20:44 +0000597 break;
598 case 0xffff0fe0: /* __kernel_get_tls */
599 env->regs[0] = env->cp15.c13_tls2;
600 break;
Dr. David Alan Gilbert97cc7562011-08-31 17:24:34 +0100601 case 0xffff0f60: /* __kernel_cmpxchg64 */
602 arm_kernel_cmpxchg64_helper(env);
603 break;
604
pbrookfbb4a2e2008-05-29 00:20:44 +0000605 default:
606 return 1;
607 }
608 /* Jump back to the caller. */
609 addr = env->regs[14];
610 if (addr & 1) {
611 env->thumb = 1;
612 addr &= ~1;
613 }
614 env->regs[15] = addr;
615
616 return 0;
617}
618
Paul Brook426f5ab2009-11-22 21:35:13 +0000619static int do_strex(CPUARMState *env)
620{
621 uint32_t val;
622 int size;
623 int rc = 1;
624 int segv = 0;
625 uint32_t addr;
626 start_exclusive();
627 addr = env->exclusive_addr;
628 if (addr != env->exclusive_test) {
629 goto fail;
630 }
631 size = env->exclusive_info & 0xf;
632 switch (size) {
633 case 0:
634 segv = get_user_u8(val, addr);
635 break;
636 case 1:
637 segv = get_user_u16(val, addr);
638 break;
639 case 2:
640 case 3:
641 segv = get_user_u32(val, addr);
642 break;
Aurelien Jarnof7001a32009-12-24 00:17:12 +0100643 default:
644 abort();
Paul Brook426f5ab2009-11-22 21:35:13 +0000645 }
646 if (segv) {
647 env->cp15.c6_data = addr;
648 goto done;
649 }
650 if (val != env->exclusive_val) {
651 goto fail;
652 }
653 if (size == 3) {
654 segv = get_user_u32(val, addr + 4);
655 if (segv) {
656 env->cp15.c6_data = addr + 4;
657 goto done;
658 }
659 if (val != env->exclusive_high) {
660 goto fail;
661 }
662 }
663 val = env->regs[(env->exclusive_info >> 8) & 0xf];
664 switch (size) {
665 case 0:
666 segv = put_user_u8(val, addr);
667 break;
668 case 1:
669 segv = put_user_u16(val, addr);
670 break;
671 case 2:
672 case 3:
673 segv = put_user_u32(val, addr);
674 break;
675 }
676 if (segv) {
677 env->cp15.c6_data = addr;
678 goto done;
679 }
680 if (size == 3) {
681 val = env->regs[(env->exclusive_info >> 12) & 0xf];
Peter Maydell2c9adbd2010-12-07 15:37:34 +0000682 segv = put_user_u32(val, addr + 4);
Paul Brook426f5ab2009-11-22 21:35:13 +0000683 if (segv) {
684 env->cp15.c6_data = addr + 4;
685 goto done;
686 }
687 }
688 rc = 0;
689fail:
Paul Brook725b8a62009-12-11 15:38:10 +0000690 env->regs[15] += 4;
Paul Brook426f5ab2009-11-22 21:35:13 +0000691 env->regs[(env->exclusive_info >> 4) & 0xf] = rc;
692done:
693 end_exclusive();
694 return segv;
695}
696
bellardb346ff42003-06-15 20:05:50 +0000697void cpu_loop(CPUARMState *env)
698{
Andreas Färber0315c312012-12-17 07:34:52 +0100699 CPUState *cs = CPU(arm_env_get_cpu(env));
bellardb346ff42003-06-15 20:05:50 +0000700 int trapnr;
701 unsigned int n, insn;
Anthony Liguoric227f092009-10-01 16:12:16 -0500702 target_siginfo_t info;
bellardb5ff1b32005-11-26 10:38:39 +0000703 uint32_t addr;
ths3b46e622007-09-17 08:09:54 +0000704
bellardb346ff42003-06-15 20:05:50 +0000705 for(;;) {
Andreas Färber0315c312012-12-17 07:34:52 +0100706 cpu_exec_start(cs);
bellardb346ff42003-06-15 20:05:50 +0000707 trapnr = cpu_arm_exec(env);
Andreas Färber0315c312012-12-17 07:34:52 +0100708 cpu_exec_end(cs);
bellardb346ff42003-06-15 20:05:50 +0000709 switch(trapnr) {
710 case EXCP_UDEF:
bellardc6981052004-02-16 21:49:03 +0000711 {
712 TaskState *ts = env->opaque;
713 uint32_t opcode;
aurel326d9a42b2008-04-07 20:30:53 +0000714 int rc;
bellardc6981052004-02-16 21:49:03 +0000715
716 /* we handle the FPU emulation here, as Linux */
717 /* we get the opcode */
bellard2f619692007-11-16 10:46:05 +0000718 /* FIXME - what to do if get_user() fails? */
Paul Brookd8fd2952012-03-30 18:02:50 +0100719 get_user_code_u32(opcode, env->regs[15], env->bswap_code);
ths3b46e622007-09-17 08:09:54 +0000720
aurel326d9a42b2008-04-07 20:30:53 +0000721 rc = EmulateAll(opcode, &ts->fpa, env);
722 if (rc == 0) { /* illegal instruction */
bellardc6981052004-02-16 21:49:03 +0000723 info.si_signo = SIGILL;
724 info.si_errno = 0;
725 info.si_code = TARGET_ILL_ILLOPN;
726 info._sifields._sigfault._addr = env->regs[15];
pbrook624f7972008-05-31 16:11:38 +0000727 queue_signal(env, info.si_signo, &info);
aurel326d9a42b2008-04-07 20:30:53 +0000728 } else if (rc < 0) { /* FP exception */
729 int arm_fpe=0;
730
731 /* translate softfloat flags to FPSR flags */
732 if (-rc & float_flag_invalid)
733 arm_fpe |= BIT_IOC;
734 if (-rc & float_flag_divbyzero)
735 arm_fpe |= BIT_DZC;
736 if (-rc & float_flag_overflow)
737 arm_fpe |= BIT_OFC;
738 if (-rc & float_flag_underflow)
739 arm_fpe |= BIT_UFC;
740 if (-rc & float_flag_inexact)
741 arm_fpe |= BIT_IXC;
742
743 FPSR fpsr = ts->fpa.fpsr;
744 //printf("fpsr 0x%x, arm_fpe 0x%x\n",fpsr,arm_fpe);
745
746 if (fpsr & (arm_fpe << 16)) { /* exception enabled? */
747 info.si_signo = SIGFPE;
748 info.si_errno = 0;
749
750 /* ordered by priority, least first */
751 if (arm_fpe & BIT_IXC) info.si_code = TARGET_FPE_FLTRES;
752 if (arm_fpe & BIT_UFC) info.si_code = TARGET_FPE_FLTUND;
753 if (arm_fpe & BIT_OFC) info.si_code = TARGET_FPE_FLTOVF;
754 if (arm_fpe & BIT_DZC) info.si_code = TARGET_FPE_FLTDIV;
755 if (arm_fpe & BIT_IOC) info.si_code = TARGET_FPE_FLTINV;
756
757 info._sifields._sigfault._addr = env->regs[15];
pbrook624f7972008-05-31 16:11:38 +0000758 queue_signal(env, info.si_signo, &info);
aurel326d9a42b2008-04-07 20:30:53 +0000759 } else {
760 env->regs[15] += 4;
761 }
762
763 /* accumulate unenabled exceptions */
764 if ((!(fpsr & BIT_IXE)) && (arm_fpe & BIT_IXC))
765 fpsr |= BIT_IXC;
766 if ((!(fpsr & BIT_UFE)) && (arm_fpe & BIT_UFC))
767 fpsr |= BIT_UFC;
768 if ((!(fpsr & BIT_OFE)) && (arm_fpe & BIT_OFC))
769 fpsr |= BIT_OFC;
770 if ((!(fpsr & BIT_DZE)) && (arm_fpe & BIT_DZC))
771 fpsr |= BIT_DZC;
772 if ((!(fpsr & BIT_IOE)) && (arm_fpe & BIT_IOC))
773 fpsr |= BIT_IOC;
774 ts->fpa.fpsr=fpsr;
775 } else { /* everything OK */
bellardc6981052004-02-16 21:49:03 +0000776 /* increment PC */
777 env->regs[15] += 4;
778 }
779 }
bellardb346ff42003-06-15 20:05:50 +0000780 break;
781 case EXCP_SWI:
pbrook06c949e2006-02-04 19:35:26 +0000782 case EXCP_BKPT:
bellardb346ff42003-06-15 20:05:50 +0000783 {
pbrookce4defa2006-02-09 16:49:55 +0000784 env->eabi = 1;
bellardb346ff42003-06-15 20:05:50 +0000785 /* system call */
pbrook06c949e2006-02-04 19:35:26 +0000786 if (trapnr == EXCP_BKPT) {
787 if (env->thumb) {
bellard2f619692007-11-16 10:46:05 +0000788 /* FIXME - what to do if get_user() fails? */
Paul Brookd8fd2952012-03-30 18:02:50 +0100789 get_user_code_u16(insn, env->regs[15], env->bswap_code);
pbrook06c949e2006-02-04 19:35:26 +0000790 n = insn & 0xff;
791 env->regs[15] += 2;
792 } else {
bellard2f619692007-11-16 10:46:05 +0000793 /* FIXME - what to do if get_user() fails? */
Paul Brookd8fd2952012-03-30 18:02:50 +0100794 get_user_code_u32(insn, env->regs[15], env->bswap_code);
pbrook06c949e2006-02-04 19:35:26 +0000795 n = (insn & 0xf) | ((insn >> 4) & 0xff0);
796 env->regs[15] += 4;
797 }
bellard192c7bd2005-04-27 20:11:21 +0000798 } else {
pbrook06c949e2006-02-04 19:35:26 +0000799 if (env->thumb) {
bellard2f619692007-11-16 10:46:05 +0000800 /* FIXME - what to do if get_user() fails? */
Paul Brookd8fd2952012-03-30 18:02:50 +0100801 get_user_code_u16(insn, env->regs[15] - 2,
802 env->bswap_code);
pbrook06c949e2006-02-04 19:35:26 +0000803 n = insn & 0xff;
804 } else {
bellard2f619692007-11-16 10:46:05 +0000805 /* FIXME - what to do if get_user() fails? */
Paul Brookd8fd2952012-03-30 18:02:50 +0100806 get_user_code_u32(insn, env->regs[15] - 4,
807 env->bswap_code);
pbrook06c949e2006-02-04 19:35:26 +0000808 n = insn & 0xffffff;
809 }
bellard192c7bd2005-04-27 20:11:21 +0000810 }
811
bellard6f1f31c2004-04-25 18:00:45 +0000812 if (n == ARM_NR_cacheflush) {
Blue Swirldcfd14b2011-05-14 11:55:30 +0000813 /* nop */
bellarda4f81972005-04-23 18:25:41 +0000814 } else if (n == ARM_NR_semihosting
815 || n == ARM_NR_thumb_semihosting) {
816 env->regs[0] = do_arm_semihosting (env);
Alexander Graf3a1363a2012-05-29 05:30:26 +0000817 } else if (n == 0 || n >= ARM_SYSCALL_BASE || env->thumb) {
bellardb346ff42003-06-15 20:05:50 +0000818 /* linux syscall */
pbrookce4defa2006-02-09 16:49:55 +0000819 if (env->thumb || n == 0) {
bellard192c7bd2005-04-27 20:11:21 +0000820 n = env->regs[7];
821 } else {
822 n -= ARM_SYSCALL_BASE;
pbrookce4defa2006-02-09 16:49:55 +0000823 env->eabi = 0;
bellard192c7bd2005-04-27 20:11:21 +0000824 }
pbrookfbb4a2e2008-05-29 00:20:44 +0000825 if ( n > ARM_NR_BASE) {
826 switch (n) {
827 case ARM_NR_cacheflush:
Blue Swirldcfd14b2011-05-14 11:55:30 +0000828 /* nop */
pbrookfbb4a2e2008-05-29 00:20:44 +0000829 break;
830 case ARM_NR_set_tls:
831 cpu_set_tls(env, env->regs[0]);
832 env->regs[0] = 0;
833 break;
834 default:
835 gemu_log("qemu: Unsupported ARM syscall: 0x%x\n",
836 n);
837 env->regs[0] = -TARGET_ENOSYS;
838 break;
839 }
840 } else {
841 env->regs[0] = do_syscall(env,
842 n,
843 env->regs[0],
844 env->regs[1],
845 env->regs[2],
846 env->regs[3],
847 env->regs[4],
Peter Maydell5945cfc2011-06-16 17:37:13 +0100848 env->regs[5],
849 0, 0);
pbrookfbb4a2e2008-05-29 00:20:44 +0000850 }
bellardb346ff42003-06-15 20:05:50 +0000851 } else {
852 goto error;
853 }
854 }
855 break;
bellard43fff232003-07-09 19:31:39 +0000856 case EXCP_INTERRUPT:
857 /* just indicate that signals should be handled asap */
858 break;
bellard68016c62005-02-07 23:12:27 +0000859 case EXCP_PREFETCH_ABORT:
balrogeae473c2008-07-29 14:09:57 +0000860 addr = env->cp15.c6_insn;
bellardb5ff1b32005-11-26 10:38:39 +0000861 goto do_segv;
bellard68016c62005-02-07 23:12:27 +0000862 case EXCP_DATA_ABORT:
balrogeae473c2008-07-29 14:09:57 +0000863 addr = env->cp15.c6_data;
bellardb5ff1b32005-11-26 10:38:39 +0000864 do_segv:
bellard68016c62005-02-07 23:12:27 +0000865 {
866 info.si_signo = SIGSEGV;
867 info.si_errno = 0;
868 /* XXX: check env->error_code */
869 info.si_code = TARGET_SEGV_MAPERR;
bellardb5ff1b32005-11-26 10:38:39 +0000870 info._sifields._sigfault._addr = addr;
pbrook624f7972008-05-31 16:11:38 +0000871 queue_signal(env, info.si_signo, &info);
bellard68016c62005-02-07 23:12:27 +0000872 }
873 break;
bellard1fddef42005-04-17 19:16:13 +0000874 case EXCP_DEBUG:
875 {
876 int sig;
877
878 sig = gdb_handlesig (env, TARGET_SIGTRAP);
879 if (sig)
880 {
881 info.si_signo = sig;
882 info.si_errno = 0;
883 info.si_code = TARGET_TRAP_BRKPT;
pbrook624f7972008-05-31 16:11:38 +0000884 queue_signal(env, info.si_signo, &info);
bellard1fddef42005-04-17 19:16:13 +0000885 }
886 }
887 break;
pbrookfbb4a2e2008-05-29 00:20:44 +0000888 case EXCP_KERNEL_TRAP:
889 if (do_kernel_trap(env))
890 goto error;
891 break;
Paul Brook426f5ab2009-11-22 21:35:13 +0000892 case EXCP_STREX:
893 if (do_strex(env)) {
894 addr = env->cp15.c6_data;
895 goto do_segv;
896 }
Paul Brooke9273452009-11-24 13:10:08 +0000897 break;
bellardb346ff42003-06-15 20:05:50 +0000898 default:
899 error:
ths5fafdf22007-09-16 21:08:06 +0000900 fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
bellardb346ff42003-06-15 20:05:50 +0000901 trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +0200902 cpu_dump_state(cs, stderr, fprintf, 0);
bellardb346ff42003-06-15 20:05:50 +0000903 abort();
904 }
905 process_pending_signals(env);
906 }
907}
908
909#endif
bellard1b6b0292003-03-22 17:31:38 +0000910
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800911#ifdef TARGET_UNICORE32
912
Andreas Färber05390242012-02-25 03:37:53 +0100913void cpu_loop(CPUUniCore32State *env)
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800914{
Andreas Färber0315c312012-12-17 07:34:52 +0100915 CPUState *cs = CPU(uc32_env_get_cpu(env));
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800916 int trapnr;
917 unsigned int n, insn;
918 target_siginfo_t info;
919
920 for (;;) {
Andreas Färber0315c312012-12-17 07:34:52 +0100921 cpu_exec_start(cs);
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800922 trapnr = uc32_cpu_exec(env);
Andreas Färber0315c312012-12-17 07:34:52 +0100923 cpu_exec_end(cs);
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800924 switch (trapnr) {
925 case UC32_EXCP_PRIV:
926 {
927 /* system call */
928 get_user_u32(insn, env->regs[31] - 4);
929 n = insn & 0xffffff;
930
931 if (n >= UC32_SYSCALL_BASE) {
932 /* linux syscall */
933 n -= UC32_SYSCALL_BASE;
934 if (n == UC32_SYSCALL_NR_set_tls) {
935 cpu_set_tls(env, env->regs[0]);
936 env->regs[0] = 0;
937 } else {
938 env->regs[0] = do_syscall(env,
939 n,
940 env->regs[0],
941 env->regs[1],
942 env->regs[2],
943 env->regs[3],
944 env->regs[4],
Peter Maydell5945cfc2011-06-16 17:37:13 +0100945 env->regs[5],
946 0, 0);
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800947 }
948 } else {
949 goto error;
950 }
951 }
952 break;
Guan Xuetaod48813d2012-08-10 14:42:23 +0800953 case UC32_EXCP_DTRAP:
954 case UC32_EXCP_ITRAP:
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800955 info.si_signo = SIGSEGV;
956 info.si_errno = 0;
957 /* XXX: check env->error_code */
958 info.si_code = TARGET_SEGV_MAPERR;
959 info._sifields._sigfault._addr = env->cp0.c4_faultaddr;
960 queue_signal(env, info.si_signo, &info);
961 break;
962 case EXCP_INTERRUPT:
963 /* just indicate that signals should be handled asap */
964 break;
965 case EXCP_DEBUG:
966 {
967 int sig;
968
969 sig = gdb_handlesig(env, TARGET_SIGTRAP);
970 if (sig) {
971 info.si_signo = sig;
972 info.si_errno = 0;
973 info.si_code = TARGET_TRAP_BRKPT;
974 queue_signal(env, info.si_signo, &info);
975 }
976 }
977 break;
978 default:
979 goto error;
980 }
981 process_pending_signals(env);
982 }
983
984error:
985 fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +0200986 cpu_dump_state(cs, stderr, fprintf, 0);
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800987 abort();
988}
989#endif
990
bellard93ac68b2003-09-30 20:57:29 +0000991#ifdef TARGET_SPARC
blueswir1ed23fbd2008-08-30 09:20:21 +0000992#define SPARC64_STACK_BIAS 2047
bellard93ac68b2003-09-30 20:57:29 +0000993
bellard060366c2004-01-04 15:50:01 +0000994//#define DEBUG_WIN
995
bellard2623cba2005-02-19 17:25:31 +0000996/* WARNING: dealing with register windows _is_ complicated. More info
997 can be found at http://www.sics.se/~psm/sparcstack.html */
bellard060366c2004-01-04 15:50:01 +0000998static inline int get_reg_index(CPUSPARCState *env, int cwp, int index)
999{
blueswir11a140262008-06-07 08:07:37 +00001000 index = (index + cwp * 16) % (16 * env->nwindows);
bellard060366c2004-01-04 15:50:01 +00001001 /* wrap handling : if cwp is on the last window, then we use the
1002 registers 'after' the end */
blueswir11a140262008-06-07 08:07:37 +00001003 if (index < 8 && env->cwp == env->nwindows - 1)
1004 index += 16 * env->nwindows;
bellard060366c2004-01-04 15:50:01 +00001005 return index;
1006}
1007
bellard2623cba2005-02-19 17:25:31 +00001008/* save the register window 'cwp1' */
1009static inline void save_window_offset(CPUSPARCState *env, int cwp1)
bellard060366c2004-01-04 15:50:01 +00001010{
bellard2623cba2005-02-19 17:25:31 +00001011 unsigned int i;
blueswir1992f48a2007-10-14 16:27:31 +00001012 abi_ulong sp_ptr;
ths3b46e622007-09-17 08:09:54 +00001013
pbrook53a59602006-03-25 19:31:22 +00001014 sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
blueswir1ed23fbd2008-08-30 09:20:21 +00001015#ifdef TARGET_SPARC64
1016 if (sp_ptr & 3)
1017 sp_ptr += SPARC64_STACK_BIAS;
1018#endif
bellard060366c2004-01-04 15:50:01 +00001019#if defined(DEBUG_WIN)
blueswir12daf0282008-06-15 18:02:48 +00001020 printf("win_overflow: sp_ptr=0x" TARGET_ABI_FMT_lx " save_cwp=%d\n",
1021 sp_ptr, cwp1);
bellard060366c2004-01-04 15:50:01 +00001022#endif
bellard2623cba2005-02-19 17:25:31 +00001023 for(i = 0; i < 16; i++) {
bellard2f619692007-11-16 10:46:05 +00001024 /* FIXME - what to do if put_user() fails? */
1025 put_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
blueswir1992f48a2007-10-14 16:27:31 +00001026 sp_ptr += sizeof(abi_ulong);
bellard2623cba2005-02-19 17:25:31 +00001027 }
bellard060366c2004-01-04 15:50:01 +00001028}
1029
1030static void save_window(CPUSPARCState *env)
1031{
bellard5ef54112006-07-18 21:14:09 +00001032#ifndef TARGET_SPARC64
bellard2623cba2005-02-19 17:25:31 +00001033 unsigned int new_wim;
blueswir11a140262008-06-07 08:07:37 +00001034 new_wim = ((env->wim >> 1) | (env->wim << (env->nwindows - 1))) &
1035 ((1LL << env->nwindows) - 1);
1036 save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
bellard2623cba2005-02-19 17:25:31 +00001037 env->wim = new_wim;
bellard5ef54112006-07-18 21:14:09 +00001038#else
blueswir11a140262008-06-07 08:07:37 +00001039 save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
bellard5ef54112006-07-18 21:14:09 +00001040 env->cansave++;
1041 env->canrestore--;
1042#endif
bellard060366c2004-01-04 15:50:01 +00001043}
1044
1045static void restore_window(CPUSPARCState *env)
1046{
blueswir1eda52952008-08-27 19:19:44 +00001047#ifndef TARGET_SPARC64
1048 unsigned int new_wim;
1049#endif
1050 unsigned int i, cwp1;
blueswir1992f48a2007-10-14 16:27:31 +00001051 abi_ulong sp_ptr;
ths3b46e622007-09-17 08:09:54 +00001052
blueswir1eda52952008-08-27 19:19:44 +00001053#ifndef TARGET_SPARC64
blueswir11a140262008-06-07 08:07:37 +00001054 new_wim = ((env->wim << 1) | (env->wim >> (env->nwindows - 1))) &
1055 ((1LL << env->nwindows) - 1);
blueswir1eda52952008-08-27 19:19:44 +00001056#endif
ths3b46e622007-09-17 08:09:54 +00001057
bellard060366c2004-01-04 15:50:01 +00001058 /* restore the invalid window */
blueswir11a140262008-06-07 08:07:37 +00001059 cwp1 = cpu_cwp_inc(env, env->cwp + 1);
pbrook53a59602006-03-25 19:31:22 +00001060 sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
blueswir1ed23fbd2008-08-30 09:20:21 +00001061#ifdef TARGET_SPARC64
1062 if (sp_ptr & 3)
1063 sp_ptr += SPARC64_STACK_BIAS;
1064#endif
bellard060366c2004-01-04 15:50:01 +00001065#if defined(DEBUG_WIN)
blueswir12daf0282008-06-15 18:02:48 +00001066 printf("win_underflow: sp_ptr=0x" TARGET_ABI_FMT_lx " load_cwp=%d\n",
1067 sp_ptr, cwp1);
bellard060366c2004-01-04 15:50:01 +00001068#endif
bellard2623cba2005-02-19 17:25:31 +00001069 for(i = 0; i < 16; i++) {
bellard2f619692007-11-16 10:46:05 +00001070 /* FIXME - what to do if get_user() fails? */
1071 get_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
blueswir1992f48a2007-10-14 16:27:31 +00001072 sp_ptr += sizeof(abi_ulong);
bellard2623cba2005-02-19 17:25:31 +00001073 }
bellard5ef54112006-07-18 21:14:09 +00001074#ifdef TARGET_SPARC64
1075 env->canrestore++;
blueswir11a140262008-06-07 08:07:37 +00001076 if (env->cleanwin < env->nwindows - 1)
1077 env->cleanwin++;
bellard5ef54112006-07-18 21:14:09 +00001078 env->cansave--;
blueswir1eda52952008-08-27 19:19:44 +00001079#else
1080 env->wim = new_wim;
bellard5ef54112006-07-18 21:14:09 +00001081#endif
bellard060366c2004-01-04 15:50:01 +00001082}
1083
1084static void flush_windows(CPUSPARCState *env)
1085{
1086 int offset, cwp1;
bellard2623cba2005-02-19 17:25:31 +00001087
1088 offset = 1;
bellard060366c2004-01-04 15:50:01 +00001089 for(;;) {
1090 /* if restore would invoke restore_window(), then we can stop */
blueswir11a140262008-06-07 08:07:37 +00001091 cwp1 = cpu_cwp_inc(env, env->cwp + offset);
blueswir1eda52952008-08-27 19:19:44 +00001092#ifndef TARGET_SPARC64
bellard060366c2004-01-04 15:50:01 +00001093 if (env->wim & (1 << cwp1))
1094 break;
blueswir1eda52952008-08-27 19:19:44 +00001095#else
1096 if (env->canrestore == 0)
1097 break;
1098 env->cansave++;
1099 env->canrestore--;
1100#endif
bellard2623cba2005-02-19 17:25:31 +00001101 save_window_offset(env, cwp1);
bellard060366c2004-01-04 15:50:01 +00001102 offset++;
1103 }
blueswir11a140262008-06-07 08:07:37 +00001104 cwp1 = cpu_cwp_inc(env, env->cwp + 1);
blueswir1eda52952008-08-27 19:19:44 +00001105#ifndef TARGET_SPARC64
1106 /* set wim so that restore will reload the registers */
bellard2623cba2005-02-19 17:25:31 +00001107 env->wim = 1 << cwp1;
blueswir1eda52952008-08-27 19:19:44 +00001108#endif
bellard2623cba2005-02-19 17:25:31 +00001109#if defined(DEBUG_WIN)
1110 printf("flush_windows: nb=%d\n", offset - 1);
bellard80a9d032005-01-03 23:31:27 +00001111#endif
bellard2623cba2005-02-19 17:25:31 +00001112}
bellard060366c2004-01-04 15:50:01 +00001113
bellard93ac68b2003-09-30 20:57:29 +00001114void cpu_loop (CPUSPARCState *env)
1115{
Andreas Färber878096e2013-05-27 01:33:50 +02001116 CPUState *cs = CPU(sparc_env_get_cpu(env));
Richard Henderson2cc20262010-04-25 11:01:25 -07001117 int trapnr;
1118 abi_long ret;
Anthony Liguoric227f092009-10-01 16:12:16 -05001119 target_siginfo_t info;
ths3b46e622007-09-17 08:09:54 +00001120
bellard060366c2004-01-04 15:50:01 +00001121 while (1) {
1122 trapnr = cpu_sparc_exec (env);
ths3b46e622007-09-17 08:09:54 +00001123
Richard Henderson20132b92012-10-09 14:50:00 -07001124 /* Compute PSR before exposing state. */
1125 if (env->cc_op != CC_OP_FLAGS) {
1126 cpu_get_psr(env);
1127 }
1128
bellard060366c2004-01-04 15:50:01 +00001129 switch (trapnr) {
bellard5ef54112006-07-18 21:14:09 +00001130#ifndef TARGET_SPARC64
ths5fafdf22007-09-16 21:08:06 +00001131 case 0x88:
bellard060366c2004-01-04 15:50:01 +00001132 case 0x90:
bellard5ef54112006-07-18 21:14:09 +00001133#else
blueswir1cb33da52007-10-09 16:34:29 +00001134 case 0x110:
bellard5ef54112006-07-18 21:14:09 +00001135 case 0x16d:
1136#endif
bellard060366c2004-01-04 15:50:01 +00001137 ret = do_syscall (env, env->gregs[1],
ths5fafdf22007-09-16 21:08:06 +00001138 env->regwptr[0], env->regwptr[1],
1139 env->regwptr[2], env->regwptr[3],
Peter Maydell5945cfc2011-06-16 17:37:13 +01001140 env->regwptr[4], env->regwptr[5],
1141 0, 0);
Richard Henderson2cc20262010-04-25 11:01:25 -07001142 if ((abi_ulong)ret >= (abi_ulong)(-515)) {
blueswir1992f48a2007-10-14 16:27:31 +00001143#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
bellard27908722006-10-23 21:31:01 +00001144 env->xcc |= PSR_CARRY;
1145#else
bellard060366c2004-01-04 15:50:01 +00001146 env->psr |= PSR_CARRY;
bellard27908722006-10-23 21:31:01 +00001147#endif
bellard060366c2004-01-04 15:50:01 +00001148 ret = -ret;
1149 } else {
blueswir1992f48a2007-10-14 16:27:31 +00001150#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
bellard27908722006-10-23 21:31:01 +00001151 env->xcc &= ~PSR_CARRY;
1152#else
bellard060366c2004-01-04 15:50:01 +00001153 env->psr &= ~PSR_CARRY;
bellard27908722006-10-23 21:31:01 +00001154#endif
bellard060366c2004-01-04 15:50:01 +00001155 }
1156 env->regwptr[0] = ret;
1157 /* next instruction */
1158 env->pc = env->npc;
1159 env->npc = env->npc + 4;
1160 break;
1161 case 0x83: /* flush windows */
blueswir1992f48a2007-10-14 16:27:31 +00001162#ifdef TARGET_ABI32
1163 case 0x103:
1164#endif
bellard2623cba2005-02-19 17:25:31 +00001165 flush_windows(env);
bellard060366c2004-01-04 15:50:01 +00001166 /* next instruction */
1167 env->pc = env->npc;
1168 env->npc = env->npc + 4;
1169 break;
bellard34751872005-07-02 14:31:34 +00001170#ifndef TARGET_SPARC64
bellard060366c2004-01-04 15:50:01 +00001171 case TT_WIN_OVF: /* window overflow */
1172 save_window(env);
1173 break;
1174 case TT_WIN_UNF: /* window underflow */
1175 restore_window(env);
1176 break;
bellard61ff6f52005-02-15 22:54:53 +00001177 case TT_TFAULT:
1178 case TT_DFAULT:
1179 {
Richard Henderson59f71822011-10-25 10:34:07 -07001180 info.si_signo = TARGET_SIGSEGV;
bellard61ff6f52005-02-15 22:54:53 +00001181 info.si_errno = 0;
1182 /* XXX: check env->error_code */
1183 info.si_code = TARGET_SEGV_MAPERR;
1184 info._sifields._sigfault._addr = env->mmuregs[4];
pbrook624f7972008-05-31 16:11:38 +00001185 queue_signal(env, info.si_signo, &info);
bellard61ff6f52005-02-15 22:54:53 +00001186 }
1187 break;
bellard34751872005-07-02 14:31:34 +00001188#else
bellard5ef54112006-07-18 21:14:09 +00001189 case TT_SPILL: /* window overflow */
1190 save_window(env);
1191 break;
1192 case TT_FILL: /* window underflow */
1193 restore_window(env);
1194 break;
blueswir17f84a722007-07-07 20:46:41 +00001195 case TT_TFAULT:
1196 case TT_DFAULT:
1197 {
Richard Henderson59f71822011-10-25 10:34:07 -07001198 info.si_signo = TARGET_SIGSEGV;
blueswir17f84a722007-07-07 20:46:41 +00001199 info.si_errno = 0;
1200 /* XXX: check env->error_code */
1201 info.si_code = TARGET_SEGV_MAPERR;
1202 if (trapnr == TT_DFAULT)
1203 info._sifields._sigfault._addr = env->dmmuregs[4];
1204 else
Igor Kovalenko8194f352009-08-03 23:15:02 +04001205 info._sifields._sigfault._addr = cpu_tsptr(env)->tpc;
pbrook624f7972008-05-31 16:11:38 +00001206 queue_signal(env, info.si_signo, &info);
blueswir17f84a722007-07-07 20:46:41 +00001207 }
1208 break;
bellard27524dc2007-11-11 19:32:52 +00001209#ifndef TARGET_ABI32
blueswir15bfb56b2007-10-05 17:01:51 +00001210 case 0x16e:
1211 flush_windows(env);
1212 sparc64_get_context(env);
1213 break;
1214 case 0x16f:
1215 flush_windows(env);
1216 sparc64_set_context(env);
1217 break;
bellard34751872005-07-02 14:31:34 +00001218#endif
bellard27524dc2007-11-11 19:32:52 +00001219#endif
bellard48dc41e2006-06-21 18:15:50 +00001220 case EXCP_INTERRUPT:
1221 /* just indicate that signals should be handled asap */
1222 break;
Richard Henderson75f22e42011-10-25 10:34:06 -07001223 case TT_ILL_INSN:
1224 {
1225 info.si_signo = TARGET_SIGILL;
1226 info.si_errno = 0;
1227 info.si_code = TARGET_ILL_ILLOPC;
1228 info._sifields._sigfault._addr = env->pc;
1229 queue_signal(env, info.si_signo, &info);
1230 }
1231 break;
bellard1fddef42005-04-17 19:16:13 +00001232 case EXCP_DEBUG:
1233 {
1234 int sig;
1235
1236 sig = gdb_handlesig (env, TARGET_SIGTRAP);
1237 if (sig)
1238 {
1239 info.si_signo = sig;
1240 info.si_errno = 0;
1241 info.si_code = TARGET_TRAP_BRKPT;
pbrook624f7972008-05-31 16:11:38 +00001242 queue_signal(env, info.si_signo, &info);
bellard1fddef42005-04-17 19:16:13 +00001243 }
1244 }
1245 break;
bellard060366c2004-01-04 15:50:01 +00001246 default:
1247 printf ("Unhandled trap: 0x%x\n", trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +02001248 cpu_dump_state(cs, stderr, fprintf, 0);
bellard060366c2004-01-04 15:50:01 +00001249 exit (1);
1250 }
1251 process_pending_signals (env);
1252 }
bellard93ac68b2003-09-30 20:57:29 +00001253}
1254
1255#endif
1256
bellard67867302003-11-23 17:05:30 +00001257#ifdef TARGET_PPC
Andreas Färber05390242012-02-25 03:37:53 +01001258static inline uint64_t cpu_ppc_get_tb(CPUPPCState *env)
bellard9fddaa02004-05-21 12:59:32 +00001259{
1260 /* TO FIX */
1261 return 0;
1262}
ths3b46e622007-09-17 08:09:54 +00001263
Andreas Färber05390242012-02-25 03:37:53 +01001264uint64_t cpu_ppc_load_tbl(CPUPPCState *env)
bellard9fddaa02004-05-21 12:59:32 +00001265{
Alexander Grafe3ea6522009-12-21 12:24:17 +01001266 return cpu_ppc_get_tb(env);
bellard9fddaa02004-05-21 12:59:32 +00001267}
ths3b46e622007-09-17 08:09:54 +00001268
Andreas Färber05390242012-02-25 03:37:53 +01001269uint32_t cpu_ppc_load_tbu(CPUPPCState *env)
bellard9fddaa02004-05-21 12:59:32 +00001270{
1271 return cpu_ppc_get_tb(env) >> 32;
1272}
ths3b46e622007-09-17 08:09:54 +00001273
Andreas Färber05390242012-02-25 03:37:53 +01001274uint64_t cpu_ppc_load_atbl(CPUPPCState *env)
bellard9fddaa02004-05-21 12:59:32 +00001275{
Aurelien Jarnob711de92009-12-21 13:52:08 +01001276 return cpu_ppc_get_tb(env);
bellard9fddaa02004-05-21 12:59:32 +00001277}
1278
Andreas Färber05390242012-02-25 03:37:53 +01001279uint32_t cpu_ppc_load_atbu(CPUPPCState *env)
bellard9fddaa02004-05-21 12:59:32 +00001280{
j_mayera062e362007-09-30 00:38:38 +00001281 return cpu_ppc_get_tb(env) >> 32;
bellard9fddaa02004-05-21 12:59:32 +00001282}
ths5fafdf22007-09-16 21:08:06 +00001283
Andreas Färber05390242012-02-25 03:37:53 +01001284uint32_t cpu_ppc601_load_rtcu(CPUPPCState *env)
j_mayer76a66252007-03-07 08:32:30 +00001285__attribute__ (( alias ("cpu_ppc_load_tbu") ));
1286
Andreas Färber05390242012-02-25 03:37:53 +01001287uint32_t cpu_ppc601_load_rtcl(CPUPPCState *env)
bellard9fddaa02004-05-21 12:59:32 +00001288{
j_mayer76a66252007-03-07 08:32:30 +00001289 return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
bellard9fddaa02004-05-21 12:59:32 +00001290}
j_mayer76a66252007-03-07 08:32:30 +00001291
j_mayera750fc02007-09-26 23:54:22 +00001292/* XXX: to be fixed */
Alexander Graf73b01962009-12-21 14:02:39 +01001293int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp)
j_mayera750fc02007-09-26 23:54:22 +00001294{
1295 return -1;
1296}
1297
Alexander Graf73b01962009-12-21 14:02:39 +01001298int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val)
j_mayera750fc02007-09-26 23:54:22 +00001299{
1300 return -1;
1301}
1302
Blue Swirl001faf32009-05-13 17:53:17 +00001303#define EXCP_DUMP(env, fmt, ...) \
1304do { \
1305 fprintf(stderr, fmt , ## __VA_ARGS__); \
Andreas Färber878096e2013-05-27 01:33:50 +02001306 cpu_dump_state(ENV_GET_CPU(env), stderr, fprintf, 0); \
Blue Swirl001faf32009-05-13 17:53:17 +00001307 qemu_log(fmt, ## __VA_ARGS__); \
Blue Swirleeacee42012-06-03 16:35:32 +00001308 if (qemu_log_enabled()) { \
malc430c7ec2009-07-15 20:52:47 +04001309 log_cpu_state(env, 0); \
Blue Swirleeacee42012-06-03 16:35:32 +00001310 } \
j_mayere1833e12007-09-29 13:06:16 +00001311} while (0)
1312
Nathan Froyd56f066b2009-08-03 08:43:27 -07001313static int do_store_exclusive(CPUPPCState *env)
1314{
1315 target_ulong addr;
1316 target_ulong page_addr;
1317 target_ulong val;
1318 int flags;
1319 int segv = 0;
1320
1321 addr = env->reserve_ea;
1322 page_addr = addr & TARGET_PAGE_MASK;
1323 start_exclusive();
1324 mmap_lock();
1325 flags = page_get_flags(page_addr);
1326 if ((flags & PAGE_READ) == 0) {
1327 segv = 1;
1328 } else {
1329 int reg = env->reserve_info & 0x1f;
1330 int size = (env->reserve_info >> 5) & 0xf;
1331 int stored = 0;
1332
1333 if (addr == env->reserve_addr) {
1334 switch (size) {
1335 case 1: segv = get_user_u8(val, addr); break;
1336 case 2: segv = get_user_u16(val, addr); break;
1337 case 4: segv = get_user_u32(val, addr); break;
1338#if defined(TARGET_PPC64)
1339 case 8: segv = get_user_u64(val, addr); break;
1340#endif
1341 default: abort();
1342 }
1343 if (!segv && val == env->reserve_val) {
1344 val = env->gpr[reg];
1345 switch (size) {
1346 case 1: segv = put_user_u8(val, addr); break;
1347 case 2: segv = put_user_u16(val, addr); break;
1348 case 4: segv = put_user_u32(val, addr); break;
1349#if defined(TARGET_PPC64)
1350 case 8: segv = put_user_u64(val, addr); break;
1351#endif
1352 default: abort();
1353 }
1354 if (!segv) {
1355 stored = 1;
1356 }
1357 }
1358 }
1359 env->crf[0] = (stored << 1) | xer_so;
1360 env->reserve_addr = (target_ulong)-1;
1361 }
1362 if (!segv) {
1363 env->nip += 4;
1364 }
1365 mmap_unlock();
1366 end_exclusive();
1367 return segv;
1368}
1369
bellard67867302003-11-23 17:05:30 +00001370void cpu_loop(CPUPPCState *env)
1371{
Andreas Färber0315c312012-12-17 07:34:52 +01001372 CPUState *cs = CPU(ppc_env_get_cpu(env));
Anthony Liguoric227f092009-10-01 16:12:16 -05001373 target_siginfo_t info;
bellard61190b12004-01-04 23:54:31 +00001374 int trapnr;
Richard Henderson9e0e2f92011-10-26 09:59:18 -07001375 target_ulong ret;
ths3b46e622007-09-17 08:09:54 +00001376
bellard67867302003-11-23 17:05:30 +00001377 for(;;) {
Andreas Färber0315c312012-12-17 07:34:52 +01001378 cpu_exec_start(cs);
bellard67867302003-11-23 17:05:30 +00001379 trapnr = cpu_ppc_exec(env);
Andreas Färber0315c312012-12-17 07:34:52 +01001380 cpu_exec_end(cs);
bellard67867302003-11-23 17:05:30 +00001381 switch(trapnr) {
j_mayere1833e12007-09-29 13:06:16 +00001382 case POWERPC_EXCP_NONE:
1383 /* Just go on */
bellard67867302003-11-23 17:05:30 +00001384 break;
j_mayere1833e12007-09-29 13:06:16 +00001385 case POWERPC_EXCP_CRITICAL: /* Critical input */
1386 cpu_abort(env, "Critical interrupt while in user mode. "
1387 "Aborting\n");
1388 break;
1389 case POWERPC_EXCP_MCHECK: /* Machine check exception */
1390 cpu_abort(env, "Machine check exception while in user mode. "
1391 "Aborting\n");
1392 break;
1393 case POWERPC_EXCP_DSI: /* Data storage exception */
Blue Swirl90e189e2009-08-16 11:13:18 +00001394 EXCP_DUMP(env, "Invalid data memory access: 0x" TARGET_FMT_lx "\n",
j_mayere1833e12007-09-29 13:06:16 +00001395 env->spr[SPR_DAR]);
1396 /* XXX: check this. Seems bugged */
1397 switch (env->error_code & 0xFF000000) {
1398 case 0x40000000:
1399 info.si_signo = TARGET_SIGSEGV;
1400 info.si_errno = 0;
1401 info.si_code = TARGET_SEGV_MAPERR;
1402 break;
1403 case 0x04000000:
1404 info.si_signo = TARGET_SIGILL;
1405 info.si_errno = 0;
1406 info.si_code = TARGET_ILL_ILLADR;
1407 break;
1408 case 0x08000000:
1409 info.si_signo = TARGET_SIGSEGV;
1410 info.si_errno = 0;
1411 info.si_code = TARGET_SEGV_ACCERR;
1412 break;
1413 default:
1414 /* Let's send a regular segfault... */
1415 EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
1416 env->error_code);
1417 info.si_signo = TARGET_SIGSEGV;
1418 info.si_errno = 0;
1419 info.si_code = TARGET_SEGV_MAPERR;
1420 break;
1421 }
1422 info._sifields._sigfault._addr = env->nip;
pbrook624f7972008-05-31 16:11:38 +00001423 queue_signal(env, info.si_signo, &info);
j_mayere1833e12007-09-29 13:06:16 +00001424 break;
1425 case POWERPC_EXCP_ISI: /* Instruction storage exception */
Blue Swirl90e189e2009-08-16 11:13:18 +00001426 EXCP_DUMP(env, "Invalid instruction fetch: 0x\n" TARGET_FMT_lx
1427 "\n", env->spr[SPR_SRR0]);
j_mayere1833e12007-09-29 13:06:16 +00001428 /* XXX: check this */
1429 switch (env->error_code & 0xFF000000) {
1430 case 0x40000000:
1431 info.si_signo = TARGET_SIGSEGV;
1432 info.si_errno = 0;
1433 info.si_code = TARGET_SEGV_MAPERR;
1434 break;
1435 case 0x10000000:
1436 case 0x08000000:
1437 info.si_signo = TARGET_SIGSEGV;
1438 info.si_errno = 0;
1439 info.si_code = TARGET_SEGV_ACCERR;
1440 break;
1441 default:
1442 /* Let's send a regular segfault... */
1443 EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
1444 env->error_code);
1445 info.si_signo = TARGET_SIGSEGV;
1446 info.si_errno = 0;
1447 info.si_code = TARGET_SEGV_MAPERR;
1448 break;
1449 }
1450 info._sifields._sigfault._addr = env->nip - 4;
pbrook624f7972008-05-31 16:11:38 +00001451 queue_signal(env, info.si_signo, &info);
j_mayere1833e12007-09-29 13:06:16 +00001452 break;
1453 case POWERPC_EXCP_EXTERNAL: /* External input */
1454 cpu_abort(env, "External interrupt while in user mode. "
1455 "Aborting\n");
1456 break;
1457 case POWERPC_EXCP_ALIGN: /* Alignment exception */
1458 EXCP_DUMP(env, "Unaligned memory access\n");
1459 /* XXX: check this */
1460 info.si_signo = TARGET_SIGBUS;
1461 info.si_errno = 0;
1462 info.si_code = TARGET_BUS_ADRALN;
1463 info._sifields._sigfault._addr = env->nip - 4;
pbrook624f7972008-05-31 16:11:38 +00001464 queue_signal(env, info.si_signo, &info);
j_mayere1833e12007-09-29 13:06:16 +00001465 break;
1466 case POWERPC_EXCP_PROGRAM: /* Program exception */
1467 /* XXX: check this */
1468 switch (env->error_code & ~0xF) {
1469 case POWERPC_EXCP_FP:
1470 EXCP_DUMP(env, "Floating point program exception\n");
j_mayere1833e12007-09-29 13:06:16 +00001471 info.si_signo = TARGET_SIGFPE;
1472 info.si_errno = 0;
1473 switch (env->error_code & 0xF) {
1474 case POWERPC_EXCP_FP_OX:
1475 info.si_code = TARGET_FPE_FLTOVF;
1476 break;
1477 case POWERPC_EXCP_FP_UX:
1478 info.si_code = TARGET_FPE_FLTUND;
1479 break;
1480 case POWERPC_EXCP_FP_ZX:
1481 case POWERPC_EXCP_FP_VXZDZ:
1482 info.si_code = TARGET_FPE_FLTDIV;
1483 break;
1484 case POWERPC_EXCP_FP_XX:
1485 info.si_code = TARGET_FPE_FLTRES;
1486 break;
1487 case POWERPC_EXCP_FP_VXSOFT:
1488 info.si_code = TARGET_FPE_FLTINV;
1489 break;
j_mayer7c580442007-10-27 17:54:30 +00001490 case POWERPC_EXCP_FP_VXSNAN:
j_mayere1833e12007-09-29 13:06:16 +00001491 case POWERPC_EXCP_FP_VXISI:
1492 case POWERPC_EXCP_FP_VXIDI:
1493 case POWERPC_EXCP_FP_VXIMZ:
1494 case POWERPC_EXCP_FP_VXVC:
1495 case POWERPC_EXCP_FP_VXSQRT:
1496 case POWERPC_EXCP_FP_VXCVI:
1497 info.si_code = TARGET_FPE_FLTSUB;
1498 break;
1499 default:
1500 EXCP_DUMP(env, "Unknown floating point exception (%02x)\n",
1501 env->error_code);
1502 break;
1503 }
1504 break;
1505 case POWERPC_EXCP_INVAL:
1506 EXCP_DUMP(env, "Invalid instruction\n");
1507 info.si_signo = TARGET_SIGILL;
1508 info.si_errno = 0;
1509 switch (env->error_code & 0xF) {
1510 case POWERPC_EXCP_INVAL_INVAL:
1511 info.si_code = TARGET_ILL_ILLOPC;
1512 break;
1513 case POWERPC_EXCP_INVAL_LSWX:
1514 info.si_code = TARGET_ILL_ILLOPN;
1515 break;
1516 case POWERPC_EXCP_INVAL_SPR:
1517 info.si_code = TARGET_ILL_PRVREG;
1518 break;
1519 case POWERPC_EXCP_INVAL_FP:
1520 info.si_code = TARGET_ILL_COPROC;
1521 break;
1522 default:
1523 EXCP_DUMP(env, "Unknown invalid operation (%02x)\n",
1524 env->error_code & 0xF);
1525 info.si_code = TARGET_ILL_ILLADR;
1526 break;
1527 }
1528 break;
1529 case POWERPC_EXCP_PRIV:
1530 EXCP_DUMP(env, "Privilege violation\n");
1531 info.si_signo = TARGET_SIGILL;
1532 info.si_errno = 0;
1533 switch (env->error_code & 0xF) {
1534 case POWERPC_EXCP_PRIV_OPC:
1535 info.si_code = TARGET_ILL_PRVOPC;
1536 break;
1537 case POWERPC_EXCP_PRIV_REG:
1538 info.si_code = TARGET_ILL_PRVREG;
1539 break;
1540 default:
1541 EXCP_DUMP(env, "Unknown privilege violation (%02x)\n",
1542 env->error_code & 0xF);
1543 info.si_code = TARGET_ILL_PRVOPC;
1544 break;
1545 }
1546 break;
1547 case POWERPC_EXCP_TRAP:
1548 cpu_abort(env, "Tried to call a TRAP\n");
1549 break;
1550 default:
1551 /* Should not happen ! */
1552 cpu_abort(env, "Unknown program exception (%02x)\n",
1553 env->error_code);
1554 break;
1555 }
1556 info._sifields._sigfault._addr = env->nip - 4;
pbrook624f7972008-05-31 16:11:38 +00001557 queue_signal(env, info.si_signo, &info);
j_mayere1833e12007-09-29 13:06:16 +00001558 break;
1559 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
1560 EXCP_DUMP(env, "No floating point allowed\n");
1561 info.si_signo = TARGET_SIGILL;
1562 info.si_errno = 0;
1563 info.si_code = TARGET_ILL_COPROC;
1564 info._sifields._sigfault._addr = env->nip - 4;
pbrook624f7972008-05-31 16:11:38 +00001565 queue_signal(env, info.si_signo, &info);
j_mayere1833e12007-09-29 13:06:16 +00001566 break;
1567 case POWERPC_EXCP_SYSCALL: /* System call exception */
1568 cpu_abort(env, "Syscall exception while in user mode. "
1569 "Aborting\n");
1570 break;
1571 case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
1572 EXCP_DUMP(env, "No APU instruction allowed\n");
1573 info.si_signo = TARGET_SIGILL;
1574 info.si_errno = 0;
1575 info.si_code = TARGET_ILL_COPROC;
1576 info._sifields._sigfault._addr = env->nip - 4;
pbrook624f7972008-05-31 16:11:38 +00001577 queue_signal(env, info.si_signo, &info);
j_mayere1833e12007-09-29 13:06:16 +00001578 break;
1579 case POWERPC_EXCP_DECR: /* Decrementer exception */
1580 cpu_abort(env, "Decrementer interrupt while in user mode. "
1581 "Aborting\n");
1582 break;
1583 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
1584 cpu_abort(env, "Fix interval timer interrupt while in user mode. "
1585 "Aborting\n");
1586 break;
1587 case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
1588 cpu_abort(env, "Watchdog timer interrupt while in user mode. "
1589 "Aborting\n");
1590 break;
1591 case POWERPC_EXCP_DTLB: /* Data TLB error */
1592 cpu_abort(env, "Data TLB exception while in user mode. "
1593 "Aborting\n");
1594 break;
1595 case POWERPC_EXCP_ITLB: /* Instruction TLB error */
1596 cpu_abort(env, "Instruction TLB exception while in user mode. "
1597 "Aborting\n");
1598 break;
j_mayere1833e12007-09-29 13:06:16 +00001599 case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */
1600 EXCP_DUMP(env, "No SPE/floating-point instruction allowed\n");
1601 info.si_signo = TARGET_SIGILL;
1602 info.si_errno = 0;
1603 info.si_code = TARGET_ILL_COPROC;
1604 info._sifields._sigfault._addr = env->nip - 4;
pbrook624f7972008-05-31 16:11:38 +00001605 queue_signal(env, info.si_signo, &info);
j_mayere1833e12007-09-29 13:06:16 +00001606 break;
1607 case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */
1608 cpu_abort(env, "Embedded floating-point data IRQ not handled\n");
1609 break;
1610 case POWERPC_EXCP_EFPRI: /* Embedded floating-point round IRQ */
1611 cpu_abort(env, "Embedded floating-point round IRQ not handled\n");
1612 break;
1613 case POWERPC_EXCP_EPERFM: /* Embedded performance monitor IRQ */
1614 cpu_abort(env, "Performance monitor exception not handled\n");
1615 break;
1616 case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
1617 cpu_abort(env, "Doorbell interrupt while in user mode. "
1618 "Aborting\n");
1619 break;
1620 case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
1621 cpu_abort(env, "Doorbell critical interrupt while in user mode. "
1622 "Aborting\n");
1623 break;
1624 case POWERPC_EXCP_RESET: /* System reset exception */
1625 cpu_abort(env, "Reset interrupt while in user mode. "
1626 "Aborting\n");
1627 break;
j_mayere1833e12007-09-29 13:06:16 +00001628 case POWERPC_EXCP_DSEG: /* Data segment exception */
1629 cpu_abort(env, "Data segment exception while in user mode. "
1630 "Aborting\n");
1631 break;
1632 case POWERPC_EXCP_ISEG: /* Instruction segment exception */
1633 cpu_abort(env, "Instruction segment exception "
1634 "while in user mode. Aborting\n");
1635 break;
j_mayere85e7c62007-10-18 19:59:49 +00001636 /* PowerPC 64 with hypervisor mode support */
j_mayere1833e12007-09-29 13:06:16 +00001637 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
1638 cpu_abort(env, "Hypervisor decrementer interrupt "
1639 "while in user mode. Aborting\n");
1640 break;
j_mayere1833e12007-09-29 13:06:16 +00001641 case POWERPC_EXCP_TRACE: /* Trace exception */
1642 /* Nothing to do:
1643 * we use this exception to emulate step-by-step execution mode.
1644 */
1645 break;
j_mayere85e7c62007-10-18 19:59:49 +00001646 /* PowerPC 64 with hypervisor mode support */
j_mayere1833e12007-09-29 13:06:16 +00001647 case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
1648 cpu_abort(env, "Hypervisor data storage exception "
1649 "while in user mode. Aborting\n");
1650 break;
1651 case POWERPC_EXCP_HISI: /* Hypervisor instruction storage excp */
1652 cpu_abort(env, "Hypervisor instruction storage exception "
1653 "while in user mode. Aborting\n");
1654 break;
1655 case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
1656 cpu_abort(env, "Hypervisor data segment exception "
1657 "while in user mode. Aborting\n");
1658 break;
1659 case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment excp */
1660 cpu_abort(env, "Hypervisor instruction segment exception "
1661 "while in user mode. Aborting\n");
1662 break;
j_mayere1833e12007-09-29 13:06:16 +00001663 case POWERPC_EXCP_VPU: /* Vector unavailable exception */
1664 EXCP_DUMP(env, "No Altivec instructions allowed\n");
1665 info.si_signo = TARGET_SIGILL;
1666 info.si_errno = 0;
1667 info.si_code = TARGET_ILL_COPROC;
1668 info._sifields._sigfault._addr = env->nip - 4;
pbrook624f7972008-05-31 16:11:38 +00001669 queue_signal(env, info.si_signo, &info);
j_mayere1833e12007-09-29 13:06:16 +00001670 break;
1671 case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */
Dong Xu Wangb4916d72011-11-22 18:06:17 +08001672 cpu_abort(env, "Programmable interval timer interrupt "
j_mayere1833e12007-09-29 13:06:16 +00001673 "while in user mode. Aborting\n");
1674 break;
1675 case POWERPC_EXCP_IO: /* IO error exception */
1676 cpu_abort(env, "IO error exception while in user mode. "
1677 "Aborting\n");
1678 break;
1679 case POWERPC_EXCP_RUNM: /* Run mode exception */
1680 cpu_abort(env, "Run mode exception while in user mode. "
1681 "Aborting\n");
1682 break;
1683 case POWERPC_EXCP_EMUL: /* Emulation trap exception */
1684 cpu_abort(env, "Emulation trap exception not handled\n");
1685 break;
1686 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
1687 cpu_abort(env, "Instruction fetch TLB exception "
1688 "while in user-mode. Aborting");
1689 break;
1690 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
1691 cpu_abort(env, "Data load TLB exception while in user-mode. "
1692 "Aborting");
1693 break;
1694 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
1695 cpu_abort(env, "Data store TLB exception while in user-mode. "
1696 "Aborting");
1697 break;
1698 case POWERPC_EXCP_FPA: /* Floating-point assist exception */
1699 cpu_abort(env, "Floating-point assist exception not handled\n");
1700 break;
1701 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
1702 cpu_abort(env, "Instruction address breakpoint exception "
1703 "not handled\n");
1704 break;
1705 case POWERPC_EXCP_SMI: /* System management interrupt */
1706 cpu_abort(env, "System management interrupt while in user mode. "
1707 "Aborting\n");
1708 break;
1709 case POWERPC_EXCP_THERM: /* Thermal interrupt */
1710 cpu_abort(env, "Thermal interrupt interrupt while in user mode. "
1711 "Aborting\n");
1712 break;
1713 case POWERPC_EXCP_PERFM: /* Embedded performance monitor IRQ */
1714 cpu_abort(env, "Performance monitor exception not handled\n");
1715 break;
1716 case POWERPC_EXCP_VPUA: /* Vector assist exception */
1717 cpu_abort(env, "Vector assist exception not handled\n");
1718 break;
1719 case POWERPC_EXCP_SOFTP: /* Soft patch exception */
1720 cpu_abort(env, "Soft patch exception not handled\n");
1721 break;
1722 case POWERPC_EXCP_MAINT: /* Maintenance exception */
1723 cpu_abort(env, "Maintenance exception while in user mode. "
1724 "Aborting\n");
1725 break;
1726 case POWERPC_EXCP_STOP: /* stop translation */
1727 /* We did invalidate the instruction cache. Go on */
1728 break;
1729 case POWERPC_EXCP_BRANCH: /* branch instruction: */
1730 /* We just stopped because of a branch. Go on */
1731 break;
1732 case POWERPC_EXCP_SYSCALL_USER:
1733 /* system call in user-mode emulation */
bellard67867302003-11-23 17:05:30 +00001734 /* WARNING:
1735 * PPC ABI uses overflow flag in cr0 to signal an error
1736 * in syscalls.
1737 */
1738 env->crf[0] &= ~0x1;
1739 ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
1740 env->gpr[5], env->gpr[6], env->gpr[7],
Peter Maydell5945cfc2011-06-16 17:37:13 +01001741 env->gpr[8], 0, 0);
Richard Henderson9e0e2f92011-10-26 09:59:18 -07001742 if (ret == (target_ulong)(-TARGET_QEMU_ESIGRETURN)) {
Nathan Froydbcd49332009-05-12 19:13:18 -07001743 /* Returning from a successful sigreturn syscall.
1744 Avoid corrupting register state. */
1745 break;
1746 }
Richard Henderson9e0e2f92011-10-26 09:59:18 -07001747 if (ret > (target_ulong)(-515)) {
bellard67867302003-11-23 17:05:30 +00001748 env->crf[0] |= 0x1;
1749 ret = -ret;
1750 }
1751 env->gpr[3] = ret;
1752 break;
Nathan Froyd56f066b2009-08-03 08:43:27 -07001753 case POWERPC_EXCP_STCX:
1754 if (do_store_exclusive(env)) {
1755 info.si_signo = TARGET_SIGSEGV;
1756 info.si_errno = 0;
1757 info.si_code = TARGET_SEGV_MAPERR;
1758 info._sifields._sigfault._addr = env->nip;
1759 queue_signal(env, info.si_signo, &info);
1760 }
1761 break;
aurel3271f75752008-11-14 17:05:54 +00001762 case EXCP_DEBUG:
1763 {
1764 int sig;
1765
1766 sig = gdb_handlesig(env, TARGET_SIGTRAP);
1767 if (sig) {
1768 info.si_signo = sig;
1769 info.si_errno = 0;
1770 info.si_code = TARGET_TRAP_BRKPT;
1771 queue_signal(env, info.si_signo, &info);
1772 }
1773 }
1774 break;
j_mayer56ba31f2007-09-30 15:15:18 +00001775 case EXCP_INTERRUPT:
1776 /* just indicate that signals should be handled asap */
1777 break;
bellard67867302003-11-23 17:05:30 +00001778 default:
j_mayere1833e12007-09-29 13:06:16 +00001779 cpu_abort(env, "Unknown exception 0x%d. Aborting\n", trapnr);
1780 break;
bellard67867302003-11-23 17:05:30 +00001781 }
1782 process_pending_signals(env);
1783 }
1784}
1785#endif
1786
bellard048f6b42005-11-26 18:47:20 +00001787#ifdef TARGET_MIPS
1788
Richard Hendersonff4f7382013-02-10 10:30:45 -08001789# ifdef TARGET_ABI_MIPSO32
1790# define MIPS_SYS(name, args) args,
bellard048f6b42005-11-26 18:47:20 +00001791static const uint8_t mips_syscall_args[] = {
An-Cheng Huang29fb0f22011-08-09 12:31:41 -07001792 MIPS_SYS(sys_syscall , 8) /* 4000 */
bellard048f6b42005-11-26 18:47:20 +00001793 MIPS_SYS(sys_exit , 1)
1794 MIPS_SYS(sys_fork , 0)
1795 MIPS_SYS(sys_read , 3)
1796 MIPS_SYS(sys_write , 3)
1797 MIPS_SYS(sys_open , 3) /* 4005 */
1798 MIPS_SYS(sys_close , 1)
1799 MIPS_SYS(sys_waitpid , 3)
1800 MIPS_SYS(sys_creat , 2)
1801 MIPS_SYS(sys_link , 2)
1802 MIPS_SYS(sys_unlink , 1) /* 4010 */
1803 MIPS_SYS(sys_execve , 0)
1804 MIPS_SYS(sys_chdir , 1)
1805 MIPS_SYS(sys_time , 1)
1806 MIPS_SYS(sys_mknod , 3)
1807 MIPS_SYS(sys_chmod , 2) /* 4015 */
1808 MIPS_SYS(sys_lchown , 3)
1809 MIPS_SYS(sys_ni_syscall , 0)
1810 MIPS_SYS(sys_ni_syscall , 0) /* was sys_stat */
1811 MIPS_SYS(sys_lseek , 3)
1812 MIPS_SYS(sys_getpid , 0) /* 4020 */
1813 MIPS_SYS(sys_mount , 5)
1814 MIPS_SYS(sys_oldumount , 1)
1815 MIPS_SYS(sys_setuid , 1)
1816 MIPS_SYS(sys_getuid , 0)
1817 MIPS_SYS(sys_stime , 1) /* 4025 */
1818 MIPS_SYS(sys_ptrace , 4)
1819 MIPS_SYS(sys_alarm , 1)
1820 MIPS_SYS(sys_ni_syscall , 0) /* was sys_fstat */
1821 MIPS_SYS(sys_pause , 0)
1822 MIPS_SYS(sys_utime , 2) /* 4030 */
1823 MIPS_SYS(sys_ni_syscall , 0)
1824 MIPS_SYS(sys_ni_syscall , 0)
1825 MIPS_SYS(sys_access , 2)
1826 MIPS_SYS(sys_nice , 1)
1827 MIPS_SYS(sys_ni_syscall , 0) /* 4035 */
1828 MIPS_SYS(sys_sync , 0)
1829 MIPS_SYS(sys_kill , 2)
1830 MIPS_SYS(sys_rename , 2)
1831 MIPS_SYS(sys_mkdir , 2)
1832 MIPS_SYS(sys_rmdir , 1) /* 4040 */
1833 MIPS_SYS(sys_dup , 1)
1834 MIPS_SYS(sys_pipe , 0)
1835 MIPS_SYS(sys_times , 1)
1836 MIPS_SYS(sys_ni_syscall , 0)
1837 MIPS_SYS(sys_brk , 1) /* 4045 */
1838 MIPS_SYS(sys_setgid , 1)
1839 MIPS_SYS(sys_getgid , 0)
1840 MIPS_SYS(sys_ni_syscall , 0) /* was signal(2) */
1841 MIPS_SYS(sys_geteuid , 0)
1842 MIPS_SYS(sys_getegid , 0) /* 4050 */
1843 MIPS_SYS(sys_acct , 0)
1844 MIPS_SYS(sys_umount , 2)
1845 MIPS_SYS(sys_ni_syscall , 0)
1846 MIPS_SYS(sys_ioctl , 3)
1847 MIPS_SYS(sys_fcntl , 3) /* 4055 */
1848 MIPS_SYS(sys_ni_syscall , 2)
1849 MIPS_SYS(sys_setpgid , 2)
1850 MIPS_SYS(sys_ni_syscall , 0)
1851 MIPS_SYS(sys_olduname , 1)
1852 MIPS_SYS(sys_umask , 1) /* 4060 */
1853 MIPS_SYS(sys_chroot , 1)
1854 MIPS_SYS(sys_ustat , 2)
1855 MIPS_SYS(sys_dup2 , 2)
1856 MIPS_SYS(sys_getppid , 0)
1857 MIPS_SYS(sys_getpgrp , 0) /* 4065 */
1858 MIPS_SYS(sys_setsid , 0)
1859 MIPS_SYS(sys_sigaction , 3)
1860 MIPS_SYS(sys_sgetmask , 0)
1861 MIPS_SYS(sys_ssetmask , 1)
1862 MIPS_SYS(sys_setreuid , 2) /* 4070 */
1863 MIPS_SYS(sys_setregid , 2)
1864 MIPS_SYS(sys_sigsuspend , 0)
1865 MIPS_SYS(sys_sigpending , 1)
1866 MIPS_SYS(sys_sethostname , 2)
1867 MIPS_SYS(sys_setrlimit , 2) /* 4075 */
1868 MIPS_SYS(sys_getrlimit , 2)
1869 MIPS_SYS(sys_getrusage , 2)
1870 MIPS_SYS(sys_gettimeofday, 2)
1871 MIPS_SYS(sys_settimeofday, 2)
1872 MIPS_SYS(sys_getgroups , 2) /* 4080 */
1873 MIPS_SYS(sys_setgroups , 2)
1874 MIPS_SYS(sys_ni_syscall , 0) /* old_select */
1875 MIPS_SYS(sys_symlink , 2)
1876 MIPS_SYS(sys_ni_syscall , 0) /* was sys_lstat */
1877 MIPS_SYS(sys_readlink , 3) /* 4085 */
1878 MIPS_SYS(sys_uselib , 1)
1879 MIPS_SYS(sys_swapon , 2)
1880 MIPS_SYS(sys_reboot , 3)
1881 MIPS_SYS(old_readdir , 3)
1882 MIPS_SYS(old_mmap , 6) /* 4090 */
1883 MIPS_SYS(sys_munmap , 2)
1884 MIPS_SYS(sys_truncate , 2)
1885 MIPS_SYS(sys_ftruncate , 2)
1886 MIPS_SYS(sys_fchmod , 2)
1887 MIPS_SYS(sys_fchown , 3) /* 4095 */
1888 MIPS_SYS(sys_getpriority , 2)
1889 MIPS_SYS(sys_setpriority , 3)
1890 MIPS_SYS(sys_ni_syscall , 0)
1891 MIPS_SYS(sys_statfs , 2)
1892 MIPS_SYS(sys_fstatfs , 2) /* 4100 */
1893 MIPS_SYS(sys_ni_syscall , 0) /* was ioperm(2) */
1894 MIPS_SYS(sys_socketcall , 2)
1895 MIPS_SYS(sys_syslog , 3)
1896 MIPS_SYS(sys_setitimer , 3)
1897 MIPS_SYS(sys_getitimer , 2) /* 4105 */
1898 MIPS_SYS(sys_newstat , 2)
1899 MIPS_SYS(sys_newlstat , 2)
1900 MIPS_SYS(sys_newfstat , 2)
1901 MIPS_SYS(sys_uname , 1)
1902 MIPS_SYS(sys_ni_syscall , 0) /* 4110 was iopl(2) */
1903 MIPS_SYS(sys_vhangup , 0)
1904 MIPS_SYS(sys_ni_syscall , 0) /* was sys_idle() */
1905 MIPS_SYS(sys_ni_syscall , 0) /* was sys_vm86 */
1906 MIPS_SYS(sys_wait4 , 4)
1907 MIPS_SYS(sys_swapoff , 1) /* 4115 */
1908 MIPS_SYS(sys_sysinfo , 1)
1909 MIPS_SYS(sys_ipc , 6)
1910 MIPS_SYS(sys_fsync , 1)
1911 MIPS_SYS(sys_sigreturn , 0)
Paul Brook18113962009-07-09 13:11:52 +01001912 MIPS_SYS(sys_clone , 6) /* 4120 */
bellard048f6b42005-11-26 18:47:20 +00001913 MIPS_SYS(sys_setdomainname, 2)
1914 MIPS_SYS(sys_newuname , 1)
1915 MIPS_SYS(sys_ni_syscall , 0) /* sys_modify_ldt */
1916 MIPS_SYS(sys_adjtimex , 1)
1917 MIPS_SYS(sys_mprotect , 3) /* 4125 */
1918 MIPS_SYS(sys_sigprocmask , 3)
1919 MIPS_SYS(sys_ni_syscall , 0) /* was create_module */
1920 MIPS_SYS(sys_init_module , 5)
1921 MIPS_SYS(sys_delete_module, 1)
1922 MIPS_SYS(sys_ni_syscall , 0) /* 4130 was get_kernel_syms */
1923 MIPS_SYS(sys_quotactl , 0)
1924 MIPS_SYS(sys_getpgid , 1)
1925 MIPS_SYS(sys_fchdir , 1)
1926 MIPS_SYS(sys_bdflush , 2)
1927 MIPS_SYS(sys_sysfs , 3) /* 4135 */
1928 MIPS_SYS(sys_personality , 1)
1929 MIPS_SYS(sys_ni_syscall , 0) /* for afs_syscall */
1930 MIPS_SYS(sys_setfsuid , 1)
1931 MIPS_SYS(sys_setfsgid , 1)
1932 MIPS_SYS(sys_llseek , 5) /* 4140 */
1933 MIPS_SYS(sys_getdents , 3)
1934 MIPS_SYS(sys_select , 5)
1935 MIPS_SYS(sys_flock , 2)
1936 MIPS_SYS(sys_msync , 3)
1937 MIPS_SYS(sys_readv , 3) /* 4145 */
1938 MIPS_SYS(sys_writev , 3)
1939 MIPS_SYS(sys_cacheflush , 3)
1940 MIPS_SYS(sys_cachectl , 3)
1941 MIPS_SYS(sys_sysmips , 4)
1942 MIPS_SYS(sys_ni_syscall , 0) /* 4150 */
1943 MIPS_SYS(sys_getsid , 1)
1944 MIPS_SYS(sys_fdatasync , 0)
1945 MIPS_SYS(sys_sysctl , 1)
1946 MIPS_SYS(sys_mlock , 2)
1947 MIPS_SYS(sys_munlock , 2) /* 4155 */
1948 MIPS_SYS(sys_mlockall , 1)
1949 MIPS_SYS(sys_munlockall , 0)
1950 MIPS_SYS(sys_sched_setparam, 2)
1951 MIPS_SYS(sys_sched_getparam, 2)
1952 MIPS_SYS(sys_sched_setscheduler, 3) /* 4160 */
1953 MIPS_SYS(sys_sched_getscheduler, 1)
1954 MIPS_SYS(sys_sched_yield , 0)
1955 MIPS_SYS(sys_sched_get_priority_max, 1)
1956 MIPS_SYS(sys_sched_get_priority_min, 1)
1957 MIPS_SYS(sys_sched_rr_get_interval, 2) /* 4165 */
1958 MIPS_SYS(sys_nanosleep, 2)
1959 MIPS_SYS(sys_mremap , 4)
1960 MIPS_SYS(sys_accept , 3)
1961 MIPS_SYS(sys_bind , 3)
1962 MIPS_SYS(sys_connect , 3) /* 4170 */
1963 MIPS_SYS(sys_getpeername , 3)
1964 MIPS_SYS(sys_getsockname , 3)
1965 MIPS_SYS(sys_getsockopt , 5)
1966 MIPS_SYS(sys_listen , 2)
1967 MIPS_SYS(sys_recv , 4) /* 4175 */
1968 MIPS_SYS(sys_recvfrom , 6)
1969 MIPS_SYS(sys_recvmsg , 3)
1970 MIPS_SYS(sys_send , 4)
1971 MIPS_SYS(sys_sendmsg , 3)
1972 MIPS_SYS(sys_sendto , 6) /* 4180 */
1973 MIPS_SYS(sys_setsockopt , 5)
1974 MIPS_SYS(sys_shutdown , 2)
1975 MIPS_SYS(sys_socket , 3)
1976 MIPS_SYS(sys_socketpair , 4)
1977 MIPS_SYS(sys_setresuid , 3) /* 4185 */
1978 MIPS_SYS(sys_getresuid , 3)
1979 MIPS_SYS(sys_ni_syscall , 0) /* was sys_query_module */
1980 MIPS_SYS(sys_poll , 3)
1981 MIPS_SYS(sys_nfsservctl , 3)
1982 MIPS_SYS(sys_setresgid , 3) /* 4190 */
1983 MIPS_SYS(sys_getresgid , 3)
1984 MIPS_SYS(sys_prctl , 5)
1985 MIPS_SYS(sys_rt_sigreturn, 0)
1986 MIPS_SYS(sys_rt_sigaction, 4)
1987 MIPS_SYS(sys_rt_sigprocmask, 4) /* 4195 */
1988 MIPS_SYS(sys_rt_sigpending, 2)
1989 MIPS_SYS(sys_rt_sigtimedwait, 4)
1990 MIPS_SYS(sys_rt_sigqueueinfo, 3)
1991 MIPS_SYS(sys_rt_sigsuspend, 0)
1992 MIPS_SYS(sys_pread64 , 6) /* 4200 */
1993 MIPS_SYS(sys_pwrite64 , 6)
1994 MIPS_SYS(sys_chown , 3)
1995 MIPS_SYS(sys_getcwd , 2)
1996 MIPS_SYS(sys_capget , 2)
1997 MIPS_SYS(sys_capset , 2) /* 4205 */
Wesley W. Terpstra053ebb22011-07-12 14:32:31 +03001998 MIPS_SYS(sys_sigaltstack , 2)
bellard048f6b42005-11-26 18:47:20 +00001999 MIPS_SYS(sys_sendfile , 4)
2000 MIPS_SYS(sys_ni_syscall , 0)
2001 MIPS_SYS(sys_ni_syscall , 0)
2002 MIPS_SYS(sys_mmap2 , 6) /* 4210 */
2003 MIPS_SYS(sys_truncate64 , 4)
2004 MIPS_SYS(sys_ftruncate64 , 4)
2005 MIPS_SYS(sys_stat64 , 2)
2006 MIPS_SYS(sys_lstat64 , 2)
2007 MIPS_SYS(sys_fstat64 , 2) /* 4215 */
2008 MIPS_SYS(sys_pivot_root , 2)
2009 MIPS_SYS(sys_mincore , 3)
2010 MIPS_SYS(sys_madvise , 3)
2011 MIPS_SYS(sys_getdents64 , 3)
2012 MIPS_SYS(sys_fcntl64 , 3) /* 4220 */
2013 MIPS_SYS(sys_ni_syscall , 0)
2014 MIPS_SYS(sys_gettid , 0)
2015 MIPS_SYS(sys_readahead , 5)
2016 MIPS_SYS(sys_setxattr , 5)
2017 MIPS_SYS(sys_lsetxattr , 5) /* 4225 */
2018 MIPS_SYS(sys_fsetxattr , 5)
2019 MIPS_SYS(sys_getxattr , 4)
2020 MIPS_SYS(sys_lgetxattr , 4)
2021 MIPS_SYS(sys_fgetxattr , 4)
2022 MIPS_SYS(sys_listxattr , 3) /* 4230 */
2023 MIPS_SYS(sys_llistxattr , 3)
2024 MIPS_SYS(sys_flistxattr , 3)
2025 MIPS_SYS(sys_removexattr , 2)
2026 MIPS_SYS(sys_lremovexattr, 2)
2027 MIPS_SYS(sys_fremovexattr, 2) /* 4235 */
2028 MIPS_SYS(sys_tkill , 2)
2029 MIPS_SYS(sys_sendfile64 , 5)
2030 MIPS_SYS(sys_futex , 2)
2031 MIPS_SYS(sys_sched_setaffinity, 3)
2032 MIPS_SYS(sys_sched_getaffinity, 3) /* 4240 */
2033 MIPS_SYS(sys_io_setup , 2)
2034 MIPS_SYS(sys_io_destroy , 1)
2035 MIPS_SYS(sys_io_getevents, 5)
2036 MIPS_SYS(sys_io_submit , 3)
2037 MIPS_SYS(sys_io_cancel , 3) /* 4245 */
2038 MIPS_SYS(sys_exit_group , 1)
2039 MIPS_SYS(sys_lookup_dcookie, 3)
2040 MIPS_SYS(sys_epoll_create, 1)
2041 MIPS_SYS(sys_epoll_ctl , 4)
2042 MIPS_SYS(sys_epoll_wait , 3) /* 4250 */
2043 MIPS_SYS(sys_remap_file_pages, 5)
2044 MIPS_SYS(sys_set_tid_address, 1)
2045 MIPS_SYS(sys_restart_syscall, 0)
2046 MIPS_SYS(sys_fadvise64_64, 7)
2047 MIPS_SYS(sys_statfs64 , 3) /* 4255 */
2048 MIPS_SYS(sys_fstatfs64 , 2)
2049 MIPS_SYS(sys_timer_create, 3)
2050 MIPS_SYS(sys_timer_settime, 4)
2051 MIPS_SYS(sys_timer_gettime, 2)
2052 MIPS_SYS(sys_timer_getoverrun, 1) /* 4260 */
2053 MIPS_SYS(sys_timer_delete, 1)
2054 MIPS_SYS(sys_clock_settime, 2)
2055 MIPS_SYS(sys_clock_gettime, 2)
2056 MIPS_SYS(sys_clock_getres, 2)
2057 MIPS_SYS(sys_clock_nanosleep, 4) /* 4265 */
2058 MIPS_SYS(sys_tgkill , 3)
2059 MIPS_SYS(sys_utimes , 2)
2060 MIPS_SYS(sys_mbind , 4)
2061 MIPS_SYS(sys_ni_syscall , 0) /* sys_get_mempolicy */
2062 MIPS_SYS(sys_ni_syscall , 0) /* 4270 sys_set_mempolicy */
2063 MIPS_SYS(sys_mq_open , 4)
2064 MIPS_SYS(sys_mq_unlink , 1)
2065 MIPS_SYS(sys_mq_timedsend, 5)
2066 MIPS_SYS(sys_mq_timedreceive, 5)
2067 MIPS_SYS(sys_mq_notify , 2) /* 4275 */
2068 MIPS_SYS(sys_mq_getsetattr, 3)
2069 MIPS_SYS(sys_ni_syscall , 0) /* sys_vserver */
2070 MIPS_SYS(sys_waitid , 4)
2071 MIPS_SYS(sys_ni_syscall , 0) /* available, was setaltroot */
2072 MIPS_SYS(sys_add_key , 5)
ths388bb212007-05-13 13:58:00 +00002073 MIPS_SYS(sys_request_key, 4)
bellard048f6b42005-11-26 18:47:20 +00002074 MIPS_SYS(sys_keyctl , 5)
ths6f5b89a2007-03-02 20:48:00 +00002075 MIPS_SYS(sys_set_thread_area, 1)
ths388bb212007-05-13 13:58:00 +00002076 MIPS_SYS(sys_inotify_init, 0)
2077 MIPS_SYS(sys_inotify_add_watch, 3) /* 4285 */
2078 MIPS_SYS(sys_inotify_rm_watch, 2)
2079 MIPS_SYS(sys_migrate_pages, 4)
2080 MIPS_SYS(sys_openat, 4)
2081 MIPS_SYS(sys_mkdirat, 3)
2082 MIPS_SYS(sys_mknodat, 4) /* 4290 */
2083 MIPS_SYS(sys_fchownat, 5)
2084 MIPS_SYS(sys_futimesat, 3)
2085 MIPS_SYS(sys_fstatat64, 4)
2086 MIPS_SYS(sys_unlinkat, 3)
2087 MIPS_SYS(sys_renameat, 4) /* 4295 */
2088 MIPS_SYS(sys_linkat, 5)
2089 MIPS_SYS(sys_symlinkat, 3)
2090 MIPS_SYS(sys_readlinkat, 4)
2091 MIPS_SYS(sys_fchmodat, 3)
2092 MIPS_SYS(sys_faccessat, 3) /* 4300 */
2093 MIPS_SYS(sys_pselect6, 6)
2094 MIPS_SYS(sys_ppoll, 5)
2095 MIPS_SYS(sys_unshare, 1)
2096 MIPS_SYS(sys_splice, 4)
2097 MIPS_SYS(sys_sync_file_range, 7) /* 4305 */
2098 MIPS_SYS(sys_tee, 4)
2099 MIPS_SYS(sys_vmsplice, 4)
2100 MIPS_SYS(sys_move_pages, 6)
2101 MIPS_SYS(sys_set_robust_list, 2)
2102 MIPS_SYS(sys_get_robust_list, 3) /* 4310 */
2103 MIPS_SYS(sys_kexec_load, 4)
2104 MIPS_SYS(sys_getcpu, 3)
2105 MIPS_SYS(sys_epoll_pwait, 6)
2106 MIPS_SYS(sys_ioprio_set, 3)
2107 MIPS_SYS(sys_ioprio_get, 2)
Peter Maydelld979e8e2011-06-27 17:44:51 +01002108 MIPS_SYS(sys_utimensat, 4)
2109 MIPS_SYS(sys_signalfd, 3)
2110 MIPS_SYS(sys_ni_syscall, 0) /* was timerfd */
2111 MIPS_SYS(sys_eventfd, 1)
2112 MIPS_SYS(sys_fallocate, 6) /* 4320 */
2113 MIPS_SYS(sys_timerfd_create, 2)
2114 MIPS_SYS(sys_timerfd_gettime, 2)
2115 MIPS_SYS(sys_timerfd_settime, 4)
2116 MIPS_SYS(sys_signalfd4, 4)
2117 MIPS_SYS(sys_eventfd2, 2) /* 4325 */
2118 MIPS_SYS(sys_epoll_create1, 1)
2119 MIPS_SYS(sys_dup3, 3)
2120 MIPS_SYS(sys_pipe2, 2)
2121 MIPS_SYS(sys_inotify_init1, 1)
2122 MIPS_SYS(sys_preadv, 6) /* 4330 */
2123 MIPS_SYS(sys_pwritev, 6)
2124 MIPS_SYS(sys_rt_tgsigqueueinfo, 4)
2125 MIPS_SYS(sys_perf_event_open, 5)
2126 MIPS_SYS(sys_accept4, 4)
2127 MIPS_SYS(sys_recvmmsg, 5) /* 4335 */
2128 MIPS_SYS(sys_fanotify_init, 2)
2129 MIPS_SYS(sys_fanotify_mark, 6)
2130 MIPS_SYS(sys_prlimit64, 4)
2131 MIPS_SYS(sys_name_to_handle_at, 5)
2132 MIPS_SYS(sys_open_by_handle_at, 3) /* 4340 */
2133 MIPS_SYS(sys_clock_adjtime, 2)
2134 MIPS_SYS(sys_syncfs, 1)
bellard048f6b42005-11-26 18:47:20 +00002135};
Richard Hendersonff4f7382013-02-10 10:30:45 -08002136# undef MIPS_SYS
2137# endif /* O32 */
bellard048f6b42005-11-26 18:47:20 +00002138
Paul Brook590bc602009-07-09 17:45:17 +01002139static int do_store_exclusive(CPUMIPSState *env)
2140{
2141 target_ulong addr;
2142 target_ulong page_addr;
2143 target_ulong val;
2144 int flags;
2145 int segv = 0;
2146 int reg;
2147 int d;
2148
Aurelien Jarno5499b6f2009-11-22 13:08:14 +01002149 addr = env->lladdr;
Paul Brook590bc602009-07-09 17:45:17 +01002150 page_addr = addr & TARGET_PAGE_MASK;
2151 start_exclusive();
2152 mmap_lock();
2153 flags = page_get_flags(page_addr);
2154 if ((flags & PAGE_READ) == 0) {
2155 segv = 1;
2156 } else {
2157 reg = env->llreg & 0x1f;
2158 d = (env->llreg & 0x20) != 0;
2159 if (d) {
2160 segv = get_user_s64(val, addr);
2161 } else {
2162 segv = get_user_s32(val, addr);
2163 }
2164 if (!segv) {
2165 if (val != env->llval) {
2166 env->active_tc.gpr[reg] = 0;
2167 } else {
2168 if (d) {
2169 segv = put_user_u64(env->llnewval, addr);
2170 } else {
2171 segv = put_user_u32(env->llnewval, addr);
2172 }
2173 if (!segv) {
2174 env->active_tc.gpr[reg] = 1;
2175 }
2176 }
2177 }
2178 }
Aurelien Jarno5499b6f2009-11-22 13:08:14 +01002179 env->lladdr = -1;
Paul Brook590bc602009-07-09 17:45:17 +01002180 if (!segv) {
2181 env->active_tc.PC += 4;
2182 }
2183 mmap_unlock();
2184 end_exclusive();
2185 return segv;
2186}
2187
Meador Inge54b2f422013-01-10 16:50:22 -06002188/* Break codes */
2189enum {
2190 BRK_OVERFLOW = 6,
2191 BRK_DIVZERO = 7
2192};
2193
2194static int do_break(CPUMIPSState *env, target_siginfo_t *info,
2195 unsigned int code)
2196{
2197 int ret = -1;
2198
2199 switch (code) {
2200 case BRK_OVERFLOW:
2201 case BRK_DIVZERO:
2202 info->si_signo = TARGET_SIGFPE;
2203 info->si_errno = 0;
2204 info->si_code = (code == BRK_OVERFLOW) ? FPE_INTOVF : FPE_INTDIV;
2205 queue_signal(env, info->si_signo, &*info);
2206 ret = 0;
2207 break;
2208 default:
2209 break;
2210 }
2211
2212 return ret;
2213}
2214
bellard048f6b42005-11-26 18:47:20 +00002215void cpu_loop(CPUMIPSState *env)
2216{
Andreas Färber0315c312012-12-17 07:34:52 +01002217 CPUState *cs = CPU(mips_env_get_cpu(env));
Anthony Liguoric227f092009-10-01 16:12:16 -05002218 target_siginfo_t info;
Richard Hendersonff4f7382013-02-10 10:30:45 -08002219 int trapnr;
2220 abi_long ret;
2221# ifdef TARGET_ABI_MIPSO32
bellard048f6b42005-11-26 18:47:20 +00002222 unsigned int syscall_num;
Richard Hendersonff4f7382013-02-10 10:30:45 -08002223# endif
bellard048f6b42005-11-26 18:47:20 +00002224
2225 for(;;) {
Andreas Färber0315c312012-12-17 07:34:52 +01002226 cpu_exec_start(cs);
bellard048f6b42005-11-26 18:47:20 +00002227 trapnr = cpu_mips_exec(env);
Andreas Färber0315c312012-12-17 07:34:52 +01002228 cpu_exec_end(cs);
bellard048f6b42005-11-26 18:47:20 +00002229 switch(trapnr) {
2230 case EXCP_SYSCALL:
thsb5dc7732008-06-27 10:02:35 +00002231 env->active_tc.PC += 4;
Richard Hendersonff4f7382013-02-10 10:30:45 -08002232# ifdef TARGET_ABI_MIPSO32
2233 syscall_num = env->active_tc.gpr[2] - 4000;
ths388bb212007-05-13 13:58:00 +00002234 if (syscall_num >= sizeof(mips_syscall_args)) {
Wesley W. Terpstra7c2f6152011-07-12 14:33:23 +03002235 ret = -TARGET_ENOSYS;
ths388bb212007-05-13 13:58:00 +00002236 } else {
2237 int nb_args;
blueswir1992f48a2007-10-14 16:27:31 +00002238 abi_ulong sp_reg;
2239 abi_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0;
ths388bb212007-05-13 13:58:00 +00002240
2241 nb_args = mips_syscall_args[syscall_num];
thsb5dc7732008-06-27 10:02:35 +00002242 sp_reg = env->active_tc.gpr[29];
ths388bb212007-05-13 13:58:00 +00002243 switch (nb_args) {
2244 /* these arguments are taken from the stack */
An-Cheng Huang94c19612011-08-09 12:32:38 -07002245 case 8:
2246 if ((ret = get_user_ual(arg8, sp_reg + 28)) != 0) {
2247 goto done_syscall;
2248 }
2249 case 7:
2250 if ((ret = get_user_ual(arg7, sp_reg + 24)) != 0) {
2251 goto done_syscall;
2252 }
2253 case 6:
2254 if ((ret = get_user_ual(arg6, sp_reg + 20)) != 0) {
2255 goto done_syscall;
2256 }
2257 case 5:
2258 if ((ret = get_user_ual(arg5, sp_reg + 16)) != 0) {
2259 goto done_syscall;
2260 }
ths388bb212007-05-13 13:58:00 +00002261 default:
2262 break;
bellard048f6b42005-11-26 18:47:20 +00002263 }
thsb5dc7732008-06-27 10:02:35 +00002264 ret = do_syscall(env, env->active_tc.gpr[2],
2265 env->active_tc.gpr[4],
2266 env->active_tc.gpr[5],
2267 env->active_tc.gpr[6],
2268 env->active_tc.gpr[7],
Peter Maydell5945cfc2011-06-16 17:37:13 +01002269 arg5, arg6, arg7, arg8);
bellard048f6b42005-11-26 18:47:20 +00002270 }
An-Cheng Huang94c19612011-08-09 12:32:38 -07002271done_syscall:
Richard Hendersonff4f7382013-02-10 10:30:45 -08002272# else
2273 ret = do_syscall(env, env->active_tc.gpr[2],
2274 env->active_tc.gpr[4], env->active_tc.gpr[5],
2275 env->active_tc.gpr[6], env->active_tc.gpr[7],
2276 env->active_tc.gpr[8], env->active_tc.gpr[9],
2277 env->active_tc.gpr[10], env->active_tc.gpr[11]);
2278# endif /* O32 */
pbrook0b1bcb02009-04-21 01:41:10 +00002279 if (ret == -TARGET_QEMU_ESIGRETURN) {
2280 /* Returning from a successful sigreturn syscall.
2281 Avoid clobbering register state. */
2282 break;
2283 }
Richard Hendersonff4f7382013-02-10 10:30:45 -08002284 if ((abi_ulong)ret >= (abi_ulong)-1133) {
thsb5dc7732008-06-27 10:02:35 +00002285 env->active_tc.gpr[7] = 1; /* error flag */
ths388bb212007-05-13 13:58:00 +00002286 ret = -ret;
2287 } else {
thsb5dc7732008-06-27 10:02:35 +00002288 env->active_tc.gpr[7] = 0; /* error flag */
ths388bb212007-05-13 13:58:00 +00002289 }
thsb5dc7732008-06-27 10:02:35 +00002290 env->active_tc.gpr[2] = ret;
bellard048f6b42005-11-26 18:47:20 +00002291 break;
thsca7c2b12006-12-10 22:08:10 +00002292 case EXCP_TLBL:
2293 case EXCP_TLBS:
Wesley W. Terpstrae6e5bd22011-07-12 14:34:23 +03002294 case EXCP_AdEL:
2295 case EXCP_AdES:
pbrooke4474232009-04-21 01:03:10 +00002296 info.si_signo = TARGET_SIGSEGV;
2297 info.si_errno = 0;
2298 /* XXX: check env->error_code */
2299 info.si_code = TARGET_SEGV_MAPERR;
2300 info._sifields._sigfault._addr = env->CP0_BadVAddr;
2301 queue_signal(env, info.si_signo, &info);
2302 break;
bellard6900e842005-12-05 21:04:24 +00002303 case EXCP_CpU:
bellard048f6b42005-11-26 18:47:20 +00002304 case EXCP_RI:
bellardbc1ad2d2006-06-14 13:37:55 +00002305 info.si_signo = TARGET_SIGILL;
2306 info.si_errno = 0;
2307 info.si_code = 0;
pbrook624f7972008-05-31 16:11:38 +00002308 queue_signal(env, info.si_signo, &info);
bellard048f6b42005-11-26 18:47:20 +00002309 break;
bellard106ec872006-06-27 21:08:10 +00002310 case EXCP_INTERRUPT:
2311 /* just indicate that signals should be handled asap */
2312 break;
pbrookd08b2a22006-11-04 16:46:29 +00002313 case EXCP_DEBUG:
2314 {
2315 int sig;
2316
2317 sig = gdb_handlesig (env, TARGET_SIGTRAP);
2318 if (sig)
2319 {
2320 info.si_signo = sig;
2321 info.si_errno = 0;
2322 info.si_code = TARGET_TRAP_BRKPT;
pbrook624f7972008-05-31 16:11:38 +00002323 queue_signal(env, info.si_signo, &info);
pbrookd08b2a22006-11-04 16:46:29 +00002324 }
2325 }
2326 break;
Paul Brook590bc602009-07-09 17:45:17 +01002327 case EXCP_SC:
2328 if (do_store_exclusive(env)) {
2329 info.si_signo = TARGET_SIGSEGV;
2330 info.si_errno = 0;
2331 info.si_code = TARGET_SEGV_MAPERR;
2332 info._sifields._sigfault._addr = env->active_tc.PC;
2333 queue_signal(env, info.si_signo, &info);
2334 }
2335 break;
Jia Liu853c3242012-10-24 22:17:02 +08002336 case EXCP_DSPDIS:
2337 info.si_signo = TARGET_SIGILL;
2338 info.si_errno = 0;
2339 info.si_code = TARGET_ILL_ILLOPC;
2340 queue_signal(env, info.si_signo, &info);
2341 break;
Meador Inge54b2f422013-01-10 16:50:22 -06002342 /* The code below was inspired by the MIPS Linux kernel trap
2343 * handling code in arch/mips/kernel/traps.c.
2344 */
2345 case EXCP_BREAK:
2346 {
2347 abi_ulong trap_instr;
2348 unsigned int code;
2349
2350 ret = get_user_ual(trap_instr, env->active_tc.PC);
2351 if (ret != 0) {
2352 goto error;
2353 }
2354
2355 /* As described in the original Linux kernel code, the
2356 * below checks on 'code' are to work around an old
2357 * assembly bug.
2358 */
2359 code = ((trap_instr >> 6) & ((1 << 20) - 1));
2360 if (code >= (1 << 10)) {
2361 code >>= 10;
2362 }
2363
2364 if (do_break(env, &info, code) != 0) {
2365 goto error;
2366 }
2367 }
2368 break;
2369 case EXCP_TRAP:
2370 {
2371 abi_ulong trap_instr;
2372 unsigned int code = 0;
2373
2374 ret = get_user_ual(trap_instr, env->active_tc.PC);
2375 if (ret != 0) {
2376 goto error;
2377 }
2378
2379 /* The immediate versions don't provide a code. */
2380 if (!(trap_instr & 0xFC000000)) {
2381 code = ((trap_instr >> 6) & ((1 << 10) - 1));
2382 }
2383
2384 if (do_break(env, &info, code) != 0) {
2385 goto error;
2386 }
2387 }
2388 break;
bellard048f6b42005-11-26 18:47:20 +00002389 default:
Meador Inge54b2f422013-01-10 16:50:22 -06002390error:
ths5fafdf22007-09-16 21:08:06 +00002391 fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
bellard048f6b42005-11-26 18:47:20 +00002392 trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +02002393 cpu_dump_state(cs, stderr, fprintf, 0);
bellard048f6b42005-11-26 18:47:20 +00002394 abort();
2395 }
2396 process_pending_signals(env);
2397 }
2398}
2399#endif
2400
Jia Liud9627832012-07-20 15:50:52 +08002401#ifdef TARGET_OPENRISC
2402
2403void cpu_loop(CPUOpenRISCState *env)
2404{
Andreas Färber878096e2013-05-27 01:33:50 +02002405 CPUState *cs = CPU(openrisc_env_get_cpu(env));
Jia Liud9627832012-07-20 15:50:52 +08002406 int trapnr, gdbsig;
2407
2408 for (;;) {
2409 trapnr = cpu_exec(env);
2410 gdbsig = 0;
2411
2412 switch (trapnr) {
2413 case EXCP_RESET:
2414 qemu_log("\nReset request, exit, pc is %#x\n", env->pc);
2415 exit(1);
2416 break;
2417 case EXCP_BUSERR:
2418 qemu_log("\nBus error, exit, pc is %#x\n", env->pc);
2419 gdbsig = SIGBUS;
2420 break;
2421 case EXCP_DPF:
2422 case EXCP_IPF:
Andreas Färber878096e2013-05-27 01:33:50 +02002423 cpu_dump_state(cs, stderr, fprintf, 0);
Jia Liud9627832012-07-20 15:50:52 +08002424 gdbsig = TARGET_SIGSEGV;
2425 break;
2426 case EXCP_TICK:
2427 qemu_log("\nTick time interrupt pc is %#x\n", env->pc);
2428 break;
2429 case EXCP_ALIGN:
2430 qemu_log("\nAlignment pc is %#x\n", env->pc);
2431 gdbsig = SIGBUS;
2432 break;
2433 case EXCP_ILLEGAL:
2434 qemu_log("\nIllegal instructionpc is %#x\n", env->pc);
2435 gdbsig = SIGILL;
2436 break;
2437 case EXCP_INT:
2438 qemu_log("\nExternal interruptpc is %#x\n", env->pc);
2439 break;
2440 case EXCP_DTLBMISS:
2441 case EXCP_ITLBMISS:
2442 qemu_log("\nTLB miss\n");
2443 break;
2444 case EXCP_RANGE:
2445 qemu_log("\nRange\n");
2446 gdbsig = SIGSEGV;
2447 break;
2448 case EXCP_SYSCALL:
2449 env->pc += 4; /* 0xc00; */
2450 env->gpr[11] = do_syscall(env,
2451 env->gpr[11], /* return value */
2452 env->gpr[3], /* r3 - r7 are params */
2453 env->gpr[4],
2454 env->gpr[5],
2455 env->gpr[6],
2456 env->gpr[7],
2457 env->gpr[8], 0, 0);
2458 break;
2459 case EXCP_FPE:
2460 qemu_log("\nFloating point error\n");
2461 break;
2462 case EXCP_TRAP:
2463 qemu_log("\nTrap\n");
2464 gdbsig = SIGTRAP;
2465 break;
2466 case EXCP_NR:
2467 qemu_log("\nNR\n");
2468 break;
2469 default:
2470 qemu_log("\nqemu: unhandled CPU exception %#x - aborting\n",
2471 trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +02002472 cpu_dump_state(cs, stderr, fprintf, 0);
Jia Liud9627832012-07-20 15:50:52 +08002473 gdbsig = TARGET_SIGILL;
2474 break;
2475 }
2476 if (gdbsig) {
2477 gdb_handlesig(env, gdbsig);
2478 if (gdbsig != TARGET_SIGTRAP) {
2479 exit(1);
2480 }
2481 }
2482
2483 process_pending_signals(env);
2484 }
2485}
2486
2487#endif /* TARGET_OPENRISC */
2488
bellardfdf9b3e2006-04-27 21:07:38 +00002489#ifdef TARGET_SH4
Andreas Färber05390242012-02-25 03:37:53 +01002490void cpu_loop(CPUSH4State *env)
bellardfdf9b3e2006-04-27 21:07:38 +00002491{
Andreas Färber878096e2013-05-27 01:33:50 +02002492 CPUState *cs = CPU(sh_env_get_cpu(env));
bellardfdf9b3e2006-04-27 21:07:38 +00002493 int trapnr, ret;
Anthony Liguoric227f092009-10-01 16:12:16 -05002494 target_siginfo_t info;
ths3b46e622007-09-17 08:09:54 +00002495
bellardfdf9b3e2006-04-27 21:07:38 +00002496 while (1) {
2497 trapnr = cpu_sh4_exec (env);
ths3b46e622007-09-17 08:09:54 +00002498
bellardfdf9b3e2006-04-27 21:07:38 +00002499 switch (trapnr) {
2500 case 0x160:
aurel320b6d3ae2008-09-15 07:43:43 +00002501 env->pc += 2;
ths5fafdf22007-09-16 21:08:06 +00002502 ret = do_syscall(env,
2503 env->gregs[3],
2504 env->gregs[4],
2505 env->gregs[5],
2506 env->gregs[6],
2507 env->gregs[7],
2508 env->gregs[0],
Peter Maydell5945cfc2011-06-16 17:37:13 +01002509 env->gregs[1],
2510 0, 0);
pbrook9c2a9ea2006-06-18 19:12:54 +00002511 env->gregs[0] = ret;
bellardfdf9b3e2006-04-27 21:07:38 +00002512 break;
thsc3b5bc82007-12-02 06:31:25 +00002513 case EXCP_INTERRUPT:
2514 /* just indicate that signals should be handled asap */
2515 break;
pbrook355fb232006-06-17 19:58:25 +00002516 case EXCP_DEBUG:
2517 {
2518 int sig;
2519
2520 sig = gdb_handlesig (env, TARGET_SIGTRAP);
2521 if (sig)
2522 {
2523 info.si_signo = sig;
2524 info.si_errno = 0;
2525 info.si_code = TARGET_TRAP_BRKPT;
pbrook624f7972008-05-31 16:11:38 +00002526 queue_signal(env, info.si_signo, &info);
pbrook355fb232006-06-17 19:58:25 +00002527 }
2528 }
2529 break;
thsc3b5bc82007-12-02 06:31:25 +00002530 case 0xa0:
2531 case 0xc0:
2532 info.si_signo = SIGSEGV;
2533 info.si_errno = 0;
2534 info.si_code = TARGET_SEGV_MAPERR;
2535 info._sifields._sigfault._addr = env->tea;
pbrook624f7972008-05-31 16:11:38 +00002536 queue_signal(env, info.si_signo, &info);
thsc3b5bc82007-12-02 06:31:25 +00002537 break;
2538
bellardfdf9b3e2006-04-27 21:07:38 +00002539 default:
2540 printf ("Unhandled trap: 0x%x\n", trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +02002541 cpu_dump_state(cs, stderr, fprintf, 0);
bellardfdf9b3e2006-04-27 21:07:38 +00002542 exit (1);
2543 }
2544 process_pending_signals (env);
2545 }
2546}
2547#endif
2548
ths48733d12007-10-08 13:36:46 +00002549#ifdef TARGET_CRIS
Andreas Färber05390242012-02-25 03:37:53 +01002550void cpu_loop(CPUCRISState *env)
ths48733d12007-10-08 13:36:46 +00002551{
Andreas Färber878096e2013-05-27 01:33:50 +02002552 CPUState *cs = CPU(cris_env_get_cpu(env));
ths48733d12007-10-08 13:36:46 +00002553 int trapnr, ret;
Anthony Liguoric227f092009-10-01 16:12:16 -05002554 target_siginfo_t info;
ths48733d12007-10-08 13:36:46 +00002555
2556 while (1) {
2557 trapnr = cpu_cris_exec (env);
2558 switch (trapnr) {
2559 case 0xaa:
2560 {
2561 info.si_signo = SIGSEGV;
2562 info.si_errno = 0;
2563 /* XXX: check env->error_code */
2564 info.si_code = TARGET_SEGV_MAPERR;
edgar_igle00c1e72008-05-27 21:12:09 +00002565 info._sifields._sigfault._addr = env->pregs[PR_EDA];
pbrook624f7972008-05-31 16:11:38 +00002566 queue_signal(env, info.si_signo, &info);
ths48733d12007-10-08 13:36:46 +00002567 }
2568 break;
edgar_iglb6d3abd2008-02-28 11:29:27 +00002569 case EXCP_INTERRUPT:
2570 /* just indicate that signals should be handled asap */
2571 break;
ths48733d12007-10-08 13:36:46 +00002572 case EXCP_BREAK:
2573 ret = do_syscall(env,
2574 env->regs[9],
2575 env->regs[10],
2576 env->regs[11],
2577 env->regs[12],
2578 env->regs[13],
2579 env->pregs[7],
Peter Maydell5945cfc2011-06-16 17:37:13 +01002580 env->pregs[11],
2581 0, 0);
ths48733d12007-10-08 13:36:46 +00002582 env->regs[10] = ret;
ths48733d12007-10-08 13:36:46 +00002583 break;
2584 case EXCP_DEBUG:
2585 {
2586 int sig;
2587
2588 sig = gdb_handlesig (env, TARGET_SIGTRAP);
2589 if (sig)
2590 {
2591 info.si_signo = sig;
2592 info.si_errno = 0;
2593 info.si_code = TARGET_TRAP_BRKPT;
pbrook624f7972008-05-31 16:11:38 +00002594 queue_signal(env, info.si_signo, &info);
ths48733d12007-10-08 13:36:46 +00002595 }
2596 }
2597 break;
2598 default:
2599 printf ("Unhandled trap: 0x%x\n", trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +02002600 cpu_dump_state(cs, stderr, fprintf, 0);
ths48733d12007-10-08 13:36:46 +00002601 exit (1);
2602 }
2603 process_pending_signals (env);
2604 }
2605}
2606#endif
2607
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02002608#ifdef TARGET_MICROBLAZE
Andreas Färber05390242012-02-25 03:37:53 +01002609void cpu_loop(CPUMBState *env)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02002610{
Andreas Färber878096e2013-05-27 01:33:50 +02002611 CPUState *cs = CPU(mb_env_get_cpu(env));
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02002612 int trapnr, ret;
Anthony Liguoric227f092009-10-01 16:12:16 -05002613 target_siginfo_t info;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02002614
2615 while (1) {
2616 trapnr = cpu_mb_exec (env);
2617 switch (trapnr) {
2618 case 0xaa:
2619 {
2620 info.si_signo = SIGSEGV;
2621 info.si_errno = 0;
2622 /* XXX: check env->error_code */
2623 info.si_code = TARGET_SEGV_MAPERR;
2624 info._sifields._sigfault._addr = 0;
2625 queue_signal(env, info.si_signo, &info);
2626 }
2627 break;
2628 case EXCP_INTERRUPT:
2629 /* just indicate that signals should be handled asap */
2630 break;
2631 case EXCP_BREAK:
2632 /* Return address is 4 bytes after the call. */
2633 env->regs[14] += 4;
Edgar E. Iglesiasd7dce492012-04-26 14:18:25 +02002634 env->sregs[SR_PC] = env->regs[14];
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02002635 ret = do_syscall(env,
2636 env->regs[12],
2637 env->regs[5],
2638 env->regs[6],
2639 env->regs[7],
2640 env->regs[8],
2641 env->regs[9],
Peter Maydell5945cfc2011-06-16 17:37:13 +01002642 env->regs[10],
2643 0, 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02002644 env->regs[3] = ret;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02002645 break;
Edgar E. Iglesiasb76da7e2010-09-09 10:24:01 +02002646 case EXCP_HW_EXCP:
2647 env->regs[17] = env->sregs[SR_PC] + 4;
2648 if (env->iflags & D_FLAG) {
2649 env->sregs[SR_ESR] |= 1 << 12;
2650 env->sregs[SR_PC] -= 4;
Dong Xu Wangb4916d72011-11-22 18:06:17 +08002651 /* FIXME: if branch was immed, replay the imm as well. */
Edgar E. Iglesiasb76da7e2010-09-09 10:24:01 +02002652 }
2653
2654 env->iflags &= ~(IMM_FLAG | D_FLAG);
2655
2656 switch (env->sregs[SR_ESR] & 31) {
Edgar E. Iglesias22a78d62011-08-22 18:42:54 +02002657 case ESR_EC_DIVZERO:
2658 info.si_signo = SIGFPE;
2659 info.si_errno = 0;
2660 info.si_code = TARGET_FPE_FLTDIV;
2661 info._sifields._sigfault._addr = 0;
2662 queue_signal(env, info.si_signo, &info);
2663 break;
Edgar E. Iglesiasb76da7e2010-09-09 10:24:01 +02002664 case ESR_EC_FPU:
2665 info.si_signo = SIGFPE;
2666 info.si_errno = 0;
2667 if (env->sregs[SR_FSR] & FSR_IO) {
2668 info.si_code = TARGET_FPE_FLTINV;
2669 }
2670 if (env->sregs[SR_FSR] & FSR_DZ) {
2671 info.si_code = TARGET_FPE_FLTDIV;
2672 }
2673 info._sifields._sigfault._addr = 0;
2674 queue_signal(env, info.si_signo, &info);
2675 break;
2676 default:
2677 printf ("Unhandled hw-exception: 0x%x\n",
Edgar E. Iglesias2e42d522011-04-11 23:57:07 +02002678 env->sregs[SR_ESR] & ESR_EC_MASK);
Andreas Färber878096e2013-05-27 01:33:50 +02002679 cpu_dump_state(cs, stderr, fprintf, 0);
Edgar E. Iglesiasb76da7e2010-09-09 10:24:01 +02002680 exit (1);
2681 break;
2682 }
2683 break;
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02002684 case EXCP_DEBUG:
2685 {
2686 int sig;
2687
2688 sig = gdb_handlesig (env, TARGET_SIGTRAP);
2689 if (sig)
2690 {
2691 info.si_signo = sig;
2692 info.si_errno = 0;
2693 info.si_code = TARGET_TRAP_BRKPT;
2694 queue_signal(env, info.si_signo, &info);
2695 }
2696 }
2697 break;
2698 default:
2699 printf ("Unhandled trap: 0x%x\n", trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +02002700 cpu_dump_state(cs, stderr, fprintf, 0);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02002701 exit (1);
2702 }
2703 process_pending_signals (env);
2704 }
2705}
2706#endif
2707
pbrooke6e59062006-10-22 00:18:54 +00002708#ifdef TARGET_M68K
2709
2710void cpu_loop(CPUM68KState *env)
2711{
Andreas Färber878096e2013-05-27 01:33:50 +02002712 CPUState *cs = CPU(m68k_env_get_cpu(env));
pbrooke6e59062006-10-22 00:18:54 +00002713 int trapnr;
2714 unsigned int n;
Anthony Liguoric227f092009-10-01 16:12:16 -05002715 target_siginfo_t info;
pbrooke6e59062006-10-22 00:18:54 +00002716 TaskState *ts = env->opaque;
ths3b46e622007-09-17 08:09:54 +00002717
pbrooke6e59062006-10-22 00:18:54 +00002718 for(;;) {
2719 trapnr = cpu_m68k_exec(env);
2720 switch(trapnr) {
2721 case EXCP_ILLEGAL:
2722 {
2723 if (ts->sim_syscalls) {
2724 uint16_t nr;
2725 nr = lduw(env->pc + 2);
2726 env->pc += 4;
2727 do_m68k_simcall(env, nr);
2728 } else {
2729 goto do_sigill;
2730 }
2731 }
2732 break;
pbrooka87295e2007-05-26 15:09:38 +00002733 case EXCP_HALT_INSN:
pbrooke6e59062006-10-22 00:18:54 +00002734 /* Semihosing syscall. */
pbrooka87295e2007-05-26 15:09:38 +00002735 env->pc += 4;
pbrooke6e59062006-10-22 00:18:54 +00002736 do_m68k_semihosting(env, env->dregs[0]);
2737 break;
2738 case EXCP_LINEA:
2739 case EXCP_LINEF:
2740 case EXCP_UNSUPPORTED:
2741 do_sigill:
2742 info.si_signo = SIGILL;
2743 info.si_errno = 0;
2744 info.si_code = TARGET_ILL_ILLOPN;
2745 info._sifields._sigfault._addr = env->pc;
pbrook624f7972008-05-31 16:11:38 +00002746 queue_signal(env, info.si_signo, &info);
pbrooke6e59062006-10-22 00:18:54 +00002747 break;
2748 case EXCP_TRAP0:
2749 {
2750 ts->sim_syscalls = 0;
2751 n = env->dregs[0];
2752 env->pc += 2;
ths5fafdf22007-09-16 21:08:06 +00002753 env->dregs[0] = do_syscall(env,
2754 n,
pbrooke6e59062006-10-22 00:18:54 +00002755 env->dregs[1],
2756 env->dregs[2],
2757 env->dregs[3],
2758 env->dregs[4],
2759 env->dregs[5],
Peter Maydell5945cfc2011-06-16 17:37:13 +01002760 env->aregs[0],
2761 0, 0);
pbrooke6e59062006-10-22 00:18:54 +00002762 }
2763 break;
2764 case EXCP_INTERRUPT:
2765 /* just indicate that signals should be handled asap */
2766 break;
2767 case EXCP_ACCESS:
2768 {
2769 info.si_signo = SIGSEGV;
2770 info.si_errno = 0;
2771 /* XXX: check env->error_code */
2772 info.si_code = TARGET_SEGV_MAPERR;
2773 info._sifields._sigfault._addr = env->mmu.ar;
pbrook624f7972008-05-31 16:11:38 +00002774 queue_signal(env, info.si_signo, &info);
pbrooke6e59062006-10-22 00:18:54 +00002775 }
2776 break;
2777 case EXCP_DEBUG:
2778 {
2779 int sig;
2780
2781 sig = gdb_handlesig (env, TARGET_SIGTRAP);
2782 if (sig)
2783 {
2784 info.si_signo = sig;
2785 info.si_errno = 0;
2786 info.si_code = TARGET_TRAP_BRKPT;
pbrook624f7972008-05-31 16:11:38 +00002787 queue_signal(env, info.si_signo, &info);
pbrooke6e59062006-10-22 00:18:54 +00002788 }
2789 }
2790 break;
2791 default:
ths5fafdf22007-09-16 21:08:06 +00002792 fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
pbrooke6e59062006-10-22 00:18:54 +00002793 trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +02002794 cpu_dump_state(cs, stderr, fprintf, 0);
pbrooke6e59062006-10-22 00:18:54 +00002795 abort();
2796 }
2797 process_pending_signals(env);
2798 }
2799}
2800#endif /* TARGET_M68K */
2801
j_mayer7a3148a2007-04-05 07:13:51 +00002802#ifdef TARGET_ALPHA
Richard Henderson6910b8f2010-04-07 15:42:26 -07002803static void do_store_exclusive(CPUAlphaState *env, int reg, int quad)
2804{
2805 target_ulong addr, val, tmp;
2806 target_siginfo_t info;
2807 int ret = 0;
2808
2809 addr = env->lock_addr;
2810 tmp = env->lock_st_addr;
2811 env->lock_addr = -1;
2812 env->lock_st_addr = 0;
2813
2814 start_exclusive();
2815 mmap_lock();
2816
2817 if (addr == tmp) {
2818 if (quad ? get_user_s64(val, addr) : get_user_s32(val, addr)) {
2819 goto do_sigsegv;
2820 }
2821
2822 if (val == env->lock_value) {
2823 tmp = env->ir[reg];
2824 if (quad ? put_user_u64(tmp, addr) : put_user_u32(tmp, addr)) {
2825 goto do_sigsegv;
2826 }
2827 ret = 1;
2828 }
2829 }
2830 env->ir[reg] = ret;
2831 env->pc += 4;
2832
2833 mmap_unlock();
2834 end_exclusive();
2835 return;
2836
2837 do_sigsegv:
2838 mmap_unlock();
2839 end_exclusive();
2840
2841 info.si_signo = TARGET_SIGSEGV;
2842 info.si_errno = 0;
2843 info.si_code = TARGET_SEGV_MAPERR;
2844 info._sifields._sigfault._addr = addr;
2845 queue_signal(env, TARGET_SIGSEGV, &info);
2846}
2847
Andreas Färber05390242012-02-25 03:37:53 +01002848void cpu_loop(CPUAlphaState *env)
j_mayer7a3148a2007-04-05 07:13:51 +00002849{
Andreas Färber878096e2013-05-27 01:33:50 +02002850 CPUState *cs = CPU(alpha_env_get_cpu(env));
j_mayere96efcf2007-04-14 12:17:09 +00002851 int trapnr;
Anthony Liguoric227f092009-10-01 16:12:16 -05002852 target_siginfo_t info;
Richard Henderson6049f4f2009-12-27 18:30:03 -08002853 abi_long sysret;
ths3b46e622007-09-17 08:09:54 +00002854
j_mayer7a3148a2007-04-05 07:13:51 +00002855 while (1) {
2856 trapnr = cpu_alpha_exec (env);
ths3b46e622007-09-17 08:09:54 +00002857
Richard Hendersonac316ca2010-04-12 16:14:54 -07002858 /* All of the traps imply a transition through PALcode, which
2859 implies an REI instruction has been executed. Which means
2860 that the intr_flag should be cleared. */
2861 env->intr_flag = 0;
2862
j_mayer7a3148a2007-04-05 07:13:51 +00002863 switch (trapnr) {
2864 case EXCP_RESET:
2865 fprintf(stderr, "Reset requested. Exit\n");
2866 exit(1);
2867 break;
2868 case EXCP_MCHK:
2869 fprintf(stderr, "Machine check exception. Exit\n");
2870 exit(1);
2871 break;
Richard Henderson07b6c132011-05-20 14:04:57 -07002872 case EXCP_SMP_INTERRUPT:
2873 case EXCP_CLK_INTERRUPT:
2874 case EXCP_DEV_INTERRUPT:
ths5fafdf22007-09-16 21:08:06 +00002875 fprintf(stderr, "External interrupt. Exit\n");
j_mayer7a3148a2007-04-05 07:13:51 +00002876 exit(1);
2877 break;
Richard Henderson07b6c132011-05-20 14:04:57 -07002878 case EXCP_MMFAULT:
Richard Henderson6910b8f2010-04-07 15:42:26 -07002879 env->lock_addr = -1;
Richard Henderson6049f4f2009-12-27 18:30:03 -08002880 info.si_signo = TARGET_SIGSEGV;
2881 info.si_errno = 0;
Richard Henderson129d8aa2011-05-20 13:30:00 -07002882 info.si_code = (page_get_flags(env->trap_arg0) & PAGE_VALID
Richard Henderson0be1d072010-05-21 10:03:33 -07002883 ? TARGET_SEGV_ACCERR : TARGET_SEGV_MAPERR);
Richard Henderson129d8aa2011-05-20 13:30:00 -07002884 info._sifields._sigfault._addr = env->trap_arg0;
Richard Henderson6049f4f2009-12-27 18:30:03 -08002885 queue_signal(env, info.si_signo, &info);
j_mayer7a3148a2007-04-05 07:13:51 +00002886 break;
j_mayer7a3148a2007-04-05 07:13:51 +00002887 case EXCP_UNALIGN:
Richard Henderson6910b8f2010-04-07 15:42:26 -07002888 env->lock_addr = -1;
Richard Henderson6049f4f2009-12-27 18:30:03 -08002889 info.si_signo = TARGET_SIGBUS;
2890 info.si_errno = 0;
2891 info.si_code = TARGET_BUS_ADRALN;
Richard Henderson129d8aa2011-05-20 13:30:00 -07002892 info._sifields._sigfault._addr = env->trap_arg0;
Richard Henderson6049f4f2009-12-27 18:30:03 -08002893 queue_signal(env, info.si_signo, &info);
j_mayer7a3148a2007-04-05 07:13:51 +00002894 break;
2895 case EXCP_OPCDEC:
Richard Henderson6049f4f2009-12-27 18:30:03 -08002896 do_sigill:
Richard Henderson6910b8f2010-04-07 15:42:26 -07002897 env->lock_addr = -1;
Richard Henderson6049f4f2009-12-27 18:30:03 -08002898 info.si_signo = TARGET_SIGILL;
2899 info.si_errno = 0;
2900 info.si_code = TARGET_ILL_ILLOPC;
2901 info._sifields._sigfault._addr = env->pc;
2902 queue_signal(env, info.si_signo, &info);
j_mayer7a3148a2007-04-05 07:13:51 +00002903 break;
Richard Henderson07b6c132011-05-20 14:04:57 -07002904 case EXCP_ARITH:
2905 env->lock_addr = -1;
2906 info.si_signo = TARGET_SIGFPE;
2907 info.si_errno = 0;
2908 info.si_code = TARGET_FPE_FLTINV;
2909 info._sifields._sigfault._addr = env->pc;
2910 queue_signal(env, info.si_signo, &info);
2911 break;
j_mayer7a3148a2007-04-05 07:13:51 +00002912 case EXCP_FEN:
Richard Henderson6049f4f2009-12-27 18:30:03 -08002913 /* No-op. Linux simply re-enables the FPU. */
j_mayer7a3148a2007-04-05 07:13:51 +00002914 break;
Richard Henderson07b6c132011-05-20 14:04:57 -07002915 case EXCP_CALL_PAL:
Richard Henderson6910b8f2010-04-07 15:42:26 -07002916 env->lock_addr = -1;
Richard Henderson07b6c132011-05-20 14:04:57 -07002917 switch (env->error_code) {
Richard Henderson6049f4f2009-12-27 18:30:03 -08002918 case 0x80:
2919 /* BPT */
2920 info.si_signo = TARGET_SIGTRAP;
2921 info.si_errno = 0;
2922 info.si_code = TARGET_TRAP_BRKPT;
2923 info._sifields._sigfault._addr = env->pc;
2924 queue_signal(env, info.si_signo, &info);
2925 break;
2926 case 0x81:
2927 /* BUGCHK */
2928 info.si_signo = TARGET_SIGTRAP;
2929 info.si_errno = 0;
2930 info.si_code = 0;
2931 info._sifields._sigfault._addr = env->pc;
2932 queue_signal(env, info.si_signo, &info);
2933 break;
2934 case 0x83:
2935 /* CALLSYS */
2936 trapnr = env->ir[IR_V0];
2937 sysret = do_syscall(env, trapnr,
2938 env->ir[IR_A0], env->ir[IR_A1],
2939 env->ir[IR_A2], env->ir[IR_A3],
Peter Maydell5945cfc2011-06-16 17:37:13 +01002940 env->ir[IR_A4], env->ir[IR_A5],
2941 0, 0);
Richard Hendersona5b3b132010-05-03 10:07:55 -07002942 if (trapnr == TARGET_NR_sigreturn
2943 || trapnr == TARGET_NR_rt_sigreturn) {
2944 break;
2945 }
2946 /* Syscall writes 0 to V0 to bypass error check, similar
Richard Henderson0e141972012-06-07 14:47:41 -07002947 to how this is handled internal to Linux kernel.
2948 (Ab)use trapnr temporarily as boolean indicating error. */
2949 trapnr = (env->ir[IR_V0] != 0 && sysret < 0);
2950 env->ir[IR_V0] = (trapnr ? -sysret : sysret);
2951 env->ir[IR_A3] = trapnr;
Richard Henderson6049f4f2009-12-27 18:30:03 -08002952 break;
2953 case 0x86:
2954 /* IMB */
2955 /* ??? We can probably elide the code using page_unprotect
2956 that is checking for self-modifying code. Instead we
2957 could simply call tb_flush here. Until we work out the
2958 changes required to turn off the extra write protection,
2959 this can be a no-op. */
2960 break;
2961 case 0x9E:
2962 /* RDUNIQUE */
2963 /* Handled in the translator for usermode. */
2964 abort();
2965 case 0x9F:
2966 /* WRUNIQUE */
2967 /* Handled in the translator for usermode. */
2968 abort();
2969 case 0xAA:
2970 /* GENTRAP */
2971 info.si_signo = TARGET_SIGFPE;
2972 switch (env->ir[IR_A0]) {
2973 case TARGET_GEN_INTOVF:
2974 info.si_code = TARGET_FPE_INTOVF;
2975 break;
2976 case TARGET_GEN_INTDIV:
2977 info.si_code = TARGET_FPE_INTDIV;
2978 break;
2979 case TARGET_GEN_FLTOVF:
2980 info.si_code = TARGET_FPE_FLTOVF;
2981 break;
2982 case TARGET_GEN_FLTUND:
2983 info.si_code = TARGET_FPE_FLTUND;
2984 break;
2985 case TARGET_GEN_FLTINV:
2986 info.si_code = TARGET_FPE_FLTINV;
2987 break;
2988 case TARGET_GEN_FLTINE:
2989 info.si_code = TARGET_FPE_FLTRES;
2990 break;
2991 case TARGET_GEN_ROPRAND:
2992 info.si_code = 0;
2993 break;
2994 default:
2995 info.si_signo = TARGET_SIGTRAP;
2996 info.si_code = 0;
2997 break;
2998 }
2999 info.si_errno = 0;
3000 info._sifields._sigfault._addr = env->pc;
3001 queue_signal(env, info.si_signo, &info);
3002 break;
3003 default:
3004 goto do_sigill;
3005 }
j_mayer7a3148a2007-04-05 07:13:51 +00003006 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003007 case EXCP_DEBUG:
Richard Henderson6049f4f2009-12-27 18:30:03 -08003008 info.si_signo = gdb_handlesig (env, TARGET_SIGTRAP);
3009 if (info.si_signo) {
Richard Henderson6910b8f2010-04-07 15:42:26 -07003010 env->lock_addr = -1;
Richard Henderson6049f4f2009-12-27 18:30:03 -08003011 info.si_errno = 0;
3012 info.si_code = TARGET_TRAP_BRKPT;
3013 queue_signal(env, info.si_signo, &info);
j_mayer7a3148a2007-04-05 07:13:51 +00003014 }
3015 break;
Richard Henderson6910b8f2010-04-07 15:42:26 -07003016 case EXCP_STL_C:
3017 case EXCP_STQ_C:
3018 do_store_exclusive(env, env->error_code, trapnr - EXCP_STL_C);
3019 break;
Richard Hendersond0f20492012-05-31 12:05:23 -07003020 case EXCP_INTERRUPT:
3021 /* Just indicate that signals should be handled asap. */
3022 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003023 default:
3024 printf ("Unhandled trap: 0x%x\n", trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +02003025 cpu_dump_state(cs, stderr, fprintf, 0);
j_mayer7a3148a2007-04-05 07:13:51 +00003026 exit (1);
3027 }
3028 process_pending_signals (env);
3029 }
3030}
3031#endif /* TARGET_ALPHA */
3032
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003033#ifdef TARGET_S390X
3034void cpu_loop(CPUS390XState *env)
3035{
Andreas Färber878096e2013-05-27 01:33:50 +02003036 CPUState *cs = CPU(s390_env_get_cpu(env));
Richard Hendersond5a103c2012-09-14 19:31:57 -07003037 int trapnr, n, sig;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003038 target_siginfo_t info;
Richard Hendersond5a103c2012-09-14 19:31:57 -07003039 target_ulong addr;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003040
3041 while (1) {
Richard Hendersond5a103c2012-09-14 19:31:57 -07003042 trapnr = cpu_s390x_exec(env);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003043 switch (trapnr) {
3044 case EXCP_INTERRUPT:
Richard Hendersond5a103c2012-09-14 19:31:57 -07003045 /* Just indicate that signals should be handled asap. */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003046 break;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003047
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003048 case EXCP_SVC:
Richard Hendersond5a103c2012-09-14 19:31:57 -07003049 n = env->int_svc_code;
3050 if (!n) {
3051 /* syscalls > 255 */
3052 n = env->regs[1];
3053 }
3054 env->psw.addr += env->int_svc_ilen;
3055 env->regs[2] = do_syscall(env, n, env->regs[2], env->regs[3],
3056 env->regs[4], env->regs[5],
3057 env->regs[6], env->regs[7], 0, 0);
3058 break;
3059
3060 case EXCP_DEBUG:
3061 sig = gdb_handlesig(env, TARGET_SIGTRAP);
3062 if (sig) {
3063 n = TARGET_TRAP_BRKPT;
3064 goto do_signal_pc;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003065 }
3066 break;
Richard Hendersond5a103c2012-09-14 19:31:57 -07003067 case EXCP_PGM:
3068 n = env->int_pgm_code;
3069 switch (n) {
3070 case PGM_OPERATION:
3071 case PGM_PRIVILEGED:
3072 sig = SIGILL;
3073 n = TARGET_ILL_ILLOPC;
3074 goto do_signal_pc;
3075 case PGM_PROTECTION:
3076 case PGM_ADDRESSING:
3077 sig = SIGSEGV;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003078 /* XXX: check env->error_code */
Richard Hendersond5a103c2012-09-14 19:31:57 -07003079 n = TARGET_SEGV_MAPERR;
3080 addr = env->__excp_addr;
3081 goto do_signal;
3082 case PGM_EXECUTE:
3083 case PGM_SPECIFICATION:
3084 case PGM_SPECIAL_OP:
3085 case PGM_OPERAND:
3086 do_sigill_opn:
3087 sig = SIGILL;
3088 n = TARGET_ILL_ILLOPN;
3089 goto do_signal_pc;
3090
3091 case PGM_FIXPT_OVERFLOW:
3092 sig = SIGFPE;
3093 n = TARGET_FPE_INTOVF;
3094 goto do_signal_pc;
3095 case PGM_FIXPT_DIVIDE:
3096 sig = SIGFPE;
3097 n = TARGET_FPE_INTDIV;
3098 goto do_signal_pc;
3099
3100 case PGM_DATA:
3101 n = (env->fpc >> 8) & 0xff;
3102 if (n == 0xff) {
3103 /* compare-and-trap */
3104 goto do_sigill_opn;
3105 } else {
3106 /* An IEEE exception, simulated or otherwise. */
3107 if (n & 0x80) {
3108 n = TARGET_FPE_FLTINV;
3109 } else if (n & 0x40) {
3110 n = TARGET_FPE_FLTDIV;
3111 } else if (n & 0x20) {
3112 n = TARGET_FPE_FLTOVF;
3113 } else if (n & 0x10) {
3114 n = TARGET_FPE_FLTUND;
3115 } else if (n & 0x08) {
3116 n = TARGET_FPE_FLTRES;
3117 } else {
3118 /* ??? Quantum exception; BFP, DFP error. */
3119 goto do_sigill_opn;
3120 }
3121 sig = SIGFPE;
3122 goto do_signal_pc;
3123 }
3124
3125 default:
3126 fprintf(stderr, "Unhandled program exception: %#x\n", n);
Andreas Färber878096e2013-05-27 01:33:50 +02003127 cpu_dump_state(cs, stderr, fprintf, 0);
Richard Hendersond5a103c2012-09-14 19:31:57 -07003128 exit(1);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003129 }
3130 break;
Richard Hendersond5a103c2012-09-14 19:31:57 -07003131
3132 do_signal_pc:
3133 addr = env->psw.addr;
3134 do_signal:
3135 info.si_signo = sig;
3136 info.si_errno = 0;
3137 info.si_code = n;
3138 info._sifields._sigfault._addr = addr;
3139 queue_signal(env, info.si_signo, &info);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003140 break;
Richard Hendersond5a103c2012-09-14 19:31:57 -07003141
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003142 default:
Richard Hendersond5a103c2012-09-14 19:31:57 -07003143 fprintf(stderr, "Unhandled trap: 0x%x\n", trapnr);
Andreas Färber878096e2013-05-27 01:33:50 +02003144 cpu_dump_state(cs, stderr, fprintf, 0);
Richard Hendersond5a103c2012-09-14 19:31:57 -07003145 exit(1);
Ulrich Hechta4c075f2009-07-24 16:57:31 +02003146 }
3147 process_pending_signals (env);
3148 }
3149}
3150
3151#endif /* TARGET_S390X */
3152
Andreas Färbera2247f82013-06-09 19:47:04 +02003153THREAD CPUState *thread_cpu;
bellard59faf6d2003-06-25 16:18:50 +00003154
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003155void task_settid(TaskState *ts)
3156{
3157 if (ts->ts_tid == 0) {
Juan Quintela2f7bb872009-07-27 16:13:24 +02003158#ifdef CONFIG_USE_NPTL
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003159 ts->ts_tid = (pid_t)syscall(SYS_gettid);
3160#else
3161 /* when no threads are used, tid becomes pid */
3162 ts->ts_tid = getpid();
3163#endif
3164 }
3165}
3166
3167void stop_all_tasks(void)
3168{
3169 /*
3170 * We trust that when using NPTL, start_exclusive()
3171 * handles thread stopping correctly.
3172 */
3173 start_exclusive();
3174}
3175
pbrookc3a92832008-06-09 14:02:50 +00003176/* Assumes contents are already zeroed. */
pbrook624f7972008-05-31 16:11:38 +00003177void init_task_state(TaskState *ts)
3178{
3179 int i;
3180
pbrook624f7972008-05-31 16:11:38 +00003181 ts->used = 1;
3182 ts->first_free = ts->sigqueue_table;
3183 for (i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++) {
3184 ts->sigqueue_table[i].next = &ts->sigqueue_table[i + 1];
3185 }
3186 ts->sigqueue_table[i].next = NULL;
3187}
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003188
3189static void handle_arg_help(const char *arg)
3190{
3191 usage();
3192}
3193
3194static void handle_arg_log(const char *arg)
3195{
3196 int mask;
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003197
Peter Maydell4fde1eb2013-02-11 16:41:22 +00003198 mask = qemu_str_to_log_mask(arg);
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003199 if (!mask) {
Peter Maydell59a6fa62013-02-11 16:41:21 +00003200 qemu_print_log_usage(stdout);
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003201 exit(1);
3202 }
Peter Maydell24537a02013-02-11 16:41:23 +00003203 qemu_set_log(mask);
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003204}
3205
陳韋任50171d42011-11-08 17:46:44 +08003206static void handle_arg_log_filename(const char *arg)
3207{
Peter Maydell9a7e5422013-02-11 16:41:20 +00003208 qemu_set_log_filename(arg);
陳韋任50171d42011-11-08 17:46:44 +08003209}
3210
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003211static void handle_arg_set_env(const char *arg)
3212{
3213 char *r, *p, *token;
3214 r = p = strdup(arg);
3215 while ((token = strsep(&p, ",")) != NULL) {
3216 if (envlist_setenv(envlist, token) != 0) {
3217 usage();
3218 }
3219 }
3220 free(r);
3221}
3222
3223static void handle_arg_unset_env(const char *arg)
3224{
3225 char *r, *p, *token;
3226 r = p = strdup(arg);
3227 while ((token = strsep(&p, ",")) != NULL) {
3228 if (envlist_unsetenv(envlist, token) != 0) {
3229 usage();
3230 }
3231 }
3232 free(r);
3233}
3234
3235static void handle_arg_argv0(const char *arg)
3236{
3237 argv0 = strdup(arg);
3238}
3239
3240static void handle_arg_stack_size(const char *arg)
3241{
3242 char *p;
3243 guest_stack_size = strtoul(arg, &p, 0);
3244 if (guest_stack_size == 0) {
3245 usage();
3246 }
3247
3248 if (*p == 'M') {
3249 guest_stack_size *= 1024 * 1024;
3250 } else if (*p == 'k' || *p == 'K') {
3251 guest_stack_size *= 1024;
3252 }
3253}
3254
3255static void handle_arg_ld_prefix(const char *arg)
3256{
3257 interp_prefix = strdup(arg);
3258}
3259
3260static void handle_arg_pagesize(const char *arg)
3261{
3262 qemu_host_page_size = atoi(arg);
3263 if (qemu_host_page_size == 0 ||
3264 (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
3265 fprintf(stderr, "page size must be a power of two\n");
3266 exit(1);
3267 }
3268}
3269
3270static void handle_arg_gdb(const char *arg)
3271{
3272 gdbstub_port = atoi(arg);
3273}
3274
3275static void handle_arg_uname(const char *arg)
3276{
3277 qemu_uname_release = strdup(arg);
3278}
3279
3280static void handle_arg_cpu(const char *arg)
3281{
3282 cpu_model = strdup(arg);
Peter Maydellc8057f92012-08-02 13:45:54 +01003283 if (cpu_model == NULL || is_help_option(cpu_model)) {
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003284 /* XXX: implement xxx_cpu_list for targets that still miss it */
Peter Maydelle916cbf2012-09-05 17:41:08 -03003285#if defined(cpu_list)
3286 cpu_list(stdout, &fprintf);
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003287#endif
3288 exit(1);
3289 }
3290}
3291
3292#if defined(CONFIG_USE_GUEST_BASE)
3293static void handle_arg_guest_base(const char *arg)
3294{
3295 guest_base = strtol(arg, NULL, 0);
3296 have_guest_base = 1;
3297}
3298
3299static void handle_arg_reserved_va(const char *arg)
3300{
3301 char *p;
3302 int shift = 0;
3303 reserved_va = strtoul(arg, &p, 0);
3304 switch (*p) {
3305 case 'k':
3306 case 'K':
3307 shift = 10;
3308 break;
3309 case 'M':
3310 shift = 20;
3311 break;
3312 case 'G':
3313 shift = 30;
3314 break;
3315 }
3316 if (shift) {
3317 unsigned long unshifted = reserved_va;
3318 p++;
3319 reserved_va <<= shift;
3320 if (((reserved_va >> shift) != unshifted)
3321#if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS
3322 || (reserved_va > (1ul << TARGET_VIRT_ADDR_SPACE_BITS))
3323#endif
3324 ) {
3325 fprintf(stderr, "Reserved virtual address too big\n");
3326 exit(1);
3327 }
3328 }
3329 if (*p) {
3330 fprintf(stderr, "Unrecognised -R size suffix '%s'\n", p);
3331 exit(1);
3332 }
3333}
3334#endif
3335
3336static void handle_arg_singlestep(const char *arg)
3337{
3338 singlestep = 1;
3339}
3340
3341static void handle_arg_strace(const char *arg)
3342{
3343 do_strace = 1;
3344}
3345
3346static void handle_arg_version(const char *arg)
3347{
Paolo Bonzini2e599152013-06-04 14:45:27 +02003348 printf("qemu-" TARGET_NAME " version " QEMU_VERSION QEMU_PKGVERSION
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003349 ", Copyright (c) 2003-2008 Fabrice Bellard\n");
Peter Maydell1386d4c2011-09-29 15:48:12 +01003350 exit(0);
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003351}
3352
3353struct qemu_argument {
3354 const char *argv;
3355 const char *env;
3356 bool has_arg;
3357 void (*handle_opt)(const char *arg);
3358 const char *example;
3359 const char *help;
3360};
3361
Jim Meyering42644ce2012-05-21 21:56:19 +02003362static const struct qemu_argument arg_table[] = {
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003363 {"h", "", false, handle_arg_help,
3364 "", "print this help"},
3365 {"g", "QEMU_GDB", true, handle_arg_gdb,
3366 "port", "wait gdb connection to 'port'"},
3367 {"L", "QEMU_LD_PREFIX", true, handle_arg_ld_prefix,
3368 "path", "set the elf interpreter prefix to 'path'"},
3369 {"s", "QEMU_STACK_SIZE", true, handle_arg_stack_size,
3370 "size", "set the stack size to 'size' bytes"},
3371 {"cpu", "QEMU_CPU", true, handle_arg_cpu,
Peter Maydellc8057f92012-08-02 13:45:54 +01003372 "model", "select CPU (-cpu help for list)"},
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003373 {"E", "QEMU_SET_ENV", true, handle_arg_set_env,
3374 "var=value", "sets targets environment variable (see below)"},
3375 {"U", "QEMU_UNSET_ENV", true, handle_arg_unset_env,
3376 "var", "unsets targets environment variable (see below)"},
3377 {"0", "QEMU_ARGV0", true, handle_arg_argv0,
3378 "argv0", "forces target process argv[0] to be 'argv0'"},
3379 {"r", "QEMU_UNAME", true, handle_arg_uname,
3380 "uname", "set qemu uname release string to 'uname'"},
3381#if defined(CONFIG_USE_GUEST_BASE)
3382 {"B", "QEMU_GUEST_BASE", true, handle_arg_guest_base,
3383 "address", "set guest_base address to 'address'"},
3384 {"R", "QEMU_RESERVED_VA", true, handle_arg_reserved_va,
3385 "size", "reserve 'size' bytes for guest virtual address space"},
3386#endif
3387 {"d", "QEMU_LOG", true, handle_arg_log,
Peter Maydell989b6972013-02-26 17:52:40 +00003388 "item[,...]", "enable logging of specified items "
3389 "(use '-d help' for a list of items)"},
陳韋任50171d42011-11-08 17:46:44 +08003390 {"D", "QEMU_LOG_FILENAME", true, handle_arg_log_filename,
Peter Maydell989b6972013-02-26 17:52:40 +00003391 "logfile", "write logs to 'logfile' (default stderr)"},
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003392 {"p", "QEMU_PAGESIZE", true, handle_arg_pagesize,
3393 "pagesize", "set the host page size to 'pagesize'"},
3394 {"singlestep", "QEMU_SINGLESTEP", false, handle_arg_singlestep,
3395 "", "run in singlestep mode"},
3396 {"strace", "QEMU_STRACE", false, handle_arg_strace,
3397 "", "log system calls"},
3398 {"version", "QEMU_VERSION", false, handle_arg_version,
Peter Maydell1386d4c2011-09-29 15:48:12 +01003399 "", "display version information and exit"},
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003400 {NULL, NULL, false, NULL, NULL, NULL}
3401};
3402
3403static void usage(void)
3404{
Jim Meyering42644ce2012-05-21 21:56:19 +02003405 const struct qemu_argument *arginfo;
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003406 int maxarglen;
3407 int maxenvlen;
3408
Paolo Bonzini2e599152013-06-04 14:45:27 +02003409 printf("usage: qemu-" TARGET_NAME " [options] program [arguments...]\n"
3410 "Linux CPU emulator (compiled for " TARGET_NAME " emulation)\n"
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003411 "\n"
3412 "Options and associated environment variables:\n"
3413 "\n");
3414
Peter Maydell63ec54d2013-02-14 08:46:43 +00003415 /* Calculate column widths. We must always have at least enough space
3416 * for the column header.
3417 */
3418 maxarglen = strlen("Argument");
3419 maxenvlen = strlen("Env-variable");
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003420
3421 for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
Peter Maydell63ec54d2013-02-14 08:46:43 +00003422 int arglen = strlen(arginfo->argv);
3423 if (arginfo->has_arg) {
3424 arglen += strlen(arginfo->example) + 1;
3425 }
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003426 if (strlen(arginfo->env) > maxenvlen) {
3427 maxenvlen = strlen(arginfo->env);
3428 }
Peter Maydell63ec54d2013-02-14 08:46:43 +00003429 if (arglen > maxarglen) {
3430 maxarglen = arglen;
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003431 }
3432 }
3433
Peter Maydell63ec54d2013-02-14 08:46:43 +00003434 printf("%-*s %-*s Description\n", maxarglen+1, "Argument",
3435 maxenvlen, "Env-variable");
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003436
3437 for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
3438 if (arginfo->has_arg) {
3439 printf("-%s %-*s %-*s %s\n", arginfo->argv,
Peter Maydell63ec54d2013-02-14 08:46:43 +00003440 (int)(maxarglen - strlen(arginfo->argv) - 1),
3441 arginfo->example, maxenvlen, arginfo->env, arginfo->help);
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003442 } else {
Peter Maydell63ec54d2013-02-14 08:46:43 +00003443 printf("-%-*s %-*s %s\n", maxarglen, arginfo->argv,
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003444 maxenvlen, arginfo->env,
3445 arginfo->help);
3446 }
3447 }
3448
3449 printf("\n"
3450 "Defaults:\n"
3451 "QEMU_LD_PREFIX = %s\n"
Peter Maydell989b6972013-02-26 17:52:40 +00003452 "QEMU_STACK_SIZE = %ld byte\n",
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003453 interp_prefix,
Peter Maydell989b6972013-02-26 17:52:40 +00003454 guest_stack_size);
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003455
3456 printf("\n"
3457 "You can use -E and -U options or the QEMU_SET_ENV and\n"
3458 "QEMU_UNSET_ENV environment variables to set and unset\n"
3459 "environment variables for the target process.\n"
3460 "It is possible to provide several variables by separating them\n"
3461 "by commas in getsubopt(3) style. Additionally it is possible to\n"
3462 "provide the -E and -U options multiple times.\n"
3463 "The following lines are equivalent:\n"
3464 " -E var1=val2 -E var2=val2 -U LD_PRELOAD -U LD_DEBUG\n"
3465 " -E var1=val2,var2=val2 -U LD_PRELOAD,LD_DEBUG\n"
3466 " QEMU_SET_ENV=var1=val2,var2=val2 QEMU_UNSET_ENV=LD_PRELOAD,LD_DEBUG\n"
3467 "Note that if you provide several changes to a single variable\n"
3468 "the last change will stay in effect.\n");
3469
3470 exit(1);
3471}
3472
3473static int parse_args(int argc, char **argv)
3474{
3475 const char *r;
3476 int optind;
Jim Meyering42644ce2012-05-21 21:56:19 +02003477 const struct qemu_argument *arginfo;
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003478
3479 for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
3480 if (arginfo->env == NULL) {
3481 continue;
3482 }
3483
3484 r = getenv(arginfo->env);
3485 if (r != NULL) {
3486 arginfo->handle_opt(r);
3487 }
3488 }
3489
3490 optind = 1;
3491 for (;;) {
3492 if (optind >= argc) {
3493 break;
3494 }
3495 r = argv[optind];
3496 if (r[0] != '-') {
3497 break;
3498 }
3499 optind++;
3500 r++;
3501 if (!strcmp(r, "-")) {
3502 break;
3503 }
3504
3505 for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
3506 if (!strcmp(r, arginfo->argv)) {
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003507 if (arginfo->has_arg) {
Peter Maydell1386d4c2011-09-29 15:48:12 +01003508 if (optind >= argc) {
3509 usage();
3510 }
3511 arginfo->handle_opt(argv[optind]);
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003512 optind++;
Peter Maydell1386d4c2011-09-29 15:48:12 +01003513 } else {
3514 arginfo->handle_opt(NULL);
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003515 }
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003516 break;
3517 }
3518 }
3519
3520 /* no option matched the current argv */
3521 if (arginfo->handle_opt == NULL) {
3522 usage();
3523 }
3524 }
3525
3526 if (optind >= argc) {
3527 usage();
3528 }
3529
3530 filename = argv[optind];
3531 exec_path = argv[optind];
3532
3533 return optind;
3534}
3535
malc902b3d52008-12-10 19:18:40 +00003536int main(int argc, char **argv, char **envp)
bellard31e31b82003-02-18 22:55:36 +00003537{
bellard01ffc752003-02-18 23:00:51 +00003538 struct target_pt_regs regs1, *regs = &regs1;
bellard31e31b82003-02-18 22:55:36 +00003539 struct image_info info1, *info = &info1;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003540 struct linux_binprm bprm;
Nathan Froyd48e15fc2010-10-29 07:48:57 -07003541 TaskState *ts;
Andreas Färber9349b4f2012-03-14 01:38:32 +01003542 CPUArchState *env;
bellard586314f2003-03-03 15:02:29 +00003543 int optind;
aurel3204a6dfe2009-01-30 19:59:17 +00003544 char **target_environ, **wrk;
aurel327d8cec92009-04-15 16:11:52 +00003545 char **target_argv;
3546 int target_argc;
aurel327d8cec92009-04-15 16:11:52 +00003547 int i;
Arnaud Patardfd4d81d2009-06-19 10:39:36 +03003548 int ret;
thsb12b6a12007-06-17 16:38:39 +00003549
Andreas Färberce008c12012-03-04 21:32:36 +01003550 module_call_init(MODULE_INIT_QOM);
3551
malc902b3d52008-12-10 19:18:40 +00003552 qemu_cache_utils_init(envp);
3553
aurel3204a6dfe2009-01-30 19:59:17 +00003554 if ((envlist = envlist_create()) == NULL) {
3555 (void) fprintf(stderr, "Unable to allocate envlist\n");
3556 exit(1);
3557 }
3558
3559 /* add current environment into the list */
3560 for (wrk = environ; *wrk != NULL; wrk++) {
3561 (void) envlist_setenv(envlist, *wrk);
3562 }
3563
Richard Henderson703e0e82010-03-19 14:21:13 -07003564 /* Read the stack limit from the kernel. If it's "unlimited",
3565 then we can do little else besides use the default. */
3566 {
3567 struct rlimit lim;
3568 if (getrlimit(RLIMIT_STACK, &lim) == 0
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09003569 && lim.rlim_cur != RLIM_INFINITY
3570 && lim.rlim_cur == (target_long)lim.rlim_cur) {
Richard Henderson703e0e82010-03-19 14:21:13 -07003571 guest_stack_size = lim.rlim_cur;
3572 }
3573 }
3574
j_mayerb1f9be32007-03-19 08:08:28 +00003575 cpu_model = NULL;
john cooperb5ec5ce2010-02-20 11:14:59 -06003576#if defined(cpudef_setup)
3577 cpudef_setup(); /* parse cpu definitions in target config file (TBD) */
3578#endif
3579
Johannes Schauerfc9c5412011-08-06 08:54:12 +02003580 optind = parse_args(argc, argv);
Peter Maydell4b5dfd82011-07-18 11:44:09 +01003581
bellard31e31b82003-02-18 22:55:36 +00003582 /* Zero out regs */
bellard01ffc752003-02-18 23:00:51 +00003583 memset(regs, 0, sizeof(struct target_pt_regs));
bellard31e31b82003-02-18 22:55:36 +00003584
3585 /* Zero out image_info */
3586 memset(info, 0, sizeof(struct image_info));
3587
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003588 memset(&bprm, 0, sizeof (bprm));
3589
bellard74cd30b2003-04-11 00:13:41 +00003590 /* Scan interp_prefix dir for replacement files. */
3591 init_paths(interp_prefix);
3592
bellard46027c02007-11-08 13:56:19 +00003593 if (cpu_model == NULL) {
bellardaaed9092007-11-10 15:15:54 +00003594#if defined(TARGET_I386)
bellard46027c02007-11-08 13:56:19 +00003595#ifdef TARGET_X86_64
3596 cpu_model = "qemu64";
3597#else
3598 cpu_model = "qemu32";
3599#endif
bellardaaed9092007-11-10 15:15:54 +00003600#elif defined(TARGET_ARM)
pbrook088ab162009-04-09 15:20:50 +00003601 cpu_model = "any";
Guan Xuetaod2fbca92011-04-12 16:27:03 +08003602#elif defined(TARGET_UNICORE32)
3603 cpu_model = "any";
bellardaaed9092007-11-10 15:15:54 +00003604#elif defined(TARGET_M68K)
3605 cpu_model = "any";
3606#elif defined(TARGET_SPARC)
3607#ifdef TARGET_SPARC64
3608 cpu_model = "TI UltraSparc II";
3609#else
3610 cpu_model = "Fujitsu MB86904";
bellard46027c02007-11-08 13:56:19 +00003611#endif
bellardaaed9092007-11-10 15:15:54 +00003612#elif defined(TARGET_MIPS)
3613#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64)
3614 cpu_model = "20Kc";
3615#else
3616 cpu_model = "24Kf";
3617#endif
Jia Liud9627832012-07-20 15:50:52 +08003618#elif defined TARGET_OPENRISC
3619 cpu_model = "or1200";
bellardaaed9092007-11-10 15:15:54 +00003620#elif defined(TARGET_PPC)
bellard7ded4f52007-11-15 15:37:50 +00003621#ifdef TARGET_PPC64
Aurelien Jarnof7177932010-04-06 12:21:05 +02003622 cpu_model = "970fx";
bellard7ded4f52007-11-15 15:37:50 +00003623#else
bellardaaed9092007-11-10 15:15:54 +00003624 cpu_model = "750";
bellard7ded4f52007-11-15 15:37:50 +00003625#endif
bellardaaed9092007-11-10 15:15:54 +00003626#else
3627 cpu_model = "any";
3628#endif
3629 }
Jan Kiszkad5ab9712011-08-02 16:10:21 +02003630 tcg_exec_init(0);
3631 cpu_exec_init_all();
bellard83fb7ad2004-07-05 21:25:26 +00003632 /* NOTE: we need to init the CPU at this stage to get
3633 qemu_host_page_size */
bellardaaed9092007-11-10 15:15:54 +00003634 env = cpu_init(cpu_model);
3635 if (!env) {
3636 fprintf(stderr, "Unable to find CPU definition\n");
3637 exit(1);
3638 }
Andreas Färber77868122013-01-20 05:34:10 +01003639#if defined(TARGET_SPARC) || defined(TARGET_PPC)
Andreas Färberff18b762012-05-05 14:47:34 +02003640 cpu_reset(ENV_GET_CPU(env));
Blue Swirlb55a37c2009-11-07 10:37:06 +00003641#endif
3642
Andreas Färbera2247f82013-06-09 19:47:04 +02003643 thread_cpu = ENV_GET_CPU(env);
ths3b46e622007-09-17 08:09:54 +00003644
bellardb6741952007-11-11 14:46:06 +00003645 if (getenv("QEMU_STRACE")) {
3646 do_strace = 1;
thsb92c47c2007-11-01 00:07:38 +00003647 }
3648
aurel3204a6dfe2009-01-30 19:59:17 +00003649 target_environ = envlist_to_environ(envlist, NULL);
3650 envlist_free(envlist);
thsb12b6a12007-06-17 16:38:39 +00003651
Paul Brook379f6692009-07-17 12:48:08 +01003652#if defined(CONFIG_USE_GUEST_BASE)
3653 /*
3654 * Now that page sizes are configured in cpu_init() we can do
3655 * proper page alignment for guest_base.
3656 */
3657 guest_base = HOST_PAGE_ALIGN(guest_base);
Paul Brook68a1c812010-05-29 02:27:35 +01003658
Meador Inge806d1022012-07-26 16:50:02 +00003659 if (reserved_va || have_guest_base) {
3660 guest_base = init_guest_space(guest_base, reserved_va, 0,
3661 have_guest_base);
3662 if (guest_base == (unsigned long)-1) {
Peter Maydell097b8cb2012-08-20 11:36:32 +01003663 fprintf(stderr, "Unable to reserve 0x%lx bytes of virtual address "
3664 "space for use as guest address space (check your virtual "
3665 "memory ulimit setting or reserve less using -R option)\n",
3666 reserved_va);
Paul Brook68a1c812010-05-29 02:27:35 +01003667 exit(1);
3668 }
Dr. David Alan Gilbert97cc7562011-08-31 17:24:34 +01003669
Meador Inge806d1022012-07-26 16:50:02 +00003670 if (reserved_va) {
3671 mmap_next_start = reserved_va;
Dr. David Alan Gilbert97cc7562011-08-31 17:24:34 +01003672 }
3673 }
Richard Henderson14f24e12010-03-10 15:39:07 -08003674#endif /* CONFIG_USE_GUEST_BASE */
Paul Brook379f6692009-07-17 12:48:08 +01003675
3676 /*
3677 * Read in mmap_min_addr kernel parameter. This value is used
3678 * When loading the ELF image to determine whether guest_base
Richard Henderson14f24e12010-03-10 15:39:07 -08003679 * is needed. It is also used in mmap_find_vma.
Paul Brook379f6692009-07-17 12:48:08 +01003680 */
Richard Henderson14f24e12010-03-10 15:39:07 -08003681 {
Paul Brook379f6692009-07-17 12:48:08 +01003682 FILE *fp;
3683
3684 if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) {
3685 unsigned long tmp;
3686 if (fscanf(fp, "%lu", &tmp) == 1) {
3687 mmap_min_addr = tmp;
3688 qemu_log("host mmap_min_addr=0x%lx\n", mmap_min_addr);
3689 }
3690 fclose(fp);
3691 }
3692 }
Paul Brook379f6692009-07-17 12:48:08 +01003693
aurel327d8cec92009-04-15 16:11:52 +00003694 /*
3695 * Prepare copy of argv vector for target.
3696 */
3697 target_argc = argc - optind;
3698 target_argv = calloc(target_argc + 1, sizeof (char *));
3699 if (target_argv == NULL) {
3700 (void) fprintf(stderr, "Unable to allocate memory for target_argv\n");
3701 exit(1);
3702 }
3703
3704 /*
3705 * If argv0 is specified (using '-0' switch) we replace
3706 * argv[0] pointer with the given one.
3707 */
3708 i = 0;
3709 if (argv0 != NULL) {
3710 target_argv[i++] = strdup(argv0);
3711 }
3712 for (; i < target_argc; i++) {
3713 target_argv[i] = strdup(argv[optind + i]);
3714 }
3715 target_argv[target_argc] = NULL;
3716
Anthony Liguori7267c092011-08-20 22:09:37 -05003717 ts = g_malloc0 (sizeof(TaskState));
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003718 init_task_state(ts);
3719 /* build Task State */
3720 ts->info = info;
3721 ts->bprm = &bprm;
3722 env->opaque = ts;
3723 task_settid(ts);
3724
Arnaud Patardfd4d81d2009-06-19 10:39:36 +03003725 ret = loader_exec(filename, target_argv, target_environ, regs,
3726 info, &bprm);
3727 if (ret != 0) {
Peter Maydell885c1d12012-08-24 06:55:53 +00003728 printf("Error while loading %s: %s\n", filename, strerror(-ret));
thsb12b6a12007-06-17 16:38:39 +00003729 _exit(1);
3730 }
3731
3732 for (wrk = target_environ; *wrk; wrk++) {
3733 free(*wrk);
bellard31e31b82003-02-18 22:55:36 +00003734 }
ths3b46e622007-09-17 08:09:54 +00003735
thsb12b6a12007-06-17 16:38:39 +00003736 free(target_environ);
3737
blueswir12e77eac2009-01-20 16:57:34 +00003738 if (qemu_log_enabled()) {
Paul Brook379f6692009-07-17 12:48:08 +01003739#if defined(CONFIG_USE_GUEST_BASE)
3740 qemu_log("guest_base 0x%lx\n", guest_base);
3741#endif
blueswir12e77eac2009-01-20 16:57:34 +00003742 log_page_dump();
ths3b46e622007-09-17 08:09:54 +00003743
blueswir12e77eac2009-01-20 16:57:34 +00003744 qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk);
3745 qemu_log("end_code 0x" TARGET_ABI_FMT_lx "\n", info->end_code);
3746 qemu_log("start_code 0x" TARGET_ABI_FMT_lx "\n",
3747 info->start_code);
3748 qemu_log("start_data 0x" TARGET_ABI_FMT_lx "\n",
3749 info->start_data);
3750 qemu_log("end_data 0x" TARGET_ABI_FMT_lx "\n", info->end_data);
3751 qemu_log("start_stack 0x" TARGET_ABI_FMT_lx "\n",
3752 info->start_stack);
3753 qemu_log("brk 0x" TARGET_ABI_FMT_lx "\n", info->brk);
3754 qemu_log("entry 0x" TARGET_ABI_FMT_lx "\n", info->entry);
3755 }
bellard31e31b82003-02-18 22:55:36 +00003756
pbrook53a59602006-03-25 19:31:22 +00003757 target_set_brk(info->brk);
bellard31e31b82003-02-18 22:55:36 +00003758 syscall_init();
bellard66fb9762003-03-23 01:06:05 +00003759 signal_init();
bellard31e31b82003-02-18 22:55:36 +00003760
Richard Henderson9002ec72010-05-06 08:50:41 -07003761#if defined(CONFIG_USE_GUEST_BASE)
3762 /* Now that we've loaded the binary, GUEST_BASE is fixed. Delay
3763 generating the prologue until now so that the prologue can take
3764 the real value of GUEST_BASE into account. */
3765 tcg_prologue_init(&tcg_ctx);
3766#endif
3767
bellardb346ff42003-06-15 20:05:50 +00003768#if defined(TARGET_I386)
bellard2e255c62003-08-21 23:25:21 +00003769 cpu_x86_set_cpl(env, 3);
3770
bellard3802ce22003-07-26 18:02:28 +00003771 env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
bellard1bde4652005-01-12 22:34:47 +00003772 env->hflags |= HF_PE_MASK;
Eduardo Habkost0514ef22013-04-22 16:00:15 -03003773 if (env->features[FEAT_1_EDX] & CPUID_SSE) {
bellard1bde4652005-01-12 22:34:47 +00003774 env->cr[4] |= CR4_OSFXSR_MASK;
3775 env->hflags |= HF_OSFXSR_MASK;
3776 }
bellardd2fd1af2007-11-14 18:08:56 +00003777#ifndef TARGET_ABI32
bellard4dbc4222007-11-15 15:27:03 +00003778 /* enable 64 bit mode if possible */
Eduardo Habkost0514ef22013-04-22 16:00:15 -03003779 if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM)) {
bellard4dbc4222007-11-15 15:27:03 +00003780 fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n");
3781 exit(1);
3782 }
bellardd2fd1af2007-11-14 18:08:56 +00003783 env->cr[4] |= CR4_PAE_MASK;
bellard4dbc4222007-11-15 15:27:03 +00003784 env->efer |= MSR_EFER_LMA | MSR_EFER_LME;
bellardd2fd1af2007-11-14 18:08:56 +00003785 env->hflags |= HF_LMA_MASK;
3786#endif
bellard1bde4652005-01-12 22:34:47 +00003787
bellard415e5612004-02-03 23:37:12 +00003788 /* flags setup : we activate the IRQs by default as in user mode */
3789 env->eflags |= IF_MASK;
ths3b46e622007-09-17 08:09:54 +00003790
bellard6dbad632003-03-16 18:05:05 +00003791 /* linux register setup */
bellardd2fd1af2007-11-14 18:08:56 +00003792#ifndef TARGET_ABI32
j_mayer84409dd2007-04-06 08:56:50 +00003793 env->regs[R_EAX] = regs->rax;
3794 env->regs[R_EBX] = regs->rbx;
3795 env->regs[R_ECX] = regs->rcx;
3796 env->regs[R_EDX] = regs->rdx;
3797 env->regs[R_ESI] = regs->rsi;
3798 env->regs[R_EDI] = regs->rdi;
3799 env->regs[R_EBP] = regs->rbp;
3800 env->regs[R_ESP] = regs->rsp;
3801 env->eip = regs->rip;
3802#else
bellard0ecfa992003-03-03 14:32:43 +00003803 env->regs[R_EAX] = regs->eax;
3804 env->regs[R_EBX] = regs->ebx;
3805 env->regs[R_ECX] = regs->ecx;
3806 env->regs[R_EDX] = regs->edx;
3807 env->regs[R_ESI] = regs->esi;
3808 env->regs[R_EDI] = regs->edi;
3809 env->regs[R_EBP] = regs->ebp;
3810 env->regs[R_ESP] = regs->esp;
bellarddab2ed92003-03-22 15:23:14 +00003811 env->eip = regs->eip;
j_mayer84409dd2007-04-06 08:56:50 +00003812#endif
bellard31e31b82003-02-18 22:55:36 +00003813
bellardf4beb512003-05-27 23:28:08 +00003814 /* linux interrupt setup */
balroge4415702008-11-10 02:55:33 +00003815#ifndef TARGET_ABI32
3816 env->idt.limit = 511;
3817#else
3818 env->idt.limit = 255;
3819#endif
3820 env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1),
3821 PROT_READ|PROT_WRITE,
3822 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
3823 idt_table = g2h(env->idt.base);
bellardf4beb512003-05-27 23:28:08 +00003824 set_idt(0, 0);
3825 set_idt(1, 0);
3826 set_idt(2, 0);
3827 set_idt(3, 3);
3828 set_idt(4, 3);
bellardec95da62008-05-12 12:23:31 +00003829 set_idt(5, 0);
bellardf4beb512003-05-27 23:28:08 +00003830 set_idt(6, 0);
3831 set_idt(7, 0);
3832 set_idt(8, 0);
3833 set_idt(9, 0);
3834 set_idt(10, 0);
3835 set_idt(11, 0);
3836 set_idt(12, 0);
3837 set_idt(13, 0);
3838 set_idt(14, 0);
3839 set_idt(15, 0);
3840 set_idt(16, 0);
3841 set_idt(17, 0);
3842 set_idt(18, 0);
3843 set_idt(19, 0);
3844 set_idt(0x80, 3);
3845
bellard6dbad632003-03-16 18:05:05 +00003846 /* linux segment setup */
bellard8d18e892007-11-14 15:18:40 +00003847 {
3848 uint64_t *gdt_table;
balroge4415702008-11-10 02:55:33 +00003849 env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES,
3850 PROT_READ|PROT_WRITE,
3851 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
bellard8d18e892007-11-14 15:18:40 +00003852 env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1;
balroge4415702008-11-10 02:55:33 +00003853 gdt_table = g2h(env->gdt.base);
bellardd2fd1af2007-11-14 18:08:56 +00003854#ifdef TARGET_ABI32
bellard8d18e892007-11-14 15:18:40 +00003855 write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
3856 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
3857 (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
bellardd2fd1af2007-11-14 18:08:56 +00003858#else
3859 /* 64 bit code segment */
3860 write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
3861 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
3862 DESC_L_MASK |
3863 (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
3864#endif
bellard8d18e892007-11-14 15:18:40 +00003865 write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
3866 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
3867 (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
3868 }
bellard6dbad632003-03-16 18:05:05 +00003869 cpu_x86_load_seg(env, R_CS, __USER_CS);
bellardd2fd1af2007-11-14 18:08:56 +00003870 cpu_x86_load_seg(env, R_SS, __USER_DS);
3871#ifdef TARGET_ABI32
bellard6dbad632003-03-16 18:05:05 +00003872 cpu_x86_load_seg(env, R_DS, __USER_DS);
3873 cpu_x86_load_seg(env, R_ES, __USER_DS);
bellard6dbad632003-03-16 18:05:05 +00003874 cpu_x86_load_seg(env, R_FS, __USER_DS);
3875 cpu_x86_load_seg(env, R_GS, __USER_DS);
thsd6eb40f2007-06-21 22:55:02 +00003876 /* This hack makes Wine work... */
3877 env->segs[R_FS].selector = 0;
bellardd2fd1af2007-11-14 18:08:56 +00003878#else
3879 cpu_x86_load_seg(env, R_DS, 0);
3880 cpu_x86_load_seg(env, R_ES, 0);
3881 cpu_x86_load_seg(env, R_FS, 0);
3882 cpu_x86_load_seg(env, R_GS, 0);
3883#endif
bellardb346ff42003-06-15 20:05:50 +00003884#elif defined(TARGET_ARM)
3885 {
3886 int i;
bellardb5ff1b32005-11-26 10:38:39 +00003887 cpsr_write(env, regs->uregs[16], 0xffffffff);
bellardb346ff42003-06-15 20:05:50 +00003888 for(i = 0; i < 16; i++) {
3889 env->regs[i] = regs->uregs[i];
3890 }
Paul Brookd8fd2952012-03-30 18:02:50 +01003891 /* Enable BE8. */
3892 if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4
3893 && (info->elf_flags & EF_ARM_BE8)) {
3894 env->bswap_code = 1;
3895 }
bellardb346ff42003-06-15 20:05:50 +00003896 }
Guan Xuetaod2fbca92011-04-12 16:27:03 +08003897#elif defined(TARGET_UNICORE32)
3898 {
3899 int i;
3900 cpu_asr_write(env, regs->uregs[32], 0xffffffff);
3901 for (i = 0; i < 32; i++) {
3902 env->regs[i] = regs->uregs[i];
3903 }
3904 }
bellard93ac68b2003-09-30 20:57:29 +00003905#elif defined(TARGET_SPARC)
bellard060366c2004-01-04 15:50:01 +00003906 {
3907 int i;
3908 env->pc = regs->pc;
3909 env->npc = regs->npc;
3910 env->y = regs->y;
3911 for(i = 0; i < 8; i++)
3912 env->gregs[i] = regs->u_regs[i];
3913 for(i = 0; i < 8; i++)
3914 env->regwptr[i] = regs->u_regs[i + 8];
3915 }
bellard67867302003-11-23 17:05:30 +00003916#elif defined(TARGET_PPC)
3917 {
3918 int i;
bellard3fc6c082005-07-02 20:59:34 +00003919
j_mayer0411a972007-10-25 21:35:50 +00003920#if defined(TARGET_PPC64)
3921#if defined(TARGET_ABI32)
3922 env->msr &= ~((target_ulong)1 << MSR_SF);
j_mayere85e7c62007-10-18 19:59:49 +00003923#else
j_mayer0411a972007-10-25 21:35:50 +00003924 env->msr |= (target_ulong)1 << MSR_SF;
3925#endif
j_mayer84409dd2007-04-06 08:56:50 +00003926#endif
bellard67867302003-11-23 17:05:30 +00003927 env->nip = regs->nip;
3928 for(i = 0; i < 32; i++) {
3929 env->gpr[i] = regs->gpr[i];
3930 }
3931 }
pbrooke6e59062006-10-22 00:18:54 +00003932#elif defined(TARGET_M68K)
3933 {
pbrooke6e59062006-10-22 00:18:54 +00003934 env->pc = regs->pc;
3935 env->dregs[0] = regs->d0;
3936 env->dregs[1] = regs->d1;
3937 env->dregs[2] = regs->d2;
3938 env->dregs[3] = regs->d3;
3939 env->dregs[4] = regs->d4;
3940 env->dregs[5] = regs->d5;
3941 env->dregs[6] = regs->d6;
3942 env->dregs[7] = regs->d7;
3943 env->aregs[0] = regs->a0;
3944 env->aregs[1] = regs->a1;
3945 env->aregs[2] = regs->a2;
3946 env->aregs[3] = regs->a3;
3947 env->aregs[4] = regs->a4;
3948 env->aregs[5] = regs->a5;
3949 env->aregs[6] = regs->a6;
3950 env->aregs[7] = regs->usp;
3951 env->sr = regs->sr;
3952 ts->sim_syscalls = 1;
3953 }
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +02003954#elif defined(TARGET_MICROBLAZE)
3955 {
3956 env->regs[0] = regs->r0;
3957 env->regs[1] = regs->r1;
3958 env->regs[2] = regs->r2;
3959 env->regs[3] = regs->r3;
3960 env->regs[4] = regs->r4;
3961 env->regs[5] = regs->r5;
3962 env->regs[6] = regs->r6;
3963 env->regs[7] = regs->r7;
3964 env->regs[8] = regs->r8;
3965 env->regs[9] = regs->r9;
3966 env->regs[10] = regs->r10;
3967 env->regs[11] = regs->r11;
3968 env->regs[12] = regs->r12;
3969 env->regs[13] = regs->r13;
3970 env->regs[14] = regs->r14;
3971 env->regs[15] = regs->r15;
3972 env->regs[16] = regs->r16;
3973 env->regs[17] = regs->r17;
3974 env->regs[18] = regs->r18;
3975 env->regs[19] = regs->r19;
3976 env->regs[20] = regs->r20;
3977 env->regs[21] = regs->r21;
3978 env->regs[22] = regs->r22;
3979 env->regs[23] = regs->r23;
3980 env->regs[24] = regs->r24;
3981 env->regs[25] = regs->r25;
3982 env->regs[26] = regs->r26;
3983 env->regs[27] = regs->r27;
3984 env->regs[28] = regs->r28;
3985 env->regs[29] = regs->r29;
3986 env->regs[30] = regs->r30;
3987 env->regs[31] = regs->r31;
3988 env->sregs[SR_PC] = regs->pc;
3989 }
bellard048f6b42005-11-26 18:47:20 +00003990#elif defined(TARGET_MIPS)
3991 {
3992 int i;
3993
3994 for(i = 0; i < 32; i++) {
thsb5dc7732008-06-27 10:02:35 +00003995 env->active_tc.gpr[i] = regs->regs[i];
bellard048f6b42005-11-26 18:47:20 +00003996 }
Nathan Froyd0fddbbf2010-06-08 13:30:02 -07003997 env->active_tc.PC = regs->cp0_epc & ~(target_ulong)1;
3998 if (regs->cp0_epc & 1) {
3999 env->hflags |= MIPS_HFLAG_M16;
4000 }
bellard048f6b42005-11-26 18:47:20 +00004001 }
Jia Liud9627832012-07-20 15:50:52 +08004002#elif defined(TARGET_OPENRISC)
4003 {
4004 int i;
4005
4006 for (i = 0; i < 32; i++) {
4007 env->gpr[i] = regs->gpr[i];
4008 }
4009
4010 env->sr = regs->sr;
4011 env->pc = regs->pc;
4012 }
bellardfdf9b3e2006-04-27 21:07:38 +00004013#elif defined(TARGET_SH4)
4014 {
4015 int i;
4016
4017 for(i = 0; i < 16; i++) {
4018 env->gregs[i] = regs->regs[i];
4019 }
4020 env->pc = regs->pc;
4021 }
j_mayer7a3148a2007-04-05 07:13:51 +00004022#elif defined(TARGET_ALPHA)
4023 {
4024 int i;
4025
4026 for(i = 0; i < 28; i++) {
blueswir1992f48a2007-10-14 16:27:31 +00004027 env->ir[i] = ((abi_ulong *)regs)[i];
j_mayer7a3148a2007-04-05 07:13:51 +00004028 }
Richard Hendersondad081e2010-01-04 11:19:14 -08004029 env->ir[IR_SP] = regs->usp;
j_mayer7a3148a2007-04-05 07:13:51 +00004030 env->pc = regs->pc;
j_mayer7a3148a2007-04-05 07:13:51 +00004031 }
ths48733d12007-10-08 13:36:46 +00004032#elif defined(TARGET_CRIS)
4033 {
4034 env->regs[0] = regs->r0;
4035 env->regs[1] = regs->r1;
4036 env->regs[2] = regs->r2;
4037 env->regs[3] = regs->r3;
4038 env->regs[4] = regs->r4;
4039 env->regs[5] = regs->r5;
4040 env->regs[6] = regs->r6;
4041 env->regs[7] = regs->r7;
4042 env->regs[8] = regs->r8;
4043 env->regs[9] = regs->r9;
4044 env->regs[10] = regs->r10;
4045 env->regs[11] = regs->r11;
4046 env->regs[12] = regs->r12;
4047 env->regs[13] = regs->r13;
4048 env->regs[14] = info->start_stack;
4049 env->regs[15] = regs->acr;
4050 env->pc = regs->erp;
4051 }
Ulrich Hechta4c075f2009-07-24 16:57:31 +02004052#elif defined(TARGET_S390X)
4053 {
4054 int i;
4055 for (i = 0; i < 16; i++) {
4056 env->regs[i] = regs->gprs[i];
4057 }
4058 env->psw.mask = regs->psw.mask;
4059 env->psw.addr = regs->psw.addr;
4060 }
bellardb346ff42003-06-15 20:05:50 +00004061#else
4062#error unsupported target CPU
4063#endif
bellard31e31b82003-02-18 22:55:36 +00004064
Guan Xuetaod2fbca92011-04-12 16:27:03 +08004065#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)
pbrooka87295e2007-05-26 15:09:38 +00004066 ts->stack_base = info->start_stack;
4067 ts->heap_base = info->brk;
4068 /* This will be filled in on the first SYS_HEAPINFO call. */
4069 ts->heap_limit = 0;
4070#endif
4071
bellard74c33be2005-10-30 21:01:05 +00004072 if (gdbstub_port) {
Peter Maydellff7a9812011-09-06 14:15:50 +01004073 if (gdbserver_start(gdbstub_port) < 0) {
4074 fprintf(stderr, "qemu: could not open gdbserver on port %d\n",
4075 gdbstub_port);
4076 exit(1);
4077 }
bellard1fddef42005-04-17 19:16:13 +00004078 gdb_handlesig(env, 0);
4079 }
bellard1b6b0292003-03-22 17:31:38 +00004080 cpu_loop(env);
4081 /* never exits */
bellard31e31b82003-02-18 22:55:36 +00004082 return 0;
4083}