From 65890832382634ce76fb3fa445255605d67706e4 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sun, 17 Jul 2022 14:11:57 +0200 Subject: [PATCH] Partial: Migrate schemes to RMM. --- src/scheme/live.rs | 9 +++++---- src/scheme/memory.rs | 8 ++++---- src/scheme/mod.rs | 2 +- src/scheme/pipe.rs | 2 +- src/scheme/proc.rs | 41 +++++++++++++++++++++-------------------- src/scheme/user.rs | 23 +++++++++++++---------- 6 files changed, 45 insertions(+), 40 deletions(-) diff --git a/src/scheme/live.rs b/src/scheme/live.rs index 63877c8..acf14a0 100644 --- a/src/scheme/live.rs +++ b/src/scheme/live.rs @@ -13,7 +13,7 @@ use syscall::flag::{MODE_DIR, MODE_FILE}; use syscall::scheme::{calc_seek_offset_usize, Scheme}; use crate::memory::Frame; -use crate::paging::{ActivePageTable, Page, PageFlags, PhysicalAddress, TableKind, VirtualAddress}; +use crate::paging::{KernelMapper, Page, PageFlags, PhysicalAddress, VirtualAddress}; use crate::paging::mapper::PageFlushAll; static mut LIST: [u8; 2] = [b'0', b'\n']; @@ -55,15 +55,16 @@ impl DiskScheme { // Ensure live disk pages are mapped let virt = phys + crate::PHYS_OFFSET; unsafe { - let mut active_table = ActivePageTable::new(TableKind::Kernel); + let mut mapper = KernelMapper::lock(); + let mut flush_all = PageFlushAll::new(); let start_page = Page::containing_address(VirtualAddress::new(virt)); let end_page = Page::containing_address(VirtualAddress::new(virt + size - 1)); for page in Page::range_inclusive(start_page, end_page) { - if active_table.translate_page(page).is_none() { + if mapper.translate(page.start_address()).is_none() { let frame = Frame::containing_address(PhysicalAddress::new(page.start_address().data() - crate::PHYS_OFFSET)); let flags = PageFlags::new().write(true); - let result = active_table.map_to(page, frame, flags); + let result = mapper.get_mut().expect("expected KernelMapper not to be in use while initializing live scheme").map_phys(page.start_address(), frame.start_address(), flags).expect("failed to map live page"); flush_all.consume(result); } } diff --git a/src/scheme/memory.rs b/src/scheme/memory.rs index 44c7d16..8bcc8cf 100644 --- a/src/scheme/memory.rs +++ b/src/scheme/memory.rs @@ -1,10 +1,9 @@ use crate::context; use crate::context::memory::{page_flags, Grant}; use crate::memory::{free_frames, used_frames, PAGE_SIZE}; -use crate::paging::{ActivePageTable, mapper::PageFlushAll, Page, VirtualAddress}; -use crate::syscall::data::{Map, OldMap, StatVfs}; +use crate::paging::{mapper::PageFlushAll, Page, VirtualAddress}; +use crate::syscall::data::{Map, StatVfs}; use crate::syscall::error::*; -use crate::syscall::flag::MapFlags; use crate::syscall::scheme::Scheme; pub struct MemoryScheme; @@ -24,10 +23,11 @@ impl MemoryScheme { let context = context_lock.read(); let mut addr_space = context.addr_space()?.write(); + let addr_space = &mut *addr_space; let region = addr_space.grants.find_free_at(VirtualAddress::new(map.address), map.size, map.flags)?.round(); - addr_space.grants.insert(Grant::zeroed(Page::containing_address(region.start_address()), map.size / PAGE_SIZE, page_flags(map.flags), &mut *unsafe { ActivePageTable::new(rmm::TableKind::User) }, PageFlushAll::new())?); + addr_space.grants.insert(Grant::zeroed(Page::containing_address(region.start_address()), map.size / PAGE_SIZE, page_flags(map.flags), &mut addr_space.table.utable, PageFlushAll::new())?); Ok(region.start_address().data()) } diff --git a/src/scheme/mod.rs b/src/scheme/mod.rs index ac81fbb..fb3b7dc 100644 --- a/src/scheme/mod.rs +++ b/src/scheme/mod.rs @@ -16,7 +16,7 @@ use alloc::{ use core::sync::atomic::AtomicUsize; use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard}; -use crate::context::{Context, memory::AddrSpace, file::FileDescriptor}; +use crate::context::{memory::AddrSpace, file::FileDescriptor}; use crate::syscall::error::*; use crate::syscall::scheme::Scheme; diff --git a/src/scheme/pipe.rs b/src/scheme/pipe.rs index ab7cb16..4090e7e 100644 --- a/src/scheme/pipe.rs +++ b/src/scheme/pipe.rs @@ -1,7 +1,7 @@ use alloc::sync::{Arc, Weak}; use alloc::collections::{BTreeMap, VecDeque}; use core::sync::atomic::{AtomicUsize, Ordering}; -use spin::{Mutex, Once, RwLock, RwLockReadGuard, RwLockWriteGuard}; +use spin::{Mutex, Once, RwLock}; use crate::event; use crate::scheme::SchemeId; diff --git a/src/scheme/proc.rs b/src/scheme/proc.rs index 3fa2a93..628dd44 100644 --- a/src/scheme/proc.rs +++ b/src/scheme/proc.rs @@ -1,9 +1,9 @@ use crate::{ - arch::paging::{ActivePageTable, Flusher, InactivePageTable, mapper::{InactiveFlusher, Mapper, PageFlushAll}, Page, RmmA, VirtualAddress}, + arch::paging::{Flusher, mapper::{InactiveFlusher, PageFlushAll}, Page, RmmA, VirtualAddress}, context::{self, Context, ContextId, Status, file::{FileDescription, FileDescriptor}, memory::{AddrSpace, Grant, new_addrspace, map_flags, page_flags, Region}}, memory::PAGE_SIZE, ptrace, - scheme::{self, AtomicSchemeId, FileHandle, KernelScheme, SchemeId}, + scheme::{self, FileHandle, KernelScheme, SchemeId}, syscall::{ FloatRegisters, IntRegisters, @@ -13,7 +13,6 @@ use crate::{ flag::*, scheme::{calc_seek_offset_usize, Scheme}, self, - validate, }, }; @@ -279,7 +278,7 @@ impl ProcScheme { } fn current_addrspace() -> Result>> { - Ok(Arc::clone(context::contexts().current().ok_or(Error::new(ESRCH))?.read().addr_space()?)) + Ok(Arc::clone(context::current()?.read().addr_space()?)) } impl ProcScheme { @@ -451,7 +450,7 @@ impl Scheme for ProcScheme { // TODO: Better way to obtain new empty address spaces, perhaps using SYS_OPEN. But // in that case, what scheme? b"empty" => (Operation::AddrSpace { addrspace: new_addrspace()? }, false), - b"exclusive" => (Operation::AddrSpace { addrspace: addrspace.read().try_clone()? }, false), + b"exclusive" => (Operation::AddrSpace { addrspace: addrspace.write().try_clone()? }, false), b"mem" => (Operation::Memory { addrspace: Arc::clone(&addrspace) }, true), grant_handle if grant_handle.starts_with(b"grant-") => { @@ -747,16 +746,17 @@ impl Scheme for ProcScheme { } let mut addrspace = addrspace.write(); + let addrspace = &mut *addrspace; let is_active = addrspace.is_current(); let (mut inactive, mut active); - let (mut mapper, mut flusher) = if is_active { - active = (unsafe { ActivePageTable::new(rmm::TableKind::User) }, PageFlushAll::new()); - (active.0.mapper(), &mut active.1 as &mut dyn Flusher) + let mut flusher = if is_active { + active = PageFlushAll::new(); + &mut active as &mut dyn Flusher } else { - inactive = (unsafe { InactivePageTable::from_address(addrspace.frame.utable.start_address().data()) }, InactiveFlusher::new()); - (inactive.0.mapper(), &mut inactive.1 as &mut dyn Flusher) + inactive = InactiveFlusher::new(); + &mut inactive as &mut dyn Flusher }; let region = Region::new(VirtualAddress::new(base), size); @@ -772,7 +772,7 @@ impl Scheme for ProcScheme { addrspace.grants.insert(after); } - let res = current.unmap(&mut mapper, &mut flusher); + let res = current.unmap(&mut addrspace.table.utable, &mut flusher); if res.file_desc.is_some() { // We prefer avoiding file operations from within the kernel. If userspace @@ -788,7 +788,10 @@ impl Scheme for ProcScheme { // Forbid transferring grants to the same address space! if is_active { return Err(Error::new(EBUSY)); } - let src_grant = current_addrspace()?.write().grants.take(&Region::new(VirtualAddress::new(src_address), size)).ok_or(Error::new(EINVAL))?; + let current_addrspace = current_addrspace()?; + let mut current_addrspace = current_addrspace.write(); + let current_addrspace = &mut *current_addrspace; + let src_grant = current_addrspace.grants.take(&Region::new(VirtualAddress::new(src_address), size)).ok_or(Error::new(EINVAL))?; if src_address % PAGE_SIZE != 0 || src_address.saturating_add(size) > crate::USER_END_OFFSET { return Err(Error::new(EINVAL)); @@ -799,13 +802,13 @@ impl Scheme for ProcScheme { addrspace.grants.insert(Grant::transfer( src_grant, base_page, - &mut *unsafe { ActivePageTable::new(rmm::TableKind::User) }, - &mut mapper, + &mut current_addrspace.table.utable, + &mut addrspace.table.utable, PageFlushAll::new(), flusher, - )); + )?); } else if flags.intersects(MapFlags::PROT_READ | MapFlags::PROT_EXEC | MapFlags::PROT_WRITE) { - addrspace.grants.insert(Grant::zeroed(base_page, size / PAGE_SIZE, page_flags(flags), &mut mapper, flusher)?); + addrspace.grants.insert(Grant::zeroed(base_page, size / PAGE_SIZE, page_flags(flags), &mut addrspace.table.utable, flusher)?); } // TODO: Set some "in use" flag every time an address space is switched to? This @@ -1104,16 +1107,14 @@ impl Scheme for ProcScheme { let prev_addr_space = context.set_addr_space(new); - if let Some(prev) = prev_addr_space.and_then(|a| Arc::try_unwrap(a).ok()).map(RwLock::into_inner) { + if let Some(mut prev) = prev_addr_space.and_then(|a| Arc::try_unwrap(a).ok()).map(RwLock::into_inner) { // We are the last reference to the address space; therefore it must be // unmapped. - let mut table = unsafe { InactivePageTable::from_address(prev.frame.utable.start_address().data()) }; - // TODO: Optimize away clearing of page tables? In that case, what about memory // deallocation? for grant in prev.grants.into_iter() { - grant.unmap(&mut table.mapper(), ()); + grant.unmap(&mut prev.table.utable, ()); } } diff --git a/src/scheme/user.rs b/src/scheme/user.rs index 2a6fd21..e55c903 100644 --- a/src/scheme/user.rs +++ b/src/scheme/user.rs @@ -8,9 +8,9 @@ use spin::{Mutex, RwLock}; use crate::context::{self, Context}; use crate::context::file::FileDescriptor; -use crate::context::memory::{DANGLING, page_flags, round_down_pages, round_up_pages, Grant, Region, GrantFileRef}; +use crate::context::memory::{DANGLING, page_flags, Grant, Region, GrantFileRef}; use crate::event; -use crate::paging::{ActivePageTable, PAGE_SIZE, InactivePageTable, mapper::InactiveFlusher, Page, VirtualAddress}; +use crate::paging::{PAGE_SIZE, mapper::InactiveFlusher, Page, round_down_pages, round_up_pages, VirtualAddress}; use crate::scheme::{AtomicSchemeId, SchemeId}; use crate::sync::{WaitQueue, WaitMap}; use crate::syscall::data::{Map, Packet, Stat, StatVfs, TimeSpec}; @@ -147,8 +147,7 @@ impl UserInner { let mut context = context_lock.write(); let mut addr_space = context.addr_space()?.write(); - - let mut new_table = unsafe { InactivePageTable::from_address(addr_space.frame.utable.start_address().data()) }; + let addr_space = &mut *addr_space; let src_address = round_down_pages(address); let dst_address = round_down_pages(dst_address); @@ -156,6 +155,11 @@ impl UserInner { let aligned_size = round_up_pages(offset + size); let dst_region = addr_space.grants.find_free_at(VirtualAddress::new(dst_address), aligned_size, flags)?; + let current_addrspace = Arc::clone( + context::contexts().current().ok_or(Error::new(ESRCH))? + .read().addr_space()? + ); + //TODO: Use syscall_head and syscall_tail to avoid leaking data addr_space.grants.insert(Grant::borrow( Page::containing_address(VirtualAddress::new(src_address)), @@ -163,10 +167,10 @@ impl UserInner { aligned_size / PAGE_SIZE, page_flags(flags), desc_opt, - &mut *unsafe { ActivePageTable::new(rmm::TableKind::User) }, - &mut new_table.mapper(), + &mut current_addrspace.write().table.utable, + &mut addr_space.table.utable, InactiveFlusher::new(), - )); + )?); Ok(VirtualAddress::new(dst_region.start_address().data() + offset)) } @@ -176,16 +180,15 @@ impl UserInner { return Ok(()); } let context_lock = self.context.upgrade().ok_or(Error::new(ESRCH))?; - let mut context = context_lock.write(); + let context = context_lock.write(); let mut addr_space = context.addr_space()?.write(); - let mut other_table = unsafe { InactivePageTable::from_address(addr_space.frame.utable.start_address().data()) }; let region = match addr_space.grants.contains(VirtualAddress::new(address)).map(Region::from) { Some(region) => region, None => return Err(Error::new(EFAULT)), }; - addr_space.grants.take(®ion).unwrap().unmap(&mut other_table.mapper(), InactiveFlusher::new()); + addr_space.grants.take(®ion).unwrap().unmap(&mut addr_space.table.utable, InactiveFlusher::new()); Ok(()) }