linux-user: fix TARGET_NR_select
TARGET_NR_select can have three different implementations:
1- to always return -ENOSYS
microblaze, ppc, ppc64
-> TARGET_WANT_NI_OLD_SELECT
2- to take parameters from a structure pointed by arg1
(kernel sys_old_select)
i386, arm, m68k
-> TARGET_WANT_OLD_SYS_SELECT
3- to take parameters from arg[1-5]
(kernel sys_select)
x86_64, alpha, s390x,
cris, sparc, sparc64
Some (new) architectures don't define NR_select,
4- but only NR__newselect with sys_select:
mips, mips64, sh
5- don't define NR__newselect, and use pselect6 syscall:
aarch64, openrisc, tilegx, unicore32
Reported-by: Timothy Pearson <tpearson@raptorengineering.com>
Reported-by: Allan Wirth <awirth@akamai.com>
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index d7e4d9f..7aa2c1d 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -1444,6 +1444,29 @@
return ret;
}
+
+#if defined(TARGET_WANT_OLD_SYS_SELECT)
+static abi_long do_old_select(abi_ulong arg1)
+{
+ struct target_sel_arg_struct *sel;
+ abi_ulong inp, outp, exp, tvp;
+ long nsel;
+
+ if (!lock_user_struct(VERIFY_READ, sel, arg1, 1)) {
+ return -TARGET_EFAULT;
+ }
+
+ nsel = tswapal(sel->n);
+ inp = tswapal(sel->inp);
+ outp = tswapal(sel->outp);
+ exp = tswapal(sel->exp);
+ tvp = tswapal(sel->tvp);
+
+ unlock_user_struct(sel, arg1, 0);
+
+ return do_select(nsel, inp, outp, exp, tvp);
+}
+#endif
#endif
static abi_long do_pipe2(int host_pipe[], int flags)
@@ -8668,24 +8691,15 @@
break;
#if defined(TARGET_NR_select)
case TARGET_NR_select:
-#if defined(TARGET_S390X) || defined(TARGET_ALPHA)
- ret = do_select(arg1, arg2, arg3, arg4, arg5);
+#if defined(TARGET_WANT_NI_OLD_SELECT)
+ /* some architectures used to have old_select here
+ * but now ENOSYS it.
+ */
+ ret = -TARGET_ENOSYS;
+#elif defined(TARGET_WANT_OLD_SYS_SELECT)
+ ret = do_old_select(arg1);
#else
- {
- struct target_sel_arg_struct *sel;
- abi_ulong inp, outp, exp, tvp;
- long nsel;
-
- if (!lock_user_struct(VERIFY_READ, sel, arg1, 1))
- goto efault;
- nsel = tswapal(sel->n);
- inp = tswapal(sel->inp);
- outp = tswapal(sel->outp);
- exp = tswapal(sel->exp);
- tvp = tswapal(sel->tvp);
- unlock_user_struct(sel, arg1, 0);
- ret = do_select(nsel, inp, outp, exp, tvp);
- }
+ ret = do_select(arg1, arg2, arg3, arg4, arg5);
#endif
break;
#endif