Open OccupyMars2025 opened 1 year ago
// os/src/sbi.rs
// https://github.com/riscv-non-isa/riscv-sbi-doc/blob/master/riscv-sbi.adoc#function-system-reset-fid-0
pub fn shutdown() -> ! {
sbi_call(SRST_EXTENSION, SYSTEM_RESET_FUNCTION,
SystemResetType::Shutdown as usize,
/* SystemResetType::ColdReboot as usize
2023/7/2: Not implemented
[rustsbi-panic] hart 0 panicked at 'not yet implemented', rustsbi-qemu/src/qemu_test.rs:37:17
[rustsbi-panic] system shutdown scheduled due to RustSBI panic
make: *** [Makefile:9: run] Error 255
*/
// SystemResetType::ColdReboot as usize,
/*SystemResetType::WarmReboot as usize,
2023/7/2: Not implemented
[rustsbi-panic] hart 0 panicked at 'not yet implemented', rustsbi-qemu/src/qemu_test.rs:37:17
[rustsbi-panic] system shutdown scheduled due to RustSBI panic
make: *** [Makefile:9: run] Error 255
*/
// SystemResetType::WarmReboot as usize,
SystemResetReason::NoReason as usize,
0);
panic!("It should have shutdown !")
}
/*
file name: print_stack_trace_fp_chain_using_libunwind.c
2023/7/2:
/usr/include/x86_64-linux-gnu/libunwind.h
$ gcc print_stack_trace_fp_chain_using_libunwind.c -o print_stack_trace_fp_chain_using_libunwind -funwind-tables -lunwind
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
(.text+0x1b): undefined reference to `main'
collect2: error: ld returned 1 exit status
Failure: what's wrong ?
*/
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#define UNW_LOCAL_ONLY
#include <libunwind.h>
// Compile with -funwind-tables -lunwind
void print_stack_trace_libunwind() {
printf("=== Stack trace from libunwind ===\n");
unw_cursor_t cursor; unw_context_t uc;
unw_word_t pc, sp;
unw_getcontext(&uc);
unw_init_local(&cursor, &uc);
while (unw_step(&cursor) > 0) {
unw_get_reg(&cursor, UNW_REG_IP, &pc);
unw_get_reg(&cursor, UNW_REG_SP, &sp);
printf("Program counter: 0x%016" PRIxPTR "\n", (uintptr_t) pc);
printf("Stack pointer: 0x%016" PRIxPTR "\n", (uintptr_t) sp);
printf("\n");
}
printf("=== End ===\n\n");
}
/*
2023/7/2: This solution works
filename : print_stack_trace_fp_chain.c
http://rcore-os.cn/rCore-Tutorial-Book-v3/chapter1/8answer.html
实现一个linux应用程序B,能打印出调用栈链信息。(用C或Rust编程)
以使用 GCC 编译的 C 语言程序为例,使用编译参数 -fno-omit-frame-pointer 的情况下,会保存栈帧指针 fp 。
fp 指向的栈位置的负偏移量处保存了两个值:
-8(fp) 是保存的 ra
-16(fp) 是保存的上一个 fp
因此我们可以像链表一样,从当前的 fp 寄存器的值开始,每次找到上一个 fp ,逐帧恢复我们的调用栈:
*/
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
/* Compile with -fno-omit-frame-pointer
$ riscv64-unknown-elf-gcc print_stack_trace_fp_chain.c -o print_stack_trace_fp_chain -fno-omit-frame-pointer
$ qemu-riscv64 ./print_stack_trace_fp_chain
*/
void print_stack_trace_fp_chain() {
printf("=== Stack trace from fp chain ===\n");
uintptr_t *fp;
asm("mv %0, fp" : "=r"(fp) : : );
// When should this stop?
while (fp) {
printf("Return address: 0x%016" PRIxPTR "\n", fp[-1]);
// maybe fp[-2] should be named "last fp"
printf("Old stack pointer: 0x%016" PRIxPTR "\n", fp[-2]);
printf("\n");
fp = (uintptr_t *) fp[-2];
}
printf("=== End ===\n\n");
}
int main() {
print_stack_trace_fp_chain();
return 0;
}
// from opensbi project
// lib/sbi/sbi_ecall_susp.c
if (funcid == SBI_EXT_SUSP_SUSPEND)
ret = sbi_system_suspend(regs->a0, regs->a1, regs->a2);
// from opensbi project
// opensbi-master/lib/sbi/sbi_system.c
int sbi_system_suspend(u32 sleep_type, ulong resume_addr, ulong opaque)
struct sbiret sbi_ecall(int ext, int fid, unsigned long arg0,
unsigned long arg1, unsigned long arg2,
unsigned long arg3, unsigned long arg4,
unsigned long arg5)
{
struct sbiret ret;
register uintptr_t a0 asm ("a0") = (uintptr_t)(arg0);
register uintptr_t a1 asm ("a1") = (uintptr_t)(arg1);
register uintptr_t a2 asm ("a2") = (uintptr_t)(arg2);
register uintptr_t a3 asm ("a3") = (uintptr_t)(arg3);
register uintptr_t a4 asm ("a4") = (uintptr_t)(arg4);
register uintptr_t a5 asm ("a5") = (uintptr_t)(arg5);
register uintptr_t a6 asm ("a6") = (uintptr_t)(fid);
register uintptr_t a7 asm ("a7") = (uintptr_t)(ext);
asm volatile ("ecall"
: "+r" (a0), "+r" (a1)
: "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6), "r" (a7)
: "memory");
ret.error = a0;
ret.value = a1;
return ret;
}
#include <time.h>
#include <stdio.h>
// provided by AI
void sleep(unsigned int seconds) {
struct timespec ts;
ts.tv_sec = seconds;
ts.tv_nsec = 0;
while (nanosleep(&ts, &ts) == -1) {
perror("nanosleep");
}
}
int main() {
printf("Start sleeping:\n");
sleep(10);
printf("End sleeping:\n");
}
https://man7.org/training/ https://www.man7.org/linux/man-pages/man3/sleep.3.html https://patchwork.kernel.org/project/linux-riscv/list/
https://lists.riscv.org/g/tech-prs/message/235 https://docs.rs/sbi-rt/latest/sbi_rt/ opensbi-master/lib/sbi/sbi_system.c rustsbi-main/src/susp.rs
// ch5 branch: user/src/lib.rs
pub fn sleep(period_ms: usize) {
let start = sys_get_time();
while sys_get_time() < start + period_ms as isize {
sys_yield();
}
}
other's suggestion:
如果有人想要使用riscv的mtime寄存器完成sleep函数,qemu中mtime寄存器的频率是10Mhz。
我花了一点时间才最终在google group chat中找到这一点,我不理解为什么qemu没有在riscv virt中给出这一确切的值。
在以后,我们还可以在 log 信息中增加线程、CPU等信息(只是一个推荐,不做要求),这些信息将极大的方便你的代码调试。
http://rcore-os.cn/rCore-Tutorial-Book-v3/chapter1/7exercise.html#log
可以彩色输出,不要求 log 等级控制
可以关闭内核所有输出。从 lab2 开始要求关闭内核所有输出(如果实现了 log 等级控制,那么这一点自然就实现了)
os/Makefile (要求 make run LOG=xxx 可以正确执行,可以不实现对 LOG 这一属性的支持,设置默认输出等级为 INFO)
https://docs.rs/log/latest/log/index.html
The "Available logging implementations" part lists many logging implementations, you can study their
source code
Warning: The logging system may only be initialized once.
https://doc.rust-lang.org/cargo/guide/cargo-home.html
You can alter the location of the Cargo home by setting the CARGO_HOME environmental variable. The home crate provides an API for getting this location if you need this information inside your Rust crate. By default, the Cargo home is located in $HOME/.cargo/
Method to compile source code into RISC-V assembly language and run it on x86-64 machine
colorful logging
echo -e "\x1b[31mhello world\x1b[0m"
ESC ascii value is 27 = 0x1b
http://rcore-os.cn/rCore-Tutorial-Book-v3/chapter1/7exercise.html#log
https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
reset all attributes with ESC[0m
请用相关工具软件分析并给出应用程序A的代码段/数据段/堆/栈的地址空间范围。
use
option_env!("LOG")
to set max levelusing
option_env!("LOG")
will getOption<&str>
, that isSome("INFO")
here