[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250113171114.GB589@strace.io>
Date: Mon, 13 Jan 2025 19:11:14 +0200
From: "Dmitry V. Levin" <ldv@...ace.io>
To: Oleg Nesterov <oleg@...hat.com>,
Thomas Bogendoerfer <tsbogend@...ha.franken.de>
Cc: Eugene Syromyatnikov <evgsyr@...il.com>,
Mike Frysinger <vapier@...too.org>,
Renzo Davoli <renzo@...unibo.it>,
Davide Berardi <berardi.dav@...il.com>,
strace-devel@...ts.strace.io, linux-mips@...r.kernel.org,
linux-kernel@...r.kernel.org
Subject: [PATCH v2 2/7] mips: fix mips_get_syscall_arg() for O32 and N32
Fix the following get_syscall_info test assertion on mips O32:
# get_syscall_info.c:218:get_syscall_info:Expected exp_args[5] (3134521044) == info.entry.args[4] (4911432)
# get_syscall_info.c:219:get_syscall_info:wait #1: entry stop mismatch
Fix the following get_syscall_info test assertion on mips64 O32 and mips64 N32:
# get_syscall_info.c:209:get_syscall_info:Expected exp_args[2] (3134324433) == info.entry.args[1] (18446744072548908753)
# get_syscall_info.c:210:get_syscall_info:wait #1: entry stop mismatch
This makes ptrace/get_syscall_info selftest pass on mips O32,
mips64 O32, and mips64 N32.
Signed-off-by: Dmitry V. Levin <ldv@...ace.io>
---
Note that I'm not a MIPS expert, so I cannot tell why the get_user()
approach doesn't work for O32. Also, during experiments I discovered that
regs->pad0 approach works for O32, but why it works remains a mystery.
arch/mips/include/asm/syscall.h | 34 ++++++++++-----------------------
1 file changed, 10 insertions(+), 24 deletions(-)
diff --git a/arch/mips/include/asm/syscall.h b/arch/mips/include/asm/syscall.h
index ebdf4d910af2..2f85f2d8f754 100644
--- a/arch/mips/include/asm/syscall.h
+++ b/arch/mips/include/asm/syscall.h
@@ -57,37 +57,23 @@ static inline void mips_syscall_update_nr(struct task_struct *task,
static inline void mips_get_syscall_arg(unsigned long *arg,
struct task_struct *task, struct pt_regs *regs, unsigned int n)
{
- unsigned long usp __maybe_unused = regs->regs[29];
-
+#ifdef CONFIG_32BIT
switch (n) {
case 0: case 1: case 2: case 3:
*arg = regs->regs[4 + n];
-
- return;
-
-#ifdef CONFIG_32BIT
- case 4: case 5: case 6: case 7:
- get_user(*arg, (int *)usp + n);
return;
-#endif
-
-#ifdef CONFIG_64BIT
case 4: case 5: case 6: case 7:
-#ifdef CONFIG_MIPS32_O32
- if (test_tsk_thread_flag(task, TIF_32BIT_REGS))
- get_user(*arg, (int *)usp + n);
- else
-#endif
- *arg = regs->regs[4 + n];
-
+ *arg = regs->pad0[n];
return;
-#endif
-
- default:
- BUG();
}
-
- unreachable();
+#else
+ *arg = regs->regs[4 + n];
+ if ((IS_ENABLED(CONFIG_MIPS32_O32) &&
+ test_tsk_thread_flag(task, TIF_32BIT_REGS)) ||
+ (IS_ENABLED(CONFIG_MIPS32_N32) &&
+ test_tsk_thread_flag(task, TIF_32BIT_ADDR)))
+ *arg = (unsigned int)*arg;
+#endif
}
static inline long syscall_get_error(struct task_struct *task,
--
ldv
Powered by blists - more mailing lists