diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index c1129fa..aa2c4c1 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -95,32 +95,6 @@ dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rust-ucore" -version = "0.1.0" -dependencies = [ - "bbl 0.1.0", - "bit-allocator 0.1.0", - "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "linked_list_allocator 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "multiboot2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "once 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "riscv 0.2.0", - "simple-filesystem 0.0.1 (git+https://github.com/wangrunji0408/SimpleFileSystem-Rust)", - "spin 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "uart_16550 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ucore-memory 0.1.0", - "ucore-process 0.1.0", - "volatile 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "x86_64 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "xmas-elf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "simple-filesystem" version = "0.0.1" @@ -149,6 +123,32 @@ dependencies = [ "x86_64 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ucore" +version = "0.1.0" +dependencies = [ + "bbl 0.1.0", + "bit-allocator 0.1.0", + "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "linked_list_allocator 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "multiboot2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "once 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "riscv 0.2.0", + "simple-filesystem 0.0.1 (git+https://github.com/wangrunji0408/SimpleFileSystem-Rust)", + "spin 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "uart_16550 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ucore-memory 0.1.0", + "ucore-process 0.1.0", + "volatile 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "x86_64 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "xmas-elf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ucore-memory" version = "0.1.0" diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 2406781..28a0cb3 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -1,11 +1,8 @@ [package] -name = "rust-ucore" +name = "ucore" version = "0.1.0" authors = ["Runji Wang "] -[lib] -crate-type = ["staticlib"] - [features] use_apic = [] link_user_program = [] diff --git a/kernel/Makefile b/kernel/Makefile index aff0125..11722b9 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -14,7 +14,7 @@ kernel := build/$(arch)/kernel.bin iso := build/$(arch)/os.iso target ?= $(arch)-blog_os mode ?= debug -rust_lib := target/$(target)/$(mode)/librust_ucore.a +rust_lib := target/$(target)/$(mode)/ucore boot_src := src/arch/$(arch)/boot linker_script := $(boot_src)/linker.ld @@ -123,7 +123,7 @@ build/x86_64/os.iso: $(kernel) $(grub_cfg) @grub-mkrescue -o $(iso) build/isofiles 2> /dev/null @rm -r build/isofiles -build/riscv32/os.iso: $(kernel) +build/riscv32/os.iso: kernel @cd ../riscv-pk && \ mkdir -p build && \ cd build && \ @@ -132,7 +132,7 @@ build/riscv32/os.iso: $(kernel) --enable-logo \ --disable-fp-emulation \ --host=riscv64-unknown-elf \ - --with-payload=$(abspath $(kernel)) && \ + --with-payload=$(abspath $(rust_lib)) && \ make && \ cp bbl ../../kernel/$@ diff --git a/kernel/riscv32-blog_os.json b/kernel/riscv32-blog_os.json index e78bd83..ab160b8 100644 --- a/kernel/riscv32-blog_os.json +++ b/kernel/riscv32-blog_os.json @@ -7,10 +7,16 @@ "os": "none", "arch": "riscv32", "cpu": "generic-rv32", - "features": "+m", + "features": "", "max-atomic-width": "32", - "linker": "ld.lld", + "linker": "riscv64-unknown-elf-ld", "linker-flavor": "ld", + "pre-link-args": { + "ld": [ + "-Tsrc/arch/riscv32/boot/linker.ld", + "-melf32lriscv" + ] + }, "executables": true, "panic-strategy": "abort", "relocation-model": "static", diff --git a/kernel/src/arch/riscv32/atomic.patch b/kernel/src/arch/riscv32/atomic.patch deleted file mode 100644 index dd196e7..0000000 --- a/kernel/src/arch/riscv32/atomic.patch +++ /dev/null @@ -1,103 +0,0 @@ ---- atomic_backup.rs 2018-07-10 00:29:48.000000000 +0800 -+++ atomic.rs 2018-07-12 18:32:26.000000000 +0800 -@@ -1556,15 +1556,9 @@ - } - - #[inline] --unsafe fn atomic_store(dst: *mut T, val: T, order: Ordering) { -- match order { -- Release => intrinsics::atomic_store_rel(dst, val), -- Relaxed => intrinsics::atomic_store_relaxed(dst, val), -- SeqCst => intrinsics::atomic_store(dst, val), -- Acquire => panic!("there is no such thing as an acquire store"), -- AcqRel => panic!("there is no such thing as an acquire/release store"), -- __Nonexhaustive => panic!("invalid memory ordering"), -- } -+unsafe fn atomic_store(dst: *mut T, val: T, _order: Ordering) { -+ use ptr::write; -+ write(dst, val); - } - - #[inline] -@@ -1580,15 +1574,22 @@ - } - - #[inline] --unsafe fn atomic_swap(dst: *mut T, val: T, order: Ordering) -> T { -- match order { -- Acquire => intrinsics::atomic_xchg_acq(dst, val), -- Release => intrinsics::atomic_xchg_rel(dst, val), -- AcqRel => intrinsics::atomic_xchg_acqrel(dst, val), -- Relaxed => intrinsics::atomic_xchg_relaxed(dst, val), -- SeqCst => intrinsics::atomic_xchg(dst, val), -- __Nonexhaustive => panic!("invalid memory ordering"), -+unsafe fn atomic_swap(dst: *mut T, val: T, _order: Ordering) -> T { -+ let sstatus: usize; -+ asm!("csrrs $0, 0x100, x0" : "=r"(sstatus) ::: "volatile"); -+ // Disable interrupt: sstatus::clear_sie() -+ asm!("csrrc x0, 0x100, $0" :: "r"(1) :: "volatile"); -+ -+ use ptr::{read, write}; -+ let ret = read(dst); -+ write(dst, val); -+ -+ let sie = sstatus & 1 != 0; -+ if sie { -+ // Enable interrupt: sstatus::set_sie() -+ asm!("csrrs x0, 0x100, $0" :: "r"(1) :: "volatile"); - } -+ ret - } - - /// Returns the previous value (like __sync_fetch_and_add). -@@ -1618,29 +1619,30 @@ - } - - #[inline] --unsafe fn atomic_compare_exchange(dst: *mut T, -+#[cfg(target_arch = "riscv32")] -+unsafe fn atomic_compare_exchange(dst: *mut T, - old: T, - new: T, -- success: Ordering, -- failure: Ordering) -+ _success: Ordering, -+ _failure: Ordering) - -> Result { -- let (val, ok) = match (success, failure) { -- (Acquire, Acquire) => intrinsics::atomic_cxchg_acq(dst, old, new), -- (Release, Relaxed) => intrinsics::atomic_cxchg_rel(dst, old, new), -- (AcqRel, Acquire) => intrinsics::atomic_cxchg_acqrel(dst, old, new), -- (Relaxed, Relaxed) => intrinsics::atomic_cxchg_relaxed(dst, old, new), -- (SeqCst, SeqCst) => intrinsics::atomic_cxchg(dst, old, new), -- (Acquire, Relaxed) => intrinsics::atomic_cxchg_acq_failrelaxed(dst, old, new), -- (AcqRel, Relaxed) => intrinsics::atomic_cxchg_acqrel_failrelaxed(dst, old, new), -- (SeqCst, Relaxed) => intrinsics::atomic_cxchg_failrelaxed(dst, old, new), -- (SeqCst, Acquire) => intrinsics::atomic_cxchg_failacq(dst, old, new), -- (__Nonexhaustive, _) => panic!("invalid memory ordering"), -- (_, __Nonexhaustive) => panic!("invalid memory ordering"), -- (_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"), -- (_, Release) => panic!("there is no such thing as a release failure ordering"), -- _ => panic!("a failure ordering can't be stronger than a success ordering"), -- }; -- if ok { Ok(val) } else { Err(val) } -+ let sstatus: usize; -+ asm!("csrrs $0, 0x100, x0" : "=r"(sstatus) ::: "volatile"); -+ // Disable interrupt: sstatus::clear_sie() -+ asm!("csrrc x0, 0x100, $0" :: "r"(1) :: "volatile"); -+ -+ use ptr::{read, write}; -+ let ret = read(dst); -+ if ret == old { -+ write(dst, new); -+ } -+ -+ let sie = sstatus & 1 != 0; -+ if sie { -+ // Enable interrupt: sstatus::set_sie() -+ asm!("csrrs x0, 0x100, $0" :: "r"(1) :: "volatile"); -+ } -+ Ok(ret) - } - - #[inline] diff --git a/kernel/src/arch/riscv32/boot/entry.asm b/kernel/src/arch/riscv32/boot/entry.asm index 6c11050..7541b9a 100644 --- a/kernel/src/arch/riscv32/boot/entry.asm +++ b/kernel/src/arch/riscv32/boot/entry.asm @@ -1,7 +1,7 @@ .section .entry .globl kern_entry kern_entry: - la sp, bootstacktop + lui sp, %hi(bootstacktop) tail rust_main .section .bss diff --git a/kernel/src/arch/riscv32/boot/trap.asm b/kernel/src/arch/riscv32/boot/trap.asm index 7fe159b..d400826 100644 --- a/kernel/src/arch/riscv32/boot/trap.asm +++ b/kernel/src/arch/riscv32/boot/trap.asm @@ -2,10 +2,10 @@ # If coming from userspace, preserve the user stack pointer and load # the kernel stack pointer. If we came from the kernel, sscratch # will contain 0, and we should continue on the current stack. - csrrw sp, sscratch, sp + csrrw sp, 0x140, sp # sscratch bnez sp, _save_context _restore_kernel_sp: - csrr sp, sscratch + csrr sp, 0x140 # sscratch # sscratch = previous-sp, sp = kernel-sp _save_context: # provide room for trap frame @@ -42,13 +42,13 @@ _save_context: sw x30, 30*4(sp) sw x31, 31*4(sp) - # get sp, sstatus, sepc, sbadvaddr, scause + # get sp, sstatus, sepc, stval, scause # set sscratch = 0 - csrrw s0, sscratch, x0 - csrr s1, sstatus - csrr s2, sepc - csrr s3, sbadaddr - csrr s4, scause + csrrw s0, 0x140, x0 # sscratch + csrr s1, 0x100 # sstatus + csrr s2, 0x141 # sepc + csrr s3, 0x143 # stval + csrr s4, 0x142 # scause # store sp, sstatus, sepc, sbadvaddr, scause sw s0, 2*4(sp) sw s1, 32*4(sp) @@ -64,11 +64,11 @@ _save_context: bnez s0, _restore_context # back to U-mode? (sstatus.SPP = 1) _save_kernel_sp: addi s0, sp, 36*4 - csrw sscratch, s0 # sscratch = kernel-sp + csrw 0x140, s0 # sscratch = kernel-sp _restore_context: # restore sstatus, sepc - csrw sstatus, s1 - csrw sepc, s2 + csrw 0x100, s1 + csrw 0x141, s2 # restore x registers except x2 (sp) lw x1, 1*4(sp) @@ -109,7 +109,7 @@ _restore_context: .globl __alltraps __alltraps: SAVE_ALL - move a0, sp + mv a0, sp jal rust_trap .globl __trapret __trapret: diff --git a/kernel/src/arch/riscv32/compiler_rt.rs b/kernel/src/arch/riscv32/compiler_rt.rs new file mode 100644 index 0000000..432f0ef --- /dev/null +++ b/kernel/src/arch/riscv32/compiler_rt.rs @@ -0,0 +1,73 @@ +//! Workaround for missing compiler-builtin symbols +//! +//! [atomic](http://llvm.org/docs/Atomics.html#libcalls-atomic) + +/// Copy from: +/// https://github.com/rust-lang-nursery/compiler-builtins/blob/master/src/riscv32.rs +#[no_mangle] +pub extern fn __mulsi3(mut a: u32, mut b: u32) -> u32 { + let mut r: u32 = 0; + + while a > 0 { + if a & 1 > 0 { + r += b; + } + a >>= 1; + b <<= 1; + } + + r +} + +#[no_mangle] +pub extern fn abort() { + loop {} +} + +use core::ptr::{read, write}; + +#[no_mangle] +pub unsafe extern fn __atomic_load_1(src: *const u8) -> u8 { + read(src) +} + +#[no_mangle] +pub unsafe extern fn __atomic_load_2(src: *const u16) -> u16 { + read(src) +} + +#[no_mangle] +pub unsafe extern fn __atomic_load_4(src: *const u32) -> u32 { + read(src) +} + +#[no_mangle] +pub unsafe extern fn __atomic_store_1(dst: *mut u8, val: u8) { + write(dst, val) +} + +#[no_mangle] +pub unsafe extern fn __atomic_store_4(dst: *mut u32, val: u32) { + write(dst, val) +} + +unsafe fn __atomic_compare_exchange(dst: *mut T, old: T, new: T) -> (T, bool) { + use super::interrupt; + let flags = interrupt::disable_and_store(); + let ret = read(dst); + if ret == old { + write(dst, new); + } + interrupt::restore(flags); + (ret, true) +} + +#[no_mangle] +pub unsafe extern fn __atomic_compare_exchange_1(dst: *mut u8, old: u8, src: u8) -> (u8, bool) { + __atomic_compare_exchange(dst, old, src) +} + +#[no_mangle] +pub unsafe extern fn __atomic_compare_exchange_4(dst: *mut u32, old: u32, src: u32) -> (u32, bool) { + __atomic_compare_exchange(dst, old, src) +} \ No newline at end of file diff --git a/kernel/src/arch/riscv32/mod.rs b/kernel/src/arch/riscv32/mod.rs index 7f5b32e..1af72bb 100644 --- a/kernel/src/arch/riscv32/mod.rs +++ b/kernel/src/arch/riscv32/mod.rs @@ -6,10 +6,14 @@ pub mod interrupt; pub mod timer; pub mod paging; pub mod memory; +pub mod compiler_rt; pub fn init() { println!("Hello RISCV! {}", 123); interrupt::init(); memory::init(); timer::init(); -} \ No newline at end of file +} + +global_asm!(include_str!("boot/entry.asm")); +global_asm!(include_str!("boot/trap.asm")); \ No newline at end of file diff --git a/kernel/src/fs.rs b/kernel/src/fs.rs index 3389ed6..c573623 100644 --- a/kernel/src/fs.rs +++ b/kernel/src/fs.rs @@ -4,6 +4,16 @@ use alloc::boxed::Box; use arch::driver::ide; use spin::Mutex; +// Hard link user program +#[cfg(target_arch = "riscv32")] +global_asm!(r#" + .section .rodata + .align 12 +_binary_user_riscv_img_start: + .incbin "../user/user-riscv.img" +_binary_user_riscv_img_end: +"#); + pub fn shell() { #[cfg(target_arch = "riscv32")] let device = { diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 1c434c5..02fb8e2 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -49,7 +49,7 @@ pub use arch::other_main; use linked_list_allocator::LockedHeap; #[macro_use] // print! -mod logging; +pub mod logging; mod memory; mod lang; mod util; @@ -70,7 +70,7 @@ mod arch; #[cfg(target_arch = "riscv32")] #[path = "arch/riscv32/mod.rs"] -mod arch; +pub mod arch; /// The entry point of Rust kernel #[no_mangle] diff --git a/kernel/src/logging.rs b/kernel/src/logging.rs index 99b8ab0..a007cb4 100644 --- a/kernel/src/logging.rs +++ b/kernel/src/logging.rs @@ -15,12 +15,14 @@ pub fn init() { }); } +#[macro_export] macro_rules! print { ($($arg:tt)*) => ({ $crate::logging::print(format_args!($($arg)*)); }); } +#[macro_export] macro_rules! println { ($fmt:expr) => (print!(concat!($fmt, "\n"))); ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); diff --git a/kernel/src/main.rs b/kernel/src/main.rs new file mode 100644 index 0000000..8f0dad8 --- /dev/null +++ b/kernel/src/main.rs @@ -0,0 +1,6 @@ +#![no_std] // don't link the Rust standard library +#![cfg_attr(not(test), no_main)] // disable all Rust-level entry points +#![cfg_attr(test, allow(dead_code, unused_macros, unused_imports))] + +#[macro_use] +extern crate ucore;