Skip to content

Commit

Permalink
Implement Once<T> and replace existed Once
Browse files Browse the repository at this point in the history
  • Loading branch information
ClawSeven committed Dec 1, 2023
1 parent 47b3996 commit 5ba38bd
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 70 deletions.
8 changes: 4 additions & 4 deletions sgx_trts/src/emm/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ use intrusive_collections::singly_linked_list::{Link, SinglyLinkedList};
use intrusive_collections::UnsafeRef;
use sgx_tlibc_sys::ENOMEM;

use crate::sync::Once;
use crate::sync::SpinMutex as Mutex;
use core::alloc::{AllocError, Allocator, Layout};
use core::any::Any;
use core::mem::size_of;
use core::mem::MaybeUninit;
use core::ptr::NonNull;
use spin::Once;

use super::ema::EmaOptions;
use super::page::AllocFlags;
Expand Down Expand Up @@ -64,21 +64,21 @@ static RSRV_ALLOCATOR: Once<Mutex<Reserve>> = Once::new();

/// Init lowest level static memory allocator
pub fn init_static_alloc() {
STATIC.call_once(|| {
let _ = STATIC.call_once(|| {
let static_alloc = LockedHeap::empty();
unsafe {
static_alloc
.lock()
.init(STATIC_MEM.as_ptr() as usize, STATIC_MEM_SIZE)
};
static_alloc
Ok(static_alloc)
});
}

/// Init reserve memory allocator
/// init_reserve_alloc() need to be called after init_static_alloc()
pub fn init_reserve_alloc() {
RSRV_ALLOCATOR.call_once(|| Mutex::new(Reserve::new(INIT_MEM_SIZE)));
let _ = RSRV_ALLOCATOR.call_once(|| Ok(Mutex::new(Reserve::new(INIT_MEM_SIZE))));
}

pub trait EmmAllocator: Allocator + Any {
Expand Down
4 changes: 2 additions & 2 deletions sgx_trts/src/emm/vmmgr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
// specific language governing permissions and limitations
// under the License..

use crate::sync::Once;
use crate::{
arch::{SE_PAGE_SHIFT, SE_PAGE_SIZE},
emm::{PageType, ProtFlags},
Expand All @@ -28,7 +29,6 @@ use intrusive_collections::{
};
use sgx_tlibc_sys::{EEXIST, EINVAL, ENOMEM, EPERM};
use sgx_types::error::OsResult;
use spin::Once;

use super::{
alloc::AllocType,
Expand All @@ -51,7 +51,7 @@ pub(crate) static VMMGR: Once<SpinReentrantMutex<VmMgr>> = Once::new();

/// Initialize range management
pub fn init_vmmgr() {
VMMGR.call_once(|| SpinReentrantMutex::new(VmMgr::new()));
let _ = VMMGR.call_once(|| Ok(SpinReentrantMutex::new(VmMgr::new())));
}

pub fn mm_init_static_region(options: &EmaOptions) -> OsResult {
Expand Down
54 changes: 5 additions & 49 deletions sgx_trts/src/se/report.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,11 @@ use core::ptr;
use sgx_types::error::{SgxResult, SgxStatus};
use sgx_types::marker::ContiguousMemory;
use sgx_types::types::{
Attributes, AttributesFlags, ConfigId, CpuSvn, Key128bit, KeyId, KeyName, KeyRequest, Mac,
Measurement, MiscSelect, Report, Report2Mac, ReportBody, ReportData, TargetInfo,
Key128bit, KeyName, KeyRequest, Mac, Report, Report2Mac, ReportBody, ReportData, TargetInfo,
};
use sgx_types::types::{
CONFIGID_SIZE, CPUSVN_SIZE, HASH_SIZE, ISVEXT_PROD_ID_SIZE, ISV_FAMILY_ID_SIZE, KEYID_SIZE,
MAC_SIZE, REPORT2_MAC_RESERVED1_BYTES, REPORT2_MAC_RESERVED2_BYTES,
REPORT_BODY_RESERVED1_BYTES, REPORT_BODY_RESERVED2_BYTES, REPORT_BODY_RESERVED3_BYTES,
REPORT_BODY_RESERVED4_BYTES, REPORT_DATA_SIZE, TEE_REPORT2_SUBTYPE, TEE_REPORT2_TYPE,
TEE_REPORT2_VERSION, TEE_REPORT2_VERSION_SERVICETD,
REPORT2_MAC_RESERVED1_BYTES, REPORT2_MAC_RESERVED2_BYTES, TEE_REPORT2_SUBTYPE,
TEE_REPORT2_TYPE, TEE_REPORT2_VERSION, TEE_REPORT2_VERSION_SERVICETD,
};

#[repr(C, align(128))]
Expand All @@ -58,51 +54,11 @@ unsafe impl ContiguousMemory for AlignTargetInfo {}
unsafe impl ContiguousMemory for AlignReport {}
unsafe impl ContiguousMemory for AlignReport2Mac {}

static SELF_REPORT: Once = Once::new();
static mut REPORT: AlignReport = AlignReport(Report {
body: ReportBody {
cpu_svn: CpuSvn {
svn: [0; CPUSVN_SIZE],
},
misc_select: MiscSelect::empty(),
reserved1: [0; REPORT_BODY_RESERVED1_BYTES],
isv_ext_prod_id: [0; ISVEXT_PROD_ID_SIZE],
attributes: Attributes {
flags: AttributesFlags::empty(),
xfrm: 0,
},
mr_enclave: Measurement { m: [0; HASH_SIZE] },
reserved2: [0; REPORT_BODY_RESERVED2_BYTES],
mr_signer: Measurement { m: [0; HASH_SIZE] },
reserved3: [0; REPORT_BODY_RESERVED3_BYTES],
config_id: ConfigId {
id: [0; CONFIGID_SIZE],
},
isv_prod_id: 0,
isv_svn: 0,
config_svn: 0,
reserved4: [0; REPORT_BODY_RESERVED4_BYTES],
isv_family_id: [0; ISV_FAMILY_ID_SIZE],
report_data: ReportData {
d: [0; REPORT_DATA_SIZE],
},
},
key_id: KeyId {
id: [0_u8; KEYID_SIZE],
},
mac: [0_u8; MAC_SIZE],
});
static REPORT: Once<AlignReport> = Once::new();

impl AlignReport {
pub fn get_self() -> &'static AlignReport {
unsafe {
let _ = SELF_REPORT.call_once(|| {
let report = AlignReport::for_self()?;
REPORT = report;
Ok(())
});
&REPORT
}
REPORT.call_once(|| AlignReport::for_self()).unwrap()
}

pub fn for_self() -> SgxResult<AlignReport> {
Expand Down
78 changes: 63 additions & 15 deletions sgx_trts/src/sync/once.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,46 +16,94 @@
// under the License..

use crate::sync::{SpinMutex, SpinMutexGuard};
use core::sync::atomic::{AtomicUsize, Ordering};
use core::{
cell::UnsafeCell,
mem::MaybeUninit,
sync::atomic::{AtomicUsize, Ordering},
};
use sgx_types::error::SgxResult;

pub struct Once {
pub struct Once<T = ()> {
lock: SpinMutex<()>,
state: AtomicUsize,
data: UnsafeCell<MaybeUninit<T>>,
}

unsafe impl Sync for Once {}
unsafe impl Send for Once {}
impl<T> Default for Once<T> {
fn default() -> Self {
Self::new()
}
}

unsafe impl<T: Send + Sync> Sync for Once<T> {}
unsafe impl<T: Send> Send for Once<T> {}

const INCOMPLETE: usize = 0x0;
const COMPLETE: usize = 0x1;

impl Once {
pub const fn new() -> Once {
Once {
lock: SpinMutex::new(()),
state: AtomicUsize::new(INCOMPLETE),
}
impl<T> Once<T> {
/// Initialization constant of [`Once`].
#[allow(clippy::declare_interior_mutable_const)]
pub const INIT: Self = Self {
lock: SpinMutex::new(()),
state: AtomicUsize::new(INCOMPLETE),
data: UnsafeCell::new(MaybeUninit::uninit()),
};

/// Creates a new [`Once`].
pub const fn new() -> Self {
Self::INIT
}

pub fn lock(&self) -> SpinMutexGuard<()> {
self.lock.lock()
}

pub fn call_once<F>(&self, init: F) -> SgxResult
pub fn call_once<F>(&self, init: F) -> SgxResult<&T>
where
F: FnOnce() -> SgxResult,
F: FnOnce() -> SgxResult<T>,
{
if self.is_completed() {
return Ok(());
return Ok(unsafe {
// SAFETY: The status is Complete
self.force_get()
});
}

let _guard = self.lock.lock();
if !self.is_completed() {
init()?;
let val = init()?;
unsafe {
(*self.data.get()).as_mut_ptr().write(val);
}
self.state.store(COMPLETE, Ordering::Release);
}
Ok(())
unsafe { Ok(self.force_get()) }
}

/// Returns a reference to the inner value if the [`Once`] has been initialized.
pub fn get(&self) -> Option<&T> {
if self.state.load(Ordering::Acquire) == COMPLETE {
Some(unsafe { self.force_get() })
} else {
None
}
}

/// Get a reference to the initialized instance. Must only be called once COMPLETE.
unsafe fn force_get(&self) -> &T {
// SAFETY:
// * `UnsafeCell`/inner deref: data never changes again
// * `MaybeUninit`/outer deref: data was initialized
&*(*self.data.get()).as_ptr()
}

/// Get a reference to the initialized instance. Must only be called once COMPLETE.
unsafe fn force_get_mut(&mut self) -> &mut T {
// SAFETY:
// * `UnsafeCell`/inner deref: data never changes again
// * `MaybeUninit`/outer deref: data was initialized
&mut *(*self.data.get()).as_mut_ptr()
}

#[inline]
Expand Down

0 comments on commit 5ba38bd

Please sign in to comment.