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/include/asm/futex.h | 4 ++++ arch/um/include/asm/mmu.h | 3 +++ arch/um/include/asm/mmu_context.h | 13 +++++++++++-- arch/um/include/asm/tlbflush.h | 22 ++++++++++++++++++++++ arch/um/include/asm/uaccess.h | 7 ++++--- arch/um/include/shared/os.h | 6 ++++++ arch/um/kernel/Makefile | 3 ++- arch/um/kernel/mem.c | 12 +++++++++++- arch/um/kernel/physmem.c | 6 ++++++ arch/um/kernel/skas/Makefile | 4 ++-- arch/um/kernel/trap.c | 4 ++++ arch/um/os-Linux/process.c | 4 ++-- 12 files changed, 77 insertions(+), 11 deletions(-) diff --git a/arch/um/include/asm/futex.h b/arch/um/include/asm/futex.h index 780aa6bfc050..89a8ac0b6963 100644 --- a/arch/um/include/asm/futex.h +++ b/arch/um/include/asm/futex.h @@ -8,7 +8,11 @@ int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr); +#ifdef CONFIG_MMU 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..da287e8c86b3 100644 --- a/arch/um/include/asm/mmu_context.h +++ b/arch/um/include/asm/mmu_context.h @@ -37,10 +37,19 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, } #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 +#ifdef CONFIG_MMU +extern int init_new_context(struct task_struct *task, struct mm_struct *mm); extern void destroy_context(struct mm_struct *mm); +#else +static inline int init_new_context(struct task_struct *task, struct mm_struct *mm) +{ + return 0; +} +static inline void destroy_context(struct mm_struct *mm) +{ +} +#endif #include <asm-generic/mmu_context.h> diff --git a/arch/um/include/asm/tlbflush.h b/arch/um/include/asm/tlbflush.h index 13a3009942be..9157f71695c6 100644 --- a/arch/um/include/asm/tlbflush.h +++ b/arch/um/include/asm/tlbflush.h @@ -30,6 +30,7 @@ * - flush_tlb_kernel_range(start, end) flushes a range of kernel pages */ +#ifdef CONFIG_MMU extern int um_tlb_sync(struct mm_struct *mm); extern void flush_tlb_all(void); @@ -55,5 +56,26 @@ static inline void flush_tlb_kernel_range(unsigned long start, /* Kernel needs to be synced immediately */ um_tlb_sync(&init_mm); } +#else +static inline int um_tlb_sync(struct mm_struct *mm) +{ + return 0; +} + +static inline void flush_tlb_page(struct vm_area_struct *vma, + unsigned long address) +{ +} + +static inline void flush_tlb_range(struct vm_area_struct *vma, + unsigned long start, unsigned long end) +{ +} + +static inline void flush_tlb_kernel_range(unsigned long start, + unsigned long end) +{ +} +#endif #endif 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/include/shared/os.h b/arch/um/include/shared/os.h index 5babad8c5f75..6874be0c38a8 100644 --- a/arch/um/include/shared/os.h +++ b/arch/um/include/shared/os.h @@ -195,7 +195,13 @@ extern void get_host_cpu_features( extern int create_mem_file(unsigned long long len); /* tlb.c */ +#ifdef CONFIG_MMU extern void report_enomem(void); +#else +static inline void report_enomem(void) +{ +} +#endif /* process.c */ extern void os_alarm_process(int pid); diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index f8567b933ffa..b41e9bcabbe3 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile @@ -16,9 +16,10 @@ extra-y := vmlinux.lds obj-y = config.o exec.o exitcode.o irq.o ksyms.o mem.o \ physmem.o process.o ptrace.o reboot.o sigio.o \ - signal.o sysrq.o time.o tlb.o trap.o \ + signal.o sysrq.o time.o trap.o \ um_arch.o umid.o maccess.o kmsg_dump.o capflags.o skas/ obj-y += load_file.o +obj-$(CONFIG_MMU) += tlb.o obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o obj-$(CONFIG_GPROF) += gprof_syms.o diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index 53248ed04771..b674017d9871 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c @@ -64,7 +64,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; @@ -78,6 +79,7 @@ void __init mem_init(void) * Create a page table and place a pointer to it in a middle page * directory entry. */ +#ifdef CONFIG_MMU static void __init one_page_table_init(pmd_t *pmd) { if (pmd_none(*pmd)) { @@ -149,6 +151,12 @@ static void __init fixrange_init(unsigned long start, unsigned long end, j = 0; } } +#else +static void __init fixrange_init(unsigned long start, unsigned long end, + pgd_t *pgd_base) +{ +} +#endif static void __init fixaddr_user_init( void) { @@ -230,6 +238,7 @@ void *uml_kmalloc(int size, int flags) return kmalloc(size, flags); } +#ifdef CONFIG_MMU static const pgprot_t protection_map[16] = { [VM_NONE] = PAGE_NONE, [VM_READ] = PAGE_READONLY, @@ -249,3 +258,4 @@ static const pgprot_t protection_map[16] = { [VM_SHARED | VM_EXEC | VM_WRITE | VM_READ] = PAGE_SHARED }; DECLARE_VM_GET_PAGE_PROT +#endif diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c index a74f17b033c4..f55d46dbe173 100644 --- a/arch/um/kernel/physmem.c +++ b/arch/um/kernel/physmem.c @@ -84,7 +84,11 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end, exit(1); } +#ifdef CONFIG_MMU physmem_fd = create_mem_file(len); +#else + physmem_fd = -1; +#endif err = os_map_memory((void *) reserve_end, physmem_fd, reserve, map_size, 1, 1, 1); @@ -95,12 +99,14 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end, exit(1); } +#ifdef CONFIG_MMU /* * Special kludge - This page will be mapped in to userspace processes * from physmem_fd, so it needs to be written out there. */ os_seek_file(physmem_fd, __pa(__syscall_stub_start)); os_write_file(physmem_fd, __syscall_stub_start, PAGE_SIZE); +#endif memblock_add(__pa(start), len); memblock_reserve(__pa(start), reserve); diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile index 3384be42691f..64d7ba803b1a 100644 --- a/arch/um/kernel/skas/Makefile +++ b/arch/um/kernel/skas/Makefile @@ -3,8 +3,8 @@ # Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) # -obj-y := stub.o mmu.o process.o syscall.o uaccess.o \ - stub_exe_embed.o +obj-y := stub.o process.o stub_exe_embed.o +obj-$(CONFIG_MMU) += mmu.o syscall.o uaccess.o # Stub executable diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c index cdaee3e94273..a7519b3de4bf 100644 --- a/arch/um/kernel/trap.c +++ b/arch/um/kernel/trap.c @@ -24,6 +24,7 @@ int handle_page_fault(unsigned long address, unsigned long ip, int is_write, int is_user, int *code_out) { +#ifdef CONFIG_MMU struct mm_struct *mm = current->mm; struct vm_area_struct *vma; pmd_t *pmd; @@ -129,6 +130,9 @@ int handle_page_fault(unsigned long address, unsigned long ip, goto out_nosemaphore; pagefault_out_of_memory(); return 0; +#else + return -EFAULT; +#endif } static void show_segv_info(struct uml_pt_regs *regs) diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index 9f086f939420..ef1a2f0aa06a 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c @@ -63,8 +63,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