Fix check for MemorySet. Fix copy user program.

master
WangRunji 7 years ago
parent 9723d7c1a3
commit b885b7ce6a

@ -19,7 +19,11 @@ impl MemoryArea {
addr >= self.start_addr && addr < self.end_addr addr >= self.start_addr && addr < self.end_addr
} }
fn is_overlap_with(&self, other: &MemoryArea) -> bool { fn is_overlap_with(&self, other: &MemoryArea) -> bool {
!(self.end_addr <= other.start_addr || self.start_addr >= other.end_addr) let p0 = Page::of_addr(self.start_addr);
let p1 = Page::of_addr(self.end_addr - 1) + 1;
let p2 = Page::of_addr(other.start_addr);
let p3 = Page::of_addr(other.end_addr - 1) + 1;
!(p1 <= p2 || p0 >= p3)
} }
} }
@ -50,7 +54,11 @@ impl MemorySet {
self.areas.iter().find(|area| area.contains(addr)) self.areas.iter().find(|area| area.contains(addr))
} }
pub fn push(&mut self, area: MemoryArea) { pub fn push(&mut self, area: MemoryArea) {
debug_assert!(area.start_addr <= area.end_addr, "invalid memory area"); assert!(area.start_addr <= area.end_addr, "invalid memory area");
if let Some(phys_addr) = area.phys_start_addr {
assert_eq!(area.start_addr % PAGE_SIZE, phys_addr.get() % PAGE_SIZE,
"virtual & physical start address must have same page offset");
}
assert!(self.areas.iter() assert!(self.areas.iter()
.find(|other| area.is_overlap_with(other)) .find(|other| area.is_overlap_with(other))
.is_none(), "memory area overlap"); .is_none(), "memory area overlap");

@ -225,4 +225,9 @@ impl MemoryController {
}); });
page_table page_table
} }
pub fn with(&mut self, page_table: InactivePageTable, mut f: impl FnMut()) -> InactivePageTable {
let backup = self.active_table.switch(page_table);
f();
self.active_table.switch(backup)
}
} }

@ -1,8 +1,9 @@
use super::*; use super::*;
use memory::{Stack, InactivePageTable}; use memory::{Stack, InactivePageTable};
use xmas_elf::{ElfFile, program::{Flags, ProgramHeader}}; use xmas_elf::{ElfFile, program::{Flags, ProgramHeader}, header::HeaderPt2};
use core::slice; use core::slice;
use alloc::rc::Rc; use alloc::rc::Rc;
use rlibc::memcpy;
#[derive(Debug)] #[derive(Debug)]
pub struct Process { pub struct Process {
@ -58,19 +59,32 @@ impl Process {
} }
pub fn new_user(begin: usize, end: usize, mc: &mut MemoryController) -> Self { pub fn new_user(begin: usize, end: usize, mc: &mut MemoryController) -> Self {
// Parse elf
let slice = unsafe{ slice::from_raw_parts(begin as *const u8, end - begin) }; let slice = unsafe{ slice::from_raw_parts(begin as *const u8, end - begin) };
let elf = ElfFile::new(slice).expect("failed to read elf"); let elf = ElfFile::new(slice).expect("failed to read elf");
let phys_start = PhysAddr::from_kernel_virtual(begin);
let mut memory_set = MemorySet::from((&elf, phys_start)); // Make page table
let mut memory_set = MemorySet::from(&elf);
let page_table = mc.make_page_table(&mut memory_set); let page_table = mc.make_page_table(&mut memory_set);
debug!("{:#x?}", memory_set); debug!("{:#x?}", memory_set);
use xmas_elf::header::HeaderPt2; // Temporary switch to it, in order to copy data
let page_table = mc.with(page_table, || {
for ph in elf.program_iter() {
let ph = match ph {
ProgramHeader::Ph64(ph) => ph,
_ => unimplemented!(),
};
unsafe { memcpy(ph.virtual_addr as *mut u8, (begin + ph.offset as usize) as *mut u8, ph.file_size as usize) };
}
});
let entry_addr = match elf.header.pt2 { let entry_addr = match elf.header.pt2 {
HeaderPt2::Header64(header) => header.entry_point, HeaderPt2::Header64(header) => header.entry_point,
_ => unimplemented!(), _ => unimplemented!(),
} as usize; } as usize;
// Allocate kernel stack and push trap frame
let kstack = mc.alloc_stack(7).unwrap(); let kstack = mc.alloc_stack(7).unwrap();
let tf = TrapFrame::new_user_thread(entry_addr, kstack.top()); let tf = TrapFrame::new_user_thread(entry_addr, kstack.top());
let rsp = kstack.push_at_top(tf); let rsp = kstack.push_at_top(tf);
@ -90,9 +104,8 @@ impl Process {
use memory::{MemorySet, MemoryArea, PhysAddr, FromToVirtualAddress, EntryFlags}; use memory::{MemorySet, MemoryArea, PhysAddr, FromToVirtualAddress, EntryFlags};
impl<'a> From<(&'a ElfFile<'a>, PhysAddr)> for MemorySet { impl<'a> From<&'a ElfFile<'a>> for MemorySet {
fn from(input: (&'a ElfFile<'a>, PhysAddr)) -> Self { fn from(elf: &'a ElfFile<'a>) -> Self {
let (elf, phys_start) = input;
let mut set = MemorySet::new(); let mut set = MemorySet::new();
for ph in elf.program_iter() { for ph in elf.program_iter() {
let ph = match ph { let ph = match ph {
@ -102,7 +115,7 @@ impl<'a> From<(&'a ElfFile<'a>, PhysAddr)> for MemorySet {
set.push(MemoryArea { set.push(MemoryArea {
start_addr: ph.virtual_addr as usize, start_addr: ph.virtual_addr as usize,
end_addr: (ph.virtual_addr + ph.mem_size) as usize, end_addr: (ph.virtual_addr + ph.mem_size) as usize,
phys_start_addr: Some(PhysAddr(phys_start.get() as u64 + ph.offset)), phys_start_addr: None,
flags: EntryFlags::from(ph.flags).bits() as u32, flags: EntryFlags::from(ph.flags).bits() as u32,
name: "", name: "",
mapped: false, mapped: false,

Loading…
Cancel
Save