Skip to content

Commit

Permalink
rmm: Avoid double copy on RMI_DATA_CREATE
Browse files Browse the repository at this point in the history
To mitigate concurrency issues with memory regions shared
between the host and RMM, the host::copy_from operation was
used to copy data from the host.

However, for the RMI_DATA_CREATE case, this mitigation
let to double copy costs.

To address this, a new function host::copy_to_obj has been
added to perform the copy in a single step.

Signed-off-by: Sangwan Kwon <[email protected]>
  • Loading branch information
bitboom committed Jun 13, 2024
1 parent 7faa3c7 commit 38c5724
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 11 deletions.
25 changes: 24 additions & 1 deletion rmm/src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,30 @@ pub fn copy_from<T: SafetyChecked + SafetyAssured + Copy>(addr: usize) -> Option
}
}

pub fn copy_to<T: SafetyChecked + SafetyAssured + Copy>(src: &T, dst: usize) -> Option<()> {
pub fn copy_to_obj<T: SafetyChecked + SafetyAssured + Copy>(src: usize, dst: &mut T) -> Option<()> {
#[cfg(feature = "gst_page_table")]
if !validate_addr(src) || !is_not_in_realm(src) {
return None;
}
#[cfg(not(feature = "gst_page_table"))]
if !validate_addr(src) || get_granule_if!(src, GranuleState::Undelegated).is_err() {
return None;
}

PageTable::get_ref().map(src, false);
let ret = assume_safe::<T>(src).map(|safety_assumed| *dst = *safety_assumed);
PageTable::get_ref().unmap(src);

match ret {
Ok(_) => Some(()),
Err(err) => {
error!("Failed to convert a raw pointer to the struct. {:?}", err);
None
}
}
}

pub fn copy_to_ptr<T: SafetyChecked + SafetyAssured + Copy>(src: &T, dst: usize) -> Option<()> {
#[cfg(feature = "gst_page_table")]
if !validate_addr(dst) || !is_not_in_realm(dst) {
return None;
Expand Down
2 changes: 1 addition & 1 deletion rmm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub mod gic;
#[macro_use]
pub mod granule;
#[macro_use]
pub mod host;
pub(crate) mod host;
pub mod logger;
pub mod mm;
pub mod mmio;
Expand Down
4 changes: 2 additions & 2 deletions rmm/src/rmi/rec/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,8 @@ pub fn set_event_handler(mainloop: &mut Mainloop) {
crate::gic::send_state_to_host(&rec, &mut run)?;
crate::realm::timer::send_state_to_host(&rec, &mut run)?;

// NOTICE: do not modify `run` after copy_to_host_or_ret!(). it won't have any effect.
host::copy_to::<Run>(&run, run_pa).ok_or(Error::RmiErrorInput)
// NOTICE: do not modify `run` after copy_to_ptr(). it won't have any effect.
host::copy_to_ptr::<Run>(&run, run_pa).ok_or(Error::RmiErrorInput)
});

listen!(mainloop, rmi::PSCI_COMPLETE, |arg, _ret, _rmm| {
Expand Down
11 changes: 4 additions & 7 deletions rmm/src/rmi/rtt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,17 +206,14 @@ pub fn set_event_handler(mainloop: &mut Mainloop) {
// `page_table` is currently not reachable in model checking harnesses
rmm.page_table.map(target_pa, true);

// read src page
let src_page = host::copy_from::<DataPage>(src_pa).ok_or(Error::RmiErrorInput)?;
// copy src to target
host::copy_to_obj::<DataPage>(src_pa, &mut target_page).ok_or(Error::RmiErrorInput)?;

#[cfg(not(kani))]
// `rsi` is currently not reachable in model checking harnesses
HashContext::new(&mut rd)?.measure_data_granule(&src_page, ipa, flags)?;
HashContext::new(&mut rd)?.measure_data_granule(&target_page, ipa, flags)?;

// 3. copy src to _data
*target_page = src_page;

// 4. map ipa to taget_pa in S2 table
// map ipa to taget_pa in S2 table
crate::rtt::data_create(&rd, ipa, target_pa, false)?;

set_granule(&mut target_page_granule, GranuleState::Data)?;
Expand Down

0 comments on commit 38c5724

Please sign in to comment.