From d4d93df032229a9a8ec066acc2b68eeb32650ae2 Mon Sep 17 00:00:00 2001 From: NAKAMURA Gou Date: Thu, 17 Mar 2016 20:02:16 +0900 Subject: [PATCH] mmap: add "flags" checks for MAP_HUGE* --- arch/x86/kernel/include/arch/mman.h | 4 ++++ arch/x86/kernel/syscall.c | 35 +++++++++++++++++++++++------ kernel/syscall.c | 14 +++++++++--- 3 files changed, 43 insertions(+), 10 deletions(-) diff --git a/arch/x86/kernel/include/arch/mman.h b/arch/x86/kernel/include/arch/mman.h index 70bf7a04..0e041483 100644 --- a/arch/x86/kernel/include/arch/mman.h +++ b/arch/x86/kernel/include/arch/mman.h @@ -27,6 +27,10 @@ #define MAP_STACK 0x00020000 #define MAP_HUGETLB 0x00040000 +#define MAP_HUGE_SHIFT 26 +#define MAP_HUGE_2MB (21 << MAP_HUGE_SHIFT) +#define MAP_HUGE_1GB (30 << MAP_HUGE_SHIFT) + /* * for mlockall() */ diff --git a/arch/x86/kernel/syscall.c b/arch/x86/kernel/syscall.c index 694a37cf..9afbab27 100644 --- a/arch/x86/kernel/syscall.c +++ b/arch/x86/kernel/syscall.c @@ -1203,6 +1203,8 @@ SYSCALL_DECLARE(mmap) | MAP_ANONYMOUS // 20 | MAP_LOCKED // 2000 | MAP_POPULATE // 8000 + | MAP_HUGETLB // 00040000 + | (0x3F << MAP_HUGE_SHIFT) // FC000000 ; const int ignored_flags = 0 #ifdef USE_NOCACHE_MMAP @@ -1219,13 +1221,12 @@ SYSCALL_DECLARE(mmap) | MAP_GROWSDOWN // 0100 | MAP_EXECUTABLE // 1000 | MAP_NONBLOCK // 00010000 - | MAP_HUGETLB // 00040000 ; const intptr_t addr0 = ihk_mc_syscall_arg0(ctx); const size_t len0 = ihk_mc_syscall_arg1(ctx); const int prot = ihk_mc_syscall_arg2(ctx); - const int flags = ihk_mc_syscall_arg3(ctx); + const int flags0 = ihk_mc_syscall_arg3(ctx); const int fd = ihk_mc_syscall_arg4(ctx); const off_t off0 = ihk_mc_syscall_arg5(ctx); struct thread *thread = cpu_local_var(current); @@ -1233,9 +1234,10 @@ SYSCALL_DECLARE(mmap) int error; intptr_t addr; size_t len; + int flags = flags0; dkprintf("sys_mmap(%lx,%lx,%x,%x,%d,%lx)\n", - addr0, len0, prot, flags, fd, off0); + addr0, len0, prot, flags0, fd, off0); /* check constants for flags */ if (1) { @@ -1265,7 +1267,7 @@ SYSCALL_DECLARE(mmap) || ((flags & MAP_SHARED) && (flags & MAP_PRIVATE)) || (off0 & (PAGE_SIZE - 1))) { ekprintf("sys_mmap(%lx,%lx,%x,%x,%x,%lx):EINVAL\n", - addr0, len0, prot, flags, fd, off0); + addr0, len0, prot, flags0, fd, off0); error = -EINVAL; goto out; } @@ -1274,7 +1276,7 @@ SYSCALL_DECLARE(mmap) || (region->user_end <= addr) || ((region->user_end - addr) < len)) { ekprintf("sys_mmap(%lx,%lx,%x,%x,%x,%lx):ENOMEM\n", - addr0, len0, prot, flags, fd, off0); + addr0, len0, prot, flags0, fd, off0); error = -ENOMEM; goto out; } @@ -1283,18 +1285,37 @@ SYSCALL_DECLARE(mmap) if ((flags & error_flags) || (flags & ~(supported_flags | ignored_flags))) { ekprintf("sys_mmap(%lx,%lx,%x,%x,%x,%lx):unknown flags %x\n", - addr0, len0, prot, flags, fd, off0, + addr0, len0, prot, flags0, fd, off0, (flags & ~(supported_flags | ignored_flags))); error = -EINVAL; goto out; } + if (flags & MAP_HUGETLB) { + switch (flags & (0x3F << MAP_HUGE_SHIFT)) { + case 0: + flags |= MAP_HUGE_2MB; /* default hugepage size */ + break; + + case MAP_HUGE_2MB: + case MAP_HUGE_1GB: + break; + + default: + ekprintf("sys_mmap(%lx,%lx,%x,%x,%x,%lx):" + "not supported page size.\n", + addr0, len0, prot, flags0, fd, off0); + error = -EINVAL; + goto out; + } + } + addr = do_mmap(addr, len, prot, flags, fd, off0); error = 0; out: dkprintf("sys_mmap(%lx,%lx,%x,%x,%d,%lx): %ld %lx\n", - addr0, len0, prot, flags, fd, off0, error, addr); + addr0, len0, prot, flags0, fd, off0, error, addr); return (!error)? addr: error; } diff --git a/kernel/syscall.c b/kernel/syscall.c index ae328363..abc994d8 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -941,6 +941,7 @@ do_mmap(const intptr_t addr0, const size_t len0, const int prot, int populated_mapping = 0; struct process *proc = thread->proc; struct mckfd *fdp = NULL; + int pgshift; dkprintf("do_mmap(%lx,%lx,%x,%x,%d,%lx)\n", addr0, len0, prot, flags, fd, off0); @@ -1117,13 +1118,20 @@ do_mmap(const intptr_t addr0, const size_t len0, const int prot, } vrflags |= VRFLAG_PROT_TO_MAXPROT(PROT_TO_VR_FLAG(maxprot)); + if (flags & MAP_HUGETLB) { + pgshift = (flags >> MAP_HUGE_SHIFT) & 0x3F; + } + else { + pgshift = PAGE_SHIFT; /* basic page size */ + } + error = add_process_memory_range(thread->vm, addr, addr+len, phys, - vrflags, memobj, off, PAGE_SHIFT); + vrflags, memobj, off, pgshift); if (error) { ekprintf("do_mmap:add_process_memory_range" - "(%p,%lx,%lx,%lx,%lx) failed %d\n", + "(%p,%lx,%lx,%lx,%lx,%d) failed %d\n", thread->vm, addr, addr+len, - virt_to_phys(p), vrflags, error); + virt_to_phys(p), vrflags, pgshift, error); goto out; }