]> git.proxmox.com Git - qemu.git/blame - linux-user/main.c
ppc64-linux-user: Properly interpret the entry function descriptor.
[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
FB
1343 int trapnr;
1344 uint32_t 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 */
1641 cpu_abort(env, "Programable interval timer interrupt "
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 */
1707#if 0
1708 printf("syscall %d 0x%08x 0x%08x 0x%08x 0x%08x\n", env->gpr[0],
1709 env->gpr[3], env->gpr[4], env->gpr[5], env->gpr[6]);
1710#endif
1711 env->crf[0] &= ~0x1;
1712 ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
1713 env->gpr[5], env->gpr[6], env->gpr[7],
5945cfcb 1714 env->gpr[8], 0, 0);
bcd4933a
NF
1715 if (ret == (uint32_t)(-TARGET_QEMU_ESIGRETURN)) {
1716 /* Returning from a successful sigreturn syscall.
1717 Avoid corrupting register state. */
1718 break;
1719 }
e1833e1f
JM
1720 if (ret > (uint32_t)(-515)) {
1721 env->crf[0] |= 0x1;
1722 ret = -ret;
61190b14 1723 }
e1833e1f
JM
1724 env->gpr[3] = ret;
1725#if 0
1726 printf("syscall returned 0x%08x (%d)\n", ret, ret);
1727#endif
1728 break;
56f066bb
NF
1729 case POWERPC_EXCP_STCX:
1730 if (do_store_exclusive(env)) {
1731 info.si_signo = TARGET_SIGSEGV;
1732 info.si_errno = 0;
1733 info.si_code = TARGET_SEGV_MAPERR;
1734 info._sifields._sigfault._addr = env->nip;
1735 queue_signal(env, info.si_signo, &info);
1736 }
1737 break;
71f75756
AJ
1738 case EXCP_DEBUG:
1739 {
1740 int sig;
1741
1742 sig = gdb_handlesig(env, TARGET_SIGTRAP);
1743 if (sig) {
1744 info.si_signo = sig;
1745 info.si_errno = 0;
1746 info.si_code = TARGET_TRAP_BRKPT;
1747 queue_signal(env, info.si_signo, &info);
1748 }
1749 }
1750 break;
56ba31ff
JM
1751 case EXCP_INTERRUPT:
1752 /* just indicate that signals should be handled asap */
1753 break;
e1833e1f
JM
1754 default:
1755 cpu_abort(env, "Unknown exception 0x%d. Aborting\n", trapnr);
1756 break;
67867308
FB
1757 }
1758 process_pending_signals(env);
1759 }
1760}
1761#endif
1762
048f6b4d
FB
1763#ifdef TARGET_MIPS
1764
1765#define MIPS_SYS(name, args) args,
1766
1767static const uint8_t mips_syscall_args[] = {
29fb0f25 1768 MIPS_SYS(sys_syscall , 8) /* 4000 */
048f6b4d
FB
1769 MIPS_SYS(sys_exit , 1)
1770 MIPS_SYS(sys_fork , 0)
1771 MIPS_SYS(sys_read , 3)
1772 MIPS_SYS(sys_write , 3)
1773 MIPS_SYS(sys_open , 3) /* 4005 */
1774 MIPS_SYS(sys_close , 1)
1775 MIPS_SYS(sys_waitpid , 3)
1776 MIPS_SYS(sys_creat , 2)
1777 MIPS_SYS(sys_link , 2)
1778 MIPS_SYS(sys_unlink , 1) /* 4010 */
1779 MIPS_SYS(sys_execve , 0)
1780 MIPS_SYS(sys_chdir , 1)
1781 MIPS_SYS(sys_time , 1)
1782 MIPS_SYS(sys_mknod , 3)
1783 MIPS_SYS(sys_chmod , 2) /* 4015 */
1784 MIPS_SYS(sys_lchown , 3)
1785 MIPS_SYS(sys_ni_syscall , 0)
1786 MIPS_SYS(sys_ni_syscall , 0) /* was sys_stat */
1787 MIPS_SYS(sys_lseek , 3)
1788 MIPS_SYS(sys_getpid , 0) /* 4020 */
1789 MIPS_SYS(sys_mount , 5)
1790 MIPS_SYS(sys_oldumount , 1)
1791 MIPS_SYS(sys_setuid , 1)
1792 MIPS_SYS(sys_getuid , 0)
1793 MIPS_SYS(sys_stime , 1) /* 4025 */
1794 MIPS_SYS(sys_ptrace , 4)
1795 MIPS_SYS(sys_alarm , 1)
1796 MIPS_SYS(sys_ni_syscall , 0) /* was sys_fstat */
1797 MIPS_SYS(sys_pause , 0)
1798 MIPS_SYS(sys_utime , 2) /* 4030 */
1799 MIPS_SYS(sys_ni_syscall , 0)
1800 MIPS_SYS(sys_ni_syscall , 0)
1801 MIPS_SYS(sys_access , 2)
1802 MIPS_SYS(sys_nice , 1)
1803 MIPS_SYS(sys_ni_syscall , 0) /* 4035 */
1804 MIPS_SYS(sys_sync , 0)
1805 MIPS_SYS(sys_kill , 2)
1806 MIPS_SYS(sys_rename , 2)
1807 MIPS_SYS(sys_mkdir , 2)
1808 MIPS_SYS(sys_rmdir , 1) /* 4040 */
1809 MIPS_SYS(sys_dup , 1)
1810 MIPS_SYS(sys_pipe , 0)
1811 MIPS_SYS(sys_times , 1)
1812 MIPS_SYS(sys_ni_syscall , 0)
1813 MIPS_SYS(sys_brk , 1) /* 4045 */
1814 MIPS_SYS(sys_setgid , 1)
1815 MIPS_SYS(sys_getgid , 0)
1816 MIPS_SYS(sys_ni_syscall , 0) /* was signal(2) */
1817 MIPS_SYS(sys_geteuid , 0)
1818 MIPS_SYS(sys_getegid , 0) /* 4050 */
1819 MIPS_SYS(sys_acct , 0)
1820 MIPS_SYS(sys_umount , 2)
1821 MIPS_SYS(sys_ni_syscall , 0)
1822 MIPS_SYS(sys_ioctl , 3)
1823 MIPS_SYS(sys_fcntl , 3) /* 4055 */
1824 MIPS_SYS(sys_ni_syscall , 2)
1825 MIPS_SYS(sys_setpgid , 2)
1826 MIPS_SYS(sys_ni_syscall , 0)
1827 MIPS_SYS(sys_olduname , 1)
1828 MIPS_SYS(sys_umask , 1) /* 4060 */
1829 MIPS_SYS(sys_chroot , 1)
1830 MIPS_SYS(sys_ustat , 2)
1831 MIPS_SYS(sys_dup2 , 2)
1832 MIPS_SYS(sys_getppid , 0)
1833 MIPS_SYS(sys_getpgrp , 0) /* 4065 */
1834 MIPS_SYS(sys_setsid , 0)
1835 MIPS_SYS(sys_sigaction , 3)
1836 MIPS_SYS(sys_sgetmask , 0)
1837 MIPS_SYS(sys_ssetmask , 1)
1838 MIPS_SYS(sys_setreuid , 2) /* 4070 */
1839 MIPS_SYS(sys_setregid , 2)
1840 MIPS_SYS(sys_sigsuspend , 0)
1841 MIPS_SYS(sys_sigpending , 1)
1842 MIPS_SYS(sys_sethostname , 2)
1843 MIPS_SYS(sys_setrlimit , 2) /* 4075 */
1844 MIPS_SYS(sys_getrlimit , 2)
1845 MIPS_SYS(sys_getrusage , 2)
1846 MIPS_SYS(sys_gettimeofday, 2)
1847 MIPS_SYS(sys_settimeofday, 2)
1848 MIPS_SYS(sys_getgroups , 2) /* 4080 */
1849 MIPS_SYS(sys_setgroups , 2)
1850 MIPS_SYS(sys_ni_syscall , 0) /* old_select */
1851 MIPS_SYS(sys_symlink , 2)
1852 MIPS_SYS(sys_ni_syscall , 0) /* was sys_lstat */
1853 MIPS_SYS(sys_readlink , 3) /* 4085 */
1854 MIPS_SYS(sys_uselib , 1)
1855 MIPS_SYS(sys_swapon , 2)
1856 MIPS_SYS(sys_reboot , 3)
1857 MIPS_SYS(old_readdir , 3)
1858 MIPS_SYS(old_mmap , 6) /* 4090 */
1859 MIPS_SYS(sys_munmap , 2)
1860 MIPS_SYS(sys_truncate , 2)
1861 MIPS_SYS(sys_ftruncate , 2)
1862 MIPS_SYS(sys_fchmod , 2)
1863 MIPS_SYS(sys_fchown , 3) /* 4095 */
1864 MIPS_SYS(sys_getpriority , 2)
1865 MIPS_SYS(sys_setpriority , 3)
1866 MIPS_SYS(sys_ni_syscall , 0)
1867 MIPS_SYS(sys_statfs , 2)
1868 MIPS_SYS(sys_fstatfs , 2) /* 4100 */
1869 MIPS_SYS(sys_ni_syscall , 0) /* was ioperm(2) */
1870 MIPS_SYS(sys_socketcall , 2)
1871 MIPS_SYS(sys_syslog , 3)
1872 MIPS_SYS(sys_setitimer , 3)
1873 MIPS_SYS(sys_getitimer , 2) /* 4105 */
1874 MIPS_SYS(sys_newstat , 2)
1875 MIPS_SYS(sys_newlstat , 2)
1876 MIPS_SYS(sys_newfstat , 2)
1877 MIPS_SYS(sys_uname , 1)
1878 MIPS_SYS(sys_ni_syscall , 0) /* 4110 was iopl(2) */
1879 MIPS_SYS(sys_vhangup , 0)
1880 MIPS_SYS(sys_ni_syscall , 0) /* was sys_idle() */
1881 MIPS_SYS(sys_ni_syscall , 0) /* was sys_vm86 */
1882 MIPS_SYS(sys_wait4 , 4)
1883 MIPS_SYS(sys_swapoff , 1) /* 4115 */
1884 MIPS_SYS(sys_sysinfo , 1)
1885 MIPS_SYS(sys_ipc , 6)
1886 MIPS_SYS(sys_fsync , 1)
1887 MIPS_SYS(sys_sigreturn , 0)
18113962 1888 MIPS_SYS(sys_clone , 6) /* 4120 */
048f6b4d
FB
1889 MIPS_SYS(sys_setdomainname, 2)
1890 MIPS_SYS(sys_newuname , 1)
1891 MIPS_SYS(sys_ni_syscall , 0) /* sys_modify_ldt */
1892 MIPS_SYS(sys_adjtimex , 1)
1893 MIPS_SYS(sys_mprotect , 3) /* 4125 */
1894 MIPS_SYS(sys_sigprocmask , 3)
1895 MIPS_SYS(sys_ni_syscall , 0) /* was create_module */
1896 MIPS_SYS(sys_init_module , 5)
1897 MIPS_SYS(sys_delete_module, 1)
1898 MIPS_SYS(sys_ni_syscall , 0) /* 4130 was get_kernel_syms */
1899 MIPS_SYS(sys_quotactl , 0)
1900 MIPS_SYS(sys_getpgid , 1)
1901 MIPS_SYS(sys_fchdir , 1)
1902 MIPS_SYS(sys_bdflush , 2)
1903 MIPS_SYS(sys_sysfs , 3) /* 4135 */
1904 MIPS_SYS(sys_personality , 1)
1905 MIPS_SYS(sys_ni_syscall , 0) /* for afs_syscall */
1906 MIPS_SYS(sys_setfsuid , 1)
1907 MIPS_SYS(sys_setfsgid , 1)
1908 MIPS_SYS(sys_llseek , 5) /* 4140 */
1909 MIPS_SYS(sys_getdents , 3)
1910 MIPS_SYS(sys_select , 5)
1911 MIPS_SYS(sys_flock , 2)
1912 MIPS_SYS(sys_msync , 3)
1913 MIPS_SYS(sys_readv , 3) /* 4145 */
1914 MIPS_SYS(sys_writev , 3)
1915 MIPS_SYS(sys_cacheflush , 3)
1916 MIPS_SYS(sys_cachectl , 3)
1917 MIPS_SYS(sys_sysmips , 4)
1918 MIPS_SYS(sys_ni_syscall , 0) /* 4150 */
1919 MIPS_SYS(sys_getsid , 1)
1920 MIPS_SYS(sys_fdatasync , 0)
1921 MIPS_SYS(sys_sysctl , 1)
1922 MIPS_SYS(sys_mlock , 2)
1923 MIPS_SYS(sys_munlock , 2) /* 4155 */
1924 MIPS_SYS(sys_mlockall , 1)
1925 MIPS_SYS(sys_munlockall , 0)
1926 MIPS_SYS(sys_sched_setparam, 2)
1927 MIPS_SYS(sys_sched_getparam, 2)
1928 MIPS_SYS(sys_sched_setscheduler, 3) /* 4160 */
1929 MIPS_SYS(sys_sched_getscheduler, 1)
1930 MIPS_SYS(sys_sched_yield , 0)
1931 MIPS_SYS(sys_sched_get_priority_max, 1)
1932 MIPS_SYS(sys_sched_get_priority_min, 1)
1933 MIPS_SYS(sys_sched_rr_get_interval, 2) /* 4165 */
1934 MIPS_SYS(sys_nanosleep, 2)
1935 MIPS_SYS(sys_mremap , 4)
1936 MIPS_SYS(sys_accept , 3)
1937 MIPS_SYS(sys_bind , 3)
1938 MIPS_SYS(sys_connect , 3) /* 4170 */
1939 MIPS_SYS(sys_getpeername , 3)
1940 MIPS_SYS(sys_getsockname , 3)
1941 MIPS_SYS(sys_getsockopt , 5)
1942 MIPS_SYS(sys_listen , 2)
1943 MIPS_SYS(sys_recv , 4) /* 4175 */
1944 MIPS_SYS(sys_recvfrom , 6)
1945 MIPS_SYS(sys_recvmsg , 3)
1946 MIPS_SYS(sys_send , 4)
1947 MIPS_SYS(sys_sendmsg , 3)
1948 MIPS_SYS(sys_sendto , 6) /* 4180 */
1949 MIPS_SYS(sys_setsockopt , 5)
1950 MIPS_SYS(sys_shutdown , 2)
1951 MIPS_SYS(sys_socket , 3)
1952 MIPS_SYS(sys_socketpair , 4)
1953 MIPS_SYS(sys_setresuid , 3) /* 4185 */
1954 MIPS_SYS(sys_getresuid , 3)
1955 MIPS_SYS(sys_ni_syscall , 0) /* was sys_query_module */
1956 MIPS_SYS(sys_poll , 3)
1957 MIPS_SYS(sys_nfsservctl , 3)
1958 MIPS_SYS(sys_setresgid , 3) /* 4190 */
1959 MIPS_SYS(sys_getresgid , 3)
1960 MIPS_SYS(sys_prctl , 5)
1961 MIPS_SYS(sys_rt_sigreturn, 0)
1962 MIPS_SYS(sys_rt_sigaction, 4)
1963 MIPS_SYS(sys_rt_sigprocmask, 4) /* 4195 */
1964 MIPS_SYS(sys_rt_sigpending, 2)
1965 MIPS_SYS(sys_rt_sigtimedwait, 4)
1966 MIPS_SYS(sys_rt_sigqueueinfo, 3)
1967 MIPS_SYS(sys_rt_sigsuspend, 0)
1968 MIPS_SYS(sys_pread64 , 6) /* 4200 */
1969 MIPS_SYS(sys_pwrite64 , 6)
1970 MIPS_SYS(sys_chown , 3)
1971 MIPS_SYS(sys_getcwd , 2)
1972 MIPS_SYS(sys_capget , 2)
1973 MIPS_SYS(sys_capset , 2) /* 4205 */
053ebb27 1974 MIPS_SYS(sys_sigaltstack , 2)
048f6b4d
FB
1975 MIPS_SYS(sys_sendfile , 4)
1976 MIPS_SYS(sys_ni_syscall , 0)
1977 MIPS_SYS(sys_ni_syscall , 0)
1978 MIPS_SYS(sys_mmap2 , 6) /* 4210 */
1979 MIPS_SYS(sys_truncate64 , 4)
1980 MIPS_SYS(sys_ftruncate64 , 4)
1981 MIPS_SYS(sys_stat64 , 2)
1982 MIPS_SYS(sys_lstat64 , 2)
1983 MIPS_SYS(sys_fstat64 , 2) /* 4215 */
1984 MIPS_SYS(sys_pivot_root , 2)
1985 MIPS_SYS(sys_mincore , 3)
1986 MIPS_SYS(sys_madvise , 3)
1987 MIPS_SYS(sys_getdents64 , 3)
1988 MIPS_SYS(sys_fcntl64 , 3) /* 4220 */
1989 MIPS_SYS(sys_ni_syscall , 0)
1990 MIPS_SYS(sys_gettid , 0)
1991 MIPS_SYS(sys_readahead , 5)
1992 MIPS_SYS(sys_setxattr , 5)
1993 MIPS_SYS(sys_lsetxattr , 5) /* 4225 */
1994 MIPS_SYS(sys_fsetxattr , 5)
1995 MIPS_SYS(sys_getxattr , 4)
1996 MIPS_SYS(sys_lgetxattr , 4)
1997 MIPS_SYS(sys_fgetxattr , 4)
1998 MIPS_SYS(sys_listxattr , 3) /* 4230 */
1999 MIPS_SYS(sys_llistxattr , 3)
2000 MIPS_SYS(sys_flistxattr , 3)
2001 MIPS_SYS(sys_removexattr , 2)
2002 MIPS_SYS(sys_lremovexattr, 2)
2003 MIPS_SYS(sys_fremovexattr, 2) /* 4235 */
2004 MIPS_SYS(sys_tkill , 2)
2005 MIPS_SYS(sys_sendfile64 , 5)
2006 MIPS_SYS(sys_futex , 2)
2007 MIPS_SYS(sys_sched_setaffinity, 3)
2008 MIPS_SYS(sys_sched_getaffinity, 3) /* 4240 */
2009 MIPS_SYS(sys_io_setup , 2)
2010 MIPS_SYS(sys_io_destroy , 1)
2011 MIPS_SYS(sys_io_getevents, 5)
2012 MIPS_SYS(sys_io_submit , 3)
2013 MIPS_SYS(sys_io_cancel , 3) /* 4245 */
2014 MIPS_SYS(sys_exit_group , 1)
2015 MIPS_SYS(sys_lookup_dcookie, 3)
2016 MIPS_SYS(sys_epoll_create, 1)
2017 MIPS_SYS(sys_epoll_ctl , 4)
2018 MIPS_SYS(sys_epoll_wait , 3) /* 4250 */
2019 MIPS_SYS(sys_remap_file_pages, 5)
2020 MIPS_SYS(sys_set_tid_address, 1)
2021 MIPS_SYS(sys_restart_syscall, 0)
2022 MIPS_SYS(sys_fadvise64_64, 7)
2023 MIPS_SYS(sys_statfs64 , 3) /* 4255 */
2024 MIPS_SYS(sys_fstatfs64 , 2)
2025 MIPS_SYS(sys_timer_create, 3)
2026 MIPS_SYS(sys_timer_settime, 4)
2027 MIPS_SYS(sys_timer_gettime, 2)
2028 MIPS_SYS(sys_timer_getoverrun, 1) /* 4260 */
2029 MIPS_SYS(sys_timer_delete, 1)
2030 MIPS_SYS(sys_clock_settime, 2)
2031 MIPS_SYS(sys_clock_gettime, 2)
2032 MIPS_SYS(sys_clock_getres, 2)
2033 MIPS_SYS(sys_clock_nanosleep, 4) /* 4265 */
2034 MIPS_SYS(sys_tgkill , 3)
2035 MIPS_SYS(sys_utimes , 2)
2036 MIPS_SYS(sys_mbind , 4)
2037 MIPS_SYS(sys_ni_syscall , 0) /* sys_get_mempolicy */
2038 MIPS_SYS(sys_ni_syscall , 0) /* 4270 sys_set_mempolicy */
2039 MIPS_SYS(sys_mq_open , 4)
2040 MIPS_SYS(sys_mq_unlink , 1)
2041 MIPS_SYS(sys_mq_timedsend, 5)
2042 MIPS_SYS(sys_mq_timedreceive, 5)
2043 MIPS_SYS(sys_mq_notify , 2) /* 4275 */
2044 MIPS_SYS(sys_mq_getsetattr, 3)
2045 MIPS_SYS(sys_ni_syscall , 0) /* sys_vserver */
2046 MIPS_SYS(sys_waitid , 4)
2047 MIPS_SYS(sys_ni_syscall , 0) /* available, was setaltroot */
2048 MIPS_SYS(sys_add_key , 5)
388bb21a 2049 MIPS_SYS(sys_request_key, 4)
048f6b4d 2050 MIPS_SYS(sys_keyctl , 5)
6f5b89a0 2051 MIPS_SYS(sys_set_thread_area, 1)
388bb21a
TS
2052 MIPS_SYS(sys_inotify_init, 0)
2053 MIPS_SYS(sys_inotify_add_watch, 3) /* 4285 */
2054 MIPS_SYS(sys_inotify_rm_watch, 2)
2055 MIPS_SYS(sys_migrate_pages, 4)
2056 MIPS_SYS(sys_openat, 4)
2057 MIPS_SYS(sys_mkdirat, 3)
2058 MIPS_SYS(sys_mknodat, 4) /* 4290 */
2059 MIPS_SYS(sys_fchownat, 5)
2060 MIPS_SYS(sys_futimesat, 3)
2061 MIPS_SYS(sys_fstatat64, 4)
2062 MIPS_SYS(sys_unlinkat, 3)
2063 MIPS_SYS(sys_renameat, 4) /* 4295 */
2064 MIPS_SYS(sys_linkat, 5)
2065 MIPS_SYS(sys_symlinkat, 3)
2066 MIPS_SYS(sys_readlinkat, 4)
2067 MIPS_SYS(sys_fchmodat, 3)
2068 MIPS_SYS(sys_faccessat, 3) /* 4300 */
2069 MIPS_SYS(sys_pselect6, 6)
2070 MIPS_SYS(sys_ppoll, 5)
2071 MIPS_SYS(sys_unshare, 1)
2072 MIPS_SYS(sys_splice, 4)
2073 MIPS_SYS(sys_sync_file_range, 7) /* 4305 */
2074 MIPS_SYS(sys_tee, 4)
2075 MIPS_SYS(sys_vmsplice, 4)
2076 MIPS_SYS(sys_move_pages, 6)
2077 MIPS_SYS(sys_set_robust_list, 2)
2078 MIPS_SYS(sys_get_robust_list, 3) /* 4310 */
2079 MIPS_SYS(sys_kexec_load, 4)
2080 MIPS_SYS(sys_getcpu, 3)
2081 MIPS_SYS(sys_epoll_pwait, 6)
2082 MIPS_SYS(sys_ioprio_set, 3)
2083 MIPS_SYS(sys_ioprio_get, 2)
d979e8eb
PM
2084 MIPS_SYS(sys_utimensat, 4)
2085 MIPS_SYS(sys_signalfd, 3)
2086 MIPS_SYS(sys_ni_syscall, 0) /* was timerfd */
2087 MIPS_SYS(sys_eventfd, 1)
2088 MIPS_SYS(sys_fallocate, 6) /* 4320 */
2089 MIPS_SYS(sys_timerfd_create, 2)
2090 MIPS_SYS(sys_timerfd_gettime, 2)
2091 MIPS_SYS(sys_timerfd_settime, 4)
2092 MIPS_SYS(sys_signalfd4, 4)
2093 MIPS_SYS(sys_eventfd2, 2) /* 4325 */
2094 MIPS_SYS(sys_epoll_create1, 1)
2095 MIPS_SYS(sys_dup3, 3)
2096 MIPS_SYS(sys_pipe2, 2)
2097 MIPS_SYS(sys_inotify_init1, 1)
2098 MIPS_SYS(sys_preadv, 6) /* 4330 */
2099 MIPS_SYS(sys_pwritev, 6)
2100 MIPS_SYS(sys_rt_tgsigqueueinfo, 4)
2101 MIPS_SYS(sys_perf_event_open, 5)
2102 MIPS_SYS(sys_accept4, 4)
2103 MIPS_SYS(sys_recvmmsg, 5) /* 4335 */
2104 MIPS_SYS(sys_fanotify_init, 2)
2105 MIPS_SYS(sys_fanotify_mark, 6)
2106 MIPS_SYS(sys_prlimit64, 4)
2107 MIPS_SYS(sys_name_to_handle_at, 5)
2108 MIPS_SYS(sys_open_by_handle_at, 3) /* 4340 */
2109 MIPS_SYS(sys_clock_adjtime, 2)
2110 MIPS_SYS(sys_syncfs, 1)
048f6b4d
FB
2111};
2112
2113#undef MIPS_SYS
2114
590bc601
PB
2115static int do_store_exclusive(CPUMIPSState *env)
2116{
2117 target_ulong addr;
2118 target_ulong page_addr;
2119 target_ulong val;
2120 int flags;
2121 int segv = 0;
2122 int reg;
2123 int d;
2124
5499b6ff 2125 addr = env->lladdr;
590bc601
PB
2126 page_addr = addr & TARGET_PAGE_MASK;
2127 start_exclusive();
2128 mmap_lock();
2129 flags = page_get_flags(page_addr);
2130 if ((flags & PAGE_READ) == 0) {
2131 segv = 1;
2132 } else {
2133 reg = env->llreg & 0x1f;
2134 d = (env->llreg & 0x20) != 0;
2135 if (d) {
2136 segv = get_user_s64(val, addr);
2137 } else {
2138 segv = get_user_s32(val, addr);
2139 }
2140 if (!segv) {
2141 if (val != env->llval) {
2142 env->active_tc.gpr[reg] = 0;
2143 } else {
2144 if (d) {
2145 segv = put_user_u64(env->llnewval, addr);
2146 } else {
2147 segv = put_user_u32(env->llnewval, addr);
2148 }
2149 if (!segv) {
2150 env->active_tc.gpr[reg] = 1;
2151 }
2152 }
2153 }
2154 }
5499b6ff 2155 env->lladdr = -1;
590bc601
PB
2156 if (!segv) {
2157 env->active_tc.PC += 4;
2158 }
2159 mmap_unlock();
2160 end_exclusive();
2161 return segv;
2162}
2163
048f6b4d
FB
2164void cpu_loop(CPUMIPSState *env)
2165{
c227f099 2166 target_siginfo_t info;
388bb21a 2167 int trapnr, ret;
048f6b4d 2168 unsigned int syscall_num;
048f6b4d
FB
2169
2170 for(;;) {
590bc601 2171 cpu_exec_start(env);
048f6b4d 2172 trapnr = cpu_mips_exec(env);
590bc601 2173 cpu_exec_end(env);
048f6b4d
FB
2174 switch(trapnr) {
2175 case EXCP_SYSCALL:
b5dc7732
TS
2176 syscall_num = env->active_tc.gpr[2] - 4000;
2177 env->active_tc.PC += 4;
388bb21a 2178 if (syscall_num >= sizeof(mips_syscall_args)) {
7c2f6157 2179 ret = -TARGET_ENOSYS;
388bb21a
TS
2180 } else {
2181 int nb_args;
992f48a0
BS
2182 abi_ulong sp_reg;
2183 abi_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0;
388bb21a
TS
2184
2185 nb_args = mips_syscall_args[syscall_num];
b5dc7732 2186 sp_reg = env->active_tc.gpr[29];
388bb21a
TS
2187 switch (nb_args) {
2188 /* these arguments are taken from the stack */
94c19610
ACH
2189 case 8:
2190 if ((ret = get_user_ual(arg8, sp_reg + 28)) != 0) {
2191 goto done_syscall;
2192 }
2193 case 7:
2194 if ((ret = get_user_ual(arg7, sp_reg + 24)) != 0) {
2195 goto done_syscall;
2196 }
2197 case 6:
2198 if ((ret = get_user_ual(arg6, sp_reg + 20)) != 0) {
2199 goto done_syscall;
2200 }
2201 case 5:
2202 if ((ret = get_user_ual(arg5, sp_reg + 16)) != 0) {
2203 goto done_syscall;
2204 }
388bb21a
TS
2205 default:
2206 break;
048f6b4d 2207 }
b5dc7732
TS
2208 ret = do_syscall(env, env->active_tc.gpr[2],
2209 env->active_tc.gpr[4],
2210 env->active_tc.gpr[5],
2211 env->active_tc.gpr[6],
2212 env->active_tc.gpr[7],
5945cfcb 2213 arg5, arg6, arg7, arg8);
388bb21a 2214 }
94c19610 2215done_syscall:
0b1bcb00
PB
2216 if (ret == -TARGET_QEMU_ESIGRETURN) {
2217 /* Returning from a successful sigreturn syscall.
2218 Avoid clobbering register state. */
2219 break;
2220 }
388bb21a 2221 if ((unsigned int)ret >= (unsigned int)(-1133)) {
b5dc7732 2222 env->active_tc.gpr[7] = 1; /* error flag */
388bb21a
TS
2223 ret = -ret;
2224 } else {
b5dc7732 2225 env->active_tc.gpr[7] = 0; /* error flag */
048f6b4d 2226 }
b5dc7732 2227 env->active_tc.gpr[2] = ret;
048f6b4d 2228 break;
ca7c2b1b
TS
2229 case EXCP_TLBL:
2230 case EXCP_TLBS:
e6e5bd2d
WT
2231 case EXCP_AdEL:
2232 case EXCP_AdES:
e4474235
PB
2233 info.si_signo = TARGET_SIGSEGV;
2234 info.si_errno = 0;
2235 /* XXX: check env->error_code */
2236 info.si_code = TARGET_SEGV_MAPERR;
2237 info._sifields._sigfault._addr = env->CP0_BadVAddr;
2238 queue_signal(env, info.si_signo, &info);
2239 break;
6900e84b 2240 case EXCP_CpU:
048f6b4d 2241 case EXCP_RI:
bc1ad2de
FB
2242 info.si_signo = TARGET_SIGILL;
2243 info.si_errno = 0;
2244 info.si_code = 0;
624f7979 2245 queue_signal(env, info.si_signo, &info);
048f6b4d 2246 break;
106ec879
FB
2247 case EXCP_INTERRUPT:
2248 /* just indicate that signals should be handled asap */
2249 break;
d08b2a28
PB
2250 case EXCP_DEBUG:
2251 {
2252 int sig;
2253
2254 sig = gdb_handlesig (env, TARGET_SIGTRAP);
2255 if (sig)
2256 {
2257 info.si_signo = sig;
2258 info.si_errno = 0;
2259 info.si_code = TARGET_TRAP_BRKPT;
624f7979 2260 queue_signal(env, info.si_signo, &info);
d08b2a28
PB
2261 }
2262 }
2263 break;
590bc601
PB
2264 case EXCP_SC:
2265 if (do_store_exclusive(env)) {
2266 info.si_signo = TARGET_SIGSEGV;
2267 info.si_errno = 0;
2268 info.si_code = TARGET_SEGV_MAPERR;
2269 info._sifields._sigfault._addr = env->active_tc.PC;
2270 queue_signal(env, info.si_signo, &info);
2271 }
2272 break;
048f6b4d
FB
2273 default:
2274 // error:
5fafdf24 2275 fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
048f6b4d
FB
2276 trapnr);
2277 cpu_dump_state(env, stderr, fprintf, 0);
2278 abort();
2279 }
2280 process_pending_signals(env);
2281 }
2282}
2283#endif
2284
fdf9b3e8
FB
2285#ifdef TARGET_SH4
2286void cpu_loop (CPUState *env)
2287{
2288 int trapnr, ret;
c227f099 2289 target_siginfo_t info;
3b46e624 2290
fdf9b3e8
FB
2291 while (1) {
2292 trapnr = cpu_sh4_exec (env);
3b46e624 2293
fdf9b3e8
FB
2294 switch (trapnr) {
2295 case 0x160:
0b6d3ae0 2296 env->pc += 2;
5fafdf24
TS
2297 ret = do_syscall(env,
2298 env->gregs[3],
2299 env->gregs[4],
2300 env->gregs[5],
2301 env->gregs[6],
2302 env->gregs[7],
2303 env->gregs[0],
5945cfcb
PM
2304 env->gregs[1],
2305 0, 0);
9c2a9ea1 2306 env->gregs[0] = ret;
fdf9b3e8 2307 break;
c3b5bc8a
TS
2308 case EXCP_INTERRUPT:
2309 /* just indicate that signals should be handled asap */
2310 break;
355fb23d
PB
2311 case EXCP_DEBUG:
2312 {
2313 int sig;
2314
2315 sig = gdb_handlesig (env, TARGET_SIGTRAP);
2316 if (sig)
2317 {
2318 info.si_signo = sig;
2319 info.si_errno = 0;
2320 info.si_code = TARGET_TRAP_BRKPT;
624f7979 2321 queue_signal(env, info.si_signo, &info);
355fb23d
PB
2322 }
2323 }
2324 break;
c3b5bc8a
TS
2325 case 0xa0:
2326 case 0xc0:
2327 info.si_signo = SIGSEGV;
2328 info.si_errno = 0;
2329 info.si_code = TARGET_SEGV_MAPERR;
2330 info._sifields._sigfault._addr = env->tea;
624f7979 2331 queue_signal(env, info.si_signo, &info);
c3b5bc8a
TS
2332 break;
2333
fdf9b3e8
FB
2334 default:
2335 printf ("Unhandled trap: 0x%x\n", trapnr);
2336 cpu_dump_state(env, stderr, fprintf, 0);
2337 exit (1);
2338 }
2339 process_pending_signals (env);
2340 }
2341}
2342#endif
2343
48733d19
TS
2344#ifdef TARGET_CRIS
2345void cpu_loop (CPUState *env)
2346{
2347 int trapnr, ret;
c227f099 2348 target_siginfo_t info;
48733d19
TS
2349
2350 while (1) {
2351 trapnr = cpu_cris_exec (env);
2352 switch (trapnr) {
2353 case 0xaa:
2354 {
2355 info.si_signo = SIGSEGV;
2356 info.si_errno = 0;
2357 /* XXX: check env->error_code */
2358 info.si_code = TARGET_SEGV_MAPERR;
e00c1e71 2359 info._sifields._sigfault._addr = env->pregs[PR_EDA];
624f7979 2360 queue_signal(env, info.si_signo, &info);
48733d19
TS
2361 }
2362 break;
b6d3abda
EI
2363 case EXCP_INTERRUPT:
2364 /* just indicate that signals should be handled asap */
2365 break;
48733d19
TS
2366 case EXCP_BREAK:
2367 ret = do_syscall(env,
2368 env->regs[9],
2369 env->regs[10],
2370 env->regs[11],
2371 env->regs[12],
2372 env->regs[13],
2373 env->pregs[7],
5945cfcb
PM
2374 env->pregs[11],
2375 0, 0);
48733d19 2376 env->regs[10] = ret;
48733d19
TS
2377 break;
2378 case EXCP_DEBUG:
2379 {
2380 int sig;
2381
2382 sig = gdb_handlesig (env, TARGET_SIGTRAP);
2383 if (sig)
2384 {
2385 info.si_signo = sig;
2386 info.si_errno = 0;
2387 info.si_code = TARGET_TRAP_BRKPT;
624f7979 2388 queue_signal(env, info.si_signo, &info);
48733d19
TS
2389 }
2390 }
2391 break;
2392 default:
2393 printf ("Unhandled trap: 0x%x\n", trapnr);
2394 cpu_dump_state(env, stderr, fprintf, 0);
2395 exit (1);
2396 }
2397 process_pending_signals (env);
2398 }
2399}
2400#endif
2401
b779e29e
EI
2402#ifdef TARGET_MICROBLAZE
2403void cpu_loop (CPUState *env)
2404{
2405 int trapnr, ret;
c227f099 2406 target_siginfo_t info;
b779e29e
EI
2407
2408 while (1) {
2409 trapnr = cpu_mb_exec (env);
2410 switch (trapnr) {
2411 case 0xaa:
2412 {
2413 info.si_signo = SIGSEGV;
2414 info.si_errno = 0;
2415 /* XXX: check env->error_code */
2416 info.si_code = TARGET_SEGV_MAPERR;
2417 info._sifields._sigfault._addr = 0;
2418 queue_signal(env, info.si_signo, &info);
2419 }
2420 break;
2421 case EXCP_INTERRUPT:
2422 /* just indicate that signals should be handled asap */
2423 break;
2424 case EXCP_BREAK:
2425 /* Return address is 4 bytes after the call. */
2426 env->regs[14] += 4;
2427 ret = do_syscall(env,
2428 env->regs[12],
2429 env->regs[5],
2430 env->regs[6],
2431 env->regs[7],
2432 env->regs[8],
2433 env->regs[9],
5945cfcb
PM
2434 env->regs[10],
2435 0, 0);
b779e29e
EI
2436 env->regs[3] = ret;
2437 env->sregs[SR_PC] = env->regs[14];
2438 break;
b76da7e3
EI
2439 case EXCP_HW_EXCP:
2440 env->regs[17] = env->sregs[SR_PC] + 4;
2441 if (env->iflags & D_FLAG) {
2442 env->sregs[SR_ESR] |= 1 << 12;
2443 env->sregs[SR_PC] -= 4;
2444 /* FIXME: if branch was immed, replay the imm aswell. */
2445 }
2446
2447 env->iflags &= ~(IMM_FLAG | D_FLAG);
2448
2449 switch (env->sregs[SR_ESR] & 31) {
22a78d64
EI
2450 case ESR_EC_DIVZERO:
2451 info.si_signo = SIGFPE;
2452 info.si_errno = 0;
2453 info.si_code = TARGET_FPE_FLTDIV;
2454 info._sifields._sigfault._addr = 0;
2455 queue_signal(env, info.si_signo, &info);
2456 break;
b76da7e3
EI
2457 case ESR_EC_FPU:
2458 info.si_signo = SIGFPE;
2459 info.si_errno = 0;
2460 if (env->sregs[SR_FSR] & FSR_IO) {
2461 info.si_code = TARGET_FPE_FLTINV;
2462 }
2463 if (env->sregs[SR_FSR] & FSR_DZ) {
2464 info.si_code = TARGET_FPE_FLTDIV;
2465 }
2466 info._sifields._sigfault._addr = 0;
2467 queue_signal(env, info.si_signo, &info);
2468 break;
2469 default:
2470 printf ("Unhandled hw-exception: 0x%x\n",
2e42d52d 2471 env->sregs[SR_ESR] & ESR_EC_MASK);
b76da7e3
EI
2472 cpu_dump_state(env, stderr, fprintf, 0);
2473 exit (1);
2474 break;
2475 }
2476 break;
b779e29e
EI
2477 case EXCP_DEBUG:
2478 {
2479 int sig;
2480
2481 sig = gdb_handlesig (env, TARGET_SIGTRAP);
2482 if (sig)
2483 {
2484 info.si_signo = sig;
2485 info.si_errno = 0;
2486 info.si_code = TARGET_TRAP_BRKPT;
2487 queue_signal(env, info.si_signo, &info);
2488 }
2489 }
2490 break;
2491 default:
2492 printf ("Unhandled trap: 0x%x\n", trapnr);
2493 cpu_dump_state(env, stderr, fprintf, 0);
2494 exit (1);
2495 }
2496 process_pending_signals (env);
2497 }
2498}
2499#endif
2500
e6e5906b
PB
2501#ifdef TARGET_M68K
2502
2503void cpu_loop(CPUM68KState *env)
2504{
2505 int trapnr;
2506 unsigned int n;
c227f099 2507 target_siginfo_t info;
e6e5906b 2508 TaskState *ts = env->opaque;
3b46e624 2509
e6e5906b
PB
2510 for(;;) {
2511 trapnr = cpu_m68k_exec(env);
2512 switch(trapnr) {
2513 case EXCP_ILLEGAL:
2514 {
2515 if (ts->sim_syscalls) {
2516 uint16_t nr;
2517 nr = lduw(env->pc + 2);
2518 env->pc += 4;
2519 do_m68k_simcall(env, nr);
2520 } else {
2521 goto do_sigill;
2522 }
2523 }
2524 break;
a87295e8 2525 case EXCP_HALT_INSN:
e6e5906b 2526 /* Semihosing syscall. */
a87295e8 2527 env->pc += 4;
e6e5906b
PB
2528 do_m68k_semihosting(env, env->dregs[0]);
2529 break;
2530 case EXCP_LINEA:
2531 case EXCP_LINEF:
2532 case EXCP_UNSUPPORTED:
2533 do_sigill:
2534 info.si_signo = SIGILL;
2535 info.si_errno = 0;
2536 info.si_code = TARGET_ILL_ILLOPN;
2537 info._sifields._sigfault._addr = env->pc;
624f7979 2538 queue_signal(env, info.si_signo, &info);
e6e5906b
PB
2539 break;
2540 case EXCP_TRAP0:
2541 {
2542 ts->sim_syscalls = 0;
2543 n = env->dregs[0];
2544 env->pc += 2;
5fafdf24
TS
2545 env->dregs[0] = do_syscall(env,
2546 n,
e6e5906b
PB
2547 env->dregs[1],
2548 env->dregs[2],
2549 env->dregs[3],
2550 env->dregs[4],
2551 env->dregs[5],
5945cfcb
PM
2552 env->aregs[0],
2553 0, 0);
e6e5906b
PB
2554 }
2555 break;
2556 case EXCP_INTERRUPT:
2557 /* just indicate that signals should be handled asap */
2558 break;
2559 case EXCP_ACCESS:
2560 {
2561 info.si_signo = SIGSEGV;
2562 info.si_errno = 0;
2563 /* XXX: check env->error_code */
2564 info.si_code = TARGET_SEGV_MAPERR;
2565 info._sifields._sigfault._addr = env->mmu.ar;
624f7979 2566 queue_signal(env, info.si_signo, &info);
e6e5906b
PB
2567 }
2568 break;
2569 case EXCP_DEBUG:
2570 {
2571 int sig;
2572
2573 sig = gdb_handlesig (env, TARGET_SIGTRAP);
2574 if (sig)
2575 {
2576 info.si_signo = sig;
2577 info.si_errno = 0;
2578 info.si_code = TARGET_TRAP_BRKPT;
624f7979 2579 queue_signal(env, info.si_signo, &info);
e6e5906b
PB
2580 }
2581 }
2582 break;
2583 default:
5fafdf24 2584 fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
e6e5906b
PB
2585 trapnr);
2586 cpu_dump_state(env, stderr, fprintf, 0);
2587 abort();
2588 }
2589 process_pending_signals(env);
2590 }
2591}
2592#endif /* TARGET_M68K */
2593
7a3148a9 2594#ifdef TARGET_ALPHA
6910b8f6
RH
2595static void do_store_exclusive(CPUAlphaState *env, int reg, int quad)
2596{
2597 target_ulong addr, val, tmp;
2598 target_siginfo_t info;
2599 int ret = 0;
2600
2601 addr = env->lock_addr;
2602 tmp = env->lock_st_addr;
2603 env->lock_addr = -1;
2604 env->lock_st_addr = 0;
2605
2606 start_exclusive();
2607 mmap_lock();
2608
2609 if (addr == tmp) {
2610 if (quad ? get_user_s64(val, addr) : get_user_s32(val, addr)) {
2611 goto do_sigsegv;
2612 }
2613
2614 if (val == env->lock_value) {
2615 tmp = env->ir[reg];
2616 if (quad ? put_user_u64(tmp, addr) : put_user_u32(tmp, addr)) {
2617 goto do_sigsegv;
2618 }
2619 ret = 1;
2620 }
2621 }
2622 env->ir[reg] = ret;
2623 env->pc += 4;
2624
2625 mmap_unlock();
2626 end_exclusive();
2627 return;
2628
2629 do_sigsegv:
2630 mmap_unlock();
2631 end_exclusive();
2632
2633 info.si_signo = TARGET_SIGSEGV;
2634 info.si_errno = 0;
2635 info.si_code = TARGET_SEGV_MAPERR;
2636 info._sifields._sigfault._addr = addr;
2637 queue_signal(env, TARGET_SIGSEGV, &info);
2638}
2639
7a3148a9
JM
2640void cpu_loop (CPUState *env)
2641{
e96efcfc 2642 int trapnr;
c227f099 2643 target_siginfo_t info;
6049f4f8 2644 abi_long sysret;
3b46e624 2645
7a3148a9
JM
2646 while (1) {
2647 trapnr = cpu_alpha_exec (env);
3b46e624 2648
ac316ca4
RH
2649 /* All of the traps imply a transition through PALcode, which
2650 implies an REI instruction has been executed. Which means
2651 that the intr_flag should be cleared. */
2652 env->intr_flag = 0;
2653
7a3148a9
JM
2654 switch (trapnr) {
2655 case EXCP_RESET:
2656 fprintf(stderr, "Reset requested. Exit\n");
2657 exit(1);
2658 break;
2659 case EXCP_MCHK:
2660 fprintf(stderr, "Machine check exception. Exit\n");
2661 exit(1);
2662 break;
07b6c13b
RH
2663 case EXCP_SMP_INTERRUPT:
2664 case EXCP_CLK_INTERRUPT:
2665 case EXCP_DEV_INTERRUPT:
5fafdf24 2666 fprintf(stderr, "External interrupt. Exit\n");
7a3148a9
JM
2667 exit(1);
2668 break;
07b6c13b 2669 case EXCP_MMFAULT:
6910b8f6 2670 env->lock_addr = -1;
6049f4f8
RH
2671 info.si_signo = TARGET_SIGSEGV;
2672 info.si_errno = 0;
129d8aa5 2673 info.si_code = (page_get_flags(env->trap_arg0) & PAGE_VALID
0be1d07c 2674 ? TARGET_SEGV_ACCERR : TARGET_SEGV_MAPERR);
129d8aa5 2675 info._sifields._sigfault._addr = env->trap_arg0;
6049f4f8 2676 queue_signal(env, info.si_signo, &info);
7a3148a9 2677 break;
7a3148a9 2678 case EXCP_UNALIGN:
6910b8f6 2679 env->lock_addr = -1;
6049f4f8
RH
2680 info.si_signo = TARGET_SIGBUS;
2681 info.si_errno = 0;
2682 info.si_code = TARGET_BUS_ADRALN;
129d8aa5 2683 info._sifields._sigfault._addr = env->trap_arg0;
6049f4f8 2684 queue_signal(env, info.si_signo, &info);
7a3148a9
JM
2685 break;
2686 case EXCP_OPCDEC:
6049f4f8 2687 do_sigill:
6910b8f6 2688 env->lock_addr = -1;
6049f4f8
RH
2689 info.si_signo = TARGET_SIGILL;
2690 info.si_errno = 0;
2691 info.si_code = TARGET_ILL_ILLOPC;
2692 info._sifields._sigfault._addr = env->pc;
2693 queue_signal(env, info.si_signo, &info);
7a3148a9 2694 break;
07b6c13b
RH
2695 case EXCP_ARITH:
2696 env->lock_addr = -1;
2697 info.si_signo = TARGET_SIGFPE;
2698 info.si_errno = 0;
2699 info.si_code = TARGET_FPE_FLTINV;
2700 info._sifields._sigfault._addr = env->pc;
2701 queue_signal(env, info.si_signo, &info);
2702 break;
7a3148a9 2703 case EXCP_FEN:
6049f4f8 2704 /* No-op. Linux simply re-enables the FPU. */
7a3148a9 2705 break;
07b6c13b 2706 case EXCP_CALL_PAL:
6910b8f6 2707 env->lock_addr = -1;
07b6c13b 2708 switch (env->error_code) {
6049f4f8
RH
2709 case 0x80:
2710 /* BPT */
2711 info.si_signo = TARGET_SIGTRAP;
2712 info.si_errno = 0;
2713 info.si_code = TARGET_TRAP_BRKPT;
2714 info._sifields._sigfault._addr = env->pc;
2715 queue_signal(env, info.si_signo, &info);
2716 break;
2717 case 0x81:
2718 /* BUGCHK */
2719 info.si_signo = TARGET_SIGTRAP;
2720 info.si_errno = 0;
2721 info.si_code = 0;
2722 info._sifields._sigfault._addr = env->pc;
2723 queue_signal(env, info.si_signo, &info);
2724 break;
2725 case 0x83:
2726 /* CALLSYS */
2727 trapnr = env->ir[IR_V0];
2728 sysret = do_syscall(env, trapnr,
2729 env->ir[IR_A0], env->ir[IR_A1],
2730 env->ir[IR_A2], env->ir[IR_A3],
5945cfcb
PM
2731 env->ir[IR_A4], env->ir[IR_A5],
2732 0, 0);
a5b3b13b
RH
2733 if (trapnr == TARGET_NR_sigreturn
2734 || trapnr == TARGET_NR_rt_sigreturn) {
2735 break;
2736 }
2737 /* Syscall writes 0 to V0 to bypass error check, similar
2738 to how this is handled internal to Linux kernel. */
2739 if (env->ir[IR_V0] == 0) {
2740 env->ir[IR_V0] = sysret;
2741 } else {
6049f4f8
RH
2742 env->ir[IR_V0] = (sysret < 0 ? -sysret : sysret);
2743 env->ir[IR_A3] = (sysret < 0);
2744 }
2745 break;
2746 case 0x86:
2747 /* IMB */
2748 /* ??? We can probably elide the code using page_unprotect
2749 that is checking for self-modifying code. Instead we
2750 could simply call tb_flush here. Until we work out the
2751 changes required to turn off the extra write protection,
2752 this can be a no-op. */
2753 break;
2754 case 0x9E:
2755 /* RDUNIQUE */
2756 /* Handled in the translator for usermode. */
2757 abort();
2758 case 0x9F:
2759 /* WRUNIQUE */
2760 /* Handled in the translator for usermode. */
2761 abort();
2762 case 0xAA:
2763 /* GENTRAP */
2764 info.si_signo = TARGET_SIGFPE;
2765 switch (env->ir[IR_A0]) {
2766 case TARGET_GEN_INTOVF:
2767 info.si_code = TARGET_FPE_INTOVF;
2768 break;
2769 case TARGET_GEN_INTDIV:
2770 info.si_code = TARGET_FPE_INTDIV;
2771 break;
2772 case TARGET_GEN_FLTOVF:
2773 info.si_code = TARGET_FPE_FLTOVF;
2774 break;
2775 case TARGET_GEN_FLTUND:
2776 info.si_code = TARGET_FPE_FLTUND;
2777 break;
2778 case TARGET_GEN_FLTINV:
2779 info.si_code = TARGET_FPE_FLTINV;
2780 break;
2781 case TARGET_GEN_FLTINE:
2782 info.si_code = TARGET_FPE_FLTRES;
2783 break;
2784 case TARGET_GEN_ROPRAND:
2785 info.si_code = 0;
2786 break;
2787 default:
2788 info.si_signo = TARGET_SIGTRAP;
2789 info.si_code = 0;
2790 break;
2791 }
2792 info.si_errno = 0;
2793 info._sifields._sigfault._addr = env->pc;
2794 queue_signal(env, info.si_signo, &info);
2795 break;
2796 default:
2797 goto do_sigill;
2798 }
7a3148a9 2799 break;
7a3148a9 2800 case EXCP_DEBUG:
6049f4f8
RH
2801 info.si_signo = gdb_handlesig (env, TARGET_SIGTRAP);
2802 if (info.si_signo) {
6910b8f6 2803 env->lock_addr = -1;
6049f4f8
RH
2804 info.si_errno = 0;
2805 info.si_code = TARGET_TRAP_BRKPT;
2806 queue_signal(env, info.si_signo, &info);
7a3148a9
JM
2807 }
2808 break;
6910b8f6
RH
2809 case EXCP_STL_C:
2810 case EXCP_STQ_C:
2811 do_store_exclusive(env, env->error_code, trapnr - EXCP_STL_C);
2812 break;
7a3148a9
JM
2813 default:
2814 printf ("Unhandled trap: 0x%x\n", trapnr);
2815 cpu_dump_state(env, stderr, fprintf, 0);
2816 exit (1);
2817 }
2818 process_pending_signals (env);
2819 }
2820}
2821#endif /* TARGET_ALPHA */
2822
a4c075f1
UH
2823#ifdef TARGET_S390X
2824void cpu_loop(CPUS390XState *env)
2825{
2826 int trapnr;
2827 target_siginfo_t info;
2828
2829 while (1) {
2830 trapnr = cpu_s390x_exec (env);
2831
2832 switch (trapnr) {
2833 case EXCP_INTERRUPT:
2834 /* just indicate that signals should be handled asap */
2835 break;
2836 case EXCP_DEBUG:
2837 {
2838 int sig;
2839
2840 sig = gdb_handlesig (env, TARGET_SIGTRAP);
2841 if (sig) {
2842 info.si_signo = sig;
2843 info.si_errno = 0;
2844 info.si_code = TARGET_TRAP_BRKPT;
2845 queue_signal(env, info.si_signo, &info);
2846 }
2847 }
2848 break;
2849 case EXCP_SVC:
2850 {
2851 int n = env->int_svc_code;
2852 if (!n) {
2853 /* syscalls > 255 */
2854 n = env->regs[1];
2855 }
2856 env->psw.addr += env->int_svc_ilc;
2857 env->regs[2] = do_syscall(env, n,
2858 env->regs[2],
2859 env->regs[3],
2860 env->regs[4],
2861 env->regs[5],
2862 env->regs[6],
5945cfcb
PM
2863 env->regs[7],
2864 0, 0);
a4c075f1
UH
2865 }
2866 break;
2867 case EXCP_ADDR:
2868 {
2869 info.si_signo = SIGSEGV;
2870 info.si_errno = 0;
2871 /* XXX: check env->error_code */
2872 info.si_code = TARGET_SEGV_MAPERR;
2873 info._sifields._sigfault._addr = env->__excp_addr;
2874 queue_signal(env, info.si_signo, &info);
2875 }
2876 break;
2877 case EXCP_SPEC:
2878 {
2879 fprintf(stderr,"specification exception insn 0x%08x%04x\n", ldl(env->psw.addr), lduw(env->psw.addr + 4));
2880 info.si_signo = SIGILL;
2881 info.si_errno = 0;
2882 info.si_code = TARGET_ILL_ILLOPC;
2883 info._sifields._sigfault._addr = env->__excp_addr;
2884 queue_signal(env, info.si_signo, &info);
2885 }
2886 break;
2887 default:
2888 printf ("Unhandled trap: 0x%x\n", trapnr);
2889 cpu_dump_state(env, stderr, fprintf, 0);
2890 exit (1);
2891 }
2892 process_pending_signals (env);
2893 }
2894}
2895
2896#endif /* TARGET_S390X */
2897
d5975363 2898THREAD CPUState *thread_env;
59faf6d6 2899
edf8e2af
MW
2900void task_settid(TaskState *ts)
2901{
2902 if (ts->ts_tid == 0) {
2f7bb878 2903#ifdef CONFIG_USE_NPTL
edf8e2af
MW
2904 ts->ts_tid = (pid_t)syscall(SYS_gettid);
2905#else
2906 /* when no threads are used, tid becomes pid */
2907 ts->ts_tid = getpid();
2908#endif
2909 }
2910}
2911
2912void stop_all_tasks(void)
2913{
2914 /*
2915 * We trust that when using NPTL, start_exclusive()
2916 * handles thread stopping correctly.
2917 */
2918 start_exclusive();
2919}
2920
c3a92833 2921/* Assumes contents are already zeroed. */
624f7979
PB
2922void init_task_state(TaskState *ts)
2923{
2924 int i;
2925
624f7979
PB
2926 ts->used = 1;
2927 ts->first_free = ts->sigqueue_table;
2928 for (i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++) {
2929 ts->sigqueue_table[i].next = &ts->sigqueue_table[i + 1];
2930 }
2931 ts->sigqueue_table[i].next = NULL;
2932}
fc9c5412
JS
2933
2934static void handle_arg_help(const char *arg)
2935{
2936 usage();
2937}
2938
2939static void handle_arg_log(const char *arg)
2940{
2941 int mask;
2942 const CPULogItem *item;
2943
2944 mask = cpu_str_to_log_mask(arg);
2945 if (!mask) {
2946 printf("Log items (comma separated):\n");
2947 for (item = cpu_log_items; item->mask != 0; item++) {
2948 printf("%-10s %s\n", item->name, item->help);
2949 }
2950 exit(1);
2951 }
2952 cpu_set_log(mask);
2953}
2954
2955static void handle_arg_set_env(const char *arg)
2956{
2957 char *r, *p, *token;
2958 r = p = strdup(arg);
2959 while ((token = strsep(&p, ",")) != NULL) {
2960 if (envlist_setenv(envlist, token) != 0) {
2961 usage();
2962 }
2963 }
2964 free(r);
2965}
2966
2967static void handle_arg_unset_env(const char *arg)
2968{
2969 char *r, *p, *token;
2970 r = p = strdup(arg);
2971 while ((token = strsep(&p, ",")) != NULL) {
2972 if (envlist_unsetenv(envlist, token) != 0) {
2973 usage();
2974 }
2975 }
2976 free(r);
2977}
2978
2979static void handle_arg_argv0(const char *arg)
2980{
2981 argv0 = strdup(arg);
2982}
2983
2984static void handle_arg_stack_size(const char *arg)
2985{
2986 char *p;
2987 guest_stack_size = strtoul(arg, &p, 0);
2988 if (guest_stack_size == 0) {
2989 usage();
2990 }
2991
2992 if (*p == 'M') {
2993 guest_stack_size *= 1024 * 1024;
2994 } else if (*p == 'k' || *p == 'K') {
2995 guest_stack_size *= 1024;
2996 }
2997}
2998
2999static void handle_arg_ld_prefix(const char *arg)
3000{
3001 interp_prefix = strdup(arg);
3002}
3003
3004static void handle_arg_pagesize(const char *arg)
3005{
3006 qemu_host_page_size = atoi(arg);
3007 if (qemu_host_page_size == 0 ||
3008 (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
3009 fprintf(stderr, "page size must be a power of two\n");
3010 exit(1);
3011 }
3012}
3013
3014static void handle_arg_gdb(const char *arg)
3015{
3016 gdbstub_port = atoi(arg);
3017}
3018
3019static void handle_arg_uname(const char *arg)
3020{
3021 qemu_uname_release = strdup(arg);
3022}
3023
3024static void handle_arg_cpu(const char *arg)
3025{
3026 cpu_model = strdup(arg);
3027 if (cpu_model == NULL || strcmp(cpu_model, "?") == 0) {
3028 /* XXX: implement xxx_cpu_list for targets that still miss it */
3029#if defined(cpu_list_id)
3030 cpu_list_id(stdout, &fprintf, "");
3031#elif defined(cpu_list)
3032 cpu_list(stdout, &fprintf); /* deprecated */
3033#endif
3034 exit(1);
3035 }
3036}
3037
3038#if defined(CONFIG_USE_GUEST_BASE)
3039static void handle_arg_guest_base(const char *arg)
3040{
3041 guest_base = strtol(arg, NULL, 0);
3042 have_guest_base = 1;
3043}
3044
3045static void handle_arg_reserved_va(const char *arg)
3046{
3047 char *p;
3048 int shift = 0;
3049 reserved_va = strtoul(arg, &p, 0);
3050 switch (*p) {
3051 case 'k':
3052 case 'K':
3053 shift = 10;
3054 break;
3055 case 'M':
3056 shift = 20;
3057 break;
3058 case 'G':
3059 shift = 30;
3060 break;
3061 }
3062 if (shift) {
3063 unsigned long unshifted = reserved_va;
3064 p++;
3065 reserved_va <<= shift;
3066 if (((reserved_va >> shift) != unshifted)
3067#if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS
3068 || (reserved_va > (1ul << TARGET_VIRT_ADDR_SPACE_BITS))
3069#endif
3070 ) {
3071 fprintf(stderr, "Reserved virtual address too big\n");
3072 exit(1);
3073 }
3074 }
3075 if (*p) {
3076 fprintf(stderr, "Unrecognised -R size suffix '%s'\n", p);
3077 exit(1);
3078 }
3079}
3080#endif
3081
3082static void handle_arg_singlestep(const char *arg)
3083{
3084 singlestep = 1;
3085}
3086
3087static void handle_arg_strace(const char *arg)
3088{
3089 do_strace = 1;
3090}
3091
3092static void handle_arg_version(const char *arg)
3093{
3094 printf("qemu-" TARGET_ARCH " version " QEMU_VERSION QEMU_PKGVERSION
3095 ", Copyright (c) 2003-2008 Fabrice Bellard\n");
1386d4c0 3096 exit(0);
fc9c5412
JS
3097}
3098
3099struct qemu_argument {
3100 const char *argv;
3101 const char *env;
3102 bool has_arg;
3103 void (*handle_opt)(const char *arg);
3104 const char *example;
3105 const char *help;
3106};
3107
3108struct qemu_argument arg_table[] = {
3109 {"h", "", false, handle_arg_help,
3110 "", "print this help"},
3111 {"g", "QEMU_GDB", true, handle_arg_gdb,
3112 "port", "wait gdb connection to 'port'"},
3113 {"L", "QEMU_LD_PREFIX", true, handle_arg_ld_prefix,
3114 "path", "set the elf interpreter prefix to 'path'"},
3115 {"s", "QEMU_STACK_SIZE", true, handle_arg_stack_size,
3116 "size", "set the stack size to 'size' bytes"},
3117 {"cpu", "QEMU_CPU", true, handle_arg_cpu,
3118 "model", "select CPU (-cpu ? for list)"},
3119 {"E", "QEMU_SET_ENV", true, handle_arg_set_env,
3120 "var=value", "sets targets environment variable (see below)"},
3121 {"U", "QEMU_UNSET_ENV", true, handle_arg_unset_env,
3122 "var", "unsets targets environment variable (see below)"},
3123 {"0", "QEMU_ARGV0", true, handle_arg_argv0,
3124 "argv0", "forces target process argv[0] to be 'argv0'"},
3125 {"r", "QEMU_UNAME", true, handle_arg_uname,
3126 "uname", "set qemu uname release string to 'uname'"},
3127#if defined(CONFIG_USE_GUEST_BASE)
3128 {"B", "QEMU_GUEST_BASE", true, handle_arg_guest_base,
3129 "address", "set guest_base address to 'address'"},
3130 {"R", "QEMU_RESERVED_VA", true, handle_arg_reserved_va,
3131 "size", "reserve 'size' bytes for guest virtual address space"},
3132#endif
3133 {"d", "QEMU_LOG", true, handle_arg_log,
3134 "options", "activate log"},
3135 {"p", "QEMU_PAGESIZE", true, handle_arg_pagesize,
3136 "pagesize", "set the host page size to 'pagesize'"},
3137 {"singlestep", "QEMU_SINGLESTEP", false, handle_arg_singlestep,
3138 "", "run in singlestep mode"},
3139 {"strace", "QEMU_STRACE", false, handle_arg_strace,
3140 "", "log system calls"},
3141 {"version", "QEMU_VERSION", false, handle_arg_version,
1386d4c0 3142 "", "display version information and exit"},
fc9c5412
JS
3143 {NULL, NULL, false, NULL, NULL, NULL}
3144};
3145
3146static void usage(void)
3147{
3148 struct qemu_argument *arginfo;
3149 int maxarglen;
3150 int maxenvlen;
3151
3152 printf("usage: qemu-" TARGET_ARCH " [options] program [arguments...]\n"
3153 "Linux CPU emulator (compiled for " TARGET_ARCH " emulation)\n"
3154 "\n"
3155 "Options and associated environment variables:\n"
3156 "\n");
3157
3158 maxarglen = maxenvlen = 0;
3159
3160 for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
3161 if (strlen(arginfo->env) > maxenvlen) {
3162 maxenvlen = strlen(arginfo->env);
3163 }
3164 if (strlen(arginfo->argv) > maxarglen) {
3165 maxarglen = strlen(arginfo->argv);
3166 }
3167 }
3168
3169 printf("%-*s%-*sDescription\n", maxarglen+3, "Argument",
3170 maxenvlen+1, "Env-variable");
3171
3172 for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
3173 if (arginfo->has_arg) {
3174 printf("-%s %-*s %-*s %s\n", arginfo->argv,
3175 (int)(maxarglen-strlen(arginfo->argv)), arginfo->example,
3176 maxenvlen, arginfo->env, arginfo->help);
3177 } else {
3178 printf("-%-*s %-*s %s\n", maxarglen+1, arginfo->argv,
3179 maxenvlen, arginfo->env,
3180 arginfo->help);
3181 }
3182 }
3183
3184 printf("\n"
3185 "Defaults:\n"
3186 "QEMU_LD_PREFIX = %s\n"
3187 "QEMU_STACK_SIZE = %ld byte\n"
3188 "QEMU_LOG = %s\n",
3189 interp_prefix,
3190 guest_stack_size,
3191 DEBUG_LOGFILE);
3192
3193 printf("\n"
3194 "You can use -E and -U options or the QEMU_SET_ENV and\n"
3195 "QEMU_UNSET_ENV environment variables to set and unset\n"
3196 "environment variables for the target process.\n"
3197 "It is possible to provide several variables by separating them\n"
3198 "by commas in getsubopt(3) style. Additionally it is possible to\n"
3199 "provide the -E and -U options multiple times.\n"
3200 "The following lines are equivalent:\n"
3201 " -E var1=val2 -E var2=val2 -U LD_PRELOAD -U LD_DEBUG\n"
3202 " -E var1=val2,var2=val2 -U LD_PRELOAD,LD_DEBUG\n"
3203 " QEMU_SET_ENV=var1=val2,var2=val2 QEMU_UNSET_ENV=LD_PRELOAD,LD_DEBUG\n"
3204 "Note that if you provide several changes to a single variable\n"
3205 "the last change will stay in effect.\n");
3206
3207 exit(1);
3208}
3209
3210static int parse_args(int argc, char **argv)
3211{
3212 const char *r;
3213 int optind;
3214 struct qemu_argument *arginfo;
3215
3216 for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
3217 if (arginfo->env == NULL) {
3218 continue;
3219 }
3220
3221 r = getenv(arginfo->env);
3222 if (r != NULL) {
3223 arginfo->handle_opt(r);
3224 }
3225 }
3226
3227 optind = 1;
3228 for (;;) {
3229 if (optind >= argc) {
3230 break;
3231 }
3232 r = argv[optind];
3233 if (r[0] != '-') {
3234 break;
3235 }
3236 optind++;
3237 r++;
3238 if (!strcmp(r, "-")) {
3239 break;
3240 }
3241
3242 for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
3243 if (!strcmp(r, arginfo->argv)) {
fc9c5412 3244 if (arginfo->has_arg) {
1386d4c0
PM
3245 if (optind >= argc) {
3246 usage();
3247 }
3248 arginfo->handle_opt(argv[optind]);
fc9c5412 3249 optind++;
1386d4c0
PM
3250 } else {
3251 arginfo->handle_opt(NULL);
fc9c5412 3252 }
fc9c5412
JS
3253 break;
3254 }
3255 }
3256
3257 /* no option matched the current argv */
3258 if (arginfo->handle_opt == NULL) {
3259 usage();
3260 }
3261 }
3262
3263 if (optind >= argc) {
3264 usage();
3265 }
3266
3267 filename = argv[optind];
3268 exec_path = argv[optind];
3269
3270 return optind;
3271}
3272
902b3d5c 3273int main(int argc, char **argv, char **envp)
31e31b8a 3274{
c235d738 3275 const char *log_file = DEBUG_LOGFILE;
01ffc75b 3276 struct target_pt_regs regs1, *regs = &regs1;
31e31b8a 3277 struct image_info info1, *info = &info1;
edf8e2af 3278 struct linux_binprm bprm;
48e15fc2 3279 TaskState *ts;
b346ff46 3280 CPUState *env;
586314f2 3281 int optind;
04a6dfeb 3282 char **target_environ, **wrk;
7d8cec95
AJ
3283 char **target_argv;
3284 int target_argc;
7d8cec95 3285 int i;
fd4d81dd 3286 int ret;
b12b6a18 3287
902b3d5c 3288 qemu_cache_utils_init(envp);
3289
04a6dfeb
AJ
3290 if ((envlist = envlist_create()) == NULL) {
3291 (void) fprintf(stderr, "Unable to allocate envlist\n");
3292 exit(1);
3293 }
3294
3295 /* add current environment into the list */
3296 for (wrk = environ; *wrk != NULL; wrk++) {
3297 (void) envlist_setenv(envlist, *wrk);
3298 }
3299
703e0e89
RH
3300 /* Read the stack limit from the kernel. If it's "unlimited",
3301 then we can do little else besides use the default. */
3302 {
3303 struct rlimit lim;
3304 if (getrlimit(RLIMIT_STACK, &lim) == 0
81bbe906 3305 && lim.rlim_cur != RLIM_INFINITY
3306 && lim.rlim_cur == (target_long)lim.rlim_cur) {
703e0e89
RH
3307 guest_stack_size = lim.rlim_cur;
3308 }
3309 }
3310
b1f9be31 3311 cpu_model = NULL;
b5ec5ce0 3312#if defined(cpudef_setup)
3313 cpudef_setup(); /* parse cpu definitions in target config file (TBD) */
3314#endif
3315
c235d738
MF
3316 /* init debug */
3317 cpu_set_log_filename(log_file);
fc9c5412 3318 optind = parse_args(argc, argv);
586314f2 3319
31e31b8a 3320 /* Zero out regs */
01ffc75b 3321 memset(regs, 0, sizeof(struct target_pt_regs));
31e31b8a
FB
3322
3323 /* Zero out image_info */
3324 memset(info, 0, sizeof(struct image_info));
3325
edf8e2af
MW
3326 memset(&bprm, 0, sizeof (bprm));
3327
74cd30b8
FB
3328 /* Scan interp_prefix dir for replacement files. */
3329 init_paths(interp_prefix);
3330
46027c07 3331 if (cpu_model == NULL) {
aaed909a 3332#if defined(TARGET_I386)
46027c07
FB
3333#ifdef TARGET_X86_64
3334 cpu_model = "qemu64";
3335#else
3336 cpu_model = "qemu32";
3337#endif
aaed909a 3338#elif defined(TARGET_ARM)
088ab16c 3339 cpu_model = "any";
d2fbca94
GX
3340#elif defined(TARGET_UNICORE32)
3341 cpu_model = "any";
aaed909a
FB
3342#elif defined(TARGET_M68K)
3343 cpu_model = "any";
3344#elif defined(TARGET_SPARC)
3345#ifdef TARGET_SPARC64
3346 cpu_model = "TI UltraSparc II";
3347#else
3348 cpu_model = "Fujitsu MB86904";
46027c07 3349#endif
aaed909a
FB
3350#elif defined(TARGET_MIPS)
3351#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64)
3352 cpu_model = "20Kc";
3353#else
3354 cpu_model = "24Kf";
3355#endif
3356#elif defined(TARGET_PPC)
7ded4f52 3357#ifdef TARGET_PPC64
f7177937 3358 cpu_model = "970fx";
7ded4f52 3359#else
aaed909a 3360 cpu_model = "750";
7ded4f52 3361#endif
aaed909a
FB
3362#else
3363 cpu_model = "any";
3364#endif
3365 }
d5ab9713
JK
3366 tcg_exec_init(0);
3367 cpu_exec_init_all();
83fb7adf
FB
3368 /* NOTE: we need to init the CPU at this stage to get
3369 qemu_host_page_size */
aaed909a
FB
3370 env = cpu_init(cpu_model);
3371 if (!env) {
3372 fprintf(stderr, "Unable to find CPU definition\n");
3373 exit(1);
3374 }
b55a37c9
BS
3375#if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC)
3376 cpu_reset(env);
3377#endif
3378
d5975363 3379 thread_env = env;
3b46e624 3380
b6741956
FB
3381 if (getenv("QEMU_STRACE")) {
3382 do_strace = 1;
b92c47c1
TS
3383 }
3384
04a6dfeb
AJ
3385 target_environ = envlist_to_environ(envlist, NULL);
3386 envlist_free(envlist);
b12b6a18 3387
379f6698
PB
3388#if defined(CONFIG_USE_GUEST_BASE)
3389 /*
3390 * Now that page sizes are configured in cpu_init() we can do
3391 * proper page alignment for guest_base.
3392 */
3393 guest_base = HOST_PAGE_ALIGN(guest_base);
68a1c816
PB
3394
3395 if (reserved_va) {
3396 void *p;
3397 int flags;
3398
3399 flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE;
3400 if (have_guest_base) {
3401 flags |= MAP_FIXED;
3402 }
3403 p = mmap((void *)guest_base, reserved_va, PROT_NONE, flags, -1, 0);
3404 if (p == MAP_FAILED) {
3405 fprintf(stderr, "Unable to reserve guest address space\n");
3406 exit(1);
3407 }
3408 guest_base = (unsigned long)p;
3409 /* Make sure the address is properly aligned. */
3410 if (guest_base & ~qemu_host_page_mask) {
3411 munmap(p, reserved_va);
3412 p = mmap((void *)guest_base, reserved_va + qemu_host_page_size,
3413 PROT_NONE, flags, -1, 0);
3414 if (p == MAP_FAILED) {
3415 fprintf(stderr, "Unable to reserve guest address space\n");
3416 exit(1);
3417 }
3418 guest_base = HOST_PAGE_ALIGN((unsigned long)p);
3419 }
3420 qemu_log("Reserved 0x%lx bytes of guest address space\n", reserved_va);
3421 }
97cc7560
DDAG
3422
3423 if (reserved_va || have_guest_base) {
3424 if (!guest_validate_base(guest_base)) {
3425 fprintf(stderr, "Guest base/Reserved VA rejected by guest code\n");
3426 exit(1);
3427 }
3428 }
14f24e14 3429#endif /* CONFIG_USE_GUEST_BASE */
379f6698
PB
3430
3431 /*
3432 * Read in mmap_min_addr kernel parameter. This value is used
3433 * When loading the ELF image to determine whether guest_base
14f24e14 3434 * is needed. It is also used in mmap_find_vma.
379f6698 3435 */
14f24e14 3436 {
379f6698
PB
3437 FILE *fp;
3438
3439 if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) {
3440 unsigned long tmp;
3441 if (fscanf(fp, "%lu", &tmp) == 1) {
3442 mmap_min_addr = tmp;
3443 qemu_log("host mmap_min_addr=0x%lx\n", mmap_min_addr);
3444 }
3445 fclose(fp);
3446 }
3447 }
379f6698 3448
7d8cec95
AJ
3449 /*
3450 * Prepare copy of argv vector for target.
3451 */
3452 target_argc = argc - optind;
3453 target_argv = calloc(target_argc + 1, sizeof (char *));
3454 if (target_argv == NULL) {
3455 (void) fprintf(stderr, "Unable to allocate memory for target_argv\n");
3456 exit(1);
3457 }
3458
3459 /*
3460 * If argv0 is specified (using '-0' switch) we replace
3461 * argv[0] pointer with the given one.
3462 */
3463 i = 0;
3464 if (argv0 != NULL) {
3465 target_argv[i++] = strdup(argv0);
3466 }
3467 for (; i < target_argc; i++) {
3468 target_argv[i] = strdup(argv[optind + i]);
3469 }
3470 target_argv[target_argc] = NULL;
3471
7267c094 3472 ts = g_malloc0 (sizeof(TaskState));
edf8e2af
MW
3473 init_task_state(ts);
3474 /* build Task State */
3475 ts->info = info;
3476 ts->bprm = &bprm;
3477 env->opaque = ts;
3478 task_settid(ts);
3479
fd4d81dd
AP
3480 ret = loader_exec(filename, target_argv, target_environ, regs,
3481 info, &bprm);
3482 if (ret != 0) {
3483 printf("Error %d while loading %s\n", ret, filename);
b12b6a18
TS
3484 _exit(1);
3485 }
3486
7d8cec95
AJ
3487 for (i = 0; i < target_argc; i++) {
3488 free(target_argv[i]);
3489 }
3490 free(target_argv);
3491
b12b6a18
TS
3492 for (wrk = target_environ; *wrk; wrk++) {
3493 free(*wrk);
31e31b8a 3494 }
3b46e624 3495
b12b6a18
TS
3496 free(target_environ);
3497
2e77eac6 3498 if (qemu_log_enabled()) {
379f6698
PB
3499#if defined(CONFIG_USE_GUEST_BASE)
3500 qemu_log("guest_base 0x%lx\n", guest_base);
3501#endif
2e77eac6
BS
3502 log_page_dump();
3503
3504 qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk);
3505 qemu_log("end_code 0x" TARGET_ABI_FMT_lx "\n", info->end_code);
3506 qemu_log("start_code 0x" TARGET_ABI_FMT_lx "\n",
3507 info->start_code);
3508 qemu_log("start_data 0x" TARGET_ABI_FMT_lx "\n",
3509 info->start_data);
3510 qemu_log("end_data 0x" TARGET_ABI_FMT_lx "\n", info->end_data);
3511 qemu_log("start_stack 0x" TARGET_ABI_FMT_lx "\n",
3512 info->start_stack);
3513 qemu_log("brk 0x" TARGET_ABI_FMT_lx "\n", info->brk);
3514 qemu_log("entry 0x" TARGET_ABI_FMT_lx "\n", info->entry);
3515 }
31e31b8a 3516
53a5960a 3517 target_set_brk(info->brk);
31e31b8a 3518 syscall_init();
66fb9763 3519 signal_init();
31e31b8a 3520
9002ec79
RH
3521#if defined(CONFIG_USE_GUEST_BASE)
3522 /* Now that we've loaded the binary, GUEST_BASE is fixed. Delay
3523 generating the prologue until now so that the prologue can take
3524 the real value of GUEST_BASE into account. */
3525 tcg_prologue_init(&tcg_ctx);
3526#endif
3527
b346ff46 3528#if defined(TARGET_I386)
2e255c6b
FB
3529 cpu_x86_set_cpl(env, 3);
3530
3802ce26 3531 env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
1bde465e
FB
3532 env->hflags |= HF_PE_MASK;
3533 if (env->cpuid_features & CPUID_SSE) {
3534 env->cr[4] |= CR4_OSFXSR_MASK;
3535 env->hflags |= HF_OSFXSR_MASK;
3536 }
d2fd1af7 3537#ifndef TARGET_ABI32
4dbc422b
FB
3538 /* enable 64 bit mode if possible */
3539 if (!(env->cpuid_ext2_features & CPUID_EXT2_LM)) {
3540 fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n");
3541 exit(1);
3542 }
d2fd1af7 3543 env->cr[4] |= CR4_PAE_MASK;
4dbc422b 3544 env->efer |= MSR_EFER_LMA | MSR_EFER_LME;
d2fd1af7
FB
3545 env->hflags |= HF_LMA_MASK;
3546#endif
1bde465e 3547
415e561f
FB
3548 /* flags setup : we activate the IRQs by default as in user mode */
3549 env->eflags |= IF_MASK;
3b46e624 3550
6dbad63e 3551 /* linux register setup */
d2fd1af7 3552#ifndef TARGET_ABI32
84409ddb
JM
3553 env->regs[R_EAX] = regs->rax;
3554 env->regs[R_EBX] = regs->rbx;
3555 env->regs[R_ECX] = regs->rcx;
3556 env->regs[R_EDX] = regs->rdx;
3557 env->regs[R_ESI] = regs->rsi;
3558 env->regs[R_EDI] = regs->rdi;
3559 env->regs[R_EBP] = regs->rbp;
3560 env->regs[R_ESP] = regs->rsp;
3561 env->eip = regs->rip;
3562#else
0ecfa993
FB
3563 env->regs[R_EAX] = regs->eax;
3564 env->regs[R_EBX] = regs->ebx;
3565 env->regs[R_ECX] = regs->ecx;
3566 env->regs[R_EDX] = regs->edx;
3567 env->regs[R_ESI] = regs->esi;
3568 env->regs[R_EDI] = regs->edi;
3569 env->regs[R_EBP] = regs->ebp;
3570 env->regs[R_ESP] = regs->esp;
dab2ed99 3571 env->eip = regs->eip;
84409ddb 3572#endif
31e31b8a 3573
f4beb510 3574 /* linux interrupt setup */
e441570f
AZ
3575#ifndef TARGET_ABI32
3576 env->idt.limit = 511;
3577#else
3578 env->idt.limit = 255;
3579#endif
3580 env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1),
3581 PROT_READ|PROT_WRITE,
3582 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
3583 idt_table = g2h(env->idt.base);
f4beb510
FB
3584 set_idt(0, 0);
3585 set_idt(1, 0);
3586 set_idt(2, 0);
3587 set_idt(3, 3);
3588 set_idt(4, 3);
ec95da6c 3589 set_idt(5, 0);
f4beb510
FB
3590 set_idt(6, 0);
3591 set_idt(7, 0);
3592 set_idt(8, 0);
3593 set_idt(9, 0);
3594 set_idt(10, 0);
3595 set_idt(11, 0);
3596 set_idt(12, 0);
3597 set_idt(13, 0);
3598 set_idt(14, 0);
3599 set_idt(15, 0);
3600 set_idt(16, 0);
3601 set_idt(17, 0);
3602 set_idt(18, 0);
3603 set_idt(19, 0);
3604 set_idt(0x80, 3);
3605
6dbad63e 3606 /* linux segment setup */
8d18e893
FB
3607 {
3608 uint64_t *gdt_table;
e441570f
AZ
3609 env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES,
3610 PROT_READ|PROT_WRITE,
3611 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
8d18e893 3612 env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1;
e441570f 3613 gdt_table = g2h(env->gdt.base);
d2fd1af7 3614#ifdef TARGET_ABI32
8d18e893
FB
3615 write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
3616 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
3617 (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
d2fd1af7
FB
3618#else
3619 /* 64 bit code segment */
3620 write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
3621 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
3622 DESC_L_MASK |
3623 (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
3624#endif
8d18e893
FB
3625 write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
3626 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
3627 (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
3628 }
6dbad63e 3629 cpu_x86_load_seg(env, R_CS, __USER_CS);
d2fd1af7
FB
3630 cpu_x86_load_seg(env, R_SS, __USER_DS);
3631#ifdef TARGET_ABI32
6dbad63e
FB
3632 cpu_x86_load_seg(env, R_DS, __USER_DS);
3633 cpu_x86_load_seg(env, R_ES, __USER_DS);
6dbad63e
FB
3634 cpu_x86_load_seg(env, R_FS, __USER_DS);
3635 cpu_x86_load_seg(env, R_GS, __USER_DS);
d6eb40f6
TS
3636 /* This hack makes Wine work... */
3637 env->segs[R_FS].selector = 0;
d2fd1af7
FB
3638#else
3639 cpu_x86_load_seg(env, R_DS, 0);
3640 cpu_x86_load_seg(env, R_ES, 0);
3641 cpu_x86_load_seg(env, R_FS, 0);
3642 cpu_x86_load_seg(env, R_GS, 0);
3643#endif
b346ff46
FB
3644#elif defined(TARGET_ARM)
3645 {
3646 int i;
b5ff1b31 3647 cpsr_write(env, regs->uregs[16], 0xffffffff);
b346ff46
FB
3648 for(i = 0; i < 16; i++) {
3649 env->regs[i] = regs->uregs[i];
3650 }
b346ff46 3651 }
d2fbca94
GX
3652#elif defined(TARGET_UNICORE32)
3653 {
3654 int i;
3655 cpu_asr_write(env, regs->uregs[32], 0xffffffff);
3656 for (i = 0; i < 32; i++) {
3657 env->regs[i] = regs->uregs[i];
3658 }
3659 }
93ac68bc 3660#elif defined(TARGET_SPARC)
060366c5
FB
3661 {
3662 int i;
3663 env->pc = regs->pc;
3664 env->npc = regs->npc;
3665 env->y = regs->y;
3666 for(i = 0; i < 8; i++)
3667 env->gregs[i] = regs->u_regs[i];
3668 for(i = 0; i < 8; i++)
3669 env->regwptr[i] = regs->u_regs[i + 8];
3670 }
67867308
FB
3671#elif defined(TARGET_PPC)
3672 {
3673 int i;
3fc6c082 3674
0411a972
JM
3675#if defined(TARGET_PPC64)
3676#if defined(TARGET_ABI32)
3677 env->msr &= ~((target_ulong)1 << MSR_SF);
e85e7c6e 3678#else
0411a972
JM
3679 env->msr |= (target_ulong)1 << MSR_SF;
3680#endif
84409ddb 3681#endif
67867308
FB
3682 env->nip = regs->nip;
3683 for(i = 0; i < 32; i++) {
3684 env->gpr[i] = regs->gpr[i];
3685 }
3686 }
e6e5906b
PB
3687#elif defined(TARGET_M68K)
3688 {
e6e5906b
PB
3689 env->pc = regs->pc;
3690 env->dregs[0] = regs->d0;
3691 env->dregs[1] = regs->d1;
3692 env->dregs[2] = regs->d2;
3693 env->dregs[3] = regs->d3;
3694 env->dregs[4] = regs->d4;
3695 env->dregs[5] = regs->d5;
3696 env->dregs[6] = regs->d6;
3697 env->dregs[7] = regs->d7;
3698 env->aregs[0] = regs->a0;
3699 env->aregs[1] = regs->a1;
3700 env->aregs[2] = regs->a2;
3701 env->aregs[3] = regs->a3;
3702 env->aregs[4] = regs->a4;
3703 env->aregs[5] = regs->a5;
3704 env->aregs[6] = regs->a6;
3705 env->aregs[7] = regs->usp;
3706 env->sr = regs->sr;
3707 ts->sim_syscalls = 1;
3708 }
b779e29e
EI
3709#elif defined(TARGET_MICROBLAZE)
3710 {
3711 env->regs[0] = regs->r0;
3712 env->regs[1] = regs->r1;
3713 env->regs[2] = regs->r2;
3714 env->regs[3] = regs->r3;
3715 env->regs[4] = regs->r4;
3716 env->regs[5] = regs->r5;
3717 env->regs[6] = regs->r6;
3718 env->regs[7] = regs->r7;
3719 env->regs[8] = regs->r8;
3720 env->regs[9] = regs->r9;
3721 env->regs[10] = regs->r10;
3722 env->regs[11] = regs->r11;
3723 env->regs[12] = regs->r12;
3724 env->regs[13] = regs->r13;
3725 env->regs[14] = regs->r14;
3726 env->regs[15] = regs->r15;
3727 env->regs[16] = regs->r16;
3728 env->regs[17] = regs->r17;
3729 env->regs[18] = regs->r18;
3730 env->regs[19] = regs->r19;
3731 env->regs[20] = regs->r20;
3732 env->regs[21] = regs->r21;
3733 env->regs[22] = regs->r22;
3734 env->regs[23] = regs->r23;
3735 env->regs[24] = regs->r24;
3736 env->regs[25] = regs->r25;
3737 env->regs[26] = regs->r26;
3738 env->regs[27] = regs->r27;
3739 env->regs[28] = regs->r28;
3740 env->regs[29] = regs->r29;
3741 env->regs[30] = regs->r30;
3742 env->regs[31] = regs->r31;
3743 env->sregs[SR_PC] = regs->pc;
3744 }
048f6b4d
FB
3745#elif defined(TARGET_MIPS)
3746 {
3747 int i;
3748
3749 for(i = 0; i < 32; i++) {
b5dc7732 3750 env->active_tc.gpr[i] = regs->regs[i];
048f6b4d 3751 }
0fddbbf2
NF
3752 env->active_tc.PC = regs->cp0_epc & ~(target_ulong)1;
3753 if (regs->cp0_epc & 1) {
3754 env->hflags |= MIPS_HFLAG_M16;
3755 }
048f6b4d 3756 }
fdf9b3e8
FB
3757#elif defined(TARGET_SH4)
3758 {
3759 int i;
3760
3761 for(i = 0; i < 16; i++) {
3762 env->gregs[i] = regs->regs[i];
3763 }
3764 env->pc = regs->pc;
3765 }
7a3148a9
JM
3766#elif defined(TARGET_ALPHA)
3767 {
3768 int i;
3769
3770 for(i = 0; i < 28; i++) {
992f48a0 3771 env->ir[i] = ((abi_ulong *)regs)[i];
7a3148a9 3772 }
dad081ee 3773 env->ir[IR_SP] = regs->usp;
7a3148a9 3774 env->pc = regs->pc;
7a3148a9 3775 }
48733d19
TS
3776#elif defined(TARGET_CRIS)
3777 {
3778 env->regs[0] = regs->r0;
3779 env->regs[1] = regs->r1;
3780 env->regs[2] = regs->r2;
3781 env->regs[3] = regs->r3;
3782 env->regs[4] = regs->r4;
3783 env->regs[5] = regs->r5;
3784 env->regs[6] = regs->r6;
3785 env->regs[7] = regs->r7;
3786 env->regs[8] = regs->r8;
3787 env->regs[9] = regs->r9;
3788 env->regs[10] = regs->r10;
3789 env->regs[11] = regs->r11;
3790 env->regs[12] = regs->r12;
3791 env->regs[13] = regs->r13;
3792 env->regs[14] = info->start_stack;
3793 env->regs[15] = regs->acr;
3794 env->pc = regs->erp;
3795 }
a4c075f1
UH
3796#elif defined(TARGET_S390X)
3797 {
3798 int i;
3799 for (i = 0; i < 16; i++) {
3800 env->regs[i] = regs->gprs[i];
3801 }
3802 env->psw.mask = regs->psw.mask;
3803 env->psw.addr = regs->psw.addr;
3804 }
b346ff46
FB
3805#else
3806#error unsupported target CPU
3807#endif
31e31b8a 3808
d2fbca94 3809#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)
a87295e8
PB
3810 ts->stack_base = info->start_stack;
3811 ts->heap_base = info->brk;
3812 /* This will be filled in on the first SYS_HEAPINFO call. */
3813 ts->heap_limit = 0;
3814#endif
3815
74c33bed 3816 if (gdbstub_port) {
ff7a981a
PM
3817 if (gdbserver_start(gdbstub_port) < 0) {
3818 fprintf(stderr, "qemu: could not open gdbserver on port %d\n",
3819 gdbstub_port);
3820 exit(1);
3821 }
1fddef4b
FB
3822 gdb_handlesig(env, 0);
3823 }
1b6b029e
FB
3824 cpu_loop(env);
3825 /* never exits */
31e31b8a
FB
3826 return 0;
3827}