Open generalibm opened 3 years ago
@wyfcyx 谢谢,在我的机器下的运行结果和文档中有些出入,具体说来,我这里运行的结果如下:
[rustsbi] Version 0.1.0
.______ __ __ _______.___________. _______..______ __
| _ \ | | | | / | | / || _ \ | |
| |_) | | | | | | (----`---| |----`| (----`| |_) || |
| / | | | | \ \ | | \ \ | _ < | |
| |\ \----.| `--' |.----) | | | .----) | | |_) || |
| _| `._____| \______/ |_______/ |__| |_______/ |______/ |__|
[rustsbi] Platform: QEMU
[rustsbi] misa: RV64ACDFIMSU
[rustsbi] mideleg: 0x222
[rustsbi] medeleg: 0xb109
[rustsbi] Kernel entry: 0x80020000
Hello, world!
.text [0x80020000, 0x80022000)
.rodata [0x80022000, 0x80023000)
.data [0x80023000, 0x80023000)
boot_stack [0x80023000, 0x80033000)
.bss [0x80033000, 0x80033000)
Panicked at src/main.rs:46 Shutdown machine!
panicked at 'Unhandled exception! mcause: Exception(StoreFault), mepc: 000000008000261c, mtval: 0000000000100000', platform/qemu/src/main.rs:395:18
我暂时先发出这个结果,等研究完文档上的说明之后再查查什么原因。再次感谢!!!
根据上述结果最后一行的信息,定位到了 RUSTSBI 原码处,再根据 platform/qemu/src/main.rs:355
解释,应当是 RUSTSBI 认为 rCore 在 shutdown
处发出的 ecall(8,0,0,0)
为非法指令。
目前的解决方法是,安装 qemu v5.0.0 。
备注:安装 qemu v5.0.0 之后的 rCore-Tutorial 和 rCore-Tutorial-v3 均能正常 shutdown 。
最近在 qemu v5.1.0 上遇到了同样的问题,最后发现原因如下:
qemu 中 shutdown 的实现是让 guest OS 对 sifive,test1 设备进行 MMIO 写操作,在 qemu v5.1.0 中要求对该设备的 MMIO 必须是 32 位访问,而 OpenSBI 使用了 16 位的写操作 (这里),导致在 M 态发生 Store/AMO access fault 异常。
在 QEMU v5.2.0 之后该问题被修复,详见该补丁:https://github.com/qemu/qemu/commit/ab3d207fe89bc0c63739db19e177af49179aa457
问题描述
下载最新代码后,切换到 lab-1 分支,
make run
出现如下错误信息:之后,gbd 和 qemu 陷入卡死状态,目前我的处理方式是
kill -9
。我的环境
我的追踪过程
根据
os/src/main.rs:44: 'end of rust_main'
提示,追踪到os/src/panic.rs::panic_handler:26
中shutdown
;在
os/src/sbi.rs:44
中shutdown
调用sbi_call(8,0,0,0)
。根据os/src/sbi.rs:7
的定义,发现是使用了ecall
请求 M 态(即SBI)服务,在这里是 qemu 下的 openSBI v0.7,该版本实现了 RISCV SBI 的 v0.2 版本。自然而言会想到查看 SBI 手册,在这里找到了关于
shutdown
的说明。起初,看到 Replacement EID 这一列时,认为可能是我的机器环境比实验手册中环境要新一些,故阅读完该文档之后,实现了一个新版本的sbi_shutdown
取代此前os/src/panic.rs::panic_handler:26
处的shutdown
,代码如下:pub struct Sbiret { pub error: i64, pub value: i64, }
const SBI_SYSTEM_RESET: usize = 0x53525354;
pub fn sbi_shutdown() -> Sbiret { sbi_call(SBI_SYSTEM_RESET, 0, 0, 0,0) }
然后,用
sbi_hart_stop
替代os/src/panic.rs:26
处的shutdown
。make run
之后光标停在了src/main.rs:44: 'end of rust_main'
之后。至此,shutdown
问题得到了解决,但是不确定的是这个方案优劣几何。sbi_shutdown
中ecall
对于EID = 8
不支持,那么EID = 0
的时钟是否也不支持呢?在将os/src/mod.rs:15
的timer::init();
解除注释后,再把os/src/main.rs:44
中的panic("end of rust_main")
改为loop {}
后,make run
发现打印出各种 ticks ,说明 open SBI v0.7 对于EID = 0
情况的ecall
是支持的。涉及文件
rCore-Tutorial 的 lab-1 下
相关段落
os/src/sbi.rs
/// SBI 调用
[inline(always)]
fn sbi_call(eid: i32,fid: i32, arg0: usize, arg1: usize, arg2: usize) -> Sbiret { let mut error; let mut value; unsafe { llvm_asm!("ecall" : "={x10}" (error), "={x11}" (value) : "{x10}" (arg0), "{x11}" (arg1), "{x12}" (arg2), "{x17}" (eid), "{x16}" (fid) : "memory" // 如果汇编可能改变内存,则需要加入 memory 选项 : "volatile"); // 防止编译器做激进的优化(如调换指令顺序等破坏 SBI 调用行为的优化) } Sbiret{error, value} }
pub struct Sbiret { pub error: i64, pub value: i64, }
const SBI_HSM_STOP_EID:i32 = 0x48534D; const SBI_HSM_STOP_FID:i32 = 1;
const SBI_SET_TIMER: i32 = 0; const SBI_CONSOLE_PUTCHAR: i32 = 1; const SBI_CONSOLE_GETCHAR: i32 = 2; const SBI_CLEAR_IPI: i32 = 3; const SBI_SEND_IPI: i32 = 4; const SBI_REMOTE_FENCE_I: i32 = 5; const SBI_REMOTE_SFENCE_VMA: i32 = 6; const SBI_REMOTE_SFENCE_VMA_ASID: i32 = 7; const SBI_SHUTDOWN: i32 = 8;
/// 向控制台输出一个字符 /// /// 需要注意我们不能直接使用 Rust 中的 char 类型 pub fn console_putchar(c: usize) { sbi_call(SBI_CONSOLE_PUTCHAR, 0, c, 0, 0); }
/// 从控制台中读取一个字符 /// /// 没有读取到字符则返回 -1 pub fn console_getchar() -> Sbiret { sbi_call(SBI_CONSOLE_GETCHAR, 0, 0, 0, 0) }
/// 调用 SBI_SHUTDOWN 来关闭操作系统(直接退出 QEMU) pub fn shutdown() -> ! { sbi_call(SBI_SHUTDOWN, 0, 0, 0,0); unreachable!() }
/// 设置下一次时钟中断的时间 pub fn set_timer(time: usize) { sbi_call(SBI_SET_TIMER, 0, time, 0,0); }
/// 关闭 hart ,等价于 SBI_SHUTDOWN ? /// TODO: need to verify pub fn sbi_hart_stop() -> Sbiret { sbi_call(SBI_HSM_STOP_EID, SBI_HSM_STOP_FID, 0, 0, 0) }
遇到问题
对于本问题的分析如上。但是对于目前给出
shutdown
的方案仍然感到疑惑。