diff --git a/src/libos/Makefile b/src/libos/Makefile index f0afd430..209f3901 100644 --- a/src/libos/Makefile +++ b/src/libos/Makefile @@ -82,10 +82,6 @@ CXX_FLAGS := $(SGX_CXXFLAGS_T) $(C_COMMON_FLAGS) ifdef OCCLUM_BUILTIN_CONF_FILE_MAC C_FLAGS += -DOCCLUM_BUILTIN_CONF_FILE_MAC='"$(OCCLUM_BUILTIN_CONF_FILE_MAC)"' endif -# The total size of user-space memory must be builtin into the binary -ifdef OCCLUM_BUILTIN_VM_USER_SPACE_SIZE -C_FLAGS += -DOCCLUM_BUILTIN_VM_USER_SPACE_SIZE='($(OCCLUM_BUILTIN_VM_USER_SPACE_SIZE))' -endif _Other_Link_Flags := -L$(RUST_SGX_SDK_DIR)/compiler-rt/ -L$(BUILD_DIR)/lib _Other_Enclave_Libs := -locclum-libos-core -lsgx_tprotected_fs diff --git a/src/libos/src/builtin/vm_get_preallocated_user_space_memory.c b/src/libos/src/builtin/vm_get_preallocated_user_space_memory.c deleted file mode 100644 index 48445a44..00000000 --- a/src/libos/src/builtin/vm_get_preallocated_user_space_memory.c +++ /dev/null @@ -1,17 +0,0 @@ -#include - -// The total size of the memory available to user programs -// Should be provided by Makefile -#ifndef OCCLUM_BUILTIN_VM_USER_SPACE_SIZE -#define OCCLUM_BUILTIN_VM_USER_SPACE_SIZE (128*1024*1024) -#endif - -static char __preallocated_memory[OCCLUM_BUILTIN_VM_USER_SPACE_SIZE] - __attribute__ (( - section(".executable_data,\"awx\",@nobits#"), - aligned(4096))) = {0}; - -void vm_get_preallocated_user_space_memory(void** paddr, size_t* psize) { - *paddr = __preallocated_memory; - *psize = sizeof(__preallocated_memory); -} diff --git a/src/libos/src/vm/user_space_vm.rs b/src/libos/src/vm/user_space_vm.rs index 100adabe..25ec94fa 100644 --- a/src/libos/src/vm/user_space_vm.rs +++ b/src/libos/src/vm/user_space_vm.rs @@ -1,71 +1,109 @@ use super::*; +use config::LIBOS_CONFIG; /// The virtual memory manager for the entire user space -#[derive(Debug)] pub struct UserSpaceVMManager { - vm_manager: Arc>, + total_size: usize, + free_size: SgxMutex, } impl UserSpaceVMManager { - pub unsafe fn from(addr: usize, size: usize) -> Result { - let vm_manager = Arc::new(SgxMutex::new(VMManager::from(addr, size)?)); - Ok(UserSpaceVMManager { vm_manager }) + fn new() -> UserSpaceVMManager { + let rsrv_mem_size = LIBOS_CONFIG.resource_limits.user_space_size; + UserSpaceVMManager { + total_size: rsrv_mem_size, + free_size: SgxMutex::new(rsrv_mem_size), + } } pub fn alloc(&self, size: usize) -> Result { - let user_vm_range = unsafe { - let mmap_options = VMMapOptionsBuilder::default().size(size).build()?; + let vm_range = unsafe { + let ptr = sgx_alloc_rsrv_mem(size); + let perm = MemPerm::READ | MemPerm::WRITE | MemPerm::EXEC; + if ptr.is_null() { + return_errno!(ENOMEM, "run out of reserved memory"); + } + // Change the page permission to RWX + assert!(sgx_tprotect_rsrv_mem(ptr, size, perm.bits()) == sgx_status_t::SGX_SUCCESS); - let mut vm_manager = self.vm_manager.lock().unwrap(); - let user_vm_addr = vm_manager.mmap(&mmap_options)?; - VMRange::from_unchecked(user_vm_addr, user_vm_addr + size) + let addr = ptr as usize; + debug!("allocated rsrv addr is 0x{:x}, len is 0x{:x}", addr, size); + VMRange::from_unchecked(addr, addr + size) }; - Ok(UserSpaceVMRange::new( - user_vm_range, - self.vm_manager.clone(), - )) + + *self.free_size.lock().unwrap() -= size; + Ok(UserSpaceVMRange::new(vm_range)) } + fn add_free_size(&self, user_space_vmrange: &UserSpaceVMRange) { + *self.free_size.lock().unwrap() += user_space_vmrange.range().size(); + } + + // The empty range is not added to sub_range pub fn alloc_dummy(&self) -> UserSpaceVMRange { let empty_user_vm_range = unsafe { VMRange::from_unchecked(0, 0) }; - UserSpaceVMRange::new(empty_user_vm_range, self.vm_manager.clone()) + UserSpaceVMRange::new(empty_user_vm_range) + } + + pub fn get_total_size(&self) -> usize { + self.total_size + } + + pub fn get_free_size(&self) -> usize { + *self.free_size.lock().unwrap() } } lazy_static! { - pub static ref USER_SPACE_VM_MANAGER: UserSpaceVMManager = { - let (addr, size) = { - let mut addr: usize = 0; - let mut size: usize = 0; - unsafe { vm_get_preallocated_user_space_memory(&mut addr, &mut size) }; - (addr, size) - }; - let user_space_vm_manager = unsafe { - match UserSpaceVMManager::from(addr, size) { - Ok(user_space_vm) => user_space_vm, - Err(_) => panic!("Failed to initialize the user space virtual memory"), - } - }; - user_space_vm_manager - }; + pub static ref USER_SPACE_VM_MANAGER: UserSpaceVMManager = UserSpaceVMManager::new(); +} + +bitflags! { + struct MemPerm: i32 { + const READ = 1; + const WRITE = 2; + const EXEC = 4; + } } extern "C" { - pub fn vm_get_preallocated_user_space_memory(addr: &mut usize, size: &mut usize); + // Allocate a range of EPC memory from the reserved memory area with RW permission + // + // Parameters: + // Inputs: length [in]: Size of region to be allocated in bytes. Page aligned + // Return: Starting address of the new allocated memory area on success; otherwise NULL + // + fn sgx_alloc_rsrv_mem(length: usize) -> *const c_void; + + // Free a range of EPC memory from the reserved memory area + // + // Parameters: + // Inputs: addr[in]: Starting address of region to be freed. Page aligned. + // length[in]: The length of the memory to be freed in bytes. Page aligned + // Return: 0 on success; otherwise -1 + // + fn sgx_free_rsrv_mem(addr: *const c_void, length: usize) -> i32; + + // Modify the access permissions of the pages in the reserved memory area + // + // Parameters: + // Inputs: addr[in]: Starting address of region which needs to change access + // permission. Page aligned. + // length[in]: The length of the memory to be manipulated in bytes. Page aligned. + // prot[in]: The target memory protection. + // Return: sgx_status_t + // + fn sgx_tprotect_rsrv_mem(addr: *const c_void, length: usize, prot: i32) -> sgx_status_t; } #[derive(Debug)] pub struct UserSpaceVMRange { vm_range: VMRange, - vm_manager: Arc>, } impl UserSpaceVMRange { - fn new(vm_range: VMRange, vm_manager: Arc>) -> UserSpaceVMRange { - UserSpaceVMRange { - vm_range, - vm_manager, - } + fn new(vm_range: VMRange) -> UserSpaceVMRange { + UserSpaceVMRange { vm_range } } pub fn range(&self) -> &VMRange { @@ -75,14 +113,14 @@ impl UserSpaceVMRange { impl Drop for UserSpaceVMRange { fn drop(&mut self) { - let addr = self.vm_range.start(); + let addr = self.vm_range.start() as *const c_void; let size = self.vm_range.size(); if size == 0 { return; } - let mut vm_manager = self.vm_manager.lock().unwrap(); - vm_manager - .munmap(addr, size) - .expect("munmap should always succeed"); + + USER_SPACE_VM_MANAGER.add_free_size(self); + + assert!(unsafe { sgx_free_rsrv_mem(addr, size) == 0 }); } } diff --git a/tools/gen_enclave_conf/src/main.rs b/tools/gen_enclave_conf/src/main.rs index 467c8a8b..ac8a1637 100644 --- a/tools/gen_enclave_conf/src/main.rs +++ b/tools/gen_enclave_conf/src/main.rs @@ -84,6 +84,16 @@ fn main() { return; } + // get the user space size + let user_space_size = parse_memory_size(&occlum_config.resource_limits.user_space_size); + if user_space_size.is_err() { + println!( + "The user_space_size \"{}\" is not correct.", + occlum_config.resource_limits.user_space_size + ); + return; + } + let sgx_enclave_configuration = EnclaveConfiguration { ProdID: occlum_config.metadata.product_id, ISVSVN: occlum_config.metadata.version_number, @@ -97,6 +107,10 @@ fn main() { }, MiscSelect: "0".to_string(), MiscMask: "0xFFFFFFFF".to_string(), + ReservedMemMaxSize: user_space_size.unwrap() as u64, + ReservedMemMinSize: user_space_size.unwrap() as u64, + ReservedMemInitSize: user_space_size.unwrap() as u64, + ReservedMemExecutable: 1, }; // Generate the enclave configuration @@ -175,4 +189,8 @@ struct EnclaveConfiguration { DisableDebug: u32, MiscSelect: String, MiscMask: String, + ReservedMemMaxSize: u64, + ReservedMemMinSize: u64, + ReservedMemInitSize: u64, + ReservedMemExecutable: u32, }