[V-04] 虚拟化基础-寄存器集(Register set)(基于AArch64)

ver0.2
在这里插入图片描述

更多精彩内容,请关注公众号

前言

前文在讲CPU架构和ISA的时候,反复提到了寄存器。作为CPU的核心组成部分,因其可在运行时的具备存储的能力,串联了CPU-Core中各个组件,构成了CPU平稳运行的上下文。寄存器存储的数据范围包括:指令、数据(运算用的用户数据、地址、运算的中间数据)、CPU的状态。不同的体系,CPU的架构也是不一样的,本文会在前文的基础上基于AArch64详细的介绍一下寄存器体系结构和作用,虚拟化离不开CPU的虚拟化,自然理解寄存器体系也是深入虚拟化技术的重要基础。

正文

1. 寄存的工作原理

在正式的介绍ARM的寄存器体系之前,先花一点时间了解一下寄存器的硬件电路和工作原理,为后续的分析做一些必要的准备。大学时应该不是每个同学都学过数电,所以本节还是要关注一下,其实寄存器并不神秘。

1.1 D触发器

数字电路中有这样一个电子原件叫做“D触发器”,长得如图1-1所示。
D

图1-1 D触发器逻辑视图

D触发器有两个输入,一个时钟(CLK)输入和一个数据(D)输入。此外,D触发器还有两个输出一个Q表示的主输出,另一个是Q’表示的Q的补码。给输入端输入数字脉冲信号后,输出端有如图1-2的波形。
D sequence

图1-2 D触发器时序图

D触发器需要时钟和信号两路输入才能工作,当满足触发条件的时候(图1-2中的示例触发条件是时钟的上升沿),D触发器会在下一个时钟周期内保持Q和D的状态保持一致。当不向D触发器施加任何时钟输入期间,此时D无论怎么变化,Q的输出不会有任何变化(保持D-Prev状态)。在数字电路中,D的状态只有两种:高电平、低电平,通常我们用1和0表示。
到目前,我们已经实现了1bit数据的存储了。

1.2 寄存器

下面我们把D触发器按照一定的规律排列一下,如图1-3所示。
4bit Register

图1-3 4-bit Register Layout

按照前面D触发器的特性,目前我们已经可以存储4bit的数据了。那么再增加4个D触发器,就可以存储8bit也就是一个byte的数据了,如图1-4所示。
在这里插入图片描述

图1-4 8-bit Register Block

在了解了寄存器的硬件逻辑之后,寄存器的概念应该也非常清晰了。寄存器就是在计算机及其他计算系统中一种非常重要的数字电路构件,通常由触发器(D触发器)组成,主要用来暂时存放数码或指令。一个触发器可以存放一位二进制代码,若要存放N位二进制数码,则需用N个触发器。寄存器应具有接收数据、存放数据和输出数据的功能,它由触发器和门电路组成。只有得到“存入脉冲”(又称“存入指令”、“写入指令”)时,寄存器才能接收数据。同样,在时钟脉冲和相关电路的配合下,寄存器中存储的数据也可以被读出,也就是寄存器的输出过程。
站在CPU-core的视角寄存器也分为两种类型,内部寄存器和外部寄存器。内部寄存器位于CPU内部,数量较少,通常有固定的名字而不是地址编号,它们用于CPU内部的运算和数据处理,如图1-5所示,所有A-Profile Core中的寄存器都称为内部寄存器。外部寄存器则位于计算机中其他部件上,用于暂存数据,与CPU之间通过“端口”(内存模型中的特殊物理地址)交换数据,具有寄存器和内存储器的双重特点,如图1-5所示,所有A-Profie Core之外的所有节点中的寄存器都称为外部寄存器。内外部寄存器因为访问方式的不同,导致的一个最明显的结果就是访问的速度要差好多。
bus ARCH

图1-5 典型的基于ARM Soc架构

寄存器的应用非常广泛,包括但不限于存储整数数字、地址、常数、浮点数等。它们在CPU内部用于执行算术及逻辑运算、寻址内存位置、读写数据到电脑的周边设备等。总的来说,寄存器是计算机系统中非常重要的组成部分,它们以高速读写能力支持CPU的运算和数据处理需求。

2. ARM体系的寄存器

先来简要回顾一下ARM PE处理器的执行状态相关的内容:

执⾏状态(execution state):处理器运⾏时的环境,包括寄存器的位宽、⽀持的指令集、异常模型、内存管理以及编程模型等。ARMv8体系结构定义了两个执⾏状态。
AArch64:64位的执⾏状态。提供31个64位的通⽤寄存器。提供64位的程序计数(Program Counter,PC)指针寄存器、栈指针(Stack Pointer,SP)寄存器以及异常链接寄存器(Exception Link Register,ELR)。提供A64指令集。定义ARMv8异常模型,⽀持4个异常等级,即EL0〜EL3。提供64位的内存模型。定义⼀组处理器状态(PSTATE)⽤来保存PE的状态。
AArch32:32位的执⾏状态。提供13个32位的通⽤寄存器,再加上PC指针寄存器、SP寄存器、链接寄存器(Link Register,LR)。⽀持两套指令集,分别是A32和T32(Thumb指令集)指令集。⽀持ARMv7-A异常模型,基于PE模式并映射到ARMv8的异常模型中。提供32位的虚拟内存访问机制。定义⼀组PSTATE⽤来保存PE的状态。

In ARMv8, execution occurs at one of four Exception levels. In AArch64, the Exception level determines the level of privilege, in a similar way to the privilege levels defined in ARMv7. The Exception level determines the privilege level, so execution at ELn corresponds to privilege PLn.
Exception levels provide a logical separation of software execution privilege that applies across all operating states of the ARMv8 architecture. It is similar to, and supports the concept of, hierarchical protection domains common in computer science.
The following is a typical example of what software runs at each Exception level:
EL0 Normal user applications.
EL1 Operating system kernel typically described as privileged.
EL2 Hypervisor.
EL3 Low-level firmware, including the Secure Monitor.

可以看出ARM不同PE状态下,寄存器的体系也是不一样,本文会重点关注AArch64状态下的寄存器体系。
ARM的寄存器从作用和访问方式的角度大致可以分为如下几个类型:
(1) 通用寄存器(General-purpose registers)
(2) PE状态寄存器(PState registers)
(3) 特殊寄存器(Special registers)
(4) 系统寄存器(System registers)
(5) 浮点型寄存器(floating-point registers)

通用寄存器(General-purpose registers)

AArch64执⾏状态⽀持31个64位的通⽤寄存器,分别是X0〜X30。这31个通用寄存器有两种访问方式:64位(Xn)和32位(Wn),它们的映射关系如下。
GR 64  - 32

图2-1 64-bit registers with W and X access

Procedure Call Standard (PCS)
既然是通用寄存器那么大家就都可以使用,而现代的软件项目往往需要各方协作,就算一个文件中也涉及到函数调用的场景。一个通用的寄存器Xn在A函数里的值,在B函数里被修改了怎么办,这个时候大家是同一个上下文,资源是共享的。面对这样的场景,大家自然要坐下来商量解决方案,那就是指定标准和规则。看一段ARM官方的文档的说法:

Procedure Call Standard for the ARM 64-bit Architecture (AArch64) ABI release specifies how subroutines can be separately written, compiled and assembled to work together. It specifies the contract between a calling routine and a callee, or between a routine and its execution environment, for example, the obligations when calling a routine or stack layout.

ARM对通用寄存器做了分类并使用场景做了限制,如图2-2所示。
PCS

图2-2 通用寄存器分类

具体的规则这里不再赘述,详细内容大家可以查看ARM的官方手册,这里只举一个例子帮大家理解,如图2-3所示, 如果foo只是实现一个减法运算,大致的代码如下。

foo:
	SUB  X0, X0, X1
	RET

PCS demo

图2-3 PCS 示例

本节开始简要回顾了AArch64的异常模型,通用寄存器最重要的特点就是可以在所有ELn被访问,ARM手册中是这么描述的:

The AArch64 execution state provides 31 × 64-bit general-purpose registers accessible at all times and in all Exception levels.

也就是说在低level的EL环境下操作这些寄存器对CPU来说是透明无感的,换句话说如果GuestOS(EL0, EL1)如果所有操作通用寄存器的指令都会和非虚拟化话的上下文一样没有任何性能损耗。

PE状态寄存器(PSTATE registers)

如果没有异常机制,CPU会一直执行一段程序的指令流,直到这段程序自己主动让出CPU资源,并且选择下一段程序流继续执行(历史上这种设计还真的存在过)。当有了异常机制后,这个指令流是可以被打断的,去执行更紧急的任务,执行完成之后再恢复当前任务或者选择一个其他任务在当前的CPU-Core上继续执行。这是一个典型的异常处理流程。结合虚拟化的场景,例如GuestOS的内核执行在EL1层,此时来了一个中断需要切换到EL2(Hypervisor)中处理,处理完之后再恢复EL1的场景继续执行。EL1的上下文和EL2的上下文肯定是不一样的,起码的总得有一个地方得记录一下GuestOS的kernel切换出去的指令流的下一条指令的地址吧,否则就恢复不了EL1指令流的继续执行啊。AArch64上是通过PSTATE代表的一组寄存器保存这个状态。

AArch64 does not have a direct equivalent of the ARMv7 Current Program Status Register (CPSR). In AArch64, the components of the traditional CPSR are supplied as fields that can be made accessible independently. These are referred to collectively as Processor State ( PSTATE ).

PSTATE不是一个寄存器,它表示的是保存当前 process状态信息的一组寄存器或者一些标志位信息的统称,如图2-4展示PSTATE的属性定义。
PSTATE

图2-4 PSTATE各个属性定义

需要注意上面是一个全集,具体在各个ELn的分配如下:

The PSTATE .{N, Z, C, V} fields can be accessed at EL0. All other PSTATE fields can be executed at EL1 or higher and are UNDEFINED at EL0.

由于目前AArch64下EL0等级最低且不具备任何异常处理能力,因此在EL0下发生异常时不需要在这个异常等级下保存不了任何PSTATE状态。

特殊寄存器(Special registers)

下面介绍下AArch64体系下的特殊用途的寄存器,如图2-5所示。
特殊类型寄存器

图2-5 特殊用途寄存器

这些寄存器的用途都非常的重要,详细内容可以查阅相关手册,这里只回答两个问题。
为什么没有SPSR_EL0?
在ARMv8架构中,SPSR(Saved Program Status Register)寄存器是用于保存程序状态的寄存器,但它主要用于异常处理时保存处理器的状态。在ARMv8的Exception Level(EL)架构中,SPSR寄存器与特定的异常级别(EL1、EL2、EL3)相关联,因此有SPSR_EL1、SPSR_EL2和SPSR_EL3,但没有PSR_EL0。
EL0是用户模式,没有异常处理的能力,因此不需要SPSR_EL0寄存器来保存程序状态。在发生异常时,硬件会自动将当前程序的PC值(程序计数器)和PSTATE(程序状态寄存器)的值保存到与当前异常级别相对应的SPSR_ELx寄存器中,以便在异常处理完成后能够恢复程序的执行。
结合虚拟化场景,当异常发生时,CPU正在执行GuestOS中的程序,那么当前GuestOS所执行的CPU的PSTATE会保存在SPSR_EL2或者SPSR_EL3中。

为什么没有ELR_EL0?
在AArch64架构中,ELR(Exception Link Register,异常链接寄存器)是用于在异常处理过程中保存程序计数器(PC)的寄存器。然而,在AArch64的异常级别模型中,EL0(Exception Level 0)是最低的异常级别,通常用于用户模式(User Mode)的执行。
在AArch64中,异常不会直接路由(target)到EL0级别。当在EL0级别(即用户模式)触发一个异常时,这个异常会被提升到更高的异常级别(如EL1、EL2或EL3)进行处理。这是因为操作系统和虚拟化环境需要在更高的异常级别上控制和管理异常。
因此,ELR_EL0在AArch64中是不需要存在的。相反,当在EL0级别触发异常时,PC指针会被保存到对应更高异常级别的ELR寄存器中(如ELR_EL1、ELR_EL2或ELR_EL3),然后跳转到相应异常级别的异常向量表中进行处理。
其实原理和SPSR_EL0为啥不需要存在是差不多的,只是一个是用来保存PC,一个是用来保存PC指针。

系统寄存器

除上⾯介绍的通⽤寄存器和特殊寄存器之外,ARMv8体系结构还定义了很多的系统寄存器,通过访问和设置这些系统寄存器来完成对处理器不同的功能配置。ARMv8体系结构⽀持如下7类系统寄存器:
• 通⽤系统控制寄存器;
• 调试寄存器;
• 性能监控寄存器;
• 活动监控寄存器;• 统计扩展寄存器;
• RAS寄存器;
• 通⽤定时器寄存器。
系统寄存器⽀持不同的异常等级的访问,通常系统寄存器会使⽤“Reg_ELn”的⽅式来表⽰。
• Reg_EL1:处理器处于EL1、EL2以及EL3时可以访问该寄存器。
• Reg_EL2:处理器处于EL2和EL3时可以访问该寄存器。
• ⼤部分系统寄存器不⽀持处理器处于EL0时访问,但也有⼀些例外,如CTR_EL0。
• 通过MSR、MRS指令访问系统寄存器。

浮点型寄存器(floating-point registers)

浮点型寄存器的用途:

In addition to the general-purpose registers, ARMv8 also has 32 128-bit floating-point registers labeled V0-V31. The 32 registers are used to hold floating-point operands for scalar floating-point instructions and both scalar and vector operands for NEON operations.

这部分寄存器的作用和使用规则,大家可以自行查阅手册,这里不再赘述。

3. 系统寄与虚拟化

寄存器对于虚拟化技术的重要性不言而喻,在介绍系统寄存器的时候,我们说过通过配置系统寄存器完成对处理器的配置,那么来看一下手册中有多少和虚拟化相关的配置,如图3-1所示。
Hyper Reg

图3-1 手册中虚拟化相关的系统寄存器

书不尽言,生硬的照搬手册是低效和无趣的,后面的文章中,我们会经常和这些寄存器打交道,到时会做必要的说明。这里仅举一个重要的例子做简要说明。
HCR_EL2 (Hypervisor Configuration Register)

Provides configuration controls for virtualization, including defining whether various operations are trapped to EL2.

armv8在虚拟化扩展中提供了敏感指令和异常的捕获功能,可以通过配置hypervisor控制寄存器hcr_el2实现,它将vm执⾏的敏感指令
或异常路由到EL2中,hypervisor捕获到相关异常后可为其模拟相关功能。可以说这个是实现虚拟化技术的核心配置寄存器,正式有了这个寄存的配置才能够实现虚拟化技术中的核心“捕获与陷入”。它大大概长这个样子,如图3-2所示。
HCR_EL2

图3-2 HCR_EL2 Layout

其中配置EL2可以捕获的部分敏感操作或者异常如下(这里仅局一部分例子,详细的可以查阅手册):
FMO:配置该位会将fiq中断路由到EL2
IMO:配置该位会将irq中断路由到EL2
AMO:配置该位会将serror异常路由到EL2

结语

本文只聚焦AArch64的状态,实际上在介绍指令集架构ISA的时候提到过ARMv8实际上是有AArch64和AArch32两种状态,而且两种状态还可以按照一定的规则做交替执行。那么对于寄存器这块是如何做映射转换的自然也有一套规则,例如图4-1所示。
MAP

图4-1 AArch64 to AArch32 register mapping

本文我们从寄存器的硬件电路开始讲起只到介绍了AArch64的寄存器体系,为进一步研究虚拟化技术打下了基础。后续我们看到虚拟化技术中涉及到的相关寄存器时,脑海中也会有起码的概念,扫清深入虚拟化技术的障碍。限于篇幅,有些细节不能够详细的诠释,后续规划ARM体系的文章中会有一个章节做一个补充,例如各种寄存器的访问方式等等。
在这里插入图片描述

更多精彩内容,请关注公众号

Reference

[01] <SysReg_xml_A_profile-2024-03.pdf>
[02] <80-ARM-ARCH-HK0002_一文搞懂Cortex-A77_ARMv8架构工作原理.pdf>
[03] <80-ARM-ARCH-OVW-cs0002_ARM64体系结构编程与实践-基础知识.pdf>
[04] <ISA_A64_xml_A_profile-2024-03.pdf>
[05] <80-V-Kvm-ARM-zh0002_基于armv8的kvm实现分析(二)_armv8的虚拟化支持.pdf>
[06] <learn_the_architecture_a64_instruction_set_architecture_guide_102374_0102_01_en.pdf>
[07] <DEN0024A_v8_architecture_PG.pdf>
[08] <learn_the_architecture_aarch64_virtualization_guide_102142_0100_04_en.pdf>
[09] <aarch64_virtualization_100942_0100_en.pdf>
[10] <80-ARM-ARCH-OVW-cs0002_ARM64体系结构编程与实践-基础知识.pdf>
[11] 什么是D触发器,D触发器如何工作?
[12] D触发器的结构特点、工作原理

Glossary

AP - Application Processors
SCP - System Control Processor (SCP)
SMC - Secure Monitor Call (SMC)
HVC - Hypervisor Call (HVC)
OPP - Operating Performance Point (OPP)
DVFS - Dynamic Voltage and Frequency Scaling (DVFS)
DCVS - Dynamic Clock and Voltage Scaling (DCVS)
AMU - Arm Activity Monitors Extension (AMU)
EAS - Energy Aware Scheduling
IPA - Intelligent Power Allocation
AP - Application Processor (AP)
SIMD - Single Instruction Multiple Data(SIMD)
VBAR - Vector Base Address Register
SCTLR - System Control Register
ELR - Exception Link Register
ESR - Exception Syndrome Register
FAR - Fault Address Register
HCR - Hypervisor Configuration Register
SCR - Secure Configuration Register
SCTLR - System Control Register
SPSR - Saved Program Status Register
UART - Universal Asynchronous Receiver/Transmitter
ALU - Arithmetical Logical Unit
NMI - non-maskable interrupts
BSA - Base System Architecture
SBSA - Server Base System Architecture
BBR - Base Boot Requirements
TBSA - Trusted Base System Architecture
AMBA - Advanced Microcontroller Bus Architecture
TRM - Technical Reference Manual
MMU - Memory Management Unit
DSU - DynamIQ Shared Unit
BPU - Branch Predictor Unit
INTID - Interrupt ID
SBSA - Server Base System Architecture
ESR - Exception Syndrome Register
FAR - Fault Address Register
ELR - Exception Link Register
VBAR - Vector Base Address Registers
PSTATE - Process state, PSTATE
PCS - Procedure Call Standard
ABI - Application Binary Interface

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值