Move the BRK_START to a fixed, safe address (XCC)
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 26 Oct 2016 19:19:07 +0000 (15:19 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 26 Oct 2016 19:50:34 +0000 (15:50 -0400)
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 <brho@cs.berkeley.edu>
kern/arch/riscv/ros/mmu.h
kern/arch/x86/ros/mmu64.h
kern/include/ros/procinfo.h
kern/src/elf.c
kern/src/process.c
kern/src/syscall.c
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sbrk.c

index e52100b..28c16dc 100644 (file)
@@ -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
index 66d54e1..7c120bd 100644 (file)
@@ -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 */
index e5a3641..56bf7d9 100644 (file)
@@ -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 */
index 6bd1d0c..18e3fbe 100644 (file)
@@ -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;
index 4402411..af23582 100644 (file)
@@ -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. */
index f5ee658..fbad9ef 100644 (file)
@@ -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);
index f41e6d8..3c696bb 100644 (file)
 #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))