Clone grants

This commit is contained in:
Jeremy Soller 2016-09-20 22:14:08 -06:00
parent 1a3a24c8bb
commit 5757f3436e
4 changed files with 75 additions and 56 deletions

View file

@ -53,25 +53,25 @@ pub extern crate x86;
/// Offset to user heap
pub const USER_HEAP_OFFSET: usize = USER_OFFSET + PML4_SIZE;
/// Offset to user grants
pub const USER_GRANT_OFFSET: usize = USER_HEAP_OFFSET + PML4_SIZE;
/// Offset to user stack
pub const USER_STACK_OFFSET: usize = USER_HEAP_OFFSET + PML4_SIZE;
pub const USER_STACK_OFFSET: usize = USER_GRANT_OFFSET + PML4_SIZE;
/// Size of user stack
pub const USER_STACK_SIZE: usize = 1024 * 1024; // 1 MB
/// Offset to user grants
pub const USER_GRANT_OFFSET: usize = USER_STACK_OFFSET + PML4_SIZE;
/// Offset to user temporary image (used when cloning)
pub const USER_TMP_OFFSET: usize = USER_STACK_OFFSET + PML4_SIZE;
/// Offset to user temporary heap (used when cloning)
pub const USER_TMP_HEAP_OFFSET: usize = USER_TMP_OFFSET + PML4_SIZE;
/// Offset to user temporary stack (used when cloning)
pub const USER_TMP_STACK_OFFSET: usize = USER_TMP_HEAP_OFFSET + PML4_SIZE;
/// Offset to user temporary page for grants
pub const USER_TMP_GRANT_OFFSET: usize = USER_TMP_STACK_OFFSET + PML4_SIZE;
pub const USER_TMP_GRANT_OFFSET: usize = USER_TMP_HEAP_OFFSET + PML4_SIZE;
/// Offset to user temporary stack (used when cloning)
pub const USER_TMP_STACK_OFFSET: usize = USER_TMP_GRANT_OFFSET + PML4_SIZE;
/// Print to console

View file

@ -16,7 +16,31 @@ pub struct Grant {
}
impl Grant {
pub fn new(from: VirtualAddress, to: VirtualAddress, size: usize, flags: EntryFlags, new_table: &mut InactivePageTable, temporary_page: &mut TemporaryPage) -> Grant {
pub fn physmap(from: PhysicalAddress, to: VirtualAddress, size: usize, flags: EntryFlags) -> Grant {
let mut active_table = unsafe { ActivePageTable::new() };
let mut flush_all = false;
let start_page = Page::containing_address(to);
let end_page = Page::containing_address(VirtualAddress::new(to.get() + size - 1));
for page in Page::range_inclusive(start_page, end_page) {
let frame = Frame::containing_address(PhysicalAddress::new(page.start_address().get() - to.get() + from.get()));
active_table.map_to(page, frame, flags);
flush_all = true;
}
if flush_all {
active_table.flush_all();
}
Grant {
start: to,
size: size,
flags: flags
}
}
pub fn map_inactive(from: VirtualAddress, to: VirtualAddress, size: usize, flags: EntryFlags, new_table: &mut InactivePageTable, temporary_page: &mut TemporaryPage) -> Grant {
let mut active_table = unsafe { ActivePageTable::new() };
let mut frames = VecDeque::new();
@ -44,43 +68,19 @@ impl Grant {
}
}
pub fn destroy(self, new_table: &mut InactivePageTable, temporary_page: &mut TemporaryPage) {
let mut active_table = unsafe { ActivePageTable::new() };
active_table.with(new_table, temporary_page, |mapper| {
let start_page = Page::containing_address(self.start);
let end_page = Page::containing_address(VirtualAddress::new(self.start.get() + self.size - 1));
for page in Page::range_inclusive(start_page, end_page) {
mapper.unmap_return(page);
}
});
pub fn start_address(&self) -> VirtualAddress {
self.start
}
pub fn physmap(from: PhysicalAddress, to: VirtualAddress, size: usize, flags: EntryFlags) -> Grant {
let mut active_table = unsafe { ActivePageTable::new() };
let mut flush_all = false;
let start_page = Page::containing_address(to);
let end_page = Page::containing_address(VirtualAddress::new(to.get() + size - 1));
for page in Page::range_inclusive(start_page, end_page) {
let frame = Frame::containing_address(PhysicalAddress::new(page.start_address().get() - to.get() + from.get()));
active_table.map_to(page, frame, flags);
flush_all = true;
pub fn size(&self) -> usize {
self.size
}
if flush_all {
active_table.flush_all();
pub fn flags(&self) -> EntryFlags {
self.flags
}
Grant {
start: to,
size: size,
flags: flags
}
}
pub fn physunmap(self) {
pub fn unmap(self) {
let mut active_table = unsafe { ActivePageTable::new() };
let mut flush_all = false;
@ -97,16 +97,16 @@ impl Grant {
}
}
pub fn start_address(&self) -> VirtualAddress {
self.start
}
pub fn unmap_inactive(self, new_table: &mut InactivePageTable, temporary_page: &mut TemporaryPage) {
let mut active_table = unsafe { ActivePageTable::new() };
pub fn size(&self) -> usize {
self.size
active_table.with(new_table, temporary_page, |mapper| {
let start_page = Page::containing_address(self.start);
let end_page = Page::containing_address(VirtualAddress::new(self.start.get() + self.size - 1));
for page in Page::range_inclusive(start_page, end_page) {
mapper.unmap_return(page);
}
pub fn flags(&self) -> EntryFlags {
self.flags
});
}
}

View file

@ -89,7 +89,7 @@ impl UserInner {
for i in 0 .. grants.len() {
let start = grants[i].start_address().get();
if to_address + full_size < start {
grants.insert(i, Grant::new(
grants.insert(i, Grant::map_inactive(
VirtualAddress::new(from_address),
VirtualAddress::new(to_address),
full_size,
@ -106,7 +106,7 @@ impl UserInner {
}
}
grants.push(Grant::new(
grants.push(Grant::map_inactive(
VirtualAddress::new(from_address),
VirtualAddress::new(to_address),
full_size,
@ -135,7 +135,7 @@ impl UserInner {
let start = grants[i].start_address().get();
let end = start + grants[i].size();
if address >= start && address < end {
grants.remove(i).destroy(&mut new_table, &mut temporary_page);
grants.remove(i).unmap_inactive(&mut new_table, &mut temporary_page);
return Ok(());
}

View file

@ -63,6 +63,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
let mut image = vec![];
let mut heap_option = None;
let mut stack_option = None;
let grants;
let cwd;
let files;
@ -159,6 +160,12 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
stack_option = Some(new_stack);
}
if flags & CLONE_VM == CLONE_VM {
grants = context.grants.clone();
} else {
grants = Arc::new(Mutex::new(Vec::new()));
}
if flags & CLONE_FS == CLONE_FS {
cwd = context.cwd.clone();
} else {
@ -252,12 +259,21 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
// Copy user heap mapping, if found
if let Some(heap_shared) = heap_option {
let frame = active_table.p4()[1].pointed_frame().expect("user heap not mapped");
let flags = active_table.p4()[0].flags();
let flags = active_table.p4()[1].flags();
active_table.with(&mut new_table, &mut temporary_page, |mapper| {
mapper.p4_mut()[1].set(frame, flags);
});
context.heap = Some(heap_shared);
}
if ! grants.lock().is_empty() {
let frame = active_table.p4()[2].pointed_frame().expect("user heap not mapped");
let flags = active_table.p4()[2].flags();
active_table.with(&mut new_table, &mut temporary_page, |mapper| {
mapper.p4_mut()[1].set(frame, flags);
});
}
context.grants = grants;
} else {
// Copy percpu mapping
{
@ -330,6 +346,8 @@ pub fn exit(status: usize) -> ! {
context.image.clear();
drop(context.heap.take());
drop(context.stack.take());
context.grants = Arc::new(Mutex::new(Vec::new()));
context.files = Arc::new(Mutex::new(Vec::new()));
context.status = context::Status::Exited(status);
}
@ -378,6 +396,7 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
context.image.clear();
drop(context.heap.take());
drop(context.stack.take());
context.grants = Arc::new(Mutex::new(Vec::new()));
for segment in elf.segments() {
if segment.p_type == program_header::PT_LOAD {
@ -560,7 +579,7 @@ pub fn physunmap(virtual_address: usize) -> Result<usize> {
let start = grants[i].start_address().get();
let end = start + grants[i].size();
if virtual_address >= start && virtual_address < end {
grants.remove(i).physunmap();
grants.remove(i).unmap();
return Ok(0);
}