]> git.proxmox.com Git - mirror_qemu.git/blame - linux-user/main.c
linux-user: fake /proc/self/auxv
[mirror_qemu.git] / linux-user / main.c
CommitLineData
31e31b8a 1/*
93ac68bc 2 * qemu user main
5fafdf24 3 *
68d0f70e 4 * Copyright (c) 2003-2008 Fabrice Bellard
31e31b8a
FB
5 *
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
8167ee88 17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
31e31b8a
FB
18 */
19#include <stdlib.h>
20#include <stdio.h>
21#include <stdarg.h>
04369ff2 22#include <string.h>
31e31b8a 23#include <errno.h>
0ecfa993 24#include <unistd.h>
e441570f 25#include <sys/mman.h>
edf8e2af 26#include <sys/syscall.h>
703e0e89 27#include <sys/resource.h>
31e31b8a 28
3ef693a0 29#include "qemu.h"
ca10f867 30#include "qemu-common.h"
902b3d5c 31#include "cache-utils.h"
2b41f10e 32#include "cpu.h"
9002ec79 33#include "tcg.h"
29e922b6 34#include "qemu-timer.h"
04a6dfeb
AJ
35#include "envlist.h"
36
3ef693a0 37#define DEBUG_LOGFILE "/tmp/qemu.log"
586314f2 38
d088d664
AJ
39char *exec_path;
40
1b530a6d 41int singlestep;
fc9c5412
JS
42const char *filename;
43const char *argv0;
44int gdbstub_port;
45envlist_t *envlist;
46const char *cpu_model;
379f6698 47unsigned long mmap_min_addr;
14f24e14 48#if defined(CONFIG_USE_GUEST_BASE)
379f6698
PB
49unsigned long guest_base;
50int have_guest_base;
68a1c816 51unsigned long reserved_va;
379f6698 52#endif
1b530a6d 53
fc9c5412
JS
54static void usage(void);
55
7ee2822c 56static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
c5937220 57const char *qemu_uname_release = CONFIG_UNAME_RELEASE;
586314f2 58
9de5e440
FB
59/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
60 we allocate a bigger stack. Need a better solution, for example
61 by remapping the process stack directly at the right place */
703e0e89 62unsigned long guest_stack_size = 8 * 1024 * 1024UL;
31e31b8a
FB
63
64void gemu_log(const char *fmt, ...)
65{
66 va_list ap;
67
68 va_start(ap, fmt);
69 vfprintf(stderr, fmt, ap);
70 va_end(ap);
71}
72
8fcd3692 73#if defined(TARGET_I386)
a541f297 74int cpu_get_pic_interrupt(CPUState *env)
92ccca6a
FB
75{
76 return -1;
77}
8fcd3692 78#endif
92ccca6a 79
28ab0e2e
FB
80/* timers for rdtsc */
81
1dce7c3c 82#if 0
28ab0e2e
FB
83
84static uint64_t emu_time;
85
86int64_t cpu_get_real_ticks(void)
87{
88 return emu_time++;
89}
90
91#endif
92
2f7bb878 93#if defined(CONFIG_USE_NPTL)
d5975363
PB
94/***********************************************************/
95/* Helper routines for implementing atomic operations. */
96
97/* To implement exclusive operations we force all cpus to syncronise.
98 We don't require a full sync, only that no cpus are executing guest code.
99 The alternative is to map target atomic ops onto host equivalents,
100 which requires quite a lot of per host/target work. */
c2764719 101static pthread_mutex_t cpu_list_mutex = PTHREAD_MUTEX_INITIALIZER;
d5975363
PB
102static pthread_mutex_t exclusive_lock = PTHREAD_MUTEX_INITIALIZER;
103static pthread_cond_t exclusive_cond = PTHREAD_COND_INITIALIZER;
104static pthread_cond_t exclusive_resume = PTHREAD_COND_INITIALIZER;
105static int pending_cpus;
106
107/* Make sure everything is in a consistent state for calling fork(). */
108void fork_start(void)
109{
d5975363
PB
110 pthread_mutex_lock(&tb_lock);
111 pthread_mutex_lock(&exclusive_lock);
d032d1b4 112 mmap_fork_start();
d5975363
PB
113}
114
115void fork_end(int child)
116{
d032d1b4 117 mmap_fork_end(child);
d5975363
PB
118 if (child) {
119 /* Child processes created by fork() only have a single thread.
120 Discard information about the parent threads. */
121 first_cpu = thread_env;
122 thread_env->next_cpu = NULL;
123 pending_cpus = 0;
124 pthread_mutex_init(&exclusive_lock, NULL);
c2764719 125 pthread_mutex_init(&cpu_list_mutex, NULL);
d5975363
PB
126 pthread_cond_init(&exclusive_cond, NULL);
127 pthread_cond_init(&exclusive_resume, NULL);
128 pthread_mutex_init(&tb_lock, NULL);
2b1319c8 129 gdbserver_fork(thread_env);
d5975363
PB
130 } else {
131 pthread_mutex_unlock(&exclusive_lock);
132 pthread_mutex_unlock(&tb_lock);
133 }
d5975363
PB
134}
135
136/* Wait for pending exclusive operations to complete. The exclusive lock
137 must be held. */
138static inline void exclusive_idle(void)
139{
140 while (pending_cpus) {
141 pthread_cond_wait(&exclusive_resume, &exclusive_lock);
142 }
143}
144
145/* Start an exclusive operation.
146 Must only be called from outside cpu_arm_exec. */
147static inline void start_exclusive(void)
148{
149 CPUState *other;
150 pthread_mutex_lock(&exclusive_lock);
151 exclusive_idle();
152
153 pending_cpus = 1;
154 /* Make all other cpus stop executing. */
155 for (other = first_cpu; other; other = other->next_cpu) {
156 if (other->running) {
157 pending_cpus++;
3098dba0 158 cpu_exit(other);
d5975363
PB
159 }
160 }
161 if (pending_cpus > 1) {
162 pthread_cond_wait(&exclusive_cond, &exclusive_lock);
163 }
164}
165
166/* Finish an exclusive operation. */
167static inline void end_exclusive(void)
168{
169 pending_cpus = 0;
170 pthread_cond_broadcast(&exclusive_resume);
171 pthread_mutex_unlock(&exclusive_lock);
172}
173
174/* Wait for exclusive ops to finish, and begin cpu execution. */
175static inline void cpu_exec_start(CPUState *env)
176{
177 pthread_mutex_lock(&exclusive_lock);
178 exclusive_idle();
179 env->running = 1;
180 pthread_mutex_unlock(&exclusive_lock);
181}
182
183/* Mark cpu as not executing, and release pending exclusive ops. */
184static inline void cpu_exec_end(CPUState *env)
185{
186 pthread_mutex_lock(&exclusive_lock);
187 env->running = 0;
188 if (pending_cpus > 1) {
189 pending_cpus--;
190 if (pending_cpus == 1) {
191 pthread_cond_signal(&exclusive_cond);
192 }
193 }
194 exclusive_idle();
195 pthread_mutex_unlock(&exclusive_lock);
196}
c2764719
PB
197
198void cpu_list_lock(void)
199{
200 pthread_mutex_lock(&cpu_list_mutex);
201}
202
203void cpu_list_unlock(void)
204{
205 pthread_mutex_unlock(&cpu_list_mutex);
206}
2f7bb878 207#else /* if !CONFIG_USE_NPTL */
d5975363
PB
208/* These are no-ops because we are not threadsafe. */
209static inline void cpu_exec_start(CPUState *env)
210{
211}
212
213static inline void cpu_exec_end(CPUState *env)
214{
215}
216
217static inline void start_exclusive(void)
218{
219}
220
221static inline void end_exclusive(void)
222{
223}
224
225void fork_start(void)
226{
227}
228
229void fork_end(int child)
230{
2b1319c8
AJ
231 if (child) {
232 gdbserver_fork(thread_env);
233 }
d5975363 234}
c2764719
PB
235
236void cpu_list_lock(void)
237{
238}
239
240void cpu_list_unlock(void)
241{
242}
d5975363
PB
243#endif
244
245
a541f297
FB
246#ifdef TARGET_I386
247/***********************************************************/
248/* CPUX86 core interface */
249
02a1602e
FB
250void cpu_smm_update(CPUState *env)
251{
252}
253
28ab0e2e
FB
254uint64_t cpu_get_tsc(CPUX86State *env)
255{
256 return cpu_get_real_ticks();
257}
258
5fafdf24 259static void write_dt(void *ptr, unsigned long addr, unsigned long limit,
f4beb510 260 int flags)
6dbad63e 261{
f4beb510 262 unsigned int e1, e2;
53a5960a 263 uint32_t *p;
6dbad63e
FB
264 e1 = (addr << 16) | (limit & 0xffff);
265 e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
f4beb510 266 e2 |= flags;
53a5960a 267 p = ptr;
d538e8f5 268 p[0] = tswap32(e1);
269 p[1] = tswap32(e2);
f4beb510
FB
270}
271
e441570f 272static uint64_t *idt_table;
eb38c52c 273#ifdef TARGET_X86_64
d2fd1af7
FB
274static void set_gate64(void *ptr, unsigned int type, unsigned int dpl,
275 uint64_t addr, unsigned int sel)
f4beb510 276{
4dbc422b 277 uint32_t *p, e1, e2;
f4beb510
FB
278 e1 = (addr & 0xffff) | (sel << 16);
279 e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
53a5960a 280 p = ptr;
4dbc422b
FB
281 p[0] = tswap32(e1);
282 p[1] = tswap32(e2);
283 p[2] = tswap32(addr >> 32);
284 p[3] = 0;
6dbad63e 285}
d2fd1af7
FB
286/* only dpl matters as we do only user space emulation */
287static void set_idt(int n, unsigned int dpl)
288{
289 set_gate64(idt_table + n * 2, 0, dpl, 0, 0);
290}
291#else
d2fd1af7
FB
292static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
293 uint32_t addr, unsigned int sel)
294{
4dbc422b 295 uint32_t *p, e1, e2;
d2fd1af7
FB
296 e1 = (addr & 0xffff) | (sel << 16);
297 e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
298 p = ptr;
4dbc422b
FB
299 p[0] = tswap32(e1);
300 p[1] = tswap32(e2);
d2fd1af7
FB
301}
302
f4beb510
FB
303/* only dpl matters as we do only user space emulation */
304static void set_idt(int n, unsigned int dpl)
305{
306 set_gate(idt_table + n, 0, dpl, 0, 0);
307}
d2fd1af7 308#endif
31e31b8a 309
89e957e7 310void cpu_loop(CPUX86State *env)
1b6b029e 311{
bc8a22cc 312 int trapnr;
992f48a0 313 abi_ulong pc;
c227f099 314 target_siginfo_t info;
851e67a1 315
1b6b029e 316 for(;;) {
bc8a22cc 317 trapnr = cpu_x86_exec(env);
bc8a22cc 318 switch(trapnr) {
f4beb510 319 case 0x80:
d2fd1af7 320 /* linux syscall from int $0x80 */
5fafdf24
TS
321 env->regs[R_EAX] = do_syscall(env,
322 env->regs[R_EAX],
f4beb510
FB
323 env->regs[R_EBX],
324 env->regs[R_ECX],
325 env->regs[R_EDX],
326 env->regs[R_ESI],
327 env->regs[R_EDI],
5945cfcb
PM
328 env->regs[R_EBP],
329 0, 0);
f4beb510 330 break;
d2fd1af7
FB
331#ifndef TARGET_ABI32
332 case EXCP_SYSCALL:
5ba18547 333 /* linux syscall from syscall instruction */
d2fd1af7
FB
334 env->regs[R_EAX] = do_syscall(env,
335 env->regs[R_EAX],
336 env->regs[R_EDI],
337 env->regs[R_ESI],
338 env->regs[R_EDX],
339 env->regs[10],
340 env->regs[8],
5945cfcb
PM
341 env->regs[9],
342 0, 0);
d2fd1af7
FB
343 env->eip = env->exception_next_eip;
344 break;
345#endif
f4beb510
FB
346 case EXCP0B_NOSEG:
347 case EXCP0C_STACK:
348 info.si_signo = SIGBUS;
349 info.si_errno = 0;
350 info.si_code = TARGET_SI_KERNEL;
351 info._sifields._sigfault._addr = 0;
624f7979 352 queue_signal(env, info.si_signo, &info);
f4beb510 353 break;
1b6b029e 354 case EXCP0D_GPF:
d2fd1af7 355 /* XXX: potential problem if ABI32 */
84409ddb 356#ifndef TARGET_X86_64
851e67a1 357 if (env->eflags & VM_MASK) {
89e957e7 358 handle_vm86_fault(env);
84409ddb
JM
359 } else
360#endif
361 {
f4beb510
FB
362 info.si_signo = SIGSEGV;
363 info.si_errno = 0;
364 info.si_code = TARGET_SI_KERNEL;
365 info._sifields._sigfault._addr = 0;
624f7979 366 queue_signal(env, info.si_signo, &info);
1b6b029e
FB
367 }
368 break;
b689bc57
FB
369 case EXCP0E_PAGE:
370 info.si_signo = SIGSEGV;
371 info.si_errno = 0;
372 if (!(env->error_code & 1))
373 info.si_code = TARGET_SEGV_MAPERR;
374 else
375 info.si_code = TARGET_SEGV_ACCERR;
970a87a6 376 info._sifields._sigfault._addr = env->cr[2];
624f7979 377 queue_signal(env, info.si_signo, &info);
b689bc57 378 break;
9de5e440 379 case EXCP00_DIVZ:
84409ddb 380#ifndef TARGET_X86_64
bc8a22cc 381 if (env->eflags & VM_MASK) {
447db213 382 handle_vm86_trap(env, trapnr);
84409ddb
JM
383 } else
384#endif
385 {
bc8a22cc
FB
386 /* division by zero */
387 info.si_signo = SIGFPE;
388 info.si_errno = 0;
389 info.si_code = TARGET_FPE_INTDIV;
390 info._sifields._sigfault._addr = env->eip;
624f7979 391 queue_signal(env, info.si_signo, &info);
bc8a22cc 392 }
9de5e440 393 break;
01df040b 394 case EXCP01_DB:
447db213 395 case EXCP03_INT3:
84409ddb 396#ifndef TARGET_X86_64
447db213
FB
397 if (env->eflags & VM_MASK) {
398 handle_vm86_trap(env, trapnr);
84409ddb
JM
399 } else
400#endif
401 {
447db213
FB
402 info.si_signo = SIGTRAP;
403 info.si_errno = 0;
01df040b 404 if (trapnr == EXCP01_DB) {
447db213
FB
405 info.si_code = TARGET_TRAP_BRKPT;
406 info._sifields._sigfault._addr = env->eip;
407 } else {
408 info.si_code = TARGET_SI_KERNEL;
409 info._sifields._sigfault._addr = 0;
410 }
624f7979 411 queue_signal(env, info.si_signo, &info);
447db213
FB
412 }
413 break;
9de5e440
FB
414 case EXCP04_INTO:
415 case EXCP05_BOUND:
84409ddb 416#ifndef TARGET_X86_64
bc8a22cc 417 if (env->eflags & VM_MASK) {
447db213 418 handle_vm86_trap(env, trapnr);
84409ddb
JM
419 } else
420#endif
421 {
bc8a22cc
FB
422 info.si_signo = SIGSEGV;
423 info.si_errno = 0;
b689bc57 424 info.si_code = TARGET_SI_KERNEL;
bc8a22cc 425 info._sifields._sigfault._addr = 0;
624f7979 426 queue_signal(env, info.si_signo, &info);
bc8a22cc 427 }
9de5e440
FB
428 break;
429 case EXCP06_ILLOP:
430 info.si_signo = SIGILL;
431 info.si_errno = 0;
432 info.si_code = TARGET_ILL_ILLOPN;
433 info._sifields._sigfault._addr = env->eip;
624f7979 434 queue_signal(env, info.si_signo, &info);
9de5e440
FB
435 break;
436 case EXCP_INTERRUPT:
437 /* just indicate that signals should be handled asap */
438 break;
1fddef4b
FB
439 case EXCP_DEBUG:
440 {
441 int sig;
442
443 sig = gdb_handlesig (env, TARGET_SIGTRAP);
444 if (sig)
445 {
446 info.si_signo = sig;
447 info.si_errno = 0;
448 info.si_code = TARGET_TRAP_BRKPT;
624f7979 449 queue_signal(env, info.si_signo, &info);
1fddef4b
FB
450 }
451 }
452 break;
1b6b029e 453 default:
970a87a6 454 pc = env->segs[R_CS].base + env->eip;
5fafdf24 455 fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
bc8a22cc 456 (long)pc, trapnr);
1b6b029e
FB
457 abort();
458 }
66fb9763 459 process_pending_signals(env);
1b6b029e
FB
460 }
461}
b346ff46
FB
462#endif
463
464#ifdef TARGET_ARM
465
97cc7560
DDAG
466/*
467 * See the Linux kernel's Documentation/arm/kernel_user_helpers.txt
468 * Input:
469 * r0 = pointer to oldval
470 * r1 = pointer to newval
471 * r2 = pointer to target value
472 *
473 * Output:
474 * r0 = 0 if *ptr was changed, non-0 if no exchange happened
475 * C set if *ptr was changed, clear if no exchange happened
476 *
477 * Note segv's in kernel helpers are a bit tricky, we can set the
478 * data address sensibly but the PC address is just the entry point.
479 */
480static void arm_kernel_cmpxchg64_helper(CPUARMState *env)
481{
482 uint64_t oldval, newval, val;
483 uint32_t addr, cpsr;
484 target_siginfo_t info;
485
486 /* Based on the 32 bit code in do_kernel_trap */
487
488 /* XXX: This only works between threads, not between processes.
489 It's probably possible to implement this with native host
490 operations. However things like ldrex/strex are much harder so
491 there's not much point trying. */
492 start_exclusive();
493 cpsr = cpsr_read(env);
494 addr = env->regs[2];
495
496 if (get_user_u64(oldval, env->regs[0])) {
497 env->cp15.c6_data = env->regs[0];
498 goto segv;
499 };
500
501 if (get_user_u64(newval, env->regs[1])) {
502 env->cp15.c6_data = env->regs[1];
503 goto segv;
504 };
505
506 if (get_user_u64(val, addr)) {
507 env->cp15.c6_data = addr;
508 goto segv;
509 }
510
511 if (val == oldval) {
512 val = newval;
513
514 if (put_user_u64(val, addr)) {
515 env->cp15.c6_data = addr;
516 goto segv;
517 };
518
519 env->regs[0] = 0;
520 cpsr |= CPSR_C;
521 } else {
522 env->regs[0] = -1;
523 cpsr &= ~CPSR_C;
524 }
525 cpsr_write(env, cpsr, CPSR_C);
526 end_exclusive();
527 return;
528
529segv:
530 end_exclusive();
531 /* We get the PC of the entry address - which is as good as anything,
532 on a real kernel what you get depends on which mode it uses. */
533 info.si_signo = SIGSEGV;
534 info.si_errno = 0;
535 /* XXX: check env->error_code */
536 info.si_code = TARGET_SEGV_MAPERR;
537 info._sifields._sigfault._addr = env->cp15.c6_data;
538 queue_signal(env, info.si_signo, &info);
539
540 end_exclusive();
541}
542
fbb4a2e3
PB
543/* Handle a jump to the kernel code page. */
544static int
545do_kernel_trap(CPUARMState *env)
546{
547 uint32_t addr;
548 uint32_t cpsr;
549 uint32_t val;
550
551 switch (env->regs[15]) {
552 case 0xffff0fa0: /* __kernel_memory_barrier */
553 /* ??? No-op. Will need to do better for SMP. */
554 break;
555 case 0xffff0fc0: /* __kernel_cmpxchg */
d5975363
PB
556 /* XXX: This only works between threads, not between processes.
557 It's probably possible to implement this with native host
558 operations. However things like ldrex/strex are much harder so
559 there's not much point trying. */
560 start_exclusive();
fbb4a2e3
PB
561 cpsr = cpsr_read(env);
562 addr = env->regs[2];
563 /* FIXME: This should SEGV if the access fails. */
564 if (get_user_u32(val, addr))
565 val = ~env->regs[0];
566 if (val == env->regs[0]) {
567 val = env->regs[1];
568 /* FIXME: Check for segfaults. */
569 put_user_u32(val, addr);
570 env->regs[0] = 0;
571 cpsr |= CPSR_C;
572 } else {
573 env->regs[0] = -1;
574 cpsr &= ~CPSR_C;
575 }
576 cpsr_write(env, cpsr, CPSR_C);
d5975363 577 end_exclusive();
fbb4a2e3
PB
578 break;
579 case 0xffff0fe0: /* __kernel_get_tls */
580 env->regs[0] = env->cp15.c13_tls2;
581 break;
97cc7560
DDAG
582 case 0xffff0f60: /* __kernel_cmpxchg64 */
583 arm_kernel_cmpxchg64_helper(env);
584 break;
585
fbb4a2e3
PB
586 default:
587 return 1;
588 }
589 /* Jump back to the caller. */
590 addr = env->regs[14];
591 if (addr & 1) {
592 env->thumb = 1;
593 addr &= ~1;
594 }
595 env->regs[15] = addr;
596
597 return 0;
598}
599
426f5abc
PB
600static int do_strex(CPUARMState *env)
601{
602 uint32_t val;
603 int size;
604 int rc = 1;
605 int segv = 0;
606 uint32_t addr;
607 start_exclusive();
608 addr = env->exclusive_addr;
609 if (addr != env->exclusive_test) {
610 goto fail;
611 }
612 size = env->exclusive_info & 0xf;
613 switch (size) {
614 case 0:
615 segv = get_user_u8(val, addr);
616 break;
617 case 1:
618 segv = get_user_u16(val, addr);
619 break;
620 case 2:
621 case 3:
622 segv = get_user_u32(val, addr);
623 break;
f7001a3b
AJ
624 default:
625 abort();
426f5abc
PB
626 }
627 if (segv) {
628 env->cp15.c6_data = addr;
629 goto done;
630 }
631 if (val != env->exclusive_val) {
632 goto fail;
633 }
634 if (size == 3) {
635 segv = get_user_u32(val, addr + 4);
636 if (segv) {
637 env->cp15.c6_data = addr + 4;
638 goto done;
639 }
640 if (val != env->exclusive_high) {
641 goto fail;
642 }
643 }
644 val = env->regs[(env->exclusive_info >> 8) & 0xf];
645 switch (size) {
646 case 0:
647 segv = put_user_u8(val, addr);
648 break;
649 case 1:
650 segv = put_user_u16(val, addr);
651 break;
652 case 2:
653 case 3:
654 segv = put_user_u32(val, addr);
655 break;
656 }
657 if (segv) {
658 env->cp15.c6_data = addr;
659 goto done;
660 }
661 if (size == 3) {
662 val = env->regs[(env->exclusive_info >> 12) & 0xf];
2c9adbda 663 segv = put_user_u32(val, addr + 4);
426f5abc
PB
664 if (segv) {
665 env->cp15.c6_data = addr + 4;
666 goto done;
667 }
668 }
669 rc = 0;
670fail:
725b8a69 671 env->regs[15] += 4;
426f5abc
PB
672 env->regs[(env->exclusive_info >> 4) & 0xf] = rc;
673done:
674 end_exclusive();
675 return segv;
676}
677
b346ff46
FB
678void cpu_loop(CPUARMState *env)
679{
680 int trapnr;
681 unsigned int n, insn;
c227f099 682 target_siginfo_t info;
b5ff1b31 683 uint32_t addr;
3b46e624 684
b346ff46 685 for(;;) {
d5975363 686 cpu_exec_start(env);
b346ff46 687 trapnr = cpu_arm_exec(env);
d5975363 688 cpu_exec_end(env);
b346ff46
FB
689 switch(trapnr) {
690 case EXCP_UDEF:
c6981055
FB
691 {
692 TaskState *ts = env->opaque;
693 uint32_t opcode;
6d9a42be 694 int rc;
c6981055
FB
695
696 /* we handle the FPU emulation here, as Linux */
697 /* we get the opcode */
2f619698
FB
698 /* FIXME - what to do if get_user() fails? */
699 get_user_u32(opcode, env->regs[15]);
3b46e624 700
6d9a42be
AJ
701 rc = EmulateAll(opcode, &ts->fpa, env);
702 if (rc == 0) { /* illegal instruction */
c6981055
FB
703 info.si_signo = SIGILL;
704 info.si_errno = 0;
705 info.si_code = TARGET_ILL_ILLOPN;
706 info._sifields._sigfault._addr = env->regs[15];
624f7979 707 queue_signal(env, info.si_signo, &info);
6d9a42be
AJ
708 } else if (rc < 0) { /* FP exception */
709 int arm_fpe=0;
710
711 /* translate softfloat flags to FPSR flags */
712 if (-rc & float_flag_invalid)
713 arm_fpe |= BIT_IOC;
714 if (-rc & float_flag_divbyzero)
715 arm_fpe |= BIT_DZC;
716 if (-rc & float_flag_overflow)
717 arm_fpe |= BIT_OFC;
718 if (-rc & float_flag_underflow)
719 arm_fpe |= BIT_UFC;
720 if (-rc & float_flag_inexact)
721 arm_fpe |= BIT_IXC;
722
723 FPSR fpsr = ts->fpa.fpsr;
724 //printf("fpsr 0x%x, arm_fpe 0x%x\n",fpsr,arm_fpe);
725
726 if (fpsr & (arm_fpe << 16)) { /* exception enabled? */
727 info.si_signo = SIGFPE;
728 info.si_errno = 0;
729
730 /* ordered by priority, least first */
731 if (arm_fpe & BIT_IXC) info.si_code = TARGET_FPE_FLTRES;
732 if (arm_fpe & BIT_UFC) info.si_code = TARGET_FPE_FLTUND;
733 if (arm_fpe & BIT_OFC) info.si_code = TARGET_FPE_FLTOVF;
734 if (arm_fpe & BIT_DZC) info.si_code = TARGET_FPE_FLTDIV;
735 if (arm_fpe & BIT_IOC) info.si_code = TARGET_FPE_FLTINV;
736
737 info._sifields._sigfault._addr = env->regs[15];
624f7979 738 queue_signal(env, info.si_signo, &info);
6d9a42be
AJ
739 } else {
740 env->regs[15] += 4;
741 }
742
743 /* accumulate unenabled exceptions */
744 if ((!(fpsr & BIT_IXE)) && (arm_fpe & BIT_IXC))
745 fpsr |= BIT_IXC;
746 if ((!(fpsr & BIT_UFE)) && (arm_fpe & BIT_UFC))
747 fpsr |= BIT_UFC;
748 if ((!(fpsr & BIT_OFE)) && (arm_fpe & BIT_OFC))
749 fpsr |= BIT_OFC;
750 if ((!(fpsr & BIT_DZE)) && (arm_fpe & BIT_DZC))
751 fpsr |= BIT_DZC;
752 if ((!(fpsr & BIT_IOE)) && (arm_fpe & BIT_IOC))
753 fpsr |= BIT_IOC;
754 ts->fpa.fpsr=fpsr;
755 } else { /* everything OK */
c6981055
FB
756 /* increment PC */
757 env->regs[15] += 4;
758 }
759 }
b346ff46
FB
760 break;
761 case EXCP_SWI:
06c949e6 762 case EXCP_BKPT:
b346ff46 763 {
ce4defa0 764 env->eabi = 1;
b346ff46 765 /* system call */
06c949e6
PB
766 if (trapnr == EXCP_BKPT) {
767 if (env->thumb) {
2f619698
FB
768 /* FIXME - what to do if get_user() fails? */
769 get_user_u16(insn, env->regs[15]);
06c949e6
PB
770 n = insn & 0xff;
771 env->regs[15] += 2;
772 } else {
2f619698
FB
773 /* FIXME - what to do if get_user() fails? */
774 get_user_u32(insn, env->regs[15]);
06c949e6
PB
775 n = (insn & 0xf) | ((insn >> 4) & 0xff0);
776 env->regs[15] += 4;
777 }
192c7bd9 778 } else {
06c949e6 779 if (env->thumb) {
2f619698
FB
780 /* FIXME - what to do if get_user() fails? */
781 get_user_u16(insn, env->regs[15] - 2);
06c949e6
PB
782 n = insn & 0xff;
783 } else {
2f619698
FB
784 /* FIXME - what to do if get_user() fails? */
785 get_user_u32(insn, env->regs[15] - 4);
06c949e6
PB
786 n = insn & 0xffffff;
787 }
192c7bd9
FB
788 }
789
6f1f31c0 790 if (n == ARM_NR_cacheflush) {
dcfd14b3 791 /* nop */
a4f81979
FB
792 } else if (n == ARM_NR_semihosting
793 || n == ARM_NR_thumb_semihosting) {
794 env->regs[0] = do_arm_semihosting (env);
ce4defa0 795 } else if (n == 0 || n >= ARM_SYSCALL_BASE
192c7bd9 796 || (env->thumb && n == ARM_THUMB_SYSCALL)) {
b346ff46 797 /* linux syscall */
ce4defa0 798 if (env->thumb || n == 0) {
192c7bd9
FB
799 n = env->regs[7];
800 } else {
801 n -= ARM_SYSCALL_BASE;
ce4defa0 802 env->eabi = 0;
192c7bd9 803 }
fbb4a2e3
PB
804 if ( n > ARM_NR_BASE) {
805 switch (n) {
806 case ARM_NR_cacheflush:
dcfd14b3 807 /* nop */
fbb4a2e3
PB
808 break;
809 case ARM_NR_set_tls:
810 cpu_set_tls(env, env->regs[0]);
811 env->regs[0] = 0;
812 break;
813 default:
814 gemu_log("qemu: Unsupported ARM syscall: 0x%x\n",
815 n);
816 env->regs[0] = -TARGET_ENOSYS;
817 break;
818 }
819 } else {
820 env->regs[0] = do_syscall(env,
821 n,
822 env->regs[0],
823 env->regs[1],
824 env->regs[2],
825 env->regs[3],
826 env->regs[4],
5945cfcb
PM
827 env->regs[5],
828 0, 0);
fbb4a2e3 829 }
b346ff46
FB
830 } else {
831 goto error;
832 }
833 }
834 break;
43fff238
FB
835 case EXCP_INTERRUPT:
836 /* just indicate that signals should be handled asap */
837 break;
68016c62 838 case EXCP_PREFETCH_ABORT:
eae473c1 839 addr = env->cp15.c6_insn;
b5ff1b31 840 goto do_segv;
68016c62 841 case EXCP_DATA_ABORT:
eae473c1 842 addr = env->cp15.c6_data;
b5ff1b31 843 do_segv:
68016c62
FB
844 {
845 info.si_signo = SIGSEGV;
846 info.si_errno = 0;
847 /* XXX: check env->error_code */
848 info.si_code = TARGET_SEGV_MAPERR;
b5ff1b31 849 info._sifields._sigfault._addr = addr;
624f7979 850 queue_signal(env, info.si_signo, &info);
68016c62
FB
851 }
852 break;
1fddef4b
FB
853 case EXCP_DEBUG:
854 {
855 int sig;
856
857 sig = gdb_handlesig (env, TARGET_SIGTRAP);
858 if (sig)
859 {
860 info.si_signo = sig;
861 info.si_errno = 0;
862 info.si_code = TARGET_TRAP_BRKPT;
624f7979 863 queue_signal(env, info.si_signo, &info);
1fddef4b
FB
864 }
865 }
866 break;
fbb4a2e3
PB
867 case EXCP_KERNEL_TRAP:
868 if (do_kernel_trap(env))
869 goto error;
870 break;
426f5abc
PB
871 case EXCP_STREX:
872 if (do_strex(env)) {
873 addr = env->cp15.c6_data;
874 goto do_segv;
875 }
e9273455 876 break;
b346ff46
FB
877 default:
878 error:
5fafdf24 879 fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
b346ff46 880 trapnr);
7fe48483 881 cpu_dump_state(env, stderr, fprintf, 0);
b346ff46
FB
882 abort();
883 }
884 process_pending_signals(env);
885 }
886}
887
888#endif
1b6b029e 889
d2fbca94
GX
890#ifdef TARGET_UNICORE32
891
892void cpu_loop(CPUState *env)
893{
894 int trapnr;
895 unsigned int n, insn;
896 target_siginfo_t info;
897
898 for (;;) {
899 cpu_exec_start(env);
900 trapnr = uc32_cpu_exec(env);
901 cpu_exec_end(env);
902 switch (trapnr) {
903 case UC32_EXCP_PRIV:
904 {
905 /* system call */
906 get_user_u32(insn, env->regs[31] - 4);
907 n = insn & 0xffffff;
908
909 if (n >= UC32_SYSCALL_BASE) {
910 /* linux syscall */
911 n -= UC32_SYSCALL_BASE;
912 if (n == UC32_SYSCALL_NR_set_tls) {
913 cpu_set_tls(env, env->regs[0]);
914 env->regs[0] = 0;
915 } else {
916 env->regs[0] = do_syscall(env,
917 n,
918 env->regs[0],
919 env->regs[1],
920 env->regs[2],
921 env->regs[3],
922 env->regs[4],
5945cfcb
PM
923 env->regs[5],
924 0, 0);
d2fbca94
GX
925 }
926 } else {
927 goto error;
928 }
929 }
930 break;
931 case UC32_EXCP_TRAP:
932 info.si_signo = SIGSEGV;
933 info.si_errno = 0;
934 /* XXX: check env->error_code */
935 info.si_code = TARGET_SEGV_MAPERR;
936 info._sifields._sigfault._addr = env->cp0.c4_faultaddr;
937 queue_signal(env, info.si_signo, &info);
938 break;
939 case EXCP_INTERRUPT:
940 /* just indicate that signals should be handled asap */
941 break;
942 case EXCP_DEBUG:
943 {
944 int sig;
945
946 sig = gdb_handlesig(env, TARGET_SIGTRAP);
947 if (sig) {
948 info.si_signo = sig;
949 info.si_errno = 0;
950 info.si_code = TARGET_TRAP_BRKPT;
951 queue_signal(env, info.si_signo, &info);
952 }
953 }
954 break;
955 default:
956 goto error;
957 }
958 process_pending_signals(env);
959 }
960
961error:
962 fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr);
963 cpu_dump_state(env, stderr, fprintf, 0);
964 abort();
965}
966#endif
967
93ac68bc 968#ifdef TARGET_SPARC
ed23fbd9 969#define SPARC64_STACK_BIAS 2047
93ac68bc 970
060366c5
FB
971//#define DEBUG_WIN
972
2623cbaf
FB
973/* WARNING: dealing with register windows _is_ complicated. More info
974 can be found at http://www.sics.se/~psm/sparcstack.html */
060366c5
FB
975static inline int get_reg_index(CPUSPARCState *env, int cwp, int index)
976{
1a14026e 977 index = (index + cwp * 16) % (16 * env->nwindows);
060366c5
FB
978 /* wrap handling : if cwp is on the last window, then we use the
979 registers 'after' the end */
1a14026e
BS
980 if (index < 8 && env->cwp == env->nwindows - 1)
981 index += 16 * env->nwindows;
060366c5
FB
982 return index;
983}
984
2623cbaf
FB
985/* save the register window 'cwp1' */
986static inline void save_window_offset(CPUSPARCState *env, int cwp1)
060366c5 987{
2623cbaf 988 unsigned int i;
992f48a0 989 abi_ulong sp_ptr;
3b46e624 990
53a5960a 991 sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
ed23fbd9
BS
992#ifdef TARGET_SPARC64
993 if (sp_ptr & 3)
994 sp_ptr += SPARC64_STACK_BIAS;
995#endif
060366c5 996#if defined(DEBUG_WIN)
2daf0284
BS
997 printf("win_overflow: sp_ptr=0x" TARGET_ABI_FMT_lx " save_cwp=%d\n",
998 sp_ptr, cwp1);
060366c5 999#endif
2623cbaf 1000 for(i = 0; i < 16; i++) {
2f619698
FB
1001 /* FIXME - what to do if put_user() fails? */
1002 put_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
992f48a0 1003 sp_ptr += sizeof(abi_ulong);
2623cbaf 1004 }
060366c5
FB
1005}
1006
1007static void save_window(CPUSPARCState *env)
1008{
5ef54116 1009#ifndef TARGET_SPARC64
2623cbaf 1010 unsigned int new_wim;
1a14026e
BS
1011 new_wim = ((env->wim >> 1) | (env->wim << (env->nwindows - 1))) &
1012 ((1LL << env->nwindows) - 1);
1013 save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
2623cbaf 1014 env->wim = new_wim;
5ef54116 1015#else
1a14026e 1016 save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
5ef54116
FB
1017 env->cansave++;
1018 env->canrestore--;
1019#endif
060366c5
FB
1020}
1021
1022static void restore_window(CPUSPARCState *env)
1023{
eda52953
BS
1024#ifndef TARGET_SPARC64
1025 unsigned int new_wim;
1026#endif
1027 unsigned int i, cwp1;
992f48a0 1028 abi_ulong sp_ptr;
3b46e624 1029
eda52953 1030#ifndef TARGET_SPARC64
1a14026e
BS
1031 new_wim = ((env->wim << 1) | (env->wim >> (env->nwindows - 1))) &
1032 ((1LL << env->nwindows) - 1);
eda52953 1033#endif
3b46e624 1034
060366c5 1035 /* restore the invalid window */
1a14026e 1036 cwp1 = cpu_cwp_inc(env, env->cwp + 1);
53a5960a 1037 sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
ed23fbd9
BS
1038#ifdef TARGET_SPARC64
1039 if (sp_ptr & 3)
1040 sp_ptr += SPARC64_STACK_BIAS;
1041#endif
060366c5 1042#if defined(DEBUG_WIN)
2daf0284
BS
1043 printf("win_underflow: sp_ptr=0x" TARGET_ABI_FMT_lx " load_cwp=%d\n",
1044 sp_ptr, cwp1);
060366c5 1045#endif
2623cbaf 1046 for(i = 0; i < 16; i++) {
2f619698
FB
1047 /* FIXME - what to do if get_user() fails? */
1048 get_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
992f48a0 1049 sp_ptr += sizeof(abi_ulong);
2623cbaf 1050 }
5ef54116
FB
1051#ifdef TARGET_SPARC64
1052 env->canrestore++;
1a14026e
BS
1053 if (env->cleanwin < env->nwindows - 1)
1054 env->cleanwin++;
5ef54116 1055 env->cansave--;
eda52953
BS
1056#else
1057 env->wim = new_wim;
5ef54116 1058#endif
060366c5
FB
1059}
1060
1061static void flush_windows(CPUSPARCState *env)
1062{
1063 int offset, cwp1;
2623cbaf
FB
1064
1065 offset = 1;
060366c5
FB
1066 for(;;) {
1067 /* if restore would invoke restore_window(), then we can stop */
1a14026e 1068 cwp1 = cpu_cwp_inc(env, env->cwp + offset);
eda52953 1069#ifndef TARGET_SPARC64
060366c5
FB
1070 if (env->wim & (1 << cwp1))
1071 break;
eda52953
BS
1072#else
1073 if (env->canrestore == 0)
1074 break;
1075 env->cansave++;
1076 env->canrestore--;
1077#endif
2623cbaf 1078 save_window_offset(env, cwp1);
060366c5
FB
1079 offset++;
1080 }
1a14026e 1081 cwp1 = cpu_cwp_inc(env, env->cwp + 1);
eda52953
BS
1082#ifndef TARGET_SPARC64
1083 /* set wim so that restore will reload the registers */
2623cbaf 1084 env->wim = 1 << cwp1;
eda52953 1085#endif
2623cbaf
FB
1086#if defined(DEBUG_WIN)
1087 printf("flush_windows: nb=%d\n", offset - 1);
80a9d035 1088#endif
2623cbaf 1089}
060366c5 1090
93ac68bc
FB
1091void cpu_loop (CPUSPARCState *env)
1092{
2cc20260
RH
1093 int trapnr;
1094 abi_long ret;
c227f099 1095 target_siginfo_t info;
3b46e624 1096
060366c5
FB
1097 while (1) {
1098 trapnr = cpu_sparc_exec (env);
3b46e624 1099
060366c5 1100 switch (trapnr) {
5ef54116 1101#ifndef TARGET_SPARC64
5fafdf24 1102 case 0x88:
060366c5 1103 case 0x90:
5ef54116 1104#else
cb33da57 1105 case 0x110:
5ef54116
FB
1106 case 0x16d:
1107#endif
060366c5 1108 ret = do_syscall (env, env->gregs[1],
5fafdf24
TS
1109 env->regwptr[0], env->regwptr[1],
1110 env->regwptr[2], env->regwptr[3],
5945cfcb
PM
1111 env->regwptr[4], env->regwptr[5],
1112 0, 0);
2cc20260 1113 if ((abi_ulong)ret >= (abi_ulong)(-515)) {
992f48a0 1114#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
27908725
FB
1115 env->xcc |= PSR_CARRY;
1116#else
060366c5 1117 env->psr |= PSR_CARRY;
27908725 1118#endif
060366c5
FB
1119 ret = -ret;
1120 } else {
992f48a0 1121#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
27908725
FB
1122 env->xcc &= ~PSR_CARRY;
1123#else
060366c5 1124 env->psr &= ~PSR_CARRY;
27908725 1125#endif
060366c5
FB
1126 }
1127 env->regwptr[0] = ret;
1128 /* next instruction */
1129 env->pc = env->npc;
1130 env->npc = env->npc + 4;
1131 break;
1132 case 0x83: /* flush windows */
992f48a0
BS
1133#ifdef TARGET_ABI32
1134 case 0x103:
1135#endif
2623cbaf 1136 flush_windows(env);
060366c5
FB
1137 /* next instruction */
1138 env->pc = env->npc;
1139 env->npc = env->npc + 4;
1140 break;
3475187d 1141#ifndef TARGET_SPARC64
060366c5
FB
1142 case TT_WIN_OVF: /* window overflow */
1143 save_window(env);
1144 break;
1145 case TT_WIN_UNF: /* window underflow */
1146 restore_window(env);
1147 break;
61ff6f58
FB
1148 case TT_TFAULT:
1149 case TT_DFAULT:
1150 {
59f7182f 1151 info.si_signo = TARGET_SIGSEGV;
61ff6f58
FB
1152 info.si_errno = 0;
1153 /* XXX: check env->error_code */
1154 info.si_code = TARGET_SEGV_MAPERR;
1155 info._sifields._sigfault._addr = env->mmuregs[4];
624f7979 1156 queue_signal(env, info.si_signo, &info);
61ff6f58
FB
1157 }
1158 break;
3475187d 1159#else
5ef54116
FB
1160 case TT_SPILL: /* window overflow */
1161 save_window(env);
1162 break;
1163 case TT_FILL: /* window underflow */
1164 restore_window(env);
1165 break;
7f84a729
BS
1166 case TT_TFAULT:
1167 case TT_DFAULT:
1168 {
59f7182f 1169 info.si_signo = TARGET_SIGSEGV;
7f84a729
BS
1170 info.si_errno = 0;
1171 /* XXX: check env->error_code */
1172 info.si_code = TARGET_SEGV_MAPERR;
1173 if (trapnr == TT_DFAULT)
1174 info._sifields._sigfault._addr = env->dmmuregs[4];
1175 else
8194f35a 1176 info._sifields._sigfault._addr = cpu_tsptr(env)->tpc;
624f7979 1177 queue_signal(env, info.si_signo, &info);
7f84a729
BS
1178 }
1179 break;
27524dc3 1180#ifndef TARGET_ABI32
5bfb56b2
BS
1181 case 0x16e:
1182 flush_windows(env);
1183 sparc64_get_context(env);
1184 break;
1185 case 0x16f:
1186 flush_windows(env);
1187 sparc64_set_context(env);
1188 break;
27524dc3 1189#endif
3475187d 1190#endif
48dc41eb
FB
1191 case EXCP_INTERRUPT:
1192 /* just indicate that signals should be handled asap */
1193 break;
75f22e4e
RH
1194 case TT_ILL_INSN:
1195 {
1196 info.si_signo = TARGET_SIGILL;
1197 info.si_errno = 0;
1198 info.si_code = TARGET_ILL_ILLOPC;
1199 info._sifields._sigfault._addr = env->pc;
1200 queue_signal(env, info.si_signo, &info);
1201 }
1202 break;
1fddef4b
FB
1203 case EXCP_DEBUG:
1204 {
1205 int sig;
1206
1207 sig = gdb_handlesig (env, TARGET_SIGTRAP);
1208 if (sig)
1209 {
1210 info.si_signo = sig;
1211 info.si_errno = 0;
1212 info.si_code = TARGET_TRAP_BRKPT;
624f7979 1213 queue_signal(env, info.si_signo, &info);
1fddef4b
FB
1214 }
1215 }
1216 break;
060366c5
FB
1217 default:
1218 printf ("Unhandled trap: 0x%x\n", trapnr);
7fe48483 1219 cpu_dump_state(env, stderr, fprintf, 0);
060366c5
FB
1220 exit (1);
1221 }
1222 process_pending_signals (env);
1223 }
93ac68bc
FB
1224}
1225
1226#endif
1227
67867308 1228#ifdef TARGET_PPC
9fddaa0c
FB
1229static inline uint64_t cpu_ppc_get_tb (CPUState *env)
1230{
1231 /* TO FIX */
1232 return 0;
1233}
3b46e624 1234
e3ea6529 1235uint64_t cpu_ppc_load_tbl (CPUState *env)
9fddaa0c 1236{
e3ea6529 1237 return cpu_ppc_get_tb(env);
9fddaa0c 1238}
3b46e624 1239
9fddaa0c
FB
1240uint32_t cpu_ppc_load_tbu (CPUState *env)
1241{
1242 return cpu_ppc_get_tb(env) >> 32;
1243}
3b46e624 1244
b711de95 1245uint64_t cpu_ppc_load_atbl (CPUState *env)
9fddaa0c 1246{
b711de95 1247 return cpu_ppc_get_tb(env);
9fddaa0c 1248}
5fafdf24 1249
a062e36c 1250uint32_t cpu_ppc_load_atbu (CPUState *env)
9fddaa0c 1251{
a062e36c 1252 return cpu_ppc_get_tb(env) >> 32;
9fddaa0c 1253}
76a66253 1254
76a66253
JM
1255uint32_t cpu_ppc601_load_rtcu (CPUState *env)
1256__attribute__ (( alias ("cpu_ppc_load_tbu") ));
1257
76a66253 1258uint32_t cpu_ppc601_load_rtcl (CPUState *env)
9fddaa0c 1259{
76a66253 1260 return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
9fddaa0c 1261}
76a66253 1262
a750fc0b 1263/* XXX: to be fixed */
73b01960 1264int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp)
a750fc0b
JM
1265{
1266 return -1;
1267}
1268
73b01960 1269int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val)
a750fc0b
JM
1270{
1271 return -1;
1272}
1273
001faf32
BS
1274#define EXCP_DUMP(env, fmt, ...) \
1275do { \
1276 fprintf(stderr, fmt , ## __VA_ARGS__); \
1277 cpu_dump_state(env, stderr, fprintf, 0); \
1278 qemu_log(fmt, ## __VA_ARGS__); \
430c7ec7 1279 if (logfile) \
1280 log_cpu_state(env, 0); \
e1833e1f
JM
1281} while (0)
1282
56f066bb
NF
1283static int do_store_exclusive(CPUPPCState *env)
1284{
1285 target_ulong addr;
1286 target_ulong page_addr;
1287 target_ulong val;
1288 int flags;
1289 int segv = 0;
1290
1291 addr = env->reserve_ea;
1292 page_addr = addr & TARGET_PAGE_MASK;
1293 start_exclusive();
1294 mmap_lock();
1295 flags = page_get_flags(page_addr);
1296 if ((flags & PAGE_READ) == 0) {
1297 segv = 1;
1298 } else {
1299 int reg = env->reserve_info & 0x1f;
1300 int size = (env->reserve_info >> 5) & 0xf;
1301 int stored = 0;
1302
1303 if (addr == env->reserve_addr) {
1304 switch (size) {
1305 case 1: segv = get_user_u8(val, addr); break;
1306 case 2: segv = get_user_u16(val, addr); break;
1307 case 4: segv = get_user_u32(val, addr); break;
1308#if defined(TARGET_PPC64)
1309 case 8: segv = get_user_u64(val, addr); break;
1310#endif
1311 default: abort();
1312 }
1313 if (!segv && val == env->reserve_val) {
1314 val = env->gpr[reg];
1315 switch (size) {
1316 case 1: segv = put_user_u8(val, addr); break;
1317 case 2: segv = put_user_u16(val, addr); break;
1318 case 4: segv = put_user_u32(val, addr); break;
1319#if defined(TARGET_PPC64)
1320 case 8: segv = put_user_u64(val, addr); break;
1321#endif
1322 default: abort();
1323 }
1324 if (!segv) {
1325 stored = 1;
1326 }
1327 }
1328 }
1329 env->crf[0] = (stored << 1) | xer_so;
1330 env->reserve_addr = (target_ulong)-1;
1331 }
1332 if (!segv) {
1333 env->nip += 4;
1334 }
1335 mmap_unlock();
1336 end_exclusive();
1337 return segv;
1338}
1339
67867308
FB
1340void cpu_loop(CPUPPCState *env)
1341{
c227f099 1342 target_siginfo_t info;
61190b14 1343 int trapnr;
9e0e2f96 1344 target_ulong ret;
3b46e624 1345
67867308 1346 for(;;) {
56f066bb 1347 cpu_exec_start(env);
67867308 1348 trapnr = cpu_ppc_exec(env);
56f066bb 1349 cpu_exec_end(env);
67867308 1350 switch(trapnr) {
e1833e1f
JM
1351 case POWERPC_EXCP_NONE:
1352 /* Just go on */
67867308 1353 break;
e1833e1f
JM
1354 case POWERPC_EXCP_CRITICAL: /* Critical input */
1355 cpu_abort(env, "Critical interrupt while in user mode. "
1356 "Aborting\n");
61190b14 1357 break;
e1833e1f
JM
1358 case POWERPC_EXCP_MCHECK: /* Machine check exception */
1359 cpu_abort(env, "Machine check exception while in user mode. "
1360 "Aborting\n");
1361 break;
1362 case POWERPC_EXCP_DSI: /* Data storage exception */
90e189ec 1363 EXCP_DUMP(env, "Invalid data memory access: 0x" TARGET_FMT_lx "\n",
e1833e1f
JM
1364 env->spr[SPR_DAR]);
1365 /* XXX: check this. Seems bugged */
2be0071f
FB
1366 switch (env->error_code & 0xFF000000) {
1367 case 0x40000000:
61190b14
FB
1368 info.si_signo = TARGET_SIGSEGV;
1369 info.si_errno = 0;
1370 info.si_code = TARGET_SEGV_MAPERR;
1371 break;
2be0071f 1372 case 0x04000000:
61190b14
FB
1373 info.si_signo = TARGET_SIGILL;
1374 info.si_errno = 0;
1375 info.si_code = TARGET_ILL_ILLADR;
1376 break;
2be0071f 1377 case 0x08000000:
61190b14
FB
1378 info.si_signo = TARGET_SIGSEGV;
1379 info.si_errno = 0;
1380 info.si_code = TARGET_SEGV_ACCERR;
1381 break;
61190b14
FB
1382 default:
1383 /* Let's send a regular segfault... */
e1833e1f
JM
1384 EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
1385 env->error_code);
61190b14
FB
1386 info.si_signo = TARGET_SIGSEGV;
1387 info.si_errno = 0;
1388 info.si_code = TARGET_SEGV_MAPERR;
1389 break;
1390 }
67867308 1391 info._sifields._sigfault._addr = env->nip;
624f7979 1392 queue_signal(env, info.si_signo, &info);
67867308 1393 break;
e1833e1f 1394 case POWERPC_EXCP_ISI: /* Instruction storage exception */
90e189ec
BS
1395 EXCP_DUMP(env, "Invalid instruction fetch: 0x\n" TARGET_FMT_lx
1396 "\n", env->spr[SPR_SRR0]);
e1833e1f 1397 /* XXX: check this */
2be0071f
FB
1398 switch (env->error_code & 0xFF000000) {
1399 case 0x40000000:
61190b14 1400 info.si_signo = TARGET_SIGSEGV;
67867308 1401 info.si_errno = 0;
61190b14
FB
1402 info.si_code = TARGET_SEGV_MAPERR;
1403 break;
2be0071f
FB
1404 case 0x10000000:
1405 case 0x08000000:
61190b14
FB
1406 info.si_signo = TARGET_SIGSEGV;
1407 info.si_errno = 0;
1408 info.si_code = TARGET_SEGV_ACCERR;
1409 break;
1410 default:
1411 /* Let's send a regular segfault... */
e1833e1f
JM
1412 EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
1413 env->error_code);
61190b14
FB
1414 info.si_signo = TARGET_SIGSEGV;
1415 info.si_errno = 0;
1416 info.si_code = TARGET_SEGV_MAPERR;
1417 break;
1418 }
1419 info._sifields._sigfault._addr = env->nip - 4;
624f7979 1420 queue_signal(env, info.si_signo, &info);
67867308 1421 break;
e1833e1f
JM
1422 case POWERPC_EXCP_EXTERNAL: /* External input */
1423 cpu_abort(env, "External interrupt while in user mode. "
1424 "Aborting\n");
1425 break;
1426 case POWERPC_EXCP_ALIGN: /* Alignment exception */
1427 EXCP_DUMP(env, "Unaligned memory access\n");
1428 /* XXX: check this */
61190b14 1429 info.si_signo = TARGET_SIGBUS;
67867308 1430 info.si_errno = 0;
61190b14
FB
1431 info.si_code = TARGET_BUS_ADRALN;
1432 info._sifields._sigfault._addr = env->nip - 4;
624f7979 1433 queue_signal(env, info.si_signo, &info);
67867308 1434 break;
e1833e1f
JM
1435 case POWERPC_EXCP_PROGRAM: /* Program exception */
1436 /* XXX: check this */
61190b14 1437 switch (env->error_code & ~0xF) {
e1833e1f
JM
1438 case POWERPC_EXCP_FP:
1439 EXCP_DUMP(env, "Floating point program exception\n");
61190b14
FB
1440 info.si_signo = TARGET_SIGFPE;
1441 info.si_errno = 0;
1442 switch (env->error_code & 0xF) {
e1833e1f 1443 case POWERPC_EXCP_FP_OX:
61190b14
FB
1444 info.si_code = TARGET_FPE_FLTOVF;
1445 break;
e1833e1f 1446 case POWERPC_EXCP_FP_UX:
61190b14
FB
1447 info.si_code = TARGET_FPE_FLTUND;
1448 break;
e1833e1f
JM
1449 case POWERPC_EXCP_FP_ZX:
1450 case POWERPC_EXCP_FP_VXZDZ:
61190b14
FB
1451 info.si_code = TARGET_FPE_FLTDIV;
1452 break;
e1833e1f 1453 case POWERPC_EXCP_FP_XX:
61190b14
FB
1454 info.si_code = TARGET_FPE_FLTRES;
1455 break;
e1833e1f 1456 case POWERPC_EXCP_FP_VXSOFT:
61190b14
FB
1457 info.si_code = TARGET_FPE_FLTINV;
1458 break;
7c58044c 1459 case POWERPC_EXCP_FP_VXSNAN:
e1833e1f
JM
1460 case POWERPC_EXCP_FP_VXISI:
1461 case POWERPC_EXCP_FP_VXIDI:
1462 case POWERPC_EXCP_FP_VXIMZ:
1463 case POWERPC_EXCP_FP_VXVC:
1464 case POWERPC_EXCP_FP_VXSQRT:
1465 case POWERPC_EXCP_FP_VXCVI:
61190b14
FB
1466 info.si_code = TARGET_FPE_FLTSUB;
1467 break;
1468 default:
e1833e1f
JM
1469 EXCP_DUMP(env, "Unknown floating point exception (%02x)\n",
1470 env->error_code);
1471 break;
61190b14 1472 }
e1833e1f
JM
1473 break;
1474 case POWERPC_EXCP_INVAL:
1475 EXCP_DUMP(env, "Invalid instruction\n");
61190b14
FB
1476 info.si_signo = TARGET_SIGILL;
1477 info.si_errno = 0;
1478 switch (env->error_code & 0xF) {
e1833e1f 1479 case POWERPC_EXCP_INVAL_INVAL:
61190b14
FB
1480 info.si_code = TARGET_ILL_ILLOPC;
1481 break;
e1833e1f 1482 case POWERPC_EXCP_INVAL_LSWX:
a750fc0b 1483 info.si_code = TARGET_ILL_ILLOPN;
61190b14 1484 break;
e1833e1f 1485 case POWERPC_EXCP_INVAL_SPR:
61190b14
FB
1486 info.si_code = TARGET_ILL_PRVREG;
1487 break;
e1833e1f 1488 case POWERPC_EXCP_INVAL_FP:
61190b14
FB
1489 info.si_code = TARGET_ILL_COPROC;
1490 break;
1491 default:
e1833e1f
JM
1492 EXCP_DUMP(env, "Unknown invalid operation (%02x)\n",
1493 env->error_code & 0xF);
61190b14
FB
1494 info.si_code = TARGET_ILL_ILLADR;
1495 break;
1496 }
1497 break;
e1833e1f
JM
1498 case POWERPC_EXCP_PRIV:
1499 EXCP_DUMP(env, "Privilege violation\n");
61190b14
FB
1500 info.si_signo = TARGET_SIGILL;
1501 info.si_errno = 0;
1502 switch (env->error_code & 0xF) {
e1833e1f 1503 case POWERPC_EXCP_PRIV_OPC:
61190b14
FB
1504 info.si_code = TARGET_ILL_PRVOPC;
1505 break;
e1833e1f 1506 case POWERPC_EXCP_PRIV_REG:
61190b14 1507 info.si_code = TARGET_ILL_PRVREG;
e1833e1f 1508 break;
61190b14 1509 default:
e1833e1f
JM
1510 EXCP_DUMP(env, "Unknown privilege violation (%02x)\n",
1511 env->error_code & 0xF);
61190b14
FB
1512 info.si_code = TARGET_ILL_PRVOPC;
1513 break;
1514 }
1515 break;
e1833e1f
JM
1516 case POWERPC_EXCP_TRAP:
1517 cpu_abort(env, "Tried to call a TRAP\n");
1518 break;
61190b14
FB
1519 default:
1520 /* Should not happen ! */
e1833e1f
JM
1521 cpu_abort(env, "Unknown program exception (%02x)\n",
1522 env->error_code);
1523 break;
61190b14
FB
1524 }
1525 info._sifields._sigfault._addr = env->nip - 4;
624f7979 1526 queue_signal(env, info.si_signo, &info);
67867308 1527 break;
e1833e1f
JM
1528 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
1529 EXCP_DUMP(env, "No floating point allowed\n");
61190b14 1530 info.si_signo = TARGET_SIGILL;
67867308 1531 info.si_errno = 0;
61190b14
FB
1532 info.si_code = TARGET_ILL_COPROC;
1533 info._sifields._sigfault._addr = env->nip - 4;
624f7979 1534 queue_signal(env, info.si_signo, &info);
67867308 1535 break;
e1833e1f
JM
1536 case POWERPC_EXCP_SYSCALL: /* System call exception */
1537 cpu_abort(env, "Syscall exception while in user mode. "
1538 "Aborting\n");
61190b14 1539 break;
e1833e1f
JM
1540 case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
1541 EXCP_DUMP(env, "No APU instruction allowed\n");
1542 info.si_signo = TARGET_SIGILL;
1543 info.si_errno = 0;
1544 info.si_code = TARGET_ILL_COPROC;
1545 info._sifields._sigfault._addr = env->nip - 4;
624f7979 1546 queue_signal(env, info.si_signo, &info);
61190b14 1547 break;
e1833e1f
JM
1548 case POWERPC_EXCP_DECR: /* Decrementer exception */
1549 cpu_abort(env, "Decrementer interrupt while in user mode. "
1550 "Aborting\n");
61190b14 1551 break;
e1833e1f
JM
1552 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
1553 cpu_abort(env, "Fix interval timer interrupt while in user mode. "
1554 "Aborting\n");
1555 break;
1556 case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
1557 cpu_abort(env, "Watchdog timer interrupt while in user mode. "
1558 "Aborting\n");
1559 break;
1560 case POWERPC_EXCP_DTLB: /* Data TLB error */
1561 cpu_abort(env, "Data TLB exception while in user mode. "
1562 "Aborting\n");
1563 break;
1564 case POWERPC_EXCP_ITLB: /* Instruction TLB error */
1565 cpu_abort(env, "Instruction TLB exception while in user mode. "
1566 "Aborting\n");
1567 break;
e1833e1f
JM
1568 case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */
1569 EXCP_DUMP(env, "No SPE/floating-point instruction allowed\n");
1570 info.si_signo = TARGET_SIGILL;
1571 info.si_errno = 0;
1572 info.si_code = TARGET_ILL_COPROC;
1573 info._sifields._sigfault._addr = env->nip - 4;
624f7979 1574 queue_signal(env, info.si_signo, &info);
e1833e1f
JM
1575 break;
1576 case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */
1577 cpu_abort(env, "Embedded floating-point data IRQ not handled\n");
1578 break;
1579 case POWERPC_EXCP_EFPRI: /* Embedded floating-point round IRQ */
1580 cpu_abort(env, "Embedded floating-point round IRQ not handled\n");
1581 break;
1582 case POWERPC_EXCP_EPERFM: /* Embedded performance monitor IRQ */
1583 cpu_abort(env, "Performance monitor exception not handled\n");
1584 break;
1585 case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
1586 cpu_abort(env, "Doorbell interrupt while in user mode. "
1587 "Aborting\n");
1588 break;
1589 case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
1590 cpu_abort(env, "Doorbell critical interrupt while in user mode. "
1591 "Aborting\n");
1592 break;
1593 case POWERPC_EXCP_RESET: /* System reset exception */
1594 cpu_abort(env, "Reset interrupt while in user mode. "
1595 "Aborting\n");
1596 break;
e1833e1f
JM
1597 case POWERPC_EXCP_DSEG: /* Data segment exception */
1598 cpu_abort(env, "Data segment exception while in user mode. "
1599 "Aborting\n");
1600 break;
1601 case POWERPC_EXCP_ISEG: /* Instruction segment exception */
1602 cpu_abort(env, "Instruction segment exception "
1603 "while in user mode. Aborting\n");
1604 break;
e85e7c6e 1605 /* PowerPC 64 with hypervisor mode support */
e1833e1f
JM
1606 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
1607 cpu_abort(env, "Hypervisor decrementer interrupt "
1608 "while in user mode. Aborting\n");
1609 break;
e1833e1f
JM
1610 case POWERPC_EXCP_TRACE: /* Trace exception */
1611 /* Nothing to do:
1612 * we use this exception to emulate step-by-step execution mode.
1613 */
1614 break;
e85e7c6e 1615 /* PowerPC 64 with hypervisor mode support */
e1833e1f
JM
1616 case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
1617 cpu_abort(env, "Hypervisor data storage exception "
1618 "while in user mode. Aborting\n");
1619 break;
1620 case POWERPC_EXCP_HISI: /* Hypervisor instruction storage excp */
1621 cpu_abort(env, "Hypervisor instruction storage exception "
1622 "while in user mode. Aborting\n");
1623 break;
1624 case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
1625 cpu_abort(env, "Hypervisor data segment exception "
1626 "while in user mode. Aborting\n");
1627 break;
1628 case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment excp */
1629 cpu_abort(env, "Hypervisor instruction segment exception "
1630 "while in user mode. Aborting\n");
1631 break;
e1833e1f
JM
1632 case POWERPC_EXCP_VPU: /* Vector unavailable exception */
1633 EXCP_DUMP(env, "No Altivec instructions allowed\n");
1634 info.si_signo = TARGET_SIGILL;
1635 info.si_errno = 0;
1636 info.si_code = TARGET_ILL_COPROC;
1637 info._sifields._sigfault._addr = env->nip - 4;
624f7979 1638 queue_signal(env, info.si_signo, &info);
e1833e1f
JM
1639 break;
1640 case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */
b4916d7b 1641 cpu_abort(env, "Programmable interval timer interrupt "
e1833e1f
JM
1642 "while in user mode. Aborting\n");
1643 break;
1644 case POWERPC_EXCP_IO: /* IO error exception */
1645 cpu_abort(env, "IO error exception while in user mode. "
1646 "Aborting\n");
1647 break;
1648 case POWERPC_EXCP_RUNM: /* Run mode exception */
1649 cpu_abort(env, "Run mode exception while in user mode. "
1650 "Aborting\n");
1651 break;
1652 case POWERPC_EXCP_EMUL: /* Emulation trap exception */
1653 cpu_abort(env, "Emulation trap exception not handled\n");
1654 break;
1655 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
1656 cpu_abort(env, "Instruction fetch TLB exception "
1657 "while in user-mode. Aborting");
1658 break;
1659 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
1660 cpu_abort(env, "Data load TLB exception while in user-mode. "
1661 "Aborting");
1662 break;
1663 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
1664 cpu_abort(env, "Data store TLB exception while in user-mode. "
1665 "Aborting");
1666 break;
1667 case POWERPC_EXCP_FPA: /* Floating-point assist exception */
1668 cpu_abort(env, "Floating-point assist exception not handled\n");
1669 break;
1670 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
1671 cpu_abort(env, "Instruction address breakpoint exception "
1672 "not handled\n");
1673 break;
1674 case POWERPC_EXCP_SMI: /* System management interrupt */
1675 cpu_abort(env, "System management interrupt while in user mode. "
1676 "Aborting\n");
1677 break;
1678 case POWERPC_EXCP_THERM: /* Thermal interrupt */
1679 cpu_abort(env, "Thermal interrupt interrupt while in user mode. "
1680 "Aborting\n");
1681 break;
1682 case POWERPC_EXCP_PERFM: /* Embedded performance monitor IRQ */
1683 cpu_abort(env, "Performance monitor exception not handled\n");
1684 break;
1685 case POWERPC_EXCP_VPUA: /* Vector assist exception */
1686 cpu_abort(env, "Vector assist exception not handled\n");
1687 break;
1688 case POWERPC_EXCP_SOFTP: /* Soft patch exception */
1689 cpu_abort(env, "Soft patch exception not handled\n");
1690 break;
1691 case POWERPC_EXCP_MAINT: /* Maintenance exception */
1692 cpu_abort(env, "Maintenance exception while in user mode. "
1693 "Aborting\n");
1694 break;
1695 case POWERPC_EXCP_STOP: /* stop translation */
1696 /* We did invalidate the instruction cache. Go on */
1697 break;
1698 case POWERPC_EXCP_BRANCH: /* branch instruction: */
1699 /* We just stopped because of a branch. Go on */
1700 break;
1701 case POWERPC_EXCP_SYSCALL_USER:
1702 /* system call in user-mode emulation */
1703 /* WARNING:
1704 * PPC ABI uses overflow flag in cr0 to signal an error
1705 * in syscalls.
1706 */
e1833e1f
JM
1707 env->crf[0] &= ~0x1;
1708 ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
1709 env->gpr[5], env->gpr[6], env->gpr[7],
5945cfcb 1710 env->gpr[8], 0, 0);
9e0e2f96 1711 if (ret == (target_ulong)(-TARGET_QEMU_ESIGRETURN)) {
bcd4933a
NF
1712 /* Returning from a successful sigreturn syscall.
1713 Avoid corrupting register state. */
1714 break;
1715 }
9e0e2f96 1716 if (ret > (target_ulong)(-515)) {
e1833e1f
JM
1717 env->crf[0] |= 0x1;
1718 ret = -ret;
61190b14 1719 }
e1833e1f 1720 env->gpr[3] = ret;
e1833e1f 1721 break;
56f066bb
NF
1722 case POWERPC_EXCP_STCX:
1723 if (do_store_exclusive(env)) {
1724 info.si_signo = TARGET_SIGSEGV;
1725 info.si_errno = 0;
1726 info.si_code = TARGET_SEGV_MAPERR;
1727 info._sifields._sigfault._addr = env->nip;
1728 queue_signal(env, info.si_signo, &info);
1729 }
1730 break;
71f75756
AJ
1731 case EXCP_DEBUG:
1732 {
1733 int sig;
1734
1735 sig = gdb_handlesig(env, TARGET_SIGTRAP);
1736 if (sig) {
1737 info.si_signo = sig;
1738 info.si_errno = 0;
1739 info.si_code = TARGET_TRAP_BRKPT;
1740 queue_signal(env, info.si_signo, &info);
1741 }
1742 }
1743 break;
56ba31ff
JM
1744 case EXCP_INTERRUPT:
1745 /* just indicate that signals should be handled asap */
1746 break;
e1833e1f
JM
1747 default:
1748 cpu_abort(env, "Unknown exception 0x%d. Aborting\n", trapnr);
1749 break;
67867308
FB
1750 }
1751 process_pending_signals(env);
1752 }
1753}
1754#endif
1755
048f6b4d
FB
1756#ifdef TARGET_MIPS
1757
1758#define MIPS_SYS(name, args) args,
1759
1760static const uint8_t mips_syscall_args[] = {
29fb0f25 1761 MIPS_SYS(sys_syscall , 8) /* 4000 */
048f6b4d
FB
1762 MIPS_SYS(sys_exit , 1)
1763 MIPS_SYS(sys_fork , 0)
1764 MIPS_SYS(sys_read , 3)
1765 MIPS_SYS(sys_write , 3)
1766 MIPS_SYS(sys_open , 3) /* 4005 */
1767 MIPS_SYS(sys_close , 1)
1768 MIPS_SYS(sys_waitpid , 3)
1769 MIPS_SYS(sys_creat , 2)
1770 MIPS_SYS(sys_link , 2)
1771 MIPS_SYS(sys_unlink , 1) /* 4010 */
1772 MIPS_SYS(sys_execve , 0)
1773 MIPS_SYS(sys_chdir , 1)
1774 MIPS_SYS(sys_time , 1)
1775 MIPS_SYS(sys_mknod , 3)
1776 MIPS_SYS(sys_chmod , 2) /* 4015 */
1777 MIPS_SYS(sys_lchown , 3)
1778 MIPS_SYS(sys_ni_syscall , 0)
1779 MIPS_SYS(sys_ni_syscall , 0) /* was sys_stat */
1780 MIPS_SYS(sys_lseek , 3)
1781 MIPS_SYS(sys_getpid , 0) /* 4020 */
1782 MIPS_SYS(sys_mount , 5)
1783 MIPS_SYS(sys_oldumount , 1)
1784 MIPS_SYS(sys_setuid , 1)
1785 MIPS_SYS(sys_getuid , 0)
1786 MIPS_SYS(sys_stime , 1) /* 4025 */
1787 MIPS_SYS(sys_ptrace , 4)
1788 MIPS_SYS(sys_alarm , 1)
1789 MIPS_SYS(sys_ni_syscall , 0) /* was sys_fstat */
1790 MIPS_SYS(sys_pause , 0)
1791 MIPS_SYS(sys_utime , 2) /* 4030 */
1792 MIPS_SYS(sys_ni_syscall , 0)
1793 MIPS_SYS(sys_ni_syscall , 0)
1794 MIPS_SYS(sys_access , 2)
1795 MIPS_SYS(sys_nice , 1)
1796 MIPS_SYS(sys_ni_syscall , 0) /* 4035 */
1797 MIPS_SYS(sys_sync , 0)
1798 MIPS_SYS(sys_kill , 2)
1799 MIPS_SYS(sys_rename , 2)
1800 MIPS_SYS(sys_mkdir , 2)
1801 MIPS_SYS(sys_rmdir , 1) /* 4040 */
1802 MIPS_SYS(sys_dup , 1)
1803 MIPS_SYS(sys_pipe , 0)
1804 MIPS_SYS(sys_times , 1)
1805 MIPS_SYS(sys_ni_syscall , 0)
1806 MIPS_SYS(sys_brk , 1) /* 4045 */
1807 MIPS_SYS(sys_setgid , 1)
1808 MIPS_SYS(sys_getgid , 0)
1809 MIPS_SYS(sys_ni_syscall , 0) /* was signal(2) */
1810 MIPS_SYS(sys_geteuid , 0)
1811 MIPS_SYS(sys_getegid , 0) /* 4050 */
1812 MIPS_SYS(sys_acct , 0)
1813 MIPS_SYS(sys_umount , 2)
1814 MIPS_SYS(sys_ni_syscall , 0)
1815 MIPS_SYS(sys_ioctl , 3)
1816 MIPS_SYS(sys_fcntl , 3) /* 4055 */
1817 MIPS_SYS(sys_ni_syscall , 2)
1818 MIPS_SYS(sys_setpgid , 2)
1819 MIPS_SYS(sys_ni_syscall , 0)
1820 MIPS_SYS(sys_olduname , 1)
1821 MIPS_SYS(sys_umask , 1) /* 4060 */
1822 MIPS_SYS(sys_chroot , 1)
1823 MIPS_SYS(sys_ustat , 2)
1824 MIPS_SYS(sys_dup2 , 2)
1825 MIPS_SYS(sys_getppid , 0)
1826 MIPS_SYS(sys_getpgrp , 0) /* 4065 */
1827 MIPS_SYS(sys_setsid , 0)
1828 MIPS_SYS(sys_sigaction , 3)
1829 MIPS_SYS(sys_sgetmask , 0)
1830 MIPS_SYS(sys_ssetmask , 1)
1831 MIPS_SYS(sys_setreuid , 2) /* 4070 */
1832 MIPS_SYS(sys_setregid , 2)
1833 MIPS_SYS(sys_sigsuspend , 0)
1834 MIPS_SYS(sys_sigpending , 1)
1835 MIPS_SYS(sys_sethostname , 2)
1836 MIPS_SYS(sys_setrlimit , 2) /* 4075 */
1837 MIPS_SYS(sys_getrlimit , 2)
1838 MIPS_SYS(sys_getrusage , 2)
1839 MIPS_SYS(sys_gettimeofday, 2)
1840 MIPS_SYS(sys_settimeofday, 2)
1841 MIPS_SYS(sys_getgroups , 2) /* 4080 */
1842 MIPS_SYS(sys_setgroups , 2)
1843 MIPS_SYS(sys_ni_syscall , 0) /* old_select */
1844 MIPS_SYS(sys_symlink , 2)
1845 MIPS_SYS(sys_ni_syscall , 0) /* was sys_lstat */
1846 MIPS_SYS(sys_readlink , 3) /* 4085 */
1847 MIPS_SYS(sys_uselib , 1)
1848 MIPS_SYS(sys_swapon , 2)
1849 MIPS_SYS(sys_reboot , 3)
1850 MIPS_SYS(old_readdir , 3)
1851 MIPS_SYS(old_mmap , 6) /* 4090 */
1852 MIPS_SYS(sys_munmap , 2)
1853 MIPS_SYS(sys_truncate , 2)
1854 MIPS_SYS(sys_ftruncate , 2)
1855 MIPS_SYS(sys_fchmod , 2)
1856 MIPS_SYS(sys_fchown , 3) /* 4095 */
1857 MIPS_SYS(sys_getpriority , 2)
1858 MIPS_SYS(sys_setpriority , 3)
1859 MIPS_SYS(sys_ni_syscall , 0)
1860 MIPS_SYS(sys_statfs , 2)
1861 MIPS_SYS(sys_fstatfs , 2) /* 4100 */
1862 MIPS_SYS(sys_ni_syscall , 0) /* was ioperm(2) */
1863 MIPS_SYS(sys_socketcall , 2)
1864 MIPS_SYS(sys_syslog , 3)
1865 MIPS_SYS(sys_setitimer , 3)
1866 MIPS_SYS(sys_getitimer , 2) /* 4105 */
1867 MIPS_SYS(sys_newstat , 2)
1868 MIPS_SYS(sys_newlstat , 2)
1869 MIPS_SYS(sys_newfstat , 2)
1870 MIPS_SYS(sys_uname , 1)
1871 MIPS_SYS(sys_ni_syscall , 0) /* 4110 was iopl(2) */
1872 MIPS_SYS(sys_vhangup , 0)
1873 MIPS_SYS(sys_ni_syscall , 0) /* was sys_idle() */
1874 MIPS_SYS(sys_ni_syscall , 0) /* was sys_vm86 */
1875 MIPS_SYS(sys_wait4 , 4)
1876 MIPS_SYS(sys_swapoff , 1) /* 4115 */
1877 MIPS_SYS(sys_sysinfo , 1)
1878 MIPS_SYS(sys_ipc , 6)
1879 MIPS_SYS(sys_fsync , 1)
1880 MIPS_SYS(sys_sigreturn , 0)
18113962 1881 MIPS_SYS(sys_clone , 6) /* 4120 */
048f6b4d
FB
1882 MIPS_SYS(sys_setdomainname, 2)
1883 MIPS_SYS(sys_newuname , 1)
1884 MIPS_SYS(sys_ni_syscall , 0) /* sys_modify_ldt */
1885 MIPS_SYS(sys_adjtimex , 1)
1886 MIPS_SYS(sys_mprotect , 3) /* 4125 */
1887 MIPS_SYS(sys_sigprocmask , 3)
1888 MIPS_SYS(sys_ni_syscall , 0) /* was create_module */
1889 MIPS_SYS(sys_init_module , 5)
1890 MIPS_SYS(sys_delete_module, 1)
1891 MIPS_SYS(sys_ni_syscall , 0) /* 4130 was get_kernel_syms */
1892 MIPS_SYS(sys_quotactl , 0)
1893 MIPS_SYS(sys_getpgid , 1)
1894 MIPS_SYS(sys_fchdir , 1)
1895 MIPS_SYS(sys_bdflush , 2)
1896 MIPS_SYS(sys_sysfs , 3) /* 4135 */
1897 MIPS_SYS(sys_personality , 1)
1898 MIPS_SYS(sys_ni_syscall , 0) /* for afs_syscall */
1899 MIPS_SYS(sys_setfsuid , 1)
1900 MIPS_SYS(sys_setfsgid , 1)
1901 MIPS_SYS(sys_llseek , 5) /* 4140 */
1902 MIPS_SYS(sys_getdents , 3)
1903 MIPS_SYS(sys_select , 5)
1904 MIPS_SYS(sys_flock , 2)
1905 MIPS_SYS(sys_msync , 3)
1906 MIPS_SYS(sys_readv , 3) /* 4145 */
1907 MIPS_SYS(sys_writev , 3)
1908 MIPS_SYS(sys_cacheflush , 3)
1909 MIPS_SYS(sys_cachectl , 3)
1910 MIPS_SYS(sys_sysmips , 4)
1911 MIPS_SYS(sys_ni_syscall , 0) /* 4150 */
1912 MIPS_SYS(sys_getsid , 1)
1913 MIPS_SYS(sys_fdatasync , 0)
1914 MIPS_SYS(sys_sysctl , 1)
1915 MIPS_SYS(sys_mlock , 2)
1916 MIPS_SYS(sys_munlock , 2) /* 4155 */
1917 MIPS_SYS(sys_mlockall , 1)
1918 MIPS_SYS(sys_munlockall , 0)
1919 MIPS_SYS(sys_sched_setparam, 2)
1920 MIPS_SYS(sys_sched_getparam, 2)
1921 MIPS_SYS(sys_sched_setscheduler, 3) /* 4160 */
1922 MIPS_SYS(sys_sched_getscheduler, 1)
1923 MIPS_SYS(sys_sched_yield , 0)
1924 MIPS_SYS(sys_sched_get_priority_max, 1)
1925 MIPS_SYS(sys_sched_get_priority_min, 1)
1926 MIPS_SYS(sys_sched_rr_get_interval, 2) /* 4165 */
1927 MIPS_SYS(sys_nanosleep, 2)
1928 MIPS_SYS(sys_mremap , 4)
1929 MIPS_SYS(sys_accept , 3)
1930 MIPS_SYS(sys_bind , 3)
1931 MIPS_SYS(sys_connect , 3) /* 4170 */
1932 MIPS_SYS(sys_getpeername , 3)
1933 MIPS_SYS(sys_getsockname , 3)
1934 MIPS_SYS(sys_getsockopt , 5)
1935 MIPS_SYS(sys_listen , 2)
1936 MIPS_SYS(sys_recv , 4) /* 4175 */
1937 MIPS_SYS(sys_recvfrom , 6)
1938 MIPS_SYS(sys_recvmsg , 3)
1939 MIPS_SYS(sys_send , 4)
1940 MIPS_SYS(sys_sendmsg , 3)
1941 MIPS_SYS(sys_sendto , 6) /* 4180 */
1942 MIPS_SYS(sys_setsockopt , 5)
1943 MIPS_SYS(sys_shutdown , 2)
1944 MIPS_SYS(sys_socket , 3)
1945 MIPS_SYS(sys_socketpair , 4)
1946 MIPS_SYS(sys_setresuid , 3) /* 4185 */
1947 MIPS_SYS(sys_getresuid , 3)
1948 MIPS_SYS(sys_ni_syscall , 0) /* was sys_query_module */
1949 MIPS_SYS(sys_poll , 3)
1950 MIPS_SYS(sys_nfsservctl , 3)
1951 MIPS_SYS(sys_setresgid , 3) /* 4190 */
1952 MIPS_SYS(sys_getresgid , 3)
1953 MIPS_SYS(sys_prctl , 5)
1954 MIPS_SYS(sys_rt_sigreturn, 0)
1955 MIPS_SYS(sys_rt_sigaction, 4)
1956 MIPS_SYS(sys_rt_sigprocmask, 4) /* 4195 */
1957 MIPS_SYS(sys_rt_sigpending, 2)
1958 MIPS_SYS(sys_rt_sigtimedwait, 4)
1959 MIPS_SYS(sys_rt_sigqueueinfo, 3)
1960 MIPS_SYS(sys_rt_sigsuspend, 0)
1961 MIPS_SYS(sys_pread64 , 6) /* 4200 */
1962 MIPS_SYS(sys_pwrite64 , 6)
1963 MIPS_SYS(sys_chown , 3)
1964 MIPS_SYS(sys_getcwd , 2)
1965 MIPS_SYS(sys_capget , 2)
1966 MIPS_SYS(sys_capset , 2) /* 4205 */
053ebb27 1967 MIPS_SYS(sys_sigaltstack , 2)
048f6b4d
FB
1968 MIPS_SYS(sys_sendfile , 4)
1969 MIPS_SYS(sys_ni_syscall , 0)
1970 MIPS_SYS(sys_ni_syscall , 0)
1971 MIPS_SYS(sys_mmap2 , 6) /* 4210 */
1972 MIPS_SYS(sys_truncate64 , 4)
1973 MIPS_SYS(sys_ftruncate64 , 4)
1974 MIPS_SYS(sys_stat64 , 2)
1975 MIPS_SYS(sys_lstat64 , 2)
1976 MIPS_SYS(sys_fstat64 , 2) /* 4215 */
1977 MIPS_SYS(sys_pivot_root , 2)
1978 MIPS_SYS(sys_mincore , 3)
1979 MIPS_SYS(sys_madvise , 3)
1980 MIPS_SYS(sys_getdents64 , 3)
1981 MIPS_SYS(sys_fcntl64 , 3) /* 4220 */
1982 MIPS_SYS(sys_ni_syscall , 0)
1983 MIPS_SYS(sys_gettid , 0)
1984 MIPS_SYS(sys_readahead , 5)
1985 MIPS_SYS(sys_setxattr , 5)
1986 MIPS_SYS(sys_lsetxattr , 5) /* 4225 */
1987 MIPS_SYS(sys_fsetxattr , 5)
1988 MIPS_SYS(sys_getxattr , 4)
1989 MIPS_SYS(sys_lgetxattr , 4)
1990 MIPS_SYS(sys_fgetxattr , 4)
1991 MIPS_SYS(sys_listxattr , 3) /* 4230 */
1992 MIPS_SYS(sys_llistxattr , 3)
1993 MIPS_SYS(sys_flistxattr , 3)
1994 MIPS_SYS(sys_removexattr , 2)
1995 MIPS_SYS(sys_lremovexattr, 2)
1996 MIPS_SYS(sys_fremovexattr, 2) /* 4235 */
1997 MIPS_SYS(sys_tkill , 2)
1998 MIPS_SYS(sys_sendfile64 , 5)
1999 MIPS_SYS(sys_futex , 2)
2000 MIPS_SYS(sys_sched_setaffinity, 3)
2001 MIPS_SYS(sys_sched_getaffinity, 3) /* 4240 */
2002 MIPS_SYS(sys_io_setup , 2)
2003 MIPS_SYS(sys_io_destroy , 1)
2004 MIPS_SYS(sys_io_getevents, 5)
2005 MIPS_SYS(sys_io_submit , 3)
2006 MIPS_SYS(sys_io_cancel , 3) /* 4245 */
2007 MIPS_SYS(sys_exit_group , 1)
2008 MIPS_SYS(sys_lookup_dcookie, 3)
2009 MIPS_SYS(sys_epoll_create, 1)
2010 MIPS_SYS(sys_epoll_ctl , 4)
2011 MIPS_SYS(sys_epoll_wait , 3) /* 4250 */
2012 MIPS_SYS(sys_remap_file_pages, 5)
2013 MIPS_SYS(sys_set_tid_address, 1)
2014 MIPS_SYS(sys_restart_syscall, 0)
2015 MIPS_SYS(sys_fadvise64_64, 7)
2016 MIPS_SYS(sys_statfs64 , 3) /* 4255 */
2017 MIPS_SYS(sys_fstatfs64 , 2)
2018 MIPS_SYS(sys_timer_create, 3)
2019 MIPS_SYS(sys_timer_settime, 4)
2020 MIPS_SYS(sys_timer_gettime, 2)
2021 MIPS_SYS(sys_timer_getoverrun, 1) /* 4260 */
2022 MIPS_SYS(sys_timer_delete, 1)
2023 MIPS_SYS(sys_clock_settime, 2)
2024 MIPS_SYS(sys_clock_gettime, 2)
2025 MIPS_SYS(sys_clock_getres, 2)
2026 MIPS_SYS(sys_clock_nanosleep, 4) /* 4265 */
2027 MIPS_SYS(sys_tgkill , 3)
2028 MIPS_SYS(sys_utimes , 2)
2029 MIPS_SYS(sys_mbind , 4)
2030 MIPS_SYS(sys_ni_syscall , 0) /* sys_get_mempolicy */
2031 MIPS_SYS(sys_ni_syscall , 0) /* 4270 sys_set_mempolicy */
2032 MIPS_SYS(sys_mq_open , 4)
2033 MIPS_SYS(sys_mq_unlink , 1)
2034 MIPS_SYS(sys_mq_timedsend, 5)
2035 MIPS_SYS(sys_mq_timedreceive, 5)
2036 MIPS_SYS(sys_mq_notify , 2) /* 4275 */
2037 MIPS_SYS(sys_mq_getsetattr, 3)
2038 MIPS_SYS(sys_ni_syscall , 0) /* sys_vserver */
2039 MIPS_SYS(sys_waitid , 4)
2040 MIPS_SYS(sys_ni_syscall , 0) /* available, was setaltroot */
2041 MIPS_SYS(sys_add_key , 5)
388bb21a 2042 MIPS_SYS(sys_request_key, 4)
048f6b4d 2043 MIPS_SYS(sys_keyctl , 5)
6f5b89a0 2044 MIPS_SYS(sys_set_thread_area, 1)
388bb21a
TS
2045 MIPS_SYS(sys_inotify_init, 0)
2046 MIPS_SYS(sys_inotify_add_watch, 3) /* 4285 */
2047 MIPS_SYS(sys_inotify_rm_watch, 2)
2048 MIPS_SYS(sys_migrate_pages, 4)
2049 MIPS_SYS(sys_openat, 4)
2050 MIPS_SYS(sys_mkdirat, 3)
2051 MIPS_SYS(sys_mknodat, 4) /* 4290 */
2052 MIPS_SYS(sys_fchownat, 5)
2053 MIPS_SYS(sys_futimesat, 3)
2054 MIPS_SYS(sys_fstatat64, 4)
2055 MIPS_SYS(sys_unlinkat, 3)
2056 MIPS_SYS(sys_renameat, 4) /* 4295 */
2057 MIPS_SYS(sys_linkat, 5)
2058 MIPS_SYS(sys_symlinkat, 3)
2059 MIPS_SYS(sys_readlinkat, 4)
2060 MIPS_SYS(sys_fchmodat, 3)
2061 MIPS_SYS(sys_faccessat, 3) /* 4300 */
2062 MIPS_SYS(sys_pselect6, 6)
2063 MIPS_SYS(sys_ppoll, 5)
2064 MIPS_SYS(sys_unshare, 1)
2065 MIPS_SYS(sys_splice, 4)
2066 MIPS_SYS(sys_sync_file_range, 7) /* 4305 */
2067 MIPS_SYS(sys_tee, 4)
2068 MIPS_SYS(sys_vmsplice, 4)
2069 MIPS_SYS(sys_move_pages, 6)
2070 MIPS_SYS(sys_set_robust_list, 2)
2071 MIPS_SYS(sys_get_robust_list, 3) /* 4310 */
2072 MIPS_SYS(sys_kexec_load, 4)
2073 MIPS_SYS(sys_getcpu, 3)
2074 MIPS_SYS(sys_epoll_pwait, 6)
2075 MIPS_SYS(sys_ioprio_set, 3)
2076 MIPS_SYS(sys_ioprio_get, 2)
d979e8eb
PM
2077 MIPS_SYS(sys_utimensat, 4)
2078 MIPS_SYS(sys_signalfd, 3)
2079 MIPS_SYS(sys_ni_syscall, 0) /* was timerfd */
2080 MIPS_SYS(sys_eventfd, 1)
2081 MIPS_SYS(sys_fallocate, 6) /* 4320 */
2082 MIPS_SYS(sys_timerfd_create, 2)
2083 MIPS_SYS(sys_timerfd_gettime, 2)
2084 MIPS_SYS(sys_timerfd_settime, 4)
2085 MIPS_SYS(sys_signalfd4, 4)
2086 MIPS_SYS(sys_eventfd2, 2) /* 4325 */
2087 MIPS_SYS(sys_epoll_create1, 1)
2088 MIPS_SYS(sys_dup3, 3)
2089 MIPS_SYS(sys_pipe2, 2)
2090 MIPS_SYS(sys_inotify_init1, 1)
2091 MIPS_SYS(sys_preadv, 6) /* 4330 */
2092 MIPS_SYS(sys_pwritev, 6)
2093 MIPS_SYS(sys_rt_tgsigqueueinfo, 4)
2094 MIPS_SYS(sys_perf_event_open, 5)
2095 MIPS_SYS(sys_accept4, 4)
2096 MIPS_SYS(sys_recvmmsg, 5) /* 4335 */
2097 MIPS_SYS(sys_fanotify_init, 2)
2098 MIPS_SYS(sys_fanotify_mark, 6)
2099 MIPS_SYS(sys_prlimit64, 4)
2100 MIPS_SYS(sys_name_to_handle_at, 5)
2101 MIPS_SYS(sys_open_by_handle_at, 3) /* 4340 */
2102 MIPS_SYS(sys_clock_adjtime, 2)
2103 MIPS_SYS(sys_syncfs, 1)
048f6b4d
FB
2104};
2105
2106#undef MIPS_SYS
2107
590bc601
PB
2108static int do_store_exclusive(CPUMIPSState *env)
2109{
2110 target_ulong addr;
2111 target_ulong page_addr;
2112 target_ulong val;
2113 int flags;
2114 int segv = 0;
2115 int reg;
2116 int d;
2117
5499b6ff 2118 addr = env->lladdr;
590bc601
PB
2119 page_addr = addr & TARGET_PAGE_MASK;
2120 start_exclusive();
2121 mmap_lock();
2122 flags = page_get_flags(page_addr);
2123 if ((flags & PAGE_READ) == 0) {
2124 segv = 1;
2125 } else {
2126 reg = env->llreg & 0x1f;
2127 d = (env->llreg & 0x20) != 0;
2128 if (d) {
2129 segv = get_user_s64(val, addr);
2130 } else {
2131 segv = get_user_s32(val, addr);
2132 }
2133 if (!segv) {
2134 if (val != env->llval) {
2135 env->active_tc.gpr[reg] = 0;
2136 } else {
2137 if (d) {
2138 segv = put_user_u64(env->llnewval, addr);
2139 } else {
2140 segv = put_user_u32(env->llnewval, addr);
2141 }
2142 if (!segv) {
2143 env->active_tc.gpr[reg] = 1;
2144 }
2145 }
2146 }
2147 }
5499b6ff 2148 env->lladdr = -1;
590bc601
PB
2149 if (!segv) {
2150 env->active_tc.PC += 4;
2151 }
2152 mmap_unlock();
2153 end_exclusive();
2154 return segv;
2155}
2156
048f6b4d
FB
2157void cpu_loop(CPUMIPSState *env)
2158{
c227f099 2159 target_siginfo_t info;
388bb21a 2160 int trapnr, ret;
048f6b4d 2161 unsigned int syscall_num;
048f6b4d
FB
2162
2163 for(;;) {
590bc601 2164 cpu_exec_start(env);
048f6b4d 2165 trapnr = cpu_mips_exec(env);
590bc601 2166 cpu_exec_end(env);
048f6b4d
FB
2167 switch(trapnr) {
2168 case EXCP_SYSCALL:
b5dc7732
TS
2169 syscall_num = env->active_tc.gpr[2] - 4000;
2170 env->active_tc.PC += 4;
388bb21a 2171 if (syscall_num >= sizeof(mips_syscall_args)) {
7c2f6157 2172 ret = -TARGET_ENOSYS;
388bb21a
TS
2173 } else {
2174 int nb_args;
992f48a0
BS
2175 abi_ulong sp_reg;
2176 abi_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0;
388bb21a
TS
2177
2178 nb_args = mips_syscall_args[syscall_num];
b5dc7732 2179 sp_reg = env->active_tc.gpr[29];
388bb21a
TS
2180 switch (nb_args) {
2181 /* these arguments are taken from the stack */
94c19610
ACH
2182 case 8:
2183 if ((ret = get_user_ual(arg8, sp_reg + 28)) != 0) {
2184 goto done_syscall;
2185 }
2186 case 7:
2187 if ((ret = get_user_ual(arg7, sp_reg + 24)) != 0) {
2188 goto done_syscall;
2189 }
2190 case 6:
2191 if ((ret = get_user_ual(arg6, sp_reg + 20)) != 0) {
2192 goto done_syscall;
2193 }
2194 case 5:
2195 if ((ret = get_user_ual(arg5, sp_reg + 16)) != 0) {
2196 goto done_syscall;
2197 }
388bb21a
TS
2198 default:
2199 break;
048f6b4d 2200 }
b5dc7732
TS
2201 ret = do_syscall(env, env->active_tc.gpr[2],
2202 env->active_tc.gpr[4],
2203 env->active_tc.gpr[5],
2204 env->active_tc.gpr[6],
2205 env->active_tc.gpr[7],
5945cfcb 2206 arg5, arg6, arg7, arg8);
388bb21a 2207 }
94c19610 2208done_syscall:
0b1bcb00
PB
2209 if (ret == -TARGET_QEMU_ESIGRETURN) {
2210 /* Returning from a successful sigreturn syscall.
2211 Avoid clobbering register state. */
2212 break;
2213 }
388bb21a 2214 if ((unsigned int)ret >= (unsigned int)(-1133)) {
b5dc7732 2215 env->active_tc.gpr[7] = 1; /* error flag */
388bb21a
TS
2216 ret = -ret;
2217 } else {
b5dc7732 2218 env->active_tc.gpr[7] = 0; /* error flag */
048f6b4d 2219 }
b5dc7732 2220 env->active_tc.gpr[2] = ret;
048f6b4d 2221 break;
ca7c2b1b
TS
2222 case EXCP_TLBL:
2223 case EXCP_TLBS:
e6e5bd2d
WT
2224 case EXCP_AdEL:
2225 case EXCP_AdES:
e4474235
PB
2226 info.si_signo = TARGET_SIGSEGV;
2227 info.si_errno = 0;
2228 /* XXX: check env->error_code */
2229 info.si_code = TARGET_SEGV_MAPERR;
2230 info._sifields._sigfault._addr = env->CP0_BadVAddr;
2231 queue_signal(env, info.si_signo, &info);
2232 break;
6900e84b 2233 case EXCP_CpU:
048f6b4d 2234 case EXCP_RI:
bc1ad2de
FB
2235 info.si_signo = TARGET_SIGILL;
2236 info.si_errno = 0;
2237 info.si_code = 0;
624f7979 2238 queue_signal(env, info.si_signo, &info);
048f6b4d 2239 break;
106ec879
FB
2240 case EXCP_INTERRUPT:
2241 /* just indicate that signals should be handled asap */
2242 break;
d08b2a28
PB
2243 case EXCP_DEBUG:
2244 {
2245 int sig;
2246
2247 sig = gdb_handlesig (env, TARGET_SIGTRAP);
2248 if (sig)
2249 {
2250 info.si_signo = sig;
2251 info.si_errno = 0;
2252 info.si_code = TARGET_TRAP_BRKPT;
624f7979 2253 queue_signal(env, info.si_signo, &info);
d08b2a28
PB
2254 }
2255 }
2256 break;
590bc601
PB
2257 case EXCP_SC:
2258 if (do_store_exclusive(env)) {
2259 info.si_signo = TARGET_SIGSEGV;
2260 info.si_errno = 0;
2261 info.si_code = TARGET_SEGV_MAPERR;
2262 info._sifields._sigfault._addr = env->active_tc.PC;
2263 queue_signal(env, info.si_signo, &info);
2264 }
2265 break;
048f6b4d
FB
2266 default:
2267 // error:
5fafdf24 2268 fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
048f6b4d
FB
2269 trapnr);
2270 cpu_dump_state(env, stderr, fprintf, 0);
2271 abort();
2272 }
2273 process_pending_signals(env);
2274 }
2275}
2276#endif
2277
fdf9b3e8
FB
2278#ifdef TARGET_SH4
2279void cpu_loop (CPUState *env)
2280{
2281 int trapnr, ret;
c227f099 2282 target_siginfo_t info;
3b46e624 2283
fdf9b3e8
FB
2284 while (1) {
2285 trapnr = cpu_sh4_exec (env);
3b46e624 2286
fdf9b3e8
FB
2287 switch (trapnr) {
2288 case 0x160:
0b6d3ae0 2289 env->pc += 2;
5fafdf24
TS
2290 ret = do_syscall(env,
2291 env->gregs[3],
2292 env->gregs[4],
2293 env->gregs[5],
2294 env->gregs[6],
2295 env->gregs[7],
2296 env->gregs[0],
5945cfcb
PM
2297 env->gregs[1],
2298 0, 0);
9c2a9ea1 2299 env->gregs[0] = ret;
fdf9b3e8 2300 break;
c3b5bc8a
TS
2301 case EXCP_INTERRUPT:
2302 /* just indicate that signals should be handled asap */
2303 break;
355fb23d
PB
2304 case EXCP_DEBUG:
2305 {
2306 int sig;
2307
2308 sig = gdb_handlesig (env, TARGET_SIGTRAP);
2309 if (sig)
2310 {
2311 info.si_signo = sig;
2312 info.si_errno = 0;
2313 info.si_code = TARGET_TRAP_BRKPT;
624f7979 2314 queue_signal(env, info.si_signo, &info);
355fb23d
PB
2315 }
2316 }
2317 break;
c3b5bc8a
TS
2318 case 0xa0:
2319 case 0xc0:
2320 info.si_signo = SIGSEGV;
2321 info.si_errno = 0;
2322 info.si_code = TARGET_SEGV_MAPERR;
2323 info._sifields._sigfault._addr = env->tea;
624f7979 2324 queue_signal(env, info.si_signo, &info);
c3b5bc8a
TS
2325 break;
2326
fdf9b3e8
FB
2327 default:
2328 printf ("Unhandled trap: 0x%x\n", trapnr);
2329 cpu_dump_state(env, stderr, fprintf, 0);
2330 exit (1);
2331 }
2332 process_pending_signals (env);
2333 }
2334}
2335#endif
2336
48733d19
TS
2337#ifdef TARGET_CRIS
2338void cpu_loop (CPUState *env)
2339{
2340 int trapnr, ret;
c227f099 2341 target_siginfo_t info;
48733d19
TS
2342
2343 while (1) {
2344 trapnr = cpu_cris_exec (env);
2345 switch (trapnr) {
2346 case 0xaa:
2347 {
2348 info.si_signo = SIGSEGV;
2349 info.si_errno = 0;
2350 /* XXX: check env->error_code */
2351 info.si_code = TARGET_SEGV_MAPERR;
e00c1e71 2352 info._sifields._sigfault._addr = env->pregs[PR_EDA];
624f7979 2353 queue_signal(env, info.si_signo, &info);
48733d19
TS
2354 }
2355 break;
b6d3abda
EI
2356 case EXCP_INTERRUPT:
2357 /* just indicate that signals should be handled asap */
2358 break;
48733d19
TS
2359 case EXCP_BREAK:
2360 ret = do_syscall(env,
2361 env->regs[9],
2362 env->regs[10],
2363 env->regs[11],
2364 env->regs[12],
2365 env->regs[13],
2366 env->pregs[7],
5945cfcb
PM
2367 env->pregs[11],
2368 0, 0);
48733d19 2369 env->regs[10] = ret;
48733d19
TS
2370 break;
2371 case EXCP_DEBUG:
2372 {
2373 int sig;
2374
2375 sig = gdb_handlesig (env, TARGET_SIGTRAP);
2376 if (sig)
2377 {
2378 info.si_signo = sig;
2379 info.si_errno = 0;
2380 info.si_code = TARGET_TRAP_BRKPT;
624f7979 2381 queue_signal(env, info.si_signo, &info);
48733d19
TS
2382 }
2383 }
2384 break;
2385 default:
2386 printf ("Unhandled trap: 0x%x\n", trapnr);
2387 cpu_dump_state(env, stderr, fprintf, 0);
2388 exit (1);
2389 }
2390 process_pending_signals (env);
2391 }
2392}
2393#endif
2394
b779e29e
EI
2395#ifdef TARGET_MICROBLAZE
2396void cpu_loop (CPUState *env)
2397{
2398 int trapnr, ret;
c227f099 2399 target_siginfo_t info;
b779e29e
EI
2400
2401 while (1) {
2402 trapnr = cpu_mb_exec (env);
2403 switch (trapnr) {
2404 case 0xaa:
2405 {
2406 info.si_signo = SIGSEGV;
2407 info.si_errno = 0;
2408 /* XXX: check env->error_code */
2409 info.si_code = TARGET_SEGV_MAPERR;
2410 info._sifields._sigfault._addr = 0;
2411 queue_signal(env, info.si_signo, &info);
2412 }
2413 break;
2414 case EXCP_INTERRUPT:
2415 /* just indicate that signals should be handled asap */
2416 break;
2417 case EXCP_BREAK:
2418 /* Return address is 4 bytes after the call. */
2419 env->regs[14] += 4;
2420 ret = do_syscall(env,
2421 env->regs[12],
2422 env->regs[5],
2423 env->regs[6],
2424 env->regs[7],
2425 env->regs[8],
2426 env->regs[9],
5945cfcb
PM
2427 env->regs[10],
2428 0, 0);
b779e29e
EI
2429 env->regs[3] = ret;
2430 env->sregs[SR_PC] = env->regs[14];
2431 break;
b76da7e3
EI
2432 case EXCP_HW_EXCP:
2433 env->regs[17] = env->sregs[SR_PC] + 4;
2434 if (env->iflags & D_FLAG) {
2435 env->sregs[SR_ESR] |= 1 << 12;
2436 env->sregs[SR_PC] -= 4;
b4916d7b 2437 /* FIXME: if branch was immed, replay the imm as well. */
b76da7e3
EI
2438 }
2439
2440 env->iflags &= ~(IMM_FLAG | D_FLAG);
2441
2442 switch (env->sregs[SR_ESR] & 31) {
22a78d64
EI
2443 case ESR_EC_DIVZERO:
2444 info.si_signo = SIGFPE;
2445 info.si_errno = 0;
2446 info.si_code = TARGET_FPE_FLTDIV;
2447 info._sifields._sigfault._addr = 0;
2448 queue_signal(env, info.si_signo, &info);
2449 break;
b76da7e3
EI
2450 case ESR_EC_FPU:
2451 info.si_signo = SIGFPE;
2452 info.si_errno = 0;
2453 if (env->sregs[SR_FSR] & FSR_IO) {
2454 info.si_code = TARGET_FPE_FLTINV;
2455 }
2456 if (env->sregs[SR_FSR] & FSR_DZ) {
2457 info.si_code = TARGET_FPE_FLTDIV;
2458 }
2459 info._sifields._sigfault._addr = 0;
2460 queue_signal(env, info.si_signo, &info);
2461 break;
2462 default:
2463 printf ("Unhandled hw-exception: 0x%x\n",
2e42d52d 2464 env->sregs[SR_ESR] & ESR_EC_MASK);
b76da7e3
EI
2465 cpu_dump_state(env, stderr, fprintf, 0);
2466 exit (1);
2467 break;
2468 }
2469 break;
b779e29e
EI
2470 case EXCP_DEBUG:
2471 {
2472 int sig;
2473
2474 sig = gdb_handlesig (env, TARGET_SIGTRAP);
2475 if (sig)
2476 {
2477 info.si_signo = sig;
2478 info.si_errno = 0;
2479 info.si_code = TARGET_TRAP_BRKPT;
2480 queue_signal(env, info.si_signo, &info);
2481 }
2482 }
2483 break;
2484 default:
2485 printf ("Unhandled trap: 0x%x\n", trapnr);
2486 cpu_dump_state(env, stderr, fprintf, 0);
2487 exit (1);
2488 }
2489 process_pending_signals (env);
2490 }
2491}
2492#endif
2493
e6e5906b
PB
2494#ifdef TARGET_M68K
2495
2496void cpu_loop(CPUM68KState *env)
2497{
2498 int trapnr;
2499 unsigned int n;
c227f099 2500 target_siginfo_t info;
e6e5906b 2501 TaskState *ts = env->opaque;
3b46e624 2502
e6e5906b
PB
2503 for(;;) {
2504 trapnr = cpu_m68k_exec(env);
2505 switch(trapnr) {
2506 case EXCP_ILLEGAL:
2507 {
2508 if (ts->sim_syscalls) {
2509 uint16_t nr;
2510 nr = lduw(env->pc + 2);
2511 env->pc += 4;
2512 do_m68k_simcall(env, nr);
2513 } else {
2514 goto do_sigill;
2515 }
2516 }
2517 break;
a87295e8 2518 case EXCP_HALT_INSN:
e6e5906b 2519 /* Semihosing syscall. */
a87295e8 2520 env->pc += 4;
e6e5906b
PB
2521 do_m68k_semihosting(env, env->dregs[0]);
2522 break;
2523 case EXCP_LINEA:
2524 case EXCP_LINEF:
2525 case EXCP_UNSUPPORTED:
2526 do_sigill:
2527 info.si_signo = SIGILL;
2528 info.si_errno = 0;
2529 info.si_code = TARGET_ILL_ILLOPN;
2530 info._sifields._sigfault._addr = env->pc;
624f7979 2531 queue_signal(env, info.si_signo, &info);
e6e5906b
PB
2532 break;
2533 case EXCP_TRAP0:
2534 {
2535 ts->sim_syscalls = 0;
2536 n = env->dregs[0];
2537 env->pc += 2;
5fafdf24
TS
2538 env->dregs[0] = do_syscall(env,
2539 n,
e6e5906b
PB
2540 env->dregs[1],
2541 env->dregs[2],
2542 env->dregs[3],
2543 env->dregs[4],
2544 env->dregs[5],
5945cfcb
PM
2545 env->aregs[0],
2546 0, 0);
e6e5906b
PB
2547 }
2548 break;
2549 case EXCP_INTERRUPT:
2550 /* just indicate that signals should be handled asap */
2551 break;
2552 case EXCP_ACCESS:
2553 {
2554 info.si_signo = SIGSEGV;
2555 info.si_errno = 0;
2556 /* XXX: check env->error_code */
2557 info.si_code = TARGET_SEGV_MAPERR;
2558 info._sifields._sigfault._addr = env->mmu.ar;
624f7979 2559 queue_signal(env, info.si_signo, &info);
e6e5906b
PB
2560 }
2561 break;
2562 case EXCP_DEBUG:
2563 {
2564 int sig;
2565
2566 sig = gdb_handlesig (env, TARGET_SIGTRAP);
2567 if (sig)
2568 {
2569 info.si_signo = sig;
2570 info.si_errno = 0;
2571 info.si_code = TARGET_TRAP_BRKPT;
624f7979 2572 queue_signal(env, info.si_signo, &info);
e6e5906b
PB
2573 }
2574 }
2575 break;
2576 default:
5fafdf24 2577 fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
e6e5906b
PB
2578 trapnr);
2579 cpu_dump_state(env, stderr, fprintf, 0);
2580 abort();
2581 }
2582 process_pending_signals(env);
2583 }
2584}
2585#endif /* TARGET_M68K */
2586
7a3148a9 2587#ifdef TARGET_ALPHA
6910b8f6
RH
2588static void do_store_exclusive(CPUAlphaState *env, int reg, int quad)
2589{
2590 target_ulong addr, val, tmp;
2591 target_siginfo_t info;
2592 int ret = 0;
2593
2594 addr = env->lock_addr;
2595 tmp = env->lock_st_addr;
2596 env->lock_addr = -1;
2597 env->lock_st_addr = 0;
2598
2599 start_exclusive();
2600 mmap_lock();
2601
2602 if (addr == tmp) {
2603 if (quad ? get_user_s64(val, addr) : get_user_s32(val, addr)) {
2604 goto do_sigsegv;
2605 }
2606
2607 if (val == env->lock_value) {
2608 tmp = env->ir[reg];
2609 if (quad ? put_user_u64(tmp, addr) : put_user_u32(tmp, addr)) {
2610 goto do_sigsegv;
2611 }
2612 ret = 1;
2613 }
2614 }
2615 env->ir[reg] = ret;
2616 env->pc += 4;
2617
2618 mmap_unlock();
2619 end_exclusive();
2620 return;
2621
2622 do_sigsegv:
2623 mmap_unlock();
2624 end_exclusive();
2625
2626 info.si_signo = TARGET_SIGSEGV;
2627 info.si_errno = 0;
2628 info.si_code = TARGET_SEGV_MAPERR;
2629 info._sifields._sigfault._addr = addr;
2630 queue_signal(env, TARGET_SIGSEGV, &info);
2631}
2632
7a3148a9
JM
2633void cpu_loop (CPUState *env)
2634{
e96efcfc 2635 int trapnr;
c227f099 2636 target_siginfo_t info;
6049f4f8 2637 abi_long sysret;
3b46e624 2638
7a3148a9
JM
2639 while (1) {
2640 trapnr = cpu_alpha_exec (env);
3b46e624 2641
ac316ca4
RH
2642 /* All of the traps imply a transition through PALcode, which
2643 implies an REI instruction has been executed. Which means
2644 that the intr_flag should be cleared. */
2645 env->intr_flag = 0;
2646
7a3148a9
JM
2647 switch (trapnr) {
2648 case EXCP_RESET:
2649 fprintf(stderr, "Reset requested. Exit\n");
2650 exit(1);
2651 break;
2652 case EXCP_MCHK:
2653 fprintf(stderr, "Machine check exception. Exit\n");
2654 exit(1);
2655 break;
07b6c13b
RH
2656 case EXCP_SMP_INTERRUPT:
2657 case EXCP_CLK_INTERRUPT:
2658 case EXCP_DEV_INTERRUPT:
5fafdf24 2659 fprintf(stderr, "External interrupt. Exit\n");
7a3148a9
JM
2660 exit(1);
2661 break;
07b6c13b 2662 case EXCP_MMFAULT:
6910b8f6 2663 env->lock_addr = -1;
6049f4f8
RH
2664 info.si_signo = TARGET_SIGSEGV;
2665 info.si_errno = 0;
129d8aa5 2666 info.si_code = (page_get_flags(env->trap_arg0) & PAGE_VALID
0be1d07c 2667 ? TARGET_SEGV_ACCERR : TARGET_SEGV_MAPERR);
129d8aa5 2668 info._sifields._sigfault._addr = env->trap_arg0;
6049f4f8 2669 queue_signal(env, info.si_signo, &info);
7a3148a9 2670 break;
7a3148a9 2671 case EXCP_UNALIGN:
6910b8f6 2672 env->lock_addr = -1;
6049f4f8
RH
2673 info.si_signo = TARGET_SIGBUS;
2674 info.si_errno = 0;
2675 info.si_code = TARGET_BUS_ADRALN;
129d8aa5 2676 info._sifields._sigfault._addr = env->trap_arg0;
6049f4f8 2677 queue_signal(env, info.si_signo, &info);
7a3148a9
JM
2678 break;
2679 case EXCP_OPCDEC:
6049f4f8 2680 do_sigill:
6910b8f6 2681 env->lock_addr = -1;
6049f4f8
RH
2682 info.si_signo = TARGET_SIGILL;
2683 info.si_errno = 0;
2684 info.si_code = TARGET_ILL_ILLOPC;
2685 info._sifields._sigfault._addr = env->pc;
2686 queue_signal(env, info.si_signo, &info);
7a3148a9 2687 break;
07b6c13b
RH
2688 case EXCP_ARITH:
2689 env->lock_addr = -1;
2690 info.si_signo = TARGET_SIGFPE;
2691 info.si_errno = 0;
2692 info.si_code = TARGET_FPE_FLTINV;
2693 info._sifields._sigfault._addr = env->pc;
2694 queue_signal(env, info.si_signo, &info);
2695 break;
7a3148a9 2696 case EXCP_FEN:
6049f4f8 2697 /* No-op. Linux simply re-enables the FPU. */
7a3148a9 2698 break;
07b6c13b 2699 case EXCP_CALL_PAL:
6910b8f6 2700 env->lock_addr = -1;
07b6c13b 2701 switch (env->error_code) {
6049f4f8
RH
2702 case 0x80:
2703 /* BPT */
2704 info.si_signo = TARGET_SIGTRAP;
2705 info.si_errno = 0;
2706 info.si_code = TARGET_TRAP_BRKPT;
2707 info._sifields._sigfault._addr = env->pc;
2708 queue_signal(env, info.si_signo, &info);
2709 break;
2710 case 0x81:
2711 /* BUGCHK */
2712 info.si_signo = TARGET_SIGTRAP;
2713 info.si_errno = 0;
2714 info.si_code = 0;
2715 info._sifields._sigfault._addr = env->pc;
2716 queue_signal(env, info.si_signo, &info);
2717 break;
2718 case 0x83:
2719 /* CALLSYS */
2720 trapnr = env->ir[IR_V0];
2721 sysret = do_syscall(env, trapnr,
2722 env->ir[IR_A0], env->ir[IR_A1],
2723 env->ir[IR_A2], env->ir[IR_A3],
5945cfcb
PM
2724 env->ir[IR_A4], env->ir[IR_A5],
2725 0, 0);
a5b3b13b
RH
2726 if (trapnr == TARGET_NR_sigreturn
2727 || trapnr == TARGET_NR_rt_sigreturn) {
2728 break;
2729 }
2730 /* Syscall writes 0 to V0 to bypass error check, similar
2731 to how this is handled internal to Linux kernel. */
2732 if (env->ir[IR_V0] == 0) {
2733 env->ir[IR_V0] = sysret;
2734 } else {
6049f4f8
RH
2735 env->ir[IR_V0] = (sysret < 0 ? -sysret : sysret);
2736 env->ir[IR_A3] = (sysret < 0);
2737 }
2738 break;
2739 case 0x86:
2740 /* IMB */
2741 /* ??? We can probably elide the code using page_unprotect
2742 that is checking for self-modifying code. Instead we
2743 could simply call tb_flush here. Until we work out the
2744 changes required to turn off the extra write protection,
2745 this can be a no-op. */
2746 break;
2747 case 0x9E:
2748 /* RDUNIQUE */
2749 /* Handled in the translator for usermode. */
2750 abort();
2751 case 0x9F:
2752 /* WRUNIQUE */
2753 /* Handled in the translator for usermode. */
2754 abort();
2755 case 0xAA:
2756 /* GENTRAP */
2757 info.si_signo = TARGET_SIGFPE;
2758 switch (env->ir[IR_A0]) {
2759 case TARGET_GEN_INTOVF:
2760 info.si_code = TARGET_FPE_INTOVF;
2761 break;
2762 case TARGET_GEN_INTDIV:
2763 info.si_code = TARGET_FPE_INTDIV;
2764 break;
2765 case TARGET_GEN_FLTOVF:
2766 info.si_code = TARGET_FPE_FLTOVF;
2767 break;
2768 case TARGET_GEN_FLTUND:
2769 info.si_code = TARGET_FPE_FLTUND;
2770 break;
2771 case TARGET_GEN_FLTINV:
2772 info.si_code = TARGET_FPE_FLTINV;
2773 break;
2774 case TARGET_GEN_FLTINE:
2775 info.si_code = TARGET_FPE_FLTRES;
2776 break;
2777 case TARGET_GEN_ROPRAND:
2778 info.si_code = 0;
2779 break;
2780 default:
2781 info.si_signo = TARGET_SIGTRAP;
2782 info.si_code = 0;
2783 break;
2784 }
2785 info.si_errno = 0;
2786 info._sifields._sigfault._addr = env->pc;
2787 queue_signal(env, info.si_signo, &info);
2788 break;
2789 default:
2790 goto do_sigill;
2791 }
7a3148a9 2792 break;
7a3148a9 2793 case EXCP_DEBUG:
6049f4f8
RH
2794 info.si_signo = gdb_handlesig (env, TARGET_SIGTRAP);
2795 if (info.si_signo) {
6910b8f6 2796 env->lock_addr = -1;
6049f4f8
RH
2797 info.si_errno = 0;
2798 info.si_code = TARGET_TRAP_BRKPT;
2799 queue_signal(env, info.si_signo, &info);
7a3148a9
JM
2800 }
2801 break;
6910b8f6
RH
2802 case EXCP_STL_C:
2803 case EXCP_STQ_C:
2804 do_store_exclusive(env, env->error_code, trapnr - EXCP_STL_C);
2805 break;
7a3148a9
JM
2806 default:
2807 printf ("Unhandled trap: 0x%x\n", trapnr);
2808 cpu_dump_state(env, stderr, fprintf, 0);
2809 exit (1);
2810 }
2811 process_pending_signals (env);
2812 }
2813}
2814#endif /* TARGET_ALPHA */
2815
a4c075f1
UH
2816#ifdef TARGET_S390X
2817void cpu_loop(CPUS390XState *env)
2818{
2819 int trapnr;
2820 target_siginfo_t info;
2821
2822 while (1) {
2823 trapnr = cpu_s390x_exec (env);
2824
2825 switch (trapnr) {
2826 case EXCP_INTERRUPT:
2827 /* just indicate that signals should be handled asap */
2828 break;
2829 case EXCP_DEBUG:
2830 {
2831 int sig;
2832
2833 sig = gdb_handlesig (env, TARGET_SIGTRAP);
2834 if (sig) {
2835 info.si_signo = sig;
2836 info.si_errno = 0;
2837 info.si_code = TARGET_TRAP_BRKPT;
2838 queue_signal(env, info.si_signo, &info);
2839 }
2840 }
2841 break;
2842 case EXCP_SVC:
2843 {
2844 int n = env->int_svc_code;
2845 if (!n) {
2846 /* syscalls > 255 */
2847 n = env->regs[1];
2848 }
2849 env->psw.addr += env->int_svc_ilc;
2850 env->regs[2] = do_syscall(env, n,
2851 env->regs[2],
2852 env->regs[3],
2853 env->regs[4],
2854 env->regs[5],
2855 env->regs[6],
5945cfcb
PM
2856 env->regs[7],
2857 0, 0);
a4c075f1
UH
2858 }
2859 break;
2860 case EXCP_ADDR:
2861 {
2862 info.si_signo = SIGSEGV;
2863 info.si_errno = 0;
2864 /* XXX: check env->error_code */
2865 info.si_code = TARGET_SEGV_MAPERR;
2866 info._sifields._sigfault._addr = env->__excp_addr;
2867 queue_signal(env, info.si_signo, &info);
2868 }
2869 break;
2870 case EXCP_SPEC:
2871 {
2872 fprintf(stderr,"specification exception insn 0x%08x%04x\n", ldl(env->psw.addr), lduw(env->psw.addr + 4));
2873 info.si_signo = SIGILL;
2874 info.si_errno = 0;
2875 info.si_code = TARGET_ILL_ILLOPC;
2876 info._sifields._sigfault._addr = env->__excp_addr;
2877 queue_signal(env, info.si_signo, &info);
2878 }
2879 break;
2880 default:
2881 printf ("Unhandled trap: 0x%x\n", trapnr);
2882 cpu_dump_state(env, stderr, fprintf, 0);
2883 exit (1);
2884 }
2885 process_pending_signals (env);
2886 }
2887}
2888
2889#endif /* TARGET_S390X */
2890
d5975363 2891THREAD CPUState *thread_env;
59faf6d6 2892
edf8e2af
MW
2893void task_settid(TaskState *ts)
2894{
2895 if (ts->ts_tid == 0) {
2f7bb878 2896#ifdef CONFIG_USE_NPTL
edf8e2af
MW
2897 ts->ts_tid = (pid_t)syscall(SYS_gettid);
2898#else
2899 /* when no threads are used, tid becomes pid */
2900 ts->ts_tid = getpid();
2901#endif
2902 }
2903}
2904
2905void stop_all_tasks(void)
2906{
2907 /*
2908 * We trust that when using NPTL, start_exclusive()
2909 * handles thread stopping correctly.
2910 */
2911 start_exclusive();
2912}
2913
c3a92833 2914/* Assumes contents are already zeroed. */
624f7979
PB
2915void init_task_state(TaskState *ts)
2916{
2917 int i;
2918
624f7979
PB
2919 ts->used = 1;
2920 ts->first_free = ts->sigqueue_table;
2921 for (i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++) {
2922 ts->sigqueue_table[i].next = &ts->sigqueue_table[i + 1];
2923 }
2924 ts->sigqueue_table[i].next = NULL;
2925}
fc9c5412
JS
2926
2927static void handle_arg_help(const char *arg)
2928{
2929 usage();
2930}
2931
2932static void handle_arg_log(const char *arg)
2933{
2934 int mask;
2935 const CPULogItem *item;
2936
2937 mask = cpu_str_to_log_mask(arg);
2938 if (!mask) {
2939 printf("Log items (comma separated):\n");
2940 for (item = cpu_log_items; item->mask != 0; item++) {
2941 printf("%-10s %s\n", item->name, item->help);
2942 }
2943 exit(1);
2944 }
2945 cpu_set_log(mask);
2946}
2947
2948static void handle_arg_set_env(const char *arg)
2949{
2950 char *r, *p, *token;
2951 r = p = strdup(arg);
2952 while ((token = strsep(&p, ",")) != NULL) {
2953 if (envlist_setenv(envlist, token) != 0) {
2954 usage();
2955 }
2956 }
2957 free(r);
2958}
2959
2960static void handle_arg_unset_env(const char *arg)
2961{
2962 char *r, *p, *token;
2963 r = p = strdup(arg);
2964 while ((token = strsep(&p, ",")) != NULL) {
2965 if (envlist_unsetenv(envlist, token) != 0) {
2966 usage();
2967 }
2968 }
2969 free(r);
2970}
2971
2972static void handle_arg_argv0(const char *arg)
2973{
2974 argv0 = strdup(arg);
2975}
2976
2977static void handle_arg_stack_size(const char *arg)
2978{
2979 char *p;
2980 guest_stack_size = strtoul(arg, &p, 0);
2981 if (guest_stack_size == 0) {
2982 usage();
2983 }
2984
2985 if (*p == 'M') {
2986 guest_stack_size *= 1024 * 1024;
2987 } else if (*p == 'k' || *p == 'K') {
2988 guest_stack_size *= 1024;
2989 }
2990}
2991
2992static void handle_arg_ld_prefix(const char *arg)
2993{
2994 interp_prefix = strdup(arg);
2995}
2996
2997static void handle_arg_pagesize(const char *arg)
2998{
2999 qemu_host_page_size = atoi(arg);
3000 if (qemu_host_page_size == 0 ||
3001 (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
3002 fprintf(stderr, "page size must be a power of two\n");
3003 exit(1);
3004 }
3005}
3006
3007static void handle_arg_gdb(const char *arg)
3008{
3009 gdbstub_port = atoi(arg);
3010}
3011
3012static void handle_arg_uname(const char *arg)
3013{
3014 qemu_uname_release = strdup(arg);
3015}
3016
3017static void handle_arg_cpu(const char *arg)
3018{
3019 cpu_model = strdup(arg);
3020 if (cpu_model == NULL || strcmp(cpu_model, "?") == 0) {
3021 /* XXX: implement xxx_cpu_list for targets that still miss it */
3022#if defined(cpu_list_id)
3023 cpu_list_id(stdout, &fprintf, "");
3024#elif defined(cpu_list)
3025 cpu_list(stdout, &fprintf); /* deprecated */
3026#endif
3027 exit(1);
3028 }
3029}
3030
3031#if defined(CONFIG_USE_GUEST_BASE)
3032static void handle_arg_guest_base(const char *arg)
3033{
3034 guest_base = strtol(arg, NULL, 0);
3035 have_guest_base = 1;
3036}
3037
3038static void handle_arg_reserved_va(const char *arg)
3039{
3040 char *p;
3041 int shift = 0;
3042 reserved_va = strtoul(arg, &p, 0);
3043 switch (*p) {
3044 case 'k':
3045 case 'K':
3046 shift = 10;
3047 break;
3048 case 'M':
3049 shift = 20;
3050 break;
3051 case 'G':
3052 shift = 30;
3053 break;
3054 }
3055 if (shift) {
3056 unsigned long unshifted = reserved_va;
3057 p++;
3058 reserved_va <<= shift;
3059 if (((reserved_va >> shift) != unshifted)
3060#if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS
3061 || (reserved_va > (1ul << TARGET_VIRT_ADDR_SPACE_BITS))
3062#endif
3063 ) {
3064 fprintf(stderr, "Reserved virtual address too big\n");
3065 exit(1);
3066 }
3067 }
3068 if (*p) {
3069 fprintf(stderr, "Unrecognised -R size suffix '%s'\n", p);
3070 exit(1);
3071 }
3072}
3073#endif
3074
3075static void handle_arg_singlestep(const char *arg)
3076{
3077 singlestep = 1;
3078}
3079
3080static void handle_arg_strace(const char *arg)
3081{
3082 do_strace = 1;
3083}
3084
3085static void handle_arg_version(const char *arg)
3086{
3087 printf("qemu-" TARGET_ARCH " version " QEMU_VERSION QEMU_PKGVERSION
3088 ", Copyright (c) 2003-2008 Fabrice Bellard\n");
1386d4c0 3089 exit(0);
fc9c5412
JS
3090}
3091
3092struct qemu_argument {
3093 const char *argv;
3094 const char *env;
3095 bool has_arg;
3096 void (*handle_opt)(const char *arg);
3097 const char *example;
3098 const char *help;
3099};
3100
3101struct qemu_argument arg_table[] = {
3102 {"h", "", false, handle_arg_help,
3103 "", "print this help"},
3104 {"g", "QEMU_GDB", true, handle_arg_gdb,
3105 "port", "wait gdb connection to 'port'"},
3106 {"L", "QEMU_LD_PREFIX", true, handle_arg_ld_prefix,
3107 "path", "set the elf interpreter prefix to 'path'"},
3108 {"s", "QEMU_STACK_SIZE", true, handle_arg_stack_size,
3109 "size", "set the stack size to 'size' bytes"},
3110 {"cpu", "QEMU_CPU", true, handle_arg_cpu,
3111 "model", "select CPU (-cpu ? for list)"},
3112 {"E", "QEMU_SET_ENV", true, handle_arg_set_env,
3113 "var=value", "sets targets environment variable (see below)"},
3114 {"U", "QEMU_UNSET_ENV", true, handle_arg_unset_env,
3115 "var", "unsets targets environment variable (see below)"},
3116 {"0", "QEMU_ARGV0", true, handle_arg_argv0,
3117 "argv0", "forces target process argv[0] to be 'argv0'"},
3118 {"r", "QEMU_UNAME", true, handle_arg_uname,
3119 "uname", "set qemu uname release string to 'uname'"},
3120#if defined(CONFIG_USE_GUEST_BASE)
3121 {"B", "QEMU_GUEST_BASE", true, handle_arg_guest_base,
3122 "address", "set guest_base address to 'address'"},
3123 {"R", "QEMU_RESERVED_VA", true, handle_arg_reserved_va,
3124 "size", "reserve 'size' bytes for guest virtual address space"},
3125#endif
3126 {"d", "QEMU_LOG", true, handle_arg_log,
3127 "options", "activate log"},
3128 {"p", "QEMU_PAGESIZE", true, handle_arg_pagesize,
3129 "pagesize", "set the host page size to 'pagesize'"},
3130 {"singlestep", "QEMU_SINGLESTEP", false, handle_arg_singlestep,
3131 "", "run in singlestep mode"},
3132 {"strace", "QEMU_STRACE", false, handle_arg_strace,
3133 "", "log system calls"},
3134 {"version", "QEMU_VERSION", false, handle_arg_version,
1386d4c0 3135 "", "display version information and exit"},
fc9c5412
JS
3136 {NULL, NULL, false, NULL, NULL, NULL}
3137};
3138
3139static void usage(void)
3140{
3141 struct qemu_argument *arginfo;
3142 int maxarglen;
3143 int maxenvlen;
3144
3145 printf("usage: qemu-" TARGET_ARCH " [options] program [arguments...]\n"
3146 "Linux CPU emulator (compiled for " TARGET_ARCH " emulation)\n"
3147 "\n"
3148 "Options and associated environment variables:\n"
3149 "\n");
3150
3151 maxarglen = maxenvlen = 0;
3152
3153 for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
3154 if (strlen(arginfo->env) > maxenvlen) {
3155 maxenvlen = strlen(arginfo->env);
3156 }
3157 if (strlen(arginfo->argv) > maxarglen) {
3158 maxarglen = strlen(arginfo->argv);
3159 }
3160 }
3161
3162 printf("%-*s%-*sDescription\n", maxarglen+3, "Argument",
3163 maxenvlen+1, "Env-variable");
3164
3165 for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
3166 if (arginfo->has_arg) {
3167 printf("-%s %-*s %-*s %s\n", arginfo->argv,
3168 (int)(maxarglen-strlen(arginfo->argv)), arginfo->example,
3169 maxenvlen, arginfo->env, arginfo->help);
3170 } else {
3171 printf("-%-*s %-*s %s\n", maxarglen+1, arginfo->argv,
3172 maxenvlen, arginfo->env,
3173 arginfo->help);
3174 }
3175 }
3176
3177 printf("\n"
3178 "Defaults:\n"
3179 "QEMU_LD_PREFIX = %s\n"
3180 "QEMU_STACK_SIZE = %ld byte\n"
3181 "QEMU_LOG = %s\n",
3182 interp_prefix,
3183 guest_stack_size,
3184 DEBUG_LOGFILE);
3185
3186 printf("\n"
3187 "You can use -E and -U options or the QEMU_SET_ENV and\n"
3188 "QEMU_UNSET_ENV environment variables to set and unset\n"
3189 "environment variables for the target process.\n"
3190 "It is possible to provide several variables by separating them\n"
3191 "by commas in getsubopt(3) style. Additionally it is possible to\n"
3192 "provide the -E and -U options multiple times.\n"
3193 "The following lines are equivalent:\n"
3194 " -E var1=val2 -E var2=val2 -U LD_PRELOAD -U LD_DEBUG\n"
3195 " -E var1=val2,var2=val2 -U LD_PRELOAD,LD_DEBUG\n"
3196 " QEMU_SET_ENV=var1=val2,var2=val2 QEMU_UNSET_ENV=LD_PRELOAD,LD_DEBUG\n"
3197 "Note that if you provide several changes to a single variable\n"
3198 "the last change will stay in effect.\n");
3199
3200 exit(1);
3201}
3202
3203static int parse_args(int argc, char **argv)
3204{
3205 const char *r;
3206 int optind;
3207 struct qemu_argument *arginfo;
3208
3209 for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
3210 if (arginfo->env == NULL) {
3211 continue;
3212 }
3213
3214 r = getenv(arginfo->env);
3215 if (r != NULL) {
3216 arginfo->handle_opt(r);
3217 }
3218 }
3219
3220 optind = 1;
3221 for (;;) {
3222 if (optind >= argc) {
3223 break;
3224 }
3225 r = argv[optind];
3226 if (r[0] != '-') {
3227 break;
3228 }
3229 optind++;
3230 r++;
3231 if (!strcmp(r, "-")) {
3232 break;
3233 }
3234
3235 for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
3236 if (!strcmp(r, arginfo->argv)) {
fc9c5412 3237 if (arginfo->has_arg) {
1386d4c0
PM
3238 if (optind >= argc) {
3239 usage();
3240 }
3241 arginfo->handle_opt(argv[optind]);
fc9c5412 3242 optind++;
1386d4c0
PM
3243 } else {
3244 arginfo->handle_opt(NULL);
fc9c5412 3245 }
fc9c5412
JS
3246 break;
3247 }
3248 }
3249
3250 /* no option matched the current argv */
3251 if (arginfo->handle_opt == NULL) {
3252 usage();
3253 }
3254 }
3255
3256 if (optind >= argc) {
3257 usage();
3258 }
3259
3260 filename = argv[optind];
3261 exec_path = argv[optind];
3262
3263 return optind;
3264}
3265
902b3d5c 3266int main(int argc, char **argv, char **envp)
31e31b8a 3267{
c235d738 3268 const char *log_file = DEBUG_LOGFILE;
01ffc75b 3269 struct target_pt_regs regs1, *regs = &regs1;
31e31b8a 3270 struct image_info info1, *info = &info1;
edf8e2af 3271 struct linux_binprm bprm;
48e15fc2 3272 TaskState *ts;
b346ff46 3273 CPUState *env;
586314f2 3274 int optind;
04a6dfeb 3275 char **target_environ, **wrk;
7d8cec95
AJ
3276 char **target_argv;
3277 int target_argc;
7d8cec95 3278 int i;
fd4d81dd 3279 int ret;
b12b6a18 3280
902b3d5c 3281 qemu_cache_utils_init(envp);
3282
04a6dfeb
AJ
3283 if ((envlist = envlist_create()) == NULL) {
3284 (void) fprintf(stderr, "Unable to allocate envlist\n");
3285 exit(1);
3286 }
3287
3288 /* add current environment into the list */
3289 for (wrk = environ; *wrk != NULL; wrk++) {
3290 (void) envlist_setenv(envlist, *wrk);
3291 }
3292
703e0e89
RH
3293 /* Read the stack limit from the kernel. If it's "unlimited",
3294 then we can do little else besides use the default. */
3295 {
3296 struct rlimit lim;
3297 if (getrlimit(RLIMIT_STACK, &lim) == 0
81bbe906
TY
3298 && lim.rlim_cur != RLIM_INFINITY
3299 && lim.rlim_cur == (target_long)lim.rlim_cur) {
703e0e89
RH
3300 guest_stack_size = lim.rlim_cur;
3301 }
3302 }
3303
b1f9be31 3304 cpu_model = NULL;
b5ec5ce0 3305#if defined(cpudef_setup)
3306 cpudef_setup(); /* parse cpu definitions in target config file (TBD) */
3307#endif
3308
c235d738
MF
3309 /* init debug */
3310 cpu_set_log_filename(log_file);
fc9c5412 3311 optind = parse_args(argc, argv);
586314f2 3312
31e31b8a 3313 /* Zero out regs */
01ffc75b 3314 memset(regs, 0, sizeof(struct target_pt_regs));
31e31b8a
FB
3315
3316 /* Zero out image_info */
3317 memset(info, 0, sizeof(struct image_info));
3318
edf8e2af
MW
3319 memset(&bprm, 0, sizeof (bprm));
3320
74cd30b8
FB
3321 /* Scan interp_prefix dir for replacement files. */
3322 init_paths(interp_prefix);
3323
46027c07 3324 if (cpu_model == NULL) {
aaed909a 3325#if defined(TARGET_I386)
46027c07
FB
3326#ifdef TARGET_X86_64
3327 cpu_model = "qemu64";
3328#else
3329 cpu_model = "qemu32";
3330#endif
aaed909a 3331#elif defined(TARGET_ARM)
088ab16c 3332 cpu_model = "any";
d2fbca94
GX
3333#elif defined(TARGET_UNICORE32)
3334 cpu_model = "any";
aaed909a
FB
3335#elif defined(TARGET_M68K)
3336 cpu_model = "any";
3337#elif defined(TARGET_SPARC)
3338#ifdef TARGET_SPARC64
3339 cpu_model = "TI UltraSparc II";
3340#else
3341 cpu_model = "Fujitsu MB86904";
46027c07 3342#endif
aaed909a
FB
3343#elif defined(TARGET_MIPS)
3344#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64)
3345 cpu_model = "20Kc";
3346#else
3347 cpu_model = "24Kf";
3348#endif
3349#elif defined(TARGET_PPC)
7ded4f52 3350#ifdef TARGET_PPC64
f7177937 3351 cpu_model = "970fx";
7ded4f52 3352#else
aaed909a 3353 cpu_model = "750";
7ded4f52 3354#endif
aaed909a
FB
3355#else
3356 cpu_model = "any";
3357#endif
3358 }
d5ab9713
JK
3359 tcg_exec_init(0);
3360 cpu_exec_init_all();
83fb7adf
FB
3361 /* NOTE: we need to init the CPU at this stage to get
3362 qemu_host_page_size */
aaed909a
FB
3363 env = cpu_init(cpu_model);
3364 if (!env) {
3365 fprintf(stderr, "Unable to find CPU definition\n");
3366 exit(1);
3367 }
b55a37c9
BS
3368#if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC)
3369 cpu_reset(env);
3370#endif
3371
d5975363 3372 thread_env = env;
3b46e624 3373
b6741956
FB
3374 if (getenv("QEMU_STRACE")) {
3375 do_strace = 1;
b92c47c1
TS
3376 }
3377
04a6dfeb
AJ
3378 target_environ = envlist_to_environ(envlist, NULL);
3379 envlist_free(envlist);
b12b6a18 3380
379f6698
PB
3381#if defined(CONFIG_USE_GUEST_BASE)
3382 /*
3383 * Now that page sizes are configured in cpu_init() we can do
3384 * proper page alignment for guest_base.
3385 */
3386 guest_base = HOST_PAGE_ALIGN(guest_base);
68a1c816
PB
3387
3388 if (reserved_va) {
3389 void *p;
3390 int flags;
3391
3392 flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE;
3393 if (have_guest_base) {
3394 flags |= MAP_FIXED;
3395 }
3396 p = mmap((void *)guest_base, reserved_va, PROT_NONE, flags, -1, 0);
3397 if (p == MAP_FAILED) {
3398 fprintf(stderr, "Unable to reserve guest address space\n");
3399 exit(1);
3400 }
3401 guest_base = (unsigned long)p;
3402 /* Make sure the address is properly aligned. */
3403 if (guest_base & ~qemu_host_page_mask) {
3404 munmap(p, reserved_va);
3405 p = mmap((void *)guest_base, reserved_va + qemu_host_page_size,
3406 PROT_NONE, flags, -1, 0);
3407 if (p == MAP_FAILED) {
3408 fprintf(stderr, "Unable to reserve guest address space\n");
3409 exit(1);
3410 }
3411 guest_base = HOST_PAGE_ALIGN((unsigned long)p);
3412 }
3413 qemu_log("Reserved 0x%lx bytes of guest address space\n", reserved_va);
3414 }
97cc7560
DDAG
3415
3416 if (reserved_va || have_guest_base) {
3417 if (!guest_validate_base(guest_base)) {
3418 fprintf(stderr, "Guest base/Reserved VA rejected by guest code\n");
3419 exit(1);
3420 }
3421 }
14f24e14 3422#endif /* CONFIG_USE_GUEST_BASE */
379f6698
PB
3423
3424 /*
3425 * Read in mmap_min_addr kernel parameter. This value is used
3426 * When loading the ELF image to determine whether guest_base
14f24e14 3427 * is needed. It is also used in mmap_find_vma.
379f6698 3428 */
14f24e14 3429 {
379f6698
PB
3430 FILE *fp;
3431
3432 if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) {
3433 unsigned long tmp;
3434 if (fscanf(fp, "%lu", &tmp) == 1) {
3435 mmap_min_addr = tmp;
3436 qemu_log("host mmap_min_addr=0x%lx\n", mmap_min_addr);
3437 }
3438 fclose(fp);
3439 }
3440 }
379f6698 3441
7d8cec95
AJ
3442 /*
3443 * Prepare copy of argv vector for target.
3444 */
3445 target_argc = argc - optind;
3446 target_argv = calloc(target_argc + 1, sizeof (char *));
3447 if (target_argv == NULL) {
3448 (void) fprintf(stderr, "Unable to allocate memory for target_argv\n");
3449 exit(1);
3450 }
3451
3452 /*
3453 * If argv0 is specified (using '-0' switch) we replace
3454 * argv[0] pointer with the given one.
3455 */
3456 i = 0;
3457 if (argv0 != NULL) {
3458 target_argv[i++] = strdup(argv0);
3459 }
3460 for (; i < target_argc; i++) {
3461 target_argv[i] = strdup(argv[optind + i]);
3462 }
3463 target_argv[target_argc] = NULL;
3464
7267c094 3465 ts = g_malloc0 (sizeof(TaskState));
edf8e2af
MW
3466 init_task_state(ts);
3467 /* build Task State */
3468 ts->info = info;
3469 ts->bprm = &bprm;
3470 env->opaque = ts;
3471 task_settid(ts);
3472
fd4d81dd
AP
3473 ret = loader_exec(filename, target_argv, target_environ, regs,
3474 info, &bprm);
3475 if (ret != 0) {
3476 printf("Error %d while loading %s\n", ret, filename);
b12b6a18
TS
3477 _exit(1);
3478 }
3479
7d8cec95
AJ
3480 for (i = 0; i < target_argc; i++) {
3481 free(target_argv[i]);
3482 }
3483 free(target_argv);
3484
b12b6a18
TS
3485 for (wrk = target_environ; *wrk; wrk++) {
3486 free(*wrk);
31e31b8a 3487 }
3b46e624 3488
b12b6a18
TS
3489 free(target_environ);
3490
2e77eac6 3491 if (qemu_log_enabled()) {
379f6698
PB
3492#if defined(CONFIG_USE_GUEST_BASE)
3493 qemu_log("guest_base 0x%lx\n", guest_base);
3494#endif
2e77eac6
BS
3495 log_page_dump();
3496
3497 qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk);
3498 qemu_log("end_code 0x" TARGET_ABI_FMT_lx "\n", info->end_code);
3499 qemu_log("start_code 0x" TARGET_ABI_FMT_lx "\n",
3500 info->start_code);
3501 qemu_log("start_data 0x" TARGET_ABI_FMT_lx "\n",
3502 info->start_data);
3503 qemu_log("end_data 0x" TARGET_ABI_FMT_lx "\n", info->end_data);
3504 qemu_log("start_stack 0x" TARGET_ABI_FMT_lx "\n",
3505 info->start_stack);
3506 qemu_log("brk 0x" TARGET_ABI_FMT_lx "\n", info->brk);
3507 qemu_log("entry 0x" TARGET_ABI_FMT_lx "\n", info->entry);
3508 }
31e31b8a 3509
53a5960a 3510 target_set_brk(info->brk);
31e31b8a 3511 syscall_init();
66fb9763 3512 signal_init();
31e31b8a 3513
9002ec79
RH
3514#if defined(CONFIG_USE_GUEST_BASE)
3515 /* Now that we've loaded the binary, GUEST_BASE is fixed. Delay
3516 generating the prologue until now so that the prologue can take
3517 the real value of GUEST_BASE into account. */
3518 tcg_prologue_init(&tcg_ctx);
3519#endif
3520
b346ff46 3521#if defined(TARGET_I386)
2e255c6b
FB
3522 cpu_x86_set_cpl(env, 3);
3523
3802ce26 3524 env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
1bde465e
FB
3525 env->hflags |= HF_PE_MASK;
3526 if (env->cpuid_features & CPUID_SSE) {
3527 env->cr[4] |= CR4_OSFXSR_MASK;
3528 env->hflags |= HF_OSFXSR_MASK;
3529 }
d2fd1af7 3530#ifndef TARGET_ABI32
4dbc422b
FB
3531 /* enable 64 bit mode if possible */
3532 if (!(env->cpuid_ext2_features & CPUID_EXT2_LM)) {
3533 fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n");
3534 exit(1);
3535 }
d2fd1af7 3536 env->cr[4] |= CR4_PAE_MASK;
4dbc422b 3537 env->efer |= MSR_EFER_LMA | MSR_EFER_LME;
d2fd1af7
FB
3538 env->hflags |= HF_LMA_MASK;
3539#endif
1bde465e 3540
415e561f
FB
3541 /* flags setup : we activate the IRQs by default as in user mode */
3542 env->eflags |= IF_MASK;
3b46e624 3543
6dbad63e 3544 /* linux register setup */
d2fd1af7 3545#ifndef TARGET_ABI32
84409ddb
JM
3546 env->regs[R_EAX] = regs->rax;
3547 env->regs[R_EBX] = regs->rbx;
3548 env->regs[R_ECX] = regs->rcx;
3549 env->regs[R_EDX] = regs->rdx;
3550 env->regs[R_ESI] = regs->rsi;
3551 env->regs[R_EDI] = regs->rdi;
3552 env->regs[R_EBP] = regs->rbp;
3553 env->regs[R_ESP] = regs->rsp;
3554 env->eip = regs->rip;
3555#else
0ecfa993
FB
3556 env->regs[R_EAX] = regs->eax;
3557 env->regs[R_EBX] = regs->ebx;
3558 env->regs[R_ECX] = regs->ecx;
3559 env->regs[R_EDX] = regs->edx;
3560 env->regs[R_ESI] = regs->esi;
3561 env->regs[R_EDI] = regs->edi;
3562 env->regs[R_EBP] = regs->ebp;
3563 env->regs[R_ESP] = regs->esp;
dab2ed99 3564 env->eip = regs->eip;
84409ddb 3565#endif
31e31b8a 3566
f4beb510 3567 /* linux interrupt setup */
e441570f
AZ
3568#ifndef TARGET_ABI32
3569 env->idt.limit = 511;
3570#else
3571 env->idt.limit = 255;
3572#endif
3573 env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1),
3574 PROT_READ|PROT_WRITE,
3575 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
3576 idt_table = g2h(env->idt.base);
f4beb510
FB
3577 set_idt(0, 0);
3578 set_idt(1, 0);
3579 set_idt(2, 0);
3580 set_idt(3, 3);
3581 set_idt(4, 3);
ec95da6c 3582 set_idt(5, 0);
f4beb510
FB
3583 set_idt(6, 0);
3584 set_idt(7, 0);
3585 set_idt(8, 0);
3586 set_idt(9, 0);
3587 set_idt(10, 0);
3588 set_idt(11, 0);
3589 set_idt(12, 0);
3590 set_idt(13, 0);
3591 set_idt(14, 0);
3592 set_idt(15, 0);
3593 set_idt(16, 0);
3594 set_idt(17, 0);
3595 set_idt(18, 0);
3596 set_idt(19, 0);
3597 set_idt(0x80, 3);
3598
6dbad63e 3599 /* linux segment setup */
8d18e893
FB
3600 {
3601 uint64_t *gdt_table;
e441570f
AZ
3602 env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES,
3603 PROT_READ|PROT_WRITE,
3604 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
8d18e893 3605 env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1;
e441570f 3606 gdt_table = g2h(env->gdt.base);
d2fd1af7 3607#ifdef TARGET_ABI32
8d18e893
FB
3608 write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
3609 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
3610 (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
d2fd1af7
FB
3611#else
3612 /* 64 bit code segment */
3613 write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
3614 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
3615 DESC_L_MASK |
3616 (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
3617#endif
8d18e893
FB
3618 write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
3619 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
3620 (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
3621 }
6dbad63e 3622 cpu_x86_load_seg(env, R_CS, __USER_CS);
d2fd1af7
FB
3623 cpu_x86_load_seg(env, R_SS, __USER_DS);
3624#ifdef TARGET_ABI32
6dbad63e
FB
3625 cpu_x86_load_seg(env, R_DS, __USER_DS);
3626 cpu_x86_load_seg(env, R_ES, __USER_DS);
6dbad63e
FB
3627 cpu_x86_load_seg(env, R_FS, __USER_DS);
3628 cpu_x86_load_seg(env, R_GS, __USER_DS);
d6eb40f6
TS
3629 /* This hack makes Wine work... */
3630 env->segs[R_FS].selector = 0;
d2fd1af7
FB
3631#else
3632 cpu_x86_load_seg(env, R_DS, 0);
3633 cpu_x86_load_seg(env, R_ES, 0);
3634 cpu_x86_load_seg(env, R_FS, 0);
3635 cpu_x86_load_seg(env, R_GS, 0);
3636#endif
b346ff46
FB
3637#elif defined(TARGET_ARM)
3638 {
3639 int i;
b5ff1b31 3640 cpsr_write(env, regs->uregs[16], 0xffffffff);
b346ff46
FB
3641 for(i = 0; i < 16; i++) {
3642 env->regs[i] = regs->uregs[i];
3643 }
b346ff46 3644 }
d2fbca94
GX
3645#elif defined(TARGET_UNICORE32)
3646 {
3647 int i;
3648 cpu_asr_write(env, regs->uregs[32], 0xffffffff);
3649 for (i = 0; i < 32; i++) {
3650 env->regs[i] = regs->uregs[i];
3651 }
3652 }
93ac68bc 3653#elif defined(TARGET_SPARC)
060366c5
FB
3654 {
3655 int i;
3656 env->pc = regs->pc;
3657 env->npc = regs->npc;
3658 env->y = regs->y;
3659 for(i = 0; i < 8; i++)
3660 env->gregs[i] = regs->u_regs[i];
3661 for(i = 0; i < 8; i++)
3662 env->regwptr[i] = regs->u_regs[i + 8];
3663 }
67867308
FB
3664#elif defined(TARGET_PPC)
3665 {
3666 int i;
3fc6c082 3667
0411a972
JM
3668#if defined(TARGET_PPC64)
3669#if defined(TARGET_ABI32)
3670 env->msr &= ~((target_ulong)1 << MSR_SF);
e85e7c6e 3671#else
0411a972
JM
3672 env->msr |= (target_ulong)1 << MSR_SF;
3673#endif
84409ddb 3674#endif
67867308
FB
3675 env->nip = regs->nip;
3676 for(i = 0; i < 32; i++) {
3677 env->gpr[i] = regs->gpr[i];
3678 }
3679 }
e6e5906b
PB
3680#elif defined(TARGET_M68K)
3681 {
e6e5906b
PB
3682 env->pc = regs->pc;
3683 env->dregs[0] = regs->d0;
3684 env->dregs[1] = regs->d1;
3685 env->dregs[2] = regs->d2;
3686 env->dregs[3] = regs->d3;
3687 env->dregs[4] = regs->d4;
3688 env->dregs[5] = regs->d5;
3689 env->dregs[6] = regs->d6;
3690 env->dregs[7] = regs->d7;
3691 env->aregs[0] = regs->a0;
3692 env->aregs[1] = regs->a1;
3693 env->aregs[2] = regs->a2;
3694 env->aregs[3] = regs->a3;
3695 env->aregs[4] = regs->a4;
3696 env->aregs[5] = regs->a5;
3697 env->aregs[6] = regs->a6;
3698 env->aregs[7] = regs->usp;
3699 env->sr = regs->sr;
3700 ts->sim_syscalls = 1;
3701 }
b779e29e
EI
3702#elif defined(TARGET_MICROBLAZE)
3703 {
3704 env->regs[0] = regs->r0;
3705 env->regs[1] = regs->r1;
3706 env->regs[2] = regs->r2;
3707 env->regs[3] = regs->r3;
3708 env->regs[4] = regs->r4;
3709 env->regs[5] = regs->r5;
3710 env->regs[6] = regs->r6;
3711 env->regs[7] = regs->r7;
3712 env->regs[8] = regs->r8;
3713 env->regs[9] = regs->r9;
3714 env->regs[10] = regs->r10;
3715 env->regs[11] = regs->r11;
3716 env->regs[12] = regs->r12;
3717 env->regs[13] = regs->r13;
3718 env->regs[14] = regs->r14;
3719 env->regs[15] = regs->r15;
3720 env->regs[16] = regs->r16;
3721 env->regs[17] = regs->r17;
3722 env->regs[18] = regs->r18;
3723 env->regs[19] = regs->r19;
3724 env->regs[20] = regs->r20;
3725 env->regs[21] = regs->r21;
3726 env->regs[22] = regs->r22;
3727 env->regs[23] = regs->r23;
3728 env->regs[24] = regs->r24;
3729 env->regs[25] = regs->r25;
3730 env->regs[26] = regs->r26;
3731 env->regs[27] = regs->r27;
3732 env->regs[28] = regs->r28;
3733 env->regs[29] = regs->r29;
3734 env->regs[30] = regs->r30;
3735 env->regs[31] = regs->r31;
3736 env->sregs[SR_PC] = regs->pc;
3737 }
048f6b4d
FB
3738#elif defined(TARGET_MIPS)
3739 {
3740 int i;
3741
3742 for(i = 0; i < 32; i++) {
b5dc7732 3743 env->active_tc.gpr[i] = regs->regs[i];
048f6b4d 3744 }
0fddbbf2
NF
3745 env->active_tc.PC = regs->cp0_epc & ~(target_ulong)1;
3746 if (regs->cp0_epc & 1) {
3747 env->hflags |= MIPS_HFLAG_M16;
3748 }
048f6b4d 3749 }
fdf9b3e8
FB
3750#elif defined(TARGET_SH4)
3751 {
3752 int i;
3753
3754 for(i = 0; i < 16; i++) {
3755 env->gregs[i] = regs->regs[i];
3756 }
3757 env->pc = regs->pc;
3758 }
7a3148a9
JM
3759#elif defined(TARGET_ALPHA)
3760 {
3761 int i;
3762
3763 for(i = 0; i < 28; i++) {
992f48a0 3764 env->ir[i] = ((abi_ulong *)regs)[i];
7a3148a9 3765 }
dad081ee 3766 env->ir[IR_SP] = regs->usp;
7a3148a9 3767 env->pc = regs->pc;
7a3148a9 3768 }
48733d19
TS
3769#elif defined(TARGET_CRIS)
3770 {
3771 env->regs[0] = regs->r0;
3772 env->regs[1] = regs->r1;
3773 env->regs[2] = regs->r2;
3774 env->regs[3] = regs->r3;
3775 env->regs[4] = regs->r4;
3776 env->regs[5] = regs->r5;
3777 env->regs[6] = regs->r6;
3778 env->regs[7] = regs->r7;
3779 env->regs[8] = regs->r8;
3780 env->regs[9] = regs->r9;
3781 env->regs[10] = regs->r10;
3782 env->regs[11] = regs->r11;
3783 env->regs[12] = regs->r12;
3784 env->regs[13] = regs->r13;
3785 env->regs[14] = info->start_stack;
3786 env->regs[15] = regs->acr;
3787 env->pc = regs->erp;
3788 }
a4c075f1
UH
3789#elif defined(TARGET_S390X)
3790 {
3791 int i;
3792 for (i = 0; i < 16; i++) {
3793 env->regs[i] = regs->gprs[i];
3794 }
3795 env->psw.mask = regs->psw.mask;
3796 env->psw.addr = regs->psw.addr;
3797 }
b346ff46
FB
3798#else
3799#error unsupported target CPU
3800#endif
31e31b8a 3801
d2fbca94 3802#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)
a87295e8
PB
3803 ts->stack_base = info->start_stack;
3804 ts->heap_base = info->brk;
3805 /* This will be filled in on the first SYS_HEAPINFO call. */
3806 ts->heap_limit = 0;
3807#endif
3808
74c33bed 3809 if (gdbstub_port) {
ff7a981a
PM
3810 if (gdbserver_start(gdbstub_port) < 0) {
3811 fprintf(stderr, "qemu: could not open gdbserver on port %d\n",
3812 gdbstub_port);
3813 exit(1);
3814 }
1fddef4b
FB
3815 gdb_handlesig(env, 0);
3816 }
1b6b029e
FB
3817 cpu_loop(env);
3818 /* never exits */
31e31b8a
FB
3819 return 0;
3820}