Clone grants
This commit is contained in:
parent
1a3a24c8bb
commit
5757f3436e
|
@ -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
|
||||
|
|
|
@ -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
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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(());
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue