|  |  |  | @ -1,6 +1,6 @@ | 
			
		
	
		
			
				
					|  |  |  |  | use super::*; | 
			
		
	
		
			
				
					|  |  |  |  | use memory::Stack; | 
			
		
	
		
			
				
					|  |  |  |  | use xmas_elf::ElfFile; | 
			
		
	
		
			
				
					|  |  |  |  | use xmas_elf::{ElfFile, program::{Flags, ProgramHeader}}; | 
			
		
	
		
			
				
					|  |  |  |  | use core::slice; | 
			
		
	
		
			
				
					|  |  |  |  | use alloc::rc::Rc; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -12,6 +12,7 @@ pub struct Process { | 
			
		
	
		
			
				
					|  |  |  |  |     //                    memory_set: Rc<MemorySet>,
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub(in process) status: Status, | 
			
		
	
		
			
				
					|  |  |  |  |     pub(in process) rsp: usize, | 
			
		
	
		
			
				
					|  |  |  |  |     pub(in process) is_user: bool, | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | pub type Pid = usize; | 
			
		
	
	
		
			
				
					|  |  |  | @ -25,10 +26,8 @@ impl Process { | 
			
		
	
		
			
				
					|  |  |  |  |     /// Make a new kernel thread
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn new(name: &'static str, entry: extern fn(), mc: &mut MemoryController) -> Self { | 
			
		
	
		
			
				
					|  |  |  |  |         let kstack = mc.alloc_stack(7).unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |         let rsp = unsafe{ (kstack.top() as *mut TrapFrame).offset(-1) } as usize; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         let tf = unsafe{ &mut *(rsp as *mut TrapFrame) }; | 
			
		
	
		
			
				
					|  |  |  |  |         *tf = TrapFrame::new_kernel_thread(entry, kstack.top()); | 
			
		
	
		
			
				
					|  |  |  |  |         let tf = TrapFrame::new_kernel_thread(entry, kstack.top()); | 
			
		
	
		
			
				
					|  |  |  |  |         let rsp = kstack.push_at_top(tf); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         Process { | 
			
		
	
		
			
				
					|  |  |  |  |             pid: 0, | 
			
		
	
	
		
			
				
					|  |  |  | @ -36,6 +35,7 @@ impl Process { | 
			
		
	
		
			
				
					|  |  |  |  |             kstack, | 
			
		
	
		
			
				
					|  |  |  |  |             status: Status::Ready, | 
			
		
	
		
			
				
					|  |  |  |  |             rsp, | 
			
		
	
		
			
				
					|  |  |  |  |             is_user: false, | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  |     /// Make the first kernel thread `initproc`
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -48,40 +48,72 @@ impl Process { | 
			
		
	
		
			
				
					|  |  |  |  |             kstack: mc.kernel_stack.take().unwrap(), | 
			
		
	
		
			
				
					|  |  |  |  |             status: Status::Running, | 
			
		
	
		
			
				
					|  |  |  |  |             rsp: 0, // will be set at first schedule
 | 
			
		
	
		
			
				
					|  |  |  |  |             is_user: false, | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn new_user(begin: usize, end: usize, mc: &mut MemoryController) -> Self { | 
			
		
	
		
			
				
					|  |  |  |  |         let slice = unsafe{ slice::from_raw_parts(begin as *const u8, end - begin) }; | 
			
		
	
		
			
				
					|  |  |  |  |         let elf = ElfFile::new(slice).expect("failed to read elf"); | 
			
		
	
		
			
				
					|  |  |  |  |         let mut set = MemorySet::from(&elf); | 
			
		
	
		
			
				
					|  |  |  |  | //        set.map(mc);
 | 
			
		
	
		
			
				
					|  |  |  |  |         unimplemented!(); | 
			
		
	
		
			
				
					|  |  |  |  |         let phys_start = PhysAddr::from_kernel_virtual(begin); | 
			
		
	
		
			
				
					|  |  |  |  |         let mut set = MemorySet::from((&elf, phys_start)); | 
			
		
	
		
			
				
					|  |  |  |  |         let page_table = mc.make_page_table(&mut set); | 
			
		
	
		
			
				
					|  |  |  |  |         debug!("{:#x?}", set); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         use xmas_elf::header::HeaderPt2; | 
			
		
	
		
			
				
					|  |  |  |  |         let entry_addr = match elf.header.pt2 { | 
			
		
	
		
			
				
					|  |  |  |  |             HeaderPt2::Header64(header) => header.entry_point, | 
			
		
	
		
			
				
					|  |  |  |  |             _ => unimplemented!(), | 
			
		
	
		
			
				
					|  |  |  |  |         } as usize; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         let kstack = mc.alloc_stack(7).unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |         let tf = TrapFrame::new_user_thread(entry_addr, kstack.top()); | 
			
		
	
		
			
				
					|  |  |  |  |         let rsp = kstack.push_at_top(tf); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         Process { | 
			
		
	
		
			
				
					|  |  |  |  |             pid: 0, | 
			
		
	
		
			
				
					|  |  |  |  |             name: "user", | 
			
		
	
		
			
				
					|  |  |  |  |             kstack, | 
			
		
	
		
			
				
					|  |  |  |  |             status: Status::Ready, | 
			
		
	
		
			
				
					|  |  |  |  |             rsp, | 
			
		
	
		
			
				
					|  |  |  |  |             is_user: true, | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | use memory::{MemorySet, MemoryArea}; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | impl<'a> From<&'a ElfFile<'a>> for MemorySet { | 
			
		
	
		
			
				
					|  |  |  |  |     fn from(elf: &'a ElfFile<'a>) -> Self { | 
			
		
	
		
			
				
					|  |  |  |  |         use xmas_elf::program::ProgramHeader; | 
			
		
	
		
			
				
					|  |  |  |  | use memory::{MemorySet, MemoryArea, PhysAddr, FromToVirtualAddress, EntryFlags}; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | impl<'a> From<(&'a ElfFile<'a>, PhysAddr)> for MemorySet { | 
			
		
	
		
			
				
					|  |  |  |  |     fn from(input: (&'a ElfFile<'a>, PhysAddr)) -> Self { | 
			
		
	
		
			
				
					|  |  |  |  |         let (elf, phys_start) = input; | 
			
		
	
		
			
				
					|  |  |  |  |         let mut set = MemorySet::new(); | 
			
		
	
		
			
				
					|  |  |  |  |         for ph in elf.program_iter() { | 
			
		
	
		
			
				
					|  |  |  |  |             match ph { | 
			
		
	
		
			
				
					|  |  |  |  |                 ProgramHeader::Ph32(ph) => unimplemented!(), | 
			
		
	
		
			
				
					|  |  |  |  |                 ProgramHeader::Ph64(ph) => { | 
			
		
	
		
			
				
					|  |  |  |  |                     set.push(MemoryArea { | 
			
		
	
		
			
				
					|  |  |  |  |                         start_addr: ph.virtual_addr as usize, | 
			
		
	
		
			
				
					|  |  |  |  |                         end_addr: (ph.virtual_addr + ph.mem_size) as usize, | 
			
		
	
		
			
				
					|  |  |  |  |                         phys_start_addr: None, | 
			
		
	
		
			
				
					|  |  |  |  |                         flags: ph.flags.0,  // TODO: handle it
 | 
			
		
	
		
			
				
					|  |  |  |  |                         name: "", | 
			
		
	
		
			
				
					|  |  |  |  |                         mapped: false, | 
			
		
	
		
			
				
					|  |  |  |  |                     }); | 
			
		
	
		
			
				
					|  |  |  |  |                 }, | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             let ph = match ph { | 
			
		
	
		
			
				
					|  |  |  |  |                 ProgramHeader::Ph64(ph) => ph, | 
			
		
	
		
			
				
					|  |  |  |  |                 _ => unimplemented!(), | 
			
		
	
		
			
				
					|  |  |  |  |             }; | 
			
		
	
		
			
				
					|  |  |  |  |             set.push(MemoryArea { | 
			
		
	
		
			
				
					|  |  |  |  |                 start_addr: ph.virtual_addr as usize, | 
			
		
	
		
			
				
					|  |  |  |  |                 end_addr: (ph.virtual_addr + ph.mem_size) as usize, | 
			
		
	
		
			
				
					|  |  |  |  |                 phys_start_addr: Some(PhysAddr(phys_start.get() as u64 + ph.offset)), | 
			
		
	
		
			
				
					|  |  |  |  |                 flags: EntryFlags::from(ph.flags).bits() as u32, | 
			
		
	
		
			
				
					|  |  |  |  |                 name: "", | 
			
		
	
		
			
				
					|  |  |  |  |                 mapped: false, | 
			
		
	
		
			
				
					|  |  |  |  |             }); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         set | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | impl From<Flags> for EntryFlags { | 
			
		
	
		
			
				
					|  |  |  |  |     fn from(elf_flags: Flags) -> Self { | 
			
		
	
		
			
				
					|  |  |  |  |         let mut flags = EntryFlags::PRESENT; | 
			
		
	
		
			
				
					|  |  |  |  |         if elf_flags.is_write() { | 
			
		
	
		
			
				
					|  |  |  |  |             flags = flags | EntryFlags::WRITABLE; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         if !elf_flags.is_execute() { | 
			
		
	
		
			
				
					|  |  |  |  |             flags = flags | EntryFlags::NO_EXECUTE; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         flags | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } |