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

輸入:drcIndex, offset, buffer-address, numBytesToRead
輸出:numBytesRead
返回值:H_Success, H_Parameter, H_P2, H_P3, H_Hardware

給定 NVDIMM 的 DRC 索引,從與其關聯的元資料區域讀取 N 個位元組,在指定的偏移量處將其複製到提供的緩衝區。 元資料區域儲存配置資訊,例如標籤資訊、壞塊等。 元資料區域位於 NVDIMM 儲存區域的帶外,因此提供了單獨的訪問語義。

H_SCM_WRITE_METADATA

輸入:drcIndex, offset, data, numBytesToWrite
輸出:None
返回值:H_Success, H_Parameter, H_P2, H_P4, H_Hardware

給定 NVDIMM 的 DRC 索引,將 N 個位元組寫入與其關聯的元資料區域,從提供的緩衝區寫入到指定的偏移量處。

H_SCM_BIND_MEM

輸入:drcIndex, startingScmBlockIndex, numScmBlocksToBind,
targetLogicalMemoryAddress, continue-token
輸出:continue-token, targetLogicalMemoryAddress, numScmBlocksToBound
返回值:H_Success, H_Parameter, H_P2, H_P3, H_P4, H_Overlap,
H_Too_Big, H_P5, H_Busy

給定 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

輸入:drcIndex, scmBlockIndex
輸出:Guest-Physical-Address
返回值:H_Success, H_Parameter, H_P2, H_NotFound

給定 DRC-Index 和 SCM 塊索引,返回 SCM 塊對映到的客戶物理地址。

H_SCM_QUERY_LOGICAL_MEM_BINDING

輸入:Guest-Physical-Address
輸出:drcIndex, scmBlockIndex
返回值:H_Success, H_Parameter, H_P2, H_NotFound

給定客戶物理地址,返回哪個 DRC 索引和 SCM 塊對映到該地址。

H_SCM_UNBIND_ALL

輸入:scmTargetScope, drcIndex
輸出:None
返回值:H_Success, H_Parameter, H_P2, H_P3, H_In_Use, H_Busy,
H_LongBusyOrder1mSec, H_LongBusyOrder10mSec

根據目標範圍,從 LPAR 記憶體中取消對映屬於所有 NVDIMM 的所有 SCM 塊,或者屬於由其 drcIndex 標識的單個 NVDIMM 的所有 SCM 塊。

H_SCM_HEALTH

輸入:drcIndex
輸出:health-bitmap (r4), health-bit-valid-bitmap (r5)
返回值:H_Success, H_Parameter, H_Hardware

給定 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

輸入:drcIndex, resultBuffer Addr
輸出:None
返回值:H_Success, H_Parameter, H_Unsupported, H_Hardware, H_Authority, H_Privilege

給定 DRC 索引,收集 NVDIMM 的效能統計資訊並將它們複製到 resultBuffer。

H_SCM_FLUSH

輸入:drcIndex, continue-token
輸出:continue-token
返回值:H_SUCCESS, H_Parameter, H_P2, H_BUSY

給定 DRC 索引,將資料重新整理到後端 NVDIMM 裝置。

當重新整理花費更長時間時,hcall 返回 H_BUSY,並且需要多次發出 hcall 才能完全完成服務。 輸出中的 continue-token 將在後續的 hcall 的引數列表中傳遞給 Hypervisor,直到完全服務該 hcall,此時 Hypervisor 返回 H_SUCCESS 或其他錯誤。

H_HTM

輸入:flags, target, operation (op), op-param1, op-param2, op-param3
輸出:dumphtmbufferdata
返回值:H_Success,H_Busy,H_LongBusyOrder,H_Partial,H_Parameter, H_P2,H_P3,H_P4,H_P5,H_P6,H_State,H_Not_Available,H_Authority

H_HTM 支援硬體跟蹤宏 (HTM) 功能及其資料的設定、配置、控制和轉儲。 HTM 緩衝區儲存諸如核心指令、核心 LLAT 和巢狀之類的函式的跟蹤資料。

參考文獻