xv6-k210/doc/xv6-k210-report-车春池.md

284 lines
9.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
marp: true
---
# **xv6-k210 移植报告**
+ 报告人: 车春池
+ 华中科技大学本科三年级
+ 时间: 2020-12-26
+ 地点: 北京中科院计算所
```
(`-') (`-') <-.(`-')
(OO )_.-> _(OO ) __( OO)
(_| \_)--.,--.(_/,-.\ ,--. (`-') '-'. ,--. .----. .--. .----.
\ `.' / \ \ / (_/ / .' ( OO).-> | .' / \_,-. | /_ | / .. \
\ .') \ / / . / -. (,------. | /) .' .' | | | / \ .
.' \ _ \ /_)' .-. \ `------' | . ' .' /_ | | ' \ / '
/ .'. \ \-'\ / \ `-' / | |\ \ | | | | \ `' /
`--' '--' `-' `----' `--' '--' `------' `--' `---''
```
---
## **前言**
+ `xv6``xv6-riscv``MIT` 写的教学操作系统,在 [github](https://github.com/mit-pdos/xv6-riscv.git) 上开源
+ `xv6` 官方目前只支持 `qemu` 平台
+ `k210``kendryte` 产商于 2018 年发布的 `RISC-V` 双核 64 位处理器
+ `RustSBI`:华科网安同学 `洛佳` 提供的强大的 `Rust` 嵌入式项目,为移植工作提供很大帮助
---
## **移植成果**
+ 多核启动
+ 虚拟内存管理
+ 时钟中断
+ S 态外部中断
+ SD 卡驱动
+ 用户多进程
---
## **运行**
![run](../img/xv6-k210_on_k210.gif)
---
## **为什么选择 xv6**
+ 一开始想要移植 `riscv-pk` 在 k210 上跑,但研究一下其代码之后发现不可行
+ 寻找开源 OS最好是 RISC-V 指令集,简单,并且已经能在 qemu 或者真实板子上运行的
+ 考虑过 seL4,RT-Thread 还有其他的一些开源项目
+ 最终选择 xv6-riscv其简单RISC-V 指令集并且已经在 qemu 上稳定运行
---
## **调研**
+ `MIT` 开源协议
+ `xv6` 复杂程度
+ 架构设计RISC-V SBI 标准
![riscv_software_stack](../img/riscv_software_stack.png)
+ 虚拟环境 vs 真实硬件环境
+ 虚拟硬盘 vs SD 卡
---
## **项目搭建**
+ `MIT` 开源协议
+ 2020-10-18
+ RISC-V 官方编译链https://github.com/riscv/riscv-gnu-toolchain
+ 目录结构
```
xv6-k210
├── bootloader # bootloader 的实现
├── doc # 文档
├── kernel # 内核源码
├── linker # 链接脚本
├── xv6-user # xv6 用户程序
├── mkfs # 制作文件系统镜像的 .c 文件
├── tools # 一些工具
├── target # 目标文件
├── README.md
└── LICENSE # MIT LICENSE
```
---
## **移植工作一览**
+ 多核启动
+ 内存分配
+ 虚拟内存管理
+ 中断处理
+ S 态外部中断
+ 用户多进程
+ SD 卡驱动
+ 文件系统
+ 软硬件协同调试
+ 中文文档
---
## **K210**
+ 两个核心,双核对等,具备独立 FPU
+ 64 位处理核
+ 标称频率为 400MHZ
+ 双精度浮点处理单元
+ PLIC 支持高级中断管理
+ CLINT 支持 CPU 内置定时器中断与跨核心中断
+ 8M 的片上 SRAM
+ **S 态实现有问题**
---
## **K210 SRAM**
|模块名称|映射类型|开始地址|结束地址|空间大小|
|---|---|---|---|---|
|通用 SRAM 存储器|经 CPU 缓存|0x80000000|0x805FFFFF|0x600000|
|AI SRAM 存储器|经 CPU 缓存|0x80600000|0x807FFFFF|0x200000|
|通用 SRAM 存储器|非 CPU 缓存|0x40000000|0x405FFFFF|0x6000000|
|AI SRAM 存储器|非 CPU 缓存|0x40600000|0x407FFFFF|0x200000|
---
## **K210 VS QEMU**
+ 指令集标准版本不同qemu 是 v1.11k210 是 v1.9.1
+ `MMIO` 内存布局不同
+ 虚拟文件系统 vs SD 卡上的文件系统
---
## **RustSBI**
+ 脱胎于 2020 年暑假鹏城实验室的“rCore代码之夏”活动
+ 操作系统二进制接口标准SBI 标准)的一种实现
+ Rust 语言编写
+ 模块化设计,方便支持新的平台
+ 进入国际 RISC-V SBI 实现列表,获得编号 4
| Implementation ID | Name |
|--- |--- |
| 0 | Berkeley Boot Loader (BBL)|
| 1 | OpenSBI |
| 2 | Xvisor |
| 3 | KVM |
| **4** | **RustSBI** |
| 5 | Diosix |
---
## **多核启动**
+ 内核镜像和 RustSBI 镜像并在一起使用 py 脚本烧到 k210 的 SRAM 中
+ k210 起电运行 RustSBI然后跳转到内核入口点
+ `RustSBI` 提供接口,使得可以在启动的第 0 个核中唤醒其他核
---
## **多核启动**
![boot](../img/boot.jpg)
---
## **虚拟内存管理**
+ `vm.c`
+ 维护一个内核页表 `kernel_pagetable`
+ 这个内核页表记录了 MMIO内核空间用户态空间 RustSBI 从虚拟地址到物理地址的映射
+ 在 void kvminithart() 里面将内核页表的首地址放到 `satp` 寄存器,然后运行 `sfence.vma` 指令
---
## **虚拟内存管理**
**但是!! K210 采用的是 1.9 版本的 RISC-V 标准,不存在 sfence.vma 这条指令,只有旧版指令 sfence.vm**
怎么办?求助 `RustSBI`
---
## **虚拟内存管理**
**RustSBI 如何解决这个问题?**
+ `sfence.vma` 作为异常指令被 `RustSBI` 捕获
+ 读取 `satp`(读取 `ppn`
+ 根据第二步读取的值写 `sptbr` v1.9 指令集版本使用的寄存器,相当于 `satp`)设置页表
+ 设置 `mstatus` 中相应的位开启分页(内核无法做这个工作)
+ 运行旧版指令 `sfence.vm` 清空 `TLB`
+ 写 `mepc` 并返回到 `sfence.vma` 的下一条指令去运行(`mepc + 4`
---
## **虚拟内存管理**
<!-- <img src="../img/mem_map.jpg"> -->
![mem_map](../img/mem_map.jpg)
---
## **时钟中断**
**通过 RustSBI 设置时钟中断**
+ `timer.c`
+ 参考 `rCore` 实现
+ 通过 SBI 调用实现
```
static inline void sbi_set_timer(uint64 stime_value)
{
SBI_CALL_1(SBI_SET_TIMER, stime_value);
}
```
+ 神奇的 bugset_next_timeout 中的 printf("");
---
## **S 态外部中断**
以下参考吴一凡学长的文档,如有雷同,纯属照搬。
为什么需要移植 S 态外部中断?
+ **RustSBI 运行在 M 态OS 内核运行在 S 态**
+ **想要使用 S 态众多的数据结构来对外部中断进行处理**
移植 S 态外部中断遇到的问题:`k210` 上没有 S 态外部中断!
怎么办?
**求助 RustSBI**
---
## **S 态外部中断**
**RustSBI 使用黑科技解决 K210 上 S 态外部中断**
感谢吴一凡学长移植 `rCore``k210` 上的文档和洛佳同学的解惑。
不敢班门弄斧,只说一下步骤:
+ `RustSBI` 提供一个接口
```Rust
match cause {
Trap::Exception(Exception::SupervisorEnvCall) => {
if trap_frame.a7 == 0x0A000004 && trap_frame.a6 == 0x210 {
// We use implementation specific sbi_rustsbi_k210_sext function (extension
// id: 0x0A000004, function id: 0x210) to register S-level interrupt handler
// for K210 chip only. This chip uses 1.9.1 version of privileged spec,
// which did not declare any S-level external interrupts.
...
} else {
...
}}}
```
+ S 态外部中断处理函数 `supervisor_external_handler`
+ 将这个函数指针作为参数调用 `RustSBI` 提供的接口
+ 外部中断将会在 `supervisor_external_handler` 中处理
---
## **用户多进程**
![proc](../img/proc.jpg)
---
## **SD 卡驱动**
+ `sdcard.c`
+ 官方 SDK demo 实现了读取 sd 卡的例程
+ 暴力出奇迹,移植官方 SDK 到内核中
+ 问题:官方 SDK 编译链不同,代码太多,依赖关系复杂
+ 和很多外设打交道,比如 GPIOFPIO 等等,还需要调整时钟信号
+ 最终将官方 SDK 部分模块移植到了内核中,成功通过 SD 卡读取测试
+ SD 卡读写还不稳定
+ C 开发环境缺乏包管理工具
---
## **文件系统**
+ 由于 SD 卡读写不稳定的问题还没解决,还没完成
+ xv6 文件系统 or Fat32 文件系统 or 全都要
---
## **软硬协同调试**
+ 硬件调试非常非常麻烦,希望有软件调试环境
+ `Makefile` + 条件编译
+ `make run [platform=xxx]`
+ 类似于封装硬件抽象层
+ `RustSBI` 基本上处理了大部分平台无关性
+ 软件调试,一键部署
---
## **依赖于 RustSBI 的模块**
- [x] 多核启动
- [ ] 内存分配
- [x] 虚拟内存管理(`sfence.vma` 指令)
- [x] 时钟中断
- [x] S 态外部中断(其实有 bug 还没修)
- [ ] 用户多进程
- [x] SD 卡驱动
- [x] 文件系统
- [x] 平台无关性
---
## **中文文档**
+ 移植文档
+ `xv6-riscv` 原理文档
---
## **致谢**
+ 感谢比赛方和陈渝老师提供这次演讲机会,并且感谢邵志远老师一直以来对我的支持
+ `xv6-k210` 项目得到了很多同学的支持,特别是华科 18 级计卓班的刘一鸣和陆思彤同学,进程管理这部分的调试工作大部分是他们在做
+ 感谢 `RustSBI` 项目
+ 感谢 `rCore-Tutorial` 项目和今年暑假在鹏城实验室的`代码之夏`活动,让我踏入了 `Rust` 语言和体系结构的大门
+ 感谢洛佳同学和吴一凡学长技术上的帮助
---
## **谢谢各位**
华中科技大学
计算机科学与技术学院
校交 1801 班
车春池