fix sys_exec

master
WangRunji 6 years ago
parent 27f5c7b2e4
commit 5bc6395b23

@ -32,7 +32,7 @@ impl TrapFrame {
tf.spsr = 0b1101_00_0101; // To EL 1, enable IRQ tf.spsr = 0b1101_00_0101; // To EL 1, enable IRQ
tf tf
} }
fn new_user_thread(entry_addr: usize, sp: usize) -> Self { pub fn new_user_thread(entry_addr: usize, sp: usize) -> Self {
use core::mem::zeroed; use core::mem::zeroed;
let mut tf: Self = unsafe { zeroed() }; let mut tf: Self = unsafe { zeroed() };
tf.sp = sp; tf.sp = sp;
@ -40,9 +40,6 @@ impl TrapFrame {
tf.spsr = 0b1101_00_0000; // To EL 0, enable IRQ tf.spsr = 0b1101_00_0000; // To EL 0, enable IRQ
tf tf
} }
pub fn is_user(&self) -> bool {
unimplemented!()
}
} }
/// 新线程的内核栈初始内容 /// 新线程的内核栈初始内容
@ -201,11 +198,6 @@ impl Context {
} }
.push_at(kstack_top, ttbr) .push_at(kstack_top, ttbr)
} }
/// Called at a new user context
/// To get the init TrapFrame in sys_exec
pub unsafe fn get_init_tf(&self) -> TrapFrame {
(*(self.stack_top as *const InitStack)).tf.clone()
}
} }
const ASID_MASK: u16 = 0xffff; const ASID_MASK: u16 = 0xffff;

@ -76,7 +76,7 @@ impl TrapFrame {
/// ///
/// The new thread starts at `entry_addr`. /// The new thread starts at `entry_addr`.
/// The stack pointer will be set to `sp`. /// The stack pointer will be set to `sp`.
fn new_user_thread(entry_addr: usize, sp: usize) -> Self { pub fn new_user_thread(entry_addr: usize, sp: usize) -> Self {
use core::mem::zeroed; use core::mem::zeroed;
let mut tf: Self = unsafe { zeroed() }; let mut tf: Self = unsafe { zeroed() };
tf.sp = sp; tf.sp = sp;
@ -269,9 +269,4 @@ impl Context {
} }
.push_at(kstack_top) .push_at(kstack_top)
} }
/// Used for getting the init TrapFrame of a new user context in `sys_exec`.
pub unsafe fn get_init_tf(&self) -> TrapFrame {
(*(self.sp as *const InitStack)).tf.clone()
}
} }

@ -40,7 +40,7 @@ impl TrapFrame {
/// ///
/// The new thread starts at `entry_addr`. /// The new thread starts at `entry_addr`.
/// The stack pointer will be set to `sp`. /// The stack pointer will be set to `sp`.
fn new_user_thread(entry_addr: usize, sp: usize) -> Self { pub fn new_user_thread(entry_addr: usize, sp: usize) -> Self {
use core::mem::zeroed; use core::mem::zeroed;
let mut tf: Self = unsafe { zeroed() }; let mut tf: Self = unsafe { zeroed() };
tf.x[2] = sp; tf.x[2] = sp;
@ -289,9 +289,4 @@ impl Context {
} }
.push_at(kstack_top) .push_at(kstack_top)
} }
/// Used for getting the init TrapFrame of a new user context in `sys_exec`.
pub unsafe fn get_init_tf(&self) -> TrapFrame {
(*(self.sp as *const InitStack)).tf.clone()
}
} }

@ -73,7 +73,7 @@ impl TrapFrame {
tf.fpstate_offset = 16; // skip restoring for first time tf.fpstate_offset = 16; // skip restoring for first time
tf tf
} }
fn new_user_thread(entry_addr: usize, rsp: usize) -> Self { pub fn new_user_thread(entry_addr: usize, rsp: usize) -> Self {
use crate::arch::gdt; use crate::arch::gdt;
let mut tf = TrapFrame::default(); let mut tf = TrapFrame::default();
tf.cs = gdt::UCODE_SELECTOR.0 as usize; tf.cs = gdt::UCODE_SELECTOR.0 as usize;
@ -234,9 +234,4 @@ impl Context {
} }
.push_at(kstack_top) .push_at(kstack_top)
} }
/// Called at a new user context
/// To get the init TrapFrame in sys_exec
pub unsafe fn get_init_tf(&self) -> TrapFrame {
(*(self.0 as *const InitStack)).tf.clone()
}
} }

@ -126,13 +126,14 @@ impl Thread {
}) })
} }
/// Make a new user process from ELF `data` /// Construct virtual memory of a new user process from ELF `data`.
pub fn new_user( /// Return `(MemorySet, entry_point, ustack_top)`
pub fn new_user_vm(
data: &[u8], data: &[u8],
exec_path: &str, exec_path: &str,
mut args: Vec<String>, mut args: Vec<String>,
envs: Vec<String>, envs: Vec<String>,
) -> Box<Thread> { ) -> (MemorySet, usize, usize) {
// Parse ELF // Parse ELF
let elf = ElfFile::new(data).expect("failed to read elf"); let elf = ElfFile::new(data).expect("failed to read elf");
@ -159,22 +160,16 @@ impl Thread {
// Check interpreter (for dynamic link) // Check interpreter (for dynamic link)
if let Ok(loader_path) = elf.get_interpreter() { if let Ok(loader_path) = elf.get_interpreter() {
// assuming absolute path // assuming absolute path
if let Ok(inode) = crate::fs::ROOT_INODE.lookup_follow(loader_path, FOLLOW_MAX_DEPTH) { let inode = crate::fs::ROOT_INODE
if let Ok(buf) = inode.read_as_vec() { .lookup_follow(loader_path, FOLLOW_MAX_DEPTH)
.expect("interpreter not found");
let buf = inode.read_as_vec().expect("failed to load interpreter");
// modify args for loader
args[0] = exec_path.into();
args.insert(0, loader_path.into());
// Elf loader should not have INTERP // Elf loader should not have INTERP
// No infinite loop // No infinite loop
args.insert(0, loader_path.into()); return Thread::new_user_vm(buf.as_slice(), exec_path, args, envs);
args.insert(1, exec_path.into());
args.remove(2);
//info!("loader args: {:?}", args);
//info!("loader envs: {:?}", envs);
return Thread::new_user(buf.as_slice(), exec_path, args, envs);
} else {
warn!("loader specified as {} but failed to read", &loader_path);
}
} else {
warn!("loader specified as {} but not found", &loader_path);
}
} }
// Make page table // Make page table
@ -216,6 +211,19 @@ impl Thread {
trace!("{:#x?}", vm); trace!("{:#x?}", vm);
let entry_addr = elf.header.pt2.entry_point() as usize;
(vm, entry_addr, ustack_top)
}
/// Make a new user process from ELF `data`
pub fn new_user(
data: &[u8],
exec_path: &str,
mut args: Vec<String>,
envs: Vec<String>,
) -> Box<Thread> {
let (vm, entry_addr, ustack_top) = Self::new_user_vm(data, exec_path, args, envs);
let kstack = KernelStack::new(); let kstack = KernelStack::new();
let mut files = BTreeMap::new(); let mut files = BTreeMap::new();
@ -253,8 +261,6 @@ impl Thread {
)), )),
); );
let entry_addr = elf.header.pt2.entry_point() as usize;
Box::new(Thread { Box::new(Thread {
context: unsafe { context: unsafe {
Context::new_user_thread(entry_addr, ustack_top, kstack.top(), vm.token()) Context::new_user_thread(entry_addr, ustack_top, kstack.top(), vm.token())
@ -377,13 +383,6 @@ impl Process {
} }
self.futexes.get(&uaddr).unwrap().clone() self.futexes.get(&uaddr).unwrap().clone()
} }
pub fn clone_for_exec(&mut self, other: &Self) {
self.files = other.files.clone();
self.cwd = other.cwd.clone();
self.pid = other.pid.clone();
self.parent = other.parent.clone();
self.threads = other.threads.clone();
}
} }
trait ToMemoryAttr { trait ToMemoryAttr {

@ -143,7 +143,7 @@ pub fn sys_exec(
"exec:BEG: path: {:?}, argv: {:?}, envp: {:?}", "exec:BEG: path: {:?}, argv: {:?}, envp: {:?}",
path, argv, envp path, argv, envp
); );
let proc = process(); let mut proc = process();
let path = unsafe { proc.vm.check_and_clone_cstr(path)? }; let path = unsafe { proc.vm.check_and_clone_cstr(path)? };
let args = unsafe { proc.vm.check_and_clone_cstr_array(argv)? }; let args = unsafe { proc.vm.check_and_clone_cstr_array(argv)? };
let envs = unsafe { proc.vm.check_and_clone_cstr_array(envp)? }; let envs = unsafe { proc.vm.check_and_clone_cstr_array(envp)? };
@ -158,25 +158,29 @@ pub fn sys_exec(
path, args, envs path, args, envs
); );
// Kill other threads
proc.threads.retain(|&tid| {
if tid != processor().tid() {
processor().manager().exit(tid, 1);
}
tid == processor().tid()
});
// Read program file // Read program file
let inode = proc.lookup_inode(&path)?; let inode = proc.lookup_inode(&path)?;
let buf = inode.read_as_vec()?; let data = inode.read_as_vec()?;
// Make new Thread // Make new Thread
let mut thread = Thread::new_user(buf.as_slice(), &path, args, envs); let (mut vm, entry_addr, ustack_top) = Thread::new_user_vm(data.as_slice(), &path, args, envs);
thread.proc.lock().clone_for_exec(&proc);
// Activate new page table // Activate new page table
unsafe { unsafe {
thread.proc.lock().vm.activate(); vm.activate();
} }
core::mem::swap(&mut proc.vm, &mut vm);
// Modify the TrapFrame // Modify the TrapFrame
*tf = unsafe { thread.context.get_init_tf() }; *tf = TrapFrame::new_user_thread(entry_addr, ustack_top);
// Swap Context but keep KStack
::core::mem::swap(&mut current_thread().kstack, &mut thread.kstack);
::core::mem::swap(current_thread(), &mut *thread);
info!("exec:END: path: {:?}", path); info!("exec:END: path: {:?}", path);
Ok(0) Ok(0)

Loading…
Cancel
Save