? unknown sender #
Message details and related content
From: Ryan Houdek <redacted> Problem presented: A backwards compatibility layer that allows running x86-64 and x86 processes inside of an AArch64 process. - CPU is emulated - Syscall interface is mostly passthrough - Some syscalls require patching or emulation depending on behaviour - Not viable from the emulator design to use an AArch32 host process x86-64 and x86 userspace emulator source: https://github.com/FEX-Emu/FEX Usage of ioctl32 is currently in a downstream fork. This will be the first user of the syscall. Cross documentation: https://github.com/FEX-Emu/FEX/wiki/32Bit-x86-Woes#ioctl---54 ioctls are opaque from the emulator perspective and the data wants to be passed through a syscall as unimpeded as possible. Sadly due to ioctl struct differences between x86 and x86-64, we need a syscall that exposes the compatibility ioctl handler to userspace in a 64bit process. This is necessary behaves of the behaviour differences that occur between an x86 process doing an ioctl and an x86-64 process doing an ioctl. Both of which are captured and passed through the AArch64 ioctl space. This is implementing a new ioctl32 syscall that allows us to pass 32bit x86 ioctls through to the kernel with zero or minimal manipulation. The only supported hosts where we care about this currently is AArch64 and x86-64 (For testing purposes). PPC64LE, MIPS64LE, and RISC-V64 might be interesting to support in the future; But I don't have any platforms that get anywhere near Cortex-A77 performance in those architectures. Nor do I have the time to bring up the emulator on them. x86-64 can get to the compatibility ioctl through the int $0x80 handler.
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
index 86a9d7b3eabe..949788f5ba40 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h@@ -38,7 +38,7 @@ #define __ARM_NR_compat_set_tls (__ARM_NR_COMPAT_BASE + 5) #define __ARM_NR_COMPAT_END (__ARM_NR_COMPAT_BASE + 0x800) -#define __NR_compat_syscalls 442 +#define __NR_compat_syscalls 443 #endif #define __ARCH_WANT_SYS_CLONE
diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h
index cccfbbefbf95..35e3bc83dbdc 100644
--- a/arch/arm64/include/asm/unistd32.h
+++ b/arch/arm64/include/asm/unistd32.h@@ -891,6 +891,8 @@ __SYSCALL(__NR_faccessat2, sys_faccessat2) __SYSCALL(__NR_process_madvise, sys_process_madvise) #define __NR_epoll_pwait2 441 __SYSCALL(__NR_epoll_pwait2, compat_sys_epoll_pwait2) +#define __NR_ioctl32 442 +__SYSCALL(__NR_ioctl32, compat_sys_ioctl) /* * Please add new compat syscalls above this comment and update
diff --git a/fs/ioctl.c b/fs/ioctl.c
index 4e6cc0a7d69c..116b9bca8c07 100644
--- a/fs/ioctl.c
+++ b/fs/ioctl.c@@ -790,8 +790,8 @@ long compat_ptr_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } EXPORT_SYMBOL(compat_ptr_ioctl); -COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, - compat_ulong_t, arg) +long do_ioctl32(unsigned int fd, unsigned int cmd, + compat_ulong_t arg) { struct fd f = fdget(fd); int error;
@@ -850,4 +850,16 @@ COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, return error; } + +COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, + compat_ulong_t, arg) +{ + return do_ioctl32(fd, cmd, arg); +} + +SYSCALL_DEFINE3(ioctl32, unsigned int, fd, unsigned int, cmd, + compat_ulong_t, arg) +{ + return do_ioctl32(fd, cmd, arg); +} #endif
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index f3929aff39cf..470f928831eb 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h@@ -386,6 +386,8 @@ asmlinkage long sys_inotify_rm_watch(int fd, __s32 wd); /* fs/ioctl.c */ asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); +asmlinkage long sys_ioctl32(unsigned int fd, unsigned int cmd, + compat_ulong_t arg); /* fs/ioprio.c */ asmlinkage long sys_ioprio_set(int which, int who, int ioprio);
diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
index 728752917785..18279e5b7b4f 100644
--- a/include/uapi/asm-generic/unistd.h
+++ b/include/uapi/asm-generic/unistd.h@@ -862,8 +862,15 @@ __SYSCALL(__NR_process_madvise, sys_process_madvise) #define __NR_epoll_pwait2 441 __SC_COMP(__NR_epoll_pwait2, sys_epoll_pwait2, compat_sys_epoll_pwait2) +#define __NR_ioctl32 442 +#ifdef CONFIG_COMPAT +__SC_COMP(__NR_ioctl32, sys_ioctl32, compat_sys_ioctl) +#else +__SC_COMP(__NR_ioctl32, sys_ni_syscall, sys_ni_syscall) +#endif + #undef __NR_syscalls -#define __NR_syscalls 442 +#define __NR_syscalls 443 /* * 32 bit systems traditionally used different
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 19aa806890d5..5a2f25eb341c 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c@@ -302,6 +302,9 @@ COND_SYSCALL(recvmmsg_time32); COND_SYSCALL_COMPAT(recvmmsg_time32); COND_SYSCALL_COMPAT(recvmmsg_time64); +COND_SYSCALL(ioctl32); +COND_SYSCALL_COMPAT(ioctl32); + /* * Architecture specific syscalls: see further below */
diff --git a/tools/include/uapi/asm-generic/unistd.h b/tools/include/uapi/asm-generic/unistd.h
index 728752917785..18279e5b7b4f 100644
--- a/tools/include/uapi/asm-generic/unistd.h
+++ b/tools/include/uapi/asm-generic/unistd.h@@ -862,8 +862,15 @@ __SYSCALL(__NR_process_madvise, sys_process_madvise) #define __NR_epoll_pwait2 441 __SC_COMP(__NR_epoll_pwait2, sys_epoll_pwait2, compat_sys_epoll_pwait2) +#define __NR_ioctl32 442 +#ifdef CONFIG_COMPAT +__SC_COMP(__NR_ioctl32, sys_ioctl32, compat_sys_ioctl) +#else +__SC_COMP(__NR_ioctl32, sys_ni_syscall, sys_ni_syscall) +#endif + #undef __NR_syscalls -#define __NR_syscalls 442 +#define __NR_syscalls 443 /* * 32 bit systems traditionally used different
--
2.27.0