From ec240ef7786183cfacbf3a56fe7f8149676b4494 Mon Sep 17 00:00:00 2001
From: Jeremy Soller <jackpot51@gmail.com>
Date: Tue, 20 Sep 2016 22:14:08 -0600
Subject: [PATCH] Clone grants

---
 context/memory.rs  | 84 +++++++++++++++++++++++-----------------------
 scheme/user.rs     |  6 ++--
 syscall/process.rs | 23 +++++++++++--
 3 files changed, 66 insertions(+), 47 deletions(-)

diff --git a/context/memory.rs b/context/memory.rs
index 143ee531..911f6192 100644
--- a/context/memory.rs
+++ b/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();
-        }
+    pub fn size(&self) -> usize {
+        self.size
+    }
 
-        Grant {
-            start: to,
-            size: size,
-            flags: flags
-        }
+    pub fn flags(&self) -> EntryFlags {
+        self.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 size(&self) -> usize {
-        self.size
-    }
+    pub fn unmap_inactive(self, new_table: &mut InactivePageTable, temporary_page: &mut TemporaryPage) {
+        let mut active_table = unsafe { ActivePageTable::new() };
 
-    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/scheme/user.rs b/scheme/user.rs
index f2c797e4..7604b0fd 100644
--- a/scheme/user.rs
+++ b/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/syscall/process.rs b/syscall/process.rs
index 6a91e473..6ffd8c57 100644
--- a/syscall/process.rs
+++ b/syscall/process.rs
@@ -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);
             }
-- 
GitLab