From: Guo Ren <guoren@xxxxxxxxxxxxxxxxx> Adds initial skeletal COMPAT Kbuild (Runing 32bit U-mode on 64bit S-mode) support. - Setup kconfig & dummy functions for compiling. - Implement compat_start_thread by the way. Signed-off-by: Guo Ren <guoren@xxxxxxxxxxxxxxxxx> --- arch/riscv/Kconfig | 22 ++++++++++++++++++++++ arch/riscv/include/asm/elf.h | 8 ++++++++ arch/riscv/include/asm/processor.h | 3 +++ arch/riscv/kernel/Makefile | 2 ++ arch/riscv/kernel/compat_signal.c | 18 ++++++++++++++++++ arch/riscv/kernel/process.c | 10 ++++++++++ arch/riscv/kernel/ptrace.c | 9 +++++++++ arch/riscv/kernel/vdso.c | 8 ++++++++ 8 files changed, 80 insertions(+) create mode 100644 arch/riscv/kernel/compat_signal.c diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 821252b65f89..6c3515a492a8 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -72,6 +72,7 @@ config RISCV select HAVE_ARCH_KGDB if !XIP_KERNEL select HAVE_ARCH_KGDB_QXFER_PKT select HAVE_ARCH_MMAP_RND_BITS if MMU + select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT select HAVE_ARCH_SECCOMP_FILTER select HAVE_ARCH_TRACEHOOK select HAVE_ARCH_TRANSPARENT_HUGEPAGE if 64BIT && MMU @@ -122,12 +123,18 @@ config ARCH_MMAP_RND_BITS_MIN default 18 if 64BIT default 8 +config ARCH_MMAP_RND_COMPAT_BITS_MIN + default 8 + # max bits determined by the following formula: # VA_BITS - PAGE_SHIFT - 3 config ARCH_MMAP_RND_BITS_MAX default 24 if 64BIT # SV39 based default 17 +config ARCH_MMAP_RND_COMPAT_BITS_MAX + default 17 + # set if we run in machine mode, cleared if we run in supervisor mode config RISCV_M_MODE bool @@ -427,6 +434,21 @@ config CRASH_DUMP For more details see Documentation/admin-guide/kdump/kdump.rst +config COMPAT + bool "Kernel support for 32-bit U-mode" + depends on 64BIT && MMU + help + This option enables support for a 32-bit U-mode running under a 64-bit + kernel at S-mode. riscv32-specific components such as system calls, + the user helper functions (vdso), signal rt_frame functions and the + ptrace interface are handled appropriately by the kernel. + + If you want to execute 32-bit userspace applications, say Y. + +config SYSVIPC_COMPAT + def_bool y + depends on COMPAT && SYSVIPC + endmenu menu "Boot options" diff --git a/arch/riscv/include/asm/elf.h b/arch/riscv/include/asm/elf.h index 48c116f3c12d..37f1cbdaa242 100644 --- a/arch/riscv/include/asm/elf.h +++ b/arch/riscv/include/asm/elf.h @@ -129,5 +129,13 @@ do { if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \ typedef compat_ulong_t compat_elf_greg_t; typedef compat_elf_greg_t compat_elf_gregset_t[ELF_NGREG]; +#define compat_start_thread compat_start_thread + + +extern int compat_arch_setup_additional_pages(struct linux_binprm *bprm, + int uses_interp); +#define compat_arch_setup_additional_pages \ + compat_arch_setup_additional_pages + #endif /* CONFIG_COMPAT */ #endif /* _ASM_RISCV_ELF_H */ diff --git a/arch/riscv/include/asm/processor.h b/arch/riscv/include/asm/processor.h index 8649436b8fcf..9544c138d9ce 100644 --- a/arch/riscv/include/asm/processor.h +++ b/arch/riscv/include/asm/processor.h @@ -62,6 +62,9 @@ extern void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp); #ifdef CONFIG_COMPAT +extern void compat_start_thread(struct pt_regs *regs, + unsigned long pc, unsigned long sp); + #define DEFAULT_MAP_WINDOW_64 TASK_SIZE_64 #else #define DEFAULT_MAP_WINDOW_64 TASK_SIZE diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile index 3397ddac1a30..f83e22affd5f 100644 --- a/arch/riscv/kernel/Makefile +++ b/arch/riscv/kernel/Makefile @@ -65,3 +65,5 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_JUMP_LABEL) += jump_label.o obj-$(CONFIG_EFI) += efi.o +obj-$(CONFIG_COMPAT) += compat_syscall_table.o +obj-$(CONFIG_COMPAT) += compat_signal.o diff --git a/arch/riscv/kernel/compat_signal.c b/arch/riscv/kernel/compat_signal.c new file mode 100644 index 000000000000..1ad3d348f37c --- /dev/null +++ b/arch/riscv/kernel/compat_signal.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include <linux/compat.h> +#include <linux/signal.h> +#include <linux/uaccess.h> +#include <linux/syscalls.h> +#include <linux/tracehook.h> +#include <linux/linkage.h> + +#include <asm/ucontext.h> +#include <asm/vdso.h> +#include <asm/switch_to.h> +#include <asm/csr.h> + +COMPAT_SYSCALL_DEFINE0(rt_sigreturn) +{ + return 0; +} diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c index 03ac3aa611f5..9ebf9a95e5ea 100644 --- a/arch/riscv/kernel/process.c +++ b/arch/riscv/kernel/process.c @@ -15,6 +15,7 @@ #include <linux/tick.h> #include <linux/ptrace.h> #include <linux/uaccess.h> +#include <uapi/linux/elf.h> #include <asm/unistd.h> #include <asm/processor.h> @@ -99,6 +100,15 @@ void start_thread(struct pt_regs *regs, unsigned long pc, regs->sp = sp; } +#ifdef CONFIG_COMPAT +void compat_start_thread(struct pt_regs *regs, unsigned long pc, + unsigned long sp) +{ + start_thread(regs, pc, sp); + regs->status |= SR_UXL_32; +} +#endif + void flush_thread(void) { #ifdef CONFIG_FPU diff --git a/arch/riscv/kernel/ptrace.c b/arch/riscv/kernel/ptrace.c index 9c0511119bad..55dd50f8a5cc 100644 --- a/arch/riscv/kernel/ptrace.c +++ b/arch/riscv/kernel/ptrace.c @@ -12,6 +12,7 @@ #include <asm/thread_info.h> #include <asm/switch_to.h> #include <linux/audit.h> +#include <linux/compat.h> #include <linux/ptrace.h> #include <linux/elf.h> #include <linux/regset.h> @@ -275,3 +276,11 @@ __visible void do_syscall_trace_exit(struct pt_regs *regs) trace_sys_exit(regs, regs_return_value(regs)); #endif } + +#ifdef CONFIG_COMPAT +long compat_arch_ptrace(struct task_struct *child, compat_long_t request, + compat_ulong_t caddr, compat_ulong_t cdata) +{ + return 0; +} +#endif diff --git a/arch/riscv/kernel/vdso.c b/arch/riscv/kernel/vdso.c index a9436a65161a..4f523a23a5d1 100644 --- a/arch/riscv/kernel/vdso.c +++ b/arch/riscv/kernel/vdso.c @@ -253,6 +253,14 @@ static int __setup_additional_pages(struct mm_struct *mm, return PTR_ERR(ret); } +#ifdef CONFIG_COMPAT +int compat_arch_setup_additional_pages(struct linux_binprm *bprm, + int uses_interp) +{ + return 0; +} +#endif + int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) { struct mm_struct *mm = current->mm; -- 2.25.1