X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=linux-user%2Fsignal.c;h=74aaeea681650d21627c52353da002ed9860f8de;hb=a1516e92b6ed887ef27f3a33a27a9acd772a5de4;hp=04779c82cfdfe469a2d86f501992444d16c3302b;hpb=d1f2367bc00099e9782891fd57cab2ebcf977fda;p=qemu diff --git a/linux-user/signal.c b/linux-user/signal.c index 04779c8..74aaeea 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -21,10 +21,18 @@ #include #include #include +#include #include #include #include +#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);