From aa22fcabdeb96e810b6c91d24eda9396697e8862 Mon Sep 17 00:00:00 2001 From: WangRunji Date: Fri, 6 Jul 2018 23:02:10 +0800 Subject: [PATCH] Change target arch to RISCV32IMA. Recover some dependencies. --- docs/RISCV.md | 28 ++++++++++++++++++++++------ riscv32-blog_os.json | 2 +- src/io/riscv_io.rs | 20 ++++++++++++++++++++ src/lang.rs | 4 +++- 4 files changed, 46 insertions(+), 8 deletions(-) create mode 100644 src/io/riscv_io.rs diff --git a/docs/RISCV.md b/docs/RISCV.md index a4cd6668..b821a3d8 100644 --- a/docs/RISCV.md +++ b/docs/RISCV.md @@ -9,17 +9,27 @@ ## Rust-RISCV -### 目标指令集:RISCV32IA +### 目标指令集:RISCV32IMA -target: riscv32ia_unknown_none +target: riscv32ima_unknown_none -由于工具链二进制版本尚未内置`riscv32ia_unknown_none`的target,因此需提供配置文件:`riscv32-blog_os.json`。 +由于工具链二进制版本尚未内置此target,因此需提供配置文件:`riscv32-blog_os.json`。 -为什么要用原子指令扩展? +理想情况下,目标指令集应为RISCV32G,即使用全部扩展。但考虑到要把它跑在我们自己实现的CPU上,指令集应该尽量精简,即最好是RISCV32I。此外: -RustOS依赖的库中,大部分都使用了Rust核心库的原子操作(core::sync::atomic)。 +* 为什么用原子指令扩展? -如果目标指令集不支持原子操作,会导致无法编译。 + RustOS依赖的库中,大部分都使用了Rust核心库的原子操作(core::sync::atomic)。 + + 如果目标指令集不支持原子操作,会导致无法编译。 + + 然而LLVM后端尚不完全支持原子指令扩展,因此这条路可能走不通,需要魔改Rust标准库。 + +* 为什么用乘除指令扩展? + + Rust核心库中fmt模块会使用乘除运算,若不使用乘除指令,则会依赖LLVM提供的内置函数进行软计算,导致链接错误。这一问题理论上可以通过在xargo中设置依赖compiler-builtin解决。但如此操作后,仍有一个函数`__mulsi3`缺失(32×32)。经查,compiler-builtin中实现了类似的`__muldi3`函数(64×64),所以理论上可以用它手动实现前者。但如此操作后,还是不对,实验表明`__muldi3`本身也是不正确的。 + + 总之,没有成功配置不使用M扩展的编译环境,不过日后解决这一问题并不困难。 ## BootLoader @@ -27,3 +37,9 @@ RustOS依赖的库中,大部分都使用了Rust核心库的原子操作(core 然而官方版本和bbl-ucore中的fork版本都无法正常编译,使用的是[ucore_os_lab中的修改版本](https://github.com/chyyuu/ucore_os_lab/tree/riscv32-priv-1.10/riscv-pk)。 +bbl-ucore使用RISCV1.9的bbl,ucore_os_lab使用RISCV1.10的bbl。后者相比前者,去掉了对内核的内存映射,因此需保证虚实地址一致。 + +注:事实上ucore_os_lab中的虚实地址并不一致,且没有内存映射,但依然能够运行,应该是由于编译器生成的所有跳转都使用相对偏移。而Rust编译器会生成绝对地址跳转,因此若虚实不一致会导致非法访存。 + + + diff --git a/riscv32-blog_os.json b/riscv32-blog_os.json index 291cdeb9..2f6236e0 100644 --- a/riscv32-blog_os.json +++ b/riscv32-blog_os.json @@ -7,7 +7,7 @@ "os": "none", "arch": "riscv", "cpu": "generic-rv32", - "features": "+a", + "features": "+m,+a", "max-atomic-width": "32", "linker": "ld.lld", "linker-flavor": "ld", diff --git a/src/io/riscv_io.rs b/src/io/riscv_io.rs new file mode 100644 index 00000000..66193101 --- /dev/null +++ b/src/io/riscv_io.rs @@ -0,0 +1,20 @@ +// FIXME: merge to x86_64 io + +use core::fmt; + +macro_rules! print { + ($($arg:tt)*) => ({ + $crate::io::print(format_args!($($arg)*)); + }); +} + +macro_rules! println { + ($fmt:expr) => (print!(concat!($fmt, "\n"))); + ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); +} + +pub fn print(args: fmt::Arguments) { + use arch::serial::SerialPort; + use core::fmt::Write; + SerialPort.write_fmt(args).unwrap(); +} \ No newline at end of file diff --git a/src/lang.rs b/src/lang.rs index 3d0b9e24..d2cef8a4 100644 --- a/src/lang.rs +++ b/src/lang.rs @@ -23,7 +23,9 @@ pub fn panic(info: &PanicInfo) -> ! { #[cfg(target_arch = "riscv")] #[lang = "panic_fmt"] -unsafe extern "C" fn panic_fmt(_fmt: ::core::fmt::Arguments, _file: &'static str, _line: u32, _col: u32) -> ! { +#[no_mangle] +pub fn panic_fmt(fmt: ::core::fmt::Arguments, file: &'static str, line: u32, col: u32) -> ! { + println!("\n\nPANIC in {} at {}:{}\n {}", file, line, col, fmt); loop {} }