qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [RFC PATCH] linux-user: Add signal handling for x86_64


From: Laurent Vivier
Subject: Re: [Qemu-devel] [RFC PATCH] linux-user: Add signal handling for x86_64
Date: Fri, 3 Feb 2017 22:56:46 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.6.0

Le 25/01/2017 à 01:10, Pranith Kumar a écrit :
> Adopted from a previous patch posting:
> https://lists.gnu.org/archive/html/qemu-devel/2016-07/msg02079.html
> 
> CC: Allan Wirth <address@hidden>
> CC: Peter Maydell <address@hidden>
> Signed-off-by: Pranith Kumar <address@hidden>
> ---
>  linux-user/signal.c      | 264 
> ++++++++++++++++++++++++++++++++++++++++-------
>  target/i386/cpu.h        |   2 +
>  target/i386/fpu_helper.c |  12 +++
>  3 files changed, 242 insertions(+), 36 deletions(-)
> 
> diff --git a/linux-user/signal.c b/linux-user/signal.c
> index 0a5bb4e26b..0248621d66 100644
> --- a/linux-user/signal.c
> +++ b/linux-user/signal.c
> @@ -253,8 +253,7 @@ int do_sigprocmask(int how, const sigset_t *set, sigset_t 
> *oldset)
>      return 0;
>  }
>  
> -#if !defined(TARGET_OPENRISC) && !defined(TARGET_UNICORE32) && \
> -    !defined(TARGET_X86_64)
> +#if !defined(TARGET_OPENRISC) && !defined(TARGET_UNICORE32)
>  /* Just set the guest's signal mask to the specified value; the
>   * caller is assumed to have called block_signals() already.
>   */
> @@ -512,7 +511,7 @@ void signal_init(void)
>      }
>  }
>  
> -#if !(defined(TARGET_X86_64) || defined(TARGET_UNICORE32))
> +#ifndef TARGET_UNICORE32
>  /* Force a synchronously taken signal. The kernel force_sig() function
>   * also forces the signal to "not blocked, not ignored", but for QEMU
>   * that work is done in process_pending_signals().
> @@ -819,9 +818,8 @@ int do_sigaction(int sig, const struct target_sigaction 
> *act,
>      return ret;
>  }
>  
> -#if defined(TARGET_I386) && TARGET_ABI_BITS == 32
> -
> -/* from the Linux kernel */
> +#if defined(TARGET_I386)
> +/* from the Linux kernel - /arch/x86/include/uapi/asm/sigcontext.h */
>  
>  struct target_fpreg {
>      uint16_t significand[4];
> @@ -835,7 +833,7 @@ struct target_fpxreg {
>  };
>  
>  struct target_xmmreg {
> -    abi_ulong element[4];
> +    uint32_t element[4];
>  };
>  
>  struct target_fpstate {
> @@ -860,33 +858,117 @@ struct target_fpstate {
>      abi_ulong padding[56];
>  };

I think you should remove the definition of the target_fpstate structure
as you overwrite it with #define below:
...
> +
> +#ifndef TARGET_X86_64
> +# define target_fpstate target_fpstate_32
> +#else
> +# define target_fpstate target_fpstate_64
> +#endif
> +
...
> @@ -959,12 +1052,49 @@ static void setup_sigcontext(struct target_sigcontext 
> *sc,
>      /* non-iBCS2 extensions.. */
>      __put_user(mask, &sc->oldmask);
>      __put_user(env->cr[2], &sc->cr2);
> +#else
> +    __put_user(env->regs[8], &sc->r8);
> +    __put_user(env->regs[9], &sc->r9);
> +    __put_user(env->regs[10], &sc->r10);
> +    __put_user(env->regs[11], &sc->r11);
> +    __put_user(env->regs[12], &sc->r12);
> +    __put_user(env->regs[13], &sc->r13);
> +    __put_user(env->regs[14], &sc->r14);
> +    __put_user(env->regs[15], &sc->r15);
> +
> +    __put_user(env->regs[R_EDI], &sc->rdi);
> +    __put_user(env->regs[R_ESI], &sc->rsi);
> +    __put_user(env->regs[R_EBP], &sc->rbp);
> +    __put_user(env->regs[R_EBX], &sc->rbx);
> +    __put_user(env->regs[R_EDX], &sc->rdx);
> +    __put_user(env->regs[R_EAX], &sc->rax);
> +    __put_user(env->regs[R_ECX], &sc->rcx);
> +    __put_user(env->regs[R_ESP], &sc->rsp);
> +    __put_user(env->eip, &sc->rip);
> +
> +    __put_user(env->eflags, &sc->eflags);
> +
> +    __put_user(env->segs[R_CS].selector, &sc->cs);
> +    __put_user((uint16_t)0, &sc->gs);
> +    __put_user((uint16_t)0, &sc->fs);
> +    __put_user(env->segs[R_SS].selector, &sc->ss);
> +
> +    __put_user(env->error_code, &sc->err);
> +    __put_user(cs->exception_index, &sc->trapno);
> +    __put_user(mask, &sc->oldmask);
> +    __put_user(env->cr[2], &sc->cr2);
> +
> +    /* fpstate_addr must be 16 byte aligned for fxsave */
> +    assert(!(fpstate_addr & 0xf));
> +
> +    cpu_x86_fxsave(env, fpstate_addr);
> +    __put_user(fpstate_addr, &sc->fpstate);
> +#endif

This part would be more readable if the registers were in the same order
as  in the kernel function setup_sigcontext().
...
> +    if (info) {
> +        tswap_siginfo(&frame->info, info);
> +    }

kernel checks "ksig->ka.sa.sa_flags & SA_SIGINFO" to know if there is
siginfo structure.

...
>      /* Set up registers for signal handler */
>      env->regs[R_ESP] = frame_addr;
> +    env->regs[R_EAX] = 0;
> +    env->regs[R_EDI] = sig;
> +    env->regs[R_ESI] = (unsigned long)&frame->info;
> +    env->regs[R_EDX] = (unsigned long)&frame->uc;
>      env->eip = ka->_sa_handler;

In kernel, 32bit handler seems to not use the same registers as 64bit
handler, for instance ax is sig, info is dx and uc is cx.

...
> @@ -6181,11 +6371,13 @@ static void handle_pending_signal(CPUArchState 
> *cpu_env, int sig,
>          || defined(TARGET_PPC64) || defined(TARGET_HPPA)
>          /* These targets do not have traditional signals.  */
>          setup_rt_frame(sig, sa, &k->info, &target_old_set, cpu_env);
> -#else
> +#elif !defined(TARGET_X86_64)
>          if (sa->sa_flags & TARGET_SA_SIGINFO)
>              setup_rt_frame(sig, sa, &k->info, &target_old_set, cpu_env);
>          else
>              setup_frame(sig, sa, &target_old_set, cpu_env);
> +#else
> +        setup_rt_frame(sig, sa, 0, &target_old_set, cpu_env);

Why do we use "0" instead of "&k->info"?

Laurent




reply via email to

[Prev in Thread] Current Thread [Next in Thread]