| 
														
															@@ -26,21 +26,72 @@ DEFINE_LISTP(heap_vma); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 static LISTP_TYPE(heap_vma) g_heap_vma_list = LISTP_INIT; 
														 | 
														
														 | 
														
															 static LISTP_TYPE(heap_vma) g_heap_vma_list = LISTP_INIT; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 static PAL_LOCK g_heap_vma_lock = LOCK_INIT; 
														 | 
														
														 | 
														
															 static PAL_LOCK g_heap_vma_lock = LOCK_INIT; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+/* heap_vma objects are taken from pre-allocated pool to avoid recursive mallocs */ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+#define MAX_HEAP_VMAS 100000 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+static struct heap_vma g_heap_vma_pool[MAX_HEAP_VMAS]; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+static size_t g_heap_vma_num = 0; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+static struct heap_vma* g_free_vma = NULL; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+/* returns uninitialized heap_vma, the caller is responsible for setting at least bottom/top */ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+static struct heap_vma* __alloc_vma(void) { 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    assert(_DkInternalIsLocked(&g_heap_vma_lock)); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    if (g_free_vma) { 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        /* simple optimization: if there is a cached free vma object, use it */ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        assert((uintptr_t)g_free_vma >= (uintptr_t)&g_heap_vma_pool[0]); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        assert((uintptr_t)g_free_vma <= (uintptr_t)&g_heap_vma_pool[MAX_HEAP_VMAS - 1]); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        struct heap_vma* ret = g_free_vma; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        g_free_vma = NULL; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        g_heap_vma_num++; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        return ret; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    } 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    /* FIXME: this loop may become perf bottleneck on large number of vma objects; however, 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+     * experiments show that this number typically does not exceed 20 (thanks to VMA merging) */ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    for (size_t i = 0; i < MAX_HEAP_VMAS; i++) { 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        if (!g_heap_vma_pool[i].bottom && !g_heap_vma_pool[i].top) { 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            /* found empty slot in the pool, use it */ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            g_heap_vma_num++; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            return &g_heap_vma_pool[i]; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        } 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    } 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    return NULL; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+} 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+static void __free_vma(struct heap_vma* vma) { 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    assert(_DkInternalIsLocked(&g_heap_vma_lock)); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    assert((uintptr_t)vma >= (uintptr_t)&g_heap_vma_pool[0]); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    assert((uintptr_t)vma <= (uintptr_t)&g_heap_vma_pool[MAX_HEAP_VMAS - 1]); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    g_free_vma  = vma; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    vma->top    = 0; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    vma->bottom = 0; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    g_heap_vma_num--; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+} 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 int init_enclave_pages(void) { 
														 | 
														
														 | 
														
															 int init_enclave_pages(void) { 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    int ret; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															     g_heap_bottom = pal_sec.heap_min; 
														 | 
														
														 | 
														
															     g_heap_bottom = pal_sec.heap_min; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															     g_heap_top    = pal_sec.heap_max; 
														 | 
														
														 | 
														
															     g_heap_top    = pal_sec.heap_max; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															     size_t reserved_size = 0; 
														 | 
														
														 | 
														
															     size_t reserved_size = 0; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															     struct heap_vma* exec_vma = NULL; 
														 | 
														
														 | 
														
															     struct heap_vma* exec_vma = NULL; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    _DkInternalLock(&g_heap_vma_lock); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															     if (pal_sec.exec_addr < g_heap_top && pal_sec.exec_addr + pal_sec.exec_size > g_heap_bottom) { 
														 | 
														
														 | 
														
															     if (pal_sec.exec_addr < g_heap_top && pal_sec.exec_addr + pal_sec.exec_size > g_heap_bottom) { 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         /* there is an executable mapped inside the heap, carve a VMA for its area; this can happen 
														 | 
														
														 | 
														
															         /* there is an executable mapped inside the heap, carve a VMA for its area; this can happen 
														 | 
													
												
											
												
													
														| 
														 | 
														
															          * in case of non-PIE executables that start at a predefined address (typically 0x400000) */ 
														 | 
														
														 | 
														
															          * in case of non-PIE executables that start at a predefined address (typically 0x400000) */ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        exec_vma = malloc(sizeof(*exec_vma)); 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        exec_vma = __alloc_vma(); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         if (!exec_vma) { 
														 | 
														
														 | 
														
															         if (!exec_vma) { 
														 | 
													
												
											
												
													
														| 
														 | 
														
															             SGX_DBG(DBG_E, "*** Cannot initialize VMA for executable ***\n"); 
														 | 
														
														 | 
														
															             SGX_DBG(DBG_E, "*** Cannot initialize VMA for executable ***\n"); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-            return -PAL_ERROR_NOMEM; 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            ret = -PAL_ERROR_NOMEM; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            goto out; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         } 
														 | 
														
														 | 
														
															         } 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         exec_vma->bottom = SATURATED_P_SUB(pal_sec.exec_addr, MEMORY_GAP, g_heap_bottom); 
														 | 
														
														 | 
														
															         exec_vma->bottom = SATURATED_P_SUB(pal_sec.exec_addr, MEMORY_GAP, g_heap_bottom); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         exec_vma->top = SATURATED_P_ADD(pal_sec.exec_addr + pal_sec.exec_size, MEMORY_GAP, g_heap_top); 
														 | 
														
														 | 
														
															         exec_vma->top = SATURATED_P_ADD(pal_sec.exec_addr + pal_sec.exec_size, MEMORY_GAP, g_heap_top); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         exec_vma->is_pal_internal = false; 
														 | 
														
														 | 
														
															         exec_vma->is_pal_internal = false; 
														 | 
													
												
											
										
											
												
													
														 | 
														
															@@ -53,7 +104,11 @@ int init_enclave_pages(void) { 
														 | 
													
												
											
												
													
														| 
														 | 
														
															     atomic_add(reserved_size / g_page_size, &g_alloced_pages); 
														 | 
														
														 | 
														
															     atomic_add(reserved_size / g_page_size, &g_alloced_pages); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															     SGX_DBG(DBG_M, "Heap size: %luM\n", (g_heap_top - g_heap_bottom - reserved_size) / 1024 / 1024); 
														 | 
														
														 | 
														
															     SGX_DBG(DBG_M, "Heap size: %luM\n", (g_heap_top - g_heap_bottom - reserved_size) / 1024 / 1024); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-    return 0; 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    ret = 0; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+out: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    _DkInternalUnlock(&g_heap_vma_lock); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    return ret; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 } 
														 | 
														
														 | 
														
															 } 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															 static void* __create_vma_and_merge(void* addr, size_t size, bool is_pal_internal, 
														 | 
														
														 | 
														
															 static void* __create_vma_and_merge(void* addr, size_t size, bool is_pal_internal, 
														 | 
													
												
											
										
											
												
													
														 | 
														
															@@ -99,7 +154,7 @@ static void* __create_vma_and_merge(void* addr, size_t size, bool is_pal_interna 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															     /* create VMA with [addr, addr+size); in case of existing overlapping VMAs, the created VMA is 
														 | 
														
														 | 
														
															     /* create VMA with [addr, addr+size); in case of existing overlapping VMAs, the created VMA is 
														 | 
													
												
											
												
													
														| 
														 | 
														
															      * merged with them and the old VMAs are discarded, similar to mmap(MAX_FIXED) */ 
														 | 
														
														 | 
														
															      * merged with them and the old VMAs are discarded, similar to mmap(MAX_FIXED) */ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-    struct heap_vma* vma = malloc(sizeof(*vma)); 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    struct heap_vma* vma = __alloc_vma(); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															     if (!vma) 
														 | 
														
														 | 
														
															     if (!vma) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         return NULL; 
														 | 
														
														 | 
														
															         return NULL; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															     vma->bottom          = addr; 
														 | 
														
														 | 
														
															     vma->bottom          = addr; 
														 | 
													
												
											
										
											
												
													
														 | 
														
															@@ -126,7 +181,7 @@ static void* __create_vma_and_merge(void* addr, size_t size, bool is_pal_interna 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         vma->top    = MAX(vma_above->top, vma->top); 
														 | 
														
														 | 
														
															         vma->top    = MAX(vma_above->top, vma->top); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         LISTP_DEL(vma_above, &g_heap_vma_list, list); 
														 | 
														
														 | 
														
															         LISTP_DEL(vma_above, &g_heap_vma_list, list); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        free(vma_above); 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        __free_vma(vma_above); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         vma_above = vma_above_above; 
														 | 
														
														 | 
														
															         vma_above = vma_above_above; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															     } 
														 | 
														
														 | 
														
															     } 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
										
											
												
													
														 | 
														
															@@ -143,7 +198,7 @@ static void* __create_vma_and_merge(void* addr, size_t size, bool is_pal_interna 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         vma->top    = MAX(vma_below->top, vma->top); 
														 | 
														
														 | 
														
															         vma->top    = MAX(vma_below->top, vma->top); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         LISTP_DEL(vma_below, &g_heap_vma_list, list); 
														 | 
														
														 | 
														
															         LISTP_DEL(vma_below, &g_heap_vma_list, list); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        free(vma_below); 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        __free_vma(vma_below); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         vma_below = vma_below_below; 
														 | 
														
														 | 
														
															         vma_below = vma_below_below; 
														 | 
													
												
											
												
													
														| 
														 | 
														
															     } 
														 | 
														
														 | 
														
															     } 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
										
											
												
													
														 | 
														
															@@ -267,7 +322,7 @@ int free_enclave_pages(void* addr, size_t size) { 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															         if (vma->bottom < addr) { 
														 | 
														
														 | 
														
															         if (vma->bottom < addr) { 
														 | 
													
												
											
												
													
														| 
														 | 
														
															             /* create VMA [vma->bottom, addr); this may leave VMA [addr + size, vma->top), see below */ 
														 | 
														
														 | 
														
															             /* create VMA [vma->bottom, addr); this may leave VMA [addr + size, vma->top), see below */ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-            struct heap_vma* new = malloc(sizeof(*new)); 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            struct heap_vma* new = __alloc_vma(); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															             if (!new) { 
														 | 
														
														 | 
														
															             if (!new) { 
														 | 
													
												
											
												
													
														| 
														 | 
														
															                 SGX_DBG(DBG_E, "*** Cannot create split VMA during free of address %p ***\n", addr); 
														 | 
														
														 | 
														
															                 SGX_DBG(DBG_E, "*** Cannot create split VMA during free of address %p ***\n", addr); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															                 ret = -PAL_ERROR_NOMEM; 
														 | 
														
														 | 
														
															                 ret = -PAL_ERROR_NOMEM; 
														 | 
													
												
											
										
											
												
													
														 | 
														
															@@ -285,7 +340,7 @@ int free_enclave_pages(void* addr, size_t size) { 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         if (vma->top <= addr + size) { 
														 | 
														
														 | 
														
															         if (vma->top <= addr + size) { 
														 | 
													
												
											
												
													
														| 
														 | 
														
															             /* memory area to free completely covers/extends above the rest of the VMA */ 
														 | 
														
														 | 
														
															             /* memory area to free completely covers/extends above the rest of the VMA */ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															             LISTP_DEL(vma, &g_heap_vma_list, list); 
														 | 
														
														 | 
														
															             LISTP_DEL(vma, &g_heap_vma_list, list); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-            free(vma); 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            __free_vma(vma); 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         } 
														 | 
														
														 | 
														
															         } 
														 | 
													
												
											
												
													
														| 
														 | 
														
															     } 
														 | 
														
														 | 
														
															     } 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 |