Implement unmapping multiple whole maps

This commit is contained in:
jD91mZM2
2020-07-28 11:34:50 +02:00
parent 639e603c4f
commit 9eb2aebd43
5 changed files with 64 additions and 32 deletions

View File

@@ -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())

View File

@@ -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))
}

View File

@@ -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,

View File

@@ -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);

View File

@@ -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)