ARM init fix
[qemu] / linux-user / signal.c
index 04779c8..74aaeea 100644 (file)
 #include <stdio.h>
 #include <string.h>
 #include <stdarg.h>
+#include <unistd.h>
 #include <signal.h>
 #include <errno.h>
 #include <sys/ucontext.h>
 
+#ifdef __ia64__
+#undef uc_mcontext
+#undef uc_sigmask
+#undef uc_stack
+#undef uc_link
+#endif 
+
 #include "qemu.h"
 
 //#define DEBUG_SIGNAL
@@ -102,7 +110,8 @@ static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
     tinfo->si_signo = sig;
     tinfo->si_errno = 0;
     tinfo->si_code = 0;
-    if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || sig == SIGBUS) {
+    if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || 
+        sig == SIGBUS || sig == SIGTRAP) {
         /* should never come here, but who knows. The information for
            the target is irrelevant */
         tinfo->_sifields._sigfault._addr = 0;
@@ -123,7 +132,8 @@ static void tswap_siginfo(target_siginfo_t *tinfo,
     tinfo->si_signo = tswap32(sig);
     tinfo->si_errno = tswap32(info->si_errno);
     tinfo->si_code = tswap32(info->si_code);
-    if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || sig == SIGBUS) {
+    if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || 
+        sig == SIGBUS || sig == SIGTRAP) {
         tinfo->_sifields._sigfault._addr = 
             tswapl(info->_sifields._sigfault._addr);
     } else if (sig >= TARGET_SIGRTMIN) {
@@ -165,7 +175,7 @@ void signal_init(void)
     act.sa_flags = SA_SIGINFO;
     act.sa_sigaction = host_signal_handler;
     for(i = 1; i < NSIG; i++) {
-       sigaction(i, &act, NULL);
+        sigaction(i, &act, NULL);
     }
     
     memset(sigact_table, 0, sizeof(sigact_table));
@@ -198,7 +208,7 @@ void __attribute((noreturn)) force_sig(int sig)
 {
     int host_sig;
     host_sig = target_to_host_signal(sig);
-    fprintf(stderr, "gemu: uncaught target signal %d (%s) - exiting\n", 
+    fprintf(stderr, "qemu: uncaught target signal %d (%s) - exiting\n", 
             sig, strsignal(host_sig));
 #if 1
     _exit(-host_sig);
@@ -223,7 +233,7 @@ int queue_signal(int sig, target_siginfo_t *info)
     target_ulong handler;
 
 #if defined(DEBUG_SIGNAL)
-    fprintf(stderr, "queue_sigal: sig=%d\n", 
+    fprintf(stderr, "queue_signal: sig=%d\n", 
             sig);
 #endif
     k = &sigact_table[sig - 1];
@@ -308,7 +318,7 @@ static void host_signal_handler(int host_signum, siginfo_t *info,
     /* the CPU emulator uses some host signals to detect exceptions,
        we we forward to it some signals */
     if (host_signum == SIGSEGV || host_signum == SIGBUS) {
-        if (cpu_x86_signal_handler(host_signum, info, puc))
+        if (cpu_signal_handler(host_signum, info, puc))
             return;
     }
 
@@ -317,13 +327,13 @@ static void host_signal_handler(int host_signum, siginfo_t *info,
     if (sig < 1 || sig > TARGET_NSIG)
         return;
 #if defined(DEBUG_SIGNAL)
-    fprintf(stderr, "gemu: got signal %d\n", sig);
+    fprintf(stderr, "qemu: got signal %d\n", sig);
     dump_regs(puc);
 #endif
     host_to_target_siginfo_noswap(&tinfo, info);
     if (queue_signal(sig, &tinfo) == 1) {
         /* interrupt the virtual CPU as soon as possible */
-        cpu_x86_interrupt(global_env);
+        cpu_interrupt(global_env, CPU_INTERRUPT_EXIT);
     }
 }
 
@@ -507,10 +517,10 @@ setup_sigcontext(struct target_sigcontext *sc, struct target_fpstate *fpstate,
 {
        int err = 0;
 
-       err |= __put_user(env->segs[R_GS], (unsigned int *)&sc->gs);
-       err |= __put_user(env->segs[R_FS], (unsigned int *)&sc->fs);
-       err |= __put_user(env->segs[R_ES], (unsigned int *)&sc->es);
-       err |= __put_user(env->segs[R_DS], (unsigned int *)&sc->ds);
+       err |= __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs);
+       err |= __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs);
+       err |= __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es);
+       err |= __put_user(env->segs[R_DS].selector, (unsigned int *)&sc->ds);
        err |= __put_user(env->regs[R_EDI], &sc->edi);
        err |= __put_user(env->regs[R_ESI], &sc->esi);
        err |= __put_user(env->regs[R_EBP], &sc->ebp);
@@ -519,26 +529,22 @@ setup_sigcontext(struct target_sigcontext *sc, struct target_fpstate *fpstate,
        err |= __put_user(env->regs[R_EDX], &sc->edx);
        err |= __put_user(env->regs[R_ECX], &sc->ecx);
        err |= __put_user(env->regs[R_EAX], &sc->eax);
-       err |= __put_user(/*current->thread.trap_no*/ 0, &sc->trapno);
-       err |= __put_user(/*current->thread.error_code*/ 0, &sc->err);
+       err |= __put_user(env->exception_index, &sc->trapno);
+       err |= __put_user(env->error_code, &sc->err);
        err |= __put_user(env->eip, &sc->eip);
-       err |= __put_user(env->segs[R_CS], (unsigned int *)&sc->cs);
+       err |= __put_user(env->segs[R_CS].selector, (unsigned int *)&sc->cs);
        err |= __put_user(env->eflags, &sc->eflags);
        err |= __put_user(env->regs[R_ESP], &sc->esp_at_signal);
-       err |= __put_user(env->segs[R_SS], (unsigned int *)&sc->ss);
-#if 0
-       tmp = save_i387(fpstate);
-       if (tmp < 0)
-         err = 1;
-       else
-         err |= __put_user(tmp ? fpstate : NULL, &sc->fpstate);
-#else
-        err |= __put_user(0, &sc->fpstate);
-#endif
+       err |= __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss);
+
+        cpu_x86_fsave(env, (void *)fpstate, 1);
+        fpstate->status = fpstate->sw;
+        err |= __put_user(0xffff, &fpstate->magic);
+        err |= __put_user(fpstate, &sc->fpstate);
+
        /* non-iBCS2 extensions.. */
        err |= __put_user(mask, &sc->oldmask);
-       err |= __put_user(/*current->thread.cr2*/ 0, &sc->cr2);
-
+       err |= __put_user(env->cr[2], &sc->cr2);
        return err;
 }
 
@@ -561,13 +567,14 @@ get_sigframe(struct emulated_sigaction *ka, CPUX86State *env, size_t frame_size)
        }
 
        /* This is the legacy signal stack switching. */
-       else if ((regs->xss & 0xffff) != __USER_DS &&
-                !(ka->sa.sa_flags & SA_RESTORER) &&
-                ka->sa.sa_restorer) {
-               esp = (unsigned long) ka->sa.sa_restorer;
-       }
+       else 
 #endif
-       return (void *)((esp - frame_size) & -8ul);
+        if ((env->segs[R_SS].selector & 0xffff) != __USER_DS &&
+            !(ka->sa.sa_flags & TARGET_SA_RESTORER) &&
+            ka->sa.sa_restorer) {
+            esp = (unsigned long) ka->sa.sa_restorer;
+       }
+        return (void *)((esp - frame_size) & -8ul);
 }
 
 static void setup_frame(int sig, struct emulated_sigaction *ka,
@@ -712,25 +719,6 @@ restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax)
 {
        unsigned int err = 0;
 
-
-        
-#define COPY(x)                err |= __get_user(regs->x, &sc->x)
-
-#define COPY_SEG(seg)                                                  \
-       { unsigned short tmp;                                           \
-         err |= __get_user(tmp, &sc->seg);                             \
-         regs->x##seg = tmp; }
-
-#define COPY_SEG_STRICT(seg)                                           \
-       { unsigned short tmp;                                           \
-         err |= __get_user(tmp, &sc->seg);                             \
-         regs->x##seg = tmp|3; }
-
-#define GET_SEG(seg)                                                   \
-       { unsigned short tmp;                                           \
-         err |= __get_user(tmp, &sc->seg);                             \
-         loadsegment(seg,tmp); }
-
         cpu_x86_load_seg(env, R_GS, lduw(&sc->gs));
         cpu_x86_load_seg(env, R_FS, lduw(&sc->fs));
         cpu_x86_load_seg(env, R_ES, lduw(&sc->es));
@@ -755,17 +743,18 @@ restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax)
                 //             regs->orig_eax = -1;            /* disable syscall checks */
        }
 
-#if 0
        {
                struct _fpstate * buf;
-               err |= __get_user(buf, &sc->fpstate);
+                buf = (void *)ldl(&sc->fpstate);
                if (buf) {
+#if 0
                        if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
                                goto badframe;
-                       err |= restore_i387(buf);
+#endif
+                        cpu_x86_frstor(env, (void *)buf, 1);
                }
        }
-#endif
+
         *peax = ldl(&sc->eax);
        return err;
 #if 0
@@ -781,6 +770,9 @@ long do_sigreturn(CPUX86State *env)
     sigset_t set;
     int eax, i;
 
+#if defined(DEBUG_SIGNAL)
+    fprintf(stderr, "do_sigreturn\n");
+#endif
     /* set blocked signals */
     target_set.sig[0] = frame->sc.oldmask;
     for(i = 1; i < TARGET_NSIG_WORDS; i++)
@@ -833,6 +825,33 @@ badframe:
        return 0;
 }
 
+#else
+
+static void setup_frame(int sig, struct emulated_sigaction *ka,
+                       target_sigset_t *set, CPUState *env)
+{
+    fprintf(stderr, "setup_frame: not implemented\n");
+}
+
+static void setup_rt_frame(int sig, struct emulated_sigaction *ka, 
+                           target_siginfo_t *info,
+                          target_sigset_t *set, CPUState *env)
+{
+    fprintf(stderr, "setup_rt_frame: not implemented\n");
+}
+
+long do_sigreturn(CPUState *env)
+{
+    fprintf(stderr, "do_sigreturn: not implemented\n");
+    return -ENOSYS;
+}
+
+long do_rt_sigreturn(CPUState *env)
+{
+    fprintf(stderr, "do_rt_sigreturn: not implemented\n");
+    return -ENOSYS;
+}
+
 #endif
 
 void process_pending_signals(void *cpu_env)
@@ -859,7 +878,7 @@ void process_pending_signals(void *cpu_env)
 
  handle_signal:
 #ifdef DEBUG_SIGNAL
-    fprintf(stderr, "gemu: process signal %d\n", sig);
+    fprintf(stderr, "qemu: process signal %d\n", sig);
 #endif
     /* dequeue signal */
     q = k->first;
@@ -893,6 +912,14 @@ void process_pending_signals(void *cpu_env)
            end of the signal execution (see do_sigreturn) */
         host_to_target_sigset(&target_old_set, &old_set);
 
+        /* if the CPU is in VM86 mode, we restore the 32 bit values */
+#ifdef TARGET_I386
+        {
+            CPUX86State *env = cpu_env;
+            if (env->eflags & VM_MASK)
+                save_v86_state(env);
+        }
+#endif
         /* prepare the stack frame of the virtual CPU */
         if (k->sa.sa_flags & TARGET_SA_SIGINFO)
             setup_rt_frame(sig, k, &q->info, &target_old_set, cpu_env);