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
}
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;
let mut tf: Self = unsafe { zeroed() };
tf.sp = sp;
@ -40,9 +40,6 @@ impl TrapFrame {
tf.spsr = 0b1101_00_0000; // To EL 0, enable IRQ
tf
}
pub fn is_user(&self) -> bool {
unimplemented!()
}
}
/// 新线程的内核栈初始内容
@ -201,11 +198,6 @@ impl Context {
}
.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;

@ -76,7 +76,7 @@ impl TrapFrame {
///
/// The new thread starts at `entry_addr`.
/// 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;
let mut tf: Self = unsafe { zeroed() };
tf.sp = sp;
@ -269,9 +269,4 @@ impl Context {
}
.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 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;
let mut tf: Self = unsafe { zeroed() };
tf.x[2] = sp;
@ -289,9 +289,4 @@ impl Context {
}
.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
}
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;
let mut tf = TrapFrame::default();
tf.cs = gdt::UCODE_SELECTOR.0 as usize;
@ -234,9 +234,4 @@ impl Context {
}
.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`
pub fn new_user(
/// Construct virtual memory of a new user process from ELF `data`.
/// Return `(MemorySet, entry_point, ustack_top)`
pub fn new_user_vm(
data: &[u8],
exec_path: &str,
mut args: Vec<String>,
envs: Vec<String>,
) -> Box<Thread> {
) -> (MemorySet, usize, usize) {
// Parse ELF
let elf = ElfFile::new(data).expect("failed to read elf");
@ -159,22 +160,16 @@ impl Thread {
// Check interpreter (for dynamic link)
if let Ok(loader_path) = elf.get_interpreter() {
// assuming absolute path
if let Ok(inode) = crate::fs::ROOT_INODE.lookup_follow(loader_path, FOLLOW_MAX_DEPTH) {
if let Ok(buf) = inode.read_as_vec() {
// Elf loader should not have INTERP
// No infinite loop
args.insert(0, loader_path.into());
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);
}
let inode = crate::fs::ROOT_INODE
.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
// No infinite loop
return Thread::new_user_vm(buf.as_slice(), exec_path, args, envs);
}
// Make page table
@ -216,6 +211,19 @@ impl Thread {
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 mut files = BTreeMap::new();
@ -253,8 +261,6 @@ impl Thread {
)),
);
let entry_addr = elf.header.pt2.entry_point() as usize;
Box::new(Thread {
context: unsafe {
Context::new_user_thread(entry_addr, ustack_top, kstack.top(), vm.token())
@ -377,13 +383,6 @@ impl Process {
}
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 {

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

Loading…
Cancel
Save