uCore `hello` is available!

master
WangRunji 7 years ago
parent 8c64b2abb2
commit 893658baf8

@ -58,7 +58,7 @@ static mut TSS_PTR: Unique<TaskStateSegment> = unsafe{ Unique::new_unchecked(0 a
/// ///
/// 每次进入用户态前,都要调用此函数,才能保证正确返回内核态 /// 每次进入用户态前,都要调用此函数,才能保证正确返回内核态
pub fn set_ring0_rsp(rsp: usize) { pub fn set_ring0_rsp(rsp: usize) {
debug!("gdt.set_ring0_rsp: {:#x}", rsp); // debug!("gdt.set_ring0_rsp: {:#x}", rsp);
unsafe { unsafe {
TSS_PTR.as_mut().privilege_stack_table[0] = VirtualAddress(rsp); TSS_PTR.as_mut().privilege_stack_table[0] = VirtualAddress(rsp);
// debug!("TSS:\n{:?}", TSS_PTR.as_ref()); // debug!("TSS:\n{:?}", TSS_PTR.as_ref());

@ -75,7 +75,7 @@ use spin::Mutex;
// FIXME: Deadlock // FIXME: Deadlock
//static TICK: Mutex<usize> = Mutex::new(0); //static TICK: Mutex<usize> = Mutex::new(0);
interrupt_switch!(timer, rsp, { interrupt_switch!(timer, stack, rsp, {
// let mut tick = TICK.lock(); // let mut tick = TICK.lock();
// *tick += 1; // *tick += 1;
// let tick = *tick; // let tick = *tick;
@ -107,16 +107,16 @@ interrupt_stack_p!(to_kernel, stack, {
stack.iret.ss = gdt::KDATA_SELECTOR.0 as usize; stack.iret.ss = gdt::KDATA_SELECTOR.0 as usize;
}); });
interrupt_stack_p!(syscall, stack, { interrupt_switch!(syscall, stack, rsp, {
println!("\nInterupt: Syscall {:#x?}", stack.scratch.rax); println!("\nInterupt: Syscall {:#x?}", stack.scratch.rax);
use syscall::syscall; use syscall::syscall;
let ret = syscall(stack, false); let ret = syscall(stack, rsp, false);
stack.scratch.rax = ret as usize; stack.scratch.rax = ret as usize;
}); });
interrupt_stack_p!(syscall32, stack, { interrupt_switch!(syscall32, stack, rsp, {
println!("\nInterupt: Syscall {:#x?}", stack.scratch.rax); // println!("\nInterupt: Syscall {:#x?}", stack.scratch.rax);
use syscall::syscall; use syscall::syscall;
let ret = syscall(stack, true); let ret = syscall(stack, rsp, true);
stack.scratch.rax = ret as usize; stack.scratch.rax = ret as usize;
}); });

@ -315,11 +315,11 @@ impl Debug for InterruptStackP {
} }
macro_rules! interrupt_switch { macro_rules! interrupt_switch {
($name:ident, $rsp: ident, $func:block) => { ($name:ident, $stack: ident, $rsp: ident, $func:block) => {
#[naked] #[naked]
pub unsafe extern fn $name () { pub unsafe extern fn $name () {
#[inline(never)] #[inline(never)]
unsafe fn inner($rsp: &mut usize) { unsafe fn inner($stack: &mut InterruptStackP, $rsp: &mut usize) {
$func $func
} }
@ -333,7 +333,7 @@ macro_rules! interrupt_switch {
asm!("" : "={rsp}"(rsp) : : : "intel", "volatile"); asm!("" : "={rsp}"(rsp) : : : "intel", "volatile");
// Call inner rust function // Call inner rust function
inner(&mut rsp); inner(&mut *(rsp as *mut InterruptStackP), &mut rsp);
// Set return rsp if to user // Set return rsp if to user
use arch::gdt; use arch::gdt;

@ -26,7 +26,7 @@ pub const MAX_CPU_NUM: usize = 8;
pub const KERNEL_HEAP_OFFSET: usize = KERNEL_OFFSET - PML4_SIZE; pub const KERNEL_HEAP_OFFSET: usize = KERNEL_OFFSET - PML4_SIZE;
pub const KERNEL_HEAP_PML4: usize = (KERNEL_HEAP_OFFSET & PML4_MASK)/PML4_SIZE; pub const KERNEL_HEAP_PML4: usize = (KERNEL_HEAP_OFFSET & PML4_MASK)/PML4_SIZE;
/// Size of kernel heap /// Size of kernel heap
pub const KERNEL_HEAP_SIZE: usize = 2 * 1024 * 1024; // 1 MB pub const KERNEL_HEAP_SIZE: usize = 8 * 1024 * 1024; // 8 MB
/// Offset to kernel percpu variables /// Offset to kernel percpu variables
//TODO: Use 64-bit fs offset to enable this pub const KERNEL_PERCPU_OFFSET: usize = KERNEL_HEAP_OFFSET - PML4_SIZE; //TODO: Use 64-bit fs offset to enable this pub const KERNEL_PERCPU_OFFSET: usize = KERNEL_HEAP_OFFSET - PML4_SIZE;

@ -49,10 +49,32 @@ pub fn debug(args: fmt::Arguments) {
print_in_color(args, Color::LightRed); print_in_color(args, Color::LightRed);
} }
pub fn write(fd: usize, base: *const u8, len: usize) { pub fn write(fd: usize, base: *const u8, len: usize) -> i32 {
// debug!("write: fd: {}, base: {:?}, len: {:#x}", fd, base, len); debug!("write: fd: {}, base: {:?}, len: {:#x}", fd, base, len);
use core::slice; use core::slice;
use core::str; use core::str;
let slice = unsafe { slice::from_raw_parts(base, len) }; let slice = unsafe { slice::from_raw_parts(base, len) };
print!("{}", str::from_utf8(slice).unwrap()); print!("{}", str::from_utf8(slice).unwrap());
0
}
pub fn open(path: *const u8, flags: usize) -> i32 {
let path = unsafe { from_cstr(path) };
debug!("open: path: {:?}, flags: {:?}", path, flags);
match path {
"stdin:" => 0,
"stdout:" => 1,
_ => -1,
}
}
pub fn close(fd: usize) -> i32 {
debug!("close: fd: {:?}", fd);
0
}
pub unsafe fn from_cstr(s: *const u8) -> &'static str {
use core::{str, slice};
let len = (0usize..).find(|&i| *s.offset(i as isize) == 0).unwrap();
str::from_utf8(slice::from_raw_parts(s, len)).unwrap()
} }

@ -76,6 +76,27 @@ extern fn idle_thread() {
} }
/// Fork the current process /// Fork the current process
pub fn fork(tf: &TrapFrame) { pub fn sys_fork(tf: &TrapFrame) -> i32 {
PROCESSOR.try().unwrap().lock().fork(tf); PROCESSOR.try().unwrap().lock().fork(tf);
0
}
/// Kill the process
pub fn sys_kill(pid: usize) -> i32 {
PROCESSOR.try().unwrap().lock().kill(pid);
0
}
/// Get the current process id
pub fn sys_getpid() -> i32 {
PROCESSOR.try().unwrap().lock().current().pid as i32
}
/// Exit the current process
pub fn sys_exit(rsp: &mut usize, error_code: usize) -> i32 {
let mut processor = PROCESSOR.try().unwrap().lock();
let pid = processor.current().pid;
processor.schedule(rsp);
processor.exit(pid, error_code);
0
} }

@ -19,7 +19,7 @@ pub struct Process {
pub type Pid = usize; pub type Pid = usize;
#[derive(Debug)] #[derive(Debug, Eq, PartialEq)]
pub enum Status { pub enum Status {
Ready, Running, Sleeping(usize), Exited Ready, Running, Sleeping(usize), Exited
} }

@ -43,7 +43,8 @@ impl Processor {
fn find_next(&self) -> Pid { fn find_next(&self) -> Pid {
*self.procs.keys() *self.procs.keys()
.find(|&&i| i > self.current_pid) .find(|&&i| i > self.current_pid
&& self.get(i).status != Status::Exited)
.unwrap_or(self.procs.keys().nth(0).unwrap()) .unwrap_or(self.procs.keys().nth(0).unwrap())
} }
@ -76,8 +77,12 @@ impl Processor {
debug!("Processor: switch from {} to {}\n rsp: {:#x} -> {:#x}", pid0, pid, rsp0, rsp); debug!("Processor: switch from {} to {}\n rsp: {:#x} -> {:#x}", pid0, pid, rsp0, rsp);
} }
fn get(&self, pid: Pid) -> &Process {
self.procs.get(&pid).unwrap()
}
pub fn current(&self) -> &Process { pub fn current(&self) -> &Process {
self.procs.get(&self.current_pid).unwrap() self.get(self.current_pid)
} }
/// Fork the current process /// Fork the current process
@ -85,4 +90,15 @@ impl Processor {
let new = self.current().fork(tf, &mut self.mc.borrow_mut()); let new = self.current().fork(tf, &mut self.mc.borrow_mut());
self.add(new); self.add(new);
} }
pub fn kill(&mut self, pid: Pid) {
let process = self.procs.get_mut(&pid).unwrap();
process.status = Status::Exited;
// TODO: Remove process from set
}
pub fn exit(&mut self, pid: Pid, error_code: usize) {
debug!("Processor: {} exit, code: {}", pid, error_code);
self.kill(pid);
}
} }

@ -2,16 +2,10 @@ use super::*;
use process; use process;
use arch::interrupt::TrapFrame; use arch::interrupt::TrapFrame;
pub unsafe fn syscall(tf: &TrapFrame, is32: bool) -> i32 { pub unsafe fn syscall(tf: &TrapFrame, rsp: &mut usize, is32: bool) -> i32 {
let id = match is32 { let id = match is32 {
false => tf.scratch.rax, false => Syscall::Xv6(tf.scratch.rax),
true => match tf.scratch.rax { true => Syscall::Ucore(tf.scratch.rax),
UCORE_SYS_OPEN => SYS_OPEN,
UCORE_SYS_CLOSE => SYS_CLOSE,
UCORE_SYS_WRITE => SYS_WRITE,
UCORE_SYS_READ => SYS_READ,
_ => 0,
}
}; };
let args = match is32 { let args = match is32 {
// For ucore x86 // For ucore x86
@ -19,22 +13,38 @@ pub unsafe fn syscall(tf: &TrapFrame, is32: bool) -> i32 {
// For xv6 x86_64 // For xv6 x86_64
false => [tf.scratch.rdi, tf.scratch.rsi, tf.scratch.rdx, tf.scratch.rcx, tf.scratch.r8, tf.scratch.r9], false => [tf.scratch.rdi, tf.scratch.rsi, tf.scratch.rdx, tf.scratch.rcx, tf.scratch.r8, tf.scratch.r9],
}; };
debug!("id: {:#x}, args: {:#x?}", id, args);
match id { match id {
SYS_FORK => { Syscall::Xv6(SYS_WRITE) | Syscall::Ucore(UCORE_SYS_WRITE) =>
process::fork(tf); io::write(args[0], args[1] as *const u8, args[2]),
0 Syscall::Xv6(SYS_OPEN) | Syscall::Ucore(UCORE_SYS_OPEN) =>
} io::open(args[0] as *const u8, args[1]),
SYS_WRITE => { Syscall::Xv6(SYS_CLOSE) | Syscall::Ucore(UCORE_SYS_CLOSE) =>
io::write(args[0], args[1] as *const u8, args[2]); io::close(args[0]),
Syscall::Xv6(SYS_FORK) | Syscall::Ucore(UCORE_SYS_FORK) =>
process::sys_fork(tf),
Syscall::Xv6(SYS_KILL) | Syscall::Ucore(UCORE_SYS_KILL) =>
process::sys_kill(args[0]),
Syscall::Xv6(SYS_EXIT) | Syscall::Ucore(UCORE_SYS_EXIT) =>
process::sys_exit(rsp, args[0]),
Syscall::Ucore(UCORE_SYS_GETPID) =>
process::sys_getpid(),
Syscall::Ucore(UCORE_SYS_PUTC) =>
{
print!("{}", args[0] as u8 as char);
0 0
} },
_ => { _ => {
debug!("unknown syscall {:#x}", id); debug!("unknown syscall {:#x?}", id);
-1 -1
},
} }
} }
#[derive(Debug)]
enum Syscall {
Xv6(usize),
Ucore(usize),
} }
const SYS_FORK: usize = 1; const SYS_FORK: usize = 1;

Loading…
Cancel
Save