Skip to content

Commit

Permalink
Add function to create an instance at a given address
Browse files Browse the repository at this point in the history
- `assume_safe`: Parse an instance from a given address.
- `assume_safe_with`: Initialize an instance at a given address.

Signed-off-by: Sangwan Kwon <sangwan.kwon@samsung.com>
  • Loading branch information
bitboom committed Sep 25, 2024
1 parent cfdc214 commit 18d0b88
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 8 deletions.
61 changes: 59 additions & 2 deletions lib/safe-abstraction/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,10 +218,32 @@ pub mod raw_ptr {

Ok(SafetyAssumed {
addr,
assume_init: false,
_phantom: core::marker::PhantomData,
})
}

pub fn assume_safe_uninit_with<T: SafetyChecked + SafetyAssured>(
addr: usize,
value: T,
) -> Result<SafetyAssumed<T>, Error> {
let ptr = addr as *const T;
// Safety: This cast from a raw pointer to a reference is considered safe
// because it is used solely for the purpose of verifying alignment and range,
// without actually dereferencing the pointer.
let ref_ = unsafe { &*(ptr) };

if !ref_.is_not_null() || !ref_.is_aligned() {
return Err(Error::SafetyCheckFailed);
}

if !ref_.verify_ownership() {
return Err(Error::AssuranceCheckFailed);
}

Ok(SafetyAssumed::new_maybe_uninit_with(addr, value))
}

/// Represents a target instance that has passed all necessary safety checks.
///
/// An instance of `SafetyAssumed` signifies that it is safe to interact with the target
Expand All @@ -239,9 +261,30 @@ pub mod raw_ptr {
/// and ensure that the Rust compiler accounts for `T` in its type checking.
pub struct SafetyAssumed<T: SafetyChecked + SafetyAssured> {
addr: usize,
assume_init: bool,
_phantom: core::marker::PhantomData<T>,
}

impl<T> SafetyAssumed<T>
where
T: SafetyChecked + SafetyAssured,
{
pub fn new_maybe_uninit_with(addr: usize, value: T) -> Self {
unsafe {
let src: core::mem::MaybeUninit<T> = core::mem::MaybeUninit::new(value);
let src = &src as *const core::mem::MaybeUninit<T>;
let dst = addr as *mut core::mem::MaybeUninit<T>;
core::ptr::copy_nonoverlapping(src, dst, 1);
}

Self {
addr,
assume_init: true,
_phantom: core::marker::PhantomData,
}
}
}

impl<T> AsRef<T> for SafetyAssumed<T>
where
T: SafetyChecked + SafetyAssured,
Expand All @@ -253,7 +296,14 @@ pub mod raw_ptr {
/// are in place. Mutable access is granted under the presumption of exclusive ownership
/// and proper synchronization when accessed in multi-threaded contexts.
fn as_ref(&self) -> &T {
unsafe { T::as_ref(self.addr) }
unsafe {
if self.assume_init {
let ptr = self.addr as *mut core::mem::MaybeUninit<T>;
(*ptr).assume_init_ref()
} else {
T::as_ref(self.addr)
}
}
}
}

Expand All @@ -268,7 +318,14 @@ pub mod raw_ptr {
/// are in place. Mutable access is granted under the presumption of exclusive ownership
/// and proper synchronization when accessed in multi-threaded contexts.
fn as_mut(&mut self) -> &mut T {
unsafe { T::as_mut(self.addr) }
unsafe {
if self.assume_init {
let ptr = self.addr as *mut core::mem::MaybeUninit<T>;
(*ptr).assume_init_mut()
} else {
T::as_mut(self.addr)
}
}
}
}

Expand Down
7 changes: 7 additions & 0 deletions lib/vmsa/src/guard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ impl<'a, E> EntryGuard<'a, E> {
{
raw_ptr::assume_safe::<T>(self.addr).or(Err(Error::MmErrorOthers))
}

pub fn new_uninit_with<T>(&mut self, value: T) -> Result<raw_ptr::SafetyAssumed<T>, Error>
where
T: Content + raw_ptr::SafetyChecked + raw_ptr::SafetyAssured,
{
raw_ptr::assume_safe_uninit_with::<T>(self.addr, value).or(Err(Error::MmErrorOthers))
}
}

impl<'a, E> Deref for EntryGuard<'a, E> {
Expand Down
8 changes: 8 additions & 0 deletions rmm/src/granule/array/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,14 @@ impl Granule {
Ok(raw_ptr::assume_safe::<T>(addr)?)
}

pub fn new_uninit_with<T>(&mut self, value: T) -> Result<raw_ptr::SafetyAssumed<T>, Error>
where
T: Content + raw_ptr::SafetyChecked + raw_ptr::SafetyAssured,
{
let addr = self.index_to_addr();
Ok(raw_ptr::assume_safe_uninit_with::<T>(addr, value)?)
}

pub fn content<T>(&self) -> Result<raw_ptr::SafetyAssumed<T>, Error>
where
T: Content + raw_ptr::SafetyChecked + raw_ptr::SafetyAssured,
Expand Down
27 changes: 23 additions & 4 deletions rmm/src/rec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,29 @@ pub struct Rec<'a> {
}

impl Rec<'_> {
pub fn new() -> Self {
Self {
context: Context::new(),
attest_state: RmmRecAttestState::NoAttestInProgress,
attest_challenge: [0; MAX_CHALLENGE_SIZE],
attest_token_offset: 0,
owner: OnceCell::new(),
vcpuid: 0,
runnable: false,
psci_pending: false,
state: State::Ready,
ripas: Ripas {
start: 0,
end: 0,
addr: 0,
state: 0,
flags: 0,
},
vtcr: 0,
host_call_pending: false,
}
}

pub fn init(
&mut self,
owner: usize,
Expand All @@ -80,13 +103,9 @@ impl Rec<'_> {
}

self.vcpuid = vcpuid;
self.set_ripas(0, 0, 0, 0);
self.set_runnable(flags);
self.set_state(State::Ready);
self.context = Context::new();
self.context.sys_regs.vttbr = vttbr;
self.context.sys_regs.vmpidr = vmpidr;
self.attest_state = RmmRecAttestState::NoAttestInProgress;
timer::init_timer(self);
gic::init_gic(self);

Expand Down
3 changes: 1 addition & 2 deletions rmm/src/rmi/rec/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,7 @@ pub fn set_event_handler(mainloop: &mut Mainloop) {
#[cfg(not(kani))]
// `page_table` is currently not reachable in model checking harnesses
rmm.page_table.map(rec, true);
let mut rec = rec_granule.content_mut::<Rec<'_>>()?;

let mut rec = rec_granule.new_uninit_with::<Rec<'_>>(Rec::new())?;
match prepare_args(&mut rd, params.mpidr) {
Ok((vcpuid, vttbr, vmpidr)) => {
ret[1] = vcpuid;
Expand Down

0 comments on commit 18d0b88

Please sign in to comment.