aboutsummaryrefslogtreecommitdiff
path: root/linux-user
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2024-04-08 11:51:53 -1000
committerRichard Henderson <richard.henderson@linaro.org>2024-05-26 12:51:50 -0700
commitbae0455ce3ded1df80dee4e844194568063ad093 (patch)
treed20a7dee096811e428cac756dd08a446ff518aa1 /linux-user
parent5cc77ebe9b9e07fcd06011dc23162069ef8c5eff (diff)
linux-user/i386: Fix -mregparm=3 for signal delivery
Since v2.6.19, the kernel has supported -mregparm=3. Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'linux-user')
-rw-r--r--linux-user/i386/signal.c24
1 files changed, 11 insertions, 13 deletions
diff --git a/linux-user/i386/signal.c b/linux-user/i386/signal.c
index 3271ebd333..6763b4bda8 100644
--- a/linux-user/i386/signal.c
+++ b/linux-user/i386/signal.c
@@ -405,8 +405,6 @@ void setup_frame(int sig, struct target_sigaction *ka,
if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
goto give_sigsegv;
- __put_user(sig, &frame->sig);
-
setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0],
frame_addr + offsetof(struct sigframe, fpstate));
@@ -428,6 +426,13 @@ void setup_frame(int sig, struct target_sigaction *ka,
env->regs[R_ESP] = frame_addr;
env->eip = ka->_sa_handler;
+ /* Store argument for both -mregparm=3 and standard. */
+ env->regs[R_EAX] = sig;
+ __put_user(sig, &frame->sig);
+ /* The kernel clears EDX and ECX even though there is only one arg. */
+ 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);
@@ -449,9 +454,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;
@@ -461,14 +463,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;
}
@@ -508,9 +502,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;