⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 signal.c

📁 qemu性能直逼VMware的仿真器QEMU 的模擬速度約為實機的 25%;約為 Bochs 的 60 倍。Plex86、User-Mode-Linux、VMware 和 Virtual PC 則比
💻 C
📖 第 1 页 / 共 4 页
字号:
        target_ulong fpu_save;        int err, i;        sf = (struct target_signal_frame *)g2h(env->regwptr[UREG_FP]);#if 0	fprintf(stderr, "sigreturn\n");	fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]);#endif	//cpu_dump_state(env, stderr, fprintf, 0);        /* 1. Make sure we are not getting garbage from the user */#if 0        if (verify_area (VERIFY_READ, sf, sizeof (*sf)))                goto segv_and_exit;#endif        if (((uint) sf) & 3)                goto segv_and_exit;        err = __get_user(pc,  &sf->info.si_regs.pc);        err |= __get_user(npc, &sf->info.si_regs.npc);        if ((pc | npc) & 3)                goto segv_and_exit;        /* 2. Restore the state */        err |= __get_user(up_psr, &sf->info.si_regs.psr);        /* User can only change condition codes and FPU enabling in %psr. */        env->psr = (up_psr & (PSR_ICC /* | PSR_EF */))                  | (env->psr & ~(PSR_ICC /* | PSR_EF */));	env->pc = pc;	env->npc = npc;        err |= __get_user(env->y, &sf->info.si_regs.y);	for (i=0; i < 8; i++) {		err |= __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);	}	for (i=0; i < 8; i++) {		err |= __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);	}        err |= __get_user(fpu_save, (target_ulong *)&sf->fpu_save);        //if (fpu_save)        //        err |= restore_fpu_state(env, fpu_save);        /* This is pretty much atomic, no amount locking would prevent         * the races which exist anyways.         */        err |= __get_user(set.sig[0], &sf->info.si_mask);        for(i = 1; i < TARGET_NSIG_WORDS; i++) {            err |= (__get_user(set.sig[i], &sf->extramask[i - 1]));        }        target_to_host_sigset_internal(&host_set, &set);        sigprocmask(SIG_SETMASK, &host_set, NULL);        if (err)                goto segv_and_exit;        return env->regwptr[0];segv_and_exit:	force_sig(TARGET_SIGSEGV);}long do_rt_sigreturn(CPUState *env){    fprintf(stderr, "do_rt_sigreturn: not implemented\n");    return -ENOSYS;}#elif defined(TARGET_MIPS)struct target_sigcontext {    uint32_t   sc_regmask;     /* Unused */    uint32_t   sc_status;    uint64_t   sc_pc;    uint64_t   sc_regs[32];    uint64_t   sc_fpregs[32];    uint32_t   sc_ownedfp;     /* Unused */    uint32_t   sc_fpc_csr;    uint32_t   sc_fpc_eir;     /* Unused */    uint32_t   sc_used_math;    uint32_t   sc_dsp;         /* dsp status, was sc_ssflags */    uint64_t   sc_mdhi;    uint64_t   sc_mdlo;    target_ulong   sc_hi1;         /* Was sc_cause */    target_ulong   sc_lo1;         /* Was sc_badvaddr */    target_ulong   sc_hi2;         /* Was sc_sigset[4] */    target_ulong   sc_lo2;    target_ulong   sc_hi3;    target_ulong   sc_lo3;};struct sigframe {    uint32_t sf_ass[4];			/* argument save space for o32 */    uint32_t sf_code[2];			/* signal trampoline */    struct target_sigcontext sf_sc;    target_sigset_t sf_mask;};/* Install trampoline to jump back from signal handler */static inline int install_sigtramp(unsigned int *tramp,   unsigned int syscall){    int err;    /*    * Set up the return code ...    *    *         li      v0, __NR__foo_sigreturn    *         syscall    */    err = __put_user(0x24020000 + syscall, tramp + 0);    err |= __put_user(0x0000000c          , tramp + 1);    /* flush_cache_sigtramp((unsigned long) tramp); */    return err;}static inline intsetup_sigcontext(CPUState *regs, struct target_sigcontext *sc){    int err = 0;    err |= __put_user(regs->PC, &sc->sc_pc);    #define save_gp_reg(i) do {   					\        err |= __put_user(regs->gpr[i], &sc->sc_regs[i]);		\    } while(0)    __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);    save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6);    save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10);    save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);    save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18);    save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22);    save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);    save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30);    save_gp_reg(31);    #undef save_gp_reg    err |= __put_user(regs->HI, &sc->sc_mdhi);    err |= __put_user(regs->LO, &sc->sc_mdlo);    /* Not used yet, but might be useful if we ever have DSP suppport */#if 0    if (cpu_has_dsp) {	err |= __put_user(mfhi1(), &sc->sc_hi1);	err |= __put_user(mflo1(), &sc->sc_lo1);	err |= __put_user(mfhi2(), &sc->sc_hi2);	err |= __put_user(mflo2(), &sc->sc_lo2);	err |= __put_user(mfhi3(), &sc->sc_hi3);	err |= __put_user(mflo3(), &sc->sc_lo3);	err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);    }    /* same with 64 bit */    #ifdef CONFIG_64BIT    err |= __put_user(regs->hi, &sc->sc_hi[0]);    err |= __put_user(regs->lo, &sc->sc_lo[0]);    if (cpu_has_dsp) {	err |= __put_user(mfhi1(), &sc->sc_hi[1]);	err |= __put_user(mflo1(), &sc->sc_lo[1]);	err |= __put_user(mfhi2(), &sc->sc_hi[2]);	err |= __put_user(mflo2(), &sc->sc_lo[2]);	err |= __put_user(mfhi3(), &sc->sc_hi[3]);	err |= __put_user(mflo3(), &sc->sc_lo[3]);	err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);    }    #endif    #endif    #if 0    err |= __put_user(!!used_math(), &sc->sc_used_math);    if (!used_math())	goto out;    /*    * Save FPU state to signal context.  Signal handler will "inherit"    * current FPU state.    */    preempt_disable();    if (!is_fpu_owner()) {	own_fpu();	restore_fp(current);    }    err |= save_fp_context(sc);    preempt_enable();    out:#endif    return err;}static inline intrestore_sigcontext(CPUState *regs, struct target_sigcontext *sc){    int err = 0;    err |= __get_user(regs->CP0_EPC, &sc->sc_pc);    err |= __get_user(regs->HI, &sc->sc_mdhi);    err |= __get_user(regs->LO, &sc->sc_mdlo);    #define restore_gp_reg(i) do {   					\        err |= __get_user(regs->gpr[i], &sc->sc_regs[i]);		\    } while(0)    restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);    restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);    restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);    restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);    restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);    restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);    restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);    restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);    restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);    restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);    restore_gp_reg(31);    #undef restore_gp_reg#if 0    if (cpu_has_dsp) {	err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);	err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);	err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);	err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);	err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);	err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);	err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);    }    #ifdef CONFIG_64BIT    err |= __get_user(regs->hi, &sc->sc_hi[0]);    err |= __get_user(regs->lo, &sc->sc_lo[0]);    if (cpu_has_dsp) {	err |= __get_user(treg, &sc->sc_hi[1]); mthi1(treg);	err |= __get_user(treg, &sc->sc_lo[1]); mthi1(treg);	err |= __get_user(treg, &sc->sc_hi[2]); mthi2(treg);	err |= __get_user(treg, &sc->sc_lo[2]); mthi2(treg);	err |= __get_user(treg, &sc->sc_hi[3]); mthi3(treg);	err |= __get_user(treg, &sc->sc_lo[3]); mthi3(treg);	err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);    }    #endif    err |= __get_user(used_math, &sc->sc_used_math);    conditional_used_math(used_math);    preempt_disable();    if (used_math()) {	/* restore fpu context if we have used it before */	own_fpu();	err |= restore_fp_context(sc);    } else {	/* signal handler may have used FPU.  Give it up. */	lose_fpu();    }    preempt_enable();#endif    return err;}/* * Determine which stack to use.. */static inline void *get_sigframe(struct emulated_sigaction *ka, CPUState *regs, size_t frame_size){    unsigned long sp;    /* Default to using normal stack */    sp = regs->gpr[29];    /*     * FPU emulator may have it's own trampoline active just     * above the user stack, 16-bytes before the next lowest     * 16 byte boundary.  Try to avoid trashing it.     */    sp -= 32;#if 0    /* This is the X/Open sanctioned signal stack switching.  */    if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))	sp = current->sas_ss_sp + current->sas_ss_size;#endif    return g2h((sp - frame_size) & ~7);}static void setup_frame(int sig, struct emulated_sigaction * ka,    		target_sigset_t *set, CPUState *regs){    struct sigframe *frame;    int i;    frame = get_sigframe(ka, regs, sizeof(*frame));    if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))	goto give_sigsegv;    install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);    if(setup_sigcontext(regs, &frame->sf_sc))	goto give_sigsegv;    for(i = 0; i < TARGET_NSIG_WORDS; i++) {	if(__put_user(set->sig[i], &frame->sf_mask.sig[i]))	    goto give_sigsegv;    }    /*    * Arguments to signal handler:    *    *   a0 = signal number    *   a1 = 0 (should be cause)    *   a2 = pointer to struct sigcontext    *    * $25 and PC point to the signal handler, $29 points to the    * struct sigframe.    */    regs->gpr[ 4] = sig;    regs->gpr[ 5] = 0;    regs->gpr[ 6] = h2g(&frame->sf_sc);    regs->gpr[29] = h2g(frame);    regs->gpr[31] = h2g(frame->sf_code);    /* The original kernel code sets CP0_EPC to the handler    * since it returns to userland using eret    * we cannot do this here, and we must set PC directly */    regs->PC = regs->gpr[25] = ka->sa._sa_handler;    return;give_sigsegv:    force_sig(TARGET_SIGSEGV/*, current*/);    return;	}long do_sigreturn(CPUState *regs){   struct sigframe *frame;   sigset_t blocked;   target_sigset_t target_set;   int i;#if defined(DEBUG_SIGNAL)   fprintf(stderr, "do_sigreturn\n");#endif   frame = (struct sigframe *) regs->gpr[29];   if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))   	goto badframe;   for(i = 0; i < TARGET_NSIG_WORDS; i++) {   	if(__get_user(target_set.sig[i], &frame->sf_mask.sig[i]))	    goto badframe;   }		   target_to_host_sigset_internal(&blocked, &target_set);   sigprocmask(SIG_SETMASK, &blocked, NULL);   if (restore_sigcontext(regs, &frame->sf_sc))   	goto badframe;#if 0   /*    * Don't let your children do this ...    */   __asm__ __volatile__(   	"move\t$29, %0\n\t"   	"j\tsyscall_exit"   	:/* no outputs */   	:"r" (&regs));   /* Unreached */#endif        regs->PC = regs->CP0_EPC;   /* I am not sure this is right, but it seems to work    * maybe a problem with nested signals ? */    regs->CP0_EPC = 0;    return 0;badframe:   force_sig(TARGET_SIGSEGV/*, current*/);   return 0;	}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_rt_sigreturn(CPUState *env){    fprintf(stderr, "do_rt_sigreturn: not implemented\n");    return -ENOSYS;}#elsestatic 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;}#endifvoid process_pending_signals(void *cpu_env){    int sig;    target_ulong handler;    sigset_t set, old_set;    target_sigset_t target_old_set;    struct emulated_sigaction *k;    struct sigqueue *q;        if (!signal_pending)        return;    k = sigact_table;    for(sig = 1; sig <= TARGET_NSIG; sig++) {        if (k->pending)            goto handle_signal;        k++;    }    /* if no signal is pending, just return */    signal_pending = 0;    return; handle_signal:#ifdef DEBUG_SIGNAL    fprintf(stderr, "qemu: process signal %d\n", sig);#endif    /* dequeue signal */    q = k->first;    k->first = q->next;    if (!k->first)        k->pending = 0;          sig = gdb_handlesig (cpu_env, sig);    if (!sig) {        fprintf (stderr, "Lost signal\n");        abort();    }    handler = k->sa._sa_handler;    if (handler == TARGET_SIG_DFL) {        /* default handler : ignore some signal. The other are fatal */        if (sig != TARGET_SIGCHLD &&             sig != TARGET_SIGURG &&             sig != TARGET_SIGWINCH) {            force_sig(sig);        }    } else if (handler == TARGET_SIG_IGN) {        /* ignore sig */    } else if (handler == TARGET_SIG_ERR) {        force_sig(sig);    } else {        /* compute the blocked signals during the handler execution */        target_to_host_sigset(&set, &k->sa.sa_mask);        /* SA_NODEFER indicates that the current signal should not be           blocked during the handler */        if (!(k->sa.sa_flags & TARGET_SA_NODEFER))            sigaddset(&set, target_to_host_signal(sig));                /* block signals in the handler using Linux */        sigprocmask(SIG_BLOCK, &set, &old_set);        /* save the previous blocked signal state to restore it at the           end of the signal execution (see do_sigreturn) */        host_to_target_sigset_internal(&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);        else            setup_frame(sig, k, &target_old_set, cpu_env);	if (k->sa.sa_flags & TARGET_SA_RESETHAND)            k->sa._sa_handler = TARGET_SIG_DFL;    }    if (q != &k->info)        free_sigqueue(q);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -