Implement unmapping multiple whole maps
This commit is contained in:
@@ -54,7 +54,7 @@ impl UserGrants {
|
||||
pub fn contains(&self, address: VirtualAddress) -> Option<&Grant> {
|
||||
let byte = Region::byte(address);
|
||||
self.inner
|
||||
.range(..byte)
|
||||
.range(..=byte)
|
||||
.next_back()
|
||||
.filter(|existing| existing.occupies(byte))
|
||||
}
|
||||
@@ -66,7 +66,7 @@ impl UserGrants {
|
||||
self
|
||||
.inner
|
||||
.range(start_region..)
|
||||
.take_while(move |region| region.occupies(requested))
|
||||
.take_while(move |region| !region.intersect(requested).is_empty())
|
||||
}
|
||||
/// Return a free region with the specified size
|
||||
pub fn find_free(&self, size: usize) -> Region {
|
||||
@@ -105,6 +105,7 @@ impl UserGrants {
|
||||
// TODO: Overwrite existing grant
|
||||
return Err(Error::new(EOPNOTSUPP));
|
||||
} else {
|
||||
// TODO: Find grant close to requested address?
|
||||
requested = self.find_free(requested.size());
|
||||
}
|
||||
}
|
||||
@@ -124,7 +125,7 @@ impl DerefMut for UserGrants {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Region {
|
||||
start: VirtualAddress,
|
||||
size: usize,
|
||||
@@ -137,19 +138,16 @@ impl Region {
|
||||
|
||||
/// Create a new region spanning exactly one byte
|
||||
pub fn byte(address: VirtualAddress) -> Self {
|
||||
Self {
|
||||
start: address,
|
||||
size: 1,
|
||||
}
|
||||
Self::new(address, 1)
|
||||
}
|
||||
|
||||
/// Create a new region spanning between the start and end address
|
||||
/// (exclusive end)
|
||||
pub fn between(start: VirtualAddress, end: VirtualAddress) -> Self {
|
||||
Self {
|
||||
Self::new(
|
||||
start,
|
||||
size: end.get() - start.get(),
|
||||
}
|
||||
end.get().saturating_sub(start.get()),
|
||||
)
|
||||
}
|
||||
|
||||
/// Return the part of the specified region that intersects with self.
|
||||
@@ -227,6 +225,24 @@ impl Region {
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Region {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.start.eq(&other.start)
|
||||
}
|
||||
}
|
||||
impl Eq for Region {}
|
||||
|
||||
impl PartialOrd for Region {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
self.start.partial_cmp(&other.start)
|
||||
}
|
||||
}
|
||||
impl Ord for Region {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.start.cmp(&other.start)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Region {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{:#x}..{:#x} ({:#x} long)", self.start_address().get(), self.end_address().get(), self.size())
|
||||
|
||||
@@ -218,8 +218,8 @@ impl UserInner {
|
||||
println!("scheme returned unaligned address, causing extra frame to be allocated");
|
||||
}
|
||||
let res = UserInner::capture_inner(&context_weak, map.address, address, map.size, map.flags, Some(desc));
|
||||
if let Ok(new_address) = res {
|
||||
self.funmap.lock().insert(new_address, address);
|
||||
if let Ok(grant_address) = res {
|
||||
self.funmap.lock().insert(grant_address, address);
|
||||
}
|
||||
packet.a = Error::mux(res);
|
||||
} else {
|
||||
@@ -439,27 +439,46 @@ impl Scheme for UserScheme {
|
||||
result
|
||||
}
|
||||
|
||||
fn funmap(&self, new_address: usize) -> Result<usize> {
|
||||
fn funmap(&self, grant_address: usize) -> Result<usize> {
|
||||
let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
|
||||
let address_opt = {
|
||||
let mut funmap = inner.funmap.lock();
|
||||
funmap.remove(&new_address)
|
||||
let entry = funmap.range(..=grant_address).next_back();
|
||||
|
||||
// TODO: Check region length!!
|
||||
if let Some((&grant_base, &user_base)) = entry {
|
||||
let user_address = grant_address - grant_base + user_base;
|
||||
funmap.remove(&grant_base);
|
||||
Some(user_address)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
if let Some(address) = address_opt {
|
||||
inner.call(SYS_FUNMAP, address, 0, 0)
|
||||
if let Some(user_address) = address_opt {
|
||||
inner.call(SYS_FUNMAP, user_address, 0, 0)
|
||||
} else {
|
||||
Err(Error::new(EINVAL))
|
||||
}
|
||||
}
|
||||
|
||||
fn funmap2(&self, address: usize, size: usize) -> Result<usize> {
|
||||
fn funmap2(&self, grant_address: usize, size: usize) -> Result<usize> {
|
||||
let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
|
||||
let address_opt = {
|
||||
let mut funmap = inner.funmap.lock();
|
||||
funmap.remove(&address)
|
||||
let entry = funmap.range(..=grant_address).next_back();
|
||||
|
||||
// TODO: Check region length!!
|
||||
if let Some((&grant_base, &user_base)) = entry {
|
||||
let user_address = grant_address - grant_base + user_base;
|
||||
funmap.remove(&grant_base);
|
||||
Some(user_address)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
};
|
||||
if let Some(address) = address_opt {
|
||||
inner.call(SYS_FUNMAP2, address, size, 0)
|
||||
if let Some(user_address) = address_opt {
|
||||
inner.call(SYS_FUNMAP2, user_address, size, 0)
|
||||
} else {
|
||||
Err(Error::new(EINVAL))
|
||||
}
|
||||
|
||||
@@ -126,6 +126,11 @@ pub fn format_call(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -
|
||||
"funmap({:#X})",
|
||||
b
|
||||
),
|
||||
SYS_FUNMAP2 => format!(
|
||||
"funmap2({:#X}, {:#X})",
|
||||
b,
|
||||
c,
|
||||
),
|
||||
SYS_FPATH => format!(
|
||||
"fpath({}, {:#X}, {})",
|
||||
b,
|
||||
|
||||
@@ -507,6 +507,8 @@ pub fn funmap2(virtual_address: usize, length: usize) -> Result<usize> {
|
||||
|
||||
let conflicting: Vec<Region> = grants.conflicts(requested).map(Region::from).collect();
|
||||
|
||||
println!("conflicts: {:#?}", conflicting);
|
||||
|
||||
for conflict in conflicting {
|
||||
let grant = grants.take(&conflict).expect("conflicting region didn't exist");
|
||||
let intersection = grant.intersect(requested);
|
||||
|
||||
@@ -164,21 +164,14 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, bp: u
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
let debug = {
|
||||
let contexts = crate::context::contexts();
|
||||
if let Some(context_lock) = contexts.current() {
|
||||
let context = context_lock.read();
|
||||
let name_raw = context.name.lock();
|
||||
let name = unsafe { core::str::from_utf8_unchecked(&name_raw) };
|
||||
if name == "file:/bin/cargo" || name == "file:/bin/rustc" {
|
||||
if a == SYS_CLOCK_GETTIME {
|
||||
false
|
||||
} else if (a == SYS_WRITE || a == SYS_FSYNC) && (b == 1 || b == 2) {
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
if name == "file:/bin/testing" || name == "file:/bin/rustc" {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
@@ -196,7 +189,6 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, bp: u
|
||||
|
||||
println!("{}", debug::format_call(a, b, c, d, e, f));
|
||||
}
|
||||
*/
|
||||
|
||||
// The next lines set the current syscall in the context struct, then once the inner() function
|
||||
// completes, we set the current syscall to none.
|
||||
@@ -221,7 +213,6 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, bp: u
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if debug {
|
||||
let contexts = crate::context::contexts();
|
||||
if let Some(context_lock) = contexts.current() {
|
||||
@@ -240,7 +231,6 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, bp: u
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// errormux turns Result<usize> into -errno
|
||||
Error::mux(result)
|
||||
|
||||
Reference in New Issue
Block a user