aboutsummaryrefslogtreecommitdiff
path: root/linux-user/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux-user/main.c')
-rw-r--r--linux-user/main.c52
1 files changed, 45 insertions, 7 deletions
diff --git a/linux-user/main.c b/linux-user/main.c
index bcaa4be161..fba23a0132 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -33,7 +33,10 @@
FILE *logfile = NULL;
int loglevel;
-unsigned long x86_stack_size;
+/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
+ we allocate a bigger stack. Need a better solution, for example
+ by remapping the process stack directly at the right place */
+unsigned long x86_stack_size = 512 * 1024;
unsigned long stktop;
void gemu_log(const char *fmt, ...)
@@ -102,10 +105,11 @@ uint64_t gdt_table[6];
void cpu_loop(struct CPUX86State *env)
{
+ int err;
+ uint8_t *pc;
+ target_siginfo_t info;
+
for(;;) {
- int err;
- uint8_t *pc;
-
err = cpu_x86_exec(env);
pc = env->seg_cache[R_CS].base + env->eip;
switch(err) {
@@ -122,12 +126,42 @@ void cpu_loop(struct CPUX86State *env)
env->regs[R_EDI],
env->regs[R_EBP]);
} else {
- goto trap_error;
+ /* XXX: more precise info */
+ info.si_signo = SIGSEGV;
+ info.si_errno = 0;
+ info.si_code = 0;
+ info._sifields._sigfault._addr = 0;
+ queue_signal(info.si_signo, &info);
}
break;
+ case EXCP00_DIVZ:
+ /* division by zero */
+ info.si_signo = SIGFPE;
+ info.si_errno = 0;
+ info.si_code = TARGET_FPE_INTDIV;
+ info._sifields._sigfault._addr = env->eip;
+ queue_signal(info.si_signo, &info);
+ break;
+ case EXCP04_INTO:
+ case EXCP05_BOUND:
+ info.si_signo = SIGSEGV;
+ info.si_errno = 0;
+ info.si_code = 0;
+ info._sifields._sigfault._addr = 0;
+ queue_signal(info.si_signo, &info);
+ break;
+ case EXCP06_ILLOP:
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ info.si_code = TARGET_ILL_ILLOPN;
+ info._sifields._sigfault._addr = env->eip;
+ queue_signal(info.si_signo, &info);
+ break;
+ case EXCP_INTERRUPT:
+ /* just indicate that signals should be handled asap */
+ break;
default:
- trap_error:
- fprintf(stderr, "0x%08lx: Unknown exception %d, aborting\n",
+ fprintf(stderr, "0x%08lx: Unknown exception CPU %d, aborting\n",
(long)pc, err);
abort();
}
@@ -144,6 +178,9 @@ void usage(void)
exit(1);
}
+/* XXX: currently only used for async signals (see signal.c) */
+CPUX86State *global_env;
+
int main(int argc, char **argv)
{
const char *filename;
@@ -199,6 +236,7 @@ int main(int argc, char **argv)
signal_init();
env = cpu_x86_init();
+ global_env = env;
/* linux register setup */
env->regs[R_EAX] = regs->eax;