vue-video-player修改src就会报错_4、修改入口点代码

在riscv上电时,会进行CPU自检,然后跳转到bootloader处执行。bootloader设置好kernel的运行环境后,从硬盘加载kernel到内存,最后再跳转到kernel入口地址。

我们采用的bootloader为OpenSBI,被加载到0x80000000地址,OpenSBI探测好外设并初始化内核的环境变量后,加载内核到0x80200000地址,最后再跳转到0x80200000地址。从上文我们知道,我们的入口点_start地址正好为0x80200000,也就是OpenSBI会调用我们kernel的_start函数。

在riscv64中,有如下几种特权级:

f05f87f5e7f30c472c1bd88aae6d48fd.png

User模式:该特权模式为权限最小的模式,在linux系统中用户态就运行在该特权级;

Supervisor模式:该特权级时linux操作系统运行的模式,特权级别比User模式高;

Machine模式:CPU上电启动后运行在该特权模式,该特权比Supervisor更高。

从 U 到 S 再到 M,权限不断提高,这意味着你可以使用更多的特权指令,访需求权限更高的寄存器等等。我们可以使用一些指令来修改 CPU 的当前特权级

riscv64 的 M Mode

M-mode(机器模式,缩写为 M 模式)是 RISC-V 中 hart(hardware thread,硬件线程)可以执行的最高权
限模式。在 M 模式下运行的 hart 对内存,I/O 和一些对于启动和配置系统来说必要的底层功能有着完全的
使用权。

riscv64 的 S Mode

S-mode(监管者模式,缩写为 S 模式)是支持现代类 Unix 操作系统的权限模式,支持现代类 Unix 操作系
统所需要的基于页面的虚拟内存机制是其核心。

OpenSBI运行在Machine模式,当跳转到kernel地址0x80200000执行时,会切换到Supervisor模式执行。

在我们之前的 _start() 代码中只执行了loop,也就是无限循环,没有做任何实质的操作。现在我们需要添加不同的功能,因此就需要设置一下kernel内核的运行环境。这个运行环境我们首先需要设置的是内核堆栈,在rust函数调用时会使用到这个堆栈,如果我们不设置sp的地址,那么就可能使用sp指向的任何地址,这将给程序带来意想不到的后果。

由于riscv64的sp地址不能通过rust语言设置,因此这部分的环境变量就需要在汇编程序下设置:

# src/boot/entry_riscv64.asm
    .section .text.entry
    .global _start
_start:
    la sp, bootstacktop
    call rust_main

    .section .bss.stack
    .align 12
    .global bootstack
bootstack:
    .space 4096 * 4
    .global bootstacktop
bootstacktop:

_start 程序放在 .text.entry 这个段中,我们链接脚本中将 .text.entry 放在了.text 段的第一个位置,也就是将_start函数放在了.text的第一个位置。

在_start开始处,将堆栈的顶部地址加载到sp寄存器中,并且堆栈的大小为16k,然后调用rust_main函数。

在main.rs中,我们将_start函数删除,并且添加rust_main函数。

#![no_main]
#![no_std]

use core::panic::PanicInfo;

#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
    loop{}
}

#[no_mangle]
extern "C" fn rust_main() -> ! {
    loop{}
} 

为了支持汇编代码,我们需要开启global_asm特性,因此我们在main.rs中开启该特性,并包含src/boot/entry_riscv64.asm汇编代码:

#![no_main]
#![no_std]

use core::panic::PanicInfo;

#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
    loop{}
}

#![feature(global_asm)]
global_asm!(include_str!("boot/entry_riscv64.asm"));

#[no_mangle]
extern "C" fn rust_main() -> ! {
    loop{}
} 

注意,上面中我们将汇编特性代码添加在panic_handler下面,此时会报错:

error: an inner attribute is not permitted in this context
  --> src/main.rs:11:1
   |
11 | #![feature(global_asm)]
   | ^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.

error[E0658]: use of unstable library feature 'global_asm': `global_asm!` is not stable enough for use and is subject to change
  --> src/main.rs:13:1
   |
13 | global_asm!(include_str!("boot/entry_riscv64.asm"));
   | ^^^^^^^^^^
   |
   = note: see issue #35119 <https://github.com/rust-lang/rust/issues/35119> for more information
   = help: add `#![feature(global_asm)]` to the crate attributes to enable

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0658`.
error: could not compile `rust_os`.

这里显示错误的原因为global_asm是不稳定的功能,需要使用nightly来编译程序。但我们此时已经是使用nightly了。正真的原因是#![feature(global_asm)]特性代码放在了panic_handler代码的后面,解决的办法是#![feature(global_asm)]特性必须放在文件开头的位置,修改后的代码如下:

#![no_main]
#![no_std]
#![feature(global_asm)]

use core::panic::PanicInfo;

#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
    loop{}
}

global_asm!(include_str!("boot/entry_riscv64.asm"));

#[no_mangle]
extern "C" fn rust_main() -> ! {
    loop{}
} 

此时可以编译通过了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值