diff --git a/src/context/memory.rs b/src/context/memory.rs index 67bb598..8a957e4 100644 --- a/src/context/memory.rs +++ b/src/context/memory.rs @@ -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 { + 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()) diff --git a/src/scheme/user.rs b/src/scheme/user.rs index a090779..8c3c5d8 100644 --- a/src/scheme/user.rs +++ b/src/scheme/user.rs @@ -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 { + fn funmap(&self, grant_address: usize) -> Result { 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 { + fn funmap2(&self, grant_address: usize, size: usize) -> Result { 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)) } diff --git a/src/syscall/debug.rs b/src/syscall/debug.rs index e883ca3..e18181e 100644 --- a/src/syscall/debug.rs +++ b/src/syscall/debug.rs @@ -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, diff --git a/src/syscall/fs.rs b/src/syscall/fs.rs index 3ae8e06..a4623de 100644 --- a/src/syscall/fs.rs +++ b/src/syscall/fs.rs @@ -507,6 +507,8 @@ pub fn funmap2(virtual_address: usize, length: usize) -> Result { let conflicting: Vec = 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); diff --git a/src/syscall/mod.rs b/src/syscall/mod.rs index a441567..b58f894 100644 --- a/src/syscall/mod.rs +++ b/src/syscall/mod.rs @@ -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 into -errno Error::mux(result)