Hypercall 操作码 (hcalls)¶
概述¶
64 位 Power Book3S 平台上的虚拟化基于 PAPR 规范 [1],该规范描述了客户操作系统的运行时环境以及它应如何与 Hypervisor 交互以进行特权操作。目前有两个符合 PAPR 的 Hypervisor
IBM PowerVM (PHYP):IBM 的专有 Hypervisor,支持 AIX、IBM-i 和 Linux 作为受支持的客户机(称为逻辑分区或 LPAR)。它支持完整的 PAPR 规范。
Qemu/KVM:支持在 PPC64 Linux 主机上运行的 PPC64 Linux 客户机。虽然它只实现了 PAPR 规范的一个子集,称为 LoPAPR [2]。
在 PPC64 架构上,运行在 PAPR Hypervisor 之上的客户内核称为pSeries 客户机。 pseries 客户机在 Supervisor 模式 (HV=0) 下运行,并且每当它需要执行 Hypervisor 特权操作 [3] 或 Hypervisor 管理的其他服务时,都必须发出 Hypercall 到 Hypervisor。
因此,Hypercall (hcall) 本质上是 pseries 客户机发出的请求,要求 Hypervisor 代表客户机执行特权操作。 客户机发出带有必要输入操作数的请求。 Hypervisor 在执行特权操作后,将状态代码和输出操作数返回给客户机。
HCALL ABI¶
pseries 客户机和 PAPR Hypervisor 之间的 hcall 的 ABI 规范在 ref [2] 的第 14.5.3 节中介绍。 通过指令 HVCS 完成到 Hypervisor 上下文的切换,该指令预期 hcall 的操作码设置在 *r3* 中,并且 hcall 的任何输入参数都提供在寄存器 *r4-r12* 中。 如果必须通过内存缓冲区传递值,则存储在该缓冲区中的数据应为大端字节序。
在 Hypervisor 服务了“HVCS”指令后控制返回给客户机之后,hcall 的返回值可在 *r3* 中获得,任何输出值都会在寄存器 *r4-r12* 中返回。 同样,就像输入参数的情况一样,存储在内存缓冲区中的任何输出值都将为大端字节序。
Powerpc 架构代码提供了方便的包装器,名为 plpar_hcall_xxx,定义在架构特定的头文件 [4] 中,用于从作为 pseries 客户机运行的 Linux 内核发出 hcall。
寄存器约定¶
任何 hcall 都应遵循与“64-Bit ELF V2 ABI Specification: Power Architecture”的 2.2.1.1 节中描述的相同的寄存器约定 [5]。 下表总结了这些约定
寄存器范围 |
易失 (Y/N) |
目的 |
---|---|---|
r0 |
Y |
可选用途 |
r1 |
N |
堆栈指针 |
r2 |
N |
TOC |
r3 |
Y |
hcall 操作码/返回值 |
r4-r10 |
Y |
输入和输出值 |
r11 |
Y |
可选用途/环境指针 |
r12 |
Y |
全局入口点上的可选用途/函数入口地址 |
r13 |
N |
线程指针 |
r14-r31 |
N |
局部变量 |
LR |
Y |
链接寄存器 |
CTR |
Y |
循环计数器 |
XER |
Y |
定点异常寄存器。 |
CR0-1 |
Y |
条件寄存器字段。 |
CR2-4 |
N |
条件寄存器字段。 |
CR5-7 |
Y |
条件寄存器字段。 |
其他 |
N |
DRC & DRC 索引¶
DR1 Guest
+--+ +------------+ +---------+
| | <----> | | | User |
+--+ DRC1 | | DRC | Space |
| PAPR | Index +---------+
DR2 | Hypervisor | | |
+--+ | | <-----> | Kernel |
| | <----> | | Hcall | |
+--+ DRC2 +------------+ +---------+
PAPR Hypervisor 将共享硬件资源(如 PCI 设备、NVDIMM 等)视为 LPAR 可用的动态资源 (DR)。 当 DR 分配给 LPAR 时,PHYP 会创建一个名为动态资源连接器 (DRC) 的数据结构来管理 LPAR 访问。 LPAR 通过一个不透明的 32 位数字(称为 DRC-Index)来引用 DRC。 DRC-index 值通过设备树提供给 LPAR,它作为与 DR 关联的设备树节点中的一个属性存在。
HCALL 返回值¶
在服务了 hcall 之后,Hypervisor 在 *r3* 中设置返回值,指示 hcall 成功或失败。 如果失败,错误代码指示错误的原因。 这些代码在架构特定的头文件 [4] 中定义和记录。
在某些情况下,hcall 可能会花费很长时间,并且需要多次发出才能完全完成服务。 这些 hcall 通常会在其参数列表中接受一个不透明的值continue-token,并且返回值 H_CONTINUE 指示 Hypervisor 尚未完成对 hcall 的服务。
为了进行此类 hcall,客户机需要为初始调用设置 *continue-token == 0*,并为每个后续 hcall 使用 Hypervisor 返回的 *continue-token* 值,直到 Hypervisor 返回非 *H_CONTINUE* 返回值。
HCALL 操作码¶
以下是 PHYP 支持的 HCALL 的部分列表。 有关相应的操作码值,请查看架构特定的头文件 [4]
H_SCM_READ_METADATA
给定 NVDIMM 的 DRC 索引,从与其关联的元数据区域读取 N 个字节,在指定的偏移量处将其复制到提供的缓冲区。 元数据区域存储配置信息,例如标签信息、坏块等。 元数据区域位于 NVDIMM 存储区域的带外,因此提供了单独的访问语义。
H_SCM_WRITE_METADATA
给定 NVDIMM 的 DRC 索引,将 N 个字节写入与其关联的元数据区域,从提供的缓冲区写入到指定的偏移量处。
H_SCM_BIND_MEM
给定 NVDIMM 的 DRC-Index,在客户物理地址空间内的 targetLogicalMemoryAddress 处将连续的 SCM 块范围 (startingScmBlockIndex, startingScmBlockIndex+numScmBlocksToBind) 映射到客户机。 如果 targetLogicalMemoryAddress == 0xFFFFFFFF_FFFFFFFF,则 Hypervisor 会为客户机分配一个目标地址。 如果客户机具有指向要绑定的 SCM 块的活动 PTE 条目,则 HCALL 可能会失败。
H_SCM_UNBIND_MEM | 输入:drcIndex, startingScmLogicalMemoryAddress, numScmBlocksToUnbind | 输出:numScmBlocksUnbound | 返回值:H_Success, H_Parameter, H_P2, H_P3, H_In_Use, H_Overlap, | H_Busy, H_LongBusyOrder1mSec, H_LongBusyOrder10mSec
给定 NVDimm 的 DRC-Index,从客户物理地址空间取消映射从 startingScmLogicalMemoryAddress 开始的 numScmBlocksToUnbind SCM 块。 如果客户机具有指向要解除绑定的 SCM 块的活动 PTE 条目,则 HCALL 可能会失败。
H_SCM_QUERY_BLOCK_MEM_BINDING
给定 DRC-Index 和 SCM 块索引,返回 SCM 块映射到的客户物理地址。
H_SCM_QUERY_LOGICAL_MEM_BINDING
给定客户物理地址,返回哪个 DRC 索引和 SCM 块映射到该地址。
H_SCM_UNBIND_ALL
根据目标范围,从 LPAR 内存中取消映射属于所有 NVDIMM 的所有 SCM 块,或者属于由其 drcIndex 标识的单个 NVDIMM 的所有 SCM 块。
H_SCM_HEALTH
给定 DRC 索引,返回有关 PMEM 设备的预测性故障和整体健康状况的信息。 健康状况位图中的断言位指示 PMEM 设备的一个或多个状态(在下表中描述),并且 health-bit-valid-bitmap 指示健康状况位图中的哪些位有效。 这些位以相反的位顺序报告,例如,值 0xC400000000000000 指示位 0、1 和 5 有效。
健康状况位图标志
位 |
定义 |
---|---|
00 |
PMEM 设备无法持久保存内存内容。 如果系统断电,则不会保存任何内容。 |
01 |
PMEM 设备无法持久保存内存内容。 在断电时未成功保存内容,或者在开机时未正确恢复内容。 |
02 |
PMEM 设备内容从先前的 IPL 持久保存。 成功恢复了上次启动的数据。 |
03 |
PMEM 设备内容未从先前的 IPL 持久保存。 没有要从上次启动恢复的数据。 |
04 |
PMEM 设备内存寿命剩余量非常低 |
05 |
由于故障,PMEM 设备将在下次 IPL 时被隔离 |
06 |
由于当前平台健康状况,PMEM 设备内容无法持久保存。 硬件故障可能会阻止保存或恢复数据。 |
07 |
PMEM 设备在某些情况下无法持久保存内存内容 |
08 |
PMEM 设备已加密 |
09 |
PMEM 设备已成功完成请求的擦除或安全擦除过程。 |
10:63 |
保留/未使用 |
H_SCM_PERFORMANCE_STATS
给定 DRC 索引,收集 NVDIMM 的性能统计信息并将它们复制到 resultBuffer。
H_SCM_FLUSH
给定 DRC 索引,将数据刷新到后端 NVDIMM 设备。
当刷新花费更长时间时,hcall 返回 H_BUSY,并且需要多次发出 hcall 才能完全完成服务。 输出中的 continue-token 将在后续的 hcall 的参数列表中传递给 Hypervisor,直到完全服务该 hcall,此时 Hypervisor 返回 H_SUCCESS 或其他错误。
H_HTM
H_HTM 支持硬件跟踪宏 (HTM) 功能及其数据的设置、配置、控制和转储。 HTM 缓冲区存储诸如核心指令、核心 LLAT 和嵌套之类的函数的跟踪数据。