Partial: Migrate schemes to RMM.

This commit is contained in:
4lDO2
2022-07-17 14:11:57 +02:00
parent 486d296d6d
commit 6589083238
6 changed files with 45 additions and 40 deletions

View File

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

View File

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

View File

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

View File

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

View File

@@ -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<Arc<RwLock<AddrSpace>>> {
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<RmmA>)
let mut flusher = if is_active {
active = PageFlushAll::new();
&mut active as &mut dyn Flusher<RmmA>
} else {
inactive = (unsafe { InactivePageTable::from_address(addrspace.frame.utable.start_address().data()) }, InactiveFlusher::new());
(inactive.0.mapper(), &mut inactive.1 as &mut dyn Flusher<RmmA>)
inactive = InactiveFlusher::new();
&mut inactive as &mut dyn Flusher<RmmA>
};
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, ());
}
}

View File

@@ -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(&region).unwrap().unmap(&mut other_table.mapper(), InactiveFlusher::new());
addr_space.grants.take(&region).unwrap().unmap(&mut addr_space.table.utable, InactiveFlusher::new());
Ok(())
}