@ -3,7 +3,8 @@ use memory::{MemoryArea, MemoryAttr, MemorySet, active_table_swap, alloc_frame};
use xmas_elf ::{ ElfFile , header , program ::{ Flags , ProgramHeader , Type } } ;
use xmas_elf ::{ ElfFile , header , program ::{ Flags , ProgramHeader , Type } } ;
use core ::fmt ::{ Debug , Error , Formatter } ;
use core ::fmt ::{ Debug , Error , Formatter } ;
use ucore_memory ::{ Page } ;
use ucore_memory ::{ Page } ;
use ::memory ::{ InactivePageTable0 } ;
use ::memory ::{ InactivePageTable0 , memory_set_record } ;
use ucore_memory ::memory_set ::* ;
pub struct Context {
pub struct Context {
arch : ArchContext ,
arch : ArchContext ,
@ -61,7 +62,7 @@ impl Context {
* the new user thread Context
* the new user thread Context
* /
* /
pub fn new_user ( data : & [ u8 ] ) -> Self {
pub fn new_user ( data : & [ u8 ] ) -> Self {
info !( " come into new user " ) ;
debug !( " come into new user " ) ;
// Parse elf
// Parse elf
let elf = ElfFile ::new ( data ) . expect ( " failed to read elf " ) ;
let elf = ElfFile ::new ( data ) . expect ( " failed to read elf " ) ;
let is32 = match elf . header . pt2 {
let is32 = match elf . header . pt2 {
@ -71,7 +72,6 @@ impl Context {
assert_eq! ( elf . header . pt2 . type_ ( ) . as_type ( ) , header ::Type ::Executable , " ELF is not executable " ) ;
assert_eq! ( elf . header . pt2 . type_ ( ) . as_type ( ) , header ::Type ::Executable , " ELF is not executable " ) ;
// User stack
// User stack
info! ( " start building suer stack " ) ;
use consts ::{ USER_STACK_OFFSET , USER_STACK_SIZE , USER32_STACK_OFFSET } ;
use consts ::{ USER_STACK_OFFSET , USER_STACK_SIZE , USER32_STACK_OFFSET } ;
let ( user_stack_buttom , user_stack_top ) = match is32 {
let ( user_stack_buttom , user_stack_top ) = match is32 {
true = > ( USER32_STACK_OFFSET , USER32_STACK_OFFSET + USER_STACK_SIZE ) ,
true = > ( USER32_STACK_OFFSET , USER32_STACK_OFFSET + USER_STACK_SIZE ) ,
@ -79,16 +79,20 @@ impl Context {
} ;
} ;
// Make page table
// Make page table
info! ( " make page table! " ) ;
let mut memory_set = memory_set_from ( & elf ) ;
let mut memory_set = memory_set_from ( & elf ) ;
info! ( " start to push user stack to the mmset " ) ;
// add the new memory set to the recorder
let mmset_ptr = ( ( & mut memory_set ) as * mut MemorySet ) as usize ;
memory_set_record ( ) . push_back ( mmset_ptr ) ;
//let id = memory_set_record().iter()
// .position(|x| unsafe { info!("current memory set record include {:x?}, {:x?}", x, (*(x.clone() as *mut MemorySet)).get_page_table_mut().token()); false });
memory_set . push ( MemoryArea ::new ( user_stack_buttom , user_stack_top , MemoryAttr ::default ( ) . user ( ) , " user_stack " ) ) ;
memory_set . push ( MemoryArea ::new ( user_stack_buttom , user_stack_top , MemoryAttr ::default ( ) . user ( ) , " user_stack " ) ) ;
trace! ( " {:#x?} " , memory_set ) ;
trace! ( " {:#x?} " , memory_set ) ;
let entry_addr = elf . header . pt2 . entry_point ( ) as usize ;
let entry_addr = elf . header . pt2 . entry_point ( ) as usize ;
// Temporary switch to it, in order to copy data
// Temporary switch to it, in order to copy data
info! ( " starting copy data. " ) ;
unsafe {
unsafe {
memory_set . with ( | | {
memory_set . with ( | | {
for ph in elf . program_iter ( ) {
for ph in elf . program_iter ( ) {
@ -98,13 +102,9 @@ impl Context {
if file_size = = 0 {
if file_size = = 0 {
return ;
return ;
}
}
info! ( " file virtaddr: {:x?}, file size: {:x?} " , virt_addr , file_size ) ;
use core ::slice ;
use core ::slice ;
info! ( " starting copy! " ) ;
let target = unsafe { slice ::from_raw_parts_mut ( virt_addr as * mut u8 , file_size ) } ;
let target = unsafe { slice ::from_raw_parts_mut ( virt_addr as * mut u8 , file_size ) } ;
info! ( " target got! " ) ;
target . copy_from_slice ( & data [ offset .. offset + file_size ] ) ;
target . copy_from_slice ( & data [ offset .. offset + file_size ] ) ;
info! ( " finish copy! " ) ;
}
}
if is32 {
if is32 {
unsafe {
unsafe {
@ -115,11 +115,12 @@ impl Context {
}
}
} ) ;
} ) ;
}
}
info! ( " ending copy data. " ) ;
//set the user Memory pages in the memory set swappable
//set the user Memory pages in the memory set swappable
//memory_set_map_swappable(&mut memory_set);
//memory_set_map_swappable(&mut memory_set);
let id = memory_set_record ( ) . iter ( )
. position ( | x | x . clone ( ) = = mmset_ptr ) . unwrap ( ) ;
memory_set_record ( ) . remove ( id ) ;
Context {
Context {
arch : unsafe {
arch : unsafe {
ArchContext ::new_user_thread (
ArchContext ::new_user_thread (
@ -131,9 +132,15 @@ impl Context {
/// Fork
/// Fork
pub fn fork ( & self , tf : & TrapFrame ) -> Self {
pub fn fork ( & self , tf : & TrapFrame ) -> Self {
debug! ( " Come in to fork! " ) ;
// Clone memory set, make a new page table
// Clone memory set, make a new page table
let mut memory_set = self . memory_set . clone ( ) ;
let mut memory_set = self . memory_set . clone ( ) ;
// add the new memory set to the recorder
debug! ( " fork! new page table token: {:x?} " , memory_set . token ( ) ) ;
let mmset_ptr = ( ( & mut memory_set ) as * mut MemorySet ) as usize ;
memory_set_record ( ) . push_back ( mmset_ptr ) ;
// Copy data to temp space
// Copy data to temp space
use alloc ::vec ::Vec ;
use alloc ::vec ::Vec ;
let datas : Vec < Vec < u8 > > = memory_set . iter ( ) . map ( | area | {
let datas : Vec < Vec < u8 > > = memory_set . iter ( ) . map ( | area | {
@ -148,9 +155,11 @@ impl Context {
}
}
} ) ;
} ) ;
}
}
// map the memory set swappable
memory_set_map_swappable ( & mut memory_set ) ;
// remove the raw pointer for the memory set since it will
let id = memory_set_record ( ) . iter ( )
. position ( | x | x . clone ( ) = = mmset_ptr ) . unwrap ( ) ;
memory_set_record ( ) . remove ( id ) ;
Context {
Context {
arch : unsafe { ArchContext ::new_fork ( tf , memory_set . kstack_top ( ) , memory_set . token ( ) ) } ,
arch : unsafe { ArchContext ::new_fork ( tf , memory_set . kstack_top ( ) , memory_set . token ( ) ) } ,
memory_set ,
memory_set ,
@ -165,7 +174,16 @@ impl Context {
impl Drop for Context {
impl Drop for Context {
fn drop ( & mut self ) {
fn drop ( & mut self ) {
// remove the new memory set to the recorder (deprecated in the latest version)
/*
/*
let id = memory_set_record ( ) . iter ( )
. position ( | x | unsafe { ( * ( x . clone ( ) as * mut MemorySet ) ) . token ( ) = = self . memory_set . token ( ) } ) ;
if id . is_some ( ) {
info! ( " remove id {:x?} " , id . unwrap ( ) ) ;
memory_set_record ( ) . remove ( id . unwrap ( ) ) ;
}
* /
//set the user Memory pages in the memory set unswappable
//set the user Memory pages in the memory set unswappable
let Self { ref mut arch , ref mut memory_set } = self ;
let Self { ref mut arch , ref mut memory_set } = self ;
let pt = {
let pt = {
@ -179,8 +197,8 @@ impl Drop for Context{
}
}
}
}
}
}
info !( " Finishing setting pages unswappable " ) ;
debug !( " Finishing setting pages unswappable " ) ;
* /
}
}
}
}
@ -199,7 +217,7 @@ impl Debug for Context {
* the new memory set
* the new memory set
* /
* /
fn memory_set_from < ' a > ( elf : & ' a ElfFile < ' a > ) -> MemorySet {
fn memory_set_from < ' a > ( elf : & ' a ElfFile < ' a > ) -> MemorySet {
info !( " come in to memory_set_from " ) ;
debug !( " come in to memory_set_from " ) ;
let mut set = MemorySet ::new ( ) ;
let mut set = MemorySet ::new ( ) ;
for ph in elf . program_iter ( ) {
for ph in elf . program_iter ( ) {
if ph . get_type ( ) ! = Ok ( Type ::Load ) {
if ph . get_type ( ) ! = Ok ( Type ::Load ) {
@ -209,7 +227,6 @@ fn memory_set_from<'a>(elf: &'a ElfFile<'a>) -> MemorySet {
ProgramHeader ::Ph32 ( ph ) = > ( ph . virtual_addr as usize , ph . mem_size as usize , ph . flags ) ,
ProgramHeader ::Ph32 ( ph ) = > ( ph . virtual_addr as usize , ph . mem_size as usize , ph . flags ) ,
ProgramHeader ::Ph64 ( ph ) = > ( ph . virtual_addr as usize , ph . mem_size as usize , ph . flags ) , //???
ProgramHeader ::Ph64 ( ph ) = > ( ph . virtual_addr as usize , ph . mem_size as usize , ph . flags ) , //???
} ;
} ;
info! ( " push! " ) ;
set . push ( MemoryArea ::new ( virt_addr , virt_addr + mem_size , memory_attr_from ( flags ) , " " ) ) ;
set . push ( MemoryArea ::new ( virt_addr , virt_addr + mem_size , memory_attr_from ( flags ) , " " ) ) ;
}
}
@ -229,15 +246,15 @@ fn memory_attr_from(elf_flags: Flags) -> MemoryAttr {
* @ brief :
* @ brief :
* map the memory area in the memory_set swappalbe , specially for the user process
* map the memory area in the memory_set swappalbe , specially for the user process
* /
* /
fn memory_set_map_swappable ( memory_set : & mut MemorySet ) {
pub fn memory_set_map_swappable ( memory_set : & mut MemorySet ) {
let pt = unsafe {
let pt = unsafe {
memory_set . get_page_table_mut ( ) as * mut InactivePageTable0
memory_set . get_page_table_mut ( ) as * mut InactivePageTable0
} ;
} ;
for area in memory_set . iter ( ) {
for area in memory_set . iter ( ) {
for page in Page ::range_of ( area . get_start_addr ( ) , area . get_end_addr ( ) ) {
for page in Page ::range_of ( area . get_start_addr ( ) , area . get_end_addr ( ) ) {
let addr = page . start_address ( ) ;
let addr = page . start_address ( ) ;
active_table_swap ( ) . set_swappable ( pt , addr ) ;
unsafe { active_table_swap ( ) . set_swappable ( pt , addr ) ; }
}
}
}
}
info !( " Finishing setting pages swappable " ) ;
debug !( " Finishing setting pages swappable " ) ;
}
}