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

2017-02-05 Thread Pranith Kumar

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

2017-02-03 Thread Laurent Vivier
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

2017-02-03 Thread Pranith Kumar
On Fri, Feb 3, 2017 at 11:10 AM, Wirth, Allan  wrote:

> 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

2017-02-03 Thread Pranith Kumar

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

2017-02-03 Thread Wirth, Allan
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

2017-02-03 Thread Peter Maydell
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.

> ---
>  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

2017-01-24 Thread Pranith Kumar
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];
 };
 
-#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;