diff --git a/.cargo/config.toml b/os/.cargo/config.toml similarity index 100% rename from .cargo/config.toml rename to os/.cargo/config.toml diff --git a/.gitignore b/os/.gitignore similarity index 100% rename from .gitignore rename to os/.gitignore diff --git a/Cargo.lock b/os/Cargo.lock similarity index 100% rename from Cargo.lock rename to os/Cargo.lock diff --git a/Cargo.toml b/os/Cargo.toml similarity index 100% rename from Cargo.toml rename to os/Cargo.toml diff --git a/src/console.rs b/os/src/console.rs similarity index 100% rename from src/console.rs rename to os/src/console.rs diff --git a/src/entry.asm b/os/src/entry.asm similarity index 100% rename from src/entry.asm rename to os/src/entry.asm diff --git a/src/lang_items.rs b/os/src/lang_items.rs similarity index 73% rename from src/lang_items.rs rename to os/src/lang_items.rs index 749fc53..482328e 100644 --- a/src/lang_items.rs +++ b/os/src/lang_items.rs @@ -3,15 +3,16 @@ use crate::{sbi, println}; #[panic_handler] fn panic(info: &PanicInfo) -> ! { + let err = info.message().as_str().unwrap(); if let Some(location) = info.location() { println!( "Panicked at {}:{} {}", location.file(), location.line(), - info.message().as_str().unwrap() + err ); } else { - println!("Panicked: {}", info.message().as_str().unwrap()); + println!("Panicked: {}", err); } sbi::shutdown(true) } \ No newline at end of file diff --git a/src/linker.ld b/os/src/linker.ld similarity index 100% rename from src/linker.ld rename to os/src/linker.ld diff --git a/src/logger.rs b/os/src/logger.rs similarity index 100% rename from src/logger.rs rename to os/src/logger.rs diff --git a/src/main.rs b/os/src/main.rs similarity index 100% rename from src/main.rs rename to os/src/main.rs diff --git a/src/sbi.rs b/os/src/sbi.rs similarity index 100% rename from src/sbi.rs rename to os/src/sbi.rs diff --git a/user/.cargo/config.toml b/user/.cargo/config.toml new file mode 100644 index 0000000..6ddcd53 --- /dev/null +++ b/user/.cargo/config.toml @@ -0,0 +1,7 @@ +[build] +target = "riscv64gc-unknown-none-elf" + +[target.riscv64gc-unknown-none-elf] +rustflags = [ + "-Clink-arg=-Tsrc/linker.ld", "-Cforce-frame-pointers=yes" +] \ No newline at end of file diff --git a/user/.gitignore b/user/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/user/.gitignore @@ -0,0 +1 @@ +/target diff --git a/user/Cargo.lock b/user/Cargo.lock new file mode 100644 index 0000000..287fb7a --- /dev/null +++ b/user/Cargo.lock @@ -0,0 +1,93 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "proc-macro2" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "riscv" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ea8ff73d3720bdd0a97925f0bf79ad2744b6da8ff36be3840c48ac81191d7a7" +dependencies = [ + "critical-section", + "embedded-hal", + "paste", + "riscv-macros", + "riscv-pac", +] + +[[package]] +name = "riscv-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f265be5d634272320a7de94cea15c22a3bfdd4eb42eb43edc528415f066a1f25" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "riscv-pac" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8188909339ccc0c68cfb5a04648313f09621e8b87dc03095454f1a11f6c5d436" + +[[package]] +name = "syn" +version = "2.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "user_lib" +version = "0.1.0" +dependencies = [ + "riscv", +] diff --git a/user/Cargo.toml b/user/Cargo.toml new file mode 100644 index 0000000..534e542 --- /dev/null +++ b/user/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "user_lib" +version = "0.1.0" +edition = "2021" + +[dependencies] +riscv = "0.12.1" diff --git a/user/src/bin/00_hello_world.rs b/user/src/bin/00_hello_world.rs new file mode 100644 index 0000000..684396a --- /dev/null +++ b/user/src/bin/00_hello_world.rs @@ -0,0 +1,11 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; + +#[no_mangle] +fn main() -> i32 { + println!("Hello, world!"); + 0 +} \ No newline at end of file diff --git a/user/src/bin/01_store_fault.rs b/user/src/bin/01_store_fault.rs new file mode 100644 index 0000000..855f285 --- /dev/null +++ b/user/src/bin/01_store_fault.rs @@ -0,0 +1,15 @@ +#![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!("kerne; should kill this application"); + unsafe { + core::ptr::null_mut::().write_volatile(0); + } + 0 +} \ No newline at end of file diff --git a/user/src/bin/02_powers.rs b/user/src/bin/02_powers.rs new file mode 100644 index 0000000..54fde24 --- /dev/null +++ b/user/src/bin/02_powers.rs @@ -0,0 +1,27 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; + +const SIZE: usize = 10; +const P: u32 = 3; +const STEP: usize = 100000; +const MOD: u32 = 10007; + +#[no_mangle] +fn main() -> i32 { + let mut pow = [0u32; SIZE]; + let mut index: usize = 0; + pow[index] = 1; + for i in 1..=STEP { + let last = pow[index]; + index = (index + 1) % SIZE; + pow[index] = last * P % MOD; + if i % 10000 == 0 { + println!("{}^{}={}(MOD {})", P, i, pow[index], MOD); + } + } + println!("Test power OK!"); + 0 +} \ No newline at end of file diff --git a/user/src/bin/03_priv_inst.rs b/user/src/bin/03_priv_inst.rs new file mode 100644 index 0000000..04dac37 --- /dev/null +++ b/user/src/bin/03_priv_inst.rs @@ -0,0 +1,17 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; + +use core::arch::asm; + +#[no_mangle] +fn main() -> i32 { + println!("Try to execute privileged instruction in U Mode"); + println!("Kernel should kill this application!"); + unsafe { + asm!("sret"); + } + 0 +} diff --git a/user/src/bin/04_priv_csr.rs b/user/src/bin/04_priv_csr.rs new file mode 100644 index 0000000..fbd678f --- /dev/null +++ b/user/src/bin/04_priv_csr.rs @@ -0,0 +1,17 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; + +use riscv::register::sstatus::{self, SPP}; + +#[no_mangle] +fn main() -> i32 { + println!("Try to access privileged CSR in U Mode"); + println!("Kernel should kill this application!"); + unsafe { + sstatus::set_spp(SPP::User); + } + 0 +} diff --git a/user/src/console.rs b/user/src/console.rs new file mode 100644 index 0000000..93e7255 --- /dev/null +++ b/user/src/console.rs @@ -0,0 +1,32 @@ +use super::write; +use core::fmt::{self, Write}; + + +struct Stdout; + +const STDOUT: usize = 1; + +impl Write for Stdout { + fn write_str(&mut self, s: &str) -> fmt::Result { + write(STDOUT, s.as_bytes()); + Ok(()) + } +} + +pub fn print(args: fmt::Arguments) { + Stdout.write_fmt(args).unwrap(); +} + +#[macro_export] +macro_rules! print { + ($fmt: literal $(, $($arg: tt)+)?) => { + $crate::console::print(format_args!($fmt $(, $($arg)+)?)); + } +} + +#[macro_export] +macro_rules! println { + ($fmt: literal $(, $($arg: tt)+)?) => { + $crate::console::print(format_args!(concat!($fmt, "\n") $(, $($arg)+)?)); + } +} \ No newline at end of file diff --git a/user/src/lang_items.rs b/user/src/lang_items.rs new file mode 100644 index 0000000..afa93e2 --- /dev/null +++ b/user/src/lang_items.rs @@ -0,0 +1,17 @@ +use core::panic::PanicInfo; + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + let err = info.message().as_str().unwrap(); + if let Some(location) = info.location() { + println!( + "Panicked at {}:{}, {}", + location.file(), + location.line(), + err + ); + } else { + println!("Panicked: {}", err); + } + loop {} +} \ No newline at end of file diff --git a/user/src/lib.rs b/user/src/lib.rs new file mode 100644 index 0000000..63bf15a --- /dev/null +++ b/user/src/lib.rs @@ -0,0 +1,38 @@ +#![no_std] + +#[macro_use] +pub mod console; +mod syscall; +mod lang_items; + +#[no_mangle] +#[link_section = ".text.entry"] +pub extern "C" fn _start() -> ! { + // linkage is not stable + // but main function in user function required + extern "C" { + fn main() -> i32; + } + clear_bss(); + unsafe { + exit(main()); + } + panic!("unreachable after sys_exit") +} + +fn clear_bss() { + extern "C" { + fn sbss(); + fn ebss(); + } + (sbss as usize..ebss as usize).for_each(|addr| unsafe { + (addr as *mut u8).write_volatile(0); + }); +} + +pub fn write(fd: usize, buf: &[u8]) -> isize { + syscall::sys_write(fd, buf) +} +pub fn exit(exit_code: i32) -> isize { + syscall::sys_exit(exit_code) +} \ No newline at end of file diff --git a/user/src/linker.ld b/user/src/linker.ld new file mode 100644 index 0000000..01d13f2 --- /dev/null +++ b/user/src/linker.ld @@ -0,0 +1,46 @@ +OUTPUT_ARCH(riscv) +ENTRY(_start) +BASE_ADDRESS = 0x80400000; + +SECTIONS +{ + . = BASE_ADDRESS; + + stext = .; + .text : { + *(.text.entry) + *(.text .text.*) + } + + . = ALIGN(4K); + etext = .; + srodata = .; + .rodata : { + *(.data .rodata.*) + *(.srodata .srodata.*) + } + + . = ALIGN(4K); + erodata = .; + sdata = .; + .data : { + *(.data .data.*) + *(.sdata .sdata.*) + } + + . = ALIGN(4K); + edata = .; + .bss : { + *(.bss.stack) + sbss = .; + *(.bss .bss.*) + *(.sbss .sbss.*) + } + + . = ALIGN(4K); + ebss = .; + + /DISCARD/ : { + *(.eh_frame) + } +} \ No newline at end of file diff --git a/user/src/syscall.rs b/user/src/syscall.rs new file mode 100644 index 0000000..118cf83 --- /dev/null +++ b/user/src/syscall.rs @@ -0,0 +1,26 @@ +use core::arch::asm; + +const SYSCALL_WRITE: usize = 64; +const SYSCALL_EXIT: usize = 93; + +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 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]) +} \ No newline at end of file