This commit adds memory operations on UML under !MMU environment. Some part of the original UML code relying on CONFIG_MMU are excluded from compilation when !CONFIG_MMU. Additionally, generic functions such as uaccess, futex, memcpy/strnlen/strncpy can be used as user- and kernel-space share the address space in !CONFIG_MMU mode.
Signed-off-by: Hajime Tazaki <thehaj...@gmail.com> Signed-off-by: Ricardo Koller <ricar...@google.com> --- arch/um/Makefile | 4 ++++ arch/um/include/asm/futex.h | 4 ++++ arch/um/include/asm/mmu.h | 3 +++ arch/um/include/asm/mmu_context.h | 2 ++ arch/um/include/asm/uaccess.h | 7 ++++--- arch/um/kernel/mem.c | 3 ++- arch/um/os-Linux/mem.c | 4 ++++ arch/um/os-Linux/process.c | 4 ++-- 8 files changed, 25 insertions(+), 6 deletions(-) diff --git a/arch/um/Makefile b/arch/um/Makefile index 1d36a613aad8..fcf4bb915a31 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -46,6 +46,10 @@ ARCH_INCLUDE := -I$(srctree)/$(SHARED_HEADERS) ARCH_INCLUDE += -I$(srctree)/$(HOST_DIR)/um/shared KBUILD_CPPFLAGS += -I$(srctree)/$(HOST_DIR)/um +ifneq ($(CONFIG_MMU),y) +core-y += $(ARCH_DIR)/nommu/ +endif + # -Dvmap=kernel_vmap prevents anything from referencing the libpcap.o symbol so # named - it's a common symbol in libpcap, so we get a binary which crashes. # diff --git a/arch/um/include/asm/futex.h b/arch/um/include/asm/futex.h index 780aa6bfc050..785fd6649aa2 100644 --- a/arch/um/include/asm/futex.h +++ b/arch/um/include/asm/futex.h @@ -7,8 +7,12 @@ #include <asm/errno.h> +#ifdef CONFIG_MMU int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr); int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, u32 oldval, u32 newval); +#else +#include <asm-generic/futex.h> +#endif #endif diff --git a/arch/um/include/asm/mmu.h b/arch/um/include/asm/mmu.h index 01422b761aa0..d4087f9499e2 100644 --- a/arch/um/include/asm/mmu.h +++ b/arch/um/include/asm/mmu.h @@ -15,10 +15,13 @@ typedef struct mm_context { unsigned long sync_tlb_range_from; unsigned long sync_tlb_range_to; +#ifndef CONFIG_MMU + unsigned long end_brk; #ifdef CONFIG_BINFMT_ELF_FDPIC unsigned long exec_fdpic_loadmap; unsigned long interp_fdpic_loadmap; #endif +#endif /* !CONFIG_MMU */ } mm_context_t; #endif diff --git a/arch/um/include/asm/mmu_context.h b/arch/um/include/asm/mmu_context.h index 23dcc914d44e..033a70166066 100644 --- a/arch/um/include/asm/mmu_context.h +++ b/arch/um/include/asm/mmu_context.h @@ -36,11 +36,13 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, } } +#ifdef CONFIG_MMU #define init_new_context init_new_context extern int init_new_context(struct task_struct *task, struct mm_struct *mm); #define destroy_context destroy_context extern void destroy_context(struct mm_struct *mm); +#endif #include <asm-generic/mmu_context.h> diff --git a/arch/um/include/asm/uaccess.h b/arch/um/include/asm/uaccess.h index 1d4b6bbc1b65..9bfee12cb6b7 100644 --- a/arch/um/include/asm/uaccess.h +++ b/arch/um/include/asm/uaccess.h @@ -22,6 +22,7 @@ #define __addr_range_nowrap(addr, size) \ ((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) +#ifdef CONFIG_MMU extern unsigned long raw_copy_from_user(void *to, const void __user *from, unsigned long n); extern unsigned long raw_copy_to_user(void __user *to, const void *from, unsigned long n); extern unsigned long __clear_user(void __user *mem, unsigned long len); @@ -33,9 +34,6 @@ static inline int __access_ok(const void __user *ptr, unsigned long size); #define INLINE_COPY_FROM_USER #define INLINE_COPY_TO_USER - -#include <asm-generic/uaccess.h> - static inline int __access_ok(const void __user *ptr, unsigned long size) { unsigned long addr = (unsigned long)ptr; @@ -43,6 +41,9 @@ static inline int __access_ok(const void __user *ptr, unsigned long size) (__under_task_size(addr, size) || __access_ok_vsyscall(addr, size)); } +#endif + +#include <asm-generic/uaccess.h> /* no pagefaults for kernel addresses in um */ #define __get_kernel_nofault(dst, src, type, err_label) \ diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index e3a7ec32d6c7..f82f54bc6920 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c @@ -63,7 +63,8 @@ void __init mem_init(void) * to be turned on. */ brk_end = (unsigned long) UML_ROUND_UP(sbrk(0)); - map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0); + map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, + !IS_ENABLED(CONFIG_MMU)); memblock_free((void *)brk_end, uml_reserved - brk_end); uml_reserved = brk_end; diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c index 72f302f4d197..4f5d9a94f8e2 100644 --- a/arch/um/os-Linux/mem.c +++ b/arch/um/os-Linux/mem.c @@ -213,6 +213,10 @@ int __init create_mem_file(unsigned long long len) { int err, fd; + /* NOMMU kernel uses -1 as a fd for further use (e.g., mmap) */ + if (!IS_ENABLED(CONFIG_MMU)) + return -1; + fd = create_tmp_file(len); err = os_set_exec_close(fd); diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index 6df378639880..e2dc00fc84c0 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c @@ -70,8 +70,8 @@ int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len, prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | (x ? PROT_EXEC : 0); - loc = mmap64((void *) virt, len, prot, MAP_SHARED | MAP_FIXED, - fd, off); + loc = mmap64((void *) virt, len, prot, MAP_SHARED | MAP_FIXED | + (!IS_ENABLED(CONFIG_MMU) ? MAP_ANONYMOUS : 0), fd, off); if (loc == MAP_FAILED) return -errno; return 0; -- 2.43.0