Changeset 289 in vbox for trunk/src/VBox/Runtime/r0drv/linux/alloc-r0drv-linux.c
- Timestamp:
- Jan 25, 2007 5:41:27 AM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r0drv/linux/alloc-r0drv-linux.c
r191 r289 29 29 #include "r0drv/alloc-r0drv.h" 30 30 31 #if defined(__AMD64__) || defined(__DOXYGEN__) 32 /** 33 * We need memory in the module range (~2GB to ~0) this can only be obtained 34 * thru APIs that are not exported (see module_alloc()). 35 * 36 * So, we'll have to create a quick and dirty heap here using BSS memory. 37 * Very annoying and it's going to restrict us! 38 */ 39 # define RTMEMALLOC_EXEC_HEAP 40 #endif 41 #ifdef RTMEMALLOC_EXEC_HEAP 42 # include <iprt/heap.h> 43 # include <iprt/spinlock.h> 44 #endif 45 46 47 /******************************************************************************* 48 * Global Variables * 49 *******************************************************************************/ 50 #ifdef RTMEMALLOC_EXEC_HEAP 51 /** The heap. */ 52 static RTHEAPSIMPLE g_HeapExec = NIL_RTHEAPSIMPLE; 53 /** Spinlock protecting the heap. */ 54 static RTSPINLOCK g_HeapExecSpinlock = NIL_RTHEAPSIMPLE; 55 56 57 /** 58 * API for cleaning up the heap spinlock on IPRT termination. 59 * This is as RTMemExecDonate specific to AMD64 Linux/GNU. 60 */ 61 RTDECL(void) RTMemExecCleanup(void) 62 { 63 RTSpinlockDestroy(g_HeapSpinlock); 64 g_HeapSpinlock = NIL_RTSPINLOCK; 65 } 66 67 68 /** 69 * Donate read+write+execute memory to the exec heap. 70 * 71 * This API is specific to AMD64 and Linux/GNU. A kernel module that desires to 72 * use RTMemExecAlloc on AMD64 Linux/GNU will have to donate some statically 73 * allocated memory in the module if it wishes for GCC generated code to work. 74 * GCC can only generate modules that work in the address range ~2GB to ~0 75 * currently. 76 * 77 * The API only accept one single donation. 78 * 79 * @returns IPRT status code. 80 * @param pvMemory Pointer to the memory block. 81 * @param cb The size of the memory block. 82 */ 83 RTDECL(int) RTMemExecDonate(void *pvMemory, size_t cb) 84 { 85 AssertReturn(g_HeapExec == NIL_RTHEAPSIMPLE, VERR_WRONG_ORDER); 86 87 int rc = RTSpinlockCreate(&g_HeapExecSpinlock); 88 if (RT_SUCCESS(rc)) 89 { 90 rc = RTHeapSimpleInit(&g_HeapExec, pvMemory, cb); 91 if (RT_FAILURE(rc)) 92 RTMemExecCleanup(); 93 } 94 return rc; 95 } 96 #endif /* RTMEMALLOC_EXEC_HEAP */ 97 98 31 99 32 100 /** … … 43 111 { 44 112 #if defined(__AMD64__) 45 #if 0 46 /* 47 * We need memory in the module range (~2GB to ~0) this can only be obtained 48 * thru APIs that are not exported (see module_alloc()). 49 * 50 * So, we'll have to create a quick and dirty heap here using BSS memory. 51 * Very annoying and it's going to restrict us! 52 */ 53 static uint8_t s_abMemory[_2M]; 54 static uint8_t *s_pbMemory = NULL; /**< NULL if not initialized. */ 55 static RTSPINLOCK s_Spinlock = NIL_RTSPINLOCK; 56 static struct RTMEMRECLNXEXEC 113 # ifdef RTMEMALLOC_EXEC_HEAP 114 if (g_HeapExec != NIL_RTHEAPSIMPLE) 57 115 { 58 PRTMEMHDR pHdr; /**< NULL if no free range. */ 59 uint32_t off; /**< Offset into s_pbMemory. */ 60 uint32_t cb; 61 } s_aMemRecs[64]; 62 RTSPINLOCKTMP SpinlockTmp = RTSPINLOCKTMP_INITIALIZER; 63 64 if (!s_pbMemory) 65 { 66 /* serialize */ 116 fFlags |= RTMEMHDR_FLAG_EXEC_HEAP; 117 RTSPINLOCKTMP SpinlockTmp = RTSPINLOCKTMP_INITIALIZER; 118 RTSpinlockAcquireNoInts(g_HeapExecSpinlock, &SpinlockTmp); 119 pHdr = (PRTMEMHDR)RTHeapSimpleAlloc(g_HeapExec, cb + sizeof(*pHdr), 0); 120 RTSpinlockReleaseNoInts(g_HeapExecSpinlock, &SpinlockTmp); 67 121 } 68 69 RTSpinlockAcquireNoInts(s_Spinlock, &SpinlockTmp); 70 /* find free area and split it... */ 71 72 RTSpinlockReleaseNoInts(s_Spinlock, &SpinlockTmp); 73 74 # else 75 pHdr = (PRTMEMHDR)__vmalloc(cb + sizeof(*pHdr), GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL_EXEC); 76 # endif 77 122 else 123 # endif 124 pHdr = (PRTMEMHDR)__vmalloc(cb + sizeof(*pHdr), GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL_EXEC); 78 125 79 126 #elif defined(PAGE_KERNEL_EXEC) && defined(CONFIG_X86_PAE) … … 83 130 pHdr = (PRTMEMHDR)vmalloc(cb + sizeof(*pHdr)); 84 131 #endif 85 fFlags &= ~RTMEMHDR_FLAG_KMALLOC;86 132 } 87 133 else … … 93 139 } 94 140 else 95 {96 fFlags &= ~RTMEMHDR_FLAG_KMALLOC;97 141 pHdr = vmalloc(cb + sizeof(*pHdr)); 98 }99 142 } 100 143 … … 121 164 if (pHdr->fFlags & RTMEMHDR_FLAG_KMALLOC) 122 165 kfree(pHdr); 166 #ifdef RTMEMALLOC_EXEC_HEAP 167 else if (pHdr->fFlags & RTMEMHDR_FLAG_EXEC_HEAP) 168 { 169 RTSpinlockAcquireNoInts(g_HeapExecSpinlock, &SpinlockTmp); 170 RTHeapSimpleFree(g_HeapExec, pHdr); 171 RTSpinlockReleaseNoInts(g_HeapExecSpinlock, &SpinlockTmp); 172 } 173 #endif 123 174 else 124 175 vfree(pHdr);
Note:
See TracChangeset
for help on using the changeset viewer.