Re: [Qemu-devel] [RFC PATCH] linux-user: Add signal handling for x86_64
Hi Laurent, Thanks for the review. Laurent Vivier writes: > 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>> CC: Peter Maydell >> Signed-off-by: Pranith Kumar >> --- >> 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 >> + Good catch. I'll do that. > ... >> @@ -959,12 +1052,49 @@ static void setup_sigcontext(struct target_sigcontext >> *sc, >> /* non-iBCS2 extensions.. */ >> __put_user(mask, >oldmask); >> __put_user(env->cr[2], >cr2); >> +#else >> +__put_user(env->regs[8], >r8); >> +__put_user(env->regs[9], >r9); >> +__put_user(env->regs[10], >r10); >> +__put_user(env->regs[11], >r11); >> +__put_user(env->regs[12], >r12); >> +__put_user(env->regs[13], >r13); >> +__put_user(env->regs[14], >r14); >> +__put_user(env->regs[15], >r15); >> + >> +__put_user(env->regs[R_EDI], >rdi); >> +__put_user(env->regs[R_ESI], >rsi); >> +__put_user(env->regs[R_EBP], >rbp); >> +__put_user(env->regs[R_EBX], >rbx); >> +__put_user(env->regs[R_EDX], >rdx); >> +__put_user(env->regs[R_EAX], >rax); >> +__put_user(env->regs[R_ECX], >rcx); >> +__put_user(env->regs[R_ESP], >rsp); >> +__put_user(env->eip, >rip); >> + >> +__put_user(env->eflags, >eflags); >> + >> +__put_user(env->segs[R_CS].selector, >cs); >> +__put_user((uint16_t)0, >gs); >> +__put_user((uint16_t)0, >fs); >> +__put_user(env->segs[R_SS].selector, >ss); >> + >> +__put_user(env->error_code, >err); >> +__put_user(cs->exception_index, >trapno); >> +__put_user(mask, >oldmask); >> +__put_user(env->cr[2], >cr2); >> + >> +/* fpstate_addr must be 16 byte aligned for fxsave */ >> +assert(!(fpstate_addr & 0xf)); >> + >> +cpu_x86_fxsave(env, fpstate_addr); >> +__put_user(fpstate_addr, >fpstate); >> +#endif > > This part would be more readable if the registers were in the same order > as in the kernel function setup_sigcontext(). OK, noted this. I'll make the change. > ... >> +if (info) { >> +tswap_siginfo(>info, info); >> +} > > kernel checks "ksig->ka.sa.sa_flags & SA_SIGINFO" to know if there is > siginfo structure. > OK. I'll do the same as what the kernel is doing. > ... >> /* 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)>info; >> +env->regs[R_EDX] = (unsigned long)>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. > Hmm.. how do I reproduce the same here? Should I check if we are in 32-bit environment? > ... >> @@ -6181,11 +6371,13 @@ static void
Re: [Qemu-devel] [RFC PATCH] linux-user: Add signal handling for x86_64
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> CC: Peter Maydell > Signed-off-by: Pranith Kumar > --- > 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, >oldmask); > __put_user(env->cr[2], >cr2); > +#else > +__put_user(env->regs[8], >r8); > +__put_user(env->regs[9], >r9); > +__put_user(env->regs[10], >r10); > +__put_user(env->regs[11], >r11); > +__put_user(env->regs[12], >r12); > +__put_user(env->regs[13], >r13); > +__put_user(env->regs[14], >r14); > +__put_user(env->regs[15], >r15); > + > +__put_user(env->regs[R_EDI], >rdi); > +__put_user(env->regs[R_ESI], >rsi); > +__put_user(env->regs[R_EBP], >rbp); > +__put_user(env->regs[R_EBX], >rbx); > +__put_user(env->regs[R_EDX], >rdx); > +__put_user(env->regs[R_EAX], >rax); > +__put_user(env->regs[R_ECX], >rcx); > +__put_user(env->regs[R_ESP], >rsp); > +__put_user(env->eip, >rip); > + > +__put_user(env->eflags, >eflags); > + > +__put_user(env->segs[R_CS].selector, >cs); > +__put_user((uint16_t)0, >gs); > +__put_user((uint16_t)0, >fs); > +__put_user(env->segs[R_SS].selector, >ss); > + > +__put_user(env->error_code, >err); > +__put_user(cs->exception_index, >trapno); > +__put_user(mask, >oldmask); > +__put_user(env->cr[2], >cr2); > + > +/* fpstate_addr must be 16 byte aligned for fxsave */ > +assert(!(fpstate_addr & 0xf)); > + > +cpu_x86_fxsave(env, fpstate_addr); > +__put_user(fpstate_addr, >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(>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)>info; > +env->regs[R_EDX] = (unsigned long)>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, >info, _old_set, cpu_env); > -#else > +#elif !defined(TARGET_X86_64) > if (sa->sa_flags & TARGET_SA_SIGINFO) > setup_rt_frame(sig, sa, >info, _old_set, cpu_env); > else >
Re: [Qemu-devel] [RFC PATCH] linux-user: Add signal handling for x86_64
On Fri, Feb 3, 2017 at 11:10 AM, Wirth, Allanwrote: > The patch LGTM. :) Thanks for checking the latest patch and for the initial work. I am happy it did not get lost :) -- Pranith
Re: [Qemu-devel] [RFC PATCH] linux-user: Add signal handling for x86_64
Peter Maydell writes: > On 25 January 2017 at 00:10, Pranith Kumarwrote: >> Adopted from a previous patch posting: >> https://lists.gnu.org/archive/html/qemu-devel/2016-07/msg02079.html >> >> CC: Allan Wirth >> CC: Peter Maydell >> Signed-off-by: Pranith Kumar > > Thanks for picking this patch up. A nit about commit message format: > because this is mostly Allan's work you need to add his signed-off-by: > line (which he provided on his original patch posting), and make > a brief not of what was changed, so it looks like: > > Signed-off-by: Original Author > [OP: changed X, Y, Z] > Signed-off-by: Other Person > > It's also in this kind of situation worth considering whether the > patch would be better attributed to Allan as the git commit 'author'. > If I've taken somebody else's work and made mostly minor overhauls > to it I tend to go for giving them credit in the git commit log. OK, I'll add these SOB lines and attribute it to Allan as he did most of the work. > >> --- >> 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. >> */ > > There's a minor conflict here with the Nios2 code that's now > in master (which added another clause to this #if), but it's > trivial to resolve. I'll rebase my patch on master and fix up the conflicts and send a v2. > > Otherwise: > > Reviewed-by: Peter Maydell Thanks for the review! -- Pranith
Re: [Qemu-devel] [RFC PATCH] linux-user: Add signal handling for x86_64
Pranith, Thanks for doing this. I totally forgot about this (my work has moved elsewhere) so thank you for picking it back up. Please don’t worry about the attribution. The patch LGTM. :) Cheers, Allan On 2/3/17, 10:55 AM, "Pranith Kumar"wrote: Peter Maydell writes: > On 25 January 2017 at 00:10, Pranith Kumar wrote: >> Adopted from a previous patch posting: >> https://lists.gnu.org/archive/html/qemu-devel/2016-07/msg02079.html >> >> CC: Allan Wirth >> CC: Peter Maydell >> Signed-off-by: Pranith Kumar > > Thanks for picking this patch up. A nit about commit message format: > because this is mostly Allan's work you need to add his signed-off-by: > line (which he provided on his original patch posting), and make > a brief not of what was changed, so it looks like: > > Signed-off-by: Original Author > [OP: changed X, Y, Z] > Signed-off-by: Other Person > > It's also in this kind of situation worth considering whether the > patch would be better attributed to Allan as the git commit 'author'. > If I've taken somebody else's work and made mostly minor overhauls > to it I tend to go for giving them credit in the git commit log. OK, I'll add these SOB lines and attribute it to Allan as he did most of the work. > >> --- >> 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. >> */ > > There's a minor conflict here with the Nios2 code that's now > in master (which added another clause to this #if), but it's > trivial to resolve. I'll rebase my patch on master and fix up the conflicts and send a v2. > > Otherwise: > > Reviewed-by: Peter Maydell Thanks for the review! -- Pranith
Re: [Qemu-devel] [RFC PATCH] linux-user: Add signal handling for x86_64
On 25 January 2017 at 00:10, Pranith Kumarwrote: > Adopted from a previous patch posting: > https://lists.gnu.org/archive/html/qemu-devel/2016-07/msg02079.html > > CC: Allan Wirth > CC: Peter Maydell > Signed-off-by: Pranith Kumar Thanks for picking this patch up. A nit about commit message format: because this is mostly Allan's work you need to add his signed-off-by: line (which he provided on his original patch posting), and make a brief not of what was changed, so it looks like: Signed-off-by: Original Author [OP: changed X, Y, Z] Signed-off-by: Other Person It's also in this kind of situation worth considering whether the patch would be better attributed to Allan as the git commit 'author'. If I've taken somebody else's work and made mostly minor overhauls to it I tend to go for giving them credit in the git commit log. > --- > 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. > */ There's a minor conflict here with the Nios2 code that's now in master (which added another clause to this #if), but it's trivial to resolve. Otherwise: Reviewed-by: Peter Maydell thanks -- PMM
[Qemu-devel] [RFC PATCH] linux-user: Add signal handling for x86_64
Adopted from a previous patch posting: https://lists.gnu.org/archive/html/qemu-devel/2016-07/msg02079.html CC: Allan WirthCC: Peter Maydell Signed-off-by: Pranith Kumar --- 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]; }; -#define X86_FXSR_MAGIC 0x +struct target_fpstate_32 { +/* Regular FPU environment */ +uint32_t cw; +uint32_t sw; +uint32_t tag; +uint32_t ipoff; +uint32_t cssel; +uint32_t dataoff; +uint32_t datasel; +struct target_fpreg _st[8]; +uint16_t status; +uint16_t magic; /* 0x = regular FPU data only */ -struct target_sigcontext { +/* FXSR FPU environment */ +uint32_t _fxsr_env[6]; /* FXSR FPU env is ignored */ +uint32_t mxcsr; +uint32_t reserved; +struct target_fpxreg _fxsr_st[8]; /* FXSR FPU reg data is ignored */ +struct target_xmmreg _xmm[8]; +uint32_t padding[56]; +}; + +struct target_fpstate_64 { +/* FXSAVE format */ +uint16_t cw; +uint16_t sw; +uint16_t twd; +uint16_t fop; +uint64_t rip; +uint64_t rdp; +uint32_t mxcsr; +uint32_t mxcsr_mask; +uint32_t st_space[32]; +uint32_t xmm_space[64]; +uint32_t reserved[24]; +}; + +#ifndef TARGET_X86_64 +# define target_fpstate target_fpstate_32 +#else +# define target_fpstate target_fpstate_64 +#endif + +struct target_sigcontext_32 { uint16_t gs, __gsh; uint16_t fs, __fsh; uint16_t es, __esh; uint16_t ds, __dsh; -abi_ulong edi; -abi_ulong esi; -abi_ulong ebp; -abi_ulong esp; -abi_ulong ebx; -abi_ulong edx; -abi_ulong ecx; -abi_ulong eax; -abi_ulong trapno; -abi_ulong err; -abi_ulong eip; +uint32_t edi; +uint32_t esi; +uint32_t ebp; +uint32_t esp; +uint32_t ebx; +uint32_t edx; +uint32_t ecx; +uint32_t eax; +uint32_t trapno; +uint32_t err; +uint32_t eip; uint16_t cs, __csh; -abi_ulong eflags; -abi_ulong esp_at_signal; +uint32_t eflags; +uint32_t esp_at_signal; uint16_t ss, __ssh; -abi_ulong fpstate; /* pointer */ -abi_ulong oldmask; -abi_ulong cr2; +uint32_t fpstate; /* pointer */ +uint32_t oldmask; +uint32_t cr2; +}; + +struct target_sigcontext_64 { +uint64_t r8; +uint64_t r9; +uint64_t r10; +uint64_t r11; +uint64_t r12; +uint64_t r13; +uint64_t r14; +uint64_t r15; + +uint64_t rdi; +uint64_t rsi; +uint64_t rbp; +uint64_t rbx; +uint64_t rdx; +uint64_t rax; +uint64_t rcx; +uint64_t rsp; +uint64_t rip; + +uint64_t eflags; + +uint16_t cs; +uint16_t gs; +uint16_t fs; +uint16_t ss; + +uint64_t err; +uint64_t trapno; +uint64_t oldmask; +uint64_t cr2; + +uint64_t fpstate; /* pointer */ +uint64_t padding[8]; }; +#ifndef TARGET_X86_64 +# define target_sigcontext target_sigcontext_32 +#else +# define target_sigcontext target_sigcontext_64 +#endif + +/* see Linux/include/uapi/asm-generic/ucontext.h */ struct target_ucontext { abi_ulong tuc_flags; abi_ulong tuc_link; @@ -895,8 +977,8 @@ struct target_ucontext { target_sigset_t tuc_sigmask; /* mask last for extensibility */ }; -struct sigframe -{ +#ifndef TARGET_X86_64 +struct sigframe { abi_ulong pretcode;