blob: 7248637ae042d8cb9d7a084ae94c860fd3014dc7 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License..
pub use self::platform::*;
use core::fmt;
use core::ptr::NonNull;
pub struct RsrvMemAlloc;
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum ProtectAttr {
Read,
ReadWrite,
ReadExec,
ReadWriteExec,
}
impl RsrvMemAlloc {
/// Allocate a range of EPC memory from the reserved memory area
///
/// # Parameters
///
/// **count**
///
/// Count of pages to allocate region
///
/// # Return value
///
/// Starting address of the new allocated memory area on success;
///
#[inline]
pub unsafe fn alloc(&mut self, count: u32) -> Result<NonNull<u8>, RsrvMemAllocErr> {
NonNull::new(platform::alloc(count)).ok_or(RsrvMemAllocErr)
}
/// Allocate a range of EPC memory with a fixed address from the reserved memory area
///
/// # Parameters
///
/// **addr**
///
/// The desired starting address to allocate the reserved memory. Should be page aligned.
///
/// **count**
///
/// Count of pages to allocate region
///
/// # Return value
///
/// Starting address of the new allocated memory area on success;
///
#[inline]
pub unsafe fn alloc_with_addr(&mut self, addr: NonNull<u8>, count: u32) -> Result<NonNull<u8>, RsrvMemAllocErr> {
NonNull::new(platform::alloc_with_addr(addr.as_ptr(), count)).ok_or(RsrvMemAllocErr)
}
#[inline]
pub unsafe fn alloc_zeroed(&mut self, count: u32) -> Result<NonNull<u8>, RsrvMemAllocErr> {
NonNull::new(platform::alloc_zeroed(count)).ok_or(RsrvMemAllocErr)
}
/// Free a range of EPC memory from the reserved memory area
///
/// # Parameters
///
/// ** ptr**
///
/// Starting address of region to be freed. Page aligned.
///
/// **count**
///
/// Count of pages to allocate region
///
#[inline]
pub unsafe fn dealloc(&mut self, addr: NonNull<u8>, count: u32) -> Result<(), RsrvMemAllocErr> {
platform::dealloc(addr.as_ptr(), count)
}
/// Modify the access permissions of the pages in the reserved memory area.
///
/// # Parameters
///
/// # Parameters
///
/// ** ptr**
///
/// Starting address of region to be freed. Page aligned.
///
/// **count**
///
/// Count of pages to allocate region
///
/// **port**
///
/// The target memory protection.
///
#[inline]
pub unsafe fn protect(
&self,
addr: NonNull<u8>,
count: u32,
prot: ProtectAttr,
) -> Result<(), RsrvMemAllocErr> {
platform::protect(addr.as_ptr(), count, prot)
}
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct RsrvMemAllocErr;
impl fmt::Display for RsrvMemAllocErr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("reserves memory allocation failed")
}
}
mod platform {
use super::ProtectAttr;
use super::RsrvMemAllocErr;
use core::ffi::c_void;
use core::ptr;
const SGX_PROT_READ: u32 = 0x1;
const SGX_PROT_WRITE: u32 = 0x2;
const SGX_PROT_EXEC: u32 = 0x4;
const SE_PAGE_SIZE: usize = 0x1000;
type size_t = usize;
type int32_t = i32;
type sgx_status_t = u32;
extern "C" {
pub fn sgx_alloc_rsrv_mem(length: size_t) -> *mut c_void;
pub fn sgx_alloc_rsrv_mem_ex(desired_addr: *const c_void, length: size_t) -> *mut c_void;
pub fn sgx_free_rsrv_mem(addr: *const c_void, length: size_t) -> int32_t;
pub fn sgx_tprotect_rsrv_mem(
addr: *const c_void,
length: size_t,
prot: i32,
) -> sgx_status_t;
}
#[inline]
pub unsafe fn alloc(count: u32) -> *mut u8 {
sgx_alloc_rsrv_mem(count as usize * SE_PAGE_SIZE) as *mut u8
}
#[inline]
pub unsafe fn alloc_with_addr(addr: *mut u8, count: u32) -> *mut u8 {
sgx_alloc_rsrv_mem_ex(addr as *const c_void, count as usize * SE_PAGE_SIZE) as *mut u8
}
#[inline]
pub unsafe fn alloc_zeroed(count: u32) -> *mut u8 {
let raw = alloc(count);
if !raw.is_null() {
ptr::write_bytes(raw, 0, count as usize * SE_PAGE_SIZE);
}
raw
}
#[inline]
pub unsafe fn dealloc(addr: *mut u8, count: u32) -> Result<(), RsrvMemAllocErr> {
if sgx_free_rsrv_mem(addr as *const c_void, count as usize * SE_PAGE_SIZE) == 0 {
Ok(())
} else {
Err(RsrvMemAllocErr)
}
}
#[inline]
pub unsafe fn protect(
addr: *mut u8,
count: u32,
prot: ProtectAttr,
) -> Result<(), RsrvMemAllocErr> {
let attr = match prot {
ProtectAttr::Read => SGX_PROT_READ,
ProtectAttr::ReadWrite => SGX_PROT_READ | SGX_PROT_WRITE,
ProtectAttr::ReadExec => SGX_PROT_READ | SGX_PROT_EXEC,
ProtectAttr::ReadWriteExec => SGX_PROT_READ | SGX_PROT_WRITE | SGX_PROT_EXEC,
};
if sgx_tprotect_rsrv_mem(
addr as *const c_void,
count as usize * SE_PAGE_SIZE,
attr as i32,
) == 0
{
Ok(())
} else {
Err(RsrvMemAllocErr)
}
}
}