Compare commits

..

No commits in common. "ch2" and "master" have entirely different histories.
ch2 ... master

37 changed files with 38 additions and 895 deletions

View file

32
Cargo.lock generated Normal file
View file

@ -0,0 +1,32 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "log"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "os"
version = "0.1.0"
dependencies = [
"log",
"sbi-rt",
]
[[package]]
name = "sbi-rt"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fbaa69be1eedc61c426e6d489b2260482e928b465360576900d52d496a58bd0"
dependencies = [
"sbi-spec",
]
[[package]]
name = "sbi-spec"
version = "0.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6e36312fb5ddc10d08ecdc65187402baba4ac34585cb9d1b78522ae2358d890"

View file

@ -1,7 +1,8 @@
[package] [package]
name = "user_lib" name = "os"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
riscv = "0.12.1" log = "0.4.22"
sbi-rt = "0.0.3"

View file

@ -2,24 +2,12 @@
## Build ## Build
### in dir `user`
``` bash
cargo build --release
rust-objcopy --strip-all target/riscv64gc-unknown-none-elf/release/00_hello_world -O binary target/riscv64gc-unknown-none-elf/release/00_hello_world.bin
...
```
### in dir `os`
``` bash ``` bash
LOG=TRACE cargo build --release LOG=TRACE cargo build --release
``` ```
## Run ## Run
rustsbi-qemu should be downloaded manually.
``` bash ``` bash
qemu-system-riscv64 -machine virt -nographic -bios target/riscv64gc-unknown-none-elf/release/rustsbi-qemu.bin -device loader,file=target/riscv64gc-unknown-none-elf/release/os qemu-system-riscv64 -machine virt -nographic -bios target/riscv64gc-unknown-none-elf/release/rustsbi-qemu.bin -device loader,file=target/riscv64gc-unknown-none-elf/release/os
``` ```

132
os/Cargo.lock generated
View file

@ -1,132 +0,0 @@
# 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 = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
dependencies = [
"spin",
]
[[package]]
name = "log"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "os"
version = "0.1.0"
dependencies = [
"lazy_static",
"log",
"riscv",
"sbi-rt",
]
[[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 = "sbi-rt"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fbaa69be1eedc61c426e6d489b2260482e928b465360576900d52d496a58bd0"
dependencies = [
"sbi-spec",
]
[[package]]
name = "sbi-spec"
version = "0.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6e36312fb5ddc10d08ecdc65187402baba4ac34585cb9d1b78522ae2358d890"
[[package]]
name = "spin"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
[[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"

View file

@ -1,10 +0,0 @@
[package]
name = "os"
version = "0.1.0"
edition = "2021"
[dependencies]
lazy_static = { version = "1.5.0", features = ["spin_no_std"] }
log = "0.4.22"
riscv = "0.12.1"
sbi-rt = "0.0.3"

View file

@ -1,135 +0,0 @@
use core::{arch::asm, mem, slice};
use lazy_static::*;
use log::info;
use crate::{sbi::shutdown, sync::UPSafeCell, trap::TrapContext};
const KERNEL_STACK_SIZE: usize = 4096 * 2;
const USER_STACK_SIZE: usize = 4096 * 2;
const MAX_APP_NUM: usize = 16;
const APP_BASE_ADDRESS: usize = 0x80400000;
const APP_SIZE_LIMIT: usize = 0x20000;
#[repr(align(4096))]
struct KernelStack {
data: [u8; KERNEL_STACK_SIZE],
}
#[repr(align(4096))]
struct UserStack {
data: [u8; USER_STACK_SIZE],
}
static KERNEL_STACK: KernelStack = KernelStack {
data: [0; KERNEL_STACK_SIZE],
};
static USER_STACK: UserStack = UserStack {
data: [0; USER_STACK_SIZE],
};
impl KernelStack {
fn get_sp(&self) -> usize {
self.data.as_ptr() as usize + KERNEL_STACK_SIZE
}
pub fn push_context(&self, cx: TrapContext) -> &'static mut TrapContext {
let cx_ptr = (self.get_sp() - mem::size_of::<TrapContext>()) as *mut TrapContext;
unsafe {
*cx_ptr = cx;
}
unsafe { cx_ptr.as_mut().unwrap() }
}
}
impl UserStack {
fn get_sp(&self) -> usize {
self.data.as_ptr() as usize + USER_STACK_SIZE
}
}
struct AppManager {
num_app: usize,
current_app: usize,
app_start: [usize; MAX_APP_NUM + 1],
}
impl AppManager {
pub fn print_app_info(&self) {
info!(target: "kernel", "num_app = {}", self.num_app);
for i in 0..self.num_app {
info!(target: "kernel", "app_{} [{:#x}, {:#x}]", i, self.app_start[i], self.app_start[i + 1]);
}
}
pub fn get_current_app(&self) -> usize {
self.current_app
}
pub fn move_to_next_app(&mut self) {
self.current_app += 1;
}
unsafe fn load_app(&self, app_id: usize) {
if app_id >= self.num_app {
info!(target: "kernel", "All applications completed");
shutdown(false);
}
info!(target: "kernel", "Loading app_{}", app_id);
slice::from_raw_parts_mut(APP_BASE_ADDRESS as *mut u8, APP_SIZE_LIMIT).fill(0);
let app_src = slice::from_raw_parts(self.app_start[app_id] as *const u8, self.app_start[app_id + 1] - self.app_start[app_id]);
let app_dst = slice::from_raw_parts_mut(APP_BASE_ADDRESS as *mut u8, app_src.len());
app_dst.copy_from_slice(app_src);
asm!("fence.i");
}
}
lazy_static! {
static ref APP_MANAGER: UPSafeCell<AppManager> = unsafe {
UPSafeCell::new({
extern "C" {
fn _num_app();
}
let num_app_ptr = _num_app as usize as *const usize;
let num_app = num_app_ptr.read_volatile();
let mut app_start: [usize; MAX_APP_NUM + 1] = [0; MAX_APP_NUM + 1];
let app_start_raw: &[usize] = slice::from_raw_parts(num_app_ptr.add(1), num_app + 1);
app_start[..=num_app].copy_from_slice(app_start_raw);
AppManager {
num_app,
current_app: 0,
app_start,
}
})
};
}
pub fn init() {
print_app_info();
}
pub fn print_app_info() {
APP_MANAGER.exclusive_access().print_app_info();
}
pub fn run_next_app() -> ! {
let mut app_manager = APP_MANAGER.exclusive_access();
let current_app = app_manager.get_current_app();
unsafe {
app_manager.load_app(current_app);
}
app_manager.move_to_next_app();
drop(app_manager);
extern "C" {
fn __restore(cx_addr: usize);
}
unsafe {
__restore(KERNEL_STACK.push_context(TrapContext::app_init_context(
APP_BASE_ADDRESS,
USER_STACK.get_sp(),
)) as *const _ as usize);
}
panic!("Unreachable in batch::run_current_app");
}

View file

@ -1,47 +0,0 @@
.align 3
.section .data
.global _num_app
_num_app:
.quad 5
.quad app_0_start
.quad app_1_start
.quad app_2_start
.quad app_3_start
.quad app_4_start
.quad app_4_end
.section .data
.global app_0_start
.global app_0_end
app_0_start:
.incbin "../user/target/riscv64gc-unknown-none-elf/release/00_hello_world.bin"
app_0_end:
.section .data
.global app_1_start
.global app_1_end
app_1_start:
.incbin "../user/target/riscv64gc-unknown-none-elf/release/01_store_fault.bin"
app_1_end:
.section .data
.global app_2_start
.global app_2_end
app_2_start:
.incbin "../user/target/riscv64gc-unknown-none-elf/release/02_power.bin"
app_2_end:
.section .data
.global app_3_start
.global app_3_end
app_3_start:
.incbin "../user/target/riscv64gc-unknown-none-elf/release/03_priv_inst.bin"
app_3_end:
.section .data
.global app_4_start
.global app_4_end
app_4_start:
.incbin "../user/target/riscv64gc-unknown-none-elf/release/04_priv_csr.bin"
app_4_end:

View file

@ -1,3 +0,0 @@
mod up;
pub use up::UPSafeCell;

View file

@ -1,18 +0,0 @@
use core::cell::{RefCell, RefMut};
pub struct UPSafeCell<T> {
inner: RefCell<T>
}
unsafe impl <T> Sync for UPSafeCell<T> {}
impl<T> UPSafeCell<T> {
pub unsafe fn new(value: T) -> Self {
Self {
inner: RefCell::new(value)
}
}
pub fn exclusive_access(&self) -> RefMut<'_, T> {
self.inner.borrow_mut()
}
}

View file

@ -1,17 +0,0 @@
use core::{slice, str};
const FD_STDOUT: usize = 1;
pub fn sys_write(fd: usize, buf: *const u8, len: usize) -> isize {
match fd {
FD_STDOUT => {
let slice = unsafe { slice::from_raw_parts(buf, len) };
let str = str::from_utf8(slice).unwrap();
print!("{}", str);
len as isize
}
_ => {
panic!("Unsupported fd in sys_write!");
}
}
}

View file

@ -1,16 +0,0 @@
use fs::sys_write;
use process::sys_exit;
const SYSCALL_WRITE: usize = 64;
const SYSCALL_EXIT: usize = 93;
mod fs;
mod process;
pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize {
match syscall_id {
SYSCALL_WRITE => sys_write(args[0], args[1] as *const u8, args[2]),
SYSCALL_EXIT => sys_exit(args[0] as i32),
_ => panic!("Unsupported syscall_id: {}", syscall_id)
}
}

View file

@ -1,8 +0,0 @@
use log::info;
use crate::batch::run_next_app;
pub fn sys_exit(exit_code: i32) -> ! {
info!(target: "kernel", "Application exited with code {}", exit_code);
run_next_app()
}

View file

@ -1,28 +0,0 @@
use riscv::register::sstatus::{self, Sstatus, SPP};
#[repr(C)]
pub struct TrapContext {
pub x: [usize; 32],
pub sstatus: Sstatus,
pub sepc: usize,
}
impl TrapContext {
pub fn set_sp(&mut self, sp: usize) {
self.x[2] = sp;
}
pub fn app_init_context(entry: usize, sp: usize) -> Self {
let cur_sstatus = sstatus::read();
unsafe {
sstatus::set_spp(SPP::User);
}
let mut cx = Self {
x: [0; 32],
sstatus: cur_sstatus,
sepc: entry,
};
cx.set_sp(sp);
cx
}
}

View file

@ -1,44 +0,0 @@
mod context;
pub use context::TrapContext;
use log::error;
use core::arch::global_asm;
use riscv::{interrupt::{Exception, Trap}, register::{scause, stval, stvec::{self, TrapMode}}};
use crate::{batch::run_next_app, syscall};
global_asm!(include_str!("trap.S"));
pub fn init() {
extern "C" {
fn __alltraps();
}
unsafe {
stvec::write(__alltraps as usize, TrapMode::Direct);
}
}
#[no_mangle]
pub fn trap_handler(cx: &mut TrapContext) -> &mut TrapContext {
let scause = scause::read();
let stval = stval::read();
match scause.cause() {
Trap::Exception(e) if e == Exception::UserEnvCall as usize => {
cx.sepc += 4;
cx.x[10] = syscall::syscall(cx.x[17], [cx.x[10], cx.x[11], cx.x[12]]) as usize;
}
Trap::Exception(e) if e == Exception::StoreFault as usize || e == Exception::StorePageFault as usize => {
error!(target: "kernel", "PageFault in application, kernel killed it.");
run_next_app();
}
Trap::Exception(e) if e == Exception::IllegalInstruction as usize => {
error!(target: "kernel", "IllegalInstruction in application, kernel killed it.");
run_next_app();
}
_ => {
panic!("un supported strp {:?}, stval = {:#x}!", scause.cause(), stval);
}
}
cx
}

View file

@ -1,64 +0,0 @@
.altmacro
.macro SAVE_GP n
sd x\n, \n*8(sp)
.endm
.macro LOAD_GP n
ld x\n, \n*8(sp)
.endm
.section .text
.globl __alltraps
.globl __restore
.align 2
__alltraps:
csrrw sp, sscratch, sp
# now sp->kernel stack, sscratch->user stack
# allocate a TrapContext on kernel stack
addi sp, sp, -34*8
# save general-purpose registers
sd x1, 1*8(sp)
# skip sp(x2), we will save it later
sd x3, 3*8(sp)
# skip tp(x4), application does not use it
# save x5~x31
.set n, 5
.rept 27
SAVE_GP %n
.set n, n+1
.endr
# we can use t0/t1/t2 freely, because they were saved on kernel stack
csrr t0, sstatus
csrr t1, sepc
sd t0, 32*8(sp)
sd t1, 33*8(sp)
# read user stack from sscratch and save it on the kernel stack
csrr t2, sscratch
sd t2, 2*8(sp)
# set input argument of trap_handler(cx: &mut TrapContext)
mv a0, sp
call trap_handler
__restore:
# case1: start running app by __restore
# case2: back to U after handling trap
mv sp, a0
# now sp->kernel stack(after allocated), sscratch->user stack
# restore sstatus/sepc
ld t0, 32*8(sp)
ld t1, 33*8(sp)
ld t2, 2*8(sp)
csrw sstatus, t0
csrw sepc, t1
csrw sscratch, t2
# restore general-purpuse registers except sp/tp
ld x1, 1*8(sp)
ld x3, 3*8(sp)
.set n, 5
.rept 27
LOAD_GP %n
.set n, n+1
.endr
# release TrapContext on kernel stack
addi sp, sp, 34*8
# now sp->kernel stack, sscratch->user stack
csrrw sp, sscratch, sp
sret

View file

@ -3,16 +3,15 @@ use crate::{sbi, println};
#[panic_handler] #[panic_handler]
fn panic(info: &PanicInfo) -> ! { fn panic(info: &PanicInfo) -> ! {
let err = info.message().as_str().unwrap();
if let Some(location) = info.location() { if let Some(location) = info.location() {
println!( println!(
"Panicked at {}:{} {}", "Panicked at {}:{} {}",
location.file(), location.file(),
location.line(), location.line(),
err info.message().as_str().unwrap()
); );
} else { } else {
println!("Panicked: {}", err); println!("Panicked: {}", info.message().as_str().unwrap());
} }
sbi::shutdown(true) sbi::shutdown(true)
} }

View file

@ -8,16 +8,10 @@ mod logger;
#[macro_use] #[macro_use]
mod console; mod console;
mod batch;
mod sync;
mod trap;
mod syscall;
use core::arch::global_asm; use core::arch::global_asm;
use log::{debug, error, info, trace, warn}; use log::{debug, error, info, trace, warn};
global_asm!(include_str!("entry.asm")); global_asm!(include_str!("entry.asm"));
global_asm!(include_str!("link_app.S"));
#[no_mangle] #[no_mangle]
pub fn rust_main() -> ! { pub fn rust_main() -> ! {
@ -27,9 +21,7 @@ pub fn rust_main() -> ! {
print_system_info(); print_system_info();
print_to_console(); print_to_console();
trap::init(); panic!("Shutdown machine!");
batch::init();
batch::run_next_app();
} }
fn clear_bss() { fn clear_bss() {

View file

@ -1,7 +0,0 @@
[build]
target = "riscv64gc-unknown-none-elf"
[target.riscv64gc-unknown-none-elf]
rustflags = [
"-Clink-arg=-Tsrc/linker.ld", "-Cforce-frame-pointers=yes"
]

1
user/.gitignore vendored
View file

@ -1 +0,0 @@
/target

93
user/Cargo.lock generated
View file

@ -1,93 +0,0 @@
# 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",
]

View file

@ -1,11 +0,0 @@
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
#[no_mangle]
fn main() -> i32 {
println!("Hello, world!");
0
}

View file

@ -1,15 +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!("kerne; should kill this application");
unsafe {
core::ptr::null_mut::<u8>().write_volatile(0);
}
0
}

View file

@ -1,27 +0,0 @@
#![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
}

View file

@ -1,17 +0,0 @@
#![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
}

View file

@ -1,17 +0,0 @@
#![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
}

View file

@ -1,32 +0,0 @@
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)+)?));
}
}

View file

@ -1,17 +0,0 @@
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 {}
}

View file

@ -1,38 +0,0 @@
#![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)
}

View file

@ -1,46 +0,0 @@
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)
}
}

View file

@ -1,26 +0,0 @@
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])
}