AMD SEV基本原理
- 背景
- SME
- Arch
- C-bit
- SME-MK
- Interface
- SME
- SME-MK
- SEV
- Arch
- Interface
- SEV API
- Key Management
- Guest Policy
- Mailbox Register Protocol
- Platform Management API
- Guest Management API
背景
- TODO
SME
- SME(Secure Memory Encryption)是AMD内存加密硬件特性,AMD通过在SOC的内存控制器上增加加解密引擎,实现对内存数据的加解密。
Arch
- SME内存加密原理如下图所示:
- TODO
C-bit
- 为支持对内存的加密并且兼容原有的MMU硬件设计,AMD将页表项中原来存放物理页地址的字段划分出1个bit作为
C-bit
(enCrypted bit
),用于控制该表项指向的物理内存页是否需要加密。由于页表项的低12bit已经被用做传统的页表转换功能,因此C-bit
只能放到存放物理页地址的字段,并且其具体位置和硬件架构相关,需要通过CPUID获取得到。注意,C-bit
可以存在于PTE、PDE、PDPE甚至PML4E的表项中,因此C-bit
既可以控制1个具体的物理页是否加密,可以控制整个PDE、PDPE、PML4E表包含的物理页是否加密。 - 下图是AMD手册中1个4K页表项的字段描述,对于Hygon C86 7380 32-core Processor,其
C-bit
为bit 47。从硬件设计来看,AMD牺牲了至少1 bit物理地址位宽来支持内存页加密。
- AMD利用页表项中的物理地址来支持内存加密,势必会导致物理地址位宽减少,AMD没有给出计算减少物理地址位宽的方式,而是提供了CPUID指令让用户查询, AMD手册中查询
C-bit
和PhysAddrReduction
介绍如下图所示(Volume 3 Appendix E.4.17):
- 当EAX输入为0x8000001F,执行CPUID指令后,EBX寄存器中存放了
CbitPosition
和PhysAddrReduction
相关信息:
- CbitPosition: C-bit在页表项中的位置,单位bit
- PhysAddrReduction:引入C-bit后页表项中物理地址减少的宽度,单位bit
- C-bit既能在CPU的非虚拟化(non-vitualized)模式打开,也可以在虚拟化模式且SEV特性使能的时候打开。在虚拟化模式下,使用NPT实现硬件辅助的内存虚拟化时,AMD CPU支持通过在Guest的页表项中设置C-bit来控制是否对GPA对应的物理页是否加密。Guest页表项的C-bit控制物理页是否加密原理示意图如下所示:
- AMD NPT在检测到C-bit使能后,会在页地址转换时增加额外逻辑处理C-bit,具体为:
- 提取NPT的输入 — Guest页表项内容(GPA),根据CPUID查询得到的
CbitPosition
信息在页表项中定位C-bit
的位置,提取其内容并保存。 - 将GPA作为硬件NPT页地址转换的输入,得到HPA
- 将C-bit内容和2中得到的HPA一道,作为页表项内容填入物理内存页表
- 注意,通过CPUID查询得到的
PhysAddrReduction
,只对物理地址的宽度有影响,对Guest的GPA地址没有影响。假设查询得到PhysAddrReduction
为5,那么原来52bit的物理地址HPA
变为了52-5=47bit。对于GPA,其宽度只减少了1bit,即C-bit占用的那1bit。
SME-MK
C-bit
的引入为系统软件提供了1个内存页加密的开关。在非虚拟化的应用场景下,为了让OS软件实现更细粒度的加密控制,AMD还设计了Multi-Key Secure Memory Encryption (SME-MK)
特性,该特性允许OS软件将加密内存使用的密钥导入到SOC的内存控制器中,然后在内存加密时通过选择密钥ID(EncrKeyID
)指定使用的密钥。SME-MK
可以通过CPUID Fn8000_0023_EAX[MemHmk]
来查询CPU是否支持,可以通过CPUID Fn8000_0023_EBX[MaxMemHmkEncrKeyID]
查询EncrKeyID
的最大值。SME-MK
特性可以支持OS上不同应用程序独立加密自己的内存,其设计并非支持机密虚拟化,因此SME-MK
与SME
是互斥的。使能SME-MK
时SME
需要关闭,下文介绍SEV时我们可以知道,SEV特性依赖SME的打开。因此可以理解为,SME-MK
可以实现多个应用内存的独立加密,应用于非虚拟化场景,SME可以使多个虚机的内存独立加密,应用在虚拟化场景,即SEV场景。
Interface
SME
- 软件可以通过CPUID探测CPU是否支持SME相关特性,同时通过写SYSCFG MSR(地址:0xc0010010)设置。
- 通过
CPUID Fn8000_001F[EAX]
,可以查询CPU是否支持SME,查询信息字段解释如下 :
- 通过写SYSCFG MSR可以使能SME,SYSCFG MSR字段解释如下:
- CPUID Fn8000_001F指令的EAX和EBX输出解释已在之前 介绍,这里贴出AMD手册中ECX和EDX中各字段含义,如下 :
- 以Hygon C86 7380 32-core Processor为例,并升级到Hygon支持机密计算的内核,通过cpuid工具查看CPU是否支持SME和SEV相关特性。
- EAX:0xf,0b1111,支持SME、SEV、PageFlushMsr、SEV-ES
- EBX: 0x16f,0b101101111,
bit[0]-bit[5]为CbitPosition,二进制0b101111,十进制47,表示C-bit控制位 在页表项的bit 47
bit[6]-bit[11]为PhysAddrReduction,二进制0b101,十进制5,表示CPU寻址物理内存空间使用的地址长度减少了5bit - ECX:0xffff,15,SEV相关,参考SEV章节
- EDX:0x1,MinSevNoEsAsid,SEV相关,参考SEV章节
- 通过rdmsr工具查看当前CPU的SYSCFG MSR输出:0xf40000 = 0b1111 0100 0000 0000 0000 0000
- 参考手册,解析上面MSR寄存器的输出字段含义如下:
- bit 18: MFDE enabled
- bit 20: MVDM enabled
- bit 21: TOM2 enabled
- bit 22: FWB enabled
- bit 23: MEME,MemEncryptionModeEn enabled,内存加密特性使能
- bit 26: HMKE,HostMultiKeyMemEncrModeEn disabled
SME-MK
- 通过
CPUID Fn8000_0023_EAX[MemHmk]
指令可以查询CPU是否支持SME-MK
,如果CPU支持 ,可以通过CPUID Fn8000_0023_EBX[MaxMemHmkEncrKeyID]
查询CPU支持的密钥数上限;通过写SYSCFG MSR
可以使能SME-MK
。CPUID的输出信息如下图所示,使能SME-MK
的SYSCFG MSR
位在上一节已介绍。
- 通过cpuid工具查看SME-MK的支持情况:
- 可以看到输出EAX为0,Hygon C86 7380不支持SME-MK
SEV
- SEV:(Secure Encrypted Virtualization)是AMD设计的机密虚拟化硬件解决方案。SEV在内存加密的基础之上,引入了安全处理器解决密钥管理的扩展性问题,支持为每个内存加密的虚机关联一个密钥。
- 相比标准的X86虚拟化硬件方案,SEV最大的不同就是可以让Guest对其本身使用的主机上物理内存进行权限控制,Guest可以决定哪些内存可以暴露给hypervisor,哪些不可以暴露给hypervisor。更进一步,作为SEV的增强,SEV-ES特性还可以让Guest决定哪些寄存器可以暴露给hypervisor,哪些不可以暴露。
Arch
- SEV整体架构示意图如下:
- 传统的虚拟化架构中有两个角色,分别是Hypervisor和Guest,Hypervisor负责了所有Guest的权限管理,可以对虚机的代码和数据进行查看和修改。具体表现为:
- Hypervisor可以访问虚机GPA对应的HPA内存内容。
- Hypervisor可以访问虚机使用的CPU寄存器内容。
- Hypervisor可以篡改虚机使用的镜像文件。
- Hypervisor可以根据需要修改启动虚机所使用的命令行参数。
- SEV架构下新增了一个角色
Guest Owner
,将Hypervisor权限中的上述部分剥离出来,赋给了新角色Guest Owner。Hypervisor的CPU计算能力仍然被使用,但管理属性被削弱。SEV架构下,可以将Hypervisor的看成是提供计算虚拟化能力的虚机管理代理角色。 - 在SEV架构下,每个机密虚机都关联了一个密钥,密钥管理由AMD Secure Processor负责;CPU与AMD Secure Processor之间基于厂商提供的SEV API实现SEV Driver,Hypervisor集成SEV Dirver后,进一步通过调用SEV API实现对机密虚拟机的生命周期管理。
- AMD硬件逻辑中为每个机密虚机都关联一个密钥,作为加密该虚机内存的密钥,这是AMD Secure Processor的内部逻辑,那么Hypervisor软件如何指定虚机关联的密钥呢?AMD将VMCB结构中的ASID字段作为了机密虚机关联的密钥ID,当执行VMRUN指令运行虚机时,硬件读取VMCB结构中的ASID字段的值,作为密钥ID。当然,AMD能够支持的密钥个数有上限,上限值可以通过
CPUID 8000_001F[ECX]
查询得到,ASID作为密钥ID,其值也不能大于该上限。同时ASID在SEV使能,SEV-ES未使能的模式下,其取值还有1个下限,下限值通过CPUID 8000_001F[EDX]
查询得到。
Interface
- 在介绍SME的章节中,我们知道可以通过
CPUID Fn8000_001F
查询硬件对SME、SEV的支持情况,SEV相关字段总结如下:
- CPUID 8000_001F_EAX[SME]: 是否支持内存加密
- CPUID 8000_001F_EAX[SEV]: 是否支持机密虚拟化
- CPUID 8000_001F_EAX[SEV-ES]: 是否支持机密虚拟化且支持集存器的加密
- CPUID 8000_001F_EBX[CbitPosition]: C-bit在页表项中的位置
- CPUID 8000_001F_EBX[PhysAddrReduction]: 内存加密牺牲的物理地址位宽
- CPUID 8000_001F_ECX[NumEncryptedGuests]: 支持的最大机密虚机个数
- CPUID 8000_001F_EDX[MinSevNoEsAsid]: 使能SEV禁用SEV-ES的模式下,ASID的最小值
- 我们再分析一下SME章节中CPUID指令查询得到的输出信息,现在我们知道了
NumEncryptedGuests
和MinSevNoEsAsid
字段的含义,它确定了使能SEV禁用SEV-ES的模式下,ASID的取值范围是[1, 15]。
SEV API
- 从上述关于SEV的介绍中,我们知道AMD Secure Processor的主要功能是实现密钥管理,这是硬件的逻辑,当硬件具备这样的能力后,它通过MMIO Registers向SEV Driver提供与AMD Secure Processor通信的方式,SEV Driver再基于MMIO Registers实现平台管理API(
Platform Management API
)和虚机管理API(Guest Management API
),供Hypervisor调用,整个架构示意图如下:
- AMD在提供SEV硬件机制的同时,也提供SEV API规范,开发者只要按照该规范实现SEV Driver并集成到Hypervisor,就可以支持SEV特性。因此SEV API才是指导开发者如何实现SEV虚拟化解决方案的标准参考文档,本章节简要介绍该规范涉及的内容。
Key Management
- TODO
Guest Policy
- TODO
Mailbox Register Protocol
- TODO
Platform Management API
- TODO
Guest Management API
- TODO