-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
310 additions
and
5 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pub struct CompartmentMgr {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
use std::sync::OnceLock; | ||
|
||
use happylock::RwLock; | ||
|
||
use self::space::Unmapper; | ||
|
||
mod compartment; | ||
mod space; | ||
mod thread; | ||
|
||
pub struct Monitor { | ||
space: RwLock<space::Space>, | ||
thread_mgr: RwLock<thread::ThreadMgr>, | ||
compartments: RwLock<compartment::CompartmentMgr>, | ||
dynlink: RwLock<dynlink::context::Context>, | ||
unmapper: Unmapper, | ||
} | ||
|
||
static MONITOR: OnceLock<Monitor> = OnceLock::new(); | ||
|
||
pub fn get_monitor() -> &'static Monitor { | ||
MONITOR.get().unwrap() | ||
} | ||
|
||
pub fn set_monitor(monitor: Monitor) { | ||
if MONITOR.set(monitor).is_err() { | ||
panic!("second call to set_monitor"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
use std::{collections::HashMap, sync::Arc}; | ||
|
||
use monitor_api::MappedObjectAddrs; | ||
use twizzler_abi::syscall::{sys_object_map, sys_object_unmap, UnmapFlags}; | ||
use twizzler_object::Protections; | ||
use twizzler_runtime_api::{MapError, MapFlags, ObjID}; | ||
|
||
use self::handle::{MapHandle, MapHandleInner}; | ||
|
||
mod handle; | ||
mod unmapper; | ||
|
||
pub use unmapper::Unmapper; | ||
|
||
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)] | ||
pub struct MapInfo { | ||
pub(crate) id: ObjID, | ||
pub(crate) flags: MapFlags, | ||
} | ||
|
||
#[derive(Default)] | ||
pub struct Space { | ||
maps: HashMap<MapInfo, MappedObject>, | ||
} | ||
|
||
struct MappedObject { | ||
addrs: MappedObjectAddrs, | ||
handle_count: usize, | ||
} | ||
|
||
fn mapflags_into_prot(flags: MapFlags) -> Protections { | ||
let mut prot = Protections::empty(); | ||
if flags.contains(MapFlags::READ) { | ||
prot.insert(Protections::READ); | ||
} | ||
if flags.contains(MapFlags::WRITE) { | ||
prot.insert(Protections::WRITE); | ||
} | ||
if flags.contains(MapFlags::EXEC) { | ||
prot.insert(Protections::EXEC); | ||
} | ||
prot | ||
} | ||
|
||
impl Space { | ||
pub fn map(&mut self, info: MapInfo) -> Result<MapHandle, MapError> { | ||
// Can't use the entry API here because the closure may fail. | ||
let item = match self.maps.get_mut(&info) { | ||
Some(item) => item, | ||
None => { | ||
// Not yet mapped, so allocate a slot and map it. | ||
let slot = twz_rt::OUR_RUNTIME | ||
.allocate_slot() | ||
.ok_or(MapError::OutOfResources)?; | ||
|
||
let Ok(_) = sys_object_map( | ||
None, | ||
info.id, | ||
slot, | ||
mapflags_into_prot(info.flags), | ||
twizzler_abi::syscall::MapFlags::empty(), | ||
) else { | ||
twz_rt::OUR_RUNTIME.release_slot(slot); | ||
return Err(MapError::InternalError); | ||
}; | ||
|
||
let map = MappedObject { | ||
addrs: MappedObjectAddrs::new(slot), | ||
handle_count: 0, | ||
}; | ||
self.maps.insert(info, map); | ||
// Unwrap-Ok: just inserted. | ||
self.maps.get_mut(&info).unwrap() | ||
} | ||
}; | ||
|
||
// New maps will be set to zero, so this is unconditional. | ||
item.handle_count += 1; | ||
Ok(Arc::new(MapHandleInner::new(info, item.addrs))) | ||
} | ||
|
||
pub fn handle_drop(&mut self, info: MapInfo) -> Option<UnmapOnDrop> { | ||
// Missing maps in unmap should be ignored. | ||
let Some(item) = self.maps.get_mut(&info) else { | ||
tracing::warn!("unmap called for missing object {:?}", info); | ||
return None; | ||
}; | ||
if item.handle_count == 0 { | ||
tracing::error!("unmap called for unmapped object {:?}", info); | ||
return None; | ||
} | ||
|
||
// Decrement and maybe actually unmap. | ||
item.handle_count -= 1; | ||
if item.handle_count == 0 { | ||
let slot = item.addrs.slot; | ||
self.maps.remove(&info); | ||
Some(UnmapOnDrop { slot }) | ||
} else { | ||
None | ||
} | ||
} | ||
} | ||
|
||
// Allows us to call handle_drop and do all the hard work in the caller, since | ||
// the caller probably had to hold a lock to call these functions. | ||
pub(crate) struct UnmapOnDrop { | ||
slot: usize, | ||
} | ||
|
||
impl Drop for UnmapOnDrop { | ||
fn drop(&mut self) { | ||
if sys_object_unmap(None, self.slot, UnmapFlags::empty()).is_ok() { | ||
twz_rt::OUR_RUNTIME.release_slot(self.slot); | ||
} else { | ||
tracing::warn!("failed to unmap slot {}", self.slot); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
use std::sync::Arc; | ||
|
||
use monitor_api::MappedObjectAddrs; | ||
use twizzler_abi::object::NULLPAGE_SIZE; | ||
|
||
use super::MapInfo; | ||
use crate::mon::get_monitor; | ||
|
||
pub struct MapHandleInner { | ||
info: MapInfo, | ||
map: MappedObjectAddrs, | ||
} | ||
|
||
pub type MapHandle = Arc<MapHandleInner>; | ||
|
||
impl MapHandleInner { | ||
pub(crate) fn new(info: MapInfo, map: MappedObjectAddrs) -> Self { | ||
Self { info, map } | ||
} | ||
|
||
pub fn addrs(&self) -> MappedObjectAddrs { | ||
self.map | ||
} | ||
|
||
pub fn monitor_data_null(&self) -> *mut u8 { | ||
self.map.start as *mut u8 | ||
} | ||
|
||
pub fn monitor_data_base(&self) -> *mut u8 { | ||
(self.map.start + NULLPAGE_SIZE) as *mut u8 | ||
} | ||
} | ||
|
||
impl Drop for MapHandleInner { | ||
fn drop(&mut self) { | ||
// Toss this work onto a background thread. | ||
let monitor = get_monitor(); | ||
monitor.unmapper.background_unmap_info(self.info); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
use std::{panic::catch_unwind, sync::mpsc::Sender, thread::JoinHandle}; | ||
|
||
use super::MapInfo; | ||
use crate::mon::get_monitor; | ||
|
||
pub struct Unmapper { | ||
sender: Sender<MapInfo>, | ||
thread: JoinHandle<()>, | ||
} | ||
|
||
impl Unmapper { | ||
pub fn new(cb: fn(MapInfo)) -> Self { | ||
let (sender, receiver) = std::sync::mpsc::channel(); | ||
Self { | ||
thread: std::thread::spawn(move || loop { | ||
let key = happylock::ThreadKey::get().unwrap(); | ||
match receiver.recv() { | ||
Ok(info) => { | ||
if let Err(_) = catch_unwind(|| { | ||
let monitor = get_monitor(); | ||
let mut space = monitor.space.write(key); | ||
space.handle_drop(info); | ||
}) { | ||
tracing::error!("clean_call panicked -- exiting map cleaner thread"); | ||
break; | ||
} | ||
} | ||
Err(_) => { | ||
// If receive fails, we can't recover, but this probably doesn't happen | ||
// since the sender won't get dropped since this | ||
// struct is used in the MapMan static. | ||
break; | ||
} | ||
} | ||
}), | ||
sender, | ||
} | ||
} | ||
|
||
pub(super) fn background_unmap_info(&self, info: MapInfo) { | ||
// If the receiver is down, this will fail, but that also shouldn't happen, unless the | ||
// call to clean_call above panics. In any case, handle this gracefully. | ||
if self.sender.send(info).is_err() { | ||
tracing::warn!("failed to enqueue {:?} onto cleaner thread", info); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pub struct ThreadMgr {} |