2023年秋冬季开源操作系统训练营第二阶段的日常学习记录
一:github的访问不够通畅,影响偏大。我这github.io没有打开过。
二:感觉第零章的导引功能需要增强,比如项目布局、代码结构、相关资料、相关配置、以及如何应对意外情况,后续进度章节需要注的前提要件,都可以放到第零章,使刷过第零章后就知道本训营进度的整体需要把握、细节需要注意的事项。
三:本章要求实验均默认已有代码完成,但是需要熟悉项目代码结构。
三:本章节需手动完成的是bootloader替换,完成关机代码的替换。
四:预备知识没有提前顾备,刚开始比较蒙。
git clone https://github.com/LearningOS/2023a-rcore-put-down-crate.git
使用命令
$ cd 2023a-rcore-put-down-crate
$ git checkout ch1
$ cd os
$ make run
所有硬件加电自检后都要将硬件控制权交由引导程序,再由引导程序引导软件系统进行启动,通过驱动程序与相关硬件进行交互,达成软件系统的运行状态。
qemu做为硬件模拟器,那么问题出现的位置大概在qemu与bootloader之间。
sudo ln -s /usr/sbin/riscv64-elf-gdb /usr/sbin/riscv64-unknown-elf-gdb
从仓库
https://github.com/rustsbi/rustsbi
下载最后发布的rustsbi release版本 & debug版本。
解压release版本得到文件 rustsbi-qemu.bin
,将此文件复制到
2023a-rcore-put-down-crate/bootloader
目录下覆盖原有文件,怕出错可以先把原文件改名做备份。
然后进入2023a-rcore-put-down-crate/os
目录,运行命令:
$ make run
编译运行结果:
[rustsbi] RustSBI version 0.2.2, adapting to RISC-V SBI v1.0.0
.______ __ __ _______.___________. _______..______ __
| _ \ | | | | / | | / || _ \ | |
| |_) | | | | | | (----`---| |----`| (----`| |_) || |
| / | | | | \ \ | | \ \ | _ < | |
| |\ \----.| `--' |.----) | | | .----) | | |_) || |
| _| `._____| \______/ |_______/ |__| |_______/ |______/ |__|
[rustsbi] Implementation: RustSBI-QEMU Version 0.1.1
[rustsbi-dtb] Hart count: cluster0 with 1 cores
[rustsbi] misa: RV64ACDFHIMSU
[rustsbi] mideleg: ssoft, stimer, sext (0x1666)
[rustsbi] medeleg: ima, ia, bkpt, la, sa, uecall, ipage, lpage, spage (0xb1ab)
[rustsbi] pmp0: 0x10000000 ..= 0x10001fff (rw-)
[rustsbi] pmp6: 0x2000000 ..= 0x200ffff (rw-)
[rustsbi] pmp12: 0xc000000 ..= 0xc3fffff (rw-)
[rustsbi] enter supervisor 0x80200000
[kernel] Hello, world!
kernel给出了祖传helloworld,大概算正常运行了吧。
本章代码默认已实现
本章代码默认已实现
可以关闭内核所有输出。从 lab2 开始要求关闭内核所有输出(如果实现了 log 等级控制,那么这一点自然就实现了)。
输出 .text、.data、.rodata、.bss 各段位置,输出等级为 INFO。 本章代码默认已实现
S-Mode Supervisor模式=》操作系统使用特权级别可执行特权指令
M-Mode Machine模式=》特权级别比S-Mode更高,可以访问RISC-V处理器中所有系统资源
https://www.rustwiki.org.cn/zh-CN/core/index.html
将一个多位数的低位放在较小的地址处,高位放在较大的地址处,则称小端序(little-endian);反之则称大端序(big-endian)。
对于 RISC-V 处理器而言,load/store 指令进行数据访存时,数据在内存中的地址应该对齐。如果访存 32 位数据,内存地址应当按 32 位(4 字节)对齐。
如果数据的地址没有对齐,执行访存操作将产生异常。这也是在学习内核编程中经常碰到的一种bug。
三个地址:
QEMU开始执行 --> 物理地址0x1000
bootloader开始执行 --> 物理地址0x80000000
内核开始执行 --> 物理地址0x80200000
QEMU CPU 程序计数器初始化为0x1000, 因此QEMU第一条指令在物理地址0x1000, 第一阶段指令完成后,跳转到物理地址0x80000000,此地址是固化在QEMU的,不通过源码无法修改。
本阶段自物理地址0x80000000开始执行,主要执行rustsbi_qemu.bin加载到本段的内容,然后跳转到物理地址0x80200000。
本段自物理地址0x80200000开始执行,主要执行内核镜像加载到本段的内容。
High Address | stack |^^^^^^^^^^^^^^^^
| |
| heap |
| .bss | Data Memory
| .data |
| .rodata |_________________________
Low Address | .text | Code Memory
bootloader加载内核文件时会将内核文件相关多余的元数据(大概会是些自描述环境配置之类的)丢掉,然后加载到0x80200000位置的称为内核镜像
寄存器组a0--a7(x10--x17),保存者为--调用者保存,用来传递输入参数。其中a0和a1还用来保存返回值
寄存器组t0--t6(x5--x7,x28--x31),保存者为--调用者保存,做为临时寄存器使用,在被调函数中可以随意使用无需保存
寄存器组s0--s11(x8--x9,x18--x27),保存者为--被调用者保存,作为临时寄存器使用,被调用函数保存后才能在被调用函数中使用
zero(x0)恒为零,函数调用不会对它产生影响
ra(x1)被调用者保存
sp(x2)被调用者保存
fp(s0)做为s0临时寄存器,做为栈帧指针(Frame Pointer)寄存器
gp(x3)和tp(x4)在一个程序运行期间都不会变化,因此不必放在函数调用上下文中
栈上多个fp信息实际上保存了一条完整的函数调用链
ra,sp,fp是和函数调用紧密相关的寄存器