The VM code often wants to mmap blobs at various fixed addresses, such as the guest kernel. Our old glibc heap would start right at the top of the program's loading point, which meant that we couldn't safely use any of that memory. The current vmrunkernel just has a huge array that covers the memory regions it expects to use. This is less than ideal.
This commit just specifies a region of the process's virtual address space that glibc will use for its sbrk() allocations (e.g. malloc()). Any program can safely mmap with MAP_FIXED below this address (up to the binary's end point, which the kernel reports in procinfo->program_end. Here's a before and after. Note the old 0x21000 bytes has moved from 0x647000 to its new location at 0x100000000000. bash-4.3$ cat /proc/self/maps 00100000-00120000 rwxp 00000000 01:00 146 /lib/ld-2.19.so 00320000-00321000 r--p 00020000 01:00 146 /lib/ld-2.19.so 00321000-00322000 rw-p 00021000 01:00 146 /lib/ld-2.19.so 00322000-00323000 rw-p 00000000 00:00 0 [heap] 00400000-00443000 r-x- 00000000 01:00 102 /bin/busybox 00443000-00444000 r-xp 00043000 01:00 102 /bin/busybox 00643000-00644000 rw-p 00043000 01:00 102 /bin/busybox 00644000-00647000 rw-p 00000000 00:00 0 [heap] 00647000-00668000 rwx- 00000000 00:00 0 [heap] 400000000000-400000001000 rw-p 00000000 01:00 146 /lib/ld-2.19.so 400000001000-400000002000 rw-p 00000000 00:00 0 [heap] 400000002000-400000141000 r-xp 00000000 01:00 182 /lib/libc-2.19.so 400000141000-400000341000 ---p 0013f000 01:00 182 /lib/libc-2.19.so 400000341000-400000345000 r--p 0013f000 01:00 182 /lib/libc-2.19.so 400000345000-400000347000 rw-p 00143000 01:00 182 /lib/libc-2.19.so 400000347000-40000034a000 rw-p 00000000 00:00 0 [heap] 40000034a000-40000034b000 rw-p 00000000 00:00 0 [heap] 40000034b000-40000034f000 rw-- 00000000 00:00 0 [heap] 40000034f000-400000351000 rwx- 00000000 00:00 0 [heap] 400000351000-400000353000 rw-- 00000000 00:00 0 [heap] 7f7fff8ff000-7f7fff9ff000 rw-- 00000000 00:00 0 [heap] bash-4.3$ cat /proc/self/maps 00100000-00120000 rwxp 00000000 01:00 146 /lib/ld-2.19.so 00320000-00321000 r--p 00020000 01:00 146 /lib/ld-2.19.so 00321000-00322000 rw-p 00021000 01:00 146 /lib/ld-2.19.so 00322000-00323000 rw-p 00000000 00:00 0 [heap] 00400000-00443000 r-x- 00000000 01:00 102 /bin/busybox 00443000-00444000 r-xp 00043000 01:00 102 /bin/busybox 00643000-00644000 rw-p 00043000 01:00 102 /bin/busybox 00644000-00647000 rw-p 00000000 00:00 0 [heap] 100000000000-100000021000 rwx- 00000000 00:00 0 [heap] 400000000000-400000001000 rw-p 00000000 01:00 146 /lib/ld-2.19.so 400000001000-400000002000 rw-p 00000000 00:00 0 [heap] 400000002000-400000141000 r-xp 00000000 01:00 182 /lib/libc-2.19.so 400000141000-400000341000 ---p 0013f000 01:00 182 /lib/libc-2.19.so 400000341000-400000345000 r--p 0013f000 01:00 182 /lib/libc-2.19.so 400000345000-400000347000 rw-p 00143000 01:00 182 /lib/libc-2.19.so 400000347000-40000034a000 rw-p 00000000 00:00 0 [heap] 40000034a000-40000034b000 rw-p 00000000 00:00 0 [heap] 40000034b000-40000034f000 rw-- 00000000 00:00 0 [heap] 40000034f000-400000351000 rwx- 00000000 00:00 0 [heap] 400000351000-400000353000 rw-- 00000000 00:00 0 [heap] 7f7fff8ff000-7f7fff9ff000 rw-- 00000000 00:00 0 [heap] Rebuild glibc. Signed-off-by: Barret Rhoden <[email protected]> --- kern/arch/riscv/ros/mmu.h | 4 ++++ kern/arch/x86/ros/mmu64.h | 11 ++++++++++- kern/include/ros/procinfo.h | 2 +- kern/src/elf.c | 2 +- kern/src/process.c | 2 +- kern/src/syscall.c | 4 ++-- .../gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sbrk.c | 7 ++----- 7 files changed, 21 insertions(+), 11 deletions(-) diff --git a/kern/arch/riscv/ros/mmu.h b/kern/arch/riscv/ros/mmu.h index e52100b87f07..28c16dc909da 100644 --- a/kern/arch/riscv/ros/mmu.h +++ b/kern/arch/riscv/ros/mmu.h @@ -158,3 +158,7 @@ typedef unsigned long pgdir_t; /* Arbitrary boundary between the break and the start of * memory returned by calls to mmap with addr = 0 */ #define BRK_END 0x40000000 +#warning "Check these addresses. Seem to be small. Are they 32 bit?" +/* Arbitrary boundary where the break (glibc's heap) starts. You can safely + * mmap with MAP_FIXED below this address. */ +#define BRK_START 0x0000100000000000 diff --git a/kern/arch/x86/ros/mmu64.h b/kern/arch/x86/ros/mmu64.h index 66d54e132a6f..7c120bd08bfc 100644 --- a/kern/arch/x86/ros/mmu64.h +++ b/kern/arch/x86/ros/mmu64.h @@ -115,11 +115,17 @@ typedef struct x86_pgdir { * . . * . . * | | + * | SBRK Heap | + * | | + * BRK_START ----> +------------------------------+ 0x0000100000000000 + * . . + * . . + * | | * | Empty Memory | * | | * |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| * | | - * | Program Data & Heap | + * | Program, BSS, & Data | * | | * +------------------------------+ 0x0000000000400000 * . . @@ -197,6 +203,9 @@ typedef struct x86_pgdir { /* Arbitrary boundary between the break and the start of * memory returned by calls to mmap with addr = 0 */ #define BRK_END 0x0000400000000000 +/* Arbitrary boundary where the break (glibc's heap) starts. You can safely + * mmap with MAP_FIXED below this address. */ +#define BRK_START 0x0000100000000000 /* **************************************** */ /* Page table constants, macros, etc */ diff --git a/kern/include/ros/procinfo.h b/kern/include/ros/procinfo.h index e5a36411d60b..56bf7d967072 100644 --- a/kern/include/ros/procinfo.h +++ b/kern/include/ros/procinfo.h @@ -52,7 +52,7 @@ typedef struct procinfo { size_t max_vcores; /* TODO: change to a uint32_t */ uint64_t tsc_freq; uint64_t timing_overhead; - void *heap_bottom; + uintptr_t program_end; /* glibc relies on stuff above this point. if you change it, you need to * rebuild glibc. */ bool is_mcp; /* is in multi mode */ diff --git a/kern/src/elf.c b/kern/src/elf.c index 6bd1d0c37de3..18e3fbe55bda 100644 --- a/kern/src/elf.c +++ b/kern/src/elf.c @@ -394,7 +394,7 @@ int load_elf(struct proc* p, struct file* f, uintptr_t core0_entry = ei.dynamic ? interp_ei.entry : ei.entry; proc_init_ctx(&p->scp_ctx, 0, core0_entry, stack_top, 0); - p->procinfo->heap_bottom = (void*)ei.highest_addr; + p->procinfo->program_end = ei.highest_addr; p->args_base = (void *) stack_top; return 0; diff --git a/kern/src/process.c b/kern/src/process.c index 4402411d5627..af2358221846 100644 --- a/kern/src/process.c +++ b/kern/src/process.c @@ -281,7 +281,7 @@ void proc_init_procinfo(struct proc* p) p->procinfo->max_vcores = max_vcores(p); p->procinfo->tsc_freq = __proc_global_info.tsc_freq; p->procinfo->timing_overhead = __proc_global_info.tsc_overhead; - p->procinfo->heap_bottom = 0; + p->procinfo->program_end = 0; /* 0'ing the arguments. Some higher function will need to set them */ memset(p->procinfo->res_grant, 0, sizeof(p->procinfo->res_grant)); /* 0'ing the vcore/pcore map. Will link the vcores later. */ diff --git a/kern/src/syscall.c b/kern/src/syscall.c index f5ee65894e6e..fbad9ef0d09c 100644 --- a/kern/src/syscall.c +++ b/kern/src/syscall.c @@ -843,7 +843,7 @@ static ssize_t sys_fork(env_t* e) /* In general, a forked process should be a fresh process, and we copy over * whatever stuff is needed between procinfo/procdata. */ *env->procdata = *e->procdata; - env->procinfo->heap_bottom = e->procinfo->heap_bottom; + env->procinfo->program_end = e->procinfo->program_end; /* FYI: once we call ready, the proc is open for concurrent usage */ __proc_ready(env); @@ -998,7 +998,7 @@ static int sys_exec(struct proc *p, char *path, size_t path_l, proc_replace_binary_path(p, t_path); proc_set_progname(p, argc ? argv[0] : NULL); proc_init_procdata(p); - p->procinfo->heap_bottom = 0; + p->procinfo->program_end = 0; /* When we destroy our memory regions, accessing cur_sysc would PF */ pcpui->cur_kthread->sysc = 0; unmap_and_destroy_vmrs(p); diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sbrk.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sbrk.c index f41e6d865d19..3c696bb03f31 100644 --- a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sbrk.c +++ b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sbrk.c @@ -22,11 +22,10 @@ #include <bits/libc-lock.h> #include <ros/syscall.h> #include <ros/memlayout.h> -#include <ros/procinfo.h> #include <ros/procdata.h> #include <sys/mman.h> -static uintptr_t curbrk = 0; +static uintptr_t curbrk = BRK_START; __libc_lock_define_initialized(static, __brk_lock); static bool is_early_scp(void) @@ -56,8 +55,6 @@ static void brk_unlock(void) static uintptr_t __internal_getbrk (void) { - if(curbrk == 0) - curbrk = (uintptr_t)__procinfo.heap_bottom; return curbrk; } @@ -81,7 +78,7 @@ __internal_setbrk (uintptr_t addr) } else if(real_new_brk < real_brk) { - if(real_new_brk < (uintptr_t)__procinfo.heap_bottom) + if (real_new_brk < BRK_START) return -1; if (munmap((void*)real_new_brk, real_brk - real_new_brk)) -- 2.8.0.rc3.226.g39d4020 -- You received this message because you are subscribed to the Google Groups "Akaros" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. For more options, visit https://groups.google.com/d/optout.
