Partial: Migrate schemes to RMM.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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, ());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user