pull/1/head
Zhiyuan Shao 3 years ago
parent c06fc5cef5
commit e3d592e001

@ -2,11 +2,14 @@
### 目录
- [2.1 头歌平台](#educoder)
- [2.2 Ubuntu环境](#ubuntu)
- [2.3 openEuler操作系统](#openeuler)
- [2.2 Ubuntu操作系统的配置](#ubuntu)
- [2.3 openEuler操作系统配置](#openeuler)
- [2.4 riscv-pke实验代码的获取](#preparecode)
<a name="educoder"></a>
## 2.1 头歌平台
PKE实验在[头歌平台](https://www.educoder.net/)上进行了部署但因为仍在测试阶段所以没有开放全局选课感兴趣的读者可以尝试邀请码2T8MA。PKE实验2.0版本将于2021年秋季在头歌平台重新上线届时将开放全局选课。
@ -18,7 +21,9 @@ PKE实验在[头歌平台](https://www.educoder.net/)上进行了部署,但因
头歌平台为每个选课的学生提供了一个docker虚拟机该虚拟机环境中已经配置好了所有开发套件包括交叉编译器、Spike模拟器等用户可以通过shell选项*详细使用方法将待2.0上线时更新*进入该docker环境在该docker环境中完成实验任务。
<a name="ubuntu"></a>
## 2.2 Ubuntu环境
实验环境我们推荐采用Ubuntu 16.04LTS或18.04LTSx86_64操作系统我们未在其他系统如archRHEL等上做过测试但理论上只要将实验中所涉及到的安装包替换成其他系统中的等效软件包就可完成同样效果。另外我们在EduCoder实验平台网址https://www.educoder.net 上创建了本书的同步课程课程的终端环境中已完成实验所需软件工具的安装所以如果读者是在EduCoder平台上选择的本课程则可跳过本节的实验环境搭建过程直接进入通过终端命令行进入实验环境。
@ -167,3 +172,145 @@ you need add your code!
## 2.3 openEuler操作系统
PKE实验将提供基于华为openEuler操作系统的开发方法*具体的华为云使用方法待续*但在openEuler操作系统环境中的交叉编译器安装方法以及其他环节都可参考[2.2 Ubuntu环境](#ubuntu)的命令进行。
<a name="preparecode"></a>
## 2.4 riscv-pke实验代码的获取
获取riscv-pke代码前需要首先确认你已经按照[第二章](chapter2_installation.md)的要求完成了开发环境的构建这里我们假设环境是基于Ubuntu或者openEular头歌环境下更多的是界面操作所以无需通过命令行获取代码
环境构建好后通过以下命令下载实验1的代码
(克隆代码仓库)
`$ git clone https://gitee.com/hustos/riscv-pke.git`
克隆完成后将在当前目录应该能看到riscv-pke目录。这时可以到riscv-pke目录下查看文件结构例如
`$ cd riscv-pke`
切换到lab1_1_syscall分支
`$ git checkout lab1_1_syscall`
`$ tree -L 3`
(将看到如下输出)
```
.
├── LICENSE.txt
├── Makefile
├── README.md
├── kernel
│   ├── config.h
│   ├── elf.c
│   ├── elf.h
│   ├── kernel.c
│   ├── kernel.lds
│   ├── machine
│   │   ├── mentry.S
│   │   └── minit.c
│   ├── process.c
│   ├── process.h
│   ├── riscv.h
│   ├── strap.c
│   ├── strap.h
│   ├── strap_vector.S
│   ├── syscall.c
│   └── syscall.h
├── spike_interface
│   ├── atomic.h
│   ├── dts_parse.c
│   ├── dts_parse.h
│   ├── spike_file.c
│   ├── spike_file.h
│   ├── spike_htif.c
│   ├── spike_htif.h
│   ├── spike_memory.c
│   ├── spike_memory.h
│   ├── spike_utils.c
│   └── spike_utils.h
├── user
│   ├── app_helloworld.c
│   ├── user.lds
│   ├── user_lib.c
│   └── user_lib.h
└── util
├── functions.h
├── load_store.S
├── snprintf.c
├── snprintf.h
├── string.c
├── string.h
└── types.h
```
在代码的根目录有以下文件:
- Makefile文件它是make命令即将使用的“自动化编译”脚本
- LICENSE.txt文件即riscv-pke的版权文件里面包含了所有参与开发的人员信息。riscv-pke是开源软件你可以以任意方式自由地使用前提是使用时包含LICENSE.txt文件即可
- README.md文件一个简要的英文版代码说明。
另外是一些子目录,其中:
- kernel目录包含了riscv-pke的内核部分代码
- spike_interface目录是riscv-pke内核与spike模拟器的接口代码如设备树DTB、主机设备接口HTIF等用于接口的初始化和调用
- user目录包含了实验给定应用如lab1_1中的app_helloworld.c以及用户态的程序库文件如lab1_1中的user_lib.c
- util目录包含了一些内核和用户程序公用的代码如字符串处理string.c类型定义types.h等。
在代码的根目录输入以下命令:
`$ make`
进行构造build在环境已配好特别是交叉编译器已加入系统路径的情况下输出如下
```
compiling util/snprintf.c
compiling util/string.c
linking obj/util.a ...
Util lib has been build into "obj/util.a"
compiling spike_interface/dts_parse.c
compiling spike_interface/spike_htif.c
compiling spike_interface/spike_utils.c
compiling spike_interface/spike_file.c
compiling spike_interface/spike_memory.c
linking obj/spike_interface.a ...
Spike lib has been build into "obj/spike_interface.a"
compiling kernel/syscall.c
compiling kernel/elf.c
compiling kernel/process.c
compiling kernel/strap.c
compiling kernel/kernel.c
compiling kernel/machine/minit.c
compiling kernel/strap_vector.S
compiling kernel/machine/mentry.S
linking obj/riscv-pke ...
PKE core has been built into "obj/riscv-pke"
compiling user/app_helloworld.c
compiling user/user_lib.c
linking obj/app_helloworld ...
User app has been built into "obj/app_helloworld"
```
构造完成后在代码根目录会出现一个obj子目录该子目录包含了构造过程中所生成的所有对象文件.o、编译依赖文件.d、静态库.a文件和最终目标ELF文件如./obj/riscv-pke和./obj/app_helloworld
这时我们可以尝试借助riscv-pke内核运行app_helloworld的“Hello world!”程序:
```
$ spike ./obj/riscv-pke ./obj/app_helloworld
In m_start, hartid:0
HTIF is available!
(Emulated) memory size: 2048 MB
Enter supervisor mode...
Application: ./obj/app_helloworld
Application program entry point (virtual address): 0x0000000081000000
Switching to user mode...
call do_syscall to accomplish the syscall and lab1_1 here.
System is shutting down with exit code -1.
```
自此riscv-pke的代码获取和验证已完成。

@ -3,13 +3,12 @@
### 目录
- [3.1 实验1的基础知识](#fundamental)
- [3.1.1 获取riscv-pke代码](#subsec_preparecode)
- [3.1.2 RISC-V程序的编译和链接](#subsec_compileandlink)
- [3.1.3 指定符号的逻辑地址](#subsec_lds)
- [3.1.4 代理内核的构造过程](#subsec_building)
- [3.1.5 代理内核的启动过程](#subsec_booting)
- [3.1.6 ELF文件app的加载过程](#subsec_elf)
- [3.1.7 spike的HTIF接口](#subsec_htif)
- [3.1.1 RISC-V程序的编译和链接](#subsec_compileandlink)
- [3.1.2 指定符号的逻辑地址](#subsec_lds)
- [3.1.3 代理内核的构造过程](#subsec_building)
- [3.1.4 代理内核的启动过程](#subsec_booting)
- [3.1.5 ELF文件app的加载过程](#subsec_elf)
- [3.1.6 spike的HTIF接口](#subsec_htif)
- [3.2 lab1_1 系统调用](#syscall)
- [给定应用](#lab1_1_app)
- [实验内容](#lab1_1_content)
@ -29,148 +28,9 @@
本章我们将首先[获得代码](#subsec_preparecode),接下来介绍[程序的编译链接和ELF文件](#subsec_elfload)的基础知识接着讲述riscv-pke操作系统内核的[启动原理](#subsec_booting)最后开始实验1的3个实验。
<a name="subsec_preparecode"></a>
### 3.1.1 获取riscv-pke代码
获取riscv-pke代码前需要首先确认你已经按照[第二章](chapter2_installation.md)的要求完成了开发环境的构建这里我们假设环境是基于Ubuntu或者openEular头歌环境下更多的是界面操作所以无需通过命令行获取代码
环境构建好后通过以下命令下载实验1的代码
(克隆代码仓库)
`$ git clone https://gitee.com/hustos/riscv-pke.git`
克隆完成后将在当前目录应该能看到riscv-pke目录。这时可以到riscv-pke目录下查看文件结构例如
`$ cd riscv-pke`
切换到lab1_1_syscall分支
`$ git checkout lab1_1_syscall`
`$ tree -L 3`
(将看到如下输出)
```
.
├── LICENSE.txt
├── Makefile
├── README.md
├── kernel
│   ├── config.h
│   ├── elf.c
│   ├── elf.h
│   ├── kernel.c
│   ├── kernel.lds
│   ├── machine
│   │   ├── mentry.S
│   │   └── minit.c
│   ├── process.c
│   ├── process.h
│   ├── riscv.h
│   ├── strap.c
│   ├── strap.h
│   ├── strap_vector.S
│   ├── syscall.c
│   └── syscall.h
├── spike_interface
│   ├── atomic.h
│   ├── dts_parse.c
│   ├── dts_parse.h
│   ├── spike_file.c
│   ├── spike_file.h
│   ├── spike_htif.c
│   ├── spike_htif.h
│   ├── spike_memory.c
│   ├── spike_memory.h
│   ├── spike_utils.c
│   └── spike_utils.h
├── user
│   ├── app_helloworld.c
│   ├── user.lds
│   ├── user_lib.c
│   └── user_lib.h
└── util
├── functions.h
├── load_store.S
├── snprintf.c
├── snprintf.h
├── string.c
├── string.h
└── types.h
```
在代码的根目录有以下文件:
- Makefile文件它是make命令即将使用的“自动化编译”脚本
- LICENSE.txt文件即riscv-pke的版权文件里面包含了所有参与开发的人员信息。riscv-pke是开源软件你可以以任意方式自由地使用前提是使用时包含LICENSE.txt文件即可
- README.md文件一个简要的英文版代码说明。
另外是一些子目录,其中:
- kernel目录包含了riscv-pke的内核部分代码
- spike_interface目录是riscv-pke内核与spike模拟器的接口代码如设备树DTB、主机设备接口HTIF等用于接口的初始化和调用
- user目录包含了实验给定应用如lab1_1中的app_helloworld.c以及用户态的程序库文件如lab1_1中的user_lib.c
- util目录包含了一些内核和用户程序公用的代码如字符串处理string.c类型定义types.h等。
在代码的根目录输入以下命令:
`$ make`
进行构造build在环境已配好特别是交叉编译器已加入系统路径的情况下输出如下
```
compiling util/snprintf.c
compiling util/string.c
linking obj/util.a ...
Util lib has been build into "obj/util.a"
compiling spike_interface/dts_parse.c
compiling spike_interface/spike_htif.c
compiling spike_interface/spike_utils.c
compiling spike_interface/spike_file.c
compiling spike_interface/spike_memory.c
linking obj/spike_interface.a ...
Spike lib has been build into "obj/spike_interface.a"
compiling kernel/syscall.c
compiling kernel/elf.c
compiling kernel/process.c
compiling kernel/strap.c
compiling kernel/kernel.c
compiling kernel/machine/minit.c
compiling kernel/strap_vector.S
compiling kernel/machine/mentry.S
linking obj/riscv-pke ...
PKE core has been built into "obj/riscv-pke"
compiling user/app_helloworld.c
compiling user/user_lib.c
linking obj/app_helloworld ...
User app has been built into "obj/app_helloworld"
```
构造完成后在代码根目录会出现一个obj子目录该子目录包含了构造过程中所生成的所有对象文件.o、编译依赖文件.d、静态库.a文件和最终目标ELF文件如./obj/riscv-pke和./obj/app_helloworld
这时我们可以尝试借助riscv-pke内核运行app_helloworld的“Hello world!”程序:
```
$ spike ./obj/riscv-pke ./obj/app_helloworld
In m_start, hartid:0
HTIF is available!
(Emulated) memory size: 2048 MB
Enter supervisor mode...
Application: ./obj/app_helloworld
Application program entry point (virtual address): 0x0000000081000000
Switching to user mode...
call do_syscall to accomplish the syscall and lab1_1 here.
System is shutting down with exit code -1.
```
自此riscv-pke的代码获取和验证已完成。
<a name="subsec_compileandlink"></a>
### 3.1.2 RISC-V程序的编译和链接
### 3.1.1 RISC-V程序的编译和链接
下面我们将简要介绍RISC-V程序的编译和链接相关知识。这里我们仍然假设你已经按照[第二章](chapter2_installation.md)的要求完成了基于Ubuntu或者openEular的开发环境构建如果是在头歌平台可以通过他们提供的交互??进入终端使用里面的交叉编译器已经安装且已加入系统路径。在PKE实验的开发环境中我们通过模拟器spike所构建的目标机是risc-v机器而主机一般采用的是采用x86指令集的Intel处理器openEular可能采用的是基于ARM指令集的华为鲲鹏处理器在这种配置下我们的程序包括PKE操作系统内核以及应用都通过交叉编译器所提供的工具进行编译和链接。虽然risc-v交叉编译器和主机环境下的GCC是同一套体系但它的使用和输出还是有些细微的不同所以有必要对它进行一定的了解。
@ -371,7 +231,7 @@ Disassembly of section .text:
<a name="subsec_lds"></a>
### 3.1.3 指定符号的逻辑地址
### 3.1.2 指定符号的逻辑地址
编译器在链接过程中一个重要的任务就是为源程序中的符号symbol赋予逻辑地址。例如在以上`sections`的例子中,我们通过`objdump`命令得知helloworld.c源文件的main函数所对应的逻辑地址为0x000000000001014e而且对于任意ELF中的段segment或节section而言它的逻辑地址必然是从某个地址开始的一段连续地址空间。
@ -471,7 +331,7 @@ Disassembly of section .text:
<a name="subsec_building"></a>
### 3.1.4 代理内核的构造过程
### 3.1.3 代理内核的构造过程
这里我们讨论lab1_1中代理内核以及其上运行的应用的构造build过程。PKE实验采用了Linux中广泛采用的make软件包完成内核、支撑库以及应用的构造。关于Makefile的编写我们建议读者阅读[这篇文章](https://blog.csdn.net/foryourface/article/details/34058577)了解make文件的基础知识这里仅讨论lab1_1的Makefile以及对应的构造过程。PKE的后续实验实际上采用的Makefile跟lab1_1的非常类似所以我们在后续章节中不再对它们的构建过程进行讨论。
@ -604,7 +464,7 @@ Disassembly of section .text:
<a name="subsec_booting"></a>
### 3.1.5 代理内核的启动过程
### 3.1.4 代理内核的启动过程
在3.1.1中我们获取riscv-pke的代码并完成构造步骤后我们将通过以下命令开始lab1_1所给定的应用的执行
@ -871,7 +731,7 @@ s_start函数在kernel/kernel.c文件中定义
<a name="subsec_elf"></a>
### 3.1.6 ELF文件app的加载过程
### 3.1.5 ELF文件app的加载过程
这里我们对load_user_program()函数进行讨论它在kernel/kernel.c中定义
@ -982,7 +842,7 @@ s_start函数在kernel/kernel.c文件中定义
<a name="subsec_htif"></a>
### 3.1.7 spike的HTIF接口
### 3.1.6 spike的HTIF接口
spike提供的HTIFHost-Target InterFace接口的原理可以用下图说明

Loading…
Cancel
Save