mirror of
https://github.com/AmbiML/sparrow-kata-full.git
synced 2025-07-15 23:06:03 +00:00
kata-os-common: add CopyRegion support.
Move the CopyRegion support to kata-os-common. CopyRegion wraps a CAmkES copyregion virtual memory window to support virtual access to physical page frames. There is RAII cleanup to clear any virtual mapping. Embedding a CopyRegion in struct that may be cloned is not recommeded (at least for now). Change-Id: I7fd465fafa4a5d1de9a7e565ecb62c38a3b7e81a GitOrigin-RevId: f58e973b1c47ec05e48bfedcb9cd5e75b71c212a
This commit is contained in:
parent
f70a9af73f
commit
acf7c28eba
@ -5,8 +5,8 @@
|
|||||||
use core::mem::size_of;
|
use core::mem::size_of;
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
use crate::sel4bundle::arch;
|
use crate::sel4bundle::arch;
|
||||||
use crate::sel4bundle::CopyRegion;
|
|
||||||
use crate::sel4bundle::seL4BundleImpl;
|
use crate::sel4bundle::seL4BundleImpl;
|
||||||
|
use super::CopyRegion;
|
||||||
use super::sel4_sys;
|
use super::sel4_sys;
|
||||||
|
|
||||||
use arch::PAGE_SIZE;
|
use arch::PAGE_SIZE;
|
||||||
@ -64,8 +64,10 @@ impl seL4BundleImpl {
|
|||||||
// be on a page boundary.
|
// be on a page boundary.
|
||||||
let frame_obj = self.get_stack_frame_obj(sp - size_of::<seL4_Word>());
|
let frame_obj = self.get_stack_frame_obj(sp - size_of::<seL4_Word>());
|
||||||
|
|
||||||
let mut copy_region =
|
let mut copy_region = CopyRegion::new(
|
||||||
CopyRegion::new(unsafe { ptr::addr_of_mut!(LOAD_APPLICATION[0])});
|
unsafe { ptr::addr_of_mut!(LOAD_APPLICATION[0])},
|
||||||
|
PAGE_SIZE
|
||||||
|
);
|
||||||
copy_region.map(frame_obj.cptr)?;
|
copy_region.map(frame_obj.cptr)?;
|
||||||
|
|
||||||
// Write spillover arguments to the TCB's stack.
|
// Write spillover arguments to the TCB's stack.
|
||||||
|
@ -16,6 +16,7 @@ use kata_memory_interface::kata_object_free;
|
|||||||
use kata_memory_interface::kata_object_free_in_cnode;
|
use kata_memory_interface::kata_object_free_in_cnode;
|
||||||
use kata_memory_interface::ObjDesc;
|
use kata_memory_interface::ObjDesc;
|
||||||
use kata_memory_interface::ObjDescBundle;
|
use kata_memory_interface::ObjDescBundle;
|
||||||
|
use kata_os_common::copyregion::CopyRegion;
|
||||||
use kata_os_common::cspace_slot::CSpaceSlot;
|
use kata_os_common::cspace_slot::CSpaceSlot;
|
||||||
use kata_os_common::sel4_sys;
|
use kata_os_common::sel4_sys;
|
||||||
use kata_proc_interface::Bundle;
|
use kata_proc_interface::Bundle;
|
||||||
@ -36,9 +37,7 @@ use sel4_sys::seL4_DomainSet_Set;
|
|||||||
use sel4_sys::seL4_EndpointObject;
|
use sel4_sys::seL4_EndpointObject;
|
||||||
use sel4_sys::seL4_Error;
|
use sel4_sys::seL4_Error;
|
||||||
use sel4_sys::seL4_MinSchedContextBits;
|
use sel4_sys::seL4_MinSchedContextBits;
|
||||||
use sel4_sys::seL4_Page_Map;
|
|
||||||
use sel4_sys::seL4_PageTableObject;
|
use sel4_sys::seL4_PageTableObject;
|
||||||
use sel4_sys::seL4_Page_Unmap;
|
|
||||||
use sel4_sys::seL4_ReplyObject;
|
use sel4_sys::seL4_ReplyObject;
|
||||||
use sel4_sys::seL4_Result;
|
use sel4_sys::seL4_Result;
|
||||||
use sel4_sys::seL4_SchedContextObject;
|
use sel4_sys::seL4_SchedContextObject;
|
||||||
@ -64,8 +63,6 @@ extern "C" {
|
|||||||
// Our thread's TCB; used in setting up scheduling of new TCB's.
|
// Our thread's TCB; used in setting up scheduling of new TCB's.
|
||||||
static SELF_TCB_PROCESS_MANAGER_PROC_CTRL_0000: seL4_CPtr;
|
static SELF_TCB_PROCESS_MANAGER_PROC_CTRL_0000: seL4_CPtr;
|
||||||
|
|
||||||
static SELF_VSPACE_ROOT: seL4_CPtr;
|
|
||||||
|
|
||||||
// Region for mapping data when loading the contents of a BundleImage.
|
// Region for mapping data when loading the contents of a BundleImage.
|
||||||
static mut LOAD_APPLICATION: [seL4_Word; PAGE_SIZE / size_of::<seL4_Word>()];
|
static mut LOAD_APPLICATION: [seL4_Word; PAGE_SIZE / size_of::<seL4_Word>()];
|
||||||
}
|
}
|
||||||
@ -136,78 +133,6 @@ fn check_bundle(bundle: &ObjDescBundle) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(sleffler): move to kata-os-common
|
|
||||||
pub struct CopyRegion {
|
|
||||||
region: *mut seL4_Word,
|
|
||||||
cur_frame: Option<seL4_CPtr>,
|
|
||||||
}
|
|
||||||
impl CopyRegion {
|
|
||||||
pub fn new(region: *mut seL4_Word) -> Self {
|
|
||||||
CopyRegion {
|
|
||||||
region,
|
|
||||||
cur_frame: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Returns the region size in bytes.
|
|
||||||
pub fn size(&self) -> usize { PAGE_SIZE }
|
|
||||||
|
|
||||||
// Returns a mutable [u8] ref to the mapped region.
|
|
||||||
pub fn as_mut(&mut self) -> &mut [u8] {
|
|
||||||
assert!(self.cur_frame.is_some());
|
|
||||||
unsafe {
|
|
||||||
core::slice::from_raw_parts_mut(
|
|
||||||
self.region as _, PAGE_SIZE
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a mutable [seL4_Word] ref to the mapped region.
|
|
||||||
pub fn as_word_mut(&mut self) -> &mut [seL4_Word] {
|
|
||||||
assert!(self.cur_frame.is_some());
|
|
||||||
unsafe {
|
|
||||||
core::slice::from_raw_parts_mut(
|
|
||||||
self.region, PAGE_SIZE / size_of::<seL4_Word>(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Maps the |frame| in the SELF_VSPACE_ROOT for r/w.
|
|
||||||
pub fn map(&mut self, frame: seL4_CPtr) -> seL4_Result {
|
|
||||||
let attribs = seL4_Default_VMAttributes;
|
|
||||||
unsafe {
|
|
||||||
seL4_Page_Map(
|
|
||||||
frame,
|
|
||||||
SELF_VSPACE_ROOT,
|
|
||||||
self.region as usize,
|
|
||||||
// seL4_ReadWrite
|
|
||||||
seL4_CapRights::new(
|
|
||||||
/*grant_reply=*/ 0, /*grant=*/ 0, /*read=*/ 1, /*write=*/ 1,
|
|
||||||
),
|
|
||||||
attribs,
|
|
||||||
)
|
|
||||||
}?;
|
|
||||||
self.cur_frame = Some(frame);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmaps the current frame, if any.
|
|
||||||
pub fn unmap(&mut self) -> seL4_Result {
|
|
||||||
if let Some(cptr) = self.cur_frame {
|
|
||||||
#[cfg(target_arch = "arm")]
|
|
||||||
unsafe { seL4_ARM_Page_Unify_Instruction(cptr, 0, self.size()) }?;
|
|
||||||
|
|
||||||
unsafe { seL4_Page_Unmap(cptr) }?;
|
|
||||||
self.cur_frame = None;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Drop for CopyRegion {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
self.unmap().expect("CopyRegion");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const NOCAP: seL4_CPtr = 0;
|
const NOCAP: seL4_CPtr = 0;
|
||||||
|
|
||||||
// Layout of the CNode holding dynamic_objs. All entries are singletons
|
// Layout of the CNode holding dynamic_objs. All entries are singletons
|
||||||
@ -427,10 +352,10 @@ impl seL4BundleImpl {
|
|||||||
// to fill from the |bundle_frames| and/or zero-fill.
|
// to fill from the |bundle_frames| and/or zero-fill.
|
||||||
let mut image = BundleImage::new(bundle_frames);
|
let mut image = BundleImage::new(bundle_frames);
|
||||||
|
|
||||||
let mut copy_region =
|
let mut copy_region = CopyRegion::new(
|
||||||
CopyRegion::new(unsafe { ptr::addr_of_mut!(LOAD_APPLICATION[0])});
|
unsafe { ptr::addr_of_mut!(LOAD_APPLICATION[0])},
|
||||||
// Many places assume the copy region is PAGE_SIZE
|
PAGE_SIZE
|
||||||
assert_eq!(copy_region.size(), PAGE_SIZE);
|
);
|
||||||
|
|
||||||
let mut vaddr_top = 0;
|
let mut vaddr_top = 0;
|
||||||
while let Some(section) = image.next_section() {
|
while let Some(section) = image.next_section() {
|
||||||
|
@ -13,6 +13,7 @@ camkes_support = []
|
|||||||
allocator = { path = "src/allocator" }
|
allocator = { path = "src/allocator" }
|
||||||
camkes = { path = "src/camkes" }
|
camkes = { path = "src/camkes" }
|
||||||
capdl = { path = "src/capdl" }
|
capdl = { path = "src/capdl" }
|
||||||
|
copyregion = { path = "src/copyregion" }
|
||||||
cspace-slot = { path = "src/cspace-slot" }
|
cspace-slot = { path = "src/cspace-slot" }
|
||||||
logger = { path = "src/logger" }
|
logger = { path = "src/logger" }
|
||||||
model = { path = "src/model" }
|
model = { path = "src/model" }
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
cargo-features = ["edition2021"]
|
||||||
|
|
||||||
|
[package]
|
||||||
|
name = "copyregion"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Sam Leffler <sleffler@google.com>"]
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
log = "0.4"
|
||||||
|
sel4-sys = { path = "../sel4-sys" }
|
141
apps/system/components/kata-os-common/src/copyregion/src/lib.rs
Normal file
141
apps/system/components/kata-os-common/src/copyregion/src/lib.rs
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
//! RAII wrapper for using a KataOS copyregion object.
|
||||||
|
|
||||||
|
#![no_std]
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
|
||||||
|
use core::mem::size_of;
|
||||||
|
|
||||||
|
use sel4_sys::seL4_CapRights;
|
||||||
|
use sel4_sys::seL4_CPtr;
|
||||||
|
use sel4_sys::seL4_Default_VMAttributes;
|
||||||
|
use sel4_sys::seL4_Page_Map;
|
||||||
|
use sel4_sys::seL4_Page_Unmap;
|
||||||
|
use sel4_sys::seL4_Result;
|
||||||
|
use sel4_sys::seL4_Word;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
static SELF_VSPACE_ROOT: seL4_CPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sample usage:
|
||||||
|
// let mut copy_region = CopyRegion::new(unsafe { ptr::addr_of_mut!(LOAD_APPLICATION[0])}, PAGE_SIZE);
|
||||||
|
// copy_region.map(frame.cptr)?;
|
||||||
|
// copy_region.as_mut()[..].fill(0);
|
||||||
|
// let start = if index > 0 { 0 } else { vaddr - data_range.start };
|
||||||
|
// let end = cmp::min(data_range.end - vaddr, copy_region.size());
|
||||||
|
// image.read_exact(&mut copy_region.as_mut()[start..end])
|
||||||
|
// .map_err(|_| seL4_Error::seL4_NoError)?; // XXX
|
||||||
|
// copy_region.unmap()?;
|
||||||
|
|
||||||
|
// TODO(sleffler): do we need to parameterize VM_Attributes & CapRights?
|
||||||
|
// TODO(sleffler): Mutex-wrapped & maybe RefCell-wrapped versions?
|
||||||
|
|
||||||
|
// Fn from the criterion crate that convinces the optimizer
|
||||||
|
// a value is used in order to defeat premature optimization.
|
||||||
|
fn black_box<T>(dummy: T) -> T {
|
||||||
|
unsafe {
|
||||||
|
let ret = core::ptr::read_volatile(&dummy);
|
||||||
|
core::mem::forget(dummy);
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CopyRegion {
|
||||||
|
region: *mut seL4_Word,
|
||||||
|
size: usize,
|
||||||
|
cur_frame: Option<seL4_CPtr>,
|
||||||
|
}
|
||||||
|
impl CopyRegion {
|
||||||
|
pub fn new(region: *mut seL4_Word, size: usize) -> Self {
|
||||||
|
CopyRegion {
|
||||||
|
region,
|
||||||
|
size,
|
||||||
|
cur_frame: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the region size in bytes.
|
||||||
|
pub fn size(&self) -> usize { self.size }
|
||||||
|
|
||||||
|
// Returns the region size if mapped, otherwise 0.
|
||||||
|
pub fn mapped_bytes(&self) -> usize {
|
||||||
|
if self.cur_frame.is_some() { self.size } else { 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns an immutable [u8] ref to the mapped region.
|
||||||
|
pub fn as_ref(&mut self) -> &[u8] {
|
||||||
|
assert!(self.cur_frame.is_some());
|
||||||
|
unsafe {
|
||||||
|
core::slice::from_raw_parts(
|
||||||
|
self.region as _, self.size
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a mutable [u8] ref to the mapped region.
|
||||||
|
pub fn as_mut(&mut self) -> &mut [u8] {
|
||||||
|
assert!(self.cur_frame.is_some());
|
||||||
|
unsafe {
|
||||||
|
core::slice::from_raw_parts_mut(
|
||||||
|
self.region as _, self.size
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns an immutable [seL4_Word] ref to the mapped region.
|
||||||
|
pub fn as_word_ref(&mut self) -> &[seL4_Word] {
|
||||||
|
assert!(self.cur_frame.is_some());
|
||||||
|
unsafe {
|
||||||
|
core::slice::from_raw_parts(
|
||||||
|
self.region, self.size / size_of::<seL4_Word>(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a mutable [seL4_Word] ref to the mapped region.
|
||||||
|
pub fn as_word_mut(&mut self) -> &mut [seL4_Word] {
|
||||||
|
assert!(self.cur_frame.is_some());
|
||||||
|
unsafe {
|
||||||
|
core::slice::from_raw_parts_mut(
|
||||||
|
self.region, self.size / size_of::<seL4_Word>(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maps the |frame| in the SELF_VSPACE_ROOT for r/w.
|
||||||
|
// XXX need rights + attribs?
|
||||||
|
pub fn map(&mut self, frame: seL4_CPtr) -> seL4_Result {
|
||||||
|
black_box(frame); // NB: compiler WAR for frame clobber
|
||||||
|
unsafe {
|
||||||
|
seL4_Page_Map(
|
||||||
|
frame,
|
||||||
|
SELF_VSPACE_ROOT,
|
||||||
|
self.region as seL4_Word,
|
||||||
|
// seL4_ReadWrite
|
||||||
|
seL4_CapRights::new(
|
||||||
|
/*grant_reply=*/ 0, /*grant=*/ 0, /*read=*/ 1, /*write=*/ 1,
|
||||||
|
),
|
||||||
|
seL4_Default_VMAttributes,
|
||||||
|
)
|
||||||
|
}?;
|
||||||
|
self.cur_frame = Some(frame);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmaps the current frame, if any.
|
||||||
|
pub fn unmap(&mut self) -> seL4_Result {
|
||||||
|
if let Some(cptr) = self.cur_frame {
|
||||||
|
#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
|
||||||
|
unsafe { seL4_ARM_Page_Unify_Instruction(cptr, 0, self.size()) }?;
|
||||||
|
|
||||||
|
unsafe { seL4_Page_Unmap(cptr) }?;
|
||||||
|
self.cur_frame = None;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Drop for CopyRegion {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.unmap().expect("CopyRegion");
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,8 @@ pub extern crate allocator;
|
|||||||
pub extern crate camkes;
|
pub extern crate camkes;
|
||||||
pub extern crate capdl;
|
pub extern crate capdl;
|
||||||
#[cfg(feature = "camkes_support")]
|
#[cfg(feature = "camkes_support")]
|
||||||
|
pub extern crate copyregion;
|
||||||
|
#[cfg(feature = "camkes_support")]
|
||||||
pub extern crate cspace_slot;
|
pub extern crate cspace_slot;
|
||||||
pub extern crate logger;
|
pub extern crate logger;
|
||||||
pub extern crate model;
|
pub extern crate model;
|
||||||
|
Loading…
Reference in New Issue
Block a user