计算机体系结构基础(第3版)
上QQ阅读APP看书,第一时间看更新

第3章 特权指令系统

3.1 特权指令系统简介

在计算机系统层次结构中,应用层 特指直接运行在CPU上的应用,把虚拟机及其上运行的应用作为整体看待。在操作系统层之上,只能看到和使用指令系统的一个子集,即指令系统的用户态部分。每个应用程序都有自己的寄存器、内存空间以及可执行的指令。现代计算机的指令系统在用户态子集之外还定义了操作系统核心专用的特权态部分,我们称之为特权指令系统。

特权指令系统的存在主要是为了让计算机变得更好用、更安全。操作系统通过特权指令系统管理计算机,使得应用程序形成独占CPU的假象,并使应用间相互隔离,互不干扰。应用程序只能在操作系统划定的范围内执行,一旦超出就会被CPU切换成操作系统代码运行。

不同指令系统的特权态部分差别较大,但就其机制而言,可以分为以下几类。

(1)运行模式定义及其转换

现代计算机的操作系统都实现了保护模式,至少需要用户态和核心态两种运行模式。应用运行在用户态模式下,操作系统运行在核心态模式下。因此,指令系统必须有相应的运行模式以做区分。比如MIPS定义了user、supervisor、kernel三种模式,X86定义了Ring0~Ring3四种模式,LoongArch定义了PLV0~PLV3四种模式。

刚开机时,CPU初始化为操作系统核心态对应的运行模式,执行引导程序加载操作系统。操作系统做完一系列初始化后,控制CPU切换到操作系统用户态对应的运行模式去执行应用程序。应用程序执行过程中,如果出现用户态对应的运行模式无法处理的事件,则CPU会通过异常或中断回到核心态对应的运行模式,执行操作系统提供的服务程序。操作系统完成处理后再控制CPU返回用户态对应的运行模式,继续运行原来的应用程序或者调度另一个应用程序。在LoongArch指令系统中,CPU当前所处的运行模式由当前模式信息控制状态寄存器(CSR.CRMD)的PLV域的值确定,其值为0~3分别表示CPU正处于PLV0~PLV3四种运行模式(见图3.1)。

图3.1 LoongArch当前模式信息控制状态寄存器的格式

运行模式的转换过程与虚拟存储和异常中断紧密相关,共同构建出完备的保护模式。不少指令系统还支持虚拟机模式、调试模式等,使计算机系统更为易用。

(2)虚拟存储管理

虚拟存储管理的基本思想是让软件(包括系统软件)运行在“虚地址”上,与真正访问存储的“实地址”(物理地址)相隔离。虚实地址的转换根据地址段属性的不同,有查表转换和直接映射两种方式。查表转换是应用程序使用的主要方式。不同的进程有自己独立的虚地址空间。CPU执行访存指令时,根据操作系统给出的映射表来完成虚地址空间到物理内存的转换。

直接映射的方式与使用物理地址差别不大,主要给操作系统使用,因为在初始化之前负责虚存管理的代码本身不能运行在被管理的虚地址空间。通常用户态应用程序无法使用直接映射方式。

3.3节将对存储管理做更详细的介绍。

(3)异常与中断处理

异常与中断是一种打断正常的软件执行流,切换到专门的处理函数的机制。它在各种运行模式的转换中起到关键的纽带作用。比如用户态代码执行过程中,当出现对特权空间的访问,或者访问了虚实地址映射表未定义的地址,或者需要调用操作系统服务等情况时,CPU通过发出异常来切换到核心态,进入操作系统定义的服务函数。操作系统完成处理后,返回发生异常的代码并同时切换到用户态。

3.2节将对异常与中断做更详细的介绍。

(4)控制状态寄存器

控制状态寄存器位于一个独立的地址空间,是支撑前面3种机制的具体实现,不同的指令系统差别较大。表3.1以LoongArch指令系统为例,列出其控制状态寄存器的功能。

表3.1 LoongArch处理器的控制状态寄存器

控制状态寄存器虽然重要,但对其操作的频率通常远远低于通用寄存器,所以指令系统中通常不会设计针对控制状态寄存器的访存和复杂运算指令。不过大多数指令系统至少会定义若干在控制状态寄存器和通用寄存器之间进行数据搬运的指令,从而可以将数据移动到通用寄存器中进行相关处理,或者进一步将处理结果写回控制状态寄存器中。在LoongArch指令系统中,就定义了CSRRD和CSRWR指令来完成控制状态寄存器的读写操作。例如,指令“csrrd $t0,CSR_CRMD” 这里CSR_CRMD是一个宏定义,表示一个立即数,其值为CRMD控制状态寄存器的编号0x0。使用CSR_CRMD这样的宏定义是为了便于代码理解。将控制状态寄存器CRMD的值读出,然后写入通用寄存器$t0中;指令“csrwr $t0,CSR_CRMD”将通用寄存器$t0中的值写入控制状态寄存器CRMD中,同时将控制状态寄存器CRMD的旧值写入通用寄存器$t0中。

[1] 特指直接运行在CPU上的应用,把虚拟机及其上运行的应用作为整体看待。

[2] 这里CSR_CRMD是一个宏定义,表示一个立即数,其值为CRMD控制状态寄存器的编号0x0。使用CSR_CRMD这样的宏定义是为了便于代码理解。