EL2异常捕获设置-HCR_EL2

前言

之前写了一点关于异常的东西,比较浅显的勾勒了一下异常的全貌,就像一幅20万像素的地球全景照,20万像素也就是能画出蓝白相间的圆;画成这个样子当然不会是我这种对吹牛都要持证上岗的人的作风。再写一篇或许更繁复但只求仅能部分指明要害的文章,以表述异常的一个重要分支,EL2层行为控制相关的寄存器HCR_EL2当然也顺手写到了EL1层同类型的寄存器SCTLR_EL1。为何选择HCR_EL2也是有原因的,大概与之前选择关键的思路是一致的;对于Aarch64指令架构下的用于控制的寄存器中,我认为HCR_EL2是牵扯能力最强的寄存器,所谓牵扯能力就是说涉及的东西最多的。因为EL3不是研究的目标,EL1是为内核层次设计,百度的大神们已经讲述的非常多,所以挑出HCR_EL2进行分析,并尽可能将其控制位的设计目标表述清楚。本文假设阅读者已经看过<Aarch64异常>并基于ARM指令集的DDI0487版本,最高到arm-v8.3版本。

正文

HCR_EL2寄存器的控制位大概是44个,占了45bit,有一个控制位占了两位。综合来说,HCR_EL2的控制位是为了确定所产生的异常是否要被捕获到EL2,因此各个控制位的定义如下:

1.手工地址转换产生的异常(AT)控制

主要控制EL1能否手工执行地址转换指令。地址转换是由MMU完成,AT S1ExR/W指令在执行完成后,可以从PAR_EL1中读取出转换结果。此控制位置0则不会捕获EL1执行的ATS1ExR/W指令产生的异常;此控制位置1则会捕获EL1执行的AT S1ExR/W指令产生的异常到EL2。

2.嵌套虚拟化产生的异常(NV/NV1)。

NV 为了嵌套虚拟化存在,所谓嵌套虚拟化是指在EL1中运行Guest Hypervisor。对于嵌套虚拟化我并不感兴趣,但是这里面透露出如何在EL1中运行一个Hypervisor,使其正常运行在EL1。EL1访问CurrentEL寄存器得到的值是0x2;EL1访问特殊用途寄存器、系统寄存器;执行EL1/2转换规则的地址转换和TLB维护指令;都会被捕获到EL2。具体的特殊用途寄存器和系统寄存器是:

所有用MRS/MSR访问的命名末尾是_EL2/_EL12/_EL02的寄存器;

用MRS/MSR访问的特殊目的寄存器SPSR_irq/SPSR_abt/SPSR_und/SPSR_fiq;

用MRS/MSR访问的特殊寄存器SP_EL1。

具体的要捕获的指令还有:

EL2转换规则的地址转换指令和TLB维护指令;

    只有从EL2/EL3能访问的EL1转换规则的地址转换指令和TLB维护指令;

ERET、ERETAA和ERETAB指令。

TSC为1且EL3未实现的SMC指令。

解释一下:

CurrentEL寄存器是只读的,需要EL1以上才能访问,指示当前的异常等级,也就是说NV位可以使CurrentEL骗人。MRS/MSR自不必说,SPSR_irq/abt/und/fiq就比较有趣了,在Aarch64异常中,EL1/2/3分别有自己的SPSR寄存器,作为异步异常的IRQ、FIQ以及32位相关的Abort状态、Undefined状态都有SPSR的,作用与SPSR_ELx一致。ERET自然就是从异常返回的指令了,也是要被捕获到EL2。 

NV1 应该算是NV的副手,第一个用途是决定EL1对VBAR_EL1、ELR_EL1、SPSR_EL1的访问是否被捕获到EL2。当NV==1且NV1==0,发生到EL1和EL1发生的异常,引起SPSR_EL1.M[3:2](标志EL等级)值0b10,而不是0b01。当NV==1且NV1==1,EL1页表块页中的标志位[54]会是PXN而不是UXN;[53]位变为保留,[6]位被当做0处理。在多层次权限使能情况下,EL1转换表Table标志位的[61]作为0;[60]保留PXN表而不是UXN表,[59]变为保留。除直接读取,EL1的PSTATE.PAN被当做0处理。EL1执行LDTR*/STTR*指令与LDR*/STR*一样。

上面一段话是原样翻译过来的,我解释一下这里面的东西:

VBAR_EL1寄存器是用于保存EL1的异常向量的基地址;EL1对VBAR_EL1的访问被捕获到EL2,很明显是为了防止Guest Hypervisor中运行的EL1的内核使用了EL1的异常向量。ELR_EL1异常返回地址,同样不能使用。SPSR_EL1是异常发生时会使用的PSTATE,也是不能直接使用。

PXN和UXN的内容就比较多,但是非常有价值,因此单独取出解析一下:

XN是Execute-Never,XN位表示此页表项管理下的内存数据可以作为代码执行;

PXN只有1阶段页表且1阶段页表可以支持两个VA范围的情况下存在,置位后表示仅有>EL0状态下才能执行从此内存段的代码;

UXN标志表示只有EL0状态下才能将此页表管理的内存中的数据作为代码执行。

当厂商提供CPU未支持ARMv8.2-TTS2UXN,XN在2阶转换中同样是1位;

当ARMv8.2-TTS2UXN被支持,XN由2bit组成:

XN[1]==0,XN[0]==0,则2阶段控制:允许EL1和EL0执行此内存段数据;

XN[1]==0,XN[0]==1,则2阶段控制:不允许EL1执行内存段数据,但允许EL0执行;

XN[1]==1,XN[0]==0,则2阶段控制:不允许EL1和EL0执行内存段数据;

XN[1]==1,XN[0]==1,则2阶段控制:允许EL1执行内存段数据,不允许EL0执行。

3.指针认证(Pointer Authentication)相关的异常。

Pointer Authentication具体是个什么东西并不了解,但其相关的指令非常之多。

4.缓存一致性相关(MIOCNCE)

具体不知道干啥,只知道ARM strongly 推荐不用。

5.EL1/0同步外部异常路由设置(TEA)

 

6.错误回溯寄存器访问异常的捕获(TERR)

 

7.LOR寄存器的访问异常的捕获(TLOR)

LOR并不知为何物。

8.内核运行异常等级设置(E2H)。

置位后,表示EL2运行有一个操作系统。而置零时表示EL2运行的是Hypervisor。当E2H为0时,TCR_EL2控制EL2转换规则的1阶段,支持单VA范围,使用TTBR0_EL2作为页表基地址寄存器;当E2H为1时,TCR_EL2控制1阶段EL2&0转换规则,同时支持低VA范围(TTBR0_EL2)和高VA范围(TTBR1_EL2)。

E2H==0时TCR_EL2并不复杂,我简单说一下其中控制位(忽略可厂商自定义的位)。

HPD位是多级权限控制位,影响多级控制位,影响TTBR0_EL2指向的转换表APTable、PXNTable和UXNTable。

HD为使能硬件脏页自动回写,需要HA位使能,

HA位使能即硬件可访问标志位更新;这些都是EL2执行1阶段转换的控制。

TBI是头字节忽略。

PS是物理地址大小:

000是32位4GB;

001是36位64GB;

   010是40位1TB;

011是42位4TB;

100是44位16TB;

   101是48位256TB;

110是52位4PB。

TG0控制TTBR0_EL2的物理分页单位:

   00是4K每页,

01是64K每页,

10是16K每页。

SH0控制内存的共享属性,与使用TTBR0_EL2的TTW相关联:

   00是不可共享;

10是Outer共享;

11是Inner共享。

ORGN0和IRGN0是内存Outer/Inner缓存能力属性,与TTBR0_EL2相关联:

   00是普通内存的Outer/Inner不可缓存;

   01是普通内存的Outer/Inner回写、读分析、写分配可缓存;

   10是普通内存的Outer/Inner写通、读分配、无写分配可缓存;

   11是普通内存的Outer/Inner回写、读分配无写分配可缓存;

   按我的理解解释一下,Outer是二级缓存,Inner是一级缓存,

   回写、写通当然就是两种cache形式,

   读分配应该是读取会使用缓存,写分配应该是写入会使用缓存。

E2H==1时TCR_EL2的控制位就比较多了,不过主要功能还是上面的东西,需要关注两个地址范围TTBR0_EL2和TTBR1_EL2,大致比上面的控制位翻了一倍。

9.2阶段指令、数据缓存是否允许使用(ID/CD)。

 

10.低异常状态执行控制(RW)

置零决定EL1是aarch32;置1决定EL1是aarch64,其EL0的执行状态还是由PSTATE.nRW决定。

11.虚拟内存管理寄存器读取控制(TRVM)

此处所谓内存管理寄存器是指(aarch64):SCTLR_EL1,TTBR0_EL1,TTBR1_EL1,TCR_EL1,ESR_EL1,FAR_EL1,AFSR0_EL1,AFSR1_EL1,MAIR_EL1,AMAIR_EL1,CONTEXIDR_EL1。

哇!好多寄存器,但是很开心的发现这里面出现了许多熟悉的面孔,存储页表基地址的TTBR0_EL1(低地址段)、TTBR1_EL1(高地址段),其中的ASID占8位(ASID是啥我就不说了),另外的48位是基地址。

TCR_EL1也可参照TCR_EL2知道其控制的内容。

ESR_EL1是能给出异常发生原因的狠人,在<Aarch64异常>中已经见识过。

FAR_EL1存同步指令数据中止或PC对齐或观察点异常的失败虚拟地址,也提过了。

AFSR0_EL1/AFSR1_EL1是归厂商自定义的。

MAIR_EL1/AMAIR_EL1是内存属性相关(如Inner、Outer内存的写通、回写等属性)。

CONTEXTIDER_EL1放的是进程ID,需要内核设入,使CPU知道当前运行的进程ID,手册说仅可用于Debug和Trace逻辑。

上述寄存器就只剩下SCTLR_EL1是未知的了,但不得不说,SCTLR_EL1也是个内容丰富的寄存器呀,内容量大概有本文的一半。SCTLR_EL1的地位主要在于控制EL0的一些操作是否产生异常并路由到EL1, 是不是有点熟悉。。。本文对HCR_EL2开头也有类似的这么一句。。。所以说SCTLR_EL1在EL1/0与HCR_EL2在EL2/1/0是差不多的,不过HCR_EL2很明显更大,更强,因此简要说明SCTLR_EL1内容

EnIA/EnIB/EnDA/EnDB是指针认证相关控制位,还是忽略。

UCI是捕获EL0的cache维护指令到EL1,置零后EL0执行:

DC CVAU(按地址清理数据缓存PoU)、

DC CIVAC(按地址清除并失效数据缓存PoC)、

DC CVAC(按地址清除缓存PoC)、

DC CVAP(按地址清除缓存PoP,如内存不识别Persistence操作则与DC CVAC)、

IC IVAU(按地址失效指令缓存PoU)

将会被捕获到EL1。

在此我似乎应该说一下PoU和PoC,简单讲PoC是所有能访存的设备的同步点(特定地址下,数据内容一致),PoU是一个Core去与主存同步一下。

EE、E0E是大小端相关的控制位。

SPAN是对PSTATE.PAN的控制:

置零则发生异常到EL1时,PSTATE.PAN置1;

   置1则发生异常到EL1时PSTATE.PAN保持原样。

IESB位控制在异常入口、出口添加的隐式的错误同步事件。

WXN位可控制EL1&0转换规则,强制所有可写内存区域都作为XN处理。

nTWE/nTWI位控制捕获EL0执行WFE/WFI指令到EL1。

UCT位可捕获EL0访问CTR_EL0寄存器到EL1。

CTR_EL0位提供cache的架构信息。

DZE位捕获EL0执行DC ZVA指令到EL1:

   DC ZVA是按地址将数据缓存归零:将自然对齐的N字节的块归零,N由DCZID_EL0确定。

I位控制指令访问可缓存行控制。

UMA位EL0执行MSR/MRS访问PSTATE的D/A/I/F掩码捕获到EL1。

SA0位控制使能EL0的SP对齐检查。

SA位控制使能EL1的SP对齐检查。

C位控制数据访问的缓存能力控制。

A位控制指令对齐检查。

M位控制EL1/0的1阶地址转换使能。

另外还有其他32位相关的控制位没有列出。

SCTLR_EL1的功能明显较HCR_EL2更少一些,不过EL2也还有自己的SCTLR_EL2寄存器,当HCR_EL2关闭E2H和TGE的时候,SCTLR_EL2功能较少,但当E2H和TGE打开后SCTLR_EL2的功能就与SCTLR_EL1差不多了。

12.HVC指令的关闭(HCD)

  

13.对EL0/1执行DC ZVA指令的捕获(TDZ)

DC ZVA指令在11.9的SCTLR_EL1介绍中有提到,

EL0执行DC ZVA可以被SCTLR_EL1.DZE设置为被捕获到EL1,

EL1和EL0执行DC ZVA可以都被HCR_EL2.TDZ设置为捕获到EL2

14.对EL0产生的异常的捕获(TGE)

 

15.对EL1写虚拟内存控制寄存器的捕获(TVM)

TRVM控制EL1对虚拟内存控制寄存器的读,TVM控制写,相关的虚拟内存控制寄存器都是一样的。

16.对EL1执行TLB维护指令的捕获(TTLB)

其涉及的相关指令主要是失效TLB中缓存的转换表条目。

17.对EL0/1指令缓存维护(PoU)的捕获(TPU)

捕获cache的PoU维护指令:EL0主要用IC IVAU和DC CVAU(受到SCTLR_EL1控制),在前面已经提到过IC IVAU和DCCVAU的功能;EL1主要用IC IVAU,IC IALLU,IC IALLUIS,DCCVAU,指令功能也已经提到;

18.对EL0/1数据或统一缓存维护(PoC/Persistence)指令的捕获(TPCP)

EL0主要用DC CIVAC,DC CVAC,DCCVAP,受到SCTLR_EL1控制,第一个C表示清理,I表示失效,最后一个C是Coherency,指令功能前面已经提过。

EL1主要用DC IVAC,DC CIVAC,DCCVAC,DC CVAP。

19.对EL1数据或统一缓存(按Set/Way)维护指令的捕获(TSW)

EL1主要涉及指令为:DC ISW,DC CSW,DCCISW,C表示清理,I表示失效,SW表示set/way。

20.对EL1访问Auxiliary控制寄存器的捕获(TACR)

访问厂商定义管理寄存器ACTLR_EL1捕获到EL2。

21.对EL1访问厂商自定义功能的捕获(TIDCP)

 

22.对EL1执行SMC指令的捕获(TSC)

 

23.对EL1读ID group3/2/1/0寄存器的捕获(TID3/2/1/0)

 

24.对EL0/1执行WFE/WFI指令的捕获(TWE/TWI)

 

25.试图关闭EL0/1的一阶段页表转换并保持2阶段页表转换(DC)

SCTLR_EL1的对一阶段转换的控制力小于HCR_EL2.DC;HCR_EL2.VM的控制力也小于HCR_EL2.DC,无论VM位怎样,2阶段页表转换会被打开。提供给EL1&0的转换规则是,普通内存不可共享(non-shareable),Inner回写(write-back)、读申请(read-allocate)、写申请(write-allocate),Outer回写、读申请、写申请。

26.控制EL0/1内存屏障的最小共享域(BSU,2bit)

所谓内存屏障的最小共享域,内存屏障(barrier)我就不说了,内存屏障的minimum shareabilitydomain我认为是指所执行的内存屏障指令能够影响的范围。

00表示无影响,这个无影响应该是说只清空了Core的流水线?

01是InnerShareable,这应该表示会引起1级缓存的一致?

10是OuterShareable,这应该是表示会引起1、2级缓存的一致点(类似PoU)?

11是Fullsystem,这应该就是屏障会触发PoC点了?

上述是猜测,如有精确解释请不吝指出[email protected]

27.强制一些EL1执行的指令在内Inner共享域广播(FB)

这些指令是:

TLBI VMALLE1(按VMID失效TLB),

TLBI VAE1(按ASID下的VA失效TLB),

TLBI ASIDE1(按ASID失效TLB),

TLBI VAAE1(按VA失效TLB,所有ASID),

TLBI VALE1(按ASID下的VA失效最低级TLB),

TLBI VAALE1(按VA失效最低级TLB,所有ASID)

IC IALLU(失效所有cache到PoU点)

28.虚拟SError中断触发标志(VSE)

 

29.虚拟IRQ中断触发标志(VI)

 

30.虚拟FIQ中断触发标志(VF)

 

31.物理SError/IRQ/FIQ中断路由控制(AMO/IMO/FMO)

除被路由到EL3外,上述中断均路由到EL2,如果HCR_EL2.TGE==0则vSError/vIRQ/vFIQ都会打开。

34.对TTW的保护(PTW)

阶段的TTW服从2阶段转换;两阶段转换后,内存类型属性可能是设备内存;当这种情况发生,PTW置1则产生2阶段权限失败。

35.EL1执行的按Set/Way数据缓存失效是否引起数据缓存的清除(SWIO)

 

36.EL0/1的2阶段地址转换的使能(VM)

为EL1&0的转换规则使能2阶段转换。使能后,执行EL1的数据缓存失效指令将会变成数据缓存清除并失效。

  •  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章