add TOC and inter-page links

pull/1/head
Zhiyuan Shao 4 years ago
parent 4d06391314
commit f0cae190cf

@ -5,6 +5,13 @@
[前言](preliminary.md)
[第一章. RISC-V体系结构](chapter1.md)
- [1.1 RISC-V发展历史](chapter1.md#history)
- [1.2 RISC-V汇编语言](chapter1.md#assembly)
- [1.3 机器的特权状态](chapter1.md#machinestates)
- [1.4 中断和中断处理](chapter1.md#traps)
- [1.5 页式虚存管理](chapter1.md#paging)
- [1.6 什么是代理内核](chapter1.md#proxykernel)
- [1.7 相关工具软件](chapter1.md#toolsoftware)
[第二章. 实验1非法指令的截获](chapter2.md)

@ -1,7 +1,17 @@
## 第一章RISC-V体系结构
本章的1.1节将简单介绍RISC-V的诞生和发展历史其后将介绍和讨论RISC-V体系结构的各个方面如1.2节介绍汇编语言、1.3节讨论机器状态、1.4节分析中断和中断处理机制、1.5节讨论分页机制。最后在1.6节介绍PKE实验涉及的工具软件以及它们的使用方法。值得注意的是RISC-V的体系结构本身就是一个庞大的知识体系实际上是很难用一章的内容完全讲清楚的我们鼓励对该体系结构感兴趣的读者延申阅读参考文献[开源指令集的指南]以及[RISC-V instruction set manual]。然而不懂体系结构又无法理解操作系统和开展PKE的实验所以本章将重点阐述和讨论与操作系统设计有关的知识内容力求精简和突出重点。
### 目录
- [1.1 RISC-V发展历史](#history)
- [1.2 RISC-V汇编语言](#assembly)
- [1.3 机器的特权状态](#machinestates)
- [1.4 中断和中断处理](#traps)
- [1.5 页式虚存管理](#paging)
- [1.6 什么是代理内核](#proxykernel)
- [1.7 相关工具软件](#toolsoftware)
本章的1.1节将简单介绍RISC-V的诞生和发展历史其后将介绍和讨论RISC-V体系结构的各个方面如1.2节介绍汇编语言、1.3节讨论机器状态、1.4节分析中断和中断处理机制、1.5节讨论分页机制。最后在1.6节介绍PKE实验涉及的工具软件以及它们的使用方法。值得注意的是RISC-V的体系结构本身就是一个庞大的知识体系实际上是很难用一章的内容完全讲清楚的我们鼓励对该体系结构感兴趣的读者延申阅读参考文献[开源指令集的指南](#references)以及[RISC-V instruction set manual](#references)。然而不懂体系结构又无法理解操作系统和开展PKE的实验所以本章将重点阐述和讨论与操作系统设计有关的知识内容力求精简和突出重点。
<a name="history"></a>
### 1.1 RISC-V发展历史
RISC-V读做“risk-five”是一种典型的精简Reduced Instruction Set Computer简写为RISC指令集Instruction Set Architecture简写为ISA它是加利福尼亚大学伯克利分校的David Patterson教授与Krste Asanovic教授研究团队于2010年提出的一个开放指令集架构。名称中的“V”指的是该ISA的第五个版本有时“V”也被解读为向量Vector扩展。与之前的诸多商用指令集如x86、ARM以及MIPS等不同的是RISC-V是一个开放指令集它的提出受到了全球工业界和学术界的广泛关注。在我国RISC-V的发展、研究和应用同样得到了广泛关注在网信办、工信部、中科院等多个国家部委支持和指导下中国开放指令生态RISC-V联盟于2018年11月8日浙江乌镇举行的第五届互联网大会上正式宣布成立。
@ -14,7 +24,7 @@ RISC-V读做“risk-five”是一种典型的精简Reduced Instruction
**场景丰富**。RISC-V指令集的设计综合考虑了多种应用场景涵盖了从嵌入式低功耗应用到高性能服务器场景为各种场景考虑并设计了多个不同但指令上接近的分支。在这一点上RISC-V跟ARM类似针对不同应用场景RISC-V也都有对应版本。
**开源参考**。自RISC-V提出以来工业界和学术界都积极开展了对其的应用和研究出现了大量的开源实现参见[RISC-V开源项目列表]。这些开源实现为具体应用领域的开发者提供了大量可借鉴的参考同时也极大地降低了CPU的设计门槛。可以预见的是随着大量基于该指令集的芯片开源项目的诞生RISC-V的发展将像开源软件生态中的Linux那样成为计算机芯片与系统领域创新的基石。
**开源参考**。自RISC-V提出以来工业界和学术界都积极开展了对其的应用和研究出现了大量的开源实现参见[RISC-V开源项目列表](#refenences)。这些开源实现为具体应用领域的开发者提供了大量可借鉴的参考同时也极大地降低了CPU的设计门槛。可以预见的是随着大量基于该指令集的芯片开源项目的诞生RISC-V的发展将像开源软件生态中的Linux那样成为计算机芯片与系统领域创新的基石。
在本书所设计的实验中我们主要考虑通用计算场景所以选择RV64G作为我们目标计算机的指令集。其中RV64G中的“RV”代表RISC-V“64”代表所支持的指令是64位的实际上交叉编译器在生成代码时可能会采用32位指令减小生成的目标代码长度地址长度和寄存器长度都为64位而“G”代表通用general计算平台。实际上“G”等效于“IMAFD”其中“I”代表整数Integer计算指令、整数load、整数store以及控制流如分支跳转指令这些指令在任何RISC-V的实现中都是必须的“M”代表乘法Multiply即平台支持乘法和除法运算“A”代表原子Atomic扩展支持对寄存器进行的原子读、修改和原子写操作这些操作在多核设计中非常有用“F”代表单精度浮点Float运算支持“D”代表双精度浮点Double运算支持。
@ -22,9 +32,10 @@ RISC-V读做“risk-five”是一种典型的精简Reduced Instruction
考虑到今天64位电脑x86_64已广泛普及到桌面、服务器我们通常接触到的操作系统如Ubuntu、Windows10等都是内置的64位编译器编译出来的二进制代码特别是我们将要用到的RISC-V模拟器也都默认是64位我们将PKE实验的目标平台类型设定为桌面电脑采用通用版本RV64G
<a name="assembly"></a>
### 1.2 RISC-V汇编语言
关于RISC-V汇编语言较好的中文参考资料有《RISC-V手册——一本开源指令集的指南》参见[开源指令集的指南]里面完整列举和解释了RISC-V的所有汇编指令感兴趣的读者可以通过阅读该书了解RISC-V汇编。在这里我们不打算详细讨论RISC-V的汇编知识只重点讨论RISC-V汇编与8086汇编的不同以及PKE的代码涉及到的一些汇编语法和指令。
关于RISC-V汇编语言较好的中文参考资料有《RISC-V手册——一本开源指令集的指南》参见[开源指令集的指南](#refenences)里面完整列举和解释了RISC-V的所有汇编指令感兴趣的读者可以通过阅读该书了解RISC-V汇编。在这里我们不打算详细讨论RISC-V的汇编知识只重点讨论RISC-V汇编与8086汇编的不同以及PKE的代码涉及到的一些汇编语法和指令。
**1.2.1 寄存器**
@ -73,7 +84,7 @@ RISC-V汇编指令的格式与8086汇编是截然不同的。以最基础的加
其中rd代表目标寄存器register destinationrs1和rs2分别代表源寄存器1register source和源寄存器2immediate代表立即数。前一条指令的执行效果是将两个源寄存器rs1和rs2中所存储的值进行求和并将结果写到rd寄存器后一条指令的执行将源寄存器1中的值与立即数相加结果写到rd寄存器忽略算术溢出。需要注意的是由于我们采用了64位指令集意味着以上指令中所有的操作数无论是rd还是rs中的值以及immediate都是64位的。如果immediate不足64位则对其进行符号位最高位扩展到64位。如果要操作更小一点的数则需要用到addw它最后的w符号表示操作数为一个字32位
以上我们只是以add汇编指令作为例子举例说明了RISC-V汇编语言。读者会发现跟8086汇编语言相比RISC-V汇编语言在语法上有着根本的区别源和目的寄存器的位置是不一样的。由于本书是操作系统课程的实验指导无法完整地列举和解释所有RISC-V汇编指令我们强烈建议读者继续阅读参考文献中的[开源指令集的指南]进一步了解RISC-V汇编语言。
以上我们只是以add汇编指令作为例子举例说明了RISC-V汇编语言。读者会发现跟8086汇编语言相比RISC-V汇编语言在语法上有着根本的区别源和目的寄存器的位置是不一样的。由于本书是操作系统课程的实验指导无法完整地列举和解释所有RISC-V汇编指令我们强烈建议读者继续阅读参考文献中的[开源指令集的指南](#refenences)进一步了解RISC-V汇编语言。
**1.2.3访存和寻址模式**
@ -293,6 +304,7 @@ clobbered_regs破坏描述部分
我们看到不同的函数具有的栈帧stack frame的大小实际上是很不一样的一般来说简单的函数如main和bar的栈帧比较小都只有16个字节。这是因为对于函数来说栈的作用在于保存进入时的现场、函数中被使用的寄存器以及函数的局部变量。对于简单的函数而言其使用的寄存器较少同时也没啥局部变量这些因素就导致了较小的栈帧。另外这个函数调用过程中比较有趣的是ra和fp两个寄存器。ra寄存器指向函数的返回地址一般会在函数入口处入栈。但是对于bar函数来说因为它是叶子函数leaf function处于函数调用的最后一级所以就无需将ra寄存器入栈。fp寄存器则指向上一级函数的栈帧函数在入口处都需要将它存入栈中因为只有这样函数才能够找到来时的路在返回时做到有路可走。
<a name="machinestates"></a>
### 1.3 机器的特权状态
采用RV64G指令集的处理器定义了三种特权模式运行在最高特权级的机器模式machine mode运行在次高特权级的监管者模式supervisor mode以及最低特权级的用户模式user mode。机器模式是启动后计算机所处的模式在该模式下能够运行所有特权指令访问所有内存空间。监管者模式所处的特权级略低于机器模式但仍能够运行部分特权指令以及访问机器模式所规定的所有内存空间。用户模式的特权级最低无法执行改变机器状态的特权指令和访问超过应用程序范围的内存空间。为后续讨论的方便我们有时会简称机器模式为M模式监管者模式为S模式用户模式为U模式。
@ -305,7 +317,7 @@ clobbered_regs破坏描述部分
通过《操作系统原理》课我们知道,**现代的处理器定义不同特权级的根本原因,是为了对操作系统进行保护**。例如让操作系统运行在较高的特权模式而用户代码则运行在较低的特权模式以防止用户态代码执行恶意的动作破坏操作系统。然而用户态的代码在它的生命周期里往往会要求做一些“合法”的特权模式行为例如进行I/O典型例子如常用的printf函数这就意味着处理器同时需要支持特权模式的转换control transfer。在RISC-V处理器中实现这种特权模式转换的工具就是中断当执行在低特权模式的代码被中断时处理器将进入更高特权模式执行中断处理例程来处理打断低特权代码执行的事件。中断处理完成后处理器将从高特权模式返回低特权模式。这里的中断有时被称为异常或系统调用我们将在1.4节详细讨论中断的分类、相关术语和处理过程。需要注意的是RISC-V处理器可以实现跨特权模式的转换例如从U模式直接进入M模式或者从M模式返回U模式这些转换的发生都取决于机器的状态寄存器的设置。
RISC-V为每一种特权模式定义了一组寄存器用于控制机器的状态status以及实现状态的转换。对于操作系统而言比较重要的是机器模式和监管模式的一组寄存器Control and Status Registers简写为CSRs下面我们将分别讨论这两种模式下的CSR以及状态转换的实现。需要说明的是关于RISC-V机器的特权状态[RISC-V instruction set manual]是一个比较好的文档,这里我们将重点讨论与操作系统相关的内容。
RISC-V为每一种特权模式定义了一组寄存器用于控制机器的状态status以及实现状态的转换。对于操作系统而言比较重要的是机器模式和监管模式的一组寄存器Control and Status Registers简写为CSRs下面我们将分别讨论这两种模式下的CSR以及状态转换的实现。需要说明的是关于RISC-V机器的特权状态[RISC-V instruction set manual](#refenences)是一个比较好的文档,这里我们将重点讨论与操作系统相关的内容。
**1.3.1 机器模式下的CSR**
@ -406,7 +418,7 @@ SUMpermit Supervisor User Memory access位用于控制S模式下的虚拟
需要注意的是对于表1.5中的csrc、csrs、csrrs、csrrc以及csrrw指令都有其立即数版本。例如csrci就是csrc的立即数版本立即数版本将rs1替换为立即数并取立即数的低5位参与运算。立即数版本的功能跟非立即数版本一致但因为我们设计的实验PKE较少用到这类指令所以我们并未把它们列入表1.5中。
<a name="traps"></a>
### 1.4 中断和中断处理
通过上一节的讨论,我们知道中断是处理器在实现特权级之间 “穿越”特别是从低特权模式向高特权模式进行控制转移的重要工具和手段。由于历史或翻译的原因各种文献特别是原理课的教材中与中断相关的名词多且繁杂然而对中断概念的理解又是操作系统中非常重要的一环。我们将在1.4.1节对中断的概念和分类进行讨论力求厘清与中断相关的各种表述帮助读者形成对中断的准确理解和表达。在1.4.3节我们将讨论RISC-V处理器的中断处理并在1.4.4节介绍RISC-V平台的中断代理机制。
@ -417,7 +429,7 @@ SUMpermit Supervisor User Memory access位用于控制S模式下的虚拟
在RISC-V处理器上中断并不一定意味着特权级的变迁RISC-V支持平级中断例如简单嵌入式设备上从M模式到M模式的中断但是对于传统意义的操作系统而言由于多个特权级例如我们考虑的M+S+U模式的RISC-V机器的存在中断处理例程往往在比用户模式也就是被中断的用户程序所运行的特权模式更高级别的特权模式中如监管模式或机器模式执行。对操作系统而言这样做也可以更好地对操作系统本身以及计算机的内存资源以及I/O资源进行保护。
实际系统中导致中断发生的事件往往是比较复杂的,它们的来源、处理时机和返回方式都不尽相同。为了便于读者对中断的理解以及表达的准确性,我们借鉴参考文献[SiFive Interrupt]的中断分类标准将系统中发生的可能中断当前执行程序的事件分为3类
实际系统中导致中断发生的事件往往是比较复杂的,它们的来源、处理时机和返回方式都不尽相同。为了便于读者对中断的理解以及表达的准确性,我们借鉴参考文献[SiFive Interrupt](#refenences)的中断分类标准将系统中发生的可能中断当前执行程序的事件分为3类
**Exception**(异常):这类中断是处理器在执行某条指令时,由于条件不满足而产生的。典型的异常有除零错误、缺页、执行当前特权级不支持的指令等。**相对于正在执行的程序而言exception是同步synchronous发生的。exception产生的时机是指令执行的过程中即处理器流水线的执行阶段在exception处理完毕后系统将返回发生exception的那条指令重新执行**。
@ -441,7 +453,7 @@ SUMpermit Supervisor User Memory access位用于控制S模式下的虚拟
**1.4.2中断向量表**
系统发生中断我们用中文的“中断”这个名词来指代广义的中断并非以上的interrupt时执行的这段程序往往被称为**中断例程**interrupt routine。因为事件的多样性系统可能有多个这样的中断例程通常的做法是把这些例程的入口放在一张表中而这张表一般称为**中断向量表**interrupt table。RV64G处理器在发生中断后会将发生的中断类型、编号自动记录硬件完成到目标模式的CSR中。假设发生中断的目标模式为M模式则中断的这些信息会记录到mcause寄存器。表1.7列出了mcause的可能取值以及对应的中断信息为简化讨论我们只考虑为处理器配置本地中断控制器Core Local Interrupt即CLINT的情况[SiFive Interrupt])。
系统发生中断我们用中文的“中断”这个名词来指代广义的中断并非以上的interrupt时执行的这段程序往往被称为**中断例程**interrupt routine。因为事件的多样性系统可能有多个这样的中断例程通常的做法是把这些例程的入口放在一张表中而这张表一般称为**中断向量表**interrupt table。RV64G处理器在发生中断后会将发生的中断类型、编号自动记录硬件完成到目标模式的CSR中。假设发生中断的目标模式为M模式则中断的这些信息会记录到mcause寄存器。表1.7列出了mcause的可能取值以及对应的中断信息为简化讨论我们只考虑为处理器配置本地中断控制器Core Local Interrupt即CLINT的情况[SiFive Interrupt](#refenences))。
表1.7 mcause寄存器的取值由Interrupt及Code字段拼接及值的含义
@ -564,12 +576,10 @@ csrw medeleg, 1<<0 | 1<< 3 | 1<<8 | 1<<12 | 1<<13 | 1<<15
这段代码的作用是将M模式中interrupt中的1、5和9号分别对应Supervisor software interruptSupervisor timer interrupt和Supervisor external interrupt代理出去到S模式处理再将M模式中的exception或trap中的0、3、8、12、13和15号分别对应Instruction address misaligned调试中断Breakpoint3号用户态系统调用Environment call from U-mode8号缺页或访存异常12、13和15号代理出去到S模式处理。实际上将这些重要的中断代理出去后系统中产生的绝大部分中断事件将都在S模式处理。所以在其后的PKE实验中读者主要跟U模式以及S模式的代码打交道除启动过程和一些简单的设置如访存、中断代理等实验也基本不涉及M模式的代码。
[//]:# (### 1.5 页式虚存管理)
[comment]: <> (### 1.5 页式虚存管理)
###1.5 页式虚存管理 ###
<a name="paging"></a>
### 1.5 页式虚存管理
<div id="paging"></div>我们知道程序中的代码对数据进行访问如使用load和store指令采用的是数据的逻辑地址即程序地址。然而将程序装入内存时装载器无法保证数据的逻辑地址和物理地址内存的编址之间有完全相等的关系。实际上由于操作系统往往是计算机装入物理内存的第一个程序如果仔细规划逻辑地址空间还能勉强建立操作系统程序内部逻辑地址到其所装入的物理内存的物理地址间的相等关系但是这一点对于后续装入的应用程序几乎是无法也不可能保证的。
我们知道程序中的代码对数据进行访问如使用load和store指令采用的是数据的逻辑地址即程序地址。然而将程序装入内存时装载器无法保证数据的逻辑地址和物理地址内存的编址之间有完全相等的关系。实际上由于操作系统往往是计算机装入物理内存的第一个程序如果仔细规划逻辑地址空间还能勉强建立操作系统程序内部逻辑地址到其所装入的物理内存的物理地址间的相等关系但是这一点对于后续装入的应用程序几乎是无法也不可能保证的。
为了实现程序逻辑地址到其装入物理内存后的物理地址的转换保证程序对数据的正确寻址采用RV64G指令集的RISC-V处理器在监管模式即S模式也就是我们的PKE操作系统代码运行的特权模式提供了三种逻辑地址到物理地址的转换方式BareSv39和Sv48。由于逻辑地址到物理地址的转换与物理内存的管理有着紧密的关联所以以上三种方式也被称为虚拟内存管理Virtual Memory Management简称VMM方式。其中Bare模式是最简单的VMM方式即寻址时不对虚拟地址进行任何转换所访问的物理内存地址就等于虚拟内存地址这种方式在操作系统启动和刚进入S模式时很有用单任务模式只执行一个应用下仍然可用但多任务模式启动多个进程下就没法用了Sv39和Sv48是页式虚拟内存的管理方式它们分别支持39位和48位的逻辑地址且将物理内存以页面page的粒度进行管理。Sv39和Sv48这两种VMM用得较多的是Sv39Sv48只是在Sv39上的一个简单扩展所以在后续讨论中我们将着重讨论Sv39。
@ -657,7 +667,7 @@ satp寄存器包含一个44位的PPN它指向了一个页表的根目录所
| 8 | Sv39 | 采用Sv39的方案对虚地址进行转换 |
| 9 | Sv48 | 采用Sv39的方案对虚地址进行转换 |
实际上除了Sv39和Sv48外系统在未来的扩展中还可能支持更多的扩展如Sv57以及Sv64见[RISC-V instruction set manual]。从39、48以及57这几个数字我们可以发现的规律是它们之间两两的差是9结合图1.9中的地址翻译过程我们就很容易理解什么是Sv48了它在Sv39的基础上用上了虚地址中的39~47这9个位一共用了虚地址中的48个位作为第四级虚页号VPN[3]。这样做的结果是在进行地址翻译的时候新增了一级地址翻译。显然Sv48提供了比Sv39更大的虚拟地址空间2^48B=256TB>512GB从而能够支撑更大的应用程序的执行那么选择Sv48是不是比选择Sv39更具优势呢答案是取决于是否真的有必要支撑超过512GB虚地址空间的应用如果不需要则Sv39是更合理的选择。从图1.9中的地址翻译过程我们还可以看到一次虚地址va到实地址pa的转换涉及到4次根目录+页目录+页表+pa所在的页访问内存操作而相比于处理器内部进行的运算而言访存显然是更为耗时的操作。可以想象如果采用Sv48这个转换所需要的访存操作是5次比Sv39更多的。
实际上除了Sv39和Sv48外系统在未来的扩展中还可能支持更多的扩展如Sv57以及Sv64见[RISC-V instruction set manual](#refenences)。从39、48以及57这几个数字我们可以发现的规律是它们之间两两的差是9结合图1.9中的地址翻译过程我们就很容易理解什么是Sv48了它在Sv39的基础上用上了虚地址中的39~47这9个位一共用了虚地址中的48个位作为第四级虚页号VPN[3]。这样做的结果是在进行地址翻译的时候新增了一级地址翻译。显然Sv48提供了比Sv39更大的虚拟地址空间2^48B=256TB>512GB从而能够支撑更大的应用程序的执行那么选择Sv48是不是比选择Sv39更具优势呢答案是取决于是否真的有必要支撑超过512GB虚地址空间的应用如果不需要则Sv39是更合理的选择。从图1.9中的地址翻译过程我们还可以看到一次虚地址va到实地址pa的转换涉及到4次根目录+页目录+页表+pa所在的页访问内存操作而相比于处理器内部进行的运算而言访存显然是更为耗时的操作。可以想象如果采用Sv48这个转换所需要的访存操作是5次比Sv39更多的。
为了加快虚地址到实地址的转换今天的处理器RISC-V处理器也不例外但取决于具体的设计一般都内置了TLBTranslation Lookaside Buffer单元其速度接近寄存器。在进行地址转换时将常用的PDE/PTE存储在TLB中以加速虚实地址的转换速度。然而这又带来一个新的问题即当发生进程切换时TLB中很有可能还保留了上一个进程的地址变换所涉及的PDE/PTE这时我们就需要借助satp寄存器中的ASIDApplication Specific ID字段来判断是否发生了进程切换如果发生了操作系统就需要调用SFENCE.VMA指令来将TLB中的内容刷新。
@ -665,9 +675,41 @@ satp寄存器包含一个44位的PPN它指向了一个页表的根目录所
实际上开启采用兆页或吉页的方法在RISC-V规范中并未提供应该是让各个设计RISC-V处理器的单位自行制定。考虑到我们的PKE实验并未涉及这些非基础页所以在这里我们不打算对这部分内容进一步讨论。
<a name="proxykernel"></a>
### 1.6 什么是代理内核
代理内核是一种轻量级的应用程序执行环境可以承载静态链接的RISC-V ELF文件其运行机制如下图所示。
<img src="pictures/fig1_11.png" alt="fig1_11" style="zoom:100%;" />
图1.10 代理内核的概念
如图1.10所示代理内核的工作适配的场景是既有主机host又有目标机target的场景。代理内核并非独立存在的系统它不具有独自的IO实现而是将IO功能代理到Host主机上。它可以看成是操作系统的一个极小集为应用提供最基本的操作系统支撑使得应用可以在只具备核心资源包括处理器、内存的裸机上运行。为实现IO操作代理内核通过HTIF接口Host Target Interface的缩写同宿主机器交互完成大量IO相关的系调用其工作机制如下图所示。
<img src="pictures/fig1_12.png" alt="fig1_12" style="zoom:100%;" />
图1.11 代理内核与主机内核的交互
图1.11中的Frontend Server可理解为在Host主机上运行的一个守护进程它将二进制文件如代理操作系统内核Proxy kernel加载到内存通过控制/状态寄存器使target机器复位并启动代理内核。后者和Frontend Server通过共享内存的HTIF接口通讯实现IO操作以及加载和执行目标应用程序的动作。当目标应用程序执行完毕后目标机器通过tohost CSR通知主机端的Frontend。
### 1.6 工具软件简介
代理内核的设计,对于在类似于[Zedboard开发板](#references)这样的环境下开发、验证RISC-V处理器以及面向所开发RISC-V处理器的应用有着极大的帮助。 Zedboard是一个搭载了ARM处理器核的FPGA系统其中ARM硬核部分一般被称为PS而FPGA部分一般被称为PLPS和PL端共享内存。PS端可以运行一个完整的ARM版Linux系统如ubuntu成为图1.10中的Host部分PL端的逻辑资源则可以用来编程形成一个RISC-V处理器软核。为了在RISC-V软核上运行目标应用就可以采用代理内核的思路而无需为RISC-V处理器去开发一个完整的操作系统让在RISC-V上运行的代理内核通过HTIF去“共享”访问PS端所控制的所有外部设备如终端、存储等。这样可以极大加速开发-验证的循环最终形成可靠的基于RISC-V的系统。
例如,我们可以采用伯克利大学的开源项目[fpga-zynq](#references),在Zedboard开发板上测试所开发的RISC-V处理器fpga-zynq就用到了代理内核[Proxy Kernel](#references)来支撑目标应用。运行结果如图1.12所示:
<img src="pictures/fig1_13.png" alt="fig1_13" style="zoom:100%;" />
图1.12 代理内核与主机内核的交互
我们的PKE内核实验中也存在两个并行的Host和Target系统Host就是我们的开发主机其上运行了一个类Linux的完整操作系统而Target就是我们用[Spike](#references)模拟出来的RISC-V机器目标应用程序将在代理内核中执行。系统运行过程中代理内核借助Spike所提供的HTIF完成所有IO动作。
我们认为代理内核除了它的实用特性如以上讨论的对RISC-V的开发和验证具有很好的教学用途。在开发代理内核的过程中学生只需要将精力放在对计算机的“核心资产”即处理器和内存的管理和通过各种数据结构实现的逻辑到物理的映射上而无须过多考虑对IO设备控制的细节。这些都有助于降低操作系统开发的复杂度尽量降低学生开发的难度和复杂度。**同时,代理内核的目标是支撑给定目标应用,无需搞个“大而全”的内核,去运行各种可能的应用**。
一个显而易见的事实是:**比起复杂的多进程网络服务器(如[Apache HTTP Server](https://httpd.apache.org/)所需要的操作系统支持而言简单的Hello world!程序所需要的操作系统支持显然要少得多!**例如PKE的第一个实验lab1_1所就采用了Hello world!程序作为目标应用而支撑该应用的PKE内核代码只有500多行这可能是世界上**最小**的“操作系统”了基于该事实采用代理内核思想设计操作系统实验的一个更Strong的理由是我们可以通过对输入的目标应用的迭代从易到难从简单到复杂反推代理操作系统内核本身的“进化”学生在进化代理内核的过程中完成对操作系统课程知识点的学习。
需要说明的是我们的PKE实验代码即可以满足操作系统课程实验的开发需求同时所开发的代理内核可以无缝地在Zedboard开发板上运行。这样PKE实验实际上是同时兼顾了教学用途采用Spike模拟RISC-V环境和实际工程开发在Zedboard开发板的PL上搭载需要验证的RISC-V处理器软核用途的。这样就为选择PKE实验的学生打下了一定的RISC-V软硬协同开发基础。
<a name="toolsoftware"></a>
### 1.7 相关工具软件
PKE的实验将涉及Linux环境下较多工具软件的使用以下列出一些我们认为比较重要的工具软件并简要介绍其使用方法。详细的使用方法希望读者通过阅读其使用手册进一步掌握。
@ -691,9 +733,9 @@ git是一个开源的分布式版本控制系统对于一个本地仓库
当clone完成你就会有本地的工作目录进入该目录每个文件都有两种状态tracked or untracked。已跟踪的文件是指那些被纳入了版本控制的文件在上一次快照中有它们的记录在工作一段时间后它们的状态可能是未修改已修改或已放入暂存区。简而言之已跟踪的文件就是 git 已经知道的文件。其状态转换如图:
<img src="pictures/fig1_10.png" alt="fig1_10" style="zoom:60%;" />
<img src="pictures/fig1_10.png" alt="fig1_10" style="zoom:40%;" />
图1.10 git仓库中文件的状态转换
图1.13 git仓库中文件的状态转换
使用git status可以查看目录下的文件状态
@ -916,10 +958,10 @@ RISC-V是一个可扩展指令集spike默认支持的ISA为RV64IMAFDC
我们将目标机器的ISA指定为RV64GCV。
<a name="refenences"></a>
参考文献:
[RISC-V开源项目列表] RISC-V开源项目列表. https://riscv.org/risc-v-cores/
[RISC-V开源项目列表] RISC-V开源项目列表. https://riscv.org/risc-v-cores/
[开源指令集的指南] 勾凌睿、黄成、刘志刚《RISC-V手册——一本开源指令集的指南》. Avail at: http://crva.ict.ac.cn/documents/RISC-V-Reader-Chinese-v2p1.pdf
@ -929,6 +971,10 @@ RISC-V是一个可扩展指令集spike默认支持的ISA为RV64IMAFDC
[SiFive Interrupt] SiFive, SiFive Interrupt Cookbook (version 1.0). Avail. at: https://sifive.cdn.prismic.io/sifive/0d163928-2128-42be-a75a-464df65e04e0_sifive-interrupt-cookbook.pdf
[Zedboard] Digilent Zedboard. https://reference.digilentinc.com/programmable-logic/zedboard/start
[Proxy Kernel] RISC-V Proxy Kernel and Boot Loader. https://github.com/riscv/riscv-pk
[fpga-zynq] Rocket Chip on Zynq FPGAs. https://github.com/ucb-bar/fpga-zynq
[Spike] Spike RISC-V ISA Simulator. https://github.com/riscv/riscv-isa-sim

@ -2,7 +2,7 @@
本书的写作目标是围绕基于RISC-V的代理内核Proxy Kernel设计和指导读者完成一组实验作为《操作系统原理》课程的课程实验以及课程设计内容。课程实验的内容需要学习《操作系统原理》课程的读者独立完成课程设计的内容则鼓励有条件的读者多人合作完成。我们希望通过本书所设计的实验加深读者对原理课程所授知识的理解。
**操作系统的本质,是介于硬件和用户软件(应用)之间的一个大型软件系统,通过对硬件的包装来支撑应用的运行**。这一点在代理内核Proxy Kernel上体现得尤为明显它的作用是为应用提供最基本的操作系统支撑使其能够在裸机在实验中我们采用的是Spike模拟器上运行。正是由于这一特点代理内核可以看成是操作系统的一个极小子集。在采用代理内核的场景下计算机的软硬件界限以及代理内核的地位如图1.1所示。
**操作系统的本质,是介于硬件和用户软件(应用)之间的一个大型软件系统,通过对硬件的包装来支撑应用的运行**。这一点在代理内核Proxy Kernel上体现得尤为明显它的作用是为应用提供最基本的操作系统支撑使其能够在裸机在实验中我们采用的是Spike模拟器上运行。正是由于这一特点代理内核可以看成是操作系统的一个极小子集(对于代理内核的详细讨论,参见[1.6](chapter1.md#proxykernel)。在采用代理内核的场景下计算机的软硬件界限以及代理内核的地位如图1.1所示。
![fig0-1](pictures/fig0-1.png)
@ -12,14 +12,14 @@
本书设计的实验并未采用完整操作系统内核的方案这是因为如果采用完整内核的思路来设计实验非常容易陷入某个模块如启动、中断处理、内存管理、进程调度、设备管理、文件系统、Shell等等的设计细节整个过程虽然也会用到一些应用来验证但设计的重点始终是操作系统本身。完整方案中即使是为了运行一个最简单的Hello world程序都需要实现如用户态进程封装、进程调度等以及之前的一系列操作系统模块如启动、中断处理、内存管理等这样做反而忽略了操作系统对硬件进行封装以支撑应用运行的本质同时为了更“像”一个完整的操作系统完整操作系统内核实验方案往往需要自己“发明”一个简单文件系统并用它来组织虚拟磁盘一般是用一个文件来模拟这样就不得不引入大量与应用支撑无关的代码导致了工程庞大和重点不突出等诸多问题。
代理内核方案避免了完整内核方案以上的很多缺点,因为代理内核的存在“天生”就是为在硬件(模拟器)上支撑应用,而设计的最小化的操作系统内核。**它可以根据应用的复杂度的不同,调整自身的复杂度**例如如果只是为了支撑Hello world程序它就只需要加载、系统调用支持即可无需进程调度、设备、文件甚至虚拟存储等等内容。当然如果所支撑的应用非常复杂例如一个多线程的网络媒体服务器代理内核将约等于一个完整的操作系统内核**从学习操作系统知识的角度来看,代理内核的这些特点更有利于读者站在应用的角度来审视操作系统对硬件的包装和为应用所做的支撑,从而更好地理解从原理课程所学到的知识**。也正是代理内核的这些优点驱使我们在RISC-V Proxy Kernel and Boot Loader这个开源项目[ProxyKernel]的基础上开发并设计了本书的一组操作系统实验。为了与开源项目进行区分在本书中我们将称我们开发和设计的代理内核为PKEProxy Kernel for Education
代理内核方案避免了完整内核方案以上的很多缺点,因为代理内核的存在“天生”就是为在硬件(模拟器)上支撑应用,而设计的最小化的操作系统内核。**它可以根据应用的复杂度的不同,调整自身的复杂度**例如如果只是为了支撑Hello world程序它就只需要加载、系统调用支持即可无需进程调度、设备、文件甚至虚拟存储等等内容。当然如果所支撑的应用非常复杂例如一个多线程的网络媒体服务器代理内核将约等于一个完整的操作系统内核**从学习操作系统知识的角度来看,代理内核的这些特点更有利于读者站在应用的角度来审视操作系统对硬件的包装和为应用所做的支撑,从而更好地理解从原理课程所学到的知识**。也正是代理内核的这些优点驱使我们在RISC-V Proxy Kernel and Boot Loader这个开源项目[ProxyKernel](#references)的基础上开发并设计了本书的一组操作系统实验。为了与开源项目进行区分在本书中我们将称我们开发和设计的代理内核为PKEProxy Kernel for Education
为完成本书所设计的实验读者应具备汇编语言、C语言、基础的计算机体系结构知识、Linux环境中的基础软件如编译器、常见命令以及git工具等的使用这些基础知识。考虑到《计算机组成原理》课程与《操作系统原理》课程在开课时间上可能的重叠以及RISC-V汇编语言和8086汇编语言的巨大不同我们将在第一章介绍RISC-V计算机的体系结构的相关知识。从第二章开始我们将开始介绍PKE的实验。在完成PKE的5个实验后本书的第七章将给出操作系统课程设计题目。
<a name="references"></a>
参考文献:
[ProxyKernel] RISC-V Proxy Kernel and Boot Loader. Avail. at: https://github.com/riscv/riscv-pk
[ProxyKernel] RISC-V Proxy Kernel and Boot Loader. https://github.com/riscv/riscv-pk
Loading…
Cancel
Save