rCore-Tutorial-Book-v3 icon indicating copy to clipboard operation
rCore-Tutorial-Book-v3 copied to clipboard

rCore-Tutorial-Book-v3/chapter1/6print-and-shutdown-based-on-sbi

Open utterances-bot opened this issue 3 years ago • 57 comments
trafficstars

基于 SBI 服务完成输出和关机 — rCore-Tutorial-Book-v3 3.6.0-alpha.1 文档

https://rcore-os.github.io/rCore-Tutorial-Book-v3/chapter1/6print-and-shutdown-based-on-sbi.html

utterances-bot avatar Jan 15 '22 07:01 utterances-bot

最后使用 Qemu 运行内核的时候没有输出可能是什么问题呀 oslab@oslab-virtual-machine:~/Documents/os$ qemu-system-riscv64 \

-machine virt \
-nographic \
-bios ../bootloader/rustsbi-qemu.bin \
-device loader,file=target/riscv64gc-unknown-none-elf/release/os.bin,addr=0x80200000

[rustsbi] RustSBI version 0.2.0-alpha.6 .______ __ __ .___________. .. __ | _ \ | | | | / | | / || _ \ | | | |) | | | | | | (-------| |----| (----| |_) || | | / | | | | \ \ | | \ \ | _ < | | | |\ \----.| --' |.----) | | | .----) | | |) || | | | `.| _/ |/ || |_/ |/ ||

[rustsbi] Implementation: RustSBI-QEMU Version 0.0.2 [rustsbi-dtb] Hart count: cluster0 with 1 cores [rustsbi] misa: RV64ACDFIMSU [rustsbi] mideleg: ssoft, stimer, sext (0x222) [rustsbi] medeleg: ima, ia, bkpt, la, sa, uecall, ipage, lpage, spage (0xb1ab) [rustsbi] pmp0: 0x10000000 ..= 0x10001fff (rwx) [rustsbi] pmp1: 0x80000000 ..= 0x8fffffff (rwx) [rustsbi] pmp2: 0x0 ..= 0xffffffffffffff (---) qemu-system-riscv64: clint: invalid write: 00000004 [rustsbi] enter supervisor 0x80200000

就一直在这里没有任何输出

xuanranxiaoshi avatar Jan 15 '22 07:01 xuanranxiaoshi

@xuanranxiaoshi 是否通过GDB检查内核第一条指令的执行情况(参考本章第四节内容)?Qemu版本是否为5.0.0?运行代码仓库的ch1分支是否有输出?

wyfcyx avatar Jan 15 '22 08:01 wyfcyx

@xuanranxiaoshi 也可以看一下是否重新cargo build --release, 以及strip OS内核前的初始化数据。

PeterWrighten avatar Jan 17 '22 18:01 PeterWrighten

有可能就是没有重新cargo build --release并生成os.bin,所以运行的还是之前修改x1的程序,可以看看x1是否被赋值为100,如果是的话就是这个情况了

Adamska1008 avatar Jan 20 '22 14:01 Adamska1008

谢谢大家,已解决

xuanranxiaoshi avatar Jan 21 '22 01:01 xuanranxiaoshi

[rustsbi] enter supervisor 0x80200000 一直停在这里没输出,debug发现_start的偏移地址不在0x80200000,在网上抄了个link脚本搞定了。 OUTPUT_ARCH(riscv) ENTRY(_start) BASE_ADDRESS = 0x80200000;

SECTIONS { . = BASE_ADDRESS;

start = .;
.text : {
    stext = .;
    *(.text.entry)
    *(.text .text.*)
    . = ALIGN(4K);
    etext = .;
}

.rodata : {
    srodata = .;
    *(.rodata .rodata.*)
    . = ALIGN(4K);
    erodata = .;
}

.data : {
    sdata = .;
    *(.data .data.*)
    . = ALIGN(4K);
    edata = .;
}

.bss : {
    sbss = .;
    *(.bss.stack)
    . = ALIGN(4K);
    ebss = .;
}
end = .;

}

zcg0696 avatar Feb 22 '22 11:02 zcg0696

仔细研究linker脚本后发现自已在输入linker脚本时少了.rodata段,导致编译后这段内容放到.text前面去了。

zcg0696 avatar Feb 23 '22 05:02 zcg0696

qemu-system-riscv64
-machine virt
-nographic
-bios ../bootloader/rustsbi-qemu.bin
-device loader,file=target/riscv64gc-unknown-none-elf/release/os.bin,addr=0x80200000
-s -S

是通过这条命令启动 Qemu 运行我们的内核? 太愚笨了

mjh11930673 avatar Feb 24 '22 14:02 mjh11930673

@mjh11930673 是的

wyfcyx avatar Feb 24 '22 15:02 wyfcyx

想问一下sbi.rs中的#![allow(unused)],尝试cargo build时会报error: an inner attribute is not permitted in this context,且编译器提示应改为#[allow(unused)],我字面理解这应该是允许变量未使用的一个宏,因此我改成了#[allow(unused)],可以正常build,是文章写错了吗

jklincn avatar Mar 02 '22 07:03 jklincn

@jklinCN 加上了一点补充说明。

wyfcyx avatar Mar 03 '22 06:03 wyfcyx

我开始也没有输出 然后执行 rust-objcopy --strip-all target/riscv64gc-unknown-none-elf/release/os -O binary target/riscv64gc-unknown-none-elf/release/os.bin 去掉元数据 就有输出了

wuyuesong avatar Mar 06 '22 14:03 wuyuesong

问题:运行make run直接打印「Hello,World和panic具体行数信息」,运行qumu-system-riscv64需要gdb链接调试最后quit才能打印信息,不清楚为什么会有这种区别

运行下面命令qumu加载内核后一直卡顿在那里,没有任何输出。

qemu-system-riscv64 \
  -machine virt \
  -nographic \
  -bios ../bootloader/rustsbi-qemu.bin \
   -device loader,file=target/riscv64gc-unknown-none-elf/release/os.bin,addr=0x80200000 \
   -s -S

按照第四小节gdb调试,最后quit后可输出「Hello,World和panic具体行数信息」

切换到了ch1分支也是这种情况,如果直接运行make run就不会卡顿,不用gdb调试可直接输出「Hello,World和panic具体行数信息」

去看了Makefile里面的代码 也是对qumu-system-riscv64 运行做了封装,并没有什么其他的特殊地方,请问下老师这是什么原因造成的?

baipangbai avatar Mar 10 '22 09:03 baipangbai

@baipangbai 注意,如果不想通过 GDB 对于 Qemu 进行调试而是直接运行 Qemu 的话,则要删掉最后一行的 -s -S

wyfcyx avatar Mar 10 '22 09:03 wyfcyx

   Stdout.write_fmt(args).unwrap();
}```中 fmt::Arguments是什么类型 在实验编写的print时应该填入什么格式参数
我的报错 

| print("world"); | ----- ^^^^^^^ expected struct Arguments, found &str | | | arguments to this function are incorrect

lemon5227 avatar Apr 28 '22 19:04 lemon5227

pub fn print(args: fmt::Arguments){
    Stdout.write_fmt(args).unwrap();
}

中 fmt::Arguments是什么类型 在实验编写的print时应该填入什么格式参数?

下面是我的报错:

 print("world");
   |     ----- ^^^^^^^ expected struct `Arguments`, found `&str`
   |     |
   |     arguments to this function are incorrect

lemon5227 avatar Apr 28 '22 19:04 lemon5227

将字符串按字节切片输出,而不是按字符切片

for c in s.chars() {
   console_putchar(c as usize);
}

修改为

for b in s.bytes() {
    console_putchar(b as usize);
}

可以在终端中显示中文,Emoji

jiangshengdev avatar May 16 '22 12:05 jiangshengdev

he@ubuntu:~/C_TEST/os$ cargo build Compiling os v0.1.0 (/home/he/C_TEST/os) error: cannot find macro println in this scope --> src/lang_items.rs:41:9 | 41 | println!( | ^^^^^^^ | = note: consider importing this macro: crate::println = help: have you added the #[macro_use] on the module/import?

error: cannot find macro println in this scope --> src/lang_items.rs:48:9 | 48 | println!("Panicked: {}", info.message().unwrap()); | ^^^^^^^ | = note: consider importing this macro: crate::println = help: have you added the #[macro_use] on the module/import?

error: could not compile os due to 2 previous errors 这个报错如何解决呀

zhuiYeah avatar Jul 05 '22 02:07 zhuiYeah

@zhuiYeah 注意mod console;前面加上一行#[macro_use],参考这里

wyfcyx avatar Jul 05 '22 20:07 wyfcyx

在lang_items前几行加入 #[macro_use] mod console;

仍出现这个报错file not found for module console --> src/lang_items.rs:6:1 | 6 | mod console; | ^^^^^^^^^^^^ | = help: to create the module console, create file "src/lang_items/console.rs" or "src/lang_items/console/mod.rs"

error: cannot find macro println in this scope

zhuiYeah avatar Jul 05 '22 23:07 zhuiYeah

@zhuiYeah 请参考我们整个框架的代码

wyfcyx avatar Jul 06 '22 15:07 wyfcyx

@zhuiYeah 我也遇到这个问题了。补充说明一下,mod 的顺序有要求。必须是:

#[macro_use]
mod console;
mod lang_items;
mod sbi;

console要在其他两个前面

tomtomtomtony avatar Oct 05 '22 15:10 tomtomtomtony

@zhuiYeah @tomtomtomtony 另一个解决办法是直接在 lang_items.rs 里面引用 mod console;

TerryNex avatar Oct 22 '22 16:10 TerryNex

error[E0554]: #![feature] may not be used on the stable release channel --> src/main.rs:3:12 | 3 | #![feature(panic_info_message)] | ^^^^^^^^^^^^^^^^^^

For more information about this error, try rustc --explain E0554. error: could not compile os due to previous error

oneforever avatar Oct 30 '22 12:10 oneforever

#![feature] may not be used on the stable release channel
同问

我重新倒回第0章 可通过如下命令安装 rustc 的 nightly 版本,并把该版本设置为 rustc 的缺省版本。

rustup install nightly
rustup default nightly

http://rcore-os.cn/rCore-Tutorial-Book-v3/chapter0/5setup-devel-env.html

taotao419 avatar Nov 24 '22 02:11 taotao419

如果已经在rust_main()中添加了 console_putchar() 但是还是没有输出,需要重新cargo build --release 然后再裁减内核镜像 rust-objcopy --strip-all target/riscv64gc-unknown-none-elf/release/os -O binary target/riscv64gc-unknown-none-elf/release/os.bin

Tom-debug110 avatar Jan 12 '23 08:01 Tom-debug110

我的代码反复输出同一条内容,看起来是rust_main -> panic! -> shutdown -> panic! -> shutdown 陷入递归了,我猜原因是在我这儿用于 ecall shutdown 的值可能不是 8,所以 sbi_call(8) 的时候没有真正关机。但我确实是用的 qemu-system-riscv64,而且 rustsbi-qemu 也是拉取最新代码编译的。求助是否有思路定位原因?

Hello, world!
panicked at src/main.rs:17 Shutdown machine!
panicked at src/sbi.rs:27 It should shutdown
panicked at src/sbi.rs:27 It should shutdown
panicked at src/sbi.rs:27 It should shutdown
panicked at src/sbi.rs:27 It should shutdown
panicked at src/sbi.rs:27 It should shutdown
panicked at src/sbi.rs:27 It should shutdown
panicked at src/sbi.rs:27 It should shutdown
panicked at src/sbi.rs:27 It should shutdown

kayoch1n avatar Mar 02 '23 12:03 kayoch1n

请问按照这节写下来后,用qemu运行内核,但是一直没有输出可能是什么原因啊?

运行内核后的输出

[rustsbi] RustSBI version 0.3.0-alpha.4, adapting to RISC-V SBI v1.0.0
.______       __    __      _______.___________.  _______..______   __
|   _  \     |  |  |  |    /       |           | /       ||   _  \ |  |
|  |_)  |    |  |  |  |   |   (----`---|  |----`|   (----`|  |_)  ||  |
|      /     |  |  |  |    \   \       |  |      \   \    |   _  < |  |
|  |\  \----.|  `--'  |.----)   |      |  |  .----)   |   |  |_)  ||  |
| _| `._____| \______/ |_______/       |__|  |_______/    |______/ |__|
[rustsbi] Implementation     : RustSBI-QEMU Version 0.2.0-alpha.2
[rustsbi] Platform Name      : riscv-virtio,qemu
[rustsbi] Platform SMP       : 1
[rustsbi] Platform Memory    : 0x80000000..0x88000000
[rustsbi] Boot HART          : 0
[rustsbi] Device Tree Region : 0x87000000..0x87000ef2
[rustsbi] Firmware Address   : 0x80000000
[rustsbi] Supervisor Address : 0x80200000
[rustsbi] pmp01: 0x00000000..0x80000000 (-wr)
[rustsbi] pmp02: 0x80000000..0x80200000 (---)
[rustsbi] pmp03: 0x80200000..0x88000000 (xwr)
[rustsbi] pmp04: 0x88000000..0x00000000 (-wr)

运行内核所使用的命令

cargo build --release

rust-objcopy --strip-all target/riscv64gc-unknown-none-elf/release/os -O binary target/riscv64gc-unknown-none-elf/release/os.bin

qemu-system-riscv64 \
	machine virt \
	-nographic \
	-bios ../bootloader/rustsbi-qemu.bin \
	-device loader,file=target/riscv64gc-unknown-none-elf/release/os.bin,addr=0x80200000

其中,使用rust-objcopy得到的文件os.bin查看其信息,如下所示

stat os/target/riscv64gc-unknown-none-elf/release/os.bin

# 输出
文件:os/target/riscv64gc-unknown-none-elf/release/os.bin
大小:0               块:0          IO 块大小:4096   普通空文件
设备:803h/2051d        Inode:1108612     硬链接:1
权限:(0775/-rwxrwxr-x)  Uid: ( 1000/zephyrus)   Gid: ( 1000/zephyrus)
访问时间:2023-03-09 15:53:14.616402778 +0800
修改时间:2023-03-09 15:53:05.904545932 +0800
变更时间:2023-03-09 15:53:05.912545800 +0800
创建时间:2023-03-09 15:53:05.904545932 +0800

反汇编的话也是空的

# 执行
rust-objdump -all target/riscv64gc-unknown-none-elf/release/os

# 输出

target/riscv64gc-unknown-none-elf/release/os:   file format elf64-littleriscv

使用gdb进行调试,当运行到位于0x80200000这条指令时,查看查看$pc及后面几条指令,发现都是空

Remote debugging using localhost:1234
0x0000000000001000 in ?? ()
(gdb) b *0x80200000
Breakpoint 1 at 0x80200000
(gdb) c
Continuing.

Breakpoint 1, 0x0000000080200000 in ?? ()
(gdb) x/10i $pc
=> 0x80200000:  unimp
   0x80200002:  unimp
   0x80200004:  unimp
   0x80200006:  unimp
   0x80200008:  unimp
   0x8020000a:  unimp
   0x8020000c:  unimp
   0x8020000e:  unimp
   0x80200010:  unimp
   0x80200012:  unimp

似乎是链接的时候内存布局有问题,导致入口代码没有被排在0x80200000

我已经尝试过评论区中说的重新cargo build --release,以及rust-objcopy --strip-all <> -O binary <>这两个方法,但是还是没有输出。我个人感觉是链接的时候除了问题,但是还是不知道怎么解决这个问题。代码在ZephyrusZhang/rCore。求大佬赐教。

ZephyrusZhang avatar Mar 09 '23 08:03 ZephyrusZhang

@kayoch1n 如果你使用了最新的rustsbi的话,请注意SBI标准已经发生了更改。将源代码改为如下形式可以完成功能。

//src/sbi.rs

use core::arch::asm;
#[allow(unused)]

// legacy extensions: ignore fid
const SBI_SET_TIMER: usize = 0;
const SBI_CONSOLE_PUTCHAR: usize = 1;
const SBI_CONSOLE_GETCHAR: usize = 2;
const SBI_CLEAR_IPI: usize = 3;
const SBI_SEND_IPI: usize = 4;
const SBI_REMOTE_FENCE_I: usize = 5;
const SBI_REMOTE_SFENCE_VMA: usize = 6;
const SBI_REMOTE_SFENCE_VMA_ASID: usize = 7;

// system reset extension
const SRST_EXTENSION: usize = 0x53525354;
const SBI_SHUTDOWN: usize = 0;

#[inline(always)]
fn sbi_call(eid: usize, fid: usize, arg0: usize, arg1: usize, arg2: usize) -> usize {
    let mut ret;
    unsafe {
        asm!(
            "ecall",
            inlateout("x10") arg0 => ret,
            in("x11") arg1,
            in("x12") arg2,
            in("x16") fid,
            in("x17") eid,
        );
    }
    ret
}

pub fn console_putchar(c: usize) {
    sbi_call(SBI_CONSOLE_PUTCHAR, 0, c, 0, 0);
}

pub fn shutdown() -> ! {
    sbi_call(SRST_EXTENSION, SBI_SHUTDOWN, 0, 0, 0);
    panic!("It should shutdown!")
}

raspirin avatar Mar 14 '23 07:03 raspirin

@kayoch1n 如果你使用了最新的rustsbi的话,请注意SBI标准已经发生了更改。将源代码改为如下形式可以完成功能。

//src/sbi.rs

use core::arch::asm;
#[allow(unused)]

// legacy extensions: ignore fid
const SBI_SET_TIMER: usize = 0;
const SBI_CONSOLE_PUTCHAR: usize = 1;
const SBI_CONSOLE_GETCHAR: usize = 2;
const SBI_CLEAR_IPI: usize = 3;
const SBI_SEND_IPI: usize = 4;
const SBI_REMOTE_FENCE_I: usize = 5;
const SBI_REMOTE_SFENCE_VMA: usize = 6;
const SBI_REMOTE_SFENCE_VMA_ASID: usize = 7;

// system reset extension
const SRST_EXTENSION: usize = 0x53525354;
const SBI_SHUTDOWN: usize = 0;

#[inline(always)]
fn sbi_call(eid: usize, fid: usize, arg0: usize, arg1: usize, arg2: usize) -> usize {
    let mut ret;
    unsafe {
        asm!(
            "ecall",
            inlateout("x10") arg0 => ret,
            in("x11") arg1,
            in("x12") arg2,
            in("x16") fid,
            in("x17") eid,
        );
    }
    ret
}

pub fn console_putchar(c: usize) {
    sbi_call(SBI_CONSOLE_PUTCHAR, 0, c, 0, 0);
}

pub fn shutdown() -> ! {
    sbi_call(SRST_EXTENSION, SBI_SHUTDOWN, 0, 0, 0);
    panic!("It should shutdown!")
}

多谢指导。顺便给其他可能遇到类似问题的小伙伴指个路 -> Call SBI in different programming languages

kayoch1n avatar Mar 20 '23 09:03 kayoch1n