From 7269c4477eb0b52964988dece1180deb1ff2e103 Mon Sep 17 00:00:00 2001 From: zhanghx0905 <731931282@qq.com> Date: Fri, 19 Nov 2021 18:50:59 +0800 Subject: [PATCH] update user module to 2021autumn version --- .gitignore | 14 +- os/Makefile | 4 +- os/build.rs | 24 ++- user/Cargo.toml | 4 + user/Makefile | 40 +++-- user/src/bin/00hello_world.rs | 15 -- user/src/bin/01store_fault.rs | 13 -- user/src/bin/bad_address.rs | 17 ++ user/src/bin/bad_instruction.rs | 16 ++ user/src/bin/bad_register.rs | 17 ++ user/src/bin/exit.rs | 17 ++ user/src/bin/hello_world.rs | 15 ++ user/src/bin/{02power.rs => power.rs} | 15 +- user/src/bin/test1_write0.rs | 53 ++++++ user/src/bin/test1_write1.rs | 31 ++++ user/src/console.rs | 58 ++++++- user/src/lang_items.rs | 13 +- user/src/lib.rs | 240 ++++++++++++++++++++++++-- user/src/syscall.rs | 165 +++++++++++++++++- 19 files changed, 687 insertions(+), 84 deletions(-) delete mode 100644 user/src/bin/00hello_world.rs delete mode 100644 user/src/bin/01store_fault.rs create mode 100644 user/src/bin/bad_address.rs create mode 100644 user/src/bin/bad_instruction.rs create mode 100644 user/src/bin/bad_register.rs create mode 100644 user/src/bin/exit.rs create mode 100644 user/src/bin/hello_world.rs rename user/src/bin/{02power.rs => power.rs} (63%) create mode 100644 user/src/bin/test1_write0.rs create mode 100644 user/src/bin/test1_write1.rs diff --git a/.gitignore b/.gitignore index 614368ae..896d6630 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,8 @@ -.idea/* -os/target/* -os/.idea/* -os/Cargo.lock +.idea +Cargo.lock +target os/src/link_app.S os/last-* -user/target/* -user/.idea/* -user/Cargo.lock -tools/ +user/build +tools + diff --git a/os/Makefile b/os/Makefile index 80f4e61a..7d88863c 100644 --- a/os/Makefile +++ b/os/Makefile @@ -29,6 +29,8 @@ OBJCOPY := rust-objcopy --binary-architecture=riscv64 # Disassembly DISASM ?= -x +TEST ?= 0 + build: env switch-check $(KERNEL_BIN) switch-check: @@ -48,7 +50,7 @@ $(KERNEL_BIN): kernel @$(OBJCOPY) $(KERNEL_ELF) --strip-all -O binary $@ kernel: - @cd ../user && make build + @cd ../user && make build TEST=$(TEST) @echo Platform: $(BOARD) @cp src/linker-$(BOARD).ld src/linker.ld @cargo build --release diff --git a/os/build.rs b/os/build.rs index 5e032311..4a44c565 100644 --- a/os/build.rs +++ b/os/build.rs @@ -1,5 +1,5 @@ +use std::fs::{read_dir, File}; use std::io::{Result, Write}; -use std::fs::{File, read_dir}; fn main() { println!("cargo:rerun-if-changed=../user/src/"); @@ -7,11 +7,11 @@ fn main() { insert_app_data().unwrap(); } -static TARGET_PATH: &str = "../user/target/riscv64gc-unknown-none-elf/release/"; +static TARGET_PATH: &str = "../user/build/bin/"; fn insert_app_data() -> Result<()> { let mut f = File::create("src/link_app.S").unwrap(); - let mut apps: Vec<_> = read_dir("../user/src/bin") + let mut apps: Vec<_> = read_dir("../user/build/bin/") .unwrap() .into_iter() .map(|dir_entry| { @@ -22,12 +22,16 @@ fn insert_app_data() -> Result<()> { .collect(); apps.sort(); - writeln!(f, r#" + writeln!( + f, + r#" .align 3 .section .data .global _num_app _num_app: - .quad {}"#, apps.len())?; + .quad {}"#, + apps.len() + )?; for i in 0..apps.len() { writeln!(f, r#" .quad app_{}_start"#, i)?; @@ -36,13 +40,17 @@ _num_app: for (idx, app) in apps.iter().enumerate() { println!("app_{}: {}", idx, app); - writeln!(f, r#" + writeln!( + f, + r#" .section .data .global app_{0}_start .global app_{0}_end app_{0}_start: .incbin "{2}{1}.bin" -app_{0}_end:"#, idx, app, TARGET_PATH)?; +app_{0}_end:"#, + idx, app, TARGET_PATH + )?; } Ok(()) -} \ No newline at end of file +} diff --git a/user/Cargo.toml b/user/Cargo.toml index 817ca525..01b75c29 100644 --- a/user/Cargo.toml +++ b/user/Cargo.toml @@ -7,3 +7,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +buddy_system_allocator = "0.6" +bitflags = "1.2.1" +spin = "0.9" +lazy_static = { version = "1.4.0", features = ["spin_no_std"] } diff --git a/user/Makefile b/user/Makefile index ab508d9a..005935dd 100644 --- a/user/Makefile +++ b/user/Makefile @@ -2,20 +2,38 @@ TARGET := riscv64gc-unknown-none-elf MODE := release APP_DIR := src/bin TARGET_DIR := target/$(TARGET)/$(MODE) -APPS := $(wildcard $(APP_DIR)/*.rs) -ELFS := $(patsubst $(APP_DIR)/%.rs, $(TARGET_DIR)/%, $(APPS)) -BINS := $(patsubst $(APP_DIR)/%.rs, $(TARGET_DIR)/%.bin, $(APPS)) - +BUILD_DIR := build OBJDUMP := rust-objdump --arch-name=riscv64 OBJCOPY := rust-objcopy --binary-architecture=riscv64 +PY := python3 -elf: +TEST ?= 0 +ifeq ($(TEST), 0) + APPS := $(filter-out $(wildcard $(APP_DIR)/test*.rs), $(wildcard $(APP_DIR)/*.rs)) +else + APPS := $(wildcard $(APP_DIR)/test$(TEST)*.rs) +endif +ELFS := $(patsubst $(APP_DIR)/%.rs, $(TARGET_DIR)/%, $(APPS)) + +binary: + # @echo $(ELFS) @cargo build --release - @echo $(APPS) - @echo $(ELFS) - @echo $(BINS) + @$(foreach elf, $(ELFS), \ + $(OBJCOPY) $(elf) --strip-all -O binary $(patsubst $(TARGET_DIR)/%, $(TARGET_DIR)/%.bin, $(elf)); \ + cp $(elf) $(patsubst $(TARGET_DIR)/%, $(TARGET_DIR)/%.elf, $(elf));) + +pre: + @mkdir -p $(BUILD_DIR)/bin/ + @mkdir -p $(BUILD_DIR)/elf/ + @mkdir -p $(BUILD_DIR)/app/ + @$(foreach t, $(APPS), cp $(t) $(BUILD_DIR)/app/;) + +build: clean pre binary + @$(foreach t, $(ELFS), cp $(t).bin $(BUILD_DIR)/bin/;) + @$(foreach t, $(ELFS), cp $(t).elf $(BUILD_DIR)/elf/;) -binary: elf - $(foreach elf, $(ELFS), $(OBJCOPY) $(elf) --strip-all -O binary $(patsubst $(TARGET_DIR)/%, $(TARGET_DIR)/%.bin, $(elf));) +clean: + @cargo clean + @rm -rf $(BUILD_DIR) -build: binary +.PHONY: elf binary build clean \ No newline at end of file diff --git a/user/src/bin/00hello_world.rs b/user/src/bin/00hello_world.rs deleted file mode 100644 index 242749ac..00000000 --- a/user/src/bin/00hello_world.rs +++ /dev/null @@ -1,15 +0,0 @@ -#![no_std] -#![no_main] -#![feature(asm)] - -#[macro_use] -extern crate user_lib; - -#[no_mangle] -fn main() -> i32 { - println!("Hello, world!"); - unsafe { - asm!("sret"); - } - 0 -} \ No newline at end of file diff --git a/user/src/bin/01store_fault.rs b/user/src/bin/01store_fault.rs deleted file mode 100644 index 994d8bfd..00000000 --- a/user/src/bin/01store_fault.rs +++ /dev/null @@ -1,13 +0,0 @@ -#![no_std] -#![no_main] - -#[macro_use] -extern crate user_lib; - -#[no_mangle] -fn main() -> i32 { - println!("Into Test store_fault, we will insert an invalid store operation..."); - println!("Kernel should kill this application!"); - unsafe { (0x0 as *mut u8).write_volatile(0); } - 0 -} \ No newline at end of file diff --git a/user/src/bin/bad_address.rs b/user/src/bin/bad_address.rs new file mode 100644 index 00000000..64222bf6 --- /dev/null +++ b/user/src/bin/bad_address.rs @@ -0,0 +1,17 @@ +#![no_std] +#![no_main] +#![feature(asm)] + +extern crate user_lib; + +/// 由于 rustsbi 的问题,该程序无法正确退出 +/// > rustsbi 0.2.0-alpha.1 已经修复,可以正常退出 + +#[no_mangle] +pub fn main() -> isize { + unsafe { + #[allow(clippy::zero_ptr)] + (0x0 as *mut u8).write_volatile(0); + } + panic!("FAIL: T.T\n"); +} diff --git a/user/src/bin/bad_instruction.rs b/user/src/bin/bad_instruction.rs new file mode 100644 index 00000000..cdaa171b --- /dev/null +++ b/user/src/bin/bad_instruction.rs @@ -0,0 +1,16 @@ +#![no_std] +#![no_main] +#![feature(asm)] + +extern crate user_lib; + +/// 由于 rustsbi 的问题,该程序无法正确退出 +/// > rustsbi 0.2.0-alpha.1 已经修复,可以正常退出 + +#[no_mangle] +pub fn main() -> ! { + unsafe { + asm!("sret"); + } + panic!("FAIL: T.T\n"); +} diff --git a/user/src/bin/bad_register.rs b/user/src/bin/bad_register.rs new file mode 100644 index 00000000..af1f25af --- /dev/null +++ b/user/src/bin/bad_register.rs @@ -0,0 +1,17 @@ +#![no_std] +#![no_main] +#![feature(asm)] + +extern crate user_lib; + +/// 由于 rustsbi 的问题,该程序无法正确退出 +/// > rustsbi 0.2.0-alpha.1 已经修复,可以正常退出 + +#[no_mangle] +pub fn main() -> ! { + let mut sstatus: usize; + unsafe { + asm!("csrr {}, sstatus", out(reg) sstatus); + } + panic!("(-_-) I get sstatus:{:x}\n", sstatus); +} diff --git a/user/src/bin/exit.rs b/user/src/bin/exit.rs new file mode 100644 index 00000000..420c4ba7 --- /dev/null +++ b/user/src/bin/exit.rs @@ -0,0 +1,17 @@ +#![no_std] +#![no_main] + +extern crate user_lib; +use user_lib::exit; + +/// 正确输出: 不输出 FAIL,以 1234 退出 + +const MAGIC: usize = 1234; + +#[allow(unreachable_code)] +#[no_mangle] +pub fn main() -> i32 { + exit(MAGIC as i32); + panic!("FAIL: T.T\n"); + 0 +} diff --git a/user/src/bin/hello_world.rs b/user/src/bin/hello_world.rs new file mode 100644 index 00000000..a8a3f308 --- /dev/null +++ b/user/src/bin/hello_world.rs @@ -0,0 +1,15 @@ +#![no_std] +#![no_main] +#![feature(asm)] + +#[macro_use] +extern crate user_lib; + +/// 正确输出: +/// Hello world from user mode program! + +#[no_mangle] +fn main() -> i32 { + println!("Hello, world from user mode program!"); + 0 +} diff --git a/user/src/bin/02power.rs b/user/src/bin/power.rs similarity index 63% rename from user/src/bin/02power.rs rename to user/src/bin/power.rs index 54fde244..2cc8880a 100644 --- a/user/src/bin/02power.rs +++ b/user/src/bin/power.rs @@ -4,6 +4,19 @@ #[macro_use] extern crate user_lib; +// 正确输出: +// 3^10000=5079(MOD 10007) +// 3^20000=8202(MOD 10007) +// 3^30000=8824(MOD 10007) +// 3^40000=5750(MOD 10007) +// 3^50000=3824(MOD 10007) +// 3^60000=8516(MOD 10007) +// 3^70000=2510(MOD 10007) +// 3^80000=9379(MOD 10007) +// 3^90000=2621(MOD 10007) +// 3^100000=2749(MOD 10007) +// Test power OK! + const SIZE: usize = 10; const P: u32 = 3; const STEP: usize = 100000; @@ -24,4 +37,4 @@ fn main() -> i32 { } println!("Test power OK!"); 0 -} \ No newline at end of file +} diff --git a/user/src/bin/test1_write0.rs b/user/src/bin/test1_write0.rs new file mode 100644 index 00000000..c4a77cca --- /dev/null +++ b/user/src/bin/test1_write0.rs @@ -0,0 +1,53 @@ +#![no_std] +#![no_main] +#![feature(asm)] + +#[macro_use] +extern crate user_lib; +extern crate core; +use core::slice; +use user_lib::{write, STDOUT}; + +/// 正确输出: +/// Test write0 OK! + +const STACK_SIZE: usize = 0x1000; + +unsafe fn r_sp() -> usize { + let mut sp: usize; + asm!("mv {}, sp", out(reg) sp); + sp +} + +unsafe fn stack_range() -> (usize, usize) { + let sp = r_sp(); + let top = (sp + STACK_SIZE - 1) & (!(STACK_SIZE - 1)); + (top - STACK_SIZE, top) +} + +#[no_mangle] +pub fn main() -> i32 { + assert_eq!( + write(STDOUT, unsafe { + #[allow(clippy::zero_ptr)] + slice::from_raw_parts(0x0 as *const _, 10) + }), + -1 + ); + let (bottom, top) = unsafe { stack_range() }; + assert_eq!( + write(STDOUT, unsafe { + slice::from_raw_parts((top - 5) as *const _, 10) + }), + -1 + ); + assert_eq!( + write(STDOUT, unsafe { + slice::from_raw_parts((bottom - 5) as *const _, 10) + }), + -1 + ); + // TODO: test string located in .data section + println!("Test write0 OK!"); + 0 +} diff --git a/user/src/bin/test1_write1.rs b/user/src/bin/test1_write1.rs new file mode 100644 index 00000000..276ad9c8 --- /dev/null +++ b/user/src/bin/test1_write1.rs @@ -0,0 +1,31 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; +use user_lib::{write, STDOUT}; +const DATA_STRING: &str = "string from data section\n"; + +/// 正确输出: +/// string from data section +/// strinstring from stack section +/// strin +/// Test write1 OK! + +#[no_mangle] +pub fn main() -> i32 { + assert_eq!(write(1234, DATA_STRING.as_bytes()), -1); + assert_eq!( + write(STDOUT, DATA_STRING.as_bytes()), + DATA_STRING.len() as isize + ); + assert_eq!(write(STDOUT, &DATA_STRING.as_bytes()[..5]), 5); + let stack_string = "string from stack section\n"; + assert_eq!( + write(STDOUT, stack_string.as_bytes()), + stack_string.len() as isize + ); + assert_eq!(write(STDOUT, &stack_string.as_bytes()[..5]), 5); + println!("\nTest write1 OK!"); + 0 +} diff --git a/user/src/console.rs b/user/src/console.rs index ac801174..6d6d1f3a 100644 --- a/user/src/console.rs +++ b/user/src/console.rs @@ -1,19 +1,52 @@ +use alloc::collections::vec_deque::VecDeque; +use alloc::sync::Arc; use core::fmt::{self, Write}; -use super::write; +use spin::mutex::Mutex; -struct Stdout; +pub const STDIN: usize = 0; +pub const STDOUT: usize = 1; -const STDOUT: usize = 1; +const CONSOLE_BUFFER_SIZE: usize = 256 * 10; -impl Write for Stdout { +use super::{read, write}; +use lazy_static::*; + +struct ConsoleBuffer(VecDeque); + +lazy_static! { + static ref CONSOLE_BUFFER: Arc> = { + let buffer = VecDeque::::with_capacity(CONSOLE_BUFFER_SIZE); + Arc::new(Mutex::new(ConsoleBuffer(buffer))) + }; +} + +impl ConsoleBuffer { + fn flush(&mut self) -> isize { + let s: &[u8] = self.0.make_contiguous(); + let ret = write(STDOUT, s); + self.0.clear(); + ret + } +} + +impl Write for ConsoleBuffer { fn write_str(&mut self, s: &str) -> fmt::Result { - write(STDOUT, s.as_bytes()); + for c in s.as_bytes().iter() { + self.0.push_back(*c); + if (*c == b'\n' || self.0.len() == CONSOLE_BUFFER_SIZE) && -1 == self.flush() { + return Err(fmt::Error); + } + } Ok(()) } } +#[allow(unused)] pub fn print(args: fmt::Arguments) { - Stdout.write_fmt(args).unwrap(); + let mut buf = CONSOLE_BUFFER.lock(); + // buf.write_fmt(args).unwrap(); + // BUG FIX: 关闭 stdout 后,本函数不能触发 panic,否则会造成死锁 + buf.write_fmt(args); } #[macro_export] @@ -28,4 +61,15 @@ macro_rules! println { ($fmt: literal $(, $($arg: tt)+)?) => { $crate::console::print(format_args!(concat!($fmt, "\n") $(, $($arg)+)?)); } -} \ No newline at end of file +} + +pub fn getchar() -> u8 { + let mut c = [0u8; 1]; + read(STDIN, &mut c); + c[0] +} + +pub fn flush() { + let mut buf = CONSOLE_BUFFER.lock(); + buf.flush(); +} diff --git a/user/src/lang_items.rs b/user/src/lang_items.rs index c90d297f..2d81a1df 100644 --- a/user/src/lang_items.rs +++ b/user/src/lang_items.rs @@ -1,10 +1,17 @@ +use crate::exit; + #[panic_handler] fn panic_handler(panic_info: &core::panic::PanicInfo) -> ! { let err = panic_info.message().unwrap(); if let Some(location) = panic_info.location() { - println!("Panicked at {}:{}, {}", location.file(), location.line(), err); + println!( + "Panicked at {}:{}, {}", + location.file(), + location.line(), + err + ); } else { println!("Panicked: {}", err); } - loop {} -} \ No newline at end of file + exit(-1); +} diff --git a/user/src/lib.rs b/user/src/lib.rs index c06f9245..a1eda04f 100644 --- a/user/src/lib.rs +++ b/user/src/lib.rs @@ -2,18 +2,57 @@ #![feature(asm)] #![feature(linkage)] #![feature(panic_info_message)] +#![feature(alloc_error_handler)] #[macro_use] pub mod console; -mod syscall; mod lang_items; +mod syscall; + +extern crate alloc; +extern crate core; +#[macro_use] +extern crate bitflags; + +use buddy_system_allocator::LockedHeap; +pub use console::{flush, STDIN, STDOUT}; +pub use syscall::*; + +const USER_HEAP_SIZE: usize = 16384; + +static mut HEAP_SPACE: [u8; USER_HEAP_SIZE] = [0; USER_HEAP_SIZE]; + +#[global_allocator] +static HEAP: LockedHeap = LockedHeap::empty(); + +#[alloc_error_handler] +pub fn handle_alloc_error(layout: core::alloc::Layout) -> ! { + panic!("Heap allocation error, layout = {:?}", layout); +} + +fn clear_bss() { + extern "C" { + fn start_bss(); + fn end_bss(); + } + unsafe { + core::slice::from_raw_parts_mut( + start_bss as usize as *mut u8, + end_bss as usize - start_bss as usize, + ) + .fill(0); + } +} #[no_mangle] #[link_section = ".text.entry"] pub extern "C" fn _start() -> ! { clear_bss(); + unsafe { + HEAP.lock() + .init(HEAP_SPACE.as_ptr() as usize, USER_HEAP_SIZE); + } exit(main()); - panic!("unreachable after sys_exit!"); } #[linkage = "weak"] @@ -22,17 +61,194 @@ fn main() -> i32 { panic!("Cannot find main!"); } -fn clear_bss() { - extern "C" { - fn start_bss(); - fn end_bss(); +bitflags! { + pub struct OpenFlags: u32 { + const RDONLY = 0; + const WRONLY = 1 << 0; + const RDWR = 1 << 1; + const CREATE = 1 << 9; + const TRUNC = 1 << 10; + } +} + +#[repr(C)] +#[derive(Debug, Default)] +pub struct TimeVal { + pub sec: usize, + pub usec: usize, +} + +impl TimeVal { + pub fn new() -> Self { + Self::default() + } +} + +#[repr(C)] +#[derive(Debug)] +pub struct Stat { + /// ID of device containing file + pub dev: u64, + /// inode number + pub ino: u64, + /// file type and mode + pub mode: StatMode, + /// number of hard links + pub nlink: u32, + /// unused pad + pad: [u64; 7], +} + +impl Stat { + pub fn new() -> Self { + Stat { + dev: 0, + ino: 0, + mode: StatMode::NULL, + nlink: 0, + pad: [0; 7], + } + } +} + +impl Default for Stat { + fn default() -> Self { + Self::new() + } +} + +bitflags! { + pub struct StatMode: u32 { + const NULL = 0; + /// directory + const DIR = 0o040000; + /// ordinary regular file + const FILE = 0o100000; + } +} + +const AT_FDCWD: isize = -100; + +pub fn open(path: &str, flags: OpenFlags) -> isize { + sys_openat(AT_FDCWD as usize, path, flags.bits, OpenFlags::RDWR.bits) +} + +pub fn close(fd: usize) -> isize { + if fd == STDOUT { + console::flush(); } - (start_bss as usize..end_bss as usize).for_each(|addr| { - unsafe { (addr as *mut u8).write_volatile(0); } - }); + sys_close(fd) } -use syscall::*; +pub fn read(fd: usize, buf: &mut [u8]) -> isize { + sys_read(fd, buf) +} + +pub fn write(fd: usize, buf: &[u8]) -> isize { + sys_write(fd, buf) +} + +pub fn link(old_path: &str, new_path: &str) -> isize { + sys_linkat(AT_FDCWD as usize, old_path, AT_FDCWD as usize, new_path, 0) +} + +pub fn unlink(path: &str) -> isize { + sys_unlinkat(AT_FDCWD as usize, path, 0) +} + +pub fn fstat(fd: usize, st: &Stat) -> isize { + sys_fstat(fd, st) +} -pub fn write(fd: usize, buf: &[u8]) -> isize { sys_write(fd, buf) } -pub fn exit(exit_code: i32) -> isize { sys_exit(exit_code) } \ No newline at end of file +pub fn mail_read(buf: &mut [u8]) -> isize { + sys_mail_read(buf) +} + +pub fn mail_write(pid: usize, buf: &[u8]) -> isize { + sys_mail_write(pid, buf) +} + +pub fn exit(exit_code: i32) -> ! { + console::flush(); + sys_exit(exit_code); +} + +pub fn yield_() -> isize { + sys_yield() +} + +pub fn get_time() -> isize { + let time = TimeVal::new(); + match sys_get_time(&time, 0) { + 0 => ((time.sec & 0xffff) * 1000 + time.usec / 1000) as isize, + _ => -1, + } +} + +pub fn getpid() -> isize { + sys_getpid() +} + +pub fn fork() -> isize { + sys_fork() +} + +pub fn exec(path: &str) -> isize { + sys_exec(path) +} + +pub fn set_priority(prio: isize) -> isize { + sys_set_priority(prio) +} + +pub fn wait(exit_code: &mut i32) -> isize { + loop { + match sys_waitpid(-1, exit_code as *mut _) { + -2 => { + sys_yield(); + } + n => { + return n; + } + } + } +} + +pub fn waitpid(pid: usize, exit_code: &mut i32) -> isize { + loop { + match sys_waitpid(pid as isize, exit_code as *mut _) { + -2 => { + sys_yield(); + } + n => { + return n; + } + } + } +} + +pub fn sleep(period_ms: usize) { + let start = get_time(); + while get_time() < start + period_ms as isize { + sys_yield(); + } +} + +pub fn mmap(start: usize, len: usize, prot: usize) -> isize { + sys_mmap(start, len, prot) +} + +pub fn munmap(start: usize, len: usize) -> isize { + sys_munmap(start, len) +} + +pub fn spawn(path: &str) -> isize { + sys_spawn(path) +} + +pub fn dup(fd: usize) -> isize { + sys_dup(fd) +} +pub fn pipe(pipe_fd: &mut [usize]) -> isize { + sys_pipe(pipe_fd) +} diff --git a/user/src/syscall.rs b/user/src/syscall.rs index bb7582f2..7aaa584e 100644 --- a/user/src/syscall.rs +++ b/user/src/syscall.rs @@ -1,7 +1,43 @@ -const SYSCALL_WRITE: usize = 64; -const SYSCALL_EXIT: usize = 93; +use super::{Stat, TimeVal}; -fn syscall(id: usize, args: [usize; 3]) -> isize { +pub const SYSCALL_OPENAT: usize = 56; +pub const SYSCALL_CLOSE: usize = 57; +pub const SYSCALL_READ: usize = 63; +pub const SYSCALL_WRITE: usize = 64; +pub const SYSCALL_UNLINKAT: usize = 35; +pub const SYSCALL_LINKAT: usize = 37; +pub const SYSCALL_FSTAT: usize = 80; +pub const SYSCALL_EXIT: usize = 93; +pub const SYSCALL_YIELD: usize = 124; +pub const SYSCALL_GETTIMEOFDAY: usize = 169; +pub const SYSCALL_GETPID: usize = 172; +pub const SYSCALL_FORK: usize = 220; +pub const SYSCALL_EXEC: usize = 221; +pub const SYSCALL_WAITPID: usize = 260; +pub const SYSCALL_SET_PRIORITY: usize = 140; +pub const SYSCALL_MUNMAP: usize = 215; +pub const SYSCALL_MMAP: usize = 222; +pub const SYSCALL_SPAWN: usize = 400; +pub const SYSCALL_MAIL_READ: usize = 401; +pub const SYSCALL_MAIL_WRITE: usize = 402; +pub const SYSCALL_DUP: usize = 24; +pub const SYSCALL_PIPE: usize = 59; + +pub fn syscall(id: usize, args: [usize; 3]) -> isize { + let mut ret: isize; + unsafe { + asm!( + "ecall", + inlateout("x10") args[0] => ret, + in("x11") args[1], + in("x12") args[2], + in("x17") id + ); + } + ret +} + +pub fn syscall6(id: usize, args: [usize; 6]) -> isize { let mut ret: isize; unsafe { asm!( @@ -9,16 +45,135 @@ fn syscall(id: usize, args: [usize; 3]) -> isize { inlateout("x10") args[0] => ret, in("x11") args[1], in("x12") args[2], + in("x13") args[3], + in("x14") args[4], + in("x15") args[5], in("x17") id ); } ret } +pub fn sys_openat(dirfd: usize, path: &str, flags: u32, mode: u32) -> isize { + syscall6( + SYSCALL_OPENAT, + [ + dirfd, + path.as_ptr() as usize, + flags as usize, + mode as usize, + 0, + 0, + ], + ) +} + +pub fn sys_close(fd: usize) -> isize { + syscall(SYSCALL_CLOSE, [fd, 0, 0]) +} + +pub fn sys_read(fd: usize, buffer: &mut [u8]) -> isize { + syscall( + SYSCALL_READ, + [fd, buffer.as_mut_ptr() as usize, buffer.len()], + ) +} + pub fn sys_write(fd: usize, buffer: &[u8]) -> isize { syscall(SYSCALL_WRITE, [fd, buffer.as_ptr() as usize, buffer.len()]) } -pub fn sys_exit(exit_code: i32) -> isize { - syscall(SYSCALL_EXIT, [exit_code as usize, 0, 0]) +pub fn sys_linkat( + old_dirfd: usize, + old_path: &str, + new_dirfd: usize, + new_path: &str, + flags: usize, +) -> isize { + syscall6( + SYSCALL_LINKAT, + [ + old_dirfd, + old_path.as_ptr() as usize, + new_dirfd, + new_path.as_ptr() as usize, + flags, + 0, + ], + ) +} + +pub fn sys_unlinkat(dirfd: usize, path: &str, flags: usize) -> isize { + syscall(SYSCALL_UNLINKAT, [dirfd, path.as_ptr() as usize, flags]) +} + +pub fn sys_fstat(fd: usize, st: &Stat) -> isize { + syscall(SYSCALL_FSTAT, [fd, st as *const _ as usize, 0]) +} + +pub fn sys_mail_read(buffer: &mut [u8]) -> isize { + syscall( + SYSCALL_MAIL_READ, + [buffer.as_ptr() as usize, buffer.len(), 0], + ) +} + +pub fn sys_mail_write(pid: usize, buffer: &[u8]) -> isize { + syscall( + SYSCALL_MAIL_WRITE, + [pid, buffer.as_ptr() as usize, buffer.len()], + ) +} + +pub fn sys_exit(exit_code: i32) -> ! { + syscall(SYSCALL_EXIT, [exit_code as usize, 0, 0]); + panic!("sys_exit never returns!"); +} + +pub fn sys_yield() -> isize { + syscall(SYSCALL_YIELD, [0, 0, 0]) +} + +pub fn sys_get_time(time: &TimeVal, tz: usize) -> isize { + syscall(SYSCALL_GETTIMEOFDAY, [time as *const _ as usize, tz, 0]) +} + +pub fn sys_getpid() -> isize { + syscall(SYSCALL_GETPID, [0, 0, 0]) +} + +pub fn sys_fork() -> isize { + syscall(SYSCALL_FORK, [0, 0, 0]) +} + +pub fn sys_exec(path: &str) -> isize { + syscall(SYSCALL_EXEC, [path.as_ptr() as usize, 0, 0]) +} + +pub fn sys_waitpid(pid: isize, xstatus: *mut i32) -> isize { + syscall(SYSCALL_WAITPID, [pid as usize, xstatus as usize, 0]) +} + +pub fn sys_set_priority(prio: isize) -> isize { + syscall(SYSCALL_SET_PRIORITY, [prio as usize, 0, 0]) +} + +pub fn sys_mmap(start: usize, len: usize, prot: usize) -> isize { + syscall(SYSCALL_MMAP, [start, len, prot]) +} + +pub fn sys_munmap(start: usize, len: usize) -> isize { + syscall(SYSCALL_MUNMAP, [start, len, 0]) +} + +pub fn sys_spawn(path: &str) -> isize { + syscall(SYSCALL_SPAWN, [path.as_ptr() as usize, 0, 0]) +} + +pub fn sys_dup(fd: usize) -> isize { + syscall(SYSCALL_DUP, [fd, 0, 0]) +} + +pub fn sys_pipe(pipe: &mut [usize]) -> isize { + syscall(SYSCALL_PIPE, [pipe.as_mut_ptr() as usize, 0, 0]) }