From 5757f3436ed7f409dcaeb3df668527a99535ffdf Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 20 Sep 2016 22:14:08 -0600 Subject: [PATCH] Clone grants --- arch/x86_64/src/lib.rs | 16 ++++---- kernel/context/memory.rs | 86 +++++++++++++++++++-------------------- kernel/scheme/user.rs | 6 +-- kernel/syscall/process.rs | 23 ++++++++++- 4 files changed, 75 insertions(+), 56 deletions(-) diff --git a/arch/x86_64/src/lib.rs b/arch/x86_64/src/lib.rs index ff0f9fb..427fe62 100644 --- a/arch/x86_64/src/lib.rs +++ b/arch/x86_64/src/lib.rs @@ -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 diff --git a/kernel/context/memory.rs b/kernel/context/memory.rs index 143ee53..911f619 100644 --- a/kernel/context/memory.rs +++ b/kernel/context/memory.rs @@ -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; - } - - if flush_all { - active_table.flush_all(); - } - - Grant { - start: to, - size: size, - flags: flags - } + pub fn size(&self) -> usize { + self.size } - pub fn physunmap(self) { + pub fn flags(&self) -> EntryFlags { + self.flags + } + + 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 - } - - pub fn flags(&self) -> EntryFlags { - self.flags + 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); + } + }); } } diff --git a/kernel/scheme/user.rs b/kernel/scheme/user.rs index f2c797e..7604b0f 100644 --- a/kernel/scheme/user.rs +++ b/kernel/scheme/user.rs @@ -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(()); } diff --git a/kernel/syscall/process.rs b/kernel/syscall/process.rs index 6a91e47..6ffd8c5 100644 --- a/kernel/syscall/process.rs +++ b/kernel/syscall/process.rs @@ -63,6 +63,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { 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 { 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 { // 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 { 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 { 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); }