基于64位RISC-V处理器,系统介绍RISC-V体系结构,总结常见陷阱与项目经验 RISC-V之父Krste Asanovic教授作序推荐 · 图文并茂,用通俗易懂的语言讲述RISC-V体系结构,轻易破解RISC-V体系结构中的那些“烧脑”难题 · 数十个趣味实验,让你轻松上手RISC-V,有助于读者快速掌握RISC-V体系结构。 · 详细介绍成熟商业化高性能处理器:SiFive P870和X280处理器,和职场直轨。
售 价:¥
纸质售价:¥102.50购买纸书
温馨提示:数字商品不支持退换货,不提供源文件,不支持导出打印
为你推荐
内容提要
推荐序
RISC-V的未来有无限可能
前言
第一版前言
本书约定
第1章 RISC-V体系结构基础知识
1.1 RISC-V介绍
1.1.1 RISC-V指令集优点
1.1.2 RISC-V指令集扩展
1.1.3 RISC-V商业化发展
1.2 RISC-V体系结构介绍
1.2.1 RISC-V体系结构
1.2.2 采用RISC-V体系结构的常见处理器
1.2.3 RISC-V体系结构中的基本概念
1.2.4 SBI服务
1.3 RISC-V寄存器
1.3.1 通用寄存器
1.3.2 系统寄存器
1.3.3 U模式下的系统寄存器
1.3.4 S模式下的系统寄存器
1.3.5 M模式下的系统寄存器
第2章 搭建RISC-V实验环境
2.1 实验平台
2.1.1 QEMU
2.1.2 NEMU
2.2 搭建实验环境
2.2.1 实验2-1:输出“Welcome to RISC-V!”
2.2.2 实验2-2:单步调试BenOS和MySBI
2.3 MySBI和BenOS基础实验代码解析
2.3.1 MySBI基础实验代码解析
2.3.2 BenOS基础实验代码解析
2.3.3 合并BenOS和MySBI
2.4 QEMU + RISC-V + Linux实验平台
第3章 基础指令集
3.1 RISC-V指令集介绍
3.2 RISC-V指令编码格式
3.3 加载与存储指令
3.4 PC相对寻址
3.5 移位操作
3.6 位操作指令
3.7 算术指令
3.8 比较指令
3.9 无条件跳转指令
3.10 条件跳转指令
3.11 CSR指令
3.12 寻址范围
3.13 陷阱:为什么调用RET指令之后就进入死循环
3.14 实验
3.14.1 实验3-1:熟悉加载指令
3.14.2 实验3-2:PC相对寻址
3.14.3 实验3-3:memcpy()函数的实现
3.14.4 实验3-4:memset()函数的实现
3.14.5 实验3-5:条件跳转指令1
3.14.6 实验3-6:条件跳转指令2
3.14.7 实验3-7:子函数跳转
3.14.8 实验3-8:在汇编中实现串口输出功能
第4章 函数调用规范与栈
4.1 函数调用规范
4.2 入栈与出栈
4.3 RISC-V的栈布局
4.3.1 不使用FP的栈布局
4.3.2 使用FP的栈布局
4.3.3 栈回溯
4.4 实验
4.4.1 实验4-1:观察栈布局
4.4.2 实验4-2:观察栈回溯
第5章 GNU汇编器
5.1 编译流程与ELF文件
5.2 一个简单的汇编程序
5.3 汇编语法
5.3.1 注释
5.3.2 符号
5.4 常用的伪指令
5.4.1 对齐伪指令
5.4.2 数据定义伪指令
5.4.3 与函数相关的伪指令
5.4.4 与段相关的伪指令
5.4.5 与宏相关的伪指令
5.4.6 与文件相关的伪指令
5.5 RISC-V特有的命令行选项和伪指令
5.5.1 RISC-V特有的命令行选项
5.5.2 RISC-V特有的伪指令
5.6 实验
5.6.1 实验5-1:汇编语言练习——查找最大数
5.6.2 实验5-2:汇编语言练习——通过C语言调用汇编函数
5.6.3 实验5-3:汇编语言练习——通过汇编语言调用C函数
5.6.4 实验5-4:使用汇编伪指令实现一张表
5.6.5 实验5-5:汇编宏的使用
第6章 链接器与链接脚本
6.1 链接器
6.2 链接脚本
6.2.1 一个简单的链接程序
6.2.2 设置入口点
6.2.3 基本概念
6.2.4 符号赋值与引用
6.2.5 当前位置计数器
6.2.6 SECTIONS命令
6.2.7 常用的内置函数
6.3 加载重定位
6.3.1 BenOS重定位
6.3.2 OpenSBI和Linux内核重定位
6.4 链接重定位与链接器松弛优化
6.4.1 链接重定位
6.4.2 函数跳转优化
6.4.3 符号地址访问优化
6.5 实验
6.5.1 实验6-1:分析链接脚本
6.5.2 实验6-2:输出内存布局
6.5.3 实验6-3:加载地址不等于运行地址
6.5.4 实验6-4:设置链接地址
6.5.5 实验6-5:链接器松弛优化1
6.5.6 实验6-6:链接器松弛优化2
6.5.7 实验6-7:分析Linux 5.15内核的链接脚本
第7章 内嵌汇编代码
7.1 内嵌汇编代码的基本用法
7.1.1 基础内嵌汇编代码
7.1.2 扩展内嵌汇编代码
7.1.3 内嵌汇编代码修饰符
7.1.4 使用汇编符号名字
7.1.5 内嵌汇编代码与宏结合
7.1.6 使用goto修饰词
7.1.7 小结
7.2 案例分析
7.3 注意事项
7.4 实验
7.4.1 实验7-1:实现简单的memcpy()函数
7.4.2 实验7-2:使用汇编符号名编写内嵌汇编代码
7.4.3 实验7-3:实现内嵌汇编代码完善memset()函数
7.4.4 实验7-4:实现内嵌汇编代码与宏的结合
7.4.5 实验7-5:实现读和写系统寄存器的宏
7.4.6 实验7-6:基于goto模板的内嵌汇编代码
第8章 异常处理
8.1 异常处理基本概念
8.1.1 异常类型
8.1.2 同步异常和异步异常
8.1.3 异常触发与返回的流程
8.1.4 异常返回地址
8.1.5 异常返回的处理器模式
8.1.6 栈的选择
8.2 与M模式相关的异常寄存器
8.2.1 mstatus寄存器
8.2.2 mtvec寄存器
8.2.3 mcause寄存器
8.2.4 mie寄存器
8.2.5 mtval寄存器[1]
8.2.6 mip寄存器
8.2.7 mideleg和medeleg寄存器
8.2.8 配置中断
8.3 与S模式相关的异常寄存器
8.3.1 sstatus寄存器
8.3.2 sie寄存器
8.3.3 sip寄存器
8.3.4 scause寄存器
8.3.5 stvec寄存器
8.3.6 stval寄存器
8.4 异常上下文
8.4.1 保存异常上下文
8.4.2 恢复异常上下文
8.5 案例分析8-1:实现SBI系统的调用
8.5.1 调用ECALL指令
8.5.2 实现SBI系统的调用
8.6 案例分析8-2:BenOS的异常处理
8.6.1 设置异常向量表
8.6.2 保存和恢复异常上下文
8.6.3 异常处理
8.6.4 委托中断和异常
8.6.5 触发异常
8.7 实验
8.7.1 实验8-1:在SBI中实现串口输入功能
8.7.2 实验8-2:在BenOS中触发非法指令异常
8.7.3 实验8-3:输出触发异常时函数栈的调用过程
8.7.4 实验8-4:在MySBI中模拟实现RDTIME伪指令
第9章 中断处理与中断控制器
9.1 中断处理基本概念
9.1.1 中断类型
9.1.2 中断处理过程
9.1.3 中断委派和注入
9.1.4 中断优先级
9.2 CLINT
9.3 案例分析9-1:定时器中断
9.3.1 访问mtimer
9.3.2 在MySBI中实现定时器服务
9.3.3 定时器中断处理
9.3.4 打开中断总开关
9.3.5 小结
9.4 PLIC
9.4.1 中断号
9.4.2 中断优先级
9.4.3 中断使能寄存器
9.4.4 中断待定寄存器
9.4.5 中断优先级阈值寄存器
9.4.6 中断请求/完成寄存器
9.5 案例分析9-2:串口中断
9.5.1 初始化PLIC
9.5.2 使能串口0的接收中断
9.5.3 处理中断
9.6 实验
9.6.1 实验9-1:定时器中断
9.6.2 实验9-2:使用汇编函数保存和恢复中断现场
9.6.3 实验9-3:实现并调试串口0中断
第10章 内存管理
10.1 内存管理基础知识
10.1.1 内存管理的“远古时代”
10.1.2 地址空间的抽象
10.1.3 分段机制
10.1.4 分页机制
10.2 RISC-V内存管理
10.2.1 页表分类
10.2.2 Sv39页表映射
10.2.3 Sv48页表映射
10.2.4 页表项描述符
10.2.5 页表项的常见属性
10.2.6 与地址转换相关的寄存器
10.3 物理内存属性与物理内存保护
10.3.1 物理内存属性
10.3.2 物理内存保护
10.4 案例分析:在BenOS里实现恒等映射
10.4.1 页表定义
10.4.2 页表数据结构
10.4.3 创建页表
10.4.4 打开MMU
10.4.5 测试MMU
10.4.6 图解页表的创建过程
10.5 内存管理实验
10.5.1 实验10-1:建立恒等映射
10.5.2 实验10-2:为什么MMU无法运行
10.5.3 实验10-3:实现MMU页表的转储功能
10.5.4 实验10-4:修改页面属性
10.5.5 实验10-5:使用汇编语言建立恒等映射
10.5.6 实验10-6:在MySBI中实现和验证PMP机制
第11章 高速缓存
11.1 为什么需要高速缓存
11.2 高速缓存的访问延时
11.3 高速缓存的工作原理
11.4 高速缓存的映射方式
11.4.1 直接映射
11.4.2 全相联映射
11.4.3 组相联映射
11.4.4 组相联高速缓存的例子
11.5 虚拟高速缓存与物理高速缓存
11.5.1 物理高速缓存
11.5.2 虚拟高速缓存
11.5.3 高速缓存的类型
11.6 重名和同名问题
11.6.1 重名问题
11.6.2 同名问题
11.6.3 VIPT产生的重名问题
11.7 高速缓存策略
11.8 高速缓存的维护指令
11.8.1 高速缓存管理指令
11.8.2 高速缓存预取指令
第12章 缓存一致性
12.1 为什么会产生缓存一致性问题
12.2 缓存一致性的分类
12.2.1 缓存一致性协议发展历程
12.2.2 缓存一致性分类
12.2.3 系统缓存一致性问题
12.3 缓存一致性的解决方案
12.3.1 关闭高速缓存
12.3.2 使用软件维护缓存一致性
12.3.3 使用硬件维护缓存一致性
12.4 MESI协议
12.4.1 MESI协议简介
12.4.2 本地读写与总线读写操作
12.4.3 MESI状态转换
12.4.4 初始状态为I
12.4.5 初始状态为M
12.4.6 初始状态为S
12.4.7 初始状态为E
12.4.8 小结与案例分析
12.4.9 MOESI协议
12.5 高速缓存伪共享
12.6 两种缓存一致性控制器
12.6.1 CCI缓存一致性控制器
12.6.2 CCN缓存一致性控制器
12.7 案例分析12-1:伪共享的避免
12.8 案例分析12-2:DMA和高速缓存的一致性
12.8.1 从DMA缓冲区到设备的FIFO缓冲区
12.8.2 从设备的FIFO缓冲区到DMA缓冲区
12.9 案例分析12-3:自修改代码的一致性
12.10 实验
12.10.1 实验12-1:高速缓存伪共享
12.10.2 实验12-2:使用Perf C2C工具发现高速缓存伪共享
第13章 TLB管理
13.1 TLB基础知识
13.2 TLB重名与同名问题
13.2.1 重名问题
13.2.2 同名问题
13.3 ASID
13.4 TLB管理指令
13.4.1 TLB管理指令介绍
13.4.2 TLB广播
13.4.3 SFENCE.VMA指令使用场景
13.5 TLB案例分析
13.5.1 TLB在Linux内核中的应用
13.5.2 ASID在Linux内核中的应用
13.5.3 Linux内核中的TLB维护操作
13.5.4 BBM机制
第14章 原子操作
14.1 原子操作介绍
14.2 保留加载与条件存储指令
14.2.1 LR/SC指令用法
14.2.2 LR/SC指令执行失败的情况
14.3 独占内存访问工作原理
14.3.1 独占监视器
14.3.2 独占监视器与缓存一致性
14.4 原子内存访问操作指令
14.4.1 原子内存访问操作指令工作原理
14.4.2 原子内存访问操作指令与独占内存访问指令的效率对比
14.4.3 RISC-V中的原子内存访问指令
14.5 比较并交换指令
第15章 内存屏障指令
15.1 产生内存屏障指令的原因
15.1.1 顺序一致性内存模型
15.1.2 处理器一致性内存模型
15.1.3 弱一致性内存模型
15.1.4 释放一致性内存模型
15.1.5 MCA模型
15.2 RVWMO内存模型中的一些约束条件
15.2.1 全局内存次序与保留程序次序
15.2.2 RVWMO的约束规则
15.3 RISC-V中的内存屏障指令
15.3.1 使用内存屏障的场景
15.3.2 FENCE指令
15.3.3 内置获取和释放内存屏障原语的指令
15.3.4 FENCE.I指令
15.3.5 SFENCE.VMA指令
15.4 RISC-V内存屏障指令移植指南
15.4.1 从RISC-V到x86体系结构
15.4.2 从RISC-V到ARM体系结构
15.4.3 Linux内核常用的内存屏障API函数
15.5 案例分析
15.5.1 消息传递问题
15.5.2 单方向内存屏障与自旋锁
15.5.3 通过邮箱传递消息
15.5.4 关于DMA的案例
15.5.5 在Linux内核中使指令高速缓存失效
15.6 模拟和测试内存屏障故障
15.6.1 使用Litmus测试工具集
15.6.2 编写C程序模拟
15.7 实验
15.7.1 实验15-1:编写Litmus脚本并验证内存一致性1
15.7.2 实验15-2:编写Litmus脚本并验证内存一致性2
第16章 合理使用内存屏障指令
16.1 存储缓冲区与写内存屏障指令
16.2 无效队列与读内存屏障指令
16.3 内存屏障指令总结
16.4 案例分析:Linux内核中的内存屏障指令[1]
16.4.1 第一次使用内存屏障指令
16.4.2 第二次使用内存屏障指令
16.4.3 第三次使用内存屏障指令
16.4.4 第四次使用内存屏障指令
16.4.5 小结:内存屏障指令的使用
16.5 实验
16.5.1 实验16-1:验证内存一致性1
16.5.2 实验16-2:验证内存一致性2
16.5.3 实验16-3:验证内存一致性3
第17章 与操作系统相关的内容
17.1 C语言常见的陷阱
17.1.1 数据模型
17.1.2 数据类型转换与整型提升
17.1.3 移位操作
17.2 创建进程时需注意的关键点
17.2.1 进程控制块
17.2.2 0号进程
17.2.3 do_fork()函数的实现
17.2.4 进程上下文切换
17.2.5 新进程的第一次执行
17.3 简易进程调度器
17.3.1 扩展进程控制块
17.3.2 就绪队列
17.3.3 调度类
17.3.4 简易调度器的实现
17.3.5 自愿调度
17.3.6 抢占调度
17.3.7 测试用例
17.3.8 关于调度的思考
17.4 让进程运行在用户模式
17.5 系统调用
17.5.1 系统调用介绍
17.5.2 在用户模式下调用ECALL指令
17.5.3 在内核模式下对系统调用的处理
17.5.4 系统调用表
17.6 实现clone系统调用
17.7 实验
17.7.1 实验17-1:进程创建
17.7.2 实验17-2:进程调度
17.7.3 实验17-3:让进程运行在用户模式
17.7.4 实验17-4:新建一个malloc()系统调用
17.7.5 实验17-5:新建一个clone()系统调用
第18章 可伸缩矢量计算与优化
18.1 矢量计算基本概念
18.1.1 SISD与SIMD
18.1.2 定长计算与可变长矢量计算
18.1.3 通道
18.1.4 矢量与标量
18.2 RVV寄存器
18.2.1 矢量寄存器
18.2.2 mstatus寄存器中的矢量上下文状态
18.2.3 vtype寄存器
18.2.4 vl寄存器
18.2.5 vlenb寄存器
18.2.6 vstart寄存器
18.3 配置编译和运行环境
18.3.1 搭建编译环境
18.3.2 运行第一个“hello RVV!”程序
18.3.3 单步调试汇编程序
18.3.4 单步调试C语言与汇编混合程序
18.4 RVV算术指令格式
18.5 配置指令
18.6 加载和存储指令
18.6.1 单位步长模式
18.6.2 任意步长模式
18.6.3 聚合加载/离散存储模式
18.6.4 打包数据加载与存储指令
18.6.5 首次异常加载指令
18.6.6 加载和存储全部矢量数据
18.7 矢量掩码指令
18.7.1 逻辑操作指令
18.7.2 VCPOP.M指令
18.7.3 VFIRST.M指令
18.7.4 VMSBF.M指令
18.7.5 VMSIF.M指令
18.7.6 VMSOF.M指令
18.8 矢量整型算术指令
18.8.1 加宽和变窄算术指令
18.8.2 加法和减法指令
18.8.3 加宽模式的加法和减法指令
18.8.4 位操作指令
18.8.5 移位操作指令
18.8.6 比较指令
18.8.7 数据搬移指令
18.9 案例分析18-1:使用RVV指令优化strcmp()函数
18.9.1 使用纯汇编方式
18.9.2 测试
18.10 案例分析18-2:RGB24转BGR24
18.10.1 使用C语言实现RGB24转BGR24
18.10.2 使用RVV指令优化
18.10.3 测试
18.11 案例分析18-3:4 × 4矩阵乘法运算
18.11.1 使用C语言实现4 × 4矩阵乘法运算
18.11.2 使用RVV指令优化
18.11.3 测试
18.12 案例分析18-4:使用RVV内置函数
18.13 案例分析18-5:自动矢量优化
18.14 术语
18.15 实验
18.15.1 实验18-1:RGB24转BGR32
18.15.2 实验18-2:8 × 8矩阵乘法运算
18.15.3 实验18-3:使用RVV指令优化strcpy()函数
18.15.4 实验18-4:使用RVV内置函数优化
18.15.5 实验18-5:使用RVV指令优化转置矩阵的求法
第19章 压缩指令扩展
19.1 RISC-V指令集的特点
19.2 RVC支持的指令格式与指令编码
第20章 虚拟化扩展
20.1 虚拟化技术介绍
20.1.1 虚拟化技术的发展历史
20.1.2 虚拟机管理程序的分类
20.1.3 内存虚拟化
20.1.4 I/O虚拟化
20.2 RISC-V虚拟化扩展
20.2.1 CPU虚拟化扩展
20.2.2 M模式下系统寄存器的扩展
20.2.3 HS模式下的系统寄存器
20.2.4 VS模式下的系统寄存器
20.3 RISC-V内存虚拟化
20.4 RISC-V虚拟化扩展中的新增指令
20.4.1 加载与存储虚拟机内存指令
20.4.2 虚拟化内存屏障指令
20.5 进入和退出虚拟机
20.5.1 异常陷入
20.5.2 异常返回
20.5.3 新增的中断与异常类型
20.6 中断虚拟化
20.6.1 虚拟中断注入
20.6.2 陷入与模拟
20.7 案例分析20-1:进入和退出虚拟机
20.7.1 进入虚拟机
20.7.2 退出虚拟机
20.8 案例分析20-2:建立虚拟化两阶段地址映射
20.8.1 建立第二阶段的地址映射
20.8.2 建立第一阶段的地址映射
20.8.3 测试
20.9 案例分析20-3:在虚拟机中实现虚拟定时器
20.10 案例分析20-4:在VMM中加载和存储虚拟机内存地址
20.11 案例分析20-5:在VMM中模拟串口设备
20.12 实验
20.12.1 实验20-1:加载虚拟机1
20.12.2 实验20-2:加载虚拟机2
20.12.3 实验20-3:虚拟化地址映射
20.12.4 实验20-4:解析虚拟机陷入的指令
20.12.5 实验20-5:在VMM中模拟实现vPLIC
20.12.6 实验20-6:在虚拟机中加载并运行Linux内核
第21章 RISC-V高性能处理器架构分析
21.1 处理器架构基础
21.1.1 处理器的发展历史
21.1.2 指令集架构
21.1.3 处理器微架构
21.1.4 单周期处理器
21.1.5 多周期处理器
21.1.6 超标量处理器
21.1.7 如何让程序跑得更快
21.2 香山处理器架构分析
21.2.1 香山处理器体系结构
21.2.2 香山处理器的前端子系统
21.2.3 香山处理器的后端子系统
21.2.4 香山处理器的访存子系统
21.2.5 香山处理器的L2/L3高速缓存
21.3 SiFive P870处理器核心分析
21.3.1 P870处理器总体架构
21.3.2 P870处理器前端系统
21.3.3 P870处理器执行系统
21.3.4 P870处理器访存系统
21.3.5 P870处理器新增的特性
21.4 SiFive X280处理器核心分析
RISC-V体系结构自测题
附录A RISC-V体系结构自测题的参考答案与提示
附录B RV64I指令速查表
附录C RV64M指令速查表
附录D RV64常用伪指令速查表
买过这本书的人还买过
读了这本书的人还在读
同类图书排行榜