diff mbox series

[v2,19/28] linux-user/i386: Fix -mregparm=3 for signal delivery

Message ID 20240409050302.1523277-20-richard.henderson@linaro.org
State New
Headers show
Series linux-user/i386: Properly align signal frame | expand

Commit Message

Richard Henderson April 9, 2024, 5:02 a.m. UTC
Since v2.6.19, the kernel has supported -mregparm=3.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/i386/signal.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

Comments

Paolo Bonzini April 9, 2024, 7:31 a.m. UTC | #1
On 4/9/24 07:02, Richard Henderson wrote:
> Since v2.6.19, the kernel has supported -mregparm=3.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   linux-user/i386/signal.c | 20 +++++++++-----------
>   1 file changed, 9 insertions(+), 11 deletions(-)
> 
> diff --git a/linux-user/i386/signal.c b/linux-user/i386/signal.c
> index 559b63c25b..f8cc0cff07 100644
> --- a/linux-user/i386/signal.c
> +++ b/linux-user/i386/signal.c
> @@ -427,6 +427,11 @@ void setup_frame(int sig, struct target_sigaction *ka,
>       env->regs[R_ESP] = frame_addr;
>       env->eip = ka->_sa_handler;
>   
> +    /* Make -mregparm=3 work */
> +    env->regs[R_EAX] = sig;
> +    env->regs[R_EDX] = 0;
> +    env->regs[R_ECX] = 0;

Perhaps also move here the

     __put_user(sig, &frame->sig);

from above, for consistency with setup_rt_frame?

Paolo

>       cpu_x86_load_seg(env, R_DS, __USER_DS);
>       cpu_x86_load_seg(env, R_ES, __USER_DS);
>       cpu_x86_load_seg(env, R_SS, __USER_DS);
> @@ -448,9 +453,6 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
>                       target_sigset_t *set, CPUX86State *env)
>   {
>       abi_ulong frame_addr;
> -#ifndef TARGET_X86_64
> -    abi_ulong addr;
> -#endif
>       struct rt_sigframe *frame;
>       int i;
>   
> @@ -460,14 +462,6 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
>       if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
>           goto give_sigsegv;
>   
> -    /* These fields are only in rt_sigframe on 32 bit */
> -#ifndef TARGET_X86_64
> -    __put_user(sig, &frame->sig);
> -    addr = frame_addr + offsetof(struct rt_sigframe, info);
> -    __put_user(addr, &frame->pinfo);
> -    addr = frame_addr + offsetof(struct rt_sigframe, uc);
> -    __put_user(addr, &frame->puc);
> -#endif
>       if (ka->sa_flags & TARGET_SA_SIGINFO) {
>           frame->info = *info;
>       }
> @@ -507,9 +501,13 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
>       env->eip = ka->_sa_handler;
>   
>   #ifndef TARGET_X86_64
> +    /* Store arguments for both -mregparm=3 and standard. */
>       env->regs[R_EAX] = sig;
> +    __put_user(sig, &frame->sig);
>       env->regs[R_EDX] = frame_addr + offsetof(struct rt_sigframe, info);
> +    __put_user(env->regs[R_EDX], &frame->pinfo);
>       env->regs[R_ECX] = frame_addr + offsetof(struct rt_sigframe, uc);
> +    __put_user(env->regs[R_ECX], &frame->puc);
>   #else
>       env->regs[R_EAX] = 0;
>       env->regs[R_EDI] = sig;
diff mbox series

Patch

diff --git a/linux-user/i386/signal.c b/linux-user/i386/signal.c
index 559b63c25b..f8cc0cff07 100644
--- a/linux-user/i386/signal.c
+++ b/linux-user/i386/signal.c
@@ -427,6 +427,11 @@  void setup_frame(int sig, struct target_sigaction *ka,
     env->regs[R_ESP] = frame_addr;
     env->eip = ka->_sa_handler;
 
+    /* Make -mregparm=3 work */
+    env->regs[R_EAX] = sig;
+    env->regs[R_EDX] = 0;
+    env->regs[R_ECX] = 0;
+
     cpu_x86_load_seg(env, R_DS, __USER_DS);
     cpu_x86_load_seg(env, R_ES, __USER_DS);
     cpu_x86_load_seg(env, R_SS, __USER_DS);
@@ -448,9 +453,6 @@  void setup_rt_frame(int sig, struct target_sigaction *ka,
                     target_sigset_t *set, CPUX86State *env)
 {
     abi_ulong frame_addr;
-#ifndef TARGET_X86_64
-    abi_ulong addr;
-#endif
     struct rt_sigframe *frame;
     int i;
 
@@ -460,14 +462,6 @@  void setup_rt_frame(int sig, struct target_sigaction *ka,
     if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
         goto give_sigsegv;
 
-    /* These fields are only in rt_sigframe on 32 bit */
-#ifndef TARGET_X86_64
-    __put_user(sig, &frame->sig);
-    addr = frame_addr + offsetof(struct rt_sigframe, info);
-    __put_user(addr, &frame->pinfo);
-    addr = frame_addr + offsetof(struct rt_sigframe, uc);
-    __put_user(addr, &frame->puc);
-#endif
     if (ka->sa_flags & TARGET_SA_SIGINFO) {
         frame->info = *info;
     }
@@ -507,9 +501,13 @@  void setup_rt_frame(int sig, struct target_sigaction *ka,
     env->eip = ka->_sa_handler;
 
 #ifndef TARGET_X86_64
+    /* Store arguments for both -mregparm=3 and standard. */
     env->regs[R_EAX] = sig;
+    __put_user(sig, &frame->sig);
     env->regs[R_EDX] = frame_addr + offsetof(struct rt_sigframe, info);
+    __put_user(env->regs[R_EDX], &frame->pinfo);
     env->regs[R_ECX] = frame_addr + offsetof(struct rt_sigframe, uc);
+    __put_user(env->regs[R_ECX], &frame->puc);
 #else
     env->regs[R_EAX] = 0;
     env->regs[R_EDI] = sig;