KVM(基於核心的虛擬機器)API 權威文件¶
1. 概述¶
KVM API 圍繞不同型別的檔案描述符和可以向這些檔案描述符發出的 ioctl 展開。初始的 open(“/dev/kvm”) 獲取 KVM 子系統的控制代碼;此控制代碼可用於發出系統 ioctl。在此控制代碼上執行 KVM_CREATE_VM ioctl 將建立一個 VM 檔案描述符,該描述符可用於發出 VM ioctl。在 VM fd 上執行 KVM_CREATE_VCPU 或 KVM_CREATE_DEVICE ioctl 將建立一個虛擬 CPU 或裝置,並返回一個指向新資源的檔案描述符。
換句話說,KVM API 是一組 ioctl,它們被髮出到不同型別的檔案描述符,以控制虛擬機器的各個方面。根據接受它們的檔案描述符,ioctl 屬於以下類別
系統 ioctl:這些查詢和設定影響整個 KVM 子系統的全域性屬性。此外,系統 ioctl 用於建立虛擬機器。
VM ioctl:這些查詢和設定影響整個虛擬機器的屬性,例如記憶體佈局。此外,VM ioctl 用於建立虛擬 CPU (vCPU) 和裝置。
VM ioctl 必須從用於建立 VM 的同一程序(地址空間)發出。
vCPU ioctl:這些查詢和設定控制單個虛擬 CPU 執行的屬性。
vCPU ioctl 應從用於建立 vCPU 的同一執行緒發出,非同步 vCPU ioctl 在文件中標記為非同步的情況除外。否則,切換執行緒後的第一個 ioctl 可能會受到效能影響。
裝置 ioctl:這些查詢和設定控制單個裝置執行的屬性。
裝置 ioctl 必須從用於建立 VM 的同一程序(地址空間)發出。
雖然大多數 ioctl 都是特定於一種檔案描述符,但在某些情況下,同一 ioctl 可以屬於多個類別。
KVM API 隨著時間的推移而增長。因此,KVM 定義了許多形式為 KVM_CAP_* 的常量,每個常量對應於一個或多個 ioctl 提供的一組功能。可以使用 KVM_CHECK_EXTENSION 檢查這些“功能”的可用性。某些功能還需要在需要其功能的 VM 或 VCPU 上啟用(請參閱 6. 可以在 vCPU 上啟用的功能 和 7. 可以在 VM 上啟用的功能)。
2. 限制¶
通常,可以透過 fork() 和 unix 域套接字的 SCM_RIGHTS 工具在程序之間遷移檔案描述符。KVM 明確不支援這些技巧。雖然它們不會對主機造成損害,但 API 不保證它們的實際行為。有關 KVM 支援的 ioctl 使用模型的詳細資訊,請參閱“概述”。
重要的是要注意,雖然 VM ioctl 只能從建立 VM 的程序發出,但 VM 的生命週期與其檔案描述符相關聯,而不是與其建立者(程序)相關聯。換句話說,VM 及其資源,*包括關聯的地址空間*,在釋放對 VM 檔案描述符的最後一個引用之前不會被釋放。例如,如果在 ioctl(KVM_CREATE_VM) 之後發出 fork(),則在父程序(原始程序)及其子程序都釋放了它們對 VM 檔案描述符的引用之前,VM 不會被釋放。
由於 VM 的資源在釋放對其檔案描述符的最後一個引用之前不會被釋放,因此強烈建議不要透過 fork()、dup() 等方式建立對 VM 的額外引用,而沒有仔細考慮,並且可能產生不希望的副作用,例如,當 VM 關閉時,VM 的程序分配的記憶體可能不會被釋放/未記賬。
3. 擴充套件¶
從 Linux 2.6.22 開始,KVM ABI 已穩定:不允許向後不相容的更改。但是,存在一個擴充套件工具,允許查詢和使用向後相容的 API 擴充套件。
擴充套件機制不是基於 Linux 版本號。相反,KVM 定義了擴充套件識別符號和一個工具來查詢特定擴充套件識別符號是否可用。如果是,則有一組 ioctl 可供應用程式使用。
4. API 描述¶
本節介紹可用於控制 KVM 客戶機的 ioctl。對於每個 ioctl,都提供了以下資訊以及描述
- 功能
哪個 KVM 擴充套件提供了此 ioctl。可以是“basic”,這意味著它將由任何支援 API 版本 12 的核心提供(請參閱 KVM_GET_API_VERSION),或者是一個可以使用 KVM_CHECK_EXTENSION 檢查的 KVM_CAP_xyz 常量。
- 架構
哪些指令集架構提供了此 ioctl。x86 包括 i386 和 x86_64。
- 型別
系統、vm 或 vcpu。
- 引數
ioctl 接受哪些引數。
- 返回值
返回值。未詳細說明常規錯誤號(EBADF、ENOMEM、EINVAL),但詳細說明了具有特定含義的錯誤。
4.1 KVM_GET_API_VERSION¶
- 功能:
基本
- 架構:
全部
- 型別:
系統 ioctl
- 引數:
無
- 返回值:
常量 KVM_API_VERSION (=12)
這會將 API 版本標識為穩定的 KVM API。預計此數字不會更改。但是,Linux 2.6.20 和 2.6.21 報告了早期版本;這些版本未記錄且不受支援。如果 KVM_GET_API_VERSION 返回的值不是 12,應用程式應拒絕執行。如果此檢查透過,所有描述為“basic”的 ioctl 都可用。
4.2 KVM_CREATE_VM¶
- 功能:
基本
- 架構:
全部
- 型別:
系統 ioctl
- 引數:
機器型別識別符號 (KVM_VM_*)
- 返回值:
可用於控制新虛擬機器的 VM fd。
新 VM 沒有虛擬 CPU 也沒有記憶體。您可能想要使用 0 作為機器型別。
X86:¶
可以透過 KVM_CAP_VM_TYPES 查詢支援的 X86 VM 型別。
S390:¶
為了在 S390 上建立使用者控制的虛擬機器,請檢查 KVM_CAP_S390_UCONTROL 並使用標誌 KVM_VM_S390_UCONTROL 作為特權使用者 (CAP_SYS_ADMIN)。
MIPS:¶
要在 MIPS (VZ ASE) 上使用硬體輔助虛擬化,而不是預設的陷阱和模擬實現(它更改虛擬記憶體佈局以適應使用者模式),請檢查 KVM_CAP_MIPS_VZ 並使用標誌 KVM_VM_MIPS_VZ。
ARM64:¶
在 arm64 上,VM 的物理地址大小(IPA 大小限制)預設限制為 40 位。如果主機支援擴充套件 KVM_CAP_ARM_VM_IPA_SIZE,則可以配置該限制。如果支援,請使用 KVM_VM_TYPE_ARM_IPA_SIZE(IPA_Bits) 在機器型別識別符號中設定大小,其中 IPA_Bits 是 VM 使用的任何物理地址的最大寬度。IPA_Bits 編碼在機器型別識別符號的位 [7-0] 中。
例如,要配置客戶機以使用 48 位物理地址大小
vm_fd = ioctl(dev_fd, KVM_CREATE_VM, KVM_VM_TYPE_ARM_IPA_SIZE(48));
請求的大小 (IPA_Bits) 必須是
0
暗示預設大小,40 位(為了向後相容)
N
暗示 N 位,其中 N 是一個正整數,使得 32 <= N <= Host_IPA_Limit
Host_IPA_Limit 是主機上 IPA_Bits 的最大可能值,並且取決於 CPU 功能和核心配置。可以使用執行時 KVM_CHECK_EXTENSION ioctl() 的 KVM_CAP_ARM_VM_IPA_SIZE 檢索該限制。
如果主機不支援請求的 IPA 大小(無論是隱式還是顯式),則 VM 的建立將失敗。
請注意,配置 IPA 大小不會影響客戶機 CPU 在 ID_AA64MMFR0_EL1[PARange] 中公開的功能。它只會影響由 stage2 級別(客戶機物理地址到主機物理地址轉換)轉換的地址大小。
4.3 KVM_GET_MSR_INDEX_LIST, KVM_GET_MSR_FEATURE_INDEX_LIST¶
- 功能:
基本,KVM_GET_MSR_FEATURE_INDEX_LIST 的 KVM_CAP_GET_MSR_FEATURES
- 架構:
x86
- 型別:
系統 ioctl
- 引數:
struct kvm_msr_list (輸入/輸出)
- 返回值:
成功時為 0;出錯時為 -1
錯誤
EFAULT
無法讀取或寫入 msr 索引列表
E2BIG
msr 索引列表太大,無法放入使用者指定的陣列中。
struct kvm_msr_list {
__u32 nmsrs; /* number of msrs in entries */
__u32 indices[0];
};
使用者在 nmsrs 中填寫索引陣列的大小,作為回報,kvm 調整 nmsrs 以反映 msr 的實際數量,並在索引陣列中填寫它們的編號。
KVM_GET_MSR_INDEX_LIST 返回支援的客戶機 msr。該列表因 KVM 版本和主機處理器而異,但在其他方面不會更改。
注意:如果 kvm 指示支援 MCE (KVM_CAP_MCE),則 MCE bank MSR 不會在 MSR 列表中返回,因為不同的 vCPU 可以具有不同數量的 bank,如透過 KVM_X86_SETUP_MCE ioctl 設定。
KVM_GET_MSR_FEATURE_INDEX_LIST 返回可以傳遞給 KVM_GET_MSRS 系統 ioctl 的 MSR 列表。這使使用者空間可以探測透過 MSR 公開的主機功能和處理器特性(例如,VMX 功能)。此列表也因 kvm 版本和主機處理器而異,但在其他方面不會更改。
4.4 KVM_CHECK_EXTENSION¶
- 功能:
基本,vm ioctl 的 KVM_CAP_CHECK_EXTENSION_VM
- 架構:
全部
- 型別:
系統 ioctl,vm ioctl
- 引數:
擴充套件識別符號 (KVM_CAP_*)
- 返回值:
如果不支援則為 0;如果支援則為 1(或某個其他正整數)
API 允許應用程式查詢核心 KVM API 的擴充套件。使用者空間傳遞一個擴充套件識別符號(一個整數),並接收一個描述擴充套件可用性的整數。通常 0 表示否,1 表示是,但某些擴充套件可能會在整數返回值中報告其他資訊。
根據它們的初始化,不同的 VM 可能具有不同的功能。因此,鼓勵使用 vm ioctl 來查詢功能(在 vm fd 上使用 KVM_CAP_CHECK_EXTENSION_VM 可用)
4.5 KVM_GET_VCPU_MMAP_SIZE¶
- 功能:
基本
- 架構:
全部
- 型別:
系統 ioctl
- 引數:
無
- 返回值:
vcpu mmap 區域的大小,以位元組為單位
KVM_RUN ioctl(cf.)透過共享記憶體區域與使用者空間通訊。此 ioctl 返回該區域的大小。有關詳細資訊,請參閱 KVM_RUN 文件。
除了 KVM_RUN 通訊區域的大小之外,還可以 mmap-ed VCPU 檔案描述符的其他區域,包括
如果 KVM_CAP_COALESCED_MMIO 可用,則為 KVM_COALESCED_MMIO_PAGE_OFFSET * PAGE_SIZE 處的頁面;由於歷史原因,此頁面包含在 KVM_GET_VCPU_MMAP_SIZE 的結果中。KVM_CAP_COALESCED_MMIO 尚未記錄。
如果 KVM_CAP_DIRTY_LOG_RING 可用,則為 KVM_DIRTY_LOG_PAGE_OFFSET * PAGE_SIZE 處的多個頁面。有關 KVM_CAP_DIRTY_LOG_RING 的更多資訊,請參閱 7. 可以在 VM 上啟用的功能。
4.7 KVM_CREATE_VCPU¶
- 功能:
基本
- 架構:
全部
- 型別:
vm ioctl
- 引數:
vcpu id(x86 上的 apic id)
- 返回值:
成功時為 vcpu fd,出錯時為 -1
此 API 將 vCPU 新增到虛擬機器。最多可以新增 max_vcpus。vcpu id 是一個介於 [0, max_vcpu_id) 範圍內的整數。
可以使用執行時 KVM_CHECK_EXTENSION ioctl() 的 KVM_CAP_NR_VCPUS 檢索建議的 max_vcpus 值。可以使用執行時 KVM_CHECK_EXTENSION ioctl() 的 KVM_CAP_MAX_VCPUS 檢索 max_vcpus 的最大可能值。
如果 KVM_CAP_NR_VCPUS 不存在,您應該假設 max_vcpus 最多為 4 個 CPU。如果 KVM_CAP_MAX_VCPUS 不存在,您應該假設 max_vcpus 與 KVM_CAP_NR_VCPUS 返回的值相同。
可以使用執行時 KVM_CHECK_EXTENSION ioctl() 的 KVM_CAP_MAX_VCPU_ID 檢索 max_vcpu_id 的最大可能值。
如果 KVM_CAP_MAX_VCPU_ID 不存在,您應該假設 max_vcpu_id 與 KVM_CAP_MAX_VCPUS 返回的值相同。
在使用 book3s_hv 模式的 powerpc 上,vCPU 對映到一個或多個虛擬 CPU 核心中的虛擬執行緒。(這是因為硬體要求 CPU 核心中的所有硬體執行緒都位於同一分割槽中。)KVM_CAP_PPC_SMT 功能指示每個虛擬核心 (vcore) 的 vCPU 數量。vcore id 透過將 vCPU id 除以每個 vcore 的 vCPU 數量獲得。給定 vcore 中的 vCPU 將始終位於彼此相同的物理核心中(儘管這可能不時地是不同的物理核心)。使用者空間可以透過分配 vCPU id 來控制客戶機的執行緒 (SMT) 模式。例如,如果使用者空間想要單執行緒客戶機 vCPU,它應使所有 vCPU id 都是每個 vcore 的 vCPU 數量的倍數。
對於已使用 S390 使用者控制的虛擬機器建立的虛擬 CPU,可以在頁面偏移量 KVM_S390_SIE_PAGE_OFFSET 處對生成的 vCPU fd 進行記憶體對映,以便獲得虛擬 CPU 硬體控制塊的記憶體對映。
4.8 KVM_GET_DIRTY_LOG¶
- 功能:
基本
- 架構:
全部
- 型別:
vm ioctl
- 引數:
struct kvm_dirty_log(輸入/輸出)
- 返回值:
成功時為 0,出錯時為 -1
/* for KVM_GET_DIRTY_LOG */
struct kvm_dirty_log {
__u32 slot;
__u32 padding;
union {
void __user *dirty_bitmap; /* one bit per page */
__u64 padding;
};
};
給定一個記憶體槽,返回一個位圖,其中包含自上次呼叫此 ioctl 以來已修改的任何頁面。位 0 是記憶體槽中的第一頁。確保整個結構都已清除以避免填充問題。
如果 KVM_CAP_MULTI_ADDRESS_SPACE 可用,則槽欄位的位 16-31 指定要為其返回髒點陣圖的地址空間。有關槽欄位用法的詳細資訊,請參閱 KVM_SET_USER_MEMORY_REGION。
在 ioctl 返回之前,將清除髒點陣圖中的位,除非啟用了 KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2。有關更多資訊,請參閱該功能的描述。
請注意,如果配置了 Xen shared_info 頁面,則應始終假定它是髒的。KVM 不會明確地將其標記為髒。
4.10 KVM_RUN¶
- 功能:
基本
- 架構:
全部
- 型別:
vcpu ioctl
- 引數:
無
- 返回值:
成功時為 0,出錯時為 -1
錯誤
EINTR
未遮蔽的訊號正在掛起
ENOEXEC
vcpu 尚未初始化,或者客戶機嘗試從裝置記憶體執行指令 (arm64)
ENOSYS
在沒有 syndrome 資訊且未啟用 KVM_CAP_ARM_NISV_TO_USER 的情況下,資料中止在記憶體槽之外 (arm64)
EPERM
SVE 功能集已設定但未最終確定 (arm64)
此 ioctl 用於執行客戶機虛擬 CPU。雖然沒有顯式引數,但有一個隱式引數塊可以透過在偏移量 0 處 mmap() vcpu fd 來獲得,其大小由 KVM_GET_VCPU_MMAP_SIZE 給出。該引數塊的格式為“struct kvm_run”(參見下文)。
4.11 KVM_GET_REGS¶
- 功能:
基本
- 架構:
除了 arm64 之外的所有
- 型別:
vcpu ioctl
- 引數:
struct kvm_regs(輸出)
- 返回值:
成功時為 0,出錯時為 -1
從 vCPU 讀取通用暫存器。
/* x86 */
struct kvm_regs {
/* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
__u64 rax, rbx, rcx, rdx;
__u64 rsi, rdi, rsp, rbp;
__u64 r8, r9, r10, r11;
__u64 r12, r13, r14, r15;
__u64 rip, rflags;
};
/* mips */
struct kvm_regs {
/* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
__u64 gpr[32];
__u64 hi;
__u64 lo;
__u64 pc;
};
/* LoongArch */
struct kvm_regs {
/* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
unsigned long gpr[32];
unsigned long pc;
};
4.12 KVM_SET_REGS¶
- 功能:
基本
- 架構:
除了 arm64 之外的所有
- 型別:
vcpu ioctl
- 引數:
struct kvm_regs(輸入)
- 返回值:
成功時為 0,出錯時為 -1
將通用暫存器寫入 vCPU。
有關資料結構,請參閱 KVM_GET_REGS。
4.13 KVM_GET_SREGS¶
- 功能:
基本
- 架構:
x86、ppc
- 型別:
vcpu ioctl
- 引數:
struct kvm_sregs(輸出)
- 返回值:
成功時為 0,出錯時為 -1
從 vCPU 讀取特殊暫存器。
/* x86 */
struct kvm_sregs {
struct kvm_segment cs, ds, es, fs, gs, ss;
struct kvm_segment tr, ldt;
struct kvm_dtable gdt, idt;
__u64 cr0, cr2, cr3, cr4, cr8;
__u64 efer;
__u64 apic_base;
__u64 interrupt_bitmap[(KVM_NR_INTERRUPTS + 63) / 64];
};
/* ppc -- see arch/powerpc/include/uapi/asm/kvm.h */
interrupt_bitmap 是掛起的外部中斷的點陣圖。最多可以設定一位。此中斷已被 APIC 確認,但尚未注入到 CPU 核心中。
4.14 KVM_SET_SREGS¶
- 功能:
基本
- 架構:
x86、ppc
- 型別:
vcpu ioctl
- 引數:
struct kvm_sregs(輸入)
- 返回值:
成功時為 0,出錯時為 -1
將特殊暫存器寫入 vCPU。有關資料結構,請參閱 KVM_GET_SREGS。
4.15 KVM_TRANSLATE¶
- 功能:
基本
- 架構:
x86
- 型別:
vcpu ioctl
- 引數:
struct kvm_translation(輸入/輸出)
- 返回值:
成功時為 0,出錯時為 -1
根據 vCPU 當前的地址轉換模式轉換虛擬地址。
struct kvm_translation {
/* in */
__u64 linear_address;
/* out */
__u64 physical_address;
__u8 valid;
__u8 writeable;
__u8 usermode;
__u8 pad[5];
};
4.16 KVM_INTERRUPT¶
- 功能:
基本
- 架構:
x86、ppc、mips、riscv、loongarch
- 型別:
vcpu ioctl
- 引數:
struct kvm_interrupt(輸入)
- 返回值:
成功時為 0,失敗時為負數。
將硬體中斷向量排隊以進行注入。
/* for KVM_INTERRUPT */
struct kvm_interrupt {
/* in */
__u32 irq;
};
X86:¶
- 返回值:
0
成功時,
-EEXIST
如果已有一箇中斷排隊
-EINVAL
irq 編號無效
-ENXIO
如果 PIC 在核心中
-EFAULT
如果指標無效
注意“irq”是中斷向量,而不是中斷引腳或線路。如果未使用核心內 PIC,則此 ioctl 非常有用。
PPC:¶
將外部中斷排隊以進行注入。此 ioctl 過載了 3 個不同的 irq 值
KVM_INTERRUPT_SET
一旦客戶機準備好接收中斷,這將注入一個邊緣型別外部中斷到客戶機中。注入後,中斷完成。
KVM_INTERRUPT_UNSET
這將取消設定任何掛起的中斷。
僅在使用 KVM_CAP_PPC_UNSET_IRQ 的情況下可用。
KVM_INTERRUPT_SET_LEVEL
這將注入一個級別型別的外部中斷到客戶機上下文中。中斷保持掛起狀態,直到觸發具有 KVM_INTERRUPT_UNSET 的特定 ioctl。
僅在使用 KVM_CAP_PPC_IRQ_LEVEL 的情況下可用。
請注意,“irq”的任何值(上述值除外)都無效,並且會導致意外行為。
這是一個非同步 vcpu ioctl,可以從任何執行緒呼叫。
MIPS:¶
將外部中斷排隊以注入到虛擬 CPU 中。負中斷編號將中斷出隊。
這是一個非同步 vcpu ioctl,可以從任何執行緒呼叫。
RISC-V:¶
將外部中斷排隊以注入到虛擬 CPU 中。此 ioctl 過載了 2 個不同的 irq 值
KVM_INTERRUPT_SET
這為虛擬 CPU 設定外部中斷,並且它將在準備好後接收該中斷。
KVM_INTERRUPT_UNSET
這會清除虛擬 CPU 的掛起外部中斷。
這是一個非同步 vcpu ioctl,可以從任何執行緒呼叫。
LOONGARCH:¶
將外部中斷排隊以注入到虛擬 CPU 中。負中斷編號將中斷出隊。
這是一個非同步 vcpu ioctl,可以從任何執行緒呼叫。
4.18 KVM_GET_MSRS¶
- 功能:
基本 (vcpu),KVM_CAP_GET_MSR_FEATURES(系統)
- 架構:
x86
- 型別:
系統 ioctl,vcpu ioctl
- 引數:
struct kvm_msrs(輸入/輸出)
- 返回值:
成功返回的 msr 數量;出錯時為 -1
當用作系統 ioctl 時:讀取 VM 可用的基於 MSR 的功能的值。這類似於 KVM_GET_SUPPORTED_CPUID,但它返回 MSR 索引和值。可以使用系統 ioctl 中的 KVM_GET_MSR_FEATURE_INDEX_LIST 獲取基於 MSR 的功能的列表。
當用作 vcpu ioctl 時:從 vcpu 讀取特定於模型的暫存器。可以使用系統 ioctl 中的 KVM_GET_MSR_INDEX_LIST 獲取支援的 msr 索引。
struct kvm_msrs {
__u32 nmsrs; /* number of msrs in entries */
__u32 pad;
struct kvm_msr_entry entries[0];
};
struct kvm_msr_entry {
__u32 index;
__u32 reserved;
__u64 data;
};
應用程式程式碼應設定“nmsrs”成員(指示條目陣列的大小)和每個陣列條目的“index”成員。kvm 將填寫“data”成員。
4.19 KVM_SET_MSRS¶
- 功能:
基本
- 架構:
x86
- 型別:
vcpu ioctl
- 引數:
struct kvm_msrs(輸入)
- 返回值:
成功設定的 msr 數量(見下文),出錯時為 -1
將特定於模型的暫存器寫入 vcpu。有關資料結構,請參閱 KVM_GET_MSRS。
應用程式程式碼應設定“nmsrs”成員(指示條目陣列的大小)和每個陣列條目的“index”和“data”成員。
它嘗試逐個設定陣列 entries[] 中的 MSR。如果設定 MSR 失敗,例如,由於設定了保留位,或者 KVM 不支援/模擬該 MSR,等等,它將停止處理 MSR 列表,並返回已成功設定的 MSR 的數量。
4.20 KVM_SET_CPUID¶
- 功能:
基本
- 架構:
x86
- 型別:
vcpu ioctl
- 引數:
struct kvm_cpuid (輸入)
- 返回值:
成功時為 0,出錯時為 -1
定義 vcpu 對 cpuid 指令的響應。如果可用,應用程式應使用 KVM_SET_CPUID2 ioctl。
- 買者自負
如果此 IOCTL 失敗,KVM 不保證先前的有效 CPUID 配置(如果存在)未損壞。使用者空間可以透過 KVM_GET_CPUID2 獲取結果 CPUID 配置的副本。
在 KVM_RUN 之後使用 KVM_SET_CPUID{,2},即在執行 guest 之後更改 guest vCPU 模型,可能會導致 guest 不穩定。
使用異構 CPUID 配置(模 APIC ID、拓撲等)可能會導致 guest 不穩定。
struct kvm_cpuid_entry {
__u32 function;
__u32 eax;
__u32 ebx;
__u32 ecx;
__u32 edx;
__u32 padding;
};
/* for KVM_SET_CPUID */
struct kvm_cpuid {
__u32 nent;
__u32 padding;
struct kvm_cpuid_entry entries[0];
};
4.21 KVM_SET_SIGNAL_MASK¶
- 功能:
基本
- 架構:
全部
- 型別:
vcpu ioctl
- 引數:
struct kvm_signal_mask (輸入)
- 返回值:
成功時為 0,出錯時為 -1
定義在 KVM_RUN 執行期間阻止哪些訊號。此訊號掩碼暫時覆蓋執行緒的訊號掩碼。接收到的任何未被阻止的訊號(除了 SIGKILL 和 SIGSTOP,它們保留其傳統行為)將導致 KVM_RUN 返回 -EINTR。
請注意,只有當訊號未被原始訊號掩碼阻止時,才會傳遞該訊號。
/* for KVM_SET_SIGNAL_MASK */
struct kvm_signal_mask {
__u32 len;
__u8 sigset[0];
};
4.22 KVM_GET_FPU¶
- 功能:
基本
- 架構:
x86, loongarch
- 型別:
vcpu ioctl
- 引數:
struct kvm_fpu (輸出)
- 返回值:
成功時為 0,出錯時為 -1
從 vcpu 讀取浮點狀態。
/* x86: for KVM_GET_FPU and KVM_SET_FPU */
struct kvm_fpu {
__u8 fpr[8][16];
__u16 fcw;
__u16 fsw;
__u8 ftwx; /* in fxsave format */
__u8 pad1;
__u16 last_opcode;
__u64 last_ip;
__u64 last_dp;
__u8 xmm[16][16];
__u32 mxcsr;
__u32 pad2;
};
/* LoongArch: for KVM_GET_FPU and KVM_SET_FPU */
struct kvm_fpu {
__u32 fcsr;
__u64 fcc;
struct kvm_fpureg {
__u64 val64[4];
}fpr[32];
};
4.23 KVM_SET_FPU¶
- 功能:
基本
- 架構:
x86, loongarch
- 型別:
vcpu ioctl
- 引數:
struct kvm_fpu (輸入)
- 返回值:
成功時為 0,出錯時為 -1
將浮點狀態寫入 vcpu。
/* x86: for KVM_GET_FPU and KVM_SET_FPU */
struct kvm_fpu {
__u8 fpr[8][16];
__u16 fcw;
__u16 fsw;
__u8 ftwx; /* in fxsave format */
__u8 pad1;
__u16 last_opcode;
__u64 last_ip;
__u64 last_dp;
__u8 xmm[16][16];
__u32 mxcsr;
__u32 pad2;
};
/* LoongArch: for KVM_GET_FPU and KVM_SET_FPU */
struct kvm_fpu {
__u32 fcsr;
__u64 fcc;
struct kvm_fpureg {
__u64 val64[4];
}fpr[32];
};
4.24 KVM_CREATE_IRQCHIP¶
- 功能:
KVM_CAP_IRQCHIP, KVM_CAP_S390_IRQCHIP (s390)
- 架構:
x86, arm64, s390
- 型別:
vm ioctl
- 引數:
無
- 返回值:
成功時為 0,出錯時為 -1
在核心中建立一箇中斷控制器模型。在 x86 上,建立一個虛擬 ioapic,一個虛擬 PIC(兩個 PIC,巢狀),並設定未來的 vcpu 以具有本地 APIC。GSI 0-15 的 IRQ 路由設定為 PIC 和 IOAPIC;GSI 16-23 僅轉到 IOAPIC。在 arm64 上,建立一個 GICv2。任何其他 GIC 版本都需要使用 KVM_CREATE_DEVICE,它也支援建立 GICv2。對於 GICv2,首選使用 KVM_CREATE_DEVICE 而不是 KVM_CREATE_IRQCHIP。在 s390 上,建立一個虛擬的 irq 路由表。
請注意,在 s390 上,需要先啟用 KVM_CAP_S390_IRQCHIP vm 功能,然後才能使用 KVM_CREATE_IRQCHIP。
4.25 KVM_IRQ_LINE¶
- 功能:
KVM_CAP_IRQCHIP
- 架構:
x86, arm64
- 型別:
vm ioctl
- 引數:
struct kvm_irq_level
- 返回值:
成功時為 0,出錯時為 -1
設定 GSI 輸入到核心中的中斷控制器模型的級別。在某些架構上,需要先前使用 KVM_CREATE_IRQCHIP 建立中斷控制器模型。請注意,邊沿觸發的中斷需要將級別設定為 1,然後再設定為 0。
在真實的硬體上,中斷引腳可以是低電平有效或高電平有效。這對於 struct kvm_irq_level 的 level 欄位無關緊要:1 始終表示有效(斷言),0 表示無效(解除斷言)。
x86 允許作業系統為電平觸發的中斷程式設計中斷極性(低電平有效/高電平有效),並且 KVM 過去考慮了極性。但是,由於處理低電平有效中斷時的位元腐爛,上述約定現在在 x86 上也有效。這由 KVM_CAP_X86_IOAPIC_POLARITY_IGNORED 訊號表示。除非存在此功能(或者除非它不使用核心 irqchip),否則使用者空間不應將中斷呈現給 guest 作為低電平有效。
arm64 可以在 CPU 級別或核心 irqchip (GIC) 級別發出中斷訊號,對於核心 irqchip,可以告訴 GIC 使用為特定 cpu 指定的 PPI。irq 欄位的解釋如下
bits: | 31 ... 28 | 27 ... 24 | 23 ... 16 | 15 ... 0 |
field: | vcpu2_index | irq_type | vcpu_index | irq_id |
irq_type 欄位具有以下值
- KVM_ARM_IRQ_TYPE_CPU
核心外 GIC:irq_id 0 是 IRQ,irq_id 1 是 FIQ
- KVM_ARM_IRQ_TYPE_SPI
核心內 GIC:SPI,irq_id 在 32 到 1019 之間(包括)(vcpu_index 欄位被忽略)
- KVM_ARM_IRQ_TYPE_PPI
核心內 GIC:PPI,irq_id 在 16 到 31 之間(包括)
(因此,irq_id 欄位與 ARM GIC 規範中的 IRQ ID 非常吻合)
在這兩種情況下,level 用於斷言/解除斷言線路。
當支援 KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 時,目標 vcpu 被標識為 (256 * vcpu2_index + vcpu_index)。否則,vcpu2_index 必須為零。
請注意,在 arm64 上,KVM_CAP_IRQCHIP 功能僅調節核心 irqchip 的中斷注入。KVM_IRQ_LINE 始終可用於使用者空間中斷控制器。
struct kvm_irq_level {
union {
__u32 irq; /* GSI */
__s32 status; /* not used for KVM_IRQ_LEVEL */
};
__u32 level; /* 0 or 1 */
};
4.26 KVM_GET_IRQCHIP¶
- 功能:
KVM_CAP_IRQCHIP
- 架構:
x86
- 型別:
vm ioctl
- 引數:
struct kvm_irqchip (輸入/輸出)
- 返回值:
成功時為 0,出錯時為 -1
將使用 KVM_CREATE_IRQCHIP 建立的核心中斷控制器的狀態讀取到呼叫者提供的緩衝區中。
struct kvm_irqchip {
__u32 chip_id; /* 0 = PIC1, 1 = PIC2, 2 = IOAPIC */
__u32 pad;
union {
char dummy[512]; /* reserving space */
struct kvm_pic_state pic;
struct kvm_ioapic_state ioapic;
} chip;
};
4.27 KVM_SET_IRQCHIP¶
- 功能:
KVM_CAP_IRQCHIP
- 架構:
x86
- 型別:
vm ioctl
- 引數:
struct kvm_irqchip (輸入)
- 返回值:
成功時為 0,出錯時為 -1
從呼叫者提供的緩衝區設定使用 KVM_CREATE_IRQCHIP 建立的核心中斷控制器的狀態。
struct kvm_irqchip {
__u32 chip_id; /* 0 = PIC1, 1 = PIC2, 2 = IOAPIC */
__u32 pad;
union {
char dummy[512]; /* reserving space */
struct kvm_pic_state pic;
struct kvm_ioapic_state ioapic;
} chip;
};
4.28 KVM_XEN_HVM_CONFIG¶
- 功能:
KVM_CAP_XEN_HVM
- 架構:
x86
- 型別:
vm ioctl
- 引數:
struct kvm_xen_hvm_config (輸入)
- 返回值:
成功時為 0,出錯時為 -1
設定 Xen HVM guest 用來初始化其 hypercall 頁面的 MSR,並提供使用者空間中 hypercall blobs 的起始地址和大小。當 guest 寫入 MSR 時,kvm 將一個 blob 頁面(32 位或 64 位,取決於 vcpu 模式)複製到 guest 記憶體。
MSR 索引必須在範圍 [0x40000000, 0x4fffffff] 中,即必須駐留在非官方保留給 hypervisor 使用的範圍內。最小/最大值透過 KVM_XEN_MSR_MIN_INDEX 和 KVM_XEN_MSR_MAX_INDEX 列舉。
struct kvm_xen_hvm_config {
__u32 flags;
__u32 msr;
__u64 blob_addr_32;
__u64 blob_addr_64;
__u8 blob_size_32;
__u8 blob_size_64;
__u8 pad2[30];
};
如果從 KVM_CAP_XEN_HVM 檢查返回某些標誌,則可以在此 ioctl 的標誌欄位中設定它們
KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL 標誌請求 KVM 自動生成 hypercall 頁面的內容;hypercall 將被攔截並透過 KVM_EXIT_XEN 傳遞給使用者空間。在這種情況下,所有 blob 大小和地址欄位必須為零。
KVM_XEN_HVM_CONFIG_EVTCHN_SEND 標誌指示 KVM,使用者空間將始終使用 KVM_XEN_HVM_EVTCHN_SEND ioctl 來傳遞事件通道中斷,而不是直接操作 guest 的 shared_info 結構。反過來,這可能允許 KVM 啟用某些功能,例如攔截 SCHEDOP_poll hypercall 以加速 guest 的 PV 自旋鎖操作。即使使用者空間不傳送將始終這樣做的指示,使用者空間仍然可以使用 ioctl 來傳遞事件(如果已公佈)。
目前,在 struct kvm_xen_hvm_config 中沒有其他有效標誌。
4.29 KVM_GET_CLOCK¶
- 功能:
KVM_CAP_ADJUST_CLOCK
- 架構:
x86
- 型別:
vm ioctl
- 引數:
struct kvm_clock_data (輸出)
- 返回值:
成功時為 0,出錯時為 -1
獲取當前 guest 看到的 kvmclock 的當前時間戳。與 KVM_SET_CLOCK 結合使用,它用於確保遷移等場景的單調性。
當 KVM_CAP_ADJUST_CLOCK 傳遞給 KVM_CHECK_EXTENSION 時,它返回 KVM 可以在 struct kvm_clock_data 的 flag 成員中返回的位集合。
定義了以下標誌
- KVM_CLOCK_TSC_STABLE
如果設定,則返回的值是呼叫 KVM_GET_CLOCK 時所有 VCPU 看到的精確 kvmclock 值。如果清除,則返回的值僅為 CLOCK_MONOTONIC 加上一個常數偏移量;可以使用 KVM_SET_CLOCK 修改偏移量。KVM 將嘗試使所有 VCPU 遵循此時鐘,但每個 VCPU 讀取的精確值可能會有所不同,因為主機 TSC 不穩定。
- KVM_CLOCK_REALTIME
如果設定,則 kvm_clock_data 結構中的 realtime 欄位填充了呼叫 KVM_GET_CLOCK 時主機即時時鐘源的值。如果清除,則 realtime 欄位不包含值。
- KVM_CLOCK_HOST_TSC
如果設定,則 kvm_clock_data 結構中的 host_tsc 欄位填充了呼叫 KVM_GET_CLOCK 時主機時間戳計數器 (TSC) 的值。如果清除,則 host_tsc 欄位不包含值。
struct kvm_clock_data {
__u64 clock; /* kvmclock current value */
__u32 flags;
__u32 pad0;
__u64 realtime;
__u64 host_tsc;
__u32 pad[4];
};
4.30 KVM_SET_CLOCK¶
- 功能:
KVM_CAP_ADJUST_CLOCK
- 架構:
x86
- 型別:
vm ioctl
- 引數:
struct kvm_clock_data (輸入)
- 返回值:
成功時為 0,出錯時為 -1
將 kvmclock 的當前時間戳設定為其引數中指定的值。與 KVM_GET_CLOCK 結合使用,它用於確保遷移等場景的單調性。
可以傳遞以下標誌
- KVM_CLOCK_REALTIME
如果設定,KVM 將比較 realtime 欄位的值與呼叫 KVM_SET_CLOCK 時主機即時時鐘源的值。經過的時間差將新增到將提供給 guest 的最終 kvmclock 值。
KVM_GET_CLOCK 返回的其他標誌被接受但被忽略。
struct kvm_clock_data {
__u64 clock; /* kvmclock current value */
__u32 flags;
__u32 pad0;
__u64 realtime;
__u64 host_tsc;
__u32 pad[4];
};
4.31 KVM_GET_VCPU_EVENTS¶
- 功能:
KVM_CAP_VCPU_EVENTS
- 由擴充套件:
KVM_CAP_INTR_SHADOW
- 架構:
x86, arm64
- 型別:
vcpu ioctl
- 引數:
struct kvm_vcpu_events (輸出)
- 返回值:
成功時為 0,出錯時為 -1
X86:¶
獲取當前掛起的異常、中斷和 NMI,以及 vcpu 的相關狀態。
struct kvm_vcpu_events {
struct {
__u8 injected;
__u8 nr;
__u8 has_error_code;
__u8 pending;
__u32 error_code;
} exception;
struct {
__u8 injected;
__u8 nr;
__u8 soft;
__u8 shadow;
} interrupt;
struct {
__u8 injected;
__u8 pending;
__u8 masked;
__u8 pad;
} nmi;
__u32 sipi_vector;
__u32 flags;
struct {
__u8 smm;
__u8 pending;
__u8 smm_inside_nmi;
__u8 latched_init;
} smi;
__u8 reserved[27];
__u8 exception_has_payload;
__u64 exception_payload;
};
在 flags 欄位中定義了以下位
可以設定 KVM_VCPUEVENT_VALID_SHADOW 以指示 interrupt.shadow 包含有效狀態。
可以設定 KVM_VCPUEVENT_VALID_SMM 以指示 smi 包含有效狀態。
可以設定 KVM_VCPUEVENT_VALID_PAYLOAD 以指示 exception_has_payload、exception_payload 和 exception.pending 欄位包含有效狀態。只要啟用 KVM_CAP_EXCEPTION_PAYLOAD,就會設定此位。
可以設定 KVM_VCPUEVENT_VALID_TRIPLE_FAULT 以指示 triple_fault_pending 欄位包含有效狀態。只要啟用 KVM_CAP_X86_TRIPLE_FAULT_EVENT,就會設定此位。
ARM64:¶
如果 guest 以真實裝置會生成物理 SError 的方式訪問由主機核心模擬的裝置,KVM 可能會使虛擬 SError 對該 VCPU 掛起。此係統錯誤中斷保持掛起狀態,直到 guest 透過取消遮蔽 PSTATE.A 來處理異常。
執行 VCPU 可能會導致它處理掛起的 SError,或者進行導致 SError 變為掛起狀態的訪問。事件的描述僅在 VPCU 未執行時有效。
此 API 提供了一種讀取和寫入 guest 不可見的掛起 'event' 狀態的方法。為了儲存、恢復或遷移 VCPU,可以使用此 GET/SET API 讀取然後寫入表示狀態的結構,以及其他 guest 可見的暫存器。無法“取消”已設定為掛起的 SError。
使用者空間中模擬的裝置也可能希望生成 SError。為此,使用者空間可以填充事件結構。應首先讀取當前狀態,以確保沒有掛起的 SError。如果存在掛起的 SError,則應遵循架構的“多個 SError 中斷”規則。(DDI0587.a “ARM 可靠性、可用性和可維護性 (RAS) 規範”的 2.5.3)。
SError 異常始終具有 ESR 值。某些 CPU 能夠指定虛擬 SError 的 ESR 值應是什麼。這些系統將公佈 KVM_CAP_ARM_INJECT_SERROR_ESR。在這種情況下,讀取時 exception.has_esr 將始終具有非零值,並且使 SError 掛起的代理應在 exception.serror_esr 的低 24 位中指定 ISS 欄位。如果系統支援 KVM_CAP_ARM_INJECT_SERROR_ESR,但使用者空間將 exception.has_esr 設定為零的事件,KVM 將選擇一個 ESR。
在不支援的系統上指定 exception.has_esr 將返回 -EINVAL。設定 exception.serror_esr 的低 24 位之外的任何內容將返回 -EINVAL。
無法讀取回掛起的外部中止(透過 KVM_SET_VCPU_EVENTS 注入或其他方式),因為此類異常始終直接傳遞到虛擬 CPU)。
struct kvm_vcpu_events {
struct {
__u8 serror_pending;
__u8 serror_has_esr;
__u8 ext_dabt_pending;
/* Align it to 8 bytes */
__u8 pad[5];
__u64 serror_esr;
} exception;
__u32 reserved[12];
};
4.32 KVM_SET_VCPU_EVENTS¶
- 功能:
KVM_CAP_VCPU_EVENTS
- 由擴充套件:
KVM_CAP_INTR_SHADOW
- 架構:
x86, arm64
- 型別:
vcpu ioctl
- 引數:
struct kvm_vcpu_events (輸入)
- 返回值:
成功時為 0,出錯時為 -1
X86:¶
設定掛起的異常、中斷和 NMI,以及 vcpu 的相關狀態。
有關資料結構,請參閱 KVM_GET_VCPU_EVENTS。
可以從更新中排除可能由執行 VCPU 非同步修改的欄位。這些欄位是 nmi.pending、sipi_vector、smi.smm、smi.pending。保持 flags 欄位中相應的位清除,以禁止覆蓋當前的核心狀態。這些位是
KVM_VCPUEVENT_VALID_NMI_PENDING |
將 nmi.pending 傳輸到核心 |
KVM_VCPUEVENT_VALID_SIPI_VECTOR |
傳輸 sipi_vector |
KVM_VCPUEVENT_VALID_SMM |
傳輸 smi 子結構。 |
如果 KVM_CAP_INTR_SHADOW 可用,則可以在 flags 欄位中設定 KVM_VCPUEVENT_VALID_SHADOW,以指示 interrupt.shadow 包含有效狀態,並且應寫入 VCPU。
只有當 KVM_CAP_X86_SMM 可用時,才能設定 KVM_VCPUEVENT_VALID_SMM。
如果啟用了 KVM_CAP_EXCEPTION_PAYLOAD,則可以在 flags 欄位中設定 KVM_VCPUEVENT_VALID_PAYLOAD,以指示 exception_has_payload、exception_payload 和 exception.pending 欄位包含有效狀態,並且應寫入 VCPU。
如果啟用了 KVM_CAP_X86_TRIPLE_FAULT_EVENT,則可以在 flags 欄位中設定 KVM_VCPUEVENT_VALID_TRIPLE_FAULT,以指示 triple_fault 欄位包含有效狀態,並且應寫入 VCPU。
ARM64:¶
使用者空間可能需要將幾種型別的事件注入到 guest 中。
為此 VCPU 設定掛起的 SError 異常狀態。無法“取消”已設定為掛起的 SError。
如果 guest 執行了使用者空間無法處理的 I/O 記憶體訪問,例如由於缺少指令綜合徵解碼資訊,或者由於在訪問的 IPA 處沒有對映裝置,則使用者空間可以要求核心使用 VCPU 上退出故障的地址來注入外部中止。在未進行 KVM_EXIT_MMIO 或 KVM_EXIT_ARM_NISV 的退出之後設定 ext_dabt_pending 是一種程式設計錯誤。只有當系統支援 KVM_CAP_ARM_INJECT_EXT_DABT 時,此功能才可用。這是一種幫助程式,用於提供使用者空間如何跨不同的使用者空間實現向 guest 報告上述情況的通用性。但是,使用者空間仍然可以使用 KVM_SET_ONE_REG API 操作單個暫存器來模擬所有 Arm 異常。
有關資料結構,請參閱 KVM_GET_VCPU_EVENTS。
4.33 KVM_GET_DEBUGREGS¶
- 功能:
KVM_CAP_DEBUGREGS
- 架構:
x86
- 型別:
vcpu ioctl
- 引數:
struct kvm_debugregs (輸出)
- 返回值:
成功時為 0,出錯時為 -1
從 vcpu 讀取除錯暫存器。
struct kvm_debugregs {
__u64 db[4];
__u64 dr6;
__u64 dr7;
__u64 flags;
__u64 reserved[9];
};
4.34 KVM_SET_DEBUGREGS¶
- 功能:
KVM_CAP_DEBUGREGS
- 架構:
x86
- 型別:
vcpu ioctl
- 引數:
struct kvm_debugregs (輸入)
- 返回值:
成功時為 0,出錯時為 -1
將除錯暫存器寫入 vcpu。
有關資料結構,請參閱 KVM_GET_DEBUGREGS。flags 欄位尚未使用,必須在條目上清除。
4.35 KVM_SET_USER_MEMORY_REGION¶
- 功能:
KVM_CAP_USER_MEMORY
- 架構:
全部
- 型別:
vm ioctl
- 引數:
struct kvm_userspace_memory_region (輸入)
- 返回值:
成功時為 0,出錯時為 -1
struct kvm_userspace_memory_region {
__u32 slot;
__u32 flags;
__u64 guest_phys_addr;
__u64 memory_size; /* bytes */
__u64 userspace_addr; /* start of the userspace allocated memory */
};
/* for kvm_userspace_memory_region::flags */
#define KVM_MEM_LOG_DIRTY_PAGES (1UL << 0)
#define KVM_MEM_READONLY (1UL << 1)
此 ioctl 允許使用者建立、修改或刪除 guest 物理記憶體槽。“slot” 的位 0-15 指定槽 ID,此值應小於每個 VM 支援的最大使用者記憶體槽數。可以使用 KVM_CAP_NR_MEMSLOTS 查詢允許的最大槽數。槽不得在 guest 物理地址空間中重疊。
如果 KVM_CAP_MULTI_ADDRESS_SPACE 可用,則 “slot” 的位 16-31 指定要修改的地址空間。它們必須小於 KVM_CHECK_EXTENSION 為 KVM_CAP_MULTI_ADDRESS_SPACE 功能返回的值。單獨地址空間中的槽不相關;對重疊槽的限制僅適用於每個地址空間。
刪除槽透過為 memory_size 傳遞零來完成。更改現有槽時,可以在 guest 物理記憶體空間中移動它,或者可以修改其標誌,但不能調整其大小。
該區域的記憶體從 userspace_addr 欄位表示的地址開始獲取,該地址必須指向整個記憶體槽大小的使用者可定址記憶體。任何物件都可以支援此記憶體,包括匿名記憶體、普通檔案和 hugetlbfs。
在支援某種形式的地址標記的架構上,userspace_addr 必須是未標記的地址。
建議 guest_phys_addr 和 userspace_addr 的低 21 位相同。這允許 guest 中的大頁面由主機中的大頁面支援。
flags 欄位支援兩個標誌:KVM_MEM_LOG_DIRTY_PAGES 和 KVM_MEM_READONLY。可以設定前者以指示 KVM 跟蹤槽中記憶體的寫入。有關如何使用它,請參閱 KVM_GET_DIRTY_LOG ioctl。如果 KVM_CAP_READONLY_MEM 功能允許,可以設定後者以使新槽只讀。在這種情況下,對此記憶體的寫入將作為 KVM_EXIT_MMIO 退出釋出到使用者空間。
當 KVM_CAP_SYNC_MMU 功能可用時,記憶體區域支援中的更改會自動反映到 guest 中。例如,影響該區域的 mmap() 將立即可見。另一個示例是 madvise(MADV_DROP)。
對於 TDX guest,刪除/移動記憶體區域會丟失 guest 記憶體內容。不支援只讀區域。僅支援 as-id 0。
注意:在 arm64 上,頁面表 walker 生成的寫入(例如,為了更新訪問和髒位)永遠不會導致當槽具有 KVM_MEM_READONLY 標誌時的 KVM_EXIT_MMIO 退出。這是因為 KVM 無法提供頁面表 walker 將寫入的資料,從而無法模擬訪問。相反,在 guest 中注入中止(如果頁面表更新的原因是載入或儲存,則為資料中止,如果是指令提取,則為指令中止)。
S390:¶
如果 VM 設定了 KVM_VM_S390_UCONTROL 標誌,則返回 -EINVAL 或 -EEXIST。如果在受保護的 VM 上呼叫,則返回 -EINVAL。
4.36 KVM_SET_TSS_ADDR¶
- 功能:
KVM_CAP_SET_TSS_ADDR
- 架構:
x86
- 型別:
vm ioctl
- 引數:
unsigned long tss_address (輸入)
- 返回值:
成功時為 0,出錯時為 -1
此 ioctl 定義 guest 物理地址空間中三頁區域的物理地址。該區域必須在 guest 物理地址空間的前 4GB 中,並且不得與任何記憶體槽或任何 mmio 地址衝突。如果 guest 訪問此記憶體區域,則可能會發生故障。
在基於 Intel 的主機上需要此 ioctl。由於虛擬化實現中的一個怪癖,基於 Intel 的硬體需要這樣做(當它出現時,請參閱內部文件)。
4.37 KVM_ENABLE_CAP¶
- 功能:
KVM_CAP_ENABLE_CAP
- 架構:
mips, ppc, s390, x86, loongarch
- 型別:
vcpu ioctl
- 引數:
struct kvm_enable_cap (輸入)
- 返回值:
成功時為 0;出錯時為 -1
- 功能:
KVM_CAP_ENABLE_CAP_VM
- 架構:
全部
- 型別:
vm ioctl
- 引數:
struct kvm_enable_cap (輸入)
- 返回值:
成功時為 0;出錯時為 -1
注意
並非所有擴充套件都預設啟用。使用此 ioctl,應用程式可以啟用擴充套件,使其可用於 guest。
在不支援此 ioctl 的系統上,它始終失敗。在支援它的系統上,它僅適用於支援啟用的擴充套件。
要檢查是否可以啟用功能,應使用 KVM_CHECK_EXTENSION ioctl。
struct kvm_enable_cap {
/* in */
__u32 cap;
應該啟用的功能。
__u32 flags;
指示未來增強功能的位欄位。現在必須為 0。
__u64 args[4];
用於啟用功能的引數。如果功能需要初始值才能正常執行,則這是放置它們的位置。
__u8 pad[64];
};
vcpu ioctl 應用於 vcpu 特定的功能,vm ioctl 應用於 vm 範圍的功能。
4.38 KVM_GET_MP_STATE¶
- 功能:
KVM_CAP_MP_STATE
- 架構:
x86, s390, arm64, riscv, loongarch
- 型別:
vcpu ioctl
- 引數:
struct kvm_mp_state (輸出)
- 返回值:
成功時為 0;出錯時為 -1
struct kvm_mp_state {
__u32 mp_state;
};
返回 vcpu 的當前“多處理狀態”(儘管在單處理器 guest 上也有效)。
可能的值是
KVM_MP_STATE_RUNNABLE
vcpu 當前正在執行 [x86,arm64,riscv,loongarch]
KVM_MP_STATE_UNINITIALIZED
vcpu 是尚未收到 INIT 訊號的應用程式處理器 (AP) [x86]
KVM_MP_STATE_INIT_RECEIVED
vcpu 已收到 INIT 訊號,現在已準備好進行 SIPI [x86]
KVM_MP_STATE_HALTED
vcpu 已執行 HLT 指令,正在等待中斷 [x86]
KVM_MP_STATE_SIPI_RECEIVED
vcpu 剛剛收到 SIPI(可透過 KVM_GET_VCPU_EVENTS 訪問的向量)[x86]
KVM_MP_STATE_STOPPED
vcpu 已停止 [s390,arm64,riscv]
KVM_MP_STATE_CHECK_STOP
vcpu 處於特殊錯誤狀態 [s390]
KVM_MP_STATE_OPERATING
vcpu 正在執行(正在執行或已停止)[s390]
KVM_MP_STATE_LOAD
vcpu 處於特殊載入/啟動狀態 [s390]
KVM_MP_STATE_SUSPENDED
vcpu 處於掛起狀態,正在等待喚醒事件 [arm64]
在 x86 上,只有在 KVM_CREATE_IRQCHIP 之後此 ioctl 才有用。如果沒有核心 irqchip,則必須由使用者空間在這些架構上維護多處理狀態。
對於 arm64:¶
如果 vCPU 處於 KVM_MP_STATE_SUSPENDED 狀態,KVM 將模擬 WFI 指令的架構執行。
如果識別出喚醒事件,KVM 將透過 KVM_SYSTEM_EVENT 退出返回到使用者空間,其中事件型別為 KVM_SYSTEM_EVENT_WAKEUP。如果使用者空間想要遵守喚醒,則必須將 vCPU 的 MP 狀態設定為 KVM_MP_STATE_RUNNABLE。如果不是,KVM 將繼續在後續呼叫 KVM_RUN 中等待喚醒事件。
警告
如果使用者空間打算將 vCPU 保留在 SUSPENDED 狀態,強烈建議使用者空間採取行動來抑制喚醒事件(例如遮蔽中斷)。否則,後續呼叫 KVM_RUN 將立即退出,並顯示 KVM_SYSTEM_EVENT_WAKEUP 事件,並無意中浪費 CPU 週期。
此外,如果使用者空間採取行動來抑制喚醒事件,強烈建議在再次使 vCPU 可執行時,也將其恢復到原始狀態。例如,如果使用者空間遮蔽了掛起的中斷以抑制喚醒,則應在將控制權返回給 guest 之前取消遮蔽中斷。
對於 riscv:¶
唯一有效的狀態是 KVM_MP_STATE_STOPPED 和 KVM_MP_STATE_RUNNABLE,它們反映了 vcpu 是否暫停。
在 LoongArch 上,僅使用 KVM_MP_STATE_RUNNABLE 狀態來反映 vcpu 是否可執行。
4.39 KVM_SET_MP_STATE¶
- 功能:
KVM_CAP_MP_STATE
- 架構:
x86, s390, arm64, riscv, loongarch
- 型別:
vcpu ioctl
- 引數:
struct kvm_mp_state (輸入)
- 返回值:
成功時為 0;出錯時為 -1
設定 vcpu 的當前“多處理狀態”;有關引數,請參閱 KVM_GET_MP_STATE。
在 x86 上,只有在 KVM_CREATE_IRQCHIP 之後此 ioctl 才有用。如果沒有核心 irqchip,則必須由使用者空間在這些架構上維護多處理狀態。
對於 arm64/riscv:¶
唯一有效的狀態是 KVM_MP_STATE_STOPPED 和 KVM_MP_STATE_RUNNABLE,它們反映了 vcpu 是否應該暫停。
在 LoongArch 上,僅使用 KVM_MP_STATE_RUNNABLE 狀態來反映 vcpu 是否可執行。
4.40 KVM_SET_IDENTITY_MAP_ADDR¶
- 功能:
KVM_CAP_SET_IDENTITY_MAP_ADDR
- 架構:
x86
- 型別:
vm ioctl
- 引數:
unsigned long identity (in)
- 返回值:
成功時為 0,出錯時為 -1
此 ioctl 定義了客戶機物理地址空間中一個頁大小區域的物理地址。該區域必須位於客戶機物理地址空間的前 4GB 內,並且不得與任何記憶體槽或任何 mmio 地址衝突。如果客戶機訪問此記憶體區域,可能會發生故障。
將地址設定為 0 將導致地址重置為其預設值 (0xfffbc000)。
在基於 Intel 的主機上需要此 ioctl。由於虛擬化實現中的一個怪癖,基於 Intel 的硬體需要這樣做(當它出現時,請參閱內部文件)。
如果已建立任何 VCPU,則失敗。
4.41 KVM_SET_BOOT_CPU_ID¶
- 功能:
KVM_CAP_SET_BOOT_CPU_ID
- 架構:
x86
- 型別:
vm ioctl
- 引數:
unsigned long vcpu_id
- 返回值:
成功時為 0,出錯時為 -1
定義哪個 vcpu 是引導處理器 (BSP)。值與 KVM_CREATE_VCPU 中的 vcpu id 相同。如果未呼叫此 ioctl,則預設為 vcpu 0。必須在 vcpu 建立之前呼叫此 ioctl,否則將返回 EBUSY 錯誤。
4.42 KVM_GET_XSAVE¶
- 功能:
KVM_CAP_XSAVE
- 架構:
x86
- 型別:
vcpu ioctl
- 引數:
struct kvm_xsave (out)
- 返回值:
成功時為 0,出錯時為 -1
struct kvm_xsave {
__u32 region[1024];
__u32 extra[0];
};
此 ioctl 會將當前 vcpu 的 xsave 結構複製到使用者空間。
4.43 KVM_SET_XSAVE¶
- 功能:
KVM_CAP_XSAVE 和 KVM_CAP_XSAVE2
- 架構:
x86
- 型別:
vcpu ioctl
- 引數:
struct kvm_xsave (in)
- 返回值:
成功時為 0,出錯時為 -1
struct kvm_xsave {
__u32 region[1024];
__u32 extra[0];
};
此 ioctl 會將使用者空間的 xsave 結構複製到核心。它複製的位元組數與在 vm 檔案描述符上呼叫 KVM_CHECK_EXTENSION(KVM_CAP_XSAVE2) 返回的位元組數一樣多。KVM_CHECK_EXTENSION(KVM_CAP_XSAVE2) 返回的大小值將始終至少為 4096。目前,只有在使用 arch_prctl() 啟用動態功能後,該值才會大於 4096,但將來可能會發生變化。
struct kvm_xsave 中狀態儲存區域的偏移量遵循主機上 CPUID 葉 0xD 的內容。
4.44 KVM_GET_XCRS¶
- 功能:
KVM_CAP_XCRS
- 架構:
x86
- 型別:
vcpu ioctl
- 引數:
struct kvm_xcrs (out)
- 返回值:
成功時為 0,出錯時為 -1
struct kvm_xcr {
__u32 xcr;
__u32 reserved;
__u64 value;
};
struct kvm_xcrs {
__u32 nr_xcrs;
__u32 flags;
struct kvm_xcr xcrs[KVM_MAX_XCRS];
__u64 padding[16];
};
此 ioctl 會將當前 vcpu 的 xcrs 複製到使用者空間。
4.45 KVM_SET_XCRS¶
- 功能:
KVM_CAP_XCRS
- 架構:
x86
- 型別:
vcpu ioctl
- 引數:
struct kvm_xcrs (in)
- 返回值:
成功時為 0,出錯時為 -1
struct kvm_xcr {
__u32 xcr;
__u32 reserved;
__u64 value;
};
struct kvm_xcrs {
__u32 nr_xcrs;
__u32 flags;
struct kvm_xcr xcrs[KVM_MAX_XCRS];
__u64 padding[16];
};
此 ioctl 會將 vcpu 的 xcr 設定為使用者空間指定的值。
4.46 KVM_GET_SUPPORTED_CPUID¶
- 功能:
KVM_CAP_EXT_CPUID
- 架構:
x86
- 型別:
系統 ioctl
- 引數:
struct kvm_cpuid2 (in/out)
- 返回值:
成功時為 0,出錯時為 -1
struct kvm_cpuid2 {
__u32 nent;
__u32 padding;
struct kvm_cpuid_entry2 entries[0];
};
#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX BIT(0)
#define KVM_CPUID_FLAG_STATEFUL_FUNC BIT(1) /* deprecated */
#define KVM_CPUID_FLAG_STATE_READ_NEXT BIT(2) /* deprecated */
struct kvm_cpuid_entry2 {
__u32 function;
__u32 index;
__u32 flags;
__u32 eax;
__u32 ebx;
__u32 ecx;
__u32 edx;
__u32 padding[3];
};
此 ioctl 返回 x86 cpuid 功能,這些功能受硬體和 kvm 在其預設配置中支援。使用者空間可以使用此 ioctl 返回的資訊來構建與硬體、核心和使用者空間功能一致的 cpuid 資訊(對於 KVM_SET_CPUID2),並滿足使用者要求(例如,使用者可能希望約束 cpuid 以模擬較舊的硬體,或者為了跨叢集的功能一致性)。
動態啟用的功能位需要在呼叫此 ioctl 之前使用 arch_prctl() 請求。未請求的功能位將從結果中排除。
請注意,某些功能(例如 KVM_CAP_X86_DISABLE_EXITS)可能會公開 kvm 在其預設配置中不支援的 cpuid 功能(例如 MONITOR)。如果使用者空間啟用此類功能,則它負責適當地修改此 ioctl 的結果。
使用者空間透過傳遞一個 kvm_cpuid2 結構來呼叫 KVM_GET_SUPPORTED_CPUID,其中 'nent' 欄位指示可變大小陣列 'entries' 中的條目數。如果條目數太低而無法描述 cpu 功能,則返回錯誤 (E2BIG)。如果數量太高,則調整 'nent' 欄位並返回錯誤 (ENOMEM)。如果數量恰好合適,則將 'nent' 欄位調整為 'entries' 陣列中有效條目的數量,然後填充該陣列。
返回的條目是由 cpuid 指令返回的主機 cpuid,其中未知或不受支援的功能被遮蔽掉。某些功能(例如 x2apic)可能不存在於主機 cpu 中,但如果 kvm 可以有效地模擬它們,則由 kvm 公開。每個條目中的欄位定義如下
- function
用於獲取條目的 eax 值
- index
用於獲取條目的 ecx 值(對於受 ecx 影響的條目)
- flags
以下零個或多個的 OR
- KVM_CPUID_FLAG_SIGNIFCANT_INDEX
如果索引欄位有效
- eax, ebx, ecx, edx
cpuid 指令為此 function/index 組合返回的值
x2APIC(CPUID 葉 1,ecx[21) 和 TSC 截止時間計時器(CPUID 葉 1,ecx[24])可能會返回 true,但它們依賴於 KVM_CREATE_IRQCHIP 來實現本地 APIC 的核心內模擬。TSC 截止時間計時器支援也透過以下方式報告
ioctl(KVM_CHECK_EXTENSION, KVM_CAP_TSC_DEADLINE_TIMER)
如果返回 true 並且您使用 KVM_CREATE_IRQCHIP,或者如果您在使用者空間中模擬該功能,則可以為 KVM_SET_CPUID2 啟用該功能。
在 KVM_SET_CPUID2 中啟用 x2APIC 需要 KVM_CREATE_IRQCHIP,因為 KVM 不支援將 x2APIC MSR 訪問轉發到使用者空間,即 KVM 不支援在使用者空間中模擬 x2APIC。
4.47 KVM_PPC_GET_PVINFO¶
- 功能:
KVM_CAP_PPC_GET_PVINFO
- 架構:
ppc
- 型別:
vm ioctl
- 引數:
struct kvm_ppc_pvinfo (out)
- 返回值:
成功時為 0,出錯時為 !0
struct kvm_ppc_pvinfo {
__u32 flags;
__u32 hcall[4];
__u8 pad[108];
};
此 ioctl 獲取需要使用裝置樹或其他方式從 vm 上下文傳遞到客戶機的 PV 特定資訊。
hcall 陣列定義了構成超呼叫的 4 個指令。
如果在以後向該結構新增任何其他欄位,則將在 flags 點陣圖中設定該附加資訊位的標誌。
flags 點陣圖定義為
/* the host supports the ePAPR idle hcall
#define KVM_PPC_PVINFO_FLAGS_EV_IDLE (1<<0)
4.52 KVM_SET_GSI_ROUTING¶
- 功能:
KVM_CAP_IRQ_ROUTING
- 架構:
x86 s390 arm64
- 型別:
vm ioctl
- 引數:
struct kvm_irq_routing (in)
- 返回值:
成功時為 0,出錯時為 -1
設定 GSI 路由表條目,覆蓋任何先前設定的條目。
在 arm64 上,GSI 路由具有以下限制
GSI 路由不適用於 KVM_IRQ_LINE,僅適用於 KVM_IRQFD。
struct kvm_irq_routing {
__u32 nr;
__u32 flags;
struct kvm_irq_routing_entry entries[0];
};
到目前為止,未指定任何標誌,相應的欄位必須設定為零。
struct kvm_irq_routing_entry {
__u32 gsi;
__u32 type;
__u32 flags;
__u32 pad;
union {
struct kvm_irq_routing_irqchip irqchip;
struct kvm_irq_routing_msi msi;
struct kvm_irq_routing_s390_adapter adapter;
struct kvm_irq_routing_hv_sint hv_sint;
struct kvm_irq_routing_xen_evtchn xen_evtchn;
__u32 pad[8];
} u;
};
/* gsi routing entry types */
#define KVM_IRQ_ROUTING_IRQCHIP 1
#define KVM_IRQ_ROUTING_MSI 2
#define KVM_IRQ_ROUTING_S390_ADAPTER 3
#define KVM_IRQ_ROUTING_HV_SINT 4
#define KVM_IRQ_ROUTING_XEN_EVTCHN 5
在 s390 上,在 ucontrol VM 上新增 KVM_IRQ_ROUTING_S390_ADAPTER 會因錯誤 -EINVAL 而被拒絕。
flags
KVM_MSI_VALID_DEVID:與 KVM_IRQ_ROUTING_MSI 路由條目型別一起使用,指定 devid 欄位包含有效值。每個 VM 的 KVM_CAP_MSI_DEVID 功能會宣告提供裝置 ID 的要求。如果此功能不可用,則使用者空間絕不應設定 KVM_MSI_VALID_DEVID 標誌,因為 ioctl 可能會失敗。
否則為零
struct kvm_irq_routing_irqchip {
__u32 irqchip;
__u32 pin;
};
struct kvm_irq_routing_msi {
__u32 address_lo;
__u32 address_hi;
__u32 data;
union {
__u32 pad;
__u32 devid;
};
};
如果設定了 KVM_MSI_VALID_DEVID,則 devid 包含寫入 MSI 訊息的裝置的唯一裝置識別符號。對於 PCI,這通常是低 16 位中的 BDF 識別符號。
在 x86 上,除非啟用了 KVM_CAP_X2APIC_API 功能的 KVM_X2APIC_API_USE_32BIT_IDS 功能,否則 address_hi 將被忽略。如果啟用了該功能,則 address_hi 的位 31-8 提供目標 id 的位 31-8。address_hi 的位 7-0 必須為零。
struct kvm_irq_routing_s390_adapter {
__u64 ind_addr;
__u64 summary_addr;
__u64 ind_offset;
__u32 summary_offset;
__u32 adapter_id;
};
struct kvm_irq_routing_hv_sint {
__u32 vcpu;
__u32 sint;
};
struct kvm_irq_routing_xen_evtchn {
__u32 port;
__u32 vcpu;
__u32 priority;
};
當 KVM_CAP_XEN_HVM 在其支援的功能指示中包含 KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL 位時,支援路由到 Xen 事件通道。儘管存在優先順序欄位,但僅支援值 KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL,這意味著透過 2 級事件通道傳遞。將來可能會新增 FIFO 事件通道支援。
4.55 KVM_SET_TSC_KHZ¶
- 功能:
KVM_CAP_TSC_CONTROL / KVM_CAP_VM_TSC_CONTROL
- 架構:
x86
- 型別:
vcpu ioctl / vm ioctl
- 引數:
virtual tsc_khz
- 返回值:
成功時為 0,出錯時為 -1
指定虛擬機器的 tsc 頻率。頻率的單位為 KHz。
如果聲明瞭 KVM_CAP_VM_TSC_CONTROL 功能,則它也可以用作 vm ioctl 來設定後續建立的 vCPU 的初始 tsc 頻率。
4.56 KVM_GET_TSC_KHZ¶
- 功能:
KVM_CAP_GET_TSC_KHZ / KVM_CAP_VM_TSC_CONTROL
- 架構:
x86
- 型別:
vcpu ioctl / vm ioctl
- 引數:
無
- 返回值:
成功時為 virtual tsc-khz,出錯時為負值
返回客戶機的 tsc 頻率。返回值單位為 KHz。如果主機具有不穩定的 tsc,則此 ioctl 返回 -EIO 作為錯誤。
4.57 KVM_GET_LAPIC¶
- 功能:
KVM_CAP_IRQCHIP
- 架構:
x86
- 型別:
vcpu ioctl
- 引數:
struct kvm_lapic_state (out)
- 返回值:
成功時為 0,出錯時為 -1
#define KVM_APIC_REG_SIZE 0x400
struct kvm_lapic_state {
char regs[KVM_APIC_REG_SIZE];
};
讀取本地 APIC 暫存器並將它們複製到輸入引數中。資料格式和佈局與架構手冊中記錄的相同。
如果啟用了 KVM_CAP_X2APIC_API 的 KVM_X2APIC_API_USE_32BIT_IDS 功能,則 APIC_ID 暫存器的格式取決於其 VCPU 的 APIC 模式(由 MSR_IA32_APICBASE 報告)。x2APIC 將 APIC ID 儲存在 APIC_ID 暫存器中(位元組 32-35)。xAPIC 僅允許一個 8 位 APIC ID,該 ID 儲存在 APIC 暫存器的位 31-24 中,或者等效地儲存在 struct kvm_lapic_state 的 regs 欄位的位元組 35 中。然後必須在使用 KVM_SET_MSR 設定 MSR_IA32_APICBASE 後呼叫 KVM_GET_LAPIC。
如果停用了 KVM_X2APIC_API_USE_32BIT_IDS 功能,則 struct kvm_lapic_state 始終使用 xAPIC 格式。
4.58 KVM_SET_LAPIC¶
- 功能:
KVM_CAP_IRQCHIP
- 架構:
x86
- 型別:
vcpu ioctl
- 引數:
struct kvm_lapic_state (in)
- 返回值:
成功時為 0,出錯時為 -1
#define KVM_APIC_REG_SIZE 0x400
struct kvm_lapic_state {
char regs[KVM_APIC_REG_SIZE];
};
將輸入引數複製到本地 APIC 暫存器中。資料格式和佈局與架構手冊中記錄的相同。
APIC ID 暫存器的格式(struct kvm_lapic_state 的 regs 欄位的位元組 32-35)取決於 KVM_CAP_X2APIC_API 功能的狀態。請參閱 KVM_GET_LAPIC 中的註釋。
4.59 KVM_IOEVENTFD¶
- 功能:
KVM_CAP_IOEVENTFD
- 架構:
全部
- 型別:
vm ioctl
- 引數:
struct kvm_ioeventfd (in)
- 返回值:
成功時為 0,出錯時為 !0
此 ioctl 將 ioeventfd 附加或分離到客戶機中的合法 pio/mmio 地址。在註冊地址中進行客戶機寫入將發出提供的事件訊號,而不是觸發退出。
struct kvm_ioeventfd {
__u64 datamatch;
__u64 addr; /* legal pio/mmio address */
__u32 len; /* 0, 1, 2, 4, or 8 bytes */
__s32 fd;
__u32 flags;
__u8 pad[36];
};
對於 s390 上的 virtio-ccw 裝置的特殊情況,ioevent 與子通道/virtqueue 元組匹配。
定義了以下標誌
#define KVM_IOEVENTFD_FLAG_DATAMATCH (1 << kvm_ioeventfd_flag_nr_datamatch)
#define KVM_IOEVENTFD_FLAG_PIO (1 << kvm_ioeventfd_flag_nr_pio)
#define KVM_IOEVENTFD_FLAG_DEASSIGN (1 << kvm_ioeventfd_flag_nr_deassign)
#define KVM_IOEVENTFD_FLAG_VIRTIO_CCW_NOTIFY \
(1 << kvm_ioeventfd_flag_nr_virtio_ccw_notify)
如果設定了 datamatch 標誌,則只有在寫入到註冊地址的值等於 struct kvm_ioeventfd 中的 datamatch 時,才會發出事件訊號。
對於 virtio-ccw 裝置,addr 包含子通道 id,datamatch 包含 virtqueue 索引。
使用 KVM_CAP_IOEVENTFD_ANY_LENGTH,允許零長度 ioeventfd,核心將忽略客戶機寫入的長度,並且可能會獲得更快的 vmexit。加速可能僅適用於特定架構,但 ioeventfd 無論如何都可以工作。
4.60 KVM_DIRTY_TLB¶
- 功能:
KVM_CAP_SW_TLB
- 架構:
ppc
- 型別:
vcpu ioctl
- 引數:
struct kvm_dirty_tlb (in)
- 返回值:
成功時為 0,出錯時為 -1
struct kvm_dirty_tlb {
__u64 bitmap;
__u32 num_dirty;
};
每當使用者空間更改共享 TLB 中的條目時,必須在對關聯的 vcpu 呼叫 KVM_RUN 之前呼叫此函式。
“bitmap”欄位是陣列的使用者空間地址。此陣列由多個位組成,等於上次成功呼叫 KVM_ENABLE_CAP(KVM_CAP_SW_TLB) 確定的 TLB 條目總數,向上舍入到最接近的 64 的倍數。
每個位對應一個 TLB 條目,排序方式與共享 TLB 陣列中相同。
該陣列是小端序:位 0 是第一個位元組的最低有效位,位 8 是第二個位元組的最低有效位,依此類推。這避免了不同字大小的任何複雜情況。
“num_dirty”欄位是 KVM 的效能提示,用於確定它是否應跳過處理點陣圖並僅使所有內容無效。它必須設定為點陣圖中設定的位數。
4.62 KVM_CREATE_SPAPR_TCE¶
- 功能:
KVM_CAP_SPAPR_TCE
- 架構:
powerpc
- 型別:
vm ioctl
- 引數:
struct kvm_create_spapr_tce (in)
- 返回值:
用於操作建立的 TCE 表的檔案描述符
這將建立一個虛擬 TCE(轉換控制條目)表,該表是 PAPR 樣式的虛擬 I/O 的 IOMMU。它用於將虛擬 I/O 中使用的邏輯地址轉換為客戶機物理地址,併為 PAPR 虛擬 I/O 提供分散/收集功能。
/* for KVM_CAP_SPAPR_TCE */
struct kvm_create_spapr_tce {
__u64 liobn;
__u32 window_size;
};
liobn 欄位給出了要為其建立 TCE 表的邏輯 IO 匯流排號。window_size 欄位指定此 TCE 表將轉換的 DMA 視窗的大小 - 該表將為 DMA 視窗的每 4kiB 包含一個 64 位 TCE 條目。
當客戶機在已使用此 ioctl() 建立 TCE 表的 liobn 上發出 H_PUT_TCE hcall 時,核心將在真真實模式下處理它,從而更新 TCE 表。其他 liobn 的 H_PUT_TCE 呼叫將導致 vm 退出,並且必須由使用者空間處理。
返回值是一個檔案描述符,可以將其傳遞給 mmap(2) 以將建立的 TCE 表對映到使用者空間。這使使用者空間可以讀取由核心處理的 H_PUT_TCE 呼叫寫入的條目,並且還使使用者空間可以直接更新 TCE 表,這在某些情況下很有用。
4.64 KVM_NMI¶
- 功能:
KVM_CAP_USER_NMI
- 架構:
x86
- 型別:
vcpu ioctl
- 引數:
無
- 返回值:
成功時為 0,出錯時為 -1
線上程的 vcpu 上對 NMI 進行排隊。請注意,只有在未呼叫 KVM_CREATE_IRQCHIP 時,此定義才明確,因為這是虛擬 cpu 核心和虛擬本地 APIC 之間的介面。呼叫 KVM_CREATE_IRQCHIP 後,此介面完全在核心中模擬。
要使用此函式透過 KVM_CREATE_IRQCHIP 模擬 LINT1 輸入,請使用以下演算法
暫停 vcpu
讀取本地 APIC 的狀態 (KVM_GET_LAPIC)
檢查更改 LINT1 是否會對 NMI 進行排隊(請參閱 LINT1 的 LVT 條目)
如果是,則發出 KVM_NMI
恢復 vcpu
某些客戶機配置 LINT1 NMI 輸入以導致崩潰,從而有助於除錯。
4.65 KVM_S390_UCAS_MAP¶
- 功能:
KVM_CAP_S390_UCONTROL
- 架構:
s390
- 型別:
vcpu ioctl
- 引數:
struct kvm_s390_ucas_mapping (in)
- 返回值:
成功時為 0
該引數的定義如下
struct kvm_s390_ucas_mapping {
__u64 user_addr;
__u64 vcpu_addr;
__u64 length;
};
此 ioctl 將“user_addr”處的記憶體(長度為“length”)對映到 vcpu 的地址空間,從“vcpu_addr”開始。所有引數都需要對齊 1 兆位元組。
4.66 KVM_S390_UCAS_UNMAP¶
- 功能:
KVM_CAP_S390_UCONTROL
- 架構:
s390
- 型別:
vcpu ioctl
- 引數:
struct kvm_s390_ucas_mapping (in)
- 返回值:
成功時為 0
該引數的定義如下
struct kvm_s390_ucas_mapping {
__u64 user_addr;
__u64 vcpu_addr;
__u64 length;
};
此 ioctl 取消對映 vcpu 地址空間中從“vcpu_addr”開始的記憶體(長度為“length”)。忽略欄位“user_addr”。所有引數都需要對齊 1 兆位元組。
4.67 KVM_S390_VCPU_FAULT¶
- 功能:
KVM_CAP_S390_UCONTROL
- 架構:
s390
- 型別:
vcpu ioctl
- 引數:
vcpu 絕對地址 (in)
- 返回值:
成功時為 0
此呼叫在虛擬 cpu 的地址空間(對於使用者控制的虛擬機器)或虛擬機器的地址空間(對於常規虛擬機器)上建立一個頁表條目。這僅適用於小錯誤,因此建議預先透過使用者頁表訪問主題記憶體頁。這對於處理使用者控制的虛擬機器的有效性攔截非常有用,可以在呼叫 KVM_RUN ioctl 之前將虛擬 cpu 的 lowcore 頁錯誤置於其中。
4.68 KVM_SET_ONE_REG¶
- 功能:
KVM_CAP_ONE_REG
- 架構:
全部
- 型別:
vcpu ioctl
- 引數:
struct kvm_one_reg (in)
- 返回值:
成功時為 0,失敗時為負值
錯誤
ENOENT
沒有這樣的暫存器
EINVAL
無效的暫存器 ID,或者沒有這樣的暫存器,或者在 s390 上與受保護的虛擬化模式下的 VM 一起使用
EPERM
(arm64) 在 vcpu 完成之前不允許訪問暫存器
EBUSY
(riscv) 在 vcpu 至少執行一次後不允許更改暫存器值
(這些錯誤程式碼僅供參考:不要依賴於在特定情況下返回特定錯誤程式碼。)
struct kvm_one_reg {
__u64 id;
__u64 addr;
};
使用此 ioctl,可以將單個 vcpu 暫存器設定為使用者空間定義的特定值,其中 id 指的是下面描述的暫存器識別符號,addr 是指向具有相應大小的變數的指標。可以有與架構無關的暫存器和與架構相關的暫存器。每個暫存器都有自己的操作範圍、自己的常量和寬度。為了跟蹤已實現的暫存器,請在下面找到一個列表
Arch
Register
Width (bits)
PPC
KVM_REG_PPC_HIOR
64
PPC
KVM_REG_PPC_IAC1
64
PPC
KVM_REG_PPC_IAC2
64
PPC
KVM_REG_PPC_IAC3
64
PPC
KVM_REG_PPC_IAC4
64
PPC
KVM_REG_PPC_DAC1
64
PPC
KVM_REG_PPC_DAC2
64
PPC
KVM_REG_PPC_DABR
64
PPC
KVM_REG_PPC_DSCR
64
PPC
KVM_REG_PPC_PURR
64
PPC
KVM_REG_PPC_SPURR
64
PPC
KVM_REG_PPC_DAR
64
PPC
KVM_REG_PPC_DSISR
32
PPC
KVM_REG_PPC_AMR
64
PPC
KVM_REG_PPC_UAMOR
64
PPC
KVM_REG_PPC_MMCR0
64
PPC
KVM_REG_PPC_MMCR1
64
PPC
KVM_REG_PPC_MMCRA
64
PPC
KVM_REG_PPC_MMCR2
64
PPC
KVM_REG_PPC_MMCRS
64
PPC
KVM_REG_PPC_MMCR3
64
PPC
KVM_REG_PPC_SIAR
64
PPC
KVM_REG_PPC_SDAR
64
PPC
KVM_REG_PPC_SIER
64
PPC
KVM_REG_PPC_SIER2
64
PPC
KVM_REG_PPC_SIER3
64
PPC
KVM_REG_PPC_PMC1
32
PPC
KVM_REG_PPC_PMC2
32
PPC
KVM_REG_PPC_PMC3
32
PPC
KVM_REG_PPC_PMC4
32
PPC
KVM_REG_PPC_PMC5
32
PPC
KVM_REG_PPC_PMC6
32
PPC
KVM_REG_PPC_PMC7
32
PPC
KVM_REG_PPC_PMC8
32
PPC
KVM_REG_PPC_FPR0
64
...
PPC
KVM_REG_PPC_FPR31
64
PPC
KVM_REG_PPC_VR0
128
...
PPC
KVM_REG_PPC_VR31
128
PPC
KVM_REG_PPC_VSR0
128
...
PPC
KVM_REG_PPC_VSR31
128
PPC
KVM_REG_PPC_FPSCR
64
PPC
KVM_REG_PPC_VSCR
32
PPC
KVM_REG_PPC_VPA_ADDR
64
PPC
KVM_REG_PPC_VPA_SLB
128
PPC
KVM_REG_PPC_VPA_DTL
128
PPC
KVM_REG_PPC_EPCR
32
PPC
KVM_REG_PPC_EPR
32
PPC
KVM_REG_PPC_TCR
32
PPC
KVM_REG_PPC_TSR
32
PPC
KVM_REG_PPC_OR_TSR
32
PPC
KVM_REG_PPC_CLEAR_TSR
32
PPC
KVM_REG_PPC_MAS0
32
PPC
KVM_REG_PPC_MAS1
32
PPC
KVM_REG_PPC_MAS2
64
PPC
KVM_REG_PPC_MAS7_3
64
PPC
KVM_REG_PPC_MAS4
32
PPC
KVM_REG_PPC_MAS6
32
PPC
KVM_REG_PPC_MMUCFG
32
PPC
KVM_REG_PPC_TLB0CFG
32
PPC
KVM_REG_PPC_TLB1CFG
32
PPC
KVM_REG_PPC_TLB2CFG
32
PPC
KVM_REG_PPC_TLB3CFG
32
PPC
KVM_REG_PPC_TLB0PS
32
PPC
KVM_REG_PPC_TLB1PS
32
PPC
KVM_REG_PPC_TLB2PS
32
PPC
KVM_REG_PPC_TLB3PS
32
PPC
KVM_REG_PPC_EPTCFG
32
PPC
KVM_REG_PPC_ICP_STATE
64
PPC
KVM_REG_PPC_VP_STATE
128
PPC
KVM_REG_PPC_TB_OFFSET
64
PPC
KVM_REG_PPC_SPMC1
32
PPC
KVM_REG_PPC_SPMC2
32
PPC
KVM_REG_PPC_IAMR
64
PPC
KVM_REG_PPC_TFHAR
64
PPC
KVM_REG_PPC_TFIAR
64
PPC
KVM_REG_PPC_TEXASR
64
PPC
KVM_REG_PPC_FSCR
64
PPC
KVM_REG_PPC_PSPB
32
PPC
KVM_REG_PPC_EBBHR
64
PPC
KVM_REG_PPC_EBBRR
64
PPC
KVM_REG_PPC_BESCR
64
PPC
KVM_REG_PPC_TAR
64
PPC
KVM_REG_PPC_DPDES
64
PPC
KVM_REG_PPC_DAWR
64
PPC
KVM_REG_PPC_DAWRX
64
PPC
KVM_REG_PPC_CIABR
64
PPC
KVM_REG_PPC_IC
64
PPC
KVM_REG_PPC_VTB
64
PPC
KVM_REG_PPC_CSIGR
64
PPC
KVM_REG_PPC_TACR
64
PPC
KVM_REG_PPC_TCSCR
64
PPC
KVM_REG_PPC_PID
64
PPC
KVM_REG_PPC_ACOP
64
PPC
KVM_REG_PPC_VRSAVE
32
PPC
KVM_REG_PPC_LPCR
32
PPC
KVM_REG_PPC_LPCR_64
64
PPC
KVM_REG_PPC_PPR
64
PPC
KVM_REG_PPC_ARCH_COMPAT
32
PPC
KVM_REG_PPC_DABRX
32
PPC
KVM_REG_PPC_WORT
64
PPC
KVM_REG_PPC_SPRG9
64
PPC
KVM_REG_PPC_DBSR
32
PPC
KVM_REG_PPC_TIDR
64
PPC
KVM_REG_PPC_PSSCR
64
PPC
KVM_REG_PPC_DEC_EXPIRY
64
PPC
KVM_REG_PPC_PTCR
64
PPC
KVM_REG_PPC_HASHKEYR
64
PPC
KVM_REG_PPC_HASHPKEYR
64
PPC
KVM_REG_PPC_DAWR1
64
PPC
KVM_REG_PPC_DAWRX1
64
PPC
KVM_REG_PPC_DEXCR
64
PPC
KVM_REG_PPC_TM_GPR0
64
...
PPC
KVM_REG_PPC_TM_GPR31
64
PPC
KVM_REG_PPC_TM_VSR0
128
...
PPC
KVM_REG_PPC_TM_VSR63
128
PPC
KVM_REG_PPC_TM_CR
64
PPC
KVM_REG_PPC_TM_LR
64
PPC
KVM_REG_PPC_TM_CTR
64
PPC
KVM_REG_PPC_TM_FPSCR
64
PPC
KVM_REG_PPC_TM_AMR
64
PPC
KVM_REG_PPC_TM_PPR
64
PPC
KVM_REG_PPC_TM_VRSAVE
64
PPC
KVM_REG_PPC_TM_VSCR
32
PPC
KVM_REG_PPC_TM_DSCR
64
PPC
KVM_REG_PPC_TM_TAR
64
PPC
KVM_REG_PPC_TM_XER
64
MIPS
KVM_REG_MIPS_R0
64
...
MIPS
KVM_REG_MIPS_R31
64
MIPS
KVM_REG_MIPS_HI
64
MIPS
KVM_REG_MIPS_LO
64
MIPS
KVM_REG_MIPS_PC
64
MIPS
KVM_REG_MIPS_CP0_INDEX
32
MIPS
KVM_REG_MIPS_CP0_ENTRYLO0
64
MIPS
KVM_REG_MIPS_CP0_ENTRYLO1
64
MIPS
KVM_REG_MIPS_CP0_CONTEXT
64
MIPS
KVM_REG_MIPS_CP0_CONTEXTCONFIG
32
MIPS
KVM_REG_MIPS_CP0_USERLOCAL
64
MIPS
KVM_REG_MIPS_CP0_XCONTEXTCONFIG
64
MIPS
KVM_REG_MIPS_CP0_PAGEMASK
32
MIPS
KVM_REG_MIPS_CP0_PAGEGRAIN
32
MIPS
KVM_REG_MIPS_CP0_SEGCTL0
64
MIPS
KVM_REG_MIPS_CP0_SEGCTL1
64
MIPS
KVM_REG_MIPS_CP0_SEGCTL2
64
MIPS
KVM_REG_MIPS_CP0_PWBASE
64
MIPS
KVM_REG_MIPS_CP0_PWFIELD
64
MIPS
KVM_REG_MIPS_CP0_PWSIZE
64
MIPS
KVM_REG_MIPS_CP0_WIRED
32
MIPS
KVM_REG_MIPS_CP0_PWCTL
32
MIPS
KVM_REG_MIPS_CP0_HWRENA
32
MIPS
KVM_REG_MIPS_CP0_BADVADDR
64
MIPS
KVM_REG_MIPS_CP0_BADINSTR
32
MIPS
KVM_REG_MIPS_CP0_BADINSTRP
32
MIPS
KVM_REG_MIPS_CP0_COUNT
32
MIPS
KVM_REG_MIPS_CP0_ENTRYHI
64
MIPS
KVM_REG_MIPS_CP0_COMPARE
32
MIPS
KVM_REG_MIPS_CP0_STATUS
32
MIPS
KVM_REG_MIPS_CP0_INTCTL
32
MIPS
KVM_REG_MIPS_CP0_CAUSE
32
MIPS
KVM_REG_MIPS_CP0_EPC
64
MIPS
KVM_REG_MIPS_CP0_PRID
32
MIPS
KVM_REG_MIPS_CP0_EBASE
64
MIPS
KVM_REG_MIPS_CP0_CONFIG
32
MIPS
KVM_REG_MIPS_CP0_CONFIG1
32
MIPS
KVM_REG_MIPS_CP0_CONFIG2
32
MIPS
KVM_REG_MIPS_CP0_CONFIG3
32
MIPS
KVM_REG_MIPS_CP0_CONFIG4
32
MIPS
KVM_REG_MIPS_CP0_CONFIG5
32
MIPS
KVM_REG_MIPS_CP0_CONFIG7
32
MIPS
KVM_REG_MIPS_CP0_XCONTEXT
64
MIPS
KVM_REG_MIPS_CP0_ERROREPC
64
MIPS
KVM_REG_MIPS_CP0_KSCRATCH1
64
MIPS
KVM_REG_MIPS_CP0_KSCRATCH2
64
MIPS
KVM_REG_MIPS_CP0_KSCRATCH3
64
MIPS
KVM_REG_MIPS_CP0_KSCRATCH4
64
MIPS
KVM_REG_MIPS_CP0_KSCRATCH5
64
MIPS
KVM_REG_MIPS_CP0_KSCRATCH6
64
MIPS
KVM_REG_MIPS_CP0_MAAR(0..63)
64
MIPS
KVM_REG_MIPS_COUNT_CTL
64
MIPS
KVM_REG_MIPS_COUNT_RESUME
64
MIPS
KVM_REG_MIPS_COUNT_HZ
64
MIPS
KVM_REG_MIPS_FPR_32(0..31)
32
MIPS
KVM_REG_MIPS_FPR_64(0..31)
64
MIPS
KVM_REG_MIPS_VEC_128(0..31)
128
MIPS
KVM_REG_MIPS_FCR_IR
32
MIPS
KVM_REG_MIPS_FCR_CSR
32
MIPS
KVM_REG_MIPS_MSA_IR
32
MIPS
KVM_REG_MIPS_MSA_CSR
32
ARM registers are mapped using the lower 32 bits. The upper 16 of that is the register group type, or coprocessor number
ARM core registers have the following id bit patterns
0x4020 0000 0010 <index into the kvm_regs struct:16>
ARM 32-bit CP15 registers have the following id bit patterns
0x4020 0000 000F <zero:1> <crn:4> <crm:4> <opc1:4> <opc2:3>
ARM 64-bit CP15 registers have the following id bit patterns
0x4030 0000 000F <zero:1> <zero:4> <crm:4> <opc1:4> <zero:3>
ARM CCSIDR registers are demultiplexed by CSSELR value
0x4020 0000 0011 00 <csselr:8>
ARM 32-bit VFP control registers have the following id bit patterns
0x4020 0000 0012 1 <regno:12>
ARM 64-bit FP registers have the following id bit patterns
0x4030 0000 0012 0 <regno:12>
ARM firmware pseudo-registers have the following bit pattern
0x4030 0000 0014 <regno:16>
arm64 registers are mapped using the lower 32 bits. The upper 16 of that is the register group type, or coprocessor number
arm64 core/FP-SIMD registers have the following id bit patterns. Note that the size of the access is variable, as the kvm_regs structure contains elements ranging from 32 to 128 bits. The index is a 32bit value in the kvm_regs structure seen as a 32bit array
0x60x0 0000 0010 <index into the kvm_regs struct:16>
Specifically
Encoding |
Register |
Bits |
kvm_regs member |
|---|---|---|---|
0x6030 0000 0010 0000 |
X0 |
64 |
regs.regs[0] |
0x6030 0000 0010 0002 |
X1 |
64 |
regs.regs[1] |
... |
|||
0x6030 0000 0010 003c |
X30 |
64 |
regs.regs[30] |
0x6030 0000 0010 003e |
SP |
64 |
regs.sp |
0x6030 0000 0010 0040 |
PC |
64 |
regs.pc |
0x6030 0000 0010 0042 |
PSTATE |
64 |
regs.pstate |
0x6030 0000 0010 0044 |
SP_EL1 |
64 |
sp_el1 |
0x6030 0000 0010 0046 |
ELR_EL1 |
64 |
elr_el1 |
0x6030 0000 0010 0048 |
SPSR_EL1 |
64 |
spsr[KVM_SPSR_EL1] (alias SPSR_SVC) |
0x6030 0000 0010 004a |
SPSR_ABT |
64 |
spsr[KVM_SPSR_ABT] |
0x6030 0000 0010 004c |
SPSR_UND |
64 |
spsr[KVM_SPSR_UND] |
0x6030 0000 0010 004e |
SPSR_IRQ |
64 |
spsr[KVM_SPSR_IRQ] |
0x6030 0000 0010 0050 |
SPSR_FIQ |
64 |
spsr[KVM_SPSR_FIQ] |
0x6040 0000 0010 0054 |
V0 |
128 |
fp_regs.vregs[0] [1] |
0x6040 0000 0010 0058 |
V1 |
128 |
fp_regs.vregs[1] [1] |
... |
|||
0x6040 0000 0010 00d0 |
V31 |
128 |
fp_regs.vregs[31] [1] |
0x6020 0000 0010 00d4 |
FPSR |
32 |
fp_regs.fpsr |
0x6020 0000 0010 00d5 |
FPCR |
32 |
fp_regs.fpcr |
arm64 CCSIDR registers are demultiplexed by CSSELR value
0x6020 0000 0011 00 <csselr:8>
arm64 system registers have the following id bit patterns
0x6030 0000 0013 <op0:2> <op1:3> <crn:4> <crm:4> <op2:3>
警告
Two system register IDs do not follow the specified pattern. These are KVM_REG_ARM_TIMER_CVAL and KVM_REG_ARM_TIMER_CNT, which map to system registers CNTV_CVAL_EL0 and CNTVCT_EL0 respectively. These two had their values accidentally swapped, which means TIMER_CVAL is derived from the register encoding for CNTVCT_EL0 and TIMER_CNT is derived from the register encoding for CNTV_CVAL_EL0. As this is API, it must remain this way.
arm64 firmware pseudo-registers have the following bit pattern
0x6030 0000 0014 <regno:16>
arm64 SVE registers have the following bit patterns
0x6080 0000 0015 00 <n:5> <slice:5> Zn bits[2048*slice + 2047 : 2048*slice]
0x6050 0000 0015 04 <n:4> <slice:5> Pn bits[256*slice + 255 : 256*slice]
0x6050 0000 0015 060 <slice:5> FFR bits[256*slice + 255 : 256*slice]
0x6060 0000 0015 ffff KVM_REG_ARM64_SVE_VLS pseudo-register
Access to register IDs where 2048 * slice >= 128 * max_vq will fail with ENOENT. max_vq is the vcpu’s maximum supported vector length in 128-bit quadwords: see [2] below.
These registers are only accessible on vcpus for which SVE is enabled. See KVM_ARM_VCPU_INIT for details.
In addition, except for KVM_REG_ARM64_SVE_VLS, these registers are not accessible until the vcpu’s SVE configuration has been finalized using KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE). See KVM_ARM_VCPU_INIT and KVM_ARM_VCPU_FINALIZE for more information about this procedure.
KVM_REG_ARM64_SVE_VLS is a pseudo-register that allows the set of vector lengths supported by the vcpu to be discovered and configured by userspace. When transferred to or from user memory via KVM_GET_ONE_REG or KVM_SET_ONE_REG, the value of this register is of type __u64[KVM_ARM64_SVE_VLS_WORDS], and encodes the set of vector lengths as follows
__u64 vector_lengths[KVM_ARM64_SVE_VLS_WORDS];
if (vq >= SVE_VQ_MIN && vq <= SVE_VQ_MAX &&
((vector_lengths[(vq - KVM_ARM64_SVE_VQ_MIN) / 64] >>
((vq - KVM_ARM64_SVE_VQ_MIN) % 64)) & 1))
/* Vector length vq * 16 bytes supported */
else
/* Vector length vq * 16 bytes not supported */
The maximum value vq for which the above condition is true is max_vq. This is the maximum vector length available to the guest on this vcpu, and determines which register slices are visible through this ioctl interface.
(See Scalable Vector Extension support for AArch64 Linux for an explanation of the “vq” nomenclature.)
KVM_REG_ARM64_SVE_VLS is only accessible after KVM_ARM_VCPU_INIT. KVM_ARM_VCPU_INIT initialises it to the best set of vector lengths that the host supports.
Userspace may subsequently modify it if desired until the vcpu’s SVE configuration is finalized using KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE).
Apart from simply removing all vector lengths from the host set that exceed some value, support for arbitrarily chosen sets of vector lengths is hardware-dependent and may not be available. Attempting to configure an invalid set of vector lengths via KVM_SET_ONE_REG will fail with EINVAL.
After the vcpu’s SVE configuration is finalized, further attempts to write this register will fail with EPERM.
arm64 bitmap feature firmware pseudo-registers have the following bit pattern
0x6030 0000 0016 <regno:16>
The bitmap feature firmware registers exposes the hypercall services that are available for userspace to configure. The set bits corresponds to the services that are available for the guests to access. By default, KVM sets all the supported bits during VM initialization. The userspace can discover the available services via KVM_GET_ONE_REG, and write back the bitmap corresponding to the features that it wishes guests to see via KVM_SET_ONE_REG.
Note: These registers are immutable once any of the vCPUs of the VM has run at least once. A KVM_SET_ONE_REG in such a scenario will return a -EBUSY to userspace.
(See KVM/arm64-specific hypercalls exposed to guests for more details.)
MIPS registers are mapped using the lower 32 bits. The upper 16 of that is the register group type
MIPS core registers (see above) have the following id bit patterns
0x7030 0000 0000 <reg:16>
MIPS CP0 registers (see KVM_REG_MIPS_CP0_* above) have the following id bit patterns depending on whether they’re 32-bit or 64-bit registers
0x7020 0000 0001 00 <reg:5> <sel:3> (32-bit)
0x7030 0000 0001 00 <reg:5> <sel:3> (64-bit)
Note: KVM_REG_MIPS_CP0_ENTRYLO0 and KVM_REG_MIPS_CP0_ENTRYLO1 are the MIPS64 versions of the EntryLo registers regardless of the word size of the host hardware, host kernel, guest, and whether XPA is present in the guest, i.e. with the RI and XI bits (if they exist) in bits 63 and 62 respectively, and the PFNX field starting at bit 30.
MIPS MAARs (see KVM_REG_MIPS_CP0_MAAR(*) above) have the following id bit patterns
0x7030 0000 0001 01 <reg:8>
MIPS KVM control registers (see above) have the following id bit patterns
0x7030 0000 0002 <reg:16>
MIPS FPU registers (see KVM_REG_MIPS_FPR_{32,64}() above) have the following id bit patterns depending on the size of the register being accessed. They are always accessed according to the current guest FPU mode (Status.FR and Config5.FRE), i.e. as the guest would see them, and they become unpredictable if the guest FPU mode is changed. MIPS SIMD Architecture (MSA) vector registers (see KVM_REG_MIPS_VEC_128() above) have similar patterns as they overlap the FPU registers
0x7020 0000 0003 00 <0:3> <reg:5> (32-bit FPU registers)
0x7030 0000 0003 00 <0:3> <reg:5> (64-bit FPU registers)
0x7040 0000 0003 00 <0:3> <reg:5> (128-bit MSA vector registers)
MIPS FPU control registers (see KVM_REG_MIPS_FCR_{IR,CSR} above) have the following id bit patterns
0x7020 0000 0003 01 <0:3> <reg:5>
MIPS MSA control registers (see KVM_REG_MIPS_MSA_{IR,CSR} above) have the following id bit patterns
0x7020 0000 0003 02 <0:3> <reg:5>
RISC-V registers are mapped using the lower 32 bits. The upper 8 bits of that is the register group type.
RISC-V config registers are meant for configuring a Guest VCPU and it has the following id bit patterns
0x8020 0000 01 <index into the kvm_riscv_config struct:24> (32bit Host)
0x8030 0000 01 <index into the kvm_riscv_config struct:24> (64bit Host)
Following are the RISC-V config registers
Encoding |
Register |
Description |
|---|---|---|
0x80x0 0000 0100 0000 |
isa |
ISA feature bitmap of Guest VCPU |
The isa config register can be read anytime but can only be written before a Guest VCPU runs. It will have ISA feature bits matching underlying host set by default.
RISC-V core registers represent the general execution state of a Guest VCPU and it has the following id bit patterns
0x8020 0000 02 <index into the kvm_riscv_core struct:24> (32bit Host)
0x8030 0000 02 <index into the kvm_riscv_core struct:24> (64bit Host)
Following are the RISC-V core registers
Encoding |
Register |
Description |
|---|---|---|
0x80x0 0000 0200 0000 |
regs.pc |
Program counter |
0x80x0 0000 0200 0001 |
regs.ra |
Return address |
0x80x0 0000 0200 0002 |
regs.sp |
Stack pointer |
0x80x0 0000 0200 0003 |
regs.gp |
Global pointer |
0x80x0 0000 0200 0004 |
regs.tp |
Task pointer |
0x80x0 0000 0200 0005 |
regs.t0 |
Caller saved register 0 |
0x80x0 0000 0200 0006 |
regs.t1 |
Caller saved register 1 |
0x80x0 0000 0200 0007 |
regs.t2 |
Caller saved register 2 |
0x80x0 0000 0200 0008 |
regs.s0 |
Callee saved register 0 |
0x80x0 0000 0200 0009 |
regs.s1 |
Callee saved register 1 |
0x80x0 0000 0200 000a |
regs.a0 |
Function argument (or return value) 0 |
0x80x0 0000 0200 000b |
regs.a1 |
Function argument (or return value) 1 |
0x80x0 0000 0200 000c |
regs.a2 |
Function argument 2 |
0x80x0 0000 0200 000d |
regs.a3 |
Function argument 3 |
0x80x0 0000 0200 000e |
regs.a4 |
Function argument 4 |
0x80x0 0000 0200 000f |
regs.a5 |
Function argument 5 |
0x80x0 0000 0200 0010 |
regs.a6 |
Function argument 6 |
0x80x0 0000 0200 0011 |
regs.a7 |
Function argument 7 |
0x80x0 0000 0200 0012 |
regs.s2 |
Callee saved register 2 |
0x80x0 0000 0200 0013 |
regs.s3 |
Callee saved register 3 |
0x80x0 0000 0200 0014 |
regs.s4 |
Callee saved register 4 |
0x80x0 0000 0200 0015 |
regs.s5 |
Callee saved register 5 |
0x80x0 0000 0200 0016 |
regs.s6 |
Callee saved register 6 |
0x80x0 0000 0200 0017 |
regs.s7 |
Callee saved register 7 |
0x80x0 0000 0200 0018 |
regs.s8 |
Callee saved register 8 |
0x80x0 0000 0200 0019 |
regs.s9 |
Callee saved register 9 |
0x80x0 0000 0200 001a |
regs.s10 |
Callee saved register 10 |
0x80x0 0000 0200 001b |
regs.s11 |
Callee saved register 11 |
0x80x0 0000 0200 001c |
regs.t3 |
Caller saved register 3 |
0x80x0 0000 0200 001d |
regs.t4 |
Caller saved register 4 |
0x80x0 0000 0200 001e |
regs.t5 |
Caller saved register 5 |
0x80x0 0000 0200 001f |
regs.t6 |
呼叫者儲存了暫存器 6 |
0x80x0 0000 0200 0020 |
mode |
許可權模式 (1 = S 模式或 0 = U 模式) |
RISC-V csr 暫存器代表 Guest VCPU 的監管者模式控制/狀態暫存器,它具有以下 ID 位模式
0x8020 0000 03 <index into the kvm_riscv_csr struct:24> (32bit Host)
0x8030 0000 03 <index into the kvm_riscv_csr struct:24> (64bit Host)
以下是 RISC-V csr 暫存器
Encoding |
Register |
Description |
|---|---|---|
0x80x0 0000 0300 0000 |
sstatus |
監管者狀態 |
0x80x0 0000 0300 0001 |
sie |
監管者中斷使能 |
0x80x0 0000 0300 0002 |
stvec |
監管者陷阱向量基址 |
0x80x0 0000 0300 0003 |
sscratch |
監管者暫存暫存器 |
0x80x0 0000 0300 0004 |
sepc |
監管者異常程式計數器 |
0x80x0 0000 0300 0005 |
scause |
監管者陷阱原因 |
0x80x0 0000 0300 0006 |
stval |
監管者錯誤地址或指令 |
0x80x0 0000 0300 0007 |
sip |
監管者中斷掛起 |
0x80x0 0000 0300 0008 |
satp |
監管者地址轉換和保護 |
RISC-V 定時器暫存器代表 Guest VCPU 的定時器狀態,它具有以下 ID 位模式
0x8030 0000 04 <index into the kvm_riscv_timer struct:24>
以下是 RISC-V 定時器暫存器
Encoding |
Register |
Description |
|---|---|---|
0x8030 0000 0400 0000 |
frequency |
時基頻率(只讀) |
0x8030 0000 0400 0001 |
time |
Guest 可見的時間值 |
0x8030 0000 0400 0002 |
compare |
Guest 程式設計的時間比較值 |
0x8030 0000 0400 0003 |
state |
時間比較狀態 (1 = ON 或 0 = OFF) |
RISC-V F 擴充套件暫存器代表 Guest VCPU 的單精度浮點狀態,它具有以下 ID 位模式
0x8020 0000 05 <index into the __riscv_f_ext_state struct:24>
以下是 RISC-V F 擴充套件暫存器
Encoding |
Register |
Description |
|---|---|---|
0x8020 0000 0500 0000 |
f[0] |
浮點暫存器 0 |
... |
||
0x8020 0000 0500 001f |
f[31] |
浮點暫存器 31 |
0x8020 0000 0500 0020 |
fcsr |
浮點控制和狀態暫存器 |
RISC-V D 擴充套件暫存器代表 Guest VCPU 的雙精度浮點狀態,它具有以下 ID 位模式
0x8020 0000 06 <index into the __riscv_d_ext_state struct:24> (fcsr)
0x8030 0000 06 <index into the __riscv_d_ext_state struct:24> (non-fcsr)
以下是 RISC-V D 擴充套件暫存器
Encoding |
Register |
Description |
|---|---|---|
0x8030 0000 0600 0000 |
f[0] |
浮點暫存器 0 |
... |
||
0x8030 0000 0600 001f |
f[31] |
浮點暫存器 31 |
0x8020 0000 0600 0020 |
fcsr |
浮點控制和狀態暫存器 |
LoongArch 暫存器使用低 32 位進行對映。 其中的高 16 位是暫存器組型別。
LoongArch csr 暫存器用於控制 guest cpu 或獲取 guest cpu 的狀態,它們具有以下 ID 位模式
0x9030 0000 0001 00 <reg:5> <sel:3> (64-bit)
LoongArch KVM 控制暫存器用於實現一些新定義的功能,例如設定 vcpu 計數器或重置 vcpu,它們具有以下 ID 位模式
0x9030 0000 0002 <reg:16>
4.69 KVM_GET_ONE_REG¶
- 功能:
KVM_CAP_ONE_REG
- 架構:
全部
- 型別:
vcpu ioctl
- 引數:
struct kvm_one_reg (輸入和輸出)
- 返回值:
成功時為 0,失敗時為負值
錯誤包括
ENOENT
沒有這樣的暫存器
EINVAL
無效的暫存器 ID,或者沒有這樣的暫存器,或者在 s390 上與受保護的虛擬化模式下的 VM 一起使用
EPERM
(arm64) 在 vcpu 完成之前不允許訪問暫存器
(這些錯誤程式碼僅供參考:不要依賴於在特定情況下返回特定錯誤程式碼。)
此 ioctl 允許接收 vcpu 中實現的單個暫存器的值。 要讀取的暫存器由傳入的 kvm_one_reg 結構的“id”欄位指示。 成功後,可以在“addr”指向的記憶體位置找到暫存器值。
使用此介面可訪問的暫存器列表與 4.68 中的列表相同。
4.70 KVM_KVMCLOCK_CTRL¶
- 功能:
KVM_CAP_KVMCLOCK_CTRL
- 架構:
任何實現 pvclocks 的 (目前僅限 x86)
- 型別:
vcpu ioctl
- 引數:
無
- 返回值:
成功時為 0,出錯時為 -1
此 ioctl 設定一個 guest 可訪問的標誌,指示指定的 vCPU 已被主機使用者空間暫停。
主機將在 pvclock 結構中設定一個標誌,該標誌從軟鎖死看門狗檢查。該標誌是 guest 和主機之間共享的 pvclock 結構的一部分,特別是 pvclock_vcpu_time_info 結構的 flags 欄位的第二位。它將僅由主機設定,並僅由 guest 讀取/清除。guest 檢查和清除標誌的操作必須是原子操作,因此必須使用 load-link/store-conditional 或等效項。guest 清除該標誌有兩種情況:當軟鎖死看門狗定時器重置自身或檢測到軟鎖死時。可以在暫停 vcpu 之後的任何時間呼叫此 ioctl,但在恢復 vcpu 之前。
4.71 KVM_SIGNAL_MSI¶
- 功能:
KVM_CAP_SIGNAL_MSI
- 架構:
x86 arm64
- 型別:
vm ioctl
- 引數:
struct kvm_msi (輸入)
- 返回值:
>0 表示傳遞成功,0 表示 guest 阻止了 MSI,-1 表示錯誤
直接注入 MSI 訊息。 僅在使用處理 MSI 訊息的核心 irqchip 時有效。
struct kvm_msi {
__u32 address_lo;
__u32 address_hi;
__u32 data;
__u32 flags;
__u32 devid;
__u8 pad[12];
};
- flags
KVM_MSI_VALID_DEVID:devid 包含有效值。 每個 VM 的 KVM_CAP_MSI_DEVID 功能會宣告提供裝置 ID 的要求。 如果此功能不可用,則使用者空間永遠不應設定 KVM_MSI_VALID_DEVID 標誌,因為 ioctl 可能會失敗。
如果設定了 KVM_MSI_VALID_DEVID,則 devid 包含寫入 MSI 訊息的裝置的唯一裝置識別符號。對於 PCI,這通常是低 16 位中的 BDF 識別符號。
在 x86 上,除非啟用了 KVM_CAP_X2APIC_API 功能的 KVM_X2APIC_API_USE_32BIT_IDS 功能,否則 address_hi 將被忽略。如果啟用了該功能,則 address_hi 的位 31-8 提供目標 id 的位 31-8。address_hi 的位 7-0 必須為零。
4.71 KVM_CREATE_PIT2¶
- 功能:
KVM_CAP_PIT2
- 架構:
x86
- 型別:
vm ioctl
- 引數:
struct kvm_pit_config (輸入)
- 返回值:
成功時為 0,出錯時為 -1
為 i8254 PIT 建立一個核心裝置模型。 僅在透過 KVM_CREATE_IRQCHIP 啟用核心 irqchip 支援後,此呼叫才有效。 必須傳遞以下引數
struct kvm_pit_config {
__u32 flags;
__u32 pad[15];
};
有效的標誌包括
#define KVM_PIT_SPEAKER_DUMMY 1 /* emulate speaker port stub */
PIT 定時器中斷可能會使用每個 VM 的核心執行緒進行注入。 如果存在,此執行緒將具有以下模式的名稱
kvm-pit/<owner-process-pid>
在執行具有較高優先順序的 guest 時,可能需要相應地調整此執行緒的排程引數。
此 IOCTL 替換了已過時的 KVM_CREATE_PIT。
4.72 KVM_GET_PIT2¶
- 功能:
KVM_CAP_PIT_STATE2
- 架構:
x86
- 型別:
vm ioctl
- 引數:
struct kvm_pit_state2 (輸出)
- 返回值:
成功時為 0,出錯時為 -1
檢索核心 PIT 模型的狀態。 僅在 KVM_CREATE_PIT2 之後有效。 該狀態在以下結構中返回
struct kvm_pit_state2 {
struct kvm_pit_channel_state channels[3];
__u32 flags;
__u32 reserved[9];
};
有效的標誌包括
/* disable PIT in HPET legacy mode */
#define KVM_PIT_FLAGS_HPET_LEGACY 0x00000001
/* speaker port data bit enabled */
#define KVM_PIT_FLAGS_SPEAKER_DATA_ON 0x00000002
此 IOCTL 替換了已過時的 KVM_GET_PIT。
4.73 KVM_SET_PIT2¶
- 功能:
KVM_CAP_PIT_STATE2
- 架構:
x86
- 型別:
vm ioctl
- 引數:
struct kvm_pit_state2 (輸入)
- 返回值:
成功時為 0,出錯時為 -1
設定核心 PIT 模型的狀態。 僅在 KVM_CREATE_PIT2 之後有效。 有關 struct kvm_pit_state2 的詳細資訊,請參閱 KVM_GET_PIT2。
此 IOCTL 替換了已過時的 KVM_SET_PIT。
4.74 KVM_PPC_GET_SMMU_INFO¶
- 功能:
KVM_CAP_PPC_GET_SMMU_INFO
- 架構:
powerpc
- 型別:
vm ioctl
- 引數:
無
- 返回值:
成功時為 0,出錯時為 -1
此操作會填充並返回一個結構,描述 KVM 支援的“伺服器”類 MMU 模擬的功能。 使用者空間可以反過來使用此結構來為 guest 作業系統生成適當的裝置樹屬性。
該結構包含一些全域性資訊,後跟一個支援的段頁面大小陣列
struct kvm_ppc_smmu_info {
__u64 flags;
__u32 slb_size;
__u32 pad;
struct kvm_ppc_one_seg_page_size sps[KVM_PPC_PAGE_SIZES_MAX_SZ];
};
支援的標誌包括
- KVM_PPC_PAGE_SIZES_REAL
設定該標誌後,guest 頁面大小必須“適合”後備儲存頁面大小。 如果未設定,則可以使用列表中的任何頁面大小,而不管它們如何由使用者空間支援。
- KVM_PPC_1T_SEGMENTS
除了標準的 256M 段之外,模擬的 MMU 還支援 1T 段。
- KVM_PPC_NO_HASH
此標誌指示 KVM 不支援 HPT guest,因此所有 guest 必須使用 radix MMU 模式。
“slb_size”欄位指示支援多少個 SLB 條目
“sps”陣列包含 8 個條目,指示段支援的基本頁面大小(按遞增順序)。 每個條目定義如下
struct kvm_ppc_one_seg_page_size {
__u32 page_shift; /* Base page shift of segment (or 0) */
__u32 slb_enc; /* SLB encoding for BookS */
struct kvm_ppc_one_page_size enc[KVM_PPC_PAGE_SIZES_MAX_SZ];
};
“page_shift”為 0 的條目未使用。 由於該陣列按遞增順序組織,因此在遇到此類條目時可以停止查詢。
“slb_enc”欄位提供用於 SLB 中頁面大小的編碼。 這些位位於這樣的位置,以便該值可以直接 OR 到 slbmte 指令的“vsid”引數中。
“enc”陣列是一個列表,對於每個段基本頁面大小,它都提供支援的實際頁面大小列表(這些大小隻能大於或等於基本頁面大小),以及雜湊 PTE 中相應的編碼。 同樣,該陣列是 8 個條目,按大小遞增排序,“0”移位的條目是空條目和終止符
struct kvm_ppc_one_page_size {
__u32 page_shift; /* Page shift (or 0) */
__u32 pte_enc; /* Encoding in the HPTE (>>12) */
};
“pte_enc”欄位提供一個可以 OR 到雜湊 PTE 的 RPN 欄位中的值(即,需要將其左移 12 位才能將其 OR 到雜湊 PTE 的第二個雙字中)。
4.75 KVM_IRQFD¶
- 功能:
KVM_CAP_IRQFD
- 架構:
x86 s390 arm64
- 型別:
vm ioctl
- 引數:
struct kvm_irqfd (輸入)
- 返回值:
成功時為 0,出錯時為 -1
允許設定 eventfd 以直接觸發 guest 中斷。 kvm_irqfd.fd 指定用作 eventfd 的檔案描述符,kvm_irqfd.gsi 指定由此事件切換的 irqchip 引腳。 當在 eventfd 上觸發事件時,會使用指定的 gsi 引腳將中斷注入到 guest 中。 使用 KVM_IRQFD_FLAG_DEASSIGN 標誌移除 irqfd,同時指定 kvm_irqfd.fd 和 kvm_irqfd.gsi。
使用 KVM_CAP_IRQFD_RESAMPLE,KVM_IRQFD 支援取消斷言和通知機制,從而允許模擬基於 irqfd 的電平觸發中斷。 設定 KVM_IRQFD_FLAG_RESAMPLE 後,使用者必須在 kvm_irqfd.resamplefd 欄位中傳遞一個額外的 eventfd。 在重取樣模式下執行,透過 kvm_irq.fd 釋出中斷會在 irqchip 中斷言指定的 gsi。 當重取樣 irqchip 時(例如從 EOI),將取消斷言 gsi,並透過 kvm_irqfd.resamplefd 通知使用者。 使用者有責任在使用它的裝置仍然需要服務時重新排隊中斷。 請注意,關閉 resamplefd 不足以停用 irqfd。 KVM_IRQFD_FLAG_RESAMPLE 僅在分配時是必需的,不需要使用 KVM_IRQFD_FLAG_DEASSIGN 指定。
在 arm64 上,在支援 gsi 路由的情況下,可能會發生以下情況
如果沒有任何路由條目與此 gsi 關聯,則注入失敗
如果 gsi 與 irqchip 路由條目關聯,則 irqchip.pin + 32 對應於注入的 SPI ID。
如果 gsi 與 MSI 路由條目關聯,則 MSI 訊息和裝置 ID 將轉換為 LPI(支援僅限於核心模擬的 GICv3 ITS)。
4.76 KVM_PPC_ALLOCATE_HTAB¶
- 功能:
KVM_CAP_PPC_ALLOC_HTAB
- 架構:
powerpc
- 型別:
vm ioctl
- 引數:
指向包含雜湊表順序的 u32 的指標(輸入/輸出)
- 返回值:
成功時為 0,出錯時為 -1
這會請求主機核心使用 PAPR 半虛擬化介面為 guest 分配 MMU 雜湊表。 僅當核心配置為使用 Book 3S HV 樣式的虛擬化時,此操作才會執行任何操作。 否則,該功能不存在,ioctl 返回 ENOTTY 錯誤。 此說明的其餘部分假定為 Book 3S HV。
呼叫此 ioctl 時不得有任何 vcpu 正在執行; 如果有,它將不執行任何操作並返回 EBUSY 錯誤。
該引數是指向 32 位無符號整數變數的指標,該變數包含雜湊表所需大小的順序(以 2 為底的對數),該順序必須介於 18 和 46 之間。從 ioctl 成功返回時,核心不會更改該值。
如果在請求任何 vcpu 執行時(使用 KVM_RUN ioctl)尚未分配任何雜湊表,則主機核心將分配一個預設大小的雜湊表 (16 MB)。
如果在已分配雜湊表的情況下呼叫此 ioctl,且其順序與現有雜湊表的順序不同,則會釋放現有雜湊表並分配一個新的雜湊表。 如果在已分配的雜湊表與指定的順序相同的情況下呼叫此 ioctl,則核心將清除現有雜湊表(將所有 HPTE 置零)。 在任一情況下,如果 guest 正在使用虛擬化真實模式區域 (VRMA) 功能,則核心將在任何 vcpu 的下一個 KVM_RUN 上重新建立 VMRA HPTE。
4.77 KVM_S390_INTERRUPT¶
- 功能:
基本
- 架構:
s390
- 型別:
vm ioctl、vcpu ioctl
- 引數:
struct kvm_s390_interrupt (輸入)
- 返回值:
成功時為 0,出錯時為 -1
允許將中斷注入到 guest 中。 中斷可以是浮動的(vm ioctl)或每個 cpu 的(vcpu ioctl),具體取決於中斷型別。
中斷引數透過 kvm_s390_interrupt 傳遞
struct kvm_s390_interrupt {
__u32 type;
__u32 parm;
__u64 parm64;
};
type 可以是以下之一
- KVM_S390_SIGP_STOP (vcpu)
sigp 停止; parm 中的可選標誌
- KVM_S390_PROGRAM_INT (vcpu)
程式檢查; parm 中的程式碼
- KVM_S390_SIGP_SET_PREFIX (vcpu)
sigp 設定字首; parm 中的字首地址
- KVM_S390_RESTART (vcpu)
重新啟動
- KVM_S390_INT_CLOCK_COMP (vcpu)
時鐘比較器中斷
- KVM_S390_INT_CPU_TIMER (vcpu)
CPU 定時器中斷
- KVM_S390_INT_VIRTIO (vm)
virtio 外部中斷; parm 和 parm64 中的外部中斷引數
- KVM_S390_INT_SERVICE (vm)
sclp 外部中斷; parm 中的 sclp 引數
- KVM_S390_INT_EMERGENCY (vcpu)
sigp 緊急情況; parm 中的源 cpu
- KVM_S390_INT_EXTERNAL_CALL (vcpu)
sigp 外部呼叫; parm 中的源 cpu
- KVM_S390_INT_IO(ai,cssid,ssid,schid) (vm)
用於指示 I/O 中斷的複合值(ai - 介面卡中斷; cssid,ssid,schid - 子通道); parm(子通道)和 parm64(intparm,中斷子類)中的 I/O 中斷引數
- KVM_S390_MCHK (vm, vcpu)
機器檢查中斷; parm 中的 cr 14 位,parm64 中的機器檢查中斷程式碼(請注意,此 ioctl 不支援需要其他有效負載的機器檢查)
這是一個非同步 vcpu ioctl,可以從任何執行緒呼叫。
4.78 KVM_PPC_GET_HTAB_FD¶
- 功能:
KVM_CAP_PPC_HTAB_FD
- 架構:
powerpc
- 型別:
vm ioctl
- 引數:
指向 struct kvm_get_htab_fd 的指標(輸入)
- 返回值:
成功時返回檔案描述符號 (>= 0),錯誤時返回 -1
這將返回一個檔案描述符,該檔案描述符可用於讀取 guest 的雜湊頁面表 (HPT) 中的條目,或寫入條目以初始化 HPT。 僅當引數的標誌欄位中設定了 KVM_GET_HTAB_WRITE 位時,才能寫入返回的 fd,並且僅當該位為清除狀態時,才能讀取該 fd。 引數結構如下所示
/* For KVM_PPC_GET_HTAB_FD */
struct kvm_get_htab_fd {
__u64 flags;
__u64 start_index;
__u64 reserved[2];
};
/* Values for kvm_get_htab_fd.flags */
#define KVM_GET_HTAB_BOLTED_ONLY ((__u64)0x1)
#define KVM_GET_HTAB_WRITE ((__u64)0x2)
“start_index”欄位給出了 HPT 中要開始讀取的條目的索引。 寫入時會忽略該欄位。
fd 上的讀取最初將提供有關所有“有趣的”HPT 條目的資訊。 如果設定了 KVM_GET_HTAB_BOLTED_ONLY 位,則有趣的條目是設定了固定位的條目,否則為所有條目。 到達 HPT 結尾時,read() 將返回。 如果再次在 fd 上呼叫 read(),它將從 HPT 的開頭再次開始,但只會返回自上次讀取以來已更改的 HPT 條目。
讀取或寫入的資料結構是一個標頭(8 個位元組),後跟一系列有效的 HPT 條目(每個條目 16 個位元組)。 標頭指示有多少個有效的 HPT 條目,以及有多少個無效條目位於有效條目之後。 無效條目未在流中顯式表示。 標頭格式為
struct kvm_get_htab_header {
__u32 index;
__u16 n_valid;
__u16 n_invalid;
};
寫入 fd 會建立從標頭中給出的索引開始的 HPT 條目; 首先,帶有寫入資料內容的“n_valid”有效條目,然後是“n_invalid”無效條目,使先前找到的任何有效條目無效。
4.79 KVM_CREATE_DEVICE¶
- 功能:
KVM_CAP_DEVICE_CTRL
- 架構:
全部
- 型別:
vm ioctl
- 引數:
struct kvm_create_device (輸入/輸出)
- 返回值:
成功時為 0,出錯時為 -1
錯誤
ENODEV
裝置型別未知或不受支援
EEXIST
裝置已建立,並且無法多次例項化此型別的裝置
其他錯誤條件可能由各個裝置型別定義或具有其標準含義。
在核心中建立一個模擬裝置。 fd 中返回的檔案描述符可以與 KVM_SET/GET/HAS_DEVICE_ATTR 一起使用。
如果設定了 KVM_CREATE_DEVICE_TEST 標誌,則僅測試裝置型別是否受支援(不一定是在當前 vm 中是否可以建立)。
各個裝置不應定義標誌。 屬性應該用於指定任何未由裝置型別編號暗示的行為。
struct kvm_create_device {
__u32 type; /* in: KVM_DEV_TYPE_xxx */
__u32 fd; /* out: device handle */
__u32 flags; /* in: KVM_CREATE_DEVICE_xxx */
};
4.80 KVM_SET_DEVICE_ATTR/KVM_GET_DEVICE_ATTR¶
- 功能:
KVM_CAP_DEVICE_CTRL、KVM_CAP_VM_ATTRIBUTES(用於 vm 裝置)、KVM_CAP_VCPU_ATTRIBUTES(用於 vcpu 裝置)、KVM_CAP_SYS_ATTRIBUTES(用於系統 (/dev/kvm) 裝置)(無設定)
- 架構:
x86, arm64, s390
- 型別:
device ioctl、vm ioctl、vcpu ioctl
- 引數:
struct kvm_device_attr
- 返回值:
成功時為 0,出錯時為 -1
錯誤
ENXIO
此裝置組或屬性未知/不受支援,或者缺少硬體支援。
EPERM
當前無法以這種方式訪問該屬性(例如,只讀屬性,或僅當裝置處於不同狀態時才有意義的屬性)
其他錯誤條件可能由各個裝置型別定義。
獲取/設定指定的裝置配置和/或狀態。 語義特定於裝置。 請參閱“裝置”目錄中的各個裝置文件。 與 ONE_REG 一樣,傳輸的資料大小由特定屬性定義。
struct kvm_device_attr {
__u32 flags; /* no flags currently defined */
__u32 group; /* device-defined */
__u64 attr; /* group-defined */
__u64 addr; /* userspace address of attr data */
};
4.81 KVM_HAS_DEVICE_ATTR¶
- 功能:
KVM_CAP_DEVICE_CTRL、KVM_CAP_VM_ATTRIBUTES(用於 vm 裝置)、KVM_CAP_VCPU_ATTRIBUTES(用於 vcpu 裝置)、KVM_CAP_SYS_ATTRIBUTES(用於系統 (/dev/kvm) 裝置)
- 型別:
device ioctl、vm ioctl、vcpu ioctl
- 引數:
struct kvm_device_attr
- 返回值:
成功時為 0,出錯時為 -1
錯誤
ENXIO
此裝置組或屬性未知/不受支援,或者缺少硬體支援。
測試裝置是否支援特定屬性。 成功返回表示已實現該屬性。 它不一定表示可以在裝置的當前狀態下讀取或寫入該屬性。 “addr”將被忽略。
4.82 KVM_ARM_VCPU_INIT¶
- 功能:
基本
- 架構:
arm64
- 型別:
vcpu ioctl
- 引數:
struct kvm_vcpu_init (輸入)
- 返回值:
成功時為 0;出錯時為 -1
錯誤
EINVAL
目標未知,或者功能組合無效。
ENOENT
指定的功能位未知。
這會告知 KVM 要向 guest 呈現的 CPU 型別,以及它應具有哪些可選功能。 這將導致 CPU 暫存器重置為其初始值。 如果未呼叫此方法,KVM_RUN 將為該 vcpu 返回 ENOEXEC。
- 初始值定義為
- 處理器狀態
AArch64:設定了 EL1h、D、A、I 和 F 位。 所有其他位均已清除。
AArch32:設定了 SVC、A、I 和 F 位。 所有其他位均已清除。
通用暫存器,包括 PC 和 SP:設定為 0
FPSIMD/NEON 暫存器:設定為 0
SVE 暫存器:設定為 0
系統暫存器:重置為其架構定義的 EL1(resp. SVC)或 EL2(在啟用 EL2 的情況下)的暖重置值。
請注意,由於某些暫存器反映了機器拓撲,因此應在呼叫此 ioctl 之前建立所有 vcpu。
對於給定的 vcpu,使用者空間可以多次呼叫此函式,包括在 vcpu 執行之後。 這會將 vcpu 重置為其初始狀態。 初始呼叫之後的對此函式的所有呼叫都必須使用相同的目標和相同的功能標誌集,否則將返回 EINVAL。
可能的功能
KVM_ARM_VCPU_POWER_OFF:以斷電狀態啟動 CPU。 依賴於 KVM_CAP_ARM_PSCI。 如果未設定,則 CPU 將在呼叫 KVM_RUN 時通電並執行 guest 程式碼。
KVM_ARM_VCPU_EL1_32BIT:以 32 位模式啟動 CPU。 依賴於 KVM_CAP_ARM_EL1_32BIT(僅限 arm64)。
KVM_ARM_VCPU_PSCI_0_2:為 CPU 模擬 PSCI v0.2(或與 v0.2 向後相容的未來版本)。 依賴於 KVM_CAP_ARM_PSCI_0_2。
KVM_ARM_VCPU_PMU_V3:為 CPU 模擬 PMUv3。 依賴於 KVM_CAP_ARM_PMU_V3。
KVM_ARM_VCPU_PTRAUTH_ADDRESS:僅為 arm64 啟用地址指標身份驗證。 依賴於 KVM_CAP_ARM_PTRAUTH_ADDRESS。 如果同時存在 KVM_CAP_ARM_PTRAUTH_ADDRESS 和 KVM_CAP_ARM_PTRAUTH_GENERIC,則必須請求 KVM_ARM_VCPU_PTRAUTH_ADDRESS 和 KVM_ARM_VCPU_PTRAUTH_GENERIC,或者兩者都不請求。
KVM_ARM_VCPU_PTRAUTH_GENERIC:僅為 arm64 啟用通用指標身份驗證。 依賴於 KVM_CAP_ARM_PTRAUTH_GENERIC。 如果同時存在 KVM_CAP_ARM_PTRAUTH_ADDRESS 和 KVM_CAP_ARM_PTRAUTH_GENERIC,則必須請求 KVM_ARM_VCPU_PTRAUTH_ADDRESS 和 KVM_ARM_VCPU_PTRAUTH_GENERIC,或者兩者都不請求。
KVM_ARM_VCPU_SVE:為 CPU 啟用 SVE(僅限 arm64)。 依賴於 KVM_CAP_ARM_SVE。 需要 KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE)
在 KVM_ARM_VCPU_INIT 之後
可以使用 KVM_GET_ONE_REG 讀取 KVM_REG_ARM64_SVE_VLS:此偽暫存器的初始值指示此主機上 vcpu 可能的最佳向量長度集。
在 KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE) 之前
KVM_RUN 和 KVM_GET_REG_LIST 不可用;
KVM_GET_ONE_REG 和 KVM_SET_ONE_REG 不能用於訪問可縮放的架構 SVE 暫存器 KVM_REG_ARM64_SVE_ZREG()、KVM_REG_ARM64_SVE_PREG() 或 KVM_REG_ARM64_SVE_FFR;
可以選擇使用 KVM_SET_ONE_REG 寫入 KVM_REG_ARM64_SVE_VLS,以修改 vcpu 可用的向量長度集。
在 KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE) 之後
KVM_REG_ARM64_SVE_VLS 偽暫存器是不可變的,不能再使用 KVM_SET_ONE_REG 寫入。
KVM_ARM_VCPU_HAS_EL2:啟用巢狀虛擬化支援,從 EL2 而不是 EL1 啟動客戶機。依賴於 KVM_CAP_ARM_EL2。虛擬機器在 HCR_EL2.E2H 為 RES1 (VHE) 的情況下執行,除非同時設定了 KVM_ARM_VCPU_HAS_EL2_E2H0。
KVM_ARM_VCPU_HAS_EL2_E2H0:將巢狀虛擬化支援限制為 HCR_EL2.E2H 為 RES0(非 VHE)。依賴於 KVM_CAP_ARM_EL2_E2H0。還必須設定 KVM_ARM_VCPU_HAS_EL2。
4.83 KVM_ARM_PREFERRED_TARGET¶
- 功能:
基本
- 架構:
arm64
- 型別:
vm ioctl
- 引數:
struct kvm_vcpu_init (輸出)
- 返回值:
成功時為 0;出錯時為 -1
錯誤
ENODEV
主機沒有可用的首選目標
此呼叫向 KVM 查詢主機上 KVM 可以模擬的首選 CPU 目標型別。
該 ioctl 返回 struct kvm_vcpu_init 例項,其中包含有關首選 CPU 目標型別及其建議功能的資訊。如果首選目標建議設定這些功能,則返回的 kvm_vcpu_init->features 點陣圖將設定功能位,但這不是強制性的。
此 ioctl 返回的資訊可用於準備 struct kvm_vcpu_init 例項,以用於 KVM_ARM_VCPU_INIT ioctl,這將導致 VCPU 與底層主機匹配。
4.84 KVM_GET_REG_LIST¶
- 功能:
基本
- 架構:
arm64, mips, riscv
- 型別:
vcpu ioctl
- 引數:
struct kvm_reg_list (輸入/輸出)
- 返回值:
成功時為 0;出錯時為 -1
錯誤
E2BIG
reg 索引列表太大,無法放入使用者指定的陣列中(所需的數字將寫入 n 中)。
struct kvm_reg_list {
__u64 n; /* number of registers in reg[] */
__u64 reg[0];
};
此 ioctl 返回 KVM_GET_ONE_REG/KVM_SET_ONE_REG 呼叫支援的客戶機暫存器。
請注意,由於歷史原因,s390 不支援 KVM_GET_REG_LIST(讀取:沒人關心)。核心 4.x 及更新版本中的暫存器集是
KVM_REG_S390_TODPR
KVM_REG_S390_EPOCHDIFF
KVM_REG_S390_CPU_TIMER
KVM_REG_S390_CLOCK_COMP
KVM_REG_S390_PFTOKEN
KVM_REG_S390_PFCOMPARE
KVM_REG_S390_PFSELECT
KVM_REG_S390_PP
KVM_REG_S390_GBEA
4.85 KVM_ARM_SET_DEVICE_ADDR (已棄用)¶
- 功能:
KVM_CAP_ARM_SET_DEVICE_ADDR
- 架構:
arm64
- 型別:
vm ioctl
- 引數:
struct kvm_arm_device_address (輸入)
- 返回值:
成功時為 0,出錯時為 -1
錯誤
ENODEV
裝置 ID 未知
ENXIO
當前系統不支援該裝置
EEXIST
地址已設定
E2BIG
地址位於客戶機物理地址空間之外
EBUSY
地址與其他裝置範圍重疊
struct kvm_arm_device_addr {
__u64 id;
__u64 addr;
};
在客戶機的物理地址空間中指定一個裝置地址,客戶機可以在該地址訪問模擬或直接公開的裝置,主機核心需要了解這些裝置。id 欄位是特定於架構的特定裝置的識別符號。
arm64 將 id 欄位分為兩個部分,一個是裝置 ID,另一個是特定於各個裝置的地址型別 ID
bits: | 63 ... 32 | 31 ... 16 | 15 ... 0 |
field: | 0x00000000 | device id | addr type id |
arm64 當前僅在使用核心 GIC 支援硬體 VGIC 功能時才需要這樣做,使用 KVM_ARM_DEVICE_VGIC_V2 作為裝置 ID。在為客戶機對映 VGIC 虛擬 CPU 和分配器介面設定基地址時,必須在呼叫 KVM_CREATE_IRQCHIP 之後,但在任何 VCPU 上呼叫 KVM_RUN 之前呼叫 ioctl。對於任何基地址,呼叫此 ioctl 兩次將返回 -EEXIST。
請注意,此 IOCTL 已棄用,應改用更靈活的 SET/GET_DEVICE_ATTR API。
4.86 KVM_PPC_RTAS_DEFINE_TOKEN¶
- 功能:
KVM_CAP_PPC_RTAS
- 架構:
ppc
- 型別:
vm ioctl
- 引數:
struct kvm_rtas_token_args
- 返回值:
成功時為 0,出錯時為 -1
為 RTAS(執行時抽象服務)服務定義一個令牌值,以便允許在核心中處理它。引數結構提供服務的名稱,該名稱必須是具有核心端實現的服務名稱。如果令牌值非零,則它將與該服務關聯,並且客戶機後續對指定該令牌的 RTAS 呼叫將由核心處理。如果令牌值為 0,則將忘記與該服務關聯的任何令牌,並且客戶機後續對該服務的 RTAS 呼叫將傳遞到使用者空間進行處理。
4.87 KVM_SET_GUEST_DEBUG¶
- 功能:
KVM_CAP_SET_GUEST_DEBUG
- 架構:
x86, s390, ppc, arm64
- 型別:
vcpu ioctl
- 引數:
struct kvm_guest_debug (輸入)
- 返回值:
成功時為 0;出錯時為 -1
struct kvm_guest_debug {
__u32 control;
__u32 pad;
struct kvm_guest_debug_arch arch;
};
設定特定於處理器的除錯暫存器,並將 vcpu 配置為處理客戶機除錯事件。該結構有兩個部分,第一部分是一個控制位欄位,指示執行時要處理的除錯事件型別。常見的控制位包括
KVM_GUESTDBG_ENABLE:啟用客戶機除錯
KVM_GUESTDBG_SINGLESTEP:下一次執行應單步執行
控制欄位的前 16 位是特定於架構的控制標誌,可以包括以下內容
KVM_GUESTDBG_USE_SW_BP:使用軟體斷點 [x86, arm64]
KVM_GUESTDBG_USE_HW_BP:使用硬體斷點 [x86, s390]
KVM_GUESTDBG_USE_HW:使用硬體除錯事件 [arm64]
KVM_GUESTDBG_INJECT_DB:注入 DB 型別異常 [x86]
KVM_GUESTDBG_INJECT_BP:注入 BP 型別異常 [x86]
KVM_GUESTDBG_EXIT_PENDING:觸發立即客戶機退出 [s390]
KVM_GUESTDBG_BLOCKIRQ:避免注入中斷/NMI/SMI [x86]
例如,KVM_GUESTDBG_USE_SW_BP 指示在記憶體中啟用了軟體斷點,因此我們需要確保正確捕獲斷點異常,並且 KVM 執行迴圈在斷點處退出,而不是執行到正常的客戶機向量中。對於 KVM_GUESTDBG_USE_HW_BP,我們需要確保客戶機 vCPU 的特定於架構的暫存器已更新為正確(提供)的值。
該結構的第二部分是特定於架構的,通常包含一組除錯暫存器。
對於 arm64,除錯暫存器的數量由實現定義,可以透過查詢 KVM_CAP_GUEST_DEBUG_HW_BPS 和 KVM_CAP_GUEST_DEBUG_HW_WPS 功能來確定,這些功能返回一個正數,指示支援的暫存器數量。
對於 ppc,KVM_CAP_PPC_GUEST_DEBUG_SSTEP 功能指示是否支援單步除錯事件 (KVM_GUESTDBG_SINGLESTEP)。
同樣,在支援時,KVM_CAP_SET_GUEST_DEBUG2 功能指示控制欄位中支援的 KVM_GUESTDBG_* 位。
當除錯事件以原因 KVM_EXIT_DEBUG 退出主執行迴圈時,kvm_run 結構的 kvm_debug_exit_arch 部分包含特定於架構的除錯資訊。
4.88 KVM_GET_EMULATED_CPUID¶
- 功能:
KVM_CAP_EXT_EMUL_CPUID
- 架構:
x86
- 型別:
系統 ioctl
- 引數:
struct kvm_cpuid2 (in/out)
- 返回值:
成功時為 0,出錯時為 -1
struct kvm_cpuid2 {
__u32 nent;
__u32 flags;
struct kvm_cpuid_entry2 entries[0];
};
成員“flags”用於從使用者空間傳遞標誌。
#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX BIT(0)
#define KVM_CPUID_FLAG_STATEFUL_FUNC BIT(1) /* deprecated */
#define KVM_CPUID_FLAG_STATE_READ_NEXT BIT(2) /* deprecated */
struct kvm_cpuid_entry2 {
__u32 function;
__u32 index;
__u32 flags;
__u32 eax;
__u32 ebx;
__u32 ecx;
__u32 edx;
__u32 padding[3];
};
此 ioctl 返回 kvm 模擬的 x86 cpuid 功能。使用者空間可以使用此 ioctl 返回的資訊來查詢 kvm 模擬哪些功能,而不是本機存在哪些功能。
使用者空間透過傳遞一個 kvm_cpuid2 結構來呼叫 KVM_GET_EMULATED_CPUID,其中“nent”欄位指示可變大小陣列“entries”中的條目數。如果條目數太低而無法描述 cpu 功能,則返回錯誤 (E2BIG)。如果數量過高,則調整“nent”欄位並返回錯誤 (ENOMEM)。如果數量正好,則將“nent”欄位調整為“entries”陣列中有效條目的數量,然後填充該陣列。
返回的條目是 kvm 模擬的各個功能的 CPUID 位集,如 CPUID 指令返回的那樣,清除未知或不支援的功能位。
例如,像 x2apic 這樣的功能可能不存在於主機 cpu 中,但在 KVM_GET_SUPPORTED_CPUID 中由 kvm 公開,因為它們可以被有效地模擬,因此不包括在此處。
每個條目中的欄位定義如下
- function
用於獲取條目的 eax 值
- index
用於獲取條目的 ecx 值(對於受 ecx 影響的條目)
- flags
以下零個或多個的 OR
- KVM_CPUID_FLAG_SIGNIFCANT_INDEX
如果索引欄位有效
eax, ebx, ecx, edx
cpuid 指令為此 function/index 組合返回的值
4.89 KVM_S390_MEM_OP¶
- 功能:
KVM_CAP_S390_MEM_OP, KVM_CAP_S390_PROTECTED, KVM_CAP_S390_MEM_OP_EXTENSION
- 架構:
s390
- 型別:
vm ioctl、vcpu ioctl
- 引數:
struct kvm_s390_mem_op (輸入)
- 返回值:
= 0 表示成功,< 0 表示一般錯誤(例如 -EFAULT 或 -ENOMEM),如果訪問導致此類異常,則為 16 位程式異常程式碼
從/向虛擬機器的記憶體讀取或寫入資料。KVM_CAP_S390_MEM_OP_EXTENSION 功能指定支援哪些功能。
引數透過以下結構指定
struct kvm_s390_mem_op {
__u64 gaddr; /* the guest address */
__u64 flags; /* flags */
__u32 size; /* amount of bytes */
__u32 op; /* type of operation */
__u64 buf; /* buffer in userspace */
union {
struct {
__u8 ar; /* the access register number */
__u8 key; /* access key, ignored if flag unset */
__u8 pad1[6]; /* ignored */
__u64 old_addr; /* ignored if flag unset */
};
__u32 sida_offset; /* offset into the sida */
__u8 reserved[32]; /* ignored */
};
};
記憶體區域的起始地址必須在“gaddr”欄位中指定,區域的長度必須在“size”欄位中指定(不能為 0)。“size”的最大值可以透過檢查 KVM_CAP_S390_MEM_OP 功能獲得。“buf”是使用者空間應用程式提供的緩衝區,讀取訪問時,讀取的資料應寫入其中;寫入訪問時,應寫入的資料儲存在該緩衝區中。“reserved”欄位用於將來的擴充套件。保留和未使用的值將被忽略。新增成員的未來擴充套件必須引入新的標誌。
操作型別在“op”欄位中指定。修改其行為的標誌可以在“flags”欄位中設定。未定義的標誌位必須設定為 0。
- 可能的操作包括
KVM_S390_MEMOP_LOGICAL_READKVM_S390_MEMOP_LOGICAL_WRITEKVM_S390_MEMOP_ABSOLUTE_READKVM_S390_MEMOP_ABSOLUTE_WRITEKVM_S390_MEMOP_SIDA_READKVM_S390_MEMOP_SIDA_WRITEKVM_S390_MEMOP_ABSOLUTE_CMPXCHG
邏輯讀取/寫入:¶
訪問邏輯記憶體,即,給定 VCPU 的狀態,將給定的客戶機地址轉換為絕對地址,並將絕對地址用作訪問的目標。“ar”指定要使用的訪問暫存器號;有效範圍是 0..15。邏輯訪問僅允許用於 VCPU ioctl。邏輯訪問僅允許用於非保護客戶機。
- 支援的標誌
KVM_S390_MEMOP_F_CHECK_ONLYKVM_S390_MEMOP_F_INJECT_EXCEPTIONKVM_S390_MEMOP_F_SKEY_PROTECTION
可以設定 KVM_S390_MEMOP_F_CHECK_ONLY 標誌來檢查相應的記憶體訪問是否會導致訪問異常;但是,不會對目標記憶體中的資料執行實際訪問。在這種情況下,“buf”未使用,可以為 NULL。
如果在訪問期間發生訪問異常(或在 KVM_S390_MEMOP_F_CHECK_ONLY 的情況下會發生),則 ioctl 返回一個正錯誤號,指示異常型別。如果設定了標誌 KVM_S390_MEMOP_F_INJECT_EXCEPTION,則此異常也會直接在相應的 VCPU 上引發。對於保護異常,除非另有說明,否則注入的轉換異常識別符號 (TEID) 指示抑制。
如果設定了 KVM_S390_MEMOP_F_SKEY_PROTECTION 標誌,則儲存鍵保護也生效,如果給定“key”指定的訪問鍵,禁止訪問,則可能會導致異常;有效範圍是 0..15。如果 KVM_CAP_S390_MEM_OP_EXTENSION > 0,則 KVM_S390_MEMOP_F_SKEY_PROTECTION 可用。由於訪問的記憶體可能跨越多個頁面,並且這些頁面可能具有不同的儲存鍵,因此有可能在修改記憶體後發生保護異常。在這種情況下,如果注入異常,則 TEID 不指示抑制。
絕對讀取/寫入:¶
訪問絕對記憶體。此操作旨在與 KVM_S390_MEMOP_F_SKEY_PROTECTION 標誌一起使用,以允許訪問記憶體並執行儲存鍵保護所需的檢查作為一項操作(而不是使用者空間獲取儲存鍵、執行檢查,然後在之後訪問記憶體,這可能會導致檢查和訪問之間存在延遲)。如果 KVM_CAP_S390_MEM_OP_EXTENSION 具有 KVM_S390_MEMOP_EXTENSION_CAP_BASE 位集,則 VM ioctl 允許絕對訪問。當前,VCPU ioctl 不允許絕對訪問。絕對訪問僅允許用於非保護客戶機。
- 支援的標誌
KVM_S390_MEMOP_F_CHECK_ONLYKVM_S390_MEMOP_F_SKEY_PROTECTION
與邏輯訪問共享的標誌的語義與邏輯訪問的語義相同。
絕對 cmpxchg:¶
在絕對客戶機記憶體上執行 cmpxchg。旨在與 KVM_S390_MEMOP_F_SKEY_PROTECTION 標誌一起使用。訪問僅在目標位置包含“old_addr”指向的值時才會發生,而不是進行無條件寫入。這是作為長度由“size”引數指定的原子 cmpxchg 執行的。“size”必須是 2 的冪,最大為 16。如果由於目標值與舊值不匹配而未發生交換,則“old_addr”指向的值將替換為目標值。使用者空間可以透過檢查是否發生此替換來判斷是否發生了交換。如果 KVM_CAP_S390_MEM_OP_EXTENSION 具有標誌 KVM_S390_MEMOP_EXTENSION_CAP_CMPXCHG 集,則 VM ioctl 允許 cmpxchg op。
- 支援的標誌
KVM_S390_MEMOP_F_SKEY_PROTECTION
SIDA 讀取/寫入:¶
訪問安全指令資料區域,該區域包含受保護客戶機指令模擬所需的記憶體運算元。如果 KVM_CAP_S390_PROTECTED 功能可用,則 SIDA 訪問可用。SIDA 訪問僅允許用於 VCPU ioctl。SIDA 訪問僅允許用於受保護客戶機。
不支援任何標誌。
4.90 KVM_S390_GET_SKEYS¶
- 功能:
KVM_CAP_S390_SKEYS
- 架構:
s390
- 型別:
vm ioctl
- 引數:
struct kvm_s390_skeys
- 返回值:
成功時為 0,如果客戶機未使用儲存鍵,則為 KVM_S390_GET_SKEYS_NONE,出錯時為負值
此 ioctl 用於獲取 s390 架構上的客戶機儲存鍵值。該 ioctl 透過 kvm_s390_skeys 結構獲取引數
struct kvm_s390_skeys {
__u64 start_gfn;
__u64 count;
__u64 skeydata_addr;
__u32 flags;
__u32 reserved[9];
};
start_gfn 欄位是您要獲取其儲存鍵的第一個客戶機幀的編號。
count 欄位是要獲取其儲存鍵的連續幀的數量(從 start_gfn 開始)。count 欄位必須至少為 1,允許的最大值定義為 KVM_S390_SKEYS_MAX。超出此範圍的值將導致 ioctl 返回 -EINVAL。
skeydata_addr 欄位是指向一個足夠大的緩衝區地址,該緩衝區可以容納 count 位元組。ioctl 將使用儲存鍵資料填充此緩衝區。
4.91 KVM_S390_SET_SKEYS¶
- 功能:
KVM_CAP_S390_SKEYS
- 架構:
s390
- 型別:
vm ioctl
- 引數:
struct kvm_s390_skeys
- 返回值:
成功時為 0,出錯時為負值
此 ioctl 用於設定 s390 架構上的客戶機儲存鍵值。該 ioctl 透過 kvm_s390_skeys 結構獲取引數。有關結構定義,請參閱 KVM_S390_GET_SKEYS 部分。
start_gfn 欄位是您要設定其儲存鍵的第一個客戶機幀的編號。
count 欄位是要獲取其儲存鍵的連續幀的數量(從 start_gfn 開始)。count 欄位必須至少為 1,允許的最大值定義為 KVM_S390_SKEYS_MAX。超出此範圍的值將導致 ioctl 返回 -EINVAL。
skeydata_addr 欄位是指向包含 count 位元組儲存鍵的緩衝區的地址。緩衝區中的每個位元組都將設定為從 start_gfn 開始的單個幀的儲存鍵,計數幀。
注意:如果在給定的資料中發現任何架構上無效的鍵值,則 ioctl 將返回 -EINVAL。
4.92 KVM_S390_IRQ¶
- 功能:
KVM_CAP_S390_INJECT_IRQ
- 架構:
s390
- 型別:
vcpu ioctl
- 引數:
struct kvm_s390_irq (輸入)
- 返回值:
成功時為 0,出錯時為 -1
錯誤
EINVAL
中斷型別是無效型別,型別是 KVM_S390_SIGP_STOP,並且標誌引數是無效值,型別是 KVM_S390_INT_EXTERNAL_CALL,並且程式碼大於 VCPU 的最大值
EBUSY
型別是 KVM_S390_SIGP_SET_PREFIX,並且 vcpu 未停止,型別是 KVM_S390_SIGP_STOP,並且已存在掛起的停止 irq,型別是 KVM_S390_INT_EXTERNAL_CALL,並且已存在掛起的外部呼叫中斷
允許將中斷注入到客戶機。
使用 struct kvm_s390_irq 作為引數可以注入額外的有效負載,這是透過 KVM_S390_INTERRUPT 無法實現的。
中斷引數透過 kvm_s390_irq 傳遞
struct kvm_s390_irq {
__u64 type;
union {
struct kvm_s390_io_info io;
struct kvm_s390_ext_info ext;
struct kvm_s390_pgm_info pgm;
struct kvm_s390_emerg_info emerg;
struct kvm_s390_extcall_info extcall;
struct kvm_s390_prefix_info prefix;
struct kvm_s390_stop_info stop;
struct kvm_s390_mchk_info mchk;
char reserved[64];
} u;
};
type 可以是以下之一
KVM_S390_SIGP_STOP - sigp 停止;.stop 中的引數
KVM_S390_PROGRAM_INT - 程式檢查;.pgm 中的引數
KVM_S390_SIGP_SET_PREFIX - sigp 設定字首;.prefix 中的引數
KVM_S390_RESTART - 重新啟動;沒有引數
KVM_S390_INT_CLOCK_COMP - 時鐘比較器中斷;沒有引數
KVM_S390_INT_CPU_TIMER - CPU 計時器中斷;沒有引數
KVM_S390_INT_EMERGENCY - sigp 緊急情況;.emerg 中的引數
KVM_S390_INT_EXTERNAL_CALL - sigp 外部呼叫;.extcall 中的引數
KVM_S390_MCHK - 機器檢查中斷;.mchk 中的引數
這是一個非同步 vcpu ioctl,可以從任何執行緒呼叫。
4.94 KVM_S390_GET_IRQ_STATE¶
- 功能:
KVM_CAP_S390_IRQ_STATE
- 架構:
s390
- 型別:
vcpu ioctl
- 引數:
struct kvm_s390_irq_state (輸出)
- 返回值:
>= 複製到緩衝區中的位元組數,如果緩衝區大小為 0,則為 -EINVAL,如果緩衝區大小太小而無法容納所有掛起的中斷,則為 -ENOBUFS,如果緩衝區地址無效,則為 -EFAULT
此 ioctl 允許使用者空間在單個緩衝區中檢索所有當前掛起的中斷的完整狀態。用例包括遷移和內省。引數結構包含使用者空間緩衝區的地址及其長度
struct kvm_s390_irq_state {
__u64 buf;
__u32 flags; /* will stay unused for compatibility reasons */
__u32 len;
__u32 reserved[4]; /* will stay unused for compatibility reasons */
};
使用者空間傳入上述結構,並且對於每個掛起的中斷,都會將一個 struct kvm_s390_irq 複製到提供的緩衝區。
該結構包含一個 flags 欄位和一個 reserved 欄位,用於將來的擴充套件。由於核心從未檢查 flags == 0,並且 QEMU 從未預先將 flags 和 reserved 清零,因此將來無法使用這些欄位而不破壞相容性。
如果返回 -ENOBUFS,則提供的緩衝區太小,使用者空間可以使用更大的緩衝區重試。
4.95 KVM_S390_SET_IRQ_STATE¶
- 功能:
KVM_CAP_S390_IRQ_STATE
- 架構:
s390
- 型別:
vcpu ioctl
- 引數:
struct kvm_s390_irq_state (輸入)
- 返回值:
成功時為 0,如果緩衝區地址無效,則為 -EFAULT,如果緩衝區長度無效(見下文),則為 -EINVAL,如果已存在掛起的中斷,則為 -EBUSY,發生錯誤時實際注入中斷。請參閱 KVM_S390_IRQ。
此 ioctl 允許使用者空間設定當前為 vcpu 掛起的所有 cpu 本地中斷的完整狀態。它旨在用於在遷移後恢復中斷狀態。輸入引數是一個使用者空間緩衝區,其中包含一個 struct kvm_s390_irq_state
struct kvm_s390_irq_state {
__u64 buf;
__u32 flags; /* will stay unused for compatibility reasons */
__u32 len;
__u32 reserved[4]; /* will stay unused for compatibility reasons */
};
flags 和 reserved 的限制同樣適用。(請參閱 KVM_S390_GET_IRQ_STATE)
buf 引用的使用者空間記憶體包含一個 struct kvm_s390_irq,用於每個要注入到客戶機中的中斷。如果由於某種原因無法注入其中一箇中斷,則 ioctl 將中止。
len 必須是 sizeof(struct kvm_s390_irq) 的倍數。它必須 > 0,並且不能超過 (max_vcpus + 32) * sizeof(struct kvm_s390_irq),這是可能掛起的 cpu 本地中斷的最大數量。
4.96 KVM_SMI¶
- 功能:
KVM_CAP_X86_SMM
- 架構:
x86
- 型別:
vcpu ioctl
- 引數:
無
- 返回值:
成功時為 0,出錯時為 -1
線上程的 vcpu 上排隊一個 SMI。
4.97 KVM_X86_SET_MSR_FILTER¶
- 功能:
KVM_CAP_X86_MSR_FILTER
- 架構:
x86
- 型別:
vm ioctl
- 引數:
struct kvm_msr_filter
- 返回值:
成功時為 0,出錯時 < 0
struct kvm_msr_filter_range {
#define KVM_MSR_FILTER_READ (1 << 0)
#define KVM_MSR_FILTER_WRITE (1 << 1)
__u32 flags;
__u32 nmsrs; /* number of msrs in bitmap */
__u32 base; /* MSR index the bitmap starts at */
__u8 *bitmap; /* a 1 bit allows the operations in flags, 0 denies */
};
#define KVM_MSR_FILTER_MAX_RANGES 16
struct kvm_msr_filter {
#define KVM_MSR_FILTER_DEFAULT_ALLOW (0 << 0)
#define KVM_MSR_FILTER_DEFAULT_DENY (1 << 0)
__u32 flags;
struct kvm_msr_filter_range ranges[KVM_MSR_FILTER_MAX_RANGES];
};
struct kvm_msr_filter_range 的 flags 值
KVM_MSR_FILTER_READ
使用給定的點陣圖過濾對 MSR 的讀取訪問。點陣圖中的 0 指示應拒絕讀取訪問,而 1 指示無論預設過濾器操作如何,都應允許讀取特定 MSR。
KVM_MSR_FILTER_WRITE
使用給定的點陣圖過濾對 MSR 的寫入訪問。點陣圖中的 0 指示應拒絕寫入訪問,而 1 指示無論預設過濾器操作如何,都應允許寫入特定 MSR。
struct kvm_msr_filter 的 flags 值
KVM_MSR_FILTER_DEFAULT_ALLOW
如果沒有任何過濾器範圍與正在訪問的 MSR 索引匹配,KVM 預設將允許訪問所有 MSR。
KVM_MSR_FILTER_DEFAULT_DENY
如果沒有任何過濾器範圍與正在訪問的 MSR 索引匹配,KVM 預設將拒絕訪問所有 MSR。
此 ioctl 允許使用者空間定義最多 16 個 MSR 範圍的點陣圖,以拒絕 KVM 通常允許的客戶機 MSR 訪問。如果 MSR 不在特定範圍內,則應用“預設”過濾行為。每個點陣圖範圍涵蓋 [base .. base+nmsrs) 中的 MSR。
如果使用者空間拒絕 MSR 訪問,則生成的 KVM 行為取決於是否啟用了 KVM_CAP_X86_USER_SPACE_MSR 的 KVM_MSR_EXIT_REASON_FILTER。如果啟用了 KVM_MSR_EXIT_REASON_FILTER,則 KVM 將在拒絕訪問時退出到使用者空間,即使用者空間有效地攔截 MSR 訪問。如果未啟用 KVM_MSR_EXIT_REASON_FILTER,則 KVM 將在拒絕訪問時將 #GP 注入到客戶機中。請注意,如果在 VMX 轉換期間模擬 MSR 載入/儲存時拒絕 MSR 訪問,則 KVM 將忽略 KVM_MSR_EXIT_REASON_FILTER。有關完整詳細資訊,請參閱以下警告。
如果使用者空間允許 MSR 訪問,則 KVM 將根據 vCPU 模型模擬和/或虛擬化訪問。請注意,如果使用者空間允許訪問,KVM 仍然可能最終注入 #GP,例如,如果 KVM 不支援 MSR,或者遵循 MSR 的架構行為。
預設情況下,KVM 在沒有 MSR 範圍過濾器的情況下以 KVM_MSR_FILTER_DEFAULT_ALLOW 模式執行。
使用空範圍集(所有 nmsrs == 0)呼叫此 ioctl 會停用 MSR 過濾。在該模式下,KVM_MSR_FILTER_DEFAULT_DENY 無效並導致錯誤。
警告
作為指令執行的副作用的 MSR 訪問(模擬或本機)未被過濾,因為硬體不遵守 RDMSR 和 WRMSR 之外的 MSR 點陣圖,並且 KVM 在模擬指令時會模仿該行為,以避免與硬體產生不必要的差異。例如,RDPID 讀取 MSR_TSC_AUX,SYSENTER 讀取 SYSENTER MSR 等。
透過專用 VMCS 欄位載入/儲存的 MSR 不會作為 VM-Enter/VM-Exit 模擬的一部分進行過濾。
透過 VMX 的載入/儲存列表載入/儲存的 MSR _確實_作為 VM-Enter/VM-Exit 模擬的一部分進行過濾。如果在 VM-Enter 時拒絕 MSR 訪問,則 KVM 會合成一個一致性檢查 VM-Exit(EXIT_REASON_MSR_LOAD_FAIL)。如果在 VM-Exit 時拒絕 MSR 訪問,則 KVM 會合成一個 VM-Abort。簡而言之,KVM 擴充套件了 Intel 的架構 MSR 列表,這些 MSR 無法透過 VM-Enter/VM-Exit MSR 列表載入/儲存。平臺所有者有責任將其任何此類限制告知其終端使用者。
x2APIC MSR 訪問無法過濾(KVM 會靜默忽略涵蓋任何 x2APIC MSR 的過濾器)。
請注意,在 vCPU 執行時呼叫此 ioctl 本身就是競爭性的。但是,KVM 確實保證 vCPU 將看到先前的過濾器或新過濾器,例如,舊過濾器和新過濾器中具有相同設定的 MSR 將具有確定性行為。
同樣,如果使用者空間希望攔截拒絕的訪問,則必須在啟用任何過濾器之前啟用 KVM_MSR_EXIT_REASON_FILTER,並保持啟用狀態,直到所有過濾器都被停用之後。否則可能會導致 KVM 注入 #GP 而不是退出到使用者空間。
4.98 KVM_CREATE_SPAPR_TCE_64¶
- 功能:
KVM_CAP_SPAPR_TCE_64
- 架構:
powerpc
- 型別:
vm ioctl
- 引數:
struct kvm_create_spapr_tce_64 (輸入)
- 返回值:
用於操作建立的 TCE 表的檔案描述符
這是 KVM_CAP_SPAPR_TCE 的一個擴充套件,僅支援 32 位視窗,如 4.62 KVM_CREATE_SPAPR_TCE 中所述
此功能使用 ioctl 介面中的擴充套件結構。
/* for KVM_CAP_SPAPR_TCE_64 */
struct kvm_create_spapr_tce_64 {
__u64 liobn;
__u32 page_shift;
__u32 flags;
__u64 offset; /* in pages */
__u64 size; /* in pages */
};
擴充套件的目的是支援一個具有可變頁面大小的更大的 DMA 視窗。 KVM_CREATE_SPAPR_TCE_64 接收一個 64 位視窗大小、一個 IOMMU 頁面移位以及相應 DMA 視窗的匯流排偏移量,@size 和 @offset 是 IOMMU 頁面的數量。
目前未使用 @flags。
其餘功能與 KVM_CREATE_SPAPR_TCE 相同。
4.99 KVM_REINJECT_CONTROL¶
- 功能:
KVM_CAP_REINJECT_CONTROL
- 架構:
x86
- 型別:
vm ioctl
- 引數:
struct kvm_reinject_control (輸入)
- 返回值:
成功時返回 0,如果無法讀取 struct kvm_reinject_control 則返回 -EFAULT,如果 KVM_CREATE_PIT 或 KVM_CREATE_PIT2 先前未成功則返回 -ENXIO。
i8254 (PIT) 有兩種模式,重注入和非重注入。 預設值為重注入,其中 KVM 會將經過的 i8254 計時節拍排隊,並監控來自 i8254 注入的向量的中斷完成情況。 當沒有來自 i8254 的掛起中斷時,重注入模式會取消排隊一個計時節拍並注入其中斷。 非重注入模式會在計時節拍到達時立即注入中斷。
struct kvm_reinject_control {
__u8 pit_reinject;
__u8 reserved[31];
};
建議使用 pit_reinject = 0(非重注入模式),除非執行使用 PIT 進行計時的舊作業系統(例如,Linux 2.4.x)。
4.100 KVM_PPC_CONFIGURE_V3_MMU¶
- 功能:
KVM_CAP_PPC_MMU_RADIX 或 KVM_CAP_PPC_MMU_HASH_V3
- 架構:
ppc
- 型別:
vm ioctl
- 引數:
struct kvm_ppc_mmuv3_cfg (輸入)
- 返回值:
成功時返回 0,如果無法讀取 struct kvm_ppc_mmuv3_cfg 則返回 -EFAULT,如果配置無效則返回 -EINVAL
此 ioctl 控制訪客是否將使用基數樹或 HPT(雜湊頁面表)轉換,並設定指向訪客程序表的指標。
struct kvm_ppc_mmuv3_cfg {
__u64 flags;
__u64 process_table;
};
可以在標誌中設定兩個位; KVM_PPC_MMUV3_RADIX 和 KVM_PPC_MMUV3_GTSE。 如果設定了 KVM_PPC_MMUV3_RADIX,則配置訪客使用基數樹轉換;如果清除,則使用 HPT 轉換。 如果設定了 KVM_PPC_MMUV3_GTSE 並且 KVM 允許,則配置訪客能夠使用全域性 TLB 和 SLB 無效指令;如果清除,則訪客可能無法使用這些指令。
process_table 欄位指定訪客程序表的地址和大小,該表位於訪客空間中。 此欄位的格式設定為分割槽表條目的第二個雙字,如 Power ISA V3.00 Book III 第 5.7.6.1 節中所定義。
4.101 KVM_PPC_GET_RMMU_INFO¶
- 功能:
KVM_CAP_PPC_MMU_RADIX
- 架構:
ppc
- 型別:
vm ioctl
- 引數:
struct kvm_ppc_rmmu_info (輸出)
- 返回值:
成功時返回 0,如果無法寫入 struct kvm_ppc_rmmu_info 則返回 -EFAULT,如果無法返回任何有用的資訊則返回 -EINVAL
此 ioctl 返回一個包含兩個內容的結構:(a) 一個包含支援的基數樹幾何形狀的列表,以及 (b) 一個將頁面大小對映到要在 tlbie(TLB 無效條目)指令的“AP”(實際頁面大小)欄位中放置的列表。
struct kvm_ppc_rmmu_info {
struct kvm_ppc_radix_geom {
__u8 page_shift;
__u8 level_bits[4];
__u8 pad[3];
} geometries[8];
__u32 ap_encodings[8];
};
geometries[] 欄位最多為基數頁面表提供 8 個支援的幾何形狀,以最小頁面大小的以 2 為底的對數以及樹的每個級別(從 PTE 級別到 PGD 級別)索引的位數來表示。 任何未使用的條目在 page_shift 欄位中都將為 0。
ap_encodings 提供支援的頁面大小及其 AP 欄位編碼,AP 值編碼在前 3 位,頁面大小的以 2 為底的對數編碼在後 6 位。
4.102 KVM_PPC_RESIZE_HPT_PREPARE¶
- 功能:
KVM_CAP_SPAPR_RESIZE_HPT
- 架構:
powerpc
- 型別:
vm ioctl
- 引數:
struct kvm_ppc_resize_hpt (輸入)
- 返回值:
成功完成時返回 0,如果正在準備新的 HPT 則返回 >0,該值是準備完成前的估計毫秒數,如果無法讀取 struct kvm_reinject_control 則返回 -EFAULT,如果提供的移位或標誌無效則返回 -EINVAL,如果無法分配新的 HPT 則返回 -ENOMEM
用於實現用於執行時調整訪客的雜湊頁面表 (HPT) 大小的 PAPR 擴充套件。 具體而言,這會啟動、停止或監控訪客新的潛在 HPT 的準備工作,本質上是實現 H_RESIZE_HPT_PREPARE 超呼叫。
struct kvm_ppc_resize_hpt {
__u64 flags;
__u32 shift;
__u32 pad;
};
如果在訪客沒有掛起的 HPT 時呼叫 shift > 0,則這會開始準備大小為 2^(shift) 位元組的新掛起 HPT。 然後,它會返回一個正整數,其中包含準備完成前的估計毫秒數。
如果在呼叫時存在掛起的 HPT,其大小與引數中請求的大小不匹配,則會丟棄現有的掛起 HPT 並建立一個新的 HPT,如上所述。
如果在呼叫時存在所請求大小的掛起 HPT,則會
如果掛起 HPT 的準備工作已經完成,則返回 0
如果掛起 HPT 的準備工作失敗,則返回錯誤程式碼,然後丟棄掛起 HPT。
如果掛起 HPT 的準備工作仍在進行中,則返回準備完成前的估計毫秒數。
如果使用 shift == 0 呼叫,則會丟棄當前任何掛起的 HPT 並返回 0(即取消任何正在進行的準備工作)。
flags 保留用於將來擴充套件,目前在 flags 中設定任何位將導致 -EINVAL。
通常,這將使用相同的引數重複呼叫,直到它返回 <= 0。 第一次呼叫將啟動準備工作,後續呼叫將監控準備工作,直到它完成或失敗。
4.103 KVM_PPC_RESIZE_HPT_COMMIT¶
- 功能:
KVM_CAP_SPAPR_RESIZE_HPT
- 架構:
powerpc
- 型別:
vm ioctl
- 引數:
struct kvm_ppc_resize_hpt (輸入)
- 返回值:
成功完成時返回 0,如果無法讀取 struct kvm_reinject_control 則返回 -EFAULT,如果提供的移位或標誌無效則返回 -EINVAL,如果不存在掛起的 HPT 或者掛起的 HPT 沒有所請求的大小則返回 -ENXIO,如果掛起的 HPT 未完全準備好則返回 -EBUSY,如果在將現有 HPT 條目移動到新的 HPT 時發生雜湊衝突則返回 -ENOSPC,在其他錯誤情況下返回 -EIO
用於實現用於執行時調整訪客的雜湊頁面表 (HPT) 大小的 PAPR 擴充套件。 具體而言,這會請求將訪客轉移到使用新的 HPT,本質上是實現 H_RESIZE_HPT_COMMIT 超呼叫。
struct kvm_ppc_resize_hpt {
__u64 flags;
__u32 shift;
__u32 pad;
};
只有在 KVM_PPC_RESIZE_HPT_PREPARE 使用相同引數返回 0 後才能呼叫此函式。 在其他情況下,KVM_PPC_RESIZE_HPT_COMMIT 將返回一個錯誤(通常為 -ENXIO 或 -EBUSY,但如果準備工作已啟動但失敗,則可能會出現其他錯誤)。
如果訪客尚未將自身置於沒有 vcpu 會進行 MMU 啟用的記憶體訪問的靜默狀態,這將對訪客產生未定義的影響。
成功完成後,掛起的 HPT 將成為訪客的活動 HPT,並且先前的 HPT 將被丟棄。
如果失敗,訪客仍將在其先前的 HPT 上執行。
4.104 KVM_X86_GET_MCE_CAP_SUPPORTED¶
- 功能:
KVM_CAP_MCE
- 架構:
x86
- 型別:
系統 ioctl
- 引數:
u64 mce_cap (輸出)
- 返回值:
成功時為 0,出錯時為 -1
返回支援的 MCE 功能。 u64 mce_cap 引數的格式與 MSR_IA32_MCG_CAP 暫存器相同。 支援的功能將設定相應的位。
4.105 KVM_X86_SETUP_MCE¶
- 功能:
KVM_CAP_MCE
- 架構:
x86
- 型別:
vcpu ioctl
- 引數:
u64 mcg_cap (輸入)
- 返回值:
成功時返回 0,如果無法讀取 u64 mcg_cap 則返回 -EFAULT,如果請求的 bank 數量無效則返回 -EINVAL,如果不支援請求的 MCE 功能則返回 -EINVAL。
初始化 MCE 支援以供使用。 u64 mcg_cap 引數的格式與 MSR_IA32_MCG_CAP 暫存器相同,並指定應啟用哪些功能。 檢查 KVM_CAP_MCE 時,可以檢索支援的最大錯誤報告 bank 數量。 可以使用 KVM_X86_GET_MCE_CAP_SUPPORTED 檢索支援的功能。
4.106 KVM_X86_SET_MCE¶
- 功能:
KVM_CAP_MCE
- 架構:
x86
- 型別:
vcpu ioctl
- 引數:
struct kvm_x86_mce (輸入)
- 返回值:
成功時返回 0,如果無法讀取 struct kvm_x86_mce 則返回 -EFAULT,如果 bank 編號無效則返回 -EINVAL,如果在狀態欄位中未設定 VAL 位則返回 -EINVAL。
將機器檢查錯誤 (MCE) 注入到訪客中。 輸入引數為
struct kvm_x86_mce {
__u64 status;
__u64 addr;
__u64 misc;
__u64 mcg_status;
__u8 bank;
__u8 pad1[7];
__u64 pad2[3];
};
如果報告的 MCE 是未更正的錯誤,則 KVM 會將其作為 MCE 異常注入到訪客中。 如果訪客 MCG_STATUS 暫存器報告 MCE 正在進行中,則 KVM 會導致 KVM_EXIT_SHUTDOWN vmexit。
否則,如果 MCE 是已更正的錯誤,則 KVM 只會將其儲存在相應的 bank 中(前提是此 bank 沒有儲存先前報告的未更正的錯誤)。
4.107 KVM_S390_GET_CMMA_BITS¶
- 功能:
KVM_CAP_S390_CMMA_MIGRATION
- 架構:
s390
- 型別:
vm ioctl
- 引數:
struct kvm_s390_cmma_log (輸入,輸出)
- 返回值:
成功時返回 0,出錯時返回負值
錯誤
ENOMEM
沒有足夠的記憶體來完成該任務
ENXIO
如果未啟用 CMMA
EINVAL
如果未設定 KVM_S390_CMMA_PEEK 但未啟用遷移模式
EINVAL
如果未設定 KVM_S390_CMMA_PEEK 但已停用髒跟蹤(因此自動停用了遷移模式)
EFAULT
如果使用者空間地址無效或者地址不存在頁面表(例如,在使用巨頁時)。
此 ioctl 用於獲取 s390 架構上的 CMMA 位的取值。 它旨在用於兩種情況
在即時遷移期間儲存 CMMA 值。 需要透過 KVM_REQ_START_MIGRATION VM 屬性啟用即時遷移。
透過設定標誌 KVM_S390_CMMA_PEEK 來非破壞性地檢視 CMMA 值。
ioctl 透過 kvm_s390_cmma_log 結構獲取引數。 所需的值被寫入到緩衝區,該緩衝區的位置透過 kvm_s390_cmma_log 結構中的“values”成員指示。 輸入結構中的值也會根據需要進行更新。
每個 CMMA 值佔用一個位元組。
struct kvm_s390_cmma_log {
__u64 start_gfn;
__u32 count;
__u32 flags;
union {
__u64 remaining;
__u64 mask;
};
__u64 values;
};
start_gfn 是要檢索其 CMMA 值的第一個訪客幀的編號
count 是緩衝區長度(以位元組為單位)
values 指向將在其中寫入結果的緩衝區。
如果 count 大於 KVM_S390_SKEYS_MAX,則將其視為 KVM_S390_SKEYS_MAX。 KVM_S390_SKEYS_MAX 被重新使用以與其他 ioctl 保持一致。
結果寫入到由欄位 values 指向的緩衝區中,並且輸入引數的值按如下方式更新。
根據標誌,執行不同的操作。 到目前為止,唯一支援的標誌是 KVM_S390_CMMA_PEEK。
如果未設定 KVM_S390_CMMA_PEEK,則預設行為是:start_gfn 將指示 CMMA 位被置髒的第一個頁幀。它不一定與作為輸入傳遞的頁幀相同,因為會跳過乾淨的頁面。
count 將指示實際寫入緩衝區中的位元組數。它可能(並且非常經常會)小於輸入值,因為緩衝區僅填充到找到 16 位元組的乾淨值(然後不會複製到緩衝區中)。由於 CMMA 遷移塊需要基地址和長度,總共 16 位元組,因此如果之後存在一些髒資料,我們將返回一些乾淨的資料,只要乾淨資料的大小不超過標頭的大小。這允許以增加與使用者空間的往返次數為代價,最大限度地減少要儲存或透過網路傳輸的資料量。下一次呼叫 ioctl 將跳過所有乾淨的值,從而可能節省超過我們找到的 16 位元組。
如果設定了 KVM_S390_CMMA_PEEK:即使不在遷移模式下,也會讀取現有的儲存屬性,並且不執行其他操作;
輸出 start_gfn 將等於輸入 start_gfn,
輸出 count 將等於輸入 count,除非已到達記憶體末尾。
在兩種情況下:欄位 “remaining” 將指示剩餘的髒 CMMA 值的總數,或者如果設定了 KVM_S390_CMMA_PEEK 並且未啟用遷移模式,則為 0。
mask 未使用。
values 指向使用者空間緩衝區,結果將儲存在該緩衝區中。
4.108 KVM_S390_SET_CMMA_BITS¶
- 功能:
KVM_CAP_S390_CMMA_MIGRATION
- 架構:
s390
- 型別:
vm ioctl
- 引數:
struct kvm_s390_cmma_log (輸入)
- 返回值:
成功時返回 0,出錯時返回負值
此 ioctl 用於設定 s390 架構上的 CMMA 位的值。它旨在在即時遷移期間用於恢復 CMMA 值,但對其使用沒有限制。ioctl 透過 kvm_s390_cmma_values 結構體獲取引數。每個 CMMA 值佔用一個位元組。
struct kvm_s390_cmma_log {
__u64 start_gfn;
__u32 count;
__u32 flags;
union {
__u64 remaining;
__u64 mask;
};
__u64 values;
};
start_gfn 指示起始客戶機幀號,
count 指示緩衝區中要考慮的值的數量,
flags 未使用,必須為 0。
mask 指示要考慮哪些 PGSTE 位。
remaining 未使用。
values 指向使用者空間中的緩衝區,用於儲存這些值。
如果無法分配足夠的記憶體來完成任務,則此 ioctl 可能會失敗並返回 -ENOMEM;如果未啟用 CMMA,則返回 -ENXIO;如果 count 欄位太大(例如,大於 KVM_S390_CMMA_SIZE_MAX)或 flags 欄位不為 0,則返回 -EINVAL;如果使用者空間地址無效,如果寫入了無效頁面(例如,在記憶體末尾之後),或者如果地址不存在頁表(例如,使用巨頁時),則返回 -EFAULT。
4.109 KVM_PPC_GET_CPU_CHAR¶
- 功能:
KVM_CAP_PPC_GET_CPU_CHAR
- 架構:
powerpc
- 型別:
vm ioctl
- 引數:
struct kvm_ppc_cpu_char (輸出)
- 返回值:
成功完成時返回 0,如果無法寫入 struct kvm_ppc_cpu_char,則返回 -EFAULT
此 ioctl 向用戶空間提供有關 CPU 某些特性的資訊,這些特性與指令的推測執行以及由推測執行可能導致的資訊洩露有關(請參閱 CVE-2017-5715、CVE-2017-5753 和 CVE-2017-5754)。該資訊在 struct kvm_ppc_cpu_char 中返回,如下所示
struct kvm_ppc_cpu_char {
__u64 character; /* characteristics of the CPU */
__u64 behaviour; /* recommended software behaviour */
__u64 character_mask; /* valid bits in character */
__u64 behaviour_mask; /* valid bits in behaviour */
};
為了擴充套件性,character_mask 和 behaviour_mask 欄位指示核心已填充 character 和 behaviour 的哪些位。如果未來擴充套件了定義的位集,則使用者空間將能夠判斷它是否在知道新位的核心上執行。
character 欄位描述了 CPU 的屬性,這些屬性可以幫助防止意外的資訊洩露 - 具體來說,是否存在用於快閃記憶體無效 L1 資料快取的指令(ori 30,30,0 或 mtspr SPRN_TRIG2,rN),L1 資料快取是否設定為只能由建立它們的執行緒使用的模式,bcctr[l] 指令是否阻止推測,以及是否提供了推測屏障指令(ori 31,31,0)。
behaviour 欄位描述了軟體應採取的防止意外資訊洩露的措施,因此描述了硬體容易受到哪些漏洞的影響;具體來說,是否應在從核心返回到使用者模式時重新整理 L1 資料快取,以及是否應在陣列邊界檢查和陣列訪問之間放置推測屏障。
這些欄位使用與新的 H_GET_CPU_CHARACTERISTICS 超級呼叫相同的位定義。
4.110 KVM_MEMORY_ENCRYPT_OP¶
- 功能:
基本
- 架構:
x86
- 型別:
vm ioctl、vcpu ioctl
- 引數:
一個不透明的平臺特定結構體 (輸入/輸出)
- 返回值:
成功時為 0;出錯時為 -1
如果平臺支援建立加密 VM,則可以使用此 ioctl 發出平臺特定的記憶體加密命令來管理這些加密 VM。
目前,此 ioctl 用於在 AMD 處理器上發出安全加密虛擬化 (SEV) 命令,以及在 Intel 處理器上發出可信域擴充套件 (TDX) 命令。詳細命令在安全加密虛擬化 (SEV)和英特爾可信域擴充套件 (TDX)中定義。
4.111 KVM_MEMORY_ENCRYPT_REG_REGION¶
- 功能:
基本
- 架構:
x86
- 型別:
系統
- 引數:
struct kvm_enc_region (輸入)
- 返回值:
成功時為 0;出錯時為 -1
此 ioctl 可用於註冊可能包含加密資料的客戶機記憶體區域(例如,客戶機 RAM、SMRAM 等)。
它在啟用 SEV 的客戶機中使用。啟用加密後,客戶機記憶體區域可能包含加密資料。SEV 記憶體加密引擎使用一種調整,以便位於不同位置的兩個相同的明文頁面將具有不同的密文。因此,交換或移動這些頁面的密文將不會導致交換明文。因此,重新定位(或遷移)SEV 客戶機的物理支援頁面將需要一些額外的步驟。
注意:當前的 SEV 金鑰管理規範不提供交換或遷移(移動)密文頁面的命令。因此,目前我們固定使用 ioctl 註冊的客戶機記憶體區域。
4.112 KVM_MEMORY_ENCRYPT_UNREG_REGION¶
- 功能:
基本
- 架構:
x86
- 型別:
系統
- 引數:
struct kvm_enc_region (輸入)
- 返回值:
成功時為 0;出錯時為 -1
此 ioctl 可用於登出使用上述 KVM_MEMORY_ENCRYPT_REG_REGION ioctl 註冊的客戶機記憶體區域。
4.113 KVM_HYPERV_EVENTFD¶
- 功能:
KVM_CAP_HYPERV_EVENTFD
- 架構:
x86
- 型別:
vm ioctl
- 引數:
struct kvm_hyperv_eventfd (輸入)
此 ioctl (取消)註冊一個 eventfd,以透過 SIGNAL_EVENT 超級呼叫接收來自客戶機的指定 Hyper-V 連線 id 的通知,而不會導致使用者退出。具有非零事件標誌編號(位 24-31)的 SIGNAL_EVENT 超級呼叫仍會觸發 KVM_EXIT_HYPERV_HCALL 使用者退出。
struct kvm_hyperv_eventfd {
__u32 conn_id;
__s32 fd;
__u32 flags;
__u32 padding[3];
};
conn_id 欄位應適合 24 位
#define KVM_HYPERV_CONN_ID_MASK 0x00ffffff
flags 欄位的可接受值為
#define KVM_HYPERV_EVENTFD_DEASSIGN (1 << 0)
- 返回值:
成功時返回 0,如果 conn_id 或 flags 超出允許範圍則返回 -EINVAL,如果取消分配時 conn_id 未註冊則返回 -ENOENT,如果分配時 conn_id 已註冊則返回 -EEXIST
4.114 KVM_GET_NESTED_STATE¶
- 功能:
KVM_CAP_NESTED_STATE
- 架構:
x86
- 型別:
vcpu ioctl
- 引數:
struct kvm_nested_state (輸入/輸出)
- 返回值:
成功時為 0,出錯時為 -1
錯誤
E2BIG
總狀態大小超過使用者指定的 “size” 值;所需的大小將寫入 size 中。
struct kvm_nested_state {
__u16 flags;
__u16 format;
__u32 size;
union {
struct kvm_vmx_nested_state_hdr vmx;
struct kvm_svm_nested_state_hdr svm;
/* Pad the header to 128 bytes. */
__u8 pad[120];
} hdr;
union {
struct kvm_vmx_nested_state_data vmx[0];
struct kvm_svm_nested_state_data svm[0];
} data;
};
#define KVM_STATE_NESTED_GUEST_MODE 0x00000001
#define KVM_STATE_NESTED_RUN_PENDING 0x00000002
#define KVM_STATE_NESTED_EVMCS 0x00000004
#define KVM_STATE_NESTED_FORMAT_VMX 0
#define KVM_STATE_NESTED_FORMAT_SVM 1
#define KVM_STATE_NESTED_VMX_VMCS_SIZE 0x1000
#define KVM_STATE_NESTED_VMX_SMM_GUEST_MODE 0x00000001
#define KVM_STATE_NESTED_VMX_SMM_VMXON 0x00000002
#define KVM_STATE_VMX_PREEMPTION_TIMER_DEADLINE 0x00000001
struct kvm_vmx_nested_state_hdr {
__u64 vmxon_pa;
__u64 vmcs12_pa;
struct {
__u16 flags;
} smm;
__u32 flags;
__u64 preemption_timer_deadline;
};
struct kvm_vmx_nested_state_data {
__u8 vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE];
__u8 shadow_vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE];
};
此 ioctl 將 vcpu 的巢狀虛擬化狀態從核心複製到使用者空間。
可以透過將 KVM_CAP_NESTED_STATE 傳遞給 KVM_CHECK_EXTENSION ioctl() 來檢索狀態的最大大小。
4.115 KVM_SET_NESTED_STATE¶
- 功能:
KVM_CAP_NESTED_STATE
- 架構:
x86
- 型別:
vcpu ioctl
- 引數:
struct kvm_nested_state (輸入)
- 返回值:
成功時為 0,出錯時為 -1
這會將 vcpu 的 kvm_nested_state 結構體從使用者空間複製到核心。有關 struct kvm_nested_state 的定義,請參閱 KVM_GET_NESTED_STATE。
4.116 KVM_(UN)REGISTER_COALESCED_MMIO¶
- 功能:
KVM_CAP_COALESCED_MMIO(用於合併 mmio)KVM_CAP_COALESCED_PIO(用於合併 pio)
- 架構:
全部
- 型別:
vm ioctl
- 引數:
struct kvm_coalesced_mmio_zone
- 返回值:
成功時為 0,出錯時 < 0
合併 I/O 是一種效能最佳化,它會延遲硬體暫存器寫入模擬,從而避免使用者空間退出。它通常用於減少模擬頻繁訪問的硬體暫存器的開銷。
當硬體暫存器配置為合併 I/O 時,寫入訪問不會退出到使用者空間,並且它們的值會記錄在核心和使用者空間之間共享的環形緩衝區中。
如果可以延遲對硬體暫存器的一個或多個寫入訪問,直到讀取或寫入同一裝置上的另一個硬體暫存器,則使用合併 I/O。最後一次訪問將導致 vmexit,使用者空間將在模擬之前處理來自環形緩衝區的訪問。這將避免在重複寫入時退出到使用者空間。
合併 pio 基於合併 mmio。合併 mmio 和 pio 之間幾乎沒有區別,除了合併 pio 記錄對 I/O 埠的訪問。
4.117 KVM_CLEAR_DIRTY_LOG¶
- 功能:
KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2
- 架構:
x86, arm64, mips
- 型別:
vm ioctl
- 引數:
struct kvm_clear_dirty_log (輸入)
- 返回值:
成功時為 0,出錯時為 -1
/* for KVM_CLEAR_DIRTY_LOG */
struct kvm_clear_dirty_log {
__u32 slot;
__u32 num_pages;
__u64 first_page;
union {
void __user *dirty_bitmap; /* one bit per page */
__u64 padding;
};
};
ioctl 根據在 struct kvm_clear_dirty_log 的 dirty_bitmap 欄位中傳遞的點陣圖,清除記憶體槽中頁面的髒狀態。點陣圖的位 0 對應於記憶體槽中的頁面 “first_page”,num_pages 是輸入點陣圖的位數大小。first_page 必須是 64 的倍數;num_pages 也必須是 64 的倍數,除非 first_page + num_pages 是記憶體槽的大小。對於輸入點陣圖中設定的每個位,對應的頁面在 KVM 的髒點陣圖中標記為 “clean”,並且重新啟用該頁面的髒跟蹤(例如,透過防寫,或透過清除頁表條目中的髒位)。
如果 KVM_CAP_MULTI_ADDRESS_SPACE 可用,則 slot 欄位的位 16-31 指定您要清除髒狀態的地址空間。有關 slot 欄位用法的詳細資訊,請參閱 KVM_SET_USER_MEMORY_REGION。
當啟用 KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 時,此 ioctl 最有用;有關更多資訊,請參閱該功能的描述。但是,只要 KVM_CHECK_EXTENSION 確認 KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 存在,它就可以始終使用。
4.118 KVM_GET_SUPPORTED_HV_CPUID¶
- 功能:
KVM_CAP_HYPERV_CPUID (vcpu), KVM_CAP_SYS_HYPERV_CPUID (系統)
- 架構:
x86
- 型別:
系統 ioctl,vcpu ioctl
- 引數:
struct kvm_cpuid2 (in/out)
- 返回值:
成功時為 0,出錯時為 -1
struct kvm_cpuid2 {
__u32 nent;
__u32 padding;
struct kvm_cpuid_entry2 entries[0];
};
struct kvm_cpuid_entry2 {
__u32 function;
__u32 index;
__u32 flags;
__u32 eax;
__u32 ebx;
__u32 ecx;
__u32 edx;
__u32 padding[3];
};
此 ioctl 返回與 KVM 中 Hyper-V 模擬相關的 x86 cpuid 功能葉子。使用者空間可以使用此 ioctl 返回的資訊來構造呈現給使用 Hyper-V 增強的客戶機(例如 Windows 或 Hyper-V 客戶機)的 cpuid 資訊。
此 ioctl 返回的 CPUID 功能葉子由 Hyper-V 頂級功能規範 (TLFS) 定義。這些葉子無法透過 KVM_GET_SUPPORTED_CPUID ioctl 獲得,因為其中一些葉子與 KVM 功能葉子 (0x40000000, 0x40000001) 相交。
目前,返回以下 CPUID 葉子
HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS
HYPERV_CPUID_INTERFACE
HYPERV_CPUID_VERSION
HYPERV_CPUID_FEATURES
HYPERV_CPUID_ENLIGHTMENT_INFO
HYPERV_CPUID_IMPLEMENT_LIMITS
HYPERV_CPUID_NESTED_FEATURES
HYPERV_CPUID_SYNDBG_VENDOR_AND_MAX_FUNCTIONS
HYPERV_CPUID_SYNDBG_INTERFACE
HYPERV_CPUID_SYNDBG_PLATFORM_CAPABILITIES
使用者空間透過傳遞一個 kvm_cpuid2 結構體來呼叫 KVM_GET_SUPPORTED_HV_CPUID,其中 “nent” 欄位指示變數大小陣列 “entries” 中的條目數。如果條目數太少而無法描述所有 Hyper-V 功能葉子,則會返回錯誤 (E2BIG)。如果該數量大於或等於 Hyper-V 功能葉子的數量,則 “nent” 欄位將調整為 “entries” 陣列中有效條目的數量,然後填充該陣列。
“struct kvm_cpuid_entry2” 中的 “index” 和 “flags” 欄位當前已保留,使用者空間不應期望在那裡獲得任何特定值。
請注意,vcpu 版本的 KVM_GET_SUPPORTED_HV_CPUID 目前已棄用。與無條件地公開所有支援的功能位的系統 ioctl 不同,vcpu 版本具有以下怪癖
僅當先前在相應的 vCPU 上啟用了 Enlightened VMCS 時,才會公開 HYPERV_CPUID_NESTED_FEATURES 葉子和 HV_X64_ENLIGHTENED_VMCS_RECOMMENDED 功能位(KVM_CAP_HYPERV_ENLIGHTENED_VMCS)。
HV_STIMER_DIRECT_MODE_AVAILABLE 位僅在使用核心 LAPIC 時公開。(假定已呼叫 KVM_CREATE_IRQCHIP)。
4.119 KVM_ARM_VCPU_FINALIZE¶
- 架構:
arm64
- 型別:
vcpu ioctl
- 引數:
int feature (輸入)
- 返回值:
成功時為 0,出錯時為 -1
錯誤
EPERM
未啟用該功能,需要配置,或已完成
EINVAL
功能未知或不存在
feature 的可識別值
arm64
KVM_ARM_VCPU_SVE(需要 KVM_CAP_ARM_SVE)
完成指定 vcpu 功能的配置。
必須已經初始化 vcpu,並透過在 features[] 中設定適當的標誌,透過成功的KVM_ARM_VCPU_INIT呼叫來啟用受影響的功能。
對於受影響的 vcpu 功能,這是在使用 vcpu 之前必須執行的強制性步驟。
在 KVM_ARM_VCPU_INIT 和 KVM_ARM_VCPU_FINALIZE 之間,可以使用 KVM_SET_ONE_REG 等 ioctl 來配置該功能。應該執行的確切配置以及如何執行該配置取決於具體功能。
依賴於特定功能已完成的其他呼叫,例如 KVM_RUN、KVM_GET_REG_LIST、KVM_GET_ONE_REG 和 KVM_SET_ONE_REG,除非該功能已透過 KVM_ARM_VCPU_FINALIZE 呼叫完成,否則將失敗並返回 -EPERM。
有關需要使用此 ioctl 完成的 vcpu 功能的詳細資訊,請參閱 KVM_ARM_VCPU_INIT。
4.120 KVM_SET_PMU_EVENT_FILTER¶
- 功能:
KVM_CAP_PMU_EVENT_FILTER
- 架構:
x86
- 型別:
vm ioctl
- 引數:
struct kvm_pmu_event_filter (輸入)
- 返回值:
成功時為 0,出錯時為 -1
錯誤
EFAULT
無法訪問 args[0]
EINVAL
args[0] 包含過濾器或過濾器事件中的無效資料
E2BIG
nevents 太大
EBUSY
沒有足夠的記憶體來分配過濾器
struct kvm_pmu_event_filter {
__u32 action;
__u32 nevents;
__u32 fixed_counter_bitmap;
__u32 flags;
__u32 pad[4];
__u64 events[0];
};
此 ioctl 透過限制允許哪些事件選擇和單元掩碼組合來限制客戶機可以程式設計的 PMU 事件集。
該引數包含將允許或拒絕的過濾器事件列表。
過濾器事件僅控制通用計數器;固定用途計數器由 fixed_counter_bitmap 控制。
“flags” 的有效值
``0``
要使用此模式,請清除 “flags” 欄位。
在此模式下,每個事件將包含一個事件選擇 + 單元掩碼。
當客戶機嘗試程式設計 PMU 時,會將客戶機的事件選擇 + 單元掩碼與過濾器事件進行比較,以確定客戶機是否應具有訪問許可權。
KVM_PMU_EVENT_FLAG_MASKED_EVENTS:功能:KVM_CAP_PMU_EVENT_MASKED_EVENTS
在此模式下,每個過濾器事件將包含一個事件選擇、掩碼、匹配和排除值。要編碼掩碼事件,請使用
KVM_PMU_ENCODE_MASKED_ENTRY()
編碼的事件將遵循此佈局
Bits Description
---- -----------
7:0 event select (low bits)
15:8 umask match
31:16 unused
35:32 event select (high bits)
36:54 unused
55 exclude bit
63:56 umask mask
當客戶機嘗試程式設計 PMU 時,將按照以下步驟確定客戶機是否應具有訪問許可權
將客戶機的事件選擇與過濾器事件進行匹配。
如果找到匹配項,則將客戶機的單元掩碼與包含的過濾器事件的掩碼和匹配值進行匹配。即 (unit mask & mask) == match && !exclude。
如果找到匹配項,則將客戶機的單元掩碼與排除的過濾器事件的掩碼和匹配值進行匹配。即 (unit mask & mask) == match && exclude。
如果找到包含的匹配項並且未找到排除的匹配項,則過濾該事件。
對於其他所有內容,不要過濾該事件。
如果該事件被過濾並且是允許列表,則允許客戶機程式設計該事件。
如果該事件被過濾並且是拒絕列表,則不允許客戶機程式設計該事件。
當設定新的 pmu 事件過濾器時,如果在 Intel 上呼叫時設定了任何未使用的欄位或設定了事件選擇中的任何高位 (35:32),則會返回 -EINVAL。
“action” 的有效值
#define KVM_PMU_EVENT_ALLOW 0
#define KVM_PMU_EVENT_DENY 1
透過此 API,KVM 使用者空間還可以透過配置 “action” 和 “fixed_counter_bitmap” 欄位來控制 VM 固定計數器(如果有)的行為。
具體來說,KVM 在確定是否允許客戶機 FixCtr[i] 計數其預定義的固定事件時,遵循以下虛擬碼
FixCtr[i]_is_allowed = (action == ALLOW) && (bitmap & BIT(i)) ||
(action == DENY) && !(bitmap & BIT(i));
FixCtr[i]_is_denied = !FixCtr[i]_is_allowed;
KVM 始終使用 fixed_counter_bitmap,使用者空間有責任確保正確設定 fixed_counter_bitmap,例如,如果使用者空間想要定義一個僅影響通用計數器的過濾器。
請注意,“events” 欄位也適用於固定計數器的硬編碼 event_select 和 unit_mask 值。如果兩者之間存在矛盾,“fixed_counter_bitmap” 的優先順序高於 “events”。
4.121 KVM_PPC_SVM_OFF¶
- 功能:
基本
- 架構:
powerpc
- 型別:
vm ioctl
- 引數:
無
- 返回值:
成功完成時返回 0,
錯誤
EINVAL
如果 ultravisor 未能終止安全客戶機
ENOMEM
如果 hypervisor 未能為客戶機分配新的基數頁表
此 ioctl 用於關閉客戶機的安全模式或將客戶機從安全模式轉換為正常模式。這在重置客戶機時呼叫。如果為正常客戶機呼叫,則此操作無效。
此 ioctl 發出 ultravisor 呼叫以終止安全客戶機,取消固定 VPA 頁面,並釋放 hypervisor 用於跟蹤安全頁面的所有裝置頁面。
4.122 KVM_S390_NORMAL_RESET¶
- 功能:
KVM_CAP_S390_VCPU_RESETS
- 架構:
s390
- 型別:
vcpu ioctl
- 引數:
無
- 返回值:
0
此 ioctl 根據 POP(操作原理)中的 cpu 重置定義重置 VCPU 暫存器和控制結構。
4.123 KVM_S390_INITIAL_RESET¶
- 功能:
基本
- 架構:
s390
- 型別:
vcpu ioctl
- 引數:
無
- 返回值:
0
此 ioctl 根據 POP 中的初始 cpu 重置定義重置 VCPU 暫存器和控制結構。但是,cpu 不會進入 ESA 模式。此重置是正常重置的超集。
4.124 KVM_S390_CLEAR_RESET¶
- 功能:
KVM_CAP_S390_VCPU_RESETS
- 架構:
s390
- 型別:
vcpu ioctl
- 引數:
無
- 返回值:
0
此 ioctl 根據 POP 中的清除 cpu 重置定義重置 VCPU 暫存器和控制結構。但是,cpu 不會進入 ESA 模式。此重置是初始重置的超集。
4.125 KVM_S390_PV_COMMAND¶
- 功能:
KVM_CAP_S390_PROTECTED
- 架構:
s390
- 型別:
vm ioctl
- 引數:
struct kvm_pv_cmd
- 返回值:
成功時為 0,出錯時 < 0
struct kvm_pv_cmd {
__u32 cmd; /* Command to be executed */
__u16 rc; /* Ultravisor return code */
__u16 rrc; /* Ultravisor return reason code */
__u64 data; /* Data or address */
__u32 flags; /* flags for future extensions. Must be 0 for now */
__u32 reserved[3];
};
Ultravisor 返回程式碼 如果已執行 Ultravisor 呼叫以實現該命令預期的結果,則核心會提供 Ultravisor 返回(原因)程式碼。因此,它們獨立於 IOCTL 返回程式碼。如果 KVM 更改 rc,其值將始終大於 0,因此建議在發出 PV 命令之前將其設定為 0,以便能夠檢測到 rc 的更改。
cmd 值
- KVM_PV_ENABLE
分配記憶體並向 Ultravisor 註冊 VM,從而將記憶體捐贈給 Ultravisor,這將使 KVM 無法訪問該記憶體。所有現有的 CPU 都轉換為受保護的 CPU。在此命令成功後,透過熱插拔新增的任何 CPU 在建立期間也會變為受保護的 CPU。
錯誤
EINTR
未遮蔽的訊號正在掛起
- KVM_PV_DISABLE
從 Ultravisor 取消註冊 VM,並回收已捐贈給 Ultravisor 的記憶體,使其再次可供核心使用。所有已註冊的 VCPU 都轉換回非受保護的 VCPU。如果先前已使用 KVM_PV_ASYNC_CLEANUP_PREPARE 準備了受保護的 VM 以進行非同步拆卸,並且隨後未使用 KVM_PV_ASYNC_CLEANUP_PERFORM 拆卸,則它將在此呼叫中與當前受保護的 VM 一起拆卸。
- KVM_PV_VM_SET_SEC_PARMS
將 VM 記憶體中的映象頭傳遞給 Ultravisor,以準備映象解包和驗證。
- KVM_PV_VM_UNPACK
解包(保護和解密)加密的啟動映象的頁面。
- KVM_PV_VM_VERIFY
驗證解包映象的完整性。只有在此成功後,才允許 KVM 啟動受保護的 VCPU。
- KVM_PV_INFO
- 功能:
KVM_CAP_S390_PROTECTED_DUMP
提供一個 API,該 API 透過子命令向用戶空間提供與 Ultravisor 相關的資料。len_max 是使用者空間緩衝區的大小,len_written 是 KVM 指示實際寫入該緩衝區的位元組數。如果在將來添加了更多響應欄位,則可以使用 len_written 來確定有效欄位。
enum pv_cmd_info_id { KVM_PV_INFO_VM, KVM_PV_INFO_DUMP, }; struct kvm_s390_pv_info_header { __u32 id; __u32 len_max; __u32 len_written; __u32 reserved; }; struct kvm_s390_pv_info { struct kvm_s390_pv_info_header header; struct kvm_s390_pv_info_dump dump; struct kvm_s390_pv_info_vm vm; };
子命令
- KVM_PV_INFO_VM
此子命令提供 PV 主機的基本 Ultravisor 資訊。這些值也可能作為 sysfs 韌體 UV 查詢介面中的檔案匯出,但它們在此 API 中更易於程式使用。
installed calls 和 feature_indication 成員提供已安裝的 UV 呼叫和 UV 的其他功能指示。
max_* 成員提供有關最大 PV vcpu、PV 客戶機和 PV 客戶機記憶體大小的資訊。
struct kvm_s390_pv_info_vm { __u64 inst_calls_list[4]; __u64 max_cpus; __u64 max_guests; __u64 max_guest_addr; __u64 feature_indication; };- KVM_PV_INFO_DUMP
此子命令提供與轉儲 PV 客戶機相關的資訊。
struct kvm_s390_pv_info_dump { __u64 dump_cpu_buffer_len; __u64 dump_config_mem_buffer_per_1m; __u64 dump_config_finalize_len; };
- KVM_PV_DUMP
- 功能:
KVM_CAP_S390_PROTECTED_DUMP
提供一個 API,該 API 提供有助於轉儲受保護 VM 的呼叫。
struct kvm_s390_pv_dmp { __u64 subcmd; __u64 buff_addr; __u64 buff_len; __u64 gaddr; /* For dump storage state */ };子命令
- KVM_PV_DUMP_INIT
初始化受保護 VM 的轉儲過程。如果此呼叫不成功,則所有其他子命令將失敗並返回 -EINVAL。如果尚未完成轉儲過程,則此子命令將返回 -EINVAL。
並非所有 PV vm 都可以轉儲,所有者需要在 SE 標頭中設定 dump allowed PCF 位 34 以允許轉儲。
- KVM_PV_DUMP_CONFIG_STOR_STATE
儲存以絕對客戶機地址 (gaddr) 指定的 1MB 塊開始的 buff_len 位元組的調整元件值。buff_len 需要與 conf_dump_storage_state_len 對齊,並且至少 >= 轉儲 uv_info 資料提供的 conf_dump_storage_state_len 值。即使返回錯誤 rc,也可能會寫入 buff_user。例如,如果在寫入第一頁資料後遇到故障。
- KVM_PV_DUMP_COMPLETE
如果子命令成功,則完成轉儲過程,並允許再次呼叫 KVM_PV_DUMP_INIT。
成功後,conf_dump_finalize_len 位元組的完成資料將儲存到 buff_addr。完成資料包含金鑰派生種子、IV、調整 nonce 和加密金鑰,以及以後解密轉儲所需的所有身份驗證標記。
- KVM_PV_ASYNC_CLEANUP_PREPARE
- 功能:
KVM_CAP_S390_PROTECTED_ASYNC_DISABLE
準備當前受保護的 VM 以進行非同步拆卸。當前受保護的 VM 使用的大多數資源將被留出用於後續的非同步拆卸。然後,當前受保護的 VM 將立即恢復執行,作為非受保護的 VM。任何時候最多隻能有一個受保護的 VM 準備進行非同步拆卸。如果先前已準備好拆卸受保護的 VM,但未隨後呼叫 KVM_PV_ASYNC_CLEANUP_PERFORM,則此呼叫將失敗。在這種情況下,使用者空間程序應發出正常的 KVM_PV_DISABLE。使用此呼叫留出的資源將需要使用後續的 KVM_PV_ASYNC_CLEANUP_PERFORM 或 KVM_PV_DISABLE 呼叫進行清理,否則它們將在 KVM 終止時進行清理。只要清理開始,就可以再次呼叫 KVM_PV_ASYNC_CLEANUP_PREPARE,即在 KVM_PV_ASYNC_CLEANUP_PERFORM 完成之前。
- KVM_PV_ASYNC_CLEANUP_PERFORM
- 功能:
KVM_CAP_S390_PROTECTED_ASYNC_DISABLE
拆卸先前已使用 KVM_PV_ASYNC_CLEANUP_PREPARE 準備拆卸的受保護的 VM。在此命令執行期間,將釋放已留出的資源。理想情況下,此 PV 命令應由使用者空間從單獨的執行緒發出。如果收到致命訊號(或該程序自然終止),該命令將立即終止而不完成,並且正常的 KVM 關閉過程將負責清理所有剩餘的受保護的 VM,包括其拆卸被程序終止中斷的 VM。
4.126 KVM_XEN_HVM_SET_ATTR¶
- 功能:
KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO
- 架構:
x86
- 型別:
vm ioctl
- 引數:
struct kvm_xen_hvm_attr
- 返回值:
成功時為 0,出錯時 < 0
struct kvm_xen_hvm_attr {
__u16 type;
__u16 pad[3];
union {
__u8 long_mode;
__u8 vector;
__u8 runstate_update_flag;
union {
__u64 gfn;
__u64 hva;
} shared_info;
struct {
__u32 send_port;
__u32 type; /* EVTCHNSTAT_ipi / EVTCHNSTAT_interdomain */
__u32 flags;
union {
struct {
__u32 port;
__u32 vcpu;
__u32 priority;
} port;
struct {
__u32 port; /* Zero for eventfd */
__s32 fd;
} eventfd;
__u32 padding[4];
} deliver;
} evtchn;
__u32 xen_version;
__u64 pad[8];
} u;
};
型別值
- KVM_XEN_ATTR_TYPE_LONG_MODE
設定 VM 的 ABI 模式為 32 位或 64 位(長模式)。 這決定了暴露給 VM 的 shared_info 頁面的佈局。
- KVM_XEN_ATTR_TYPE_SHARED_INFO
設定 Xen shared_info 頁面所在的客戶機物理幀編號。請注意,雖然 Xen 將前 32 個 vCPU 的 vcpu_info 放置在 shared_info 頁面中,但 KVM 不會自動執行此操作,而是要求顯式使用 KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO 或 KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO_HVA,即使給定 vCPU 的 vcpu_info 位於 shared_info 頁面的“預設”位置。 這是因為 KVM 可能不知道用作 vcpu_info[] 陣列索引的 Xen CPU id,因此可能知道正確的預設位置。
請注意,KVM 可能會不斷寫入 shared_info 頁面;它包含用於向 Xen 客戶機傳遞中斷的事件通道點陣圖,以及其他內容。 它不受髒跟蹤機制的約束——KVM 不會顯式地將頁面標記為髒,每次向客戶機傳遞事件通道中斷! 因此,如果任何 vCPU 正在執行或任何事件通道中斷可以路由到客戶機,則使用者空間應始終假設指定的 GFN 是髒的。
將 gfn 設定為 KVM_XEN_INVALID_GFN 將停用 shared_info 頁面。
- KVM_XEN_ATTR_TYPE_SHARED_INFO_HVA
如果 Xen 功能中也設定了 KVM_XEN_HVM_CONFIG_SHARED_INFO_HVA 標誌,則可以使用此屬性設定 shared_info 頁面所在的使用者空間地址,該地址將始終固定在 VMM 中,而不管它對映在客戶機物理地址空間的什麼位置。 此屬性應優先於 KVM_XEN_ATTR_TYPE_SHARED_INFO 使用,因為它避免了在客戶機物理地址空間中重新對映頁面時,不必要地使內部快取失效。
將 hva 設定為零將停用 shared_info 頁面。
- KVM_XEN_ATTR_TYPE_UPCALL_VECTOR
設定用於傳遞 Xen 事件通道 upcall 的異常向量。 這是由 hypervisor 直接注入的 HVM 範圍向量(不是透過本地 APIC),通常由客戶機透過 HVM_PARAM_CALLBACK_IRQ 配置。 可以透過將其設定為零來再次停用它(例如,對於客戶機 SHUTDOWN_soft_reset)。
- KVM_XEN_ATTR_TYPE_EVTCHN
當 KVM_CAP_XEN_HVM ioctl 指示支援 KVM_XEN_HVM_CONFIG_EVTCHN_SEND 功能時,此屬性可用。 它配置一個出站埠號,用於攔截來自客戶機的 EVTCHNOP_send 請求。 給定的傳送埠號可以被定向回客戶機上指定的 vCPU(透過 APIC ID)/埠/優先順序,或者觸發 eventfd 上的事件。 vCPU 和優先順序可以透過在後續呼叫中設定 KVM_XEN_EVTCHN_UPDATE 來更改,但對於給定的傳送埠,其他欄位不能更改。 透過在 flags 欄位中使用 KVM_XEN_EVTCHN_DEASSIGN 來刪除埠對映。 在 flags 欄位中傳遞 KVM_XEN_EVTCHN_RESET 會刪除所有出站事件通道的攔截。 flags 欄位的值是互斥的,不能作為位掩碼組合。
- KVM_XEN_ATTR_TYPE_XEN_VERSION
當 KVM_CAP_XEN_HVM ioctl 指示支援 KVM_XEN_HVM_CONFIG_EVTCHN_SEND 功能時,此屬性可用。 它配置在客戶機呼叫 XENVER_version 呼叫時返回給客戶機的 32 位版本程式碼; 通常 (XEN_MAJOR << 16 | XEN_MINOR)。 PV Xen 客戶機通常會將其用作虛擬 hypercall 以觸發事件通道傳遞,因此在核心中響應而無需退出到使用者空間是有益的。
- KVM_XEN_ATTR_TYPE_RUNSTATE_UPDATE_FLAG
當 KVM_CAP_XEN_HVM ioctl 指示支援 KVM_XEN_HVM_CONFIG_RUNSTATE_UPDATE_FLAG 時,此屬性可用。 它啟用 XEN_RUNSTATE_UPDATE 標誌,該標誌允許客戶機 vCPU 安全地讀取其他 vCPU 的 vcpu_runstate_info。 Xen 客戶機透過 HYPERVISOR_vm_assist hypercall 的 VMASST_TYPE_runstate_update_flag 啟用此功能。
4.127 KVM_XEN_HVM_GET_ATTR¶
- 功能:
KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO
- 架構:
x86
- 型別:
vm ioctl
- 引數:
struct kvm_xen_hvm_attr
- 返回值:
成功時為 0,出錯時 < 0
允許讀取 Xen VM 屬性。 對於結構和型別,請參見上面的 KVM_XEN_HVM_SET_ATTR。 KVM_XEN_ATTR_TYPE_EVTCHN 屬性無法讀取。
4.128 KVM_XEN_VCPU_SET_ATTR¶
- 功能:
KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO
- 架構:
x86
- 型別:
vcpu ioctl
- 引數:
struct kvm_xen_vcpu_attr
- 返回值:
成功時為 0,出錯時 < 0
struct kvm_xen_vcpu_attr {
__u16 type;
__u16 pad[3];
union {
__u64 gpa;
__u64 pad[4];
struct {
__u64 state;
__u64 state_entry_time;
__u64 time_running;
__u64 time_runnable;
__u64 time_blocked;
__u64 time_offline;
} runstate;
__u32 vcpu_id;
struct {
__u32 port;
__u32 priority;
__u64 expires_ns;
} timer;
__u8 vector;
} u;
};
型別值
- KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO
設定給定 vCPU 的 vcpu_info 的客戶機物理地址。 與 VM 的 shared_info 頁面一樣,如果啟用了事件通道中斷傳遞,則可以在任何時間弄髒相應的頁面,因此使用者空間應始終假設該頁面是髒的,而無需依賴髒日誌記錄。 將 gpa 設定為 KVM_XEN_INVALID_GPA 將停用 vcpu_info。
- KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO_HVA
如果 Xen 功能中也設定了 KVM_XEN_HVM_CONFIG_SHARED_INFO_HVA 標誌,則可以使用此屬性設定給定 vCPU 的 vcpu_info 的使用者空間地址。 它應該只在 vcpu_info 位於 shared_info 頁面的“預設”位置時使用。 在這種情況下,可以安全地假設使用者空間地址不會更改,因為 shared_info 頁面是客戶機記憶體的覆蓋,並且無論它對映在客戶機物理地址空間的什麼位置,都保持在固定的主機地址,因此如果修改了客戶機記憶體佈局,可以避免不必要地使內部快取失效。 如果 vcpu_info 不位於“預設”位置,則不能保證它保持在相同的主機地址,因此需要上述快取失效。
- KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO
設定給定 vCPU 的附加 pvclock 結構的客戶機物理地址。 這通常用於客戶機 vsyscall 支援。 將 gpa 設定為 KVM_XEN_INVALID_GPA 將停用該結構。
- KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADDR
設定給定 vCPU 的 vcpu_runstate_info 的客戶機物理地址。 這是 Xen 客戶機如何跟蹤 CPU 狀態(如竊取時間)的方式。 將 gpa 設定為 KVM_XEN_INVALID_GPA 將停用執行狀態區域。
- KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_CURRENT
從結構的 .u.runstate.state 成員設定給定 vCPU 的執行狀態 (RUNSTATE_running/_runnable/_blocked/_offline)。 KVM 自動計算執行和可執行時間,但阻塞和離線狀態僅顯式輸入。
- KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_DATA
從結構的 .u.runstate 成員設定 vCPU 執行狀態資料的所有欄位,包括當前執行狀態。 state_entry_time 必須等於其他四個時間的總和。
- KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADJUST
此操作 *新增* 結構的 .u.runstate 成員的內容到給定 vCPU 的執行狀態資料的相應成員,從而允許原子調整執行狀態時間。 對 state_entry_time 的調整必須等於對其他四個時間的調整之和。 state 欄位必須設定為 -1,或者設定為有效的執行狀態值(RUNSTATE_running、RUNSTATE_runnable、RUNSTATE_blocked 或 RUNSTATE_offline),以設定調整後的 state_entry_time 的當前計算狀態。
- KVM_XEN_VCPU_ATTR_TYPE_VCPU_ID
當 KVM_CAP_XEN_HVM ioctl 指示支援 KVM_XEN_HVM_CONFIG_EVTCHN_SEND 功能時,此屬性可用。 它設定給定 vCPU 的 Xen vCPU ID,以允許 KVM 攔截與計時器相關的 VCPU 操作。
- KVM_XEN_VCPU_ATTR_TYPE_TIMER
當 KVM_CAP_XEN_HVM ioctl 指示支援 KVM_XEN_HVM_CONFIG_EVTCHN_SEND 功能時,此屬性可用。 它設定 vCPU 的 VIRQ_TIMER 的事件通道埠/優先順序,以及允許儲存/恢復掛起的計時器。 將計時器埠設定為零會停用核心對單發計時器的處理。
- KVM_XEN_VCPU_ATTR_TYPE_UPCALL_VECTOR
當 KVM_CAP_XEN_HVM ioctl 指示支援 KVM_XEN_HVM_CONFIG_EVTCHN_SEND 功能時,此屬性可用。 它設定每個 vCPU 的本地 APIC upcall 向量,該向量由 Xen 客戶機使用 HVMOP_set_evtchn_upcall_vector hypercall 配置。 這通常由 Windows 客戶機使用,並且與使用 HVM_PARAM_CALLBACK_IRQ 配置的 HVM 範圍 upcall 向量不同。 透過將向量設定為零來停用它。
4.129 KVM_XEN_VCPU_GET_ATTR¶
- 功能:
KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO
- 架構:
x86
- 型別:
vcpu ioctl
- 引數:
struct kvm_xen_vcpu_attr
- 返回值:
成功時為 0,出錯時 < 0
允許讀取 Xen vCPU 屬性。 對於結構和型別,請參見上面的 KVM_XEN_VCPU_SET_ATTR。
KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADJUST 型別不能與 KVM_XEN_VCPU_GET_ATTR ioctl 一起使用。
4.131 KVM_GET_SREGS2¶
- 功能:
KVM_CAP_SREGS2
- 架構:
x86
- 型別:
vcpu ioctl
- 引數:
struct kvm_sregs2 (out)
- 返回值:
成功時為 0,出錯時為 -1
從 vcpu 讀取特殊暫存器。 此 ioctl(如果支援)替換 KVM_GET_SREGS。
struct kvm_sregs2 {
/* out (KVM_GET_SREGS2) / in (KVM_SET_SREGS2) */
struct kvm_segment cs, ds, es, fs, gs, ss;
struct kvm_segment tr, ldt;
struct kvm_dtable gdt, idt;
__u64 cr0, cr2, cr3, cr4, cr8;
__u64 efer;
__u64 apic_base;
__u64 flags;
__u64 pdptrs[4];
};
kvm_sregs2 的 flags 值
KVM_SREGS2_FLAGS_PDPTRS_VALID
指示該結構包含有效的 PDPTR 值。
4.132 KVM_SET_SREGS2¶
- 功能:
KVM_CAP_SREGS2
- 架構:
x86
- 型別:
vcpu ioctl
- 引數:
struct kvm_sregs2 (in)
- 返回值:
成功時為 0,出錯時為 -1
將特殊暫存器寫入 vcpu。 有關資料結構,請參見 KVM_GET_SREGS2。 此 ioctl(如果支援)替換 KVM_SET_SREGS。
4.133 KVM_GET_STATS_FD¶
- 功能:
KVM_CAP_STATS_BINARY_FD
- 架構:
全部
- 型別:
vm ioctl、vcpu ioctl
- 引數:
無
- 返回值:
成功時為統計資訊檔案描述符,出錯時 < 0
錯誤
ENOMEM
如果由於缺少記憶體而無法建立 fd
EMFILE
如果開啟的檔案數超過限制
返回的檔案描述符可用於以二進位制格式讀取 VM/vCPU 統計資訊資料。 檔案描述符中的資料由以下方式組織的四個塊組成
標頭 |
id 字串 |
描述符 |
統計資訊資料 |
除了從偏移量 0 開始的標頭之外,請注意不能保證這四個塊是相鄰的或以上述順序排列; id、描述符和資料塊的偏移量在標頭中找到。 但是,所有四個塊都與檔案中的 64 位偏移量對齊,並且它們不重疊。
除了資料塊之外,所有塊都是不可變的。 使用者空間可以在檢索檔案描述符後僅讀取它們一次,然後使用 pread 或 lseek 重複讀取統計資訊。
所有資料均採用系統位元組序。
標頭的格式如下
struct kvm_stats_header {
__u32 flags;
__u32 name_size;
__u32 num_desc;
__u32 id_offset;
__u32 desc_offset;
__u32 data_offset;
};
flags 欄位目前未使用。 它始終讀取為 0。
name_size 欄位是統計資訊名稱字串的大小(以位元組為單位)(包括尾隨“0”),該字串包含在“id 字串”塊中,並附加到每個描述符的末尾。
num_desc 欄位是描述符塊中包含的描述符的數量。(資料塊中的實際值數量可能更大,因為每個描述符可能包含多個值)。
id_offset 欄位是 id 字串從檔案描述符指示的檔案開始處的偏移量。 它是 8 的倍數。
desc_offset 欄位是描述符塊從檔案描述符指示的檔案開始處的偏移量。 它是 8 的倍數。
data_offset 欄位是統計資訊資料塊從檔案描述符指示的檔案開始處的偏移量。 它是 8 的倍數。
id 字串塊包含一個字串,該字串標識在其上呼叫 KVM_GET_STATS_FD 的檔案描述符。 該塊的大小(包括尾隨 '\0')由標頭中的 name_size 欄位指示。
描述符塊僅需要在檔案描述符的生存期內讀取一次,該檔案描述符包含一系列 struct kvm_stats_desc,每個描述符後跟一個大小為 name_size 的字串。
#define KVM_STATS_TYPE_SHIFT 0
#define KVM_STATS_TYPE_MASK (0xF << KVM_STATS_TYPE_SHIFT)
#define KVM_STATS_TYPE_CUMULATIVE (0x0 << KVM_STATS_TYPE_SHIFT)
#define KVM_STATS_TYPE_INSTANT (0x1 << KVM_STATS_TYPE_SHIFT)
#define KVM_STATS_TYPE_PEAK (0x2 << KVM_STATS_TYPE_SHIFT)
#define KVM_STATS_TYPE_LINEAR_HIST (0x3 << KVM_STATS_TYPE_SHIFT)
#define KVM_STATS_TYPE_LOG_HIST (0x4 << KVM_STATS_TYPE_SHIFT)
#define KVM_STATS_TYPE_MAX KVM_STATS_TYPE_LOG_HIST
#define KVM_STATS_UNIT_SHIFT 4
#define KVM_STATS_UNIT_MASK (0xF << KVM_STATS_UNIT_SHIFT)
#define KVM_STATS_UNIT_NONE (0x0 << KVM_STATS_UNIT_SHIFT)
#define KVM_STATS_UNIT_BYTES (0x1 << KVM_STATS_UNIT_SHIFT)
#define KVM_STATS_UNIT_SECONDS (0x2 << KVM_STATS_UNIT_SHIFT)
#define KVM_STATS_UNIT_CYCLES (0x3 << KVM_STATS_UNIT_SHIFT)
#define KVM_STATS_UNIT_BOOLEAN (0x4 << KVM_STATS_UNIT_SHIFT)
#define KVM_STATS_UNIT_MAX KVM_STATS_UNIT_BOOLEAN
#define KVM_STATS_BASE_SHIFT 8
#define KVM_STATS_BASE_MASK (0xF << KVM_STATS_BASE_SHIFT)
#define KVM_STATS_BASE_POW10 (0x0 << KVM_STATS_BASE_SHIFT)
#define KVM_STATS_BASE_POW2 (0x1 << KVM_STATS_BASE_SHIFT)
#define KVM_STATS_BASE_MAX KVM_STATS_BASE_POW2
struct kvm_stats_desc {
__u32 flags;
__s16 exponent;
__u16 size;
__u32 offset;
__u32 bucket_size;
char name[];
};
flags 欄位包含此描述符描述的統計資訊資料的型別和單位。 它的位元組序是 CPU 原生的。 支援以下標誌
flags 的位 0-3 編碼型別
KVM_STATS_TYPE_CUMULATIVE統計資訊報告累積計數。 資料的值只能增加。 KVM 中使用的大多數計數器都是這種型別。 此型別的相應size欄位始終為 1。 所有累積統計資訊資料都是讀/寫的。
KVM_STATS_TYPE_INSTANT統計資訊報告瞬時值。 它的值可以增加或減少。 此型別通常用作某些資源的度量,例如髒頁的數量、大頁的數量等。所有瞬時統計資訊都是隻讀的。 此型別的相應size欄位始終為 1。
KVM_STATS_TYPE_PEAK統計資訊資料報告峰值,例如雜湊表桶中的最大項數、最長的等待時間等等。 資料的值只能增加。 此型別的相應size欄位始終為 1。
KVM_STATS_TYPE_LINEAR_HIST統計資訊報告為線性直方圖。 桶的數量由size欄位指定。 桶的大小由hist_param欄位指定。 第 N 個桶的範圍(1 <= N <size)是 [hist_param``*(N-1), ``hist_param``*N), while the range of the last bucket is [``hist_param``*(``size-1), +INF)。 (+INF 表示正無窮大值。)
KVM_STATS_TYPE_LOG_HIST統計資訊報告為對數直方圖。 桶的數量由size欄位指定。 第一個桶的範圍是 [0, 1),而最後一個桶的範圍是 [pow(2,size-2), +INF)。 否則,第 N 個桶(1 < N <size)覆蓋 [pow(2, N-2), pow(2, N-1))。
flags 的位 4-7 編碼單位
KVM_STATS_UNIT_NONE統計資訊資料的值沒有單位。 這通常意味著該值是事件的簡單計數器。
KVM_STATS_UNIT_BYTES它指示統計資訊資料用於測量記憶體大小,單位為位元組、KiByte、MiByte、GiByte 等。 資料的單位由描述符中的exponent欄位確定。
KVM_STATS_UNIT_SECONDS它指示統計資訊資料用於測量時間或延遲。
KVM_STATS_UNIT_CYCLES它指示統計資訊資料用於測量 CPU 時鐘週期。
KVM_STATS_UNIT_BOOLEAN它指示統計資訊將始終為 0 或 1。 “峰值”型別的布林統計資訊永遠不會從 1 返回到 0。 布林統計資訊可以是線性直方圖(具有兩個桶),但不能是對數直方圖。
請注意,對於直方圖,單位適用於桶範圍,而桶值指示有多少個樣本落入桶的範圍內。
flags 的位 8-11 與 exponent 一起編碼單位的比例
KVM_STATS_BASE_POW10比例基於 10 的冪。 它用於測量時間和 CPU 時鐘週期。 例如,exponent 為 -9 可以與KVM_STATS_UNIT_SECONDS一起使用,以表示單位是納秒。
KVM_STATS_BASE_POW2比例基於 2 的冪。 它用於測量記憶體大小。 例如,exponent 為 20 可以與KVM_STATS_UNIT_BYTES一起使用,以表示單位是 MiB。
size 欄位是此統計資訊資料的值的數量。 對於大多數簡單統計資訊,它的值通常為 1。 1 表示它包含一個無符號 64 位資料。
offset 欄位是從資料塊的開始到相應統計資訊資料的開始的偏移量。
bucket_size 欄位用作直方圖統計資訊資料的引數。 它僅由線性直方圖統計資訊資料使用,指定桶的大小,單位由 flags 的位 4-11 以及 exponent 表示。
name 欄位是統計資訊資料的名稱字串。 名稱字串從 struct kvm_stats_desc 的末尾開始。 最大長度(包括尾隨 '\0')由標頭中的 name_size 指示。
統計資訊資料塊包含一個 64 位值的陣列,其順序與描述符塊中的描述符相同。
4.134 KVM_GET_XSAVE2¶
- 功能:
KVM_CAP_XSAVE2
- 架構:
x86
- 型別:
vcpu ioctl
- 引數:
struct kvm_xsave (out)
- 返回值:
成功時為 0,出錯時為 -1
struct kvm_xsave {
__u32 region[1024];
__u32 extra[0];
};
此 ioctl 會將當前 vcpu 的 xsave 結構複製到使用者空間。 它複製 KVM_CHECK_EXTENSION(KVM_CAP_XSAVE2) 在 vm 檔案描述符上呼叫時返回的位元組數。 KVM_CHECK_EXTENSION(KVM_CAP_XSAVE2) 返回的大小值將始終至少為 4096。 目前,只有當使用 arch_prctl() 啟用了動態功能時,它才會大於 4096,但這可能會在將來發生變化。
struct kvm_xsave 中狀態儲存區域的偏移量遵循主機上 CPUID 葉 0xD 的內容。
4.135 KVM_XEN_HVM_EVTCHN_SEND¶
- 功能:
KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_EVTCHN_SEND
- 架構:
x86
- 型別:
vm ioctl
- 引數:
struct kvm_irq_routing_xen_evtchn
- 返回值:
成功時為 0,出錯時 < 0
struct kvm_irq_routing_xen_evtchn {
__u32 port;
__u32 vcpu;
__u32 priority;
};
此 ioctl 將事件通道中斷直接注入到客戶機 vCPU。
4.136 KVM_S390_PV_CPU_COMMAND¶
- 功能:
KVM_CAP_S390_PROTECTED_DUMP
- 架構:
s390
- 型別:
vcpu ioctl
- 引數:
無
- 返回值:
成功時為 0,出錯時 < 0
此 ioctl 與 KVM_S390_PV_COMMAND 非常相似,但處理 vcpu 的請求。 它重複使用 kvm_s390_pv_dmp 結構,因此也共享命令 id。
command
- KVM_PV_DUMP
提供一個 API,該 API 提供有助於轉儲受保護的 VM 的 vcpu 的呼叫。
subcommand
- KVM_PV_DUMP_CPU
提供加密的轉儲資料,例如暫存器值。 返回的資料的長度由 uv_info.guest_cpu_stor_len 提供。
4.137 KVM_S390_ZPCI_OP¶
- 功能:
KVM_CAP_S390_ZPCI_OP
- 架構:
s390
- 型別:
vm ioctl
- 引數:
struct kvm_s390_zpci_op (in)
- 返回值:
成功時為 0,出錯時 <0
用於管理 zPCI 裝置的硬體輔助虛擬化功能。
引數透過以下結構指定
struct kvm_s390_zpci_op {
/* in */
__u32 fh; /* target device */
__u8 op; /* operation to perform */
__u8 pad[3];
union {
/* for KVM_S390_ZPCIOP_REG_AEN */
struct {
__u64 ibv; /* Guest addr of interrupt bit vector */
__u64 sb; /* Guest addr of summary bit */
__u32 flags;
__u32 noi; /* Number of interrupts */
__u8 isc; /* Guest interrupt subclass */
__u8 sbo; /* Offset of guest summary bit vector */
__u16 pad;
} reg_aen;
__u64 reserved[8];
} u;
};
操作的型別在“op”欄位中指定。 KVM_S390_ZPCIOP_REG_AEN 用於為介面卡事件通知解釋註冊 VM,這將允許韌體將介面卡事件直接傳遞到 VM,KVM 提供備份傳遞機制; KVM_S390_ZPCIOP_DEREG_AEN 用於隨後停用介面卡事件通知的解釋。
目標 zPCI 功能也必須透過“fh”欄位指定。 對於 KVM_S390_ZPCIOP_REG_AEN 操作,必須透過“reg_aen”結構提供其他資訊以建立韌體傳遞。
“pad”和“reserved”欄位可用於未來的擴充套件,使用者空間應將其設定為 0。
4.138 KVM_ARM_SET_COUNTER_OFFSET¶
- 功能:
KVM_CAP_COUNTER_OFFSET
- 架構:
arm64
- 型別:
vm ioctl
- 引數:
struct kvm_arm_counter_offset (in)
- 返回值:
成功時為 0,出錯時 < 0
此功能指示使用者空間能夠使用 KVM_ARM_SET_CNT_OFFSET ioctl 和以下資料結構將單個 VM 範圍的偏移量應用於客戶機檢視的虛擬計數器和物理計數器
struct kvm_arm_counter_offset {
__u64 counter_offset;
__u64 reserved;
};
該偏移量描述了從虛擬和物理計數器檢視中減去的計數器週期數(類似於 CNTVOFF_EL2 和 CNTPOFF_EL2 系統暫存器的效果,但僅是全域性的)。 該偏移量始終適用於此 VM 的所有 vcpu(已建立或在此 ioctl 之後建立)。
使用者空間有責任根據客戶機計數器的先前值來計算偏移量。
“reserved”欄位的任何非 0 值都可能導致返回錯誤 (-EINVAL)。 如果併發發出任何 vcpu ioctl,此 ioctl 也會返回 -EBUSY。
請注意,使用此 ioctl 會導致 KVM 忽略後續使用者空間使用 SET_ONE_REG 介面寫入 CNTVCT_EL0 和 CNTPCT_EL0 暫存器的操作。 不會返回任何錯誤,但不會應用生成的偏移量。
4.139 KVM_ARM_GET_REG_WRITABLE_MASKS¶
- 功能:
KVM_CAP_ARM_SUPPORTED_REG_MASK_RANGES
- 架構:
arm64
- 型別:
vm ioctl
- 引數:
struct reg_mask_range (in/out)
- 返回值:
成功時為 0,出錯時 < 0
#define KVM_ARM_FEATURE_ID_RANGE 0
#define KVM_ARM_FEATURE_ID_RANGE_SIZE (3 * 8 * 8)
struct reg_mask_range {
__u64 addr; /* Pointer to mask array */
__u32 range; /* Requested range */
__u32 reserved[13];
};
此 ioctl 將所選暫存器範圍的可寫掩碼複製到使用者空間。
addr 欄位是指向 KVM 將可寫掩碼複製到的目標陣列的指標。
range 欄位表示請求的暫存器範圍。對於 KVM_CAP_ARM_SUPPORTED_REG_MASK_RANGES 功能,KVM_CHECK_EXTENSION 返回支援的範圍,表示為一組標誌。每個標誌的位索引表示 range 欄位的可能值。所有其他值都保留供將來使用,KVM 可能會返回錯誤。
reserved[13] 陣列保留供將來使用,應為 0,否則 KVM 可能會返回錯誤。
KVM_ARM_FEATURE_ID_RANGE (0)¶
Feature ID 範圍定義為 AArch64 系統暫存器空間,其中 op0==3,op1=={0, 1, 3},CRn==0,CRm=={0-7},op2=={0-7}。
由 addr 指向的返回的掩碼陣列由宏 ARM64_FEATURE_ID_RANGE_IDX(op0, op1, crn, crm, op2) 索引,允許使用者空間知道對於由 op0, op1, crn, crm, op2 描述的系統暫存器,哪些欄位可以更改。KVM 拒絕 ID 暫存器值,這些值描述了系統支援的功能的超集。
4.140 KVM_SET_USER_MEMORY_REGION2¶
- 功能:
KVM_CAP_USER_MEMORY2
- 架構:
全部
- 型別:
vm ioctl
- 引數:
struct kvm_userspace_memory_region2 (in)
- 返回值:
成功時為 0,出錯時為 -1
KVM_SET_USER_MEMORY_REGION2 是 KVM_SET_USER_MEMORY_REGION 的擴充套件,允許將 guest_memfd 記憶體對映到 guest 中。所有與 KVM_SET_USER_MEMORY_REGION 共享的欄位都相同。使用者空間可以在標誌中設定 KVM_MEM_GUEST_MEMFD,以使 KVM 將記憶體區域繫結到給定的 guest_memfd 範圍 [guest_memfd_offset, guest_memfd_offset + memory_size]。目標 guest_memfd 必須指向通過當前 VM 上的 KVM_CREATE_GUEST_MEMFD 建立的檔案,並且目標範圍不能繫結到任何其他記憶體區域。所有標準邊界檢查都適用(使用常識)。
struct kvm_userspace_memory_region2 {
__u32 slot;
__u32 flags;
__u64 guest_phys_addr;
__u64 memory_size; /* bytes */
__u64 userspace_addr; /* start of the userspace allocated memory */
__u64 guest_memfd_offset;
__u32 guest_memfd;
__u32 pad1;
__u64 pad2[14];
};
KVM_MEM_GUEST_MEMFD 區域_必須_具有有效的 guest_memfd(私有記憶體)和 userspace_addr(共享記憶體)。但是,userspace_addr 的 “有效” 僅表示地址本身必須是合法的使用者空間地址。在 KVM_SET_USER_MEMORY_REGION2 時,userspace_addr 的後備對映不需要有效/填充,例如,共享記憶體可以按需延遲對映/分配。
將 gfn 對映到 guest 中時,KVM 基於 gfn 的 KVM_MEMORY_ATTRIBUTE_PRIVATE 狀態選擇共享或私有,即使用 userspace_addr 或 guest_memfd。在 VM 建立時,所有記憶體都是共享的,即所有 gfn 的 PRIVATE 屬性都是 ‘0’。使用者空間可以透過根據需要切換 KVM_MEMORY_ATTRIBUTE_PRIVATE(透過 KVM_SET_MEMORY_ATTRIBUTES)來控制記憶體是共享的還是私有的。
S390:¶
如果 VM 設定了 KVM_VM_S390_UCONTROL 標誌,則返回 -EINVAL。如果在受保護的 VM 上呼叫,則返回 -EINVAL。
4.141 KVM_SET_MEMORY_ATTRIBUTES¶
- 功能:
KVM_CAP_MEMORY_ATTRIBUTES
- 架構:
x86
- 型別:
vm ioctl
- 引數:
struct kvm_memory_attributes (in)
- 返回值:
成功時為 0,出錯時 <0
KVM_SET_MEMORY_ATTRIBUTES 允許使用者空間為一系列客戶機物理記憶體設定記憶體屬性。
struct kvm_memory_attributes {
__u64 address;
__u64 size;
__u64 attributes;
__u64 flags;
};
#define KVM_MEMORY_ATTRIBUTE_PRIVATE (1ULL << 3)
地址和大小必須按頁對齊。支援的屬性可以透過 KVM_CAP_MEMORY_ATTRIBUTES 上的 ioctl(KVM_CHECK_EXTENSION) 檢索。如果在 VM 上執行,KVM_CAP_MEMORY_ATTRIBUTES 精確地返回該 VM 支援的屬性。如果在系統範圍內執行,KVM_CAP_MEMORY_ATTRIBUTES 返回 KVM 支援的所有屬性。目前定義的唯一屬性是 KVM_MEMORY_ATTRIBUTE_PRIVATE,它將關聯的 gfn 標記為客戶機私有記憶體。
請注意,沒有 “get” API。使用者空間負責根據需要顯式跟蹤 gfn/頁的狀態。
“flags” 欄位保留供將來擴充套件使用,必須為 “0”。
4.142 KVM_CREATE_GUEST_MEMFD¶
- 功能:
KVM_CAP_GUEST_MEMFD
- 架構:
無
- 型別:
vm ioctl
- 引數:
struct kvm_create_guest_memfd(in)
- 返回值:
成功時返回檔案描述符,出錯時返回 <0
KVM_CREATE_GUEST_MEMFD 建立一個匿名檔案並返回指向它的檔案描述符。guest_memfd 檔案大致類似於透過 memfd_create() 建立的檔案,例如,guest_memfd 檔案駐留在 RAM 中,具有易失性儲存,並且在最後一個引用被刪除時自動釋放。與 “常規” memfd_create() 檔案不同,guest_memfd 檔案繫結到其擁有的虛擬機器(見下文),不能由使用者空間對映、讀取或寫入,並且無法調整大小(guest_memfd 檔案確實支援 PUNCH_HOLE)。
struct kvm_create_guest_memfd {
__u64 size;
__u64 flags;
__u64 reserved[6];
};
從概念上講,支援 guest_memfd 檔案的 inode 表示物理記憶體,即作為事物耦合到虛擬機器,而不是耦合到 “struct kvm”。該檔案本身繫結到 “struct kvm”,是該例項對底層記憶體的檢視,例如,有效地提供了客戶機地址到主機記憶體的轉換。這允許用於使用多個 KVM 結構來管理單個虛擬機器的使用場景,例如,在執行虛擬機器的 intrahost 遷移時。
KVM 目前僅支援透過 KVM_SET_USER_MEMORY_REGION2 對映 guest_memfd,更具體地說,是透過 “struct kvm_userspace_memory_region2” 中的 guest_memfd 和 guest_memfd_offset 欄位,其中 guest_memfd_offset 是進入 guest_memfd 例項的偏移量。對於給定的 guest_memfd 檔案,每個頁面最多可以有一個對映,即不允許將多個記憶體區域繫結到單個 guest_memfd 範圍(任意數量的記憶體區域可以繫結到單個 guest_memfd 檔案,但繫結的範圍不得重疊)。
有關更多詳細資訊,請參見 KVM_SET_USER_MEMORY_REGION2。
4.143 KVM_PRE_FAULT_MEMORY¶
- 功能:
KVM_CAP_PRE_FAULT_MEMORY
- 架構:
無
- 型別:
vcpu ioctl
- 引數:
struct kvm_pre_fault_memory (in/out)
- 返回值:
如果至少處理了一個頁面,則為 0,如果出錯,則為 < 0
錯誤
EINVAL
指定的 gpa 和 size 無效(例如,未按頁面對齊,導致溢位,或者大小為零)。
ENOENT
指定的 gpa 超出了定義的記憶體插槽。
EINTR
未遮蔽的訊號正在掛起,並且未處理任何頁面。
EFAULT
引數地址無效。
EOPNOTSUPP
虛擬機器監控程式不支援為 GPA 對映記憶體,和/或對於當前的 vCPU 狀態/模式不支援。
EIO
意外的錯誤情況(也會導致 WARN)
struct kvm_pre_fault_memory {
/* in/out */
__u64 gpa;
__u64 size;
/* in */
__u64 flags;
__u64 padding[5];
};
KVM_PRE_FAULT_MEMORY 填充 KVM 的第 2 階段頁表,用於對映當前 vCPU 狀態的記憶體。KVM 對映記憶體的方式與 vCPU 生成第 2 階段讀取頁面錯誤的方式相同,例如,根據需要進行記憶體錯誤,但不會破壞 CoW。但是,KVM 不會將任何新建立的第 2 階段 PTE 標記為已訪問。
對於機密 VM 型別,如果在客戶機 “最終確定”/測量之前有一個私有客戶機記憶體的初始設定,則只有在完成所有必要的設定以將客戶機置於 “最終確定” 狀態之後,才能發出此 ioctl,以便可以可靠地確保上述語義。
在某些情況下,多個 vCPU 可能共享頁表。在這種情況下,可以並行呼叫 ioctl。
當 ioctl 返回時,輸入值會更新為指向剩餘範圍。如果在返回時 size > 0,則呼叫方可以使用相同的 struct kvm_map_memory 引數再次發出 ioctl。
陰影頁表無法支援此 ioctl,因為它們由虛擬地址或巢狀的客戶機物理地址索引。當客戶機使用陰影頁表時(例如,因為它執行具有巢狀頁表的巢狀客戶機),呼叫此 ioctl 將失敗,並顯示 EOPNOTSUPP,即使 KVM_CHECK_EXTENSION 報告該功能存在。
flags 目前必須為零。
5. kvm_run 結構¶
應用程式程式碼透過 mmap() 一個 vcpu fd 來獲取指向 kvm_run 結構的指標。從那時起,應用程式程式碼可以透過在呼叫 KVM_RUN ioctl 之前更改 kvm_run 中的欄位來控制執行,並透過查詢結構成員來獲取有關 KVM_RUN 返回原因的資訊。
struct kvm_run {
/* in */
__u8 request_interrupt_window;
請求 KVM_RUN 在可以向 guest 中注入外部中斷時返回。與 KVM_INTERRUPT 結合使用時很有用。
__u8 immediate_exit;
此欄位在 KVM_RUN 啟動時輪詢一次;如果非零,KVM_RUN 會立即退出,返回 -EINTR。在使用訊號將 VCPU “踢” 出 KVM_RUN 的常見情況下,可以使用此欄位來避免使用可伸縮性較差的 KVM_SET_SIGNAL_MASK。使用者空間可以設定一個訊號處理程式,將 run->immediate_exit 設定為非零值,而不是在 KVM_RUN 之外阻止訊號。
如果 KVM_CAP_IMMEDIATE_EXIT 不可用,則忽略此欄位。
__u8 padding1[6];
/* out */
__u32 exit_reason;
當 KVM_RUN 成功返回(返回值 0)時,它會通知應用程式程式碼 KVM_RUN 返回的原因。此欄位的允許值在下面詳細說明。
__u8 ready_for_interrupt_injection;
如果已指定 request_interrupt_window,則此欄位指示現在可以使用 KVM_INTERRUPT 注入中斷。
__u8 if_flag;
當前中斷標誌的值。僅當未使用核心內本地 APIC 時才有效。
__u16 flags;
更多特定於體系結構的標誌,詳細說明了可能影響裝置行為的 VCPU 狀態。當前定義的標誌
/* x86, set if the VCPU is in system management mode */
#define KVM_RUN_X86_SMM (1 << 0)
/* x86, set if bus lock detected in VM */
#define KVM_RUN_X86_BUS_LOCK (1 << 1)
/* x86, set if the VCPU is executing a nested (L2) guest */
#define KVM_RUN_X86_GUEST_MODE (1 << 2)
/* arm64, set for KVM_EXIT_DEBUG */
#define KVM_DEBUG_ARCH_HSR_HIGH_VALID (1 << 0)
/* in (pre_kvm_run), out (post_kvm_run) */
__u64 cr8;
cr8 暫存器的值。僅當未使用核心內本地 APIC 時才有效。既是輸入又是輸出。
__u64 apic_base;
APIC BASE msr 的值。僅當未使用核心內本地 APIC 時才有效。既是輸入又是輸出。
union {
/* KVM_EXIT_UNKNOWN */
struct {
__u64 hardware_exit_reason;
} hw;
如果 exit_reason 為 KVM_EXIT_UNKNOWN,則 vcpu 由於未知原因退出。有關更多特定於體系結構的資訊,請參見 hardware_exit_reason。
/* KVM_EXIT_FAIL_ENTRY */
struct {
__u64 hardware_entry_failure_reason;
__u32 cpu; /* if KVM_LAST_CPU */
} fail_entry;
如果 exit_reason 為 KVM_EXIT_FAIL_ENTRY,則由於未知原因無法執行 vcpu。有關更多特定於體系結構的資訊,請參見 hardware_entry_failure_reason。
/* KVM_EXIT_EXCEPTION */
struct {
__u32 exception;
__u32 error_code;
} ex;
未使用。
/* KVM_EXIT_IO */
struct {
#define KVM_EXIT_IO_IN 0
#define KVM_EXIT_IO_OUT 1
__u8 direction;
__u8 size; /* bytes */
__u16 port;
__u32 count;
__u64 data_offset; /* relative to kvm_run start */
} io;
如果 exit_reason 為 KVM_EXIT_IO,則 vcpu 執行了埠 I/O 指令,而該指令無法由 kvm 滿足。data_offset 描述了資料所在的位置(KVM_EXIT_IO_OUT)或 kvm 希望應用程式程式碼放置資料以用於下一個 KVM_RUN 呼叫的位置(KVM_EXIT_IO_IN)。資料格式是一個壓縮陣列。
/* KVM_EXIT_DEBUG */
struct {
struct kvm_debug_exit_arch arch;
} debug;
如果 exit_reason 為 KVM_EXIT_DEBUG,則 vcpu 正在處理除錯事件,併為此返回特定於體系結構的資訊。
/* KVM_EXIT_MMIO */
struct {
__u64 phys_addr;
__u8 data[8];
__u32 len;
__u8 is_write;
} mmio;
如果 exit_reason 為 KVM_EXIT_MMIO,則 vcpu 執行了記憶體對映 I/O 指令,而該指令無法由 kvm 滿足。如果 ‘is_write’ 為 true,則 ‘data’ 成員包含寫入的資料,否則應由應用程式程式碼填充。
‘data’ 成員在其前 ‘len’ 個位元組中包含該值,就像 VCPU 直接對位元組陣列執行適當寬度的載入或儲存一樣。
注意
對於 KVM_EXIT_IO、KVM_EXIT_MMIO、KVM_EXIT_OSI、KVM_EXIT_PAPR、KVM_EXIT_XEN、KVM_EXIT_EPR、KVM_EXIT_HYPERCALL、KVM_EXIT_TDX、KVM_EXIT_X86_RDMSR 和 KVM_EXIT_X86_WRMSR,只有在使用者空間透過 KVM_RUN 重新進入核心後,相應的操作才會完成(並且客戶機狀態保持一致)。核心端將首先完成未完成的操作,然後檢查掛起的訊號。
操作的掛起狀態不會儲存在對使用者空間可見的狀態中,因此使用者空間應確保在執行即時遷移之前完成操作。使用者空間可以使用未遮蔽的訊號掛起或將 immediate_exit 欄位設定為完成掛起的操作,而無需允許執行任何其他指令來重新進入客戶機。
/* KVM_EXIT_HYPERCALL */
struct {
__u64 nr;
__u64 args[6];
__u64 ret;
__u64 flags;
} hypercall;
強烈建議使用者空間使用 KVM_EXIT_IO (x86) 或 KVM_EXIT_MMIO(除 s390 之外的所有體系結構)來實現需要客戶機與主機使用者空間互動的功能。
注意
KVM_EXIT_IO 比 KVM_EXIT_MMIO 快得多。
對於 arm64:¶
可以根據 SMCCC 過濾器的配置啟用 SMCCC 退出。有關更多詳細資訊,請參見 通用 vm 介面 KVM_ARM_SMCCC_FILTER。
nr 包含客戶機的 SMCCC 呼叫的函式 ID。使用者空間應使用 KVM_GET_ONE_REG ioctl 從 vCPU 的 GPR 中檢索呼叫引數。
flags的定義KVM_HYPERCALL_EXIT_SMC:指示客戶機使用 SMC 通路來啟動 SMCCC 呼叫。如果此位為 0,則客戶機使用 HVC 通路進行 SMCCC 呼叫。KVM_HYPERCALL_EXIT_16BIT:指示客戶機使用 16 位指令來啟動 SMCCC 呼叫。如果此位為 0,則客戶機使用 32 位指令。AArch64 客戶機始終將此位設定為 0。
在退出點,PC 指向緊跟在陷阱指令之後的指令。
/* KVM_EXIT_TPR_ACCESS */
struct {
__u64 rip;
__u32 is_write;
__u32 pad;
} tpr_access;
要記錄(KVM_TPR_ACCESS_REPORTING)。
/* KVM_EXIT_S390_SIEIC */
struct {
__u8 icptcode;
__u64 mask; /* psw upper half */
__u64 addr; /* psw lower half */
__u16 ipa;
__u32 ipb;
} s390_sieic;
s390 特定。
/* KVM_EXIT_S390_RESET */
#define KVM_S390_RESET_POR 1
#define KVM_S390_RESET_CLEAR 2
#define KVM_S390_RESET_SUBSYSTEM 4
#define KVM_S390_RESET_CPU_INIT 8
#define KVM_S390_RESET_IPL 16
__u64 s390_reset_flags;
s390 特定。
/* KVM_EXIT_S390_UCONTROL */
struct {
__u64 trans_exc_code;
__u32 pgm_code;
} s390_ucontrol;
s390 特定。使用者控制的虛擬機器 (KVM_VM_S390_UNCONTROL) 的主機頁表上發生了頁面錯誤,核心無法解決。程式程式碼和轉換異常程式碼(放置在 cpu 的低核心中)在此處以 z 體系結構操作原則手冊中動態地址轉換 (DAT) 章節中的定義呈現。
/* KVM_EXIT_DCR */
struct {
__u32 dcrn;
__u32 data;
__u8 is_write;
} dcr;
已棄用 - 曾用於 440 KVM。
/* KVM_EXIT_OSI */
struct {
__u64 gprs[32];
} osi;
MOL 使用一個特殊的管理程式呼叫介面,它稱之為 ‘OSI’。要啟用它,我們會捕獲管理程式呼叫並退出,並使用包含所有客戶機 gpr 的此退出結構。
如果 exit_reason 為 KVM_EXIT_OSI,則 vcpu 觸發了此類管理程式呼叫。使用者空間現在可以處理管理程式呼叫,並在完成後根據需要修改 gpr。在客戶機條目中,所有客戶機 GPR 都將被此結構中的值替換。
/* KVM_EXIT_PAPR_HCALL */
struct {
__u64 nr;
__u64 ret;
__u64 args[9];
} papr_hcall;
這在 64 位 PowerPC 上使用,用於模擬 pSeries 分割槽,例如,在 qemu 中使用 ‘pseries’ 機器型別。當客戶機使用 ‘sc 1’ 指令進行管理程式呼叫時,會發生這種情況。‘nr’ 欄位包含管理程式呼叫號(來自客戶機 R3),‘args’ 包含引數(來自客戶機 R4 - R12)。使用者空間應將返回程式碼放入 ‘ret’ 中,並將任何額外的返回值放入 args[] 中。可能的管理程式呼叫在 Power Architecture Platform Requirements (PAPR) 文件中定義,該文件可從 www.power.org 獲得(需要免費的開發人員註冊才能訪問)。
/* KVM_EXIT_S390_TSCH */
struct {
__u16 subchannel_id;
__u16 subchannel_nr;
__u32 io_int_parm;
__u32 io_int_word;
__u32 ipb;
__u8 dequeued;
} s390_tsch;
s390 特定。當 KVM_CAP_S390_CSS_SUPPORT 已啟用且 TEST SUBCHANNEL 被攔截時,會發生此退出。如果已取消排隊,則目標子通道的掛起 I/O 中斷已取消排隊,並且 subchannel_id、subchannel_nr、io_int_parm 和 io_int_word 包含該中斷的引數。ipb 是指令引數解碼所必需的。
/* KVM_EXIT_EPR */
struct {
__u32 epr;
} epr;
在 FSL BookE PowerPC 晶片上,中斷控制器具有到核心的快速補丁中斷確認路徑。當核心成功傳遞中斷時,它會自動使用中斷向量號填充 EPR 暫存器,並確認中斷控制器內部的中斷。
如果中斷控制器位於使用者空間中,我們需要透過它執行中斷確認週期,以使用此退出提取下一個要傳遞的中斷向量。
只要 KVM_CAP_PPC_EPR 都已啟用並且剛剛將外部中斷傳遞到客戶機中,就會觸發它。使用者空間應將確認的中斷向量放入 ‘epr’ 欄位中。
/* KVM_EXIT_SYSTEM_EVENT */
struct {
#define KVM_SYSTEM_EVENT_SHUTDOWN 1
#define KVM_SYSTEM_EVENT_RESET 2
#define KVM_SYSTEM_EVENT_CRASH 3
#define KVM_SYSTEM_EVENT_WAKEUP 4
#define KVM_SYSTEM_EVENT_SUSPEND 5
#define KVM_SYSTEM_EVENT_SEV_TERM 6
#define KVM_SYSTEM_EVENT_TDX_FATAL 7
__u32 type;
__u32 ndata;
__u64 data[16];
} system_event;
如果 exit_reason 為 KVM_EXIT_SYSTEM_EVENT,則 vcpu 使用某些特定於體系結構的機制(管理程式呼叫或某些特殊指令)觸發了系統級事件。對於 ARM64,這是使用來自 vcpu 的基於 HVC 指令的 PSCI 呼叫觸發的。
‘type’ 欄位描述系統級事件型別。‘type’ 的有效值為
KVM_SYSTEM_EVENT_SHUTDOWN -- 客戶機已請求關閉 VM。使用者空間沒有義務遵守此請求,如果它確實遵守此請求,則不需要同步銷燬 VM(即,它可以在最終發生關閉之前再次呼叫 KVM_RUN)。
KVM_SYSTEM_EVENT_RESET -- 客戶機已請求重置 VM。與 SHUTDOWN 一樣,使用者空間可以選擇忽略該請求,或者計劃在將來發生重置,並且可以再次呼叫 KVM_RUN。
KVM_SYSTEM_EVENT_CRASH -- 客戶機發生崩潰,客戶機已請求崩潰情況維護。使用者空間可以選擇忽略該請求,或者收集 VM 記憶體核心轉儲和/或重置/關閉 VM。
KVM_SYSTEM_EVENT_SEV_TERM -- AMD SEV 客戶機請求終止。客戶機的 GHCB 的客戶機物理地址儲存在 data[0] 中。
KVM_SYSTEM_EVENT_TDX_FATAL -- TDX 客戶機報告了一個致命錯誤狀態。KVM 不進行任何解析或轉換,它只是將 16 個通用暫存器轉儲到使用者空間,並按指令編碼中 x86-64 通用暫存器的 4 位索引的升序排列,如 Intel SDM 中定義的那樣。
KVM_SYSTEM_EVENT_WAKEUP -- 退出的 vCPU 處於掛起狀態,並且 KVM 識別到一個喚醒事件。使用者空間可以透過將退出的 vCPU 標記為可執行來遵守此事件,或者拒絕它並再次呼叫 KVM_RUN。
KVM_SYSTEM_EVENT_SUSPEND -- 客戶機已請求掛起 VM。
如果存在 KVM_CAP_SYSTEM_EVENT_DATA,則 ‘data’ 欄位可以包含特定於體系結構的系統級事件資訊。只有資料陣列的第一個 ndata 項(可能為零)有效。
對於 arm64,如果客戶機根據 PSCI 規範的 v1.1 發出了 SYSTEM_RESET2 呼叫,則 data[0] 設定為 KVM_SYSTEM_EVENT_RESET_FLAG_PSCI_RESET2。
對於 arm64,如果客戶機根據 PSCI 規範的 v1.3 發出了 SYSTEM_OFF2 呼叫,則 data[0] 設定為 KVM_SYSTEM_EVENT_SHUTDOWN_FLAG_PSCI_OFF2。
對於 RISC-V,data[0] 設定為
sbi_system_reset呼叫的第二個引數的值。
以前的 Linux 版本在此結構中定義了一個 flags 成員。該欄位現在別名為 data[0]。使用者空間可以假定只有當 ndata 大於 0 時才會寫入它。
對於 arm/arm64:¶
使用 KVM_CAP_ARM_SYSTEM_SUSPEND VM 功能啟用 KVM_SYSTEM_EVENT_SUSPEND 退出。如果客戶機呼叫 PSCI SYSTEM_SUSPEND 函式,KVM 將使用此事件型別退出到使用者空間。
使用者空間完全有責任根據 ARM DEN0022D.b 5.19 “SYSTEM_SUSPEND” 實現 PSCI SYSTEM_SUSPEND 呼叫。KVM 在退出到使用者空間之前不會更改 vCPU 的狀態,因此呼叫引數會保留在 vCPU 暫存器中。
使用者空間_必須_採取行動來處理此類退出。它必須
遵守客戶機掛起 VM 的請求。使用者空間可以透過將呼叫 vCPU 的狀態設定為 KVM_MP_STATE_SUSPENDED 來請求核心內模擬掛起。當恢復呼叫 vCPU 時,使用者空間必須根據傳遞給 PSCI 函式的引數配置 vCPU 的狀態。有關函式引數的詳細資訊,請參見 ARM DEN0022D.b 5.19.1 “預期用途”。
拒絕客戶機掛起 VM 的請求。有關可能的返回值,請參見 ARM DEN0022D.b 5.19.2 “呼叫者職責”。
當啟用 PSCI v1.3 時,將啟用使用 PSCI SYSTEM_OFF2 呼叫的休眠。如果客戶機呼叫 PSCI SYSTEM_OFF2 函式,KVM 將使用 KVM_SYSTEM_EVENT_SHUTDOWN 事件型別退出到使用者空間,並且 data[0] 設定為 KVM_SYSTEM_EVENT_SHUTDOWN_FLAG_PSCI_OFF2。SYSTEM_OFF2 函式唯一支援的休眠型別是 HIBERNATE_OFF。
/* KVM_EXIT_IOAPIC_EOI */
struct {
__u8 vector;
} eoi;
指示 VCPU 的核心內本地 APIC 收到了級別觸發的 IOAPIC 中斷的 EOI。僅當 IOAPIC 在使用者空間中實現時(即,啟用 KVM_CAP_SPLIT_IRQCHIP),才會觸發此退出;使用者空間 IOAPIC 應處理 EOI,並在中斷仍被斷言時重新觸發中斷。Vector 是收到 EOI 的 LAPIC 中斷向量。
struct kvm_hyperv_exit {
#define KVM_EXIT_HYPERV_SYNIC 1
#define KVM_EXIT_HYPERV_HCALL 2
#define KVM_EXIT_HYPERV_SYNDBG 3
__u32 type;
__u32 pad1;
union {
struct {
__u32 msr;
__u32 pad2;
__u64 control;
__u64 evt_page;
__u64 msg_page;
} synic;
struct {
__u64 input;
__u64 result;
__u64 params[2];
} hcall;
struct {
__u32 msr;
__u32 pad2;
__u64 control;
__u64 status;
__u64 send_page;
__u64 recv_page;
__u64 pending_page;
} syndbg;
} u;
};
/* KVM_EXIT_HYPERV */
struct kvm_hyperv_exit hyperv;
指示 VCPU 退出到使用者空間以處理與 Hyper-V 模擬相關的一些任務。
‘type’ 的有效值為
KVM_EXIT_HYPERV_SYNIC -- 同步通知使用者空間有關
Hyper-V SynIC 狀態更改。通知用於重新對映 SynIC 事件/訊息頁面,以及在使用者空間中啟用/停用 SynIC 訊息/事件處理。
KVM_EXIT_HYPERV_SYNDBG -- 同步通知使用者空間有關
Hyper-V Synthetic 偵錯程式狀態更改。通知用於更新 pending_page 位置,或傳送控制命令(傳送位於 send_page 中的緩衝區或接收到 recv_page 的緩衝區)。
/* KVM_EXIT_ARM_NISV */
struct {
__u64 esr_iss;
__u64 fault_ipa;
} arm_nisv;
用於 arm64 系統。如果客戶機訪問了不在 memslot 中的記憶體,KVM 通常會返回到使用者空間並要求它代表其進行 MMIO 模擬。但是,對於某些型別的指令,不提供指令解碼(方向,記憶體訪問的長度),並且從 VM 中提取和解碼指令過於複雜,無法駐留在核心中。
從歷史上看,當發生這種情況時,KVM 會列印警告並終止 VM。KVM 假定如果客戶機訪問了非 memslot 記憶體,則它正在嘗試執行 I/O,而這無法模擬,並且警告訊息也相應地措辭。但是,更常見的情況是,客戶機錯誤導致在客戶機記憶體區域之外進行訪問,如果訪問未落在 I/O 視窗中,則應導致更有意義的警告訊息和客戶機中的外部中止。
使用者空間實現可以查詢 KVM_CAP_ARM_NISV_TO_USER,並在 VM 建立時啟用此功能。完成此操作後,這些型別的錯誤將返回到使用者空間,並顯示 KVM_EXIT_ARM_NISV,其中 esr_iss 欄位中包含來自 ESR_EL2 的有效位,fault_ipa 欄位中包含錯誤的 IPA。使用者空間可以修復訪問(如果它實際上是 I/O 訪問,方法是從客戶機記憶體中解碼指令(如果非常勇敢)並繼續執行客戶機),或者它可以決定掛起、轉儲或重新啟動客戶機。
請注意,KVM 不會像對 KVM_EXIT_MMIO 所做的那樣跳過錯誤指令,但是如果使用者空間決定解碼和模擬指令,則使用者空間必須模擬對處理狀態的任何更改。
此功能不適用於受保護的 VM,因為使用者空間無法訪問執行模擬所需的狀態。相反,會直接在客戶機中注入資料中止異常。請注意,如果在受保護的 VM 上下文之外查詢,將會報告 KVM_CAP_ARM_NISV_TO_USER,但如果在受保護的 VM 檔案描述符上查詢,則不會公開該功能。
/* KVM_EXIT_X86_RDMSR / KVM_EXIT_X86_WRMSR */
struct {
__u8 error; /* user -> kernel */
__u8 pad[7];
__u32 reason; /* kernel -> user */
__u32 index; /* kernel -> user */
__u64 data; /* kernel <-> user */
} msr;
用於 x86 系統。啟用 VM 功能 KVM_CAP_X86_USER_SPACE_MSR 後,對將呼叫 #GP 的 MSR 的訪問(由 KVM 核心程式碼)可能會改為觸發讀取的 KVM_EXIT_X86_RDMSR 退出和寫入的 KVM_EXIT_X86_WRMSR 退出。
“reason” 欄位指定 MSR 攔截髮生的原因。僅當在 ENABLE_CAP 期間請求特定原因時,使用者空間才會收到 MSR 退出。當前有效的退出原因是
KVM_MSR_EXIT_REASON_UNKNOWN |
訪問 KVM 未知的 MSR |
KVM_MSR_EXIT_REASON_INVAL |
訪問無效 MSR 或保留位 |
KVM_MSR_EXIT_REASON_FILTER |
訪問被 KVM_X86_SET_MSR_FILTER 阻止 |
對於 KVM_EXIT_X86_RDMSR,“index” 欄位告訴使用者空間客戶機要讀取哪個 MSR。要透過成功的讀取來響應此請求,使用者空間將相應的資料寫入 “data” 欄位,並且必須繼續客戶機執行以確保讀取的資料傳輸到客戶機暫存器狀態中。
如果 RDMSR 請求不成功,則使用者空間透過在 “error” 欄位中放置 “1” 來指示。當再次執行 VCPU 時,這將在客戶機中注入 #GP。
對於 KVM_EXIT_X86_WRMSR,“index” 欄位告訴使用者空間客戶機要寫入哪個 MSR。完成對該事件的處理後,使用者空間必須繼續 vCPU 執行。如果 MSR 寫入不成功,則使用者空間也會將 “error” 欄位設定為 “1”。
有關與 MSR 篩選互動的詳細資訊,請參見 KVM_X86_SET_MSR_FILTER。
struct kvm_xen_exit {
#define KVM_EXIT_XEN_HCALL 1
__u32 type;
union {
struct {
__u32 longmode;
__u32 cpl;
__u64 input;
__u64 result;
__u64 params[6];
} hcall;
} u;
};
/* KVM_EXIT_XEN */
struct kvm_hyperv_exit xen;
指示 VCPU 退出到使用者空間以處理與 Xen 模擬相關的一些任務。
‘type’ 的有效值為
KVM_EXIT_XEN_HCALL -- 同步通知使用者空間有關 Xen 管理程式呼叫。使用者空間應將管理程式呼叫結果放入相應的欄位中,然後再呼叫 KVM_RUN。
/* KVM_EXIT_RISCV_SBI */
struct {
unsigned long extension_id;
unsigned long function_id;
unsigned long args[6];
unsigned long ret[2];
} riscv_sbi;
如果退出原因是 KVM_EXIT_RISCV_SBI,則表示 VCPU 完成了一個 SBI 呼叫,該呼叫未由 KVM RISC-V 核心模組處理。SBI 呼叫的詳細資訊在 kvm_run 結構的 ‘riscv_sbi’ 成員中可用。‘riscv_sbi’ 的 ‘extension_id’ 欄位表示 SBI 擴充套件 ID,而 ‘function_id’ 欄位表示給定 SBI 擴充套件的函式 ID。‘riscv_sbi’ 的 ‘args’ 陣列欄位表示 SBI 呼叫的引數,而 ‘ret’ 陣列欄位表示返回值。使用者空間應在恢復 VCPU 之前更新 SBI 呼叫的返回值。有關 RISC-V SBI 規範的更多詳細資訊,請參見 https://github.com/riscv/riscv-sbi-doc。
/* KVM_EXIT_MEMORY_FAULT */
struct {
#define KVM_MEMORY_EXIT_FLAG_PRIVATE (1ULL << 3)
__u64 flags;
__u64 gpa;
__u64 size;
} memory_fault;
KVM_EXIT_MEMORY_FAULT 指示 vCPU 遇到 KVM 無法解決的記憶體錯誤。‘gpa’ 和 ‘size’(以位元組為單位)描述了錯誤的客戶機物理地址範圍 [gpa, gpa + size)。‘flags’ 欄位描述了可能相關的錯誤訪問屬性
KVM_MEMORY_EXIT_FLAG_PRIVATE - 設定後,指示記憶體錯誤發生在私有記憶體訪問上。清除後,指示錯誤發生在共享訪問上。
注意!在所有 KVM 退出原因中,KVM_EXIT_MEMORY_FAULT 是獨一無二的,因為它伴隨的返回程式碼為 ‘-1’,而不是 ‘0’!當 KVM 以 KVM_EXIT_MEMORY_FAULT 退出時,errno 將始終設定為 EFAULT 或 EHWPOISON,對於所有其他錯誤編號,使用者空間應假定 kvm_run.exit_reason 已過時/未定義。
/* KVM_EXIT_NOTIFY */
struct {
#define KVM_NOTIFY_CONTEXT_INVALID (1 << 0)
__u32 flags;
} notify;
用於 x86 系統。當啟用 VM 功能 KVM_CAP_X86_NOTIFY_VMEXIT 時,如果在 VM 非根模式下指定的時間內未發生任何事件視窗,則會生成 VM 退出。一旦啟用該功能時設定了 KVM_X86_NOTIFY_VMEXIT_USER,它將退出到使用者空間,退出原因為 KVM_EXIT_NOTIFY,以便進一步處理。“flags”欄位包含更詳細的資訊。
“flags”的有效值為
KVM_NOTIFY_CONTEXT_INVALID -- VM 上下文已損壞,在 VMCS 中無效。如果恢復目標 VM,可能會導致未知結果。
/* KVM_EXIT_TDX */
struct {
__u64 flags;
__u64 nr;
union {
struct {
u64 ret;
u64 data[5];
} unknown;
struct {
u64 ret;
u64 gpa;
u64 size;
} get_quote;
struct {
u64 ret;
u64 leaf;
u64 r11, r12, r13, r14;
} get_tdvmcall_info;
};
} tdx;
處理來自 guest 的 TDVMCALL。 KVM 根據 Guest-Hypervisor Communication Interface (GHCI) 規範轉發選擇的 TDVMCALL;KVM 以最小的更改將這些請求橋接到使用者空間 VMM,將輸入放置在聯合中,並在重新進入時將其複製回 guest。
Flags 當前始終為零,而 nr 包含來自暫存器 R11 的 TDVMCALL 編號。聯合的其餘欄位提供 TDVMCALL 的輸入和輸出。目前定義了以下 nr 值
TDVMCALL_GET_QUOTE:guest 已請求生成 TD-Quote
由託管在主機上的 TD-Quoting Enclave 服務簽名。引數和返回值位於聯合的 get_quote 欄位中。gpa 欄位和 size 指定共享記憶體緩衝區的 guest 物理地址(不設定共享位)和大小,TDX guest 在該緩衝區中傳遞 TD 報告。ret 欄位表示 GetQuote 請求的返回值。當請求已成功排隊時,TDX guest 可以輪詢共享記憶體區域中的狀態欄位,以檢查 Quote 生成是否已完成。完成後,生成的 Quote 將透過同一緩衝區返回。
TDVMCALL_GET_TD_VM_CALL_INFO:guest 已請求支援
TDVMCALL 的狀態。給定葉的輸出值應放置在聯合的 get_tdvmcall_info 欄位的 r11 到 r14 欄位中。
KVM 可能會在未來新增對更多值的支援,這可能會導致使用者空間退出,即使沒有呼叫 KVM_ENABLE_CAP 或類似函式。在這種情況下,它將進入並帶有已有效的輸出欄位;在常見情況下,聯合的 unknown.ret 欄位將為 TDVMCALL_STATUS_SUBFUNC_UNSUPPORTED。如果使用者空間不希望支援 TDVMCALL,則無需執行任何操作。
/* Fix the size of the union. */
char padding[256];
};
/*
* shared registers between kvm and userspace.
* kvm_valid_regs specifies the register classes set by the host
* kvm_dirty_regs specified the register classes dirtied by userspace
* struct kvm_sync_regs is architecture specific, as well as the
* bits for kvm_valid_regs and kvm_dirty_regs
*/
__u64 kvm_valid_regs;
__u64 kvm_dirty_regs;
union {
struct kvm_sync_regs regs;
char padding[SYNC_REGS_SIZE_BYTES];
} s;
如果定義了 KVM_CAP_SYNC_REGS,這些欄位允許使用者空間訪問某些 guest 暫存器,而無需呼叫 SET/GET_*REGS。因此,如果使用者空間必須處理退出,我們可以避免一些系統呼叫開銷。使用者空間可以透過檢查 kvm_valid_regs 的特定位來查詢結構的有效性。這些位是特定於體系結構的,通常定義暫存器組的有效性。(例如,通用暫存器的一個位)
請注意,核心允許將 kvm_run 結構用作某些暫存器型別的主要儲存。因此,即使未設定 kvm_dirty_regs 中的相應位,核心也可以使用 kvm_run 中的值。
6. 可以在 vCPU 上啟用的功能¶
有一些功能在啟用時會改變虛擬 CPU 或虛擬機器的行為。要啟用它們,請參閱 4.37 KVM_ENABLE_CAP。
以下是功能列表以及啟用它們時它們對 vCPU 或虛擬機器的影響。
以下資訊與描述一起提供
- 架構
哪些指令集架構提供了此 ioctl。x86 包括 i386 和 x86_64。
- 目標
這是否是每個 vcpu 或每個 vm 的功能。
- 引數
該功能接受哪些引數。
- 返回值
返回值。未詳細說明常規錯誤號(EBADF、ENOMEM、EINVAL),但詳細說明了具有特定含義的錯誤。
6.1 KVM_CAP_PPC_OSI¶
- 架構:
ppc
- 目標:
vcpu
- 引數:
無
- 返回值:
成功時為 0;出錯時為 -1
此功能允許攔截 OSI 超級呼叫,否則這些呼叫將被視為要注入到 guest 中的普通系統呼叫。OSI 超級呼叫由 Mac-on-Linux 發明,用於在 guest 和主機之間建立標準化的通訊機制。
啟用此功能後,可能會發生 KVM_EXIT_OSI。
6.2 KVM_CAP_PPC_PAPR¶
- 架構:
ppc
- 目標:
vcpu
- 引數:
無
- 返回值:
成功時為 0;出錯時為 -1
此功能允許攔截 PAPR 超級呼叫。PAPR 超級呼叫使用超級呼叫指令“sc 1”完成。
它還將 guest 許可權級別設定為“supervisor”模式。通常,guest 在具有一些缺失功能的“hypervisor”許可權模式下執行。
除了上述之外,它還更改了 SDR1 的語義。在此模式下,SDR1 的 HTAB 地址部分包含 HVA 而不是 GPA,因為 PAPR 將 HTAB 對 guest 隱藏。
啟用此功能後,可能會發生 KVM_EXIT_PAPR_HCALL。
6.3 KVM_CAP_SW_TLB¶
- 架構:
ppc
- 目標:
vcpu
- 引數:
args[0] 是 struct kvm_config_tlb 的地址
- 返回值:
成功時為 0;出錯時為 -1
struct kvm_config_tlb {
__u64 params;
__u64 array;
__u32 mmu_type;
__u32 array_len;
};
配置虛擬 CPU 的 TLB 陣列,在使用者空間和 KVM 之間建立共享記憶體區域。“params”和“array”欄位是 mmu 型別特定資料結構的使用者空間地址。“array_len”欄位是一種安全機制,應設定為使用者空間為陣列保留的記憶體大小(以位元組為單位)。它必須至少是由“mmu_type”和“params”指定的大小。
當 KVM_RUN 處於活動狀態時,共享區域受 KVM 控制。其內容未定義,使用者空間對其進行的任何修改都會導致有界未定義的行為。
從 KVM_RUN 返回時,共享區域將反映 guest 的 TLB 的當前狀態。如果使用者空間進行任何更改,它必須呼叫 KVM_DIRTY_TLB 來告訴 KVM 哪些條目已更改,然後再在此 vcpu 上再次呼叫 KVM_RUN。
對於 mmu 型別 KVM_MMU_FSL_BOOKE_NOHV 和 KVM_MMU_FSL_BOOKE_HV
“params”欄位的型別為“struct kvm_book3e_206_tlb_params”。
“array”欄位指向型別為“struct kvm_book3e_206_tlb_entry”的陣列。
該陣列由第一個 TLB 中的所有條目組成,後跟第二個 TLB 中的所有條目。
在 TLB 中,條目首先按遞增的集合編號排序。在一個集合中,條目按方式排序(遞增 ESEL)。
用於確定 TLB0 中集合編號的雜湊值為:(MAS2 >> 12) & (num_sets - 1),其中“num_sets”是 tlb_sizes[] 值除以 tlb_ways[] 值。
即使硬體忽略 TLB0 的此值,mas1 的 tsize 欄位也應在 TLB0 上設定為 4K。
6.4 KVM_CAP_S390_CSS_SUPPORT¶
- 架構:
s390
- 目標:
vcpu
- 引數:
無
- 返回值:
成功時為 0;出錯時為 -1
此功能允許支援處理通道 I/O 指令。
TEST PENDING INTERRUPTION 和 TEST SUBCHANNEL 的中斷部分在核心中處理,而其他 I/O 指令傳遞給使用者空間。
啟用此功能後,將在 TEST SUBCHANNEL 攔截時發生 KVM_EXIT_S390_TSCH。
請注意,即使此功能是按 vcpu 啟用的,整個虛擬機器也會受到影響。
6.5 KVM_CAP_PPC_EPR¶
- 架構:
ppc
- 目標:
vcpu
- 引數:
args[0] 定義代理工具是否處於活動狀態
- 返回值:
成功時為 0;出錯時為 -1
此功能啟用或停用透過外部代理工具傳遞中斷。
啟用後 (args[0] != 0),每次 guest 收到傳遞的外部中斷時,它都會自動退出到使用者空間,並帶有 KVM_EXIT_EPR 退出以接收最頂層中斷向量。
停用後 (args[0] == 0),行為就像不支援此工具一樣。
啟用此功能後,可能會發生 KVM_EXIT_EPR。
6.6 KVM_CAP_IRQ_MPIC¶
- 架構:
ppc
- 引數:
args[0] 是 MPIC 裝置 fd;args[1] 是此 vcpu 的 MPIC CPU 編號
此功能將 vcpu 連線到核心中的 MPIC 裝置。
6.7 KVM_CAP_IRQ_XICS¶
- 架構:
ppc
- 目標:
vcpu
- 引數:
args[0] 是 XICS 裝置 fd;args[1] 是此 vcpu 的 XICS CPU 編號(伺服器 ID)
此功能將 vcpu 連線到核心中的 XICS 裝置。
6.8 KVM_CAP_S390_IRQCHIP¶
- 架構:
s390
- 目標:
vm
- 引數:
無
此功能為 s390 啟用核心中的 irqchip。有關詳細資訊,請參閱“4.24 KVM_CREATE_IRQCHIP”。
6.9 KVM_CAP_MIPS_FPU¶
- 架構:
mips
- 目標:
vcpu
- 引數:
args[0] 保留供將來使用(應為 0)。
此功能允許 guest 使用主機浮點單元。它允許將 Config1.FP 位設定為啟用 guest 中的 FPU。完成此操作後,可以訪問 KVM_REG_MIPS_FPR_* 和 KVM_REG_MIPS_FCR_* 暫存器(取決於當前的 guest FPU 暫存器模式),並且可以透過 KVM API 以及從 guest 訪問 Status.FR、Config5.FRE 位,具體取決於 FPU 是否支援它們。
6.10 KVM_CAP_MIPS_MSA¶
- 架構:
mips
- 目標:
vcpu
- 引數:
args[0] 保留供將來使用(應為 0)。
此功能允許 guest 使用 MIPS SIMD 架構 (MSA)。它允許將 Config3.MSAP 位設定為啟用 guest 對 MSA 的使用。完成此操作後,可以訪問 KVM_REG_MIPS_VEC_* 和 KVM_REG_MIPS_MSA_* 暫存器,並且可以透過 KVM API 以及從 guest 訪問 Config5.MSAEn 位。
6.74 KVM_CAP_SYNC_REGS¶
- 架構:
s390, x86
- 目標:
s390:始終啟用,x86:vcpu
- 引數:
無
- 返回值:
x86:KVM_CHECK_EXTENSION 返回一個位數組,指示支援哪些暫存器集(位欄位在 arch/x86/include/uapi/asm/kvm.h 中定義)。
如上面 5. kvm_run 結構 部分中 kvm_sync_regs 結構資訊中所述,KVM_CAP_SYNC_REGS“允許使用者空間訪問某些 guest 暫存器,而無需呼叫 SET/GET_*REGS”。這透過消除用於設定和/或獲取暫存器值的重複 ioctl 呼叫來減少開銷。當用戶空間進行同步 guest 狀態修改時,例如在使用者空間中模擬和/或攔截指令時,這尤其重要。
有關 s390 的具體資訊,請參閱原始碼。
對於 x86
要複製到 kvm_run 的暫存器集可由使用者空間選擇(而不是為每次退出複製所有集)。
除了 regs 和 sregs 之外,還提供 vcpu_events。
對於 x86,struct kvm_run 的“kvm_valid_regs”欄位被過載為用作使用者空間設定的輸入位陣列欄位,以指示要在下次退出時複製出的特定暫存器集。
為了指示使用者空間何時修改了應複製到 vCPU 中的值,必須設定所有架構位陣列欄位“kvm_dirty_regs”。這使用與“kvm_valid_regs”欄位相同的位標誌來完成。如果未設定 dirty 位,則即使已修改暫存器集值,也不會將其複製到 vCPU 中。
位陣列中未使用的位欄位必須設定為零。
struct kvm_sync_regs {
struct kvm_regs regs;
struct kvm_sregs sregs;
struct kvm_vcpu_events events;
};
6.75 KVM_CAP_PPC_IRQ_XIVE¶
- 架構:
ppc
- 目標:
vcpu
- 引數:
args[0] 是 XIVE 裝置 fd;args[1] 是此 vcpu 的 XIVE CPU 編號(伺服器 ID)
此功能將 vcpu 連線到核心中的 XIVE 裝置。
6.76 KVM_CAP_HYPERV_SYNIC¶
- 架構:
x86
- 目標:
vcpu
此功能(如果 KVM_CHECK_EXTENSION 指示它可用)表示核心具有 Hyper-V Synthetic 中斷控制器 (SynIC) 的實現。Hyper-V SynIC 用於支援基於 Windows Hyper-V 的 guest 準虛擬化驅動程式 (VMBus)。
為了使用 SynIC,必須透過在 vcpu fd 上透過 KVM_ENABLE_CAP ioctl 設定此功能來啟用它。請注意,即使 CPU 支援 APIC 硬體虛擬化,這也將停用 APIC 硬體虛擬化,因為它與 SynIC 自動 EOI 行為不相容。
6.77 KVM_CAP_HYPERV_SYNIC2¶
- 架構:
x86
- 目標:
vcpu
此功能啟用較新版本的 Hyper-V Synthetic 中斷控制器 (SynIC)。與 KVM_CAP_HYPERV_SYNIC 的唯一區別在於,當透過寫入相應的 MSR 來啟用 SynIC 訊息和事件標誌頁面時,KVM 不會清除它們。
6.78 KVM_CAP_HYPERV_DIRECT_TLBFLUSH¶
- 架構:
x86
- 目標:
vcpu
此功能指示在 Hyper-V hypervisor 之上執行的 KVM 為其 guest 啟用了直接 TLB 重新整理,這意味著 TLB 重新整理超級呼叫由第 0 級 hypervisor (Hyper-V) 處理,繞過 KVM。由於 Hyper-V 和 KVM 之間 hypercall 引數的 ABI 不同,啟用此功能實際上停用了 KVM 對所有 hypercall 的處理(因為某些 KVM hypercall 可能會被 Hyper-V 錯誤地視為 TLB 重新整理 hypercall),因此使用者空間應停用 CPUID 中的 KVM 標識,並且僅公開 Hyper-V 標識。在這種情況下,guest 認為它在 Hyper-V 上執行,並且僅使用 Hyper-V hypercall。
6.79 KVM_CAP_HYPERV_ENFORCE_CPUID¶
- 架構:
x86
- 目標:
vcpu
啟用後,KVM 將根據 Hyper-V CPUID 功能葉中的位停用提供給 guest 的模擬 Hyper-V 功能。否則,當在 HYPERV_CPUID_INTERFACE (0x40000001) 葉中設定 Hyper-V 標識時,將無條件地提供所有當前已實現的 Hyper-V 功能。
6.80 KVM_CAP_ENFORCE_PV_FEATURE_CPUID¶
- 架構:
x86
- 目標:
vcpu
啟用後,KVM 將根據 KVM_CPUID_FEATURES CPUID 葉 (0x40000001) 中的位停用提供給 guest 的準虛擬化功能。否則,guest 可能會使用準虛擬化功能,而不管實際透過 CPUID 葉公開了什麼。
7. 可以在 VM 上啟用的功能¶
有一些功能在啟用時會改變虛擬機器的行為。要啟用它們,請參閱 4.37 KVM_ENABLE_CAP 部分。以下是功能列表以及啟用它們時它們對 VM 的影響。
以下資訊與描述一起提供
- 架構
哪些指令集架構提供了此 ioctl。x86 包括 i386 和 x86_64。
- 引數
該功能接受哪些引數。
- 返回值
返回值。未詳細說明常規錯誤號(EBADF、ENOMEM、EINVAL),但詳細說明了具有特定含義的錯誤。
7.1 KVM_CAP_PPC_ENABLE_HCALL¶
- 架構:
ppc
- 引數:
args[0] 是 sPAPR hcall 編號;args[1] 是 0 停用,1 啟用核心處理
此功能控制核心是否處理單個 sPAPR 超級呼叫 (hcall)。啟用或停用 hcall 的核心處理在 VM 中有效。建立時,會為核心處理啟用一組初始 hcall,其中包括在該功能實現之前實現的核心處理程式的那些 hcall。如果停用,核心將不會嘗試處理 hcall,而總是退出到使用者空間來處理它。請注意,啟用一組相關 hcall 中的一些並停用另一些可能沒有意義,但 KVM 不會阻止使用者空間這樣做。
如果指定的 hcall 編號不是具有核心實現的編號,則 KVM_ENABLE_CAP ioctl 將失敗並顯示 EINVAL 錯誤。
7.2 KVM_CAP_S390_USER_SIGP¶
- 架構:
s390
- 引數:
無
此功能控制哪些 SIGP 命令將完全在使用者空間中處理。啟用此功能後,所有快速命令都將在核心中完全處理
SENSE
SENSE RUNNING
EXTERNAL CALL
EMERGENCY SIGNAL
CONDITIONAL EMERGENCY SIGNAL
所有其他命令都將在使用者空間中完全處理。
只有特權操作異常才會在核心中檢查(甚至在攔截之前的硬體中檢查)。如果未啟用此功能,則使用舊的 SIGP 命令處理方式(部分在核心和使用者空間中)。
7.3 KVM_CAP_S390_VECTOR_REGISTERS¶
- 架構:
s390
- 引數:
無
- 返回值:
成功時為 0,出錯時為負值
允許使用 z13 處理器引入的向量暫存器,並提供主機和使用者空間之間的同步。如果機器不支援向量,將返回 -EINVAL。
7.4 KVM_CAP_S390_USER_STSI¶
- 架構:
s390
- 引數:
無
此功能允許 STSI 指令的後處理程式。在核心中進行初始處理後,KVM 會退出到使用者空間,並顯示 KVM_EXIT_S390_STSI,以允許使用者空間插入更多資料。
在退出到使用者空間之前,kvm 處理程式應填寫 vcpu->run 的 s390_stsi 欄位
struct {
__u64 addr;
__u8 ar;
__u8 reserved;
__u8 fc;
__u8 sel1;
__u16 sel2;
} s390_stsi;
@addr - guest address of STSI SYSIB
@fc - function code
@sel1 - selector 1
@sel2 - selector 2
@ar - access register number
KVM 處理程式應退出到使用者空間,並顯示 rc = -EREMOTE。
7.5 KVM_CAP_SPLIT_IRQCHIP¶
- 架構:
x86
- 引數:
args[0] - 為使用者空間 IOAPIC 保留的路由數
- 返回值:
成功時為 0,出錯時為 -1
為核心中的每個處理器建立一個本地 apic。如果使用者空間 VMM 希望模擬 IOAPIC 和 PIC(以及 PIT,即使必須單獨啟用它),則可以使用此功能代替 KVM_CREATE_IRQCHIP。
此功能還啟用核心中中斷請求的路由;當 KVM_CAP_SPLIT_IRQCHIP 僅在 IRQ 路由表中使用 KVM_IRQ_ROUTING_MSI 型別的路由時。前 args[0] 個 MSI 路由保留用於 IOAPIC 引腳。每當 LAPIC 接收到這些路由的 EOI 時,將向用戶空間報告 KVM_EXIT_IOAPIC_EOI vmexit。
如果已建立 VCPU,或者 irqchip 已經在核心中(即,已經呼叫了 KVM_CREATE_IRQCHIP),則失敗。
7.6 KVM_CAP_S390_RI¶
- 架構:
s390
- 引數:
無
允許使用 zEC12 處理器引入的執行時檢測。如果機器不支援執行時檢測,將返回 -EINVAL。如果已經建立了 VCPU,將返回 -EBUSY。
7.7 KVM_CAP_X2APIC_API¶
- 架構:
x86
- 引數:
args[0] - 應啟用的功能
- 返回值:
成功時為 0,當 args[0] 包含無效功能時為 -EINVAL
args[0] 中的有效功能標誌為
#define KVM_X2APIC_API_USE_32BIT_IDS (1ULL << 0)
#define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK (1ULL << 1)
啟用 KVM_X2APIC_API_USE_32BIT_IDS 會更改 KVM_SET_GSI_ROUTING、KVM_SIGNAL_MSI、KVM_SET_LAPIC 和 KVM_GET_LAPIC 的行為,允許使用 32 位 APIC ID。請參閱它們各自部分中的 KVM_CAP_X2APIC_API。
必須啟用 KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK 才能使 x2APIC 在邏輯模式下或使用超過 255 個 VCPU 的情況下工作。否則,KVM 會將 0xff 視為廣播,即使在 x2APIC 模式下,為了支援沒有中斷重對映的物理 x2APIC。這在邏輯模式下是不希望的,因為 0xff 表示叢集 0 中的 CPU 0-7。
7.8 KVM_CAP_S390_USER_INSTR0¶
- 架構:
s390
- 引數:
無
啟用此功能後,所有非法指令 0x0000(2 位元組)都將被攔截並轉發到使用者空間。使用者空間可以使用此機制,例如實現 2 位元組軟體斷點。核心不會為這些指令注入操作異常,使用者空間必須注意這一點。
即使已經建立並正在執行 VCPU,也可以動態啟用此功能。
7.9 KVM_CAP_S390_GS¶
- 架構:
s390
- 引數:
無
- 返回值:
成功時為 0;如果機器不支援受保護的儲存,則為 -EINVAL;如果已經建立了 VCPU,則為 -EBUSY。
允許為 KVM guest 使用受保護的儲存。
7.10 KVM_CAP_S390_AIS¶
- 架構:
s390
- 引數:
無
允許使用介面卡中斷抑制。:返回值:成功時為 0;如果已經建立了 VCPU,則為 -EBUSY。
7.11 KVM_CAP_PPC_SMT¶
- 架構:
ppc
- 引數:
vsmt_mode, flags
在 VM 上啟用此功能為使用者空間提供了一種設定所需的虛擬 SMT 模式(即每個虛擬核心的虛擬 CPU 數量)的方法。虛擬 SMT 模式 vsmt_mode 必須是 1 到 8 之間的 2 的冪。在 POWER8 上,vsmt_mode 也不能大於主機的每個子核心的執行緒數。當前標誌必須為 0。成功呼叫以啟用此功能將在隨後查詢 VM 的 KVM_CAP_PPC_SMT 功能時返回 vsmt_mode。此功能僅受 HV KVM 支援,並且只能在建立任何 VCPU 之前設定。KVM_CAP_PPC_SMT_POSSIBLE 功能指示哪些虛擬 SMT 模式可用。
7.12 KVM_CAP_PPC_FWNMI¶
- 架構:
ppc
- 引數:
無
藉助此功能,guest 地址空間中的機器檢查異常將導致 KVM 以 NMI 退出原因退出 guest。這使 QEMU 能夠構建錯誤日誌並分支到 guest 核心註冊的機器檢查處理例程。如果沒有此功能,KVM 將分支到 guest 的 0x200 中斷向量。
7.13 KVM_CAP_X86_DISABLE_EXITS¶
- 架構:
x86
- 引數:
args[0] 定義停用哪些退出
- 返回值:
成功時為 0,當 args[0] 包含無效退出或已經建立了任何 vCPU 時為 -EINVAL
args[0] 中的有效位為
#define KVM_X86_DISABLE_EXITS_MWAIT (1 << 0)
#define KVM_X86_DISABLE_EXITS_HLT (1 << 1)
#define KVM_X86_DISABLE_EXITS_PAUSE (1 << 2)
#define KVM_X86_DISABLE_EXITS_CSTATE (1 << 3)
在 VM 上啟用此功能為使用者空間提供了一種不再攔截某些指令以提高某些工作負載中的延遲的方法,建議在 vCPU 與專用物理 CPU 關聯時使用。將來可以新增更多位;使用者空間可以簡單地將 KVM_CHECK_EXTENSION 結果傳遞給 KVM_ENABLE_CAP 以停用所有此類 vmexit。
如果停用 HLT 退出,請勿啟用 KVM_FEATURE_PV_UNHALT。
7.14 KVM_CAP_S390_HPAGE_1M¶
- 架構:
s390
- 引數:
無
- 返回值:
成功時為 0,如果未設定 hpage 模組引數或啟用了 cmma,或者 VM 設定了 KVM_VM_S390_UCONTROL 標誌,則為 -EINVAL
藉助此功能,可以為 VM 啟用 KVM 對透過 hugetlbfs 的 1m 頁面進行記憶體後備的支援。啟用此功能後,不能再啟用 cmma,並且 pfmfi 和儲存金鑰解釋將被停用。如果已經啟用了 cmma 或 hpage 模組引數未設定為 1,則返回 -EINVAL。
雖然通常可以在沒有此功能的情況下建立由巨頁支援的 VM,但 VM 將無法執行。
7.15 KVM_CAP_MSR_PLATFORM_INFO¶
- 架構:
x86
- 引數:
args[0] 是否應啟用該功能
藉助此功能,guest 可以讀取 MSR_PLATFORM_INFO MSR。否則,當 guest 嘗試訪問時,將引發 #GP。當前,此功能不啟用 guest 對此 MSR 的寫入許可權。
7.16 KVM_CAP_PPC_NESTED_HV¶
- 架構:
ppc
- 引數:
無
- 返回值:
成功時為 0,當實現不支援巢狀 HV 虛擬化時為 -EINVAL。
POWER9 及更高系統上的 HV-KVM 允許“巢狀 HV”虛擬化,這為 guest VM 提供了一種執行可以使用 CPU 的 supervisor 模式(特權非 hypervisor 狀態)執行的 guest 的方法。在 VM 上啟用此功能取決於 CPU 是否具有必要的功能,以及是否使用 kvm-hv 模組引數啟用了該工具。
7.17 KVM_CAP_EXCEPTION_PAYLOAD¶
- 架構:
x86
- 引數:
args[0] 是否應啟用該功能
啟用此功能後,當 L1 截獲 L2 中發生的 #PF 異常時,CR2 不會在模擬的 VM-exit 之前被修改。同樣,對於僅 kvm-intel,當 L1 截獲 L2 中發生的 #DB 異常時,DR6 不會在模擬的 VM-exit 之前被修改。因此,當 KVM_GET_VCPU_EVENTS 報告 L2 有待處理的 #PF(或 #DB)異常時,exception.has_payload 將被設定,並且故障地址(或新的 DR6 位*)將在 exception_payload 欄位中報告。同樣,當用戶空間使用 KVM_SET_VCPU_EVENTS 將 #PF(或 #DB)注入到 L2 中時,它應該設定 exception.has_payload 並將故障地址 - 或新的 DR6 位[3] - 放入 exception_payload 欄位中。
此功能還啟用 struct kvm_vcpu_events 中的 exception.pending,這允許使用者空間區分待處理異常和注入異常。
對於新的 DR6 位,請注意,當 #DB 異常將清除 DR6.RTM 時,第 16 位才會被設定。
7.18 KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2¶
- 架構:
x86, arm64, mips
- 引數:
args[0] 是否應啟用該功能
有效的標誌包括
#define KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE (1 << 0)
#define KVM_DIRTY_LOG_INITIALLY_SET (1 << 1)
當設定 KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE 時,KVM_GET_DIRTY_LOG 不會自動清除並防寫所有作為髒頁返回的頁面。相反,使用者空間將不得不使用 KVM_CLEAR_DIRTY_LOG 單獨執行此操作。
以稍微複雜的操作為代價,這提供了更好的可伸縮性和響應性,原因有兩個。首先,KVM_CLEAR_DIRTY_LOG ioctl 可以在 64 頁的粒度上執行,而不需要同步完整的 memslot;這確保了 KVM 不會長時間佔用自旋鎖。其次,在呼叫 KVM_GET_DIRTY_LOG 和使用者空間實際使用頁面中的資料之間可能會經過大量時間。頁面可能在此期間被修改,這對訪客和使用者空間都是低效的:訪客將因防寫故障而遭受更高的懲罰,而使用者空間可能會看到髒頁的錯誤報告。手動重新保護有助於減少這段時間,從而提高訪客效能並減少髒日誌誤報的數量。
當設定 KVM_DIRTY_LOG_INITIALLY_SET 時,髒點陣圖的所有位將在建立時初始化為 1。 這也提高了效能,因為可以在第一次呼叫 KVM_CLEAR_DIRTY_LOG 時以小塊逐步啟用髒日誌記錄。 KVM_DIRTY_LOG_INITIALLY_SET 依賴於 KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE(目前也僅在 x86 和 arm64 上可用)。
KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 之前以名稱 KVM_CAP_MANUAL_DIRTY_LOG_PROTECT 提供,但該實現存在錯誤,使得難以或不可能正確使用它。 KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 的可用性表明這些錯誤已修復。 使用者空間不應嘗試使用 KVM_CAP_MANUAL_DIRTY_LOG_PROTECT。
7.19 KVM_CAP_PPC_SECURE_GUEST¶
- 架構:
ppc
此功能表明 KVM 正在具有超管理程式韌體的主機上執行,因此可以支援安全訪客。 在這樣的系統上,訪客可以要求超管理程式使其成為安全訪客,即其記憶體對主機不可訪問,除非明確請求與主機共享的頁面。 當訪客請求成為安全訪客時,超管理程式會通知 KVM,KVM 有機會否決該轉換。
如果存在,則可以為 VM 啟用此功能,這意味著 KVM 將允許轉換為安全訪客模式。 否則,KVM 將否決該轉換。
7.20 KVM_CAP_HALT_POLL¶
- 架構:
全部
- 目標:
VM
- 引數:
args[0] 是以納秒為單位的最大輪詢時間
- 返回值:
成功時為 0;出錯時為 -1
KVM_CAP_HALT_POLL 覆蓋 kvm.halt_poll_ns 模組引數,以設定目標 VM 中所有 vCPU 的最大暫停輪詢時間。 可以隨時呼叫此功能任意次數,以動態更改最大暫停輪詢時間。
有關暫停輪詢的更多資訊,請參閱 KVM 暫停輪詢系統。
7.21 KVM_CAP_X86_USER_SPACE_MSR¶
- 架構:
x86
- 目標:
VM
- 引數:
args[0] 包含要報告的 KVM_MSR_EXIT_REASON_* 事件的掩碼
- 返回值:
成功時為 0;出錯時為 -1
如果拒絕訪問 MSR,則此功能允許使用者空間攔截 RDMSR 和 WRMSR 指令。 預設情況下,KVM 會在拒絕訪問時注入 #GP。
當訪客請求讀取或寫入 MSR 時,KVM 可能不會實現所有與相應系統相關的 MSR。 它也不會按 CPU 型別進行區分。
為了允許對 MSR 處理進行更細粒度的控制,使用者空間可以啟用此功能。 啟用後,匹配 args[0] 中指定的掩碼並且會在訪客內部觸發 #GP 的 MSR 訪問將改為觸發 KVM_EXIT_X86_RDMSR 和 KVM_EXIT_X86_WRMSR 退出通知。 然後,使用者空間可以實現特定於模型的 MSR 處理和/或使用者通知,以通知使用者 KVM 未模擬/虛擬化 MSR。
有效的掩碼標誌為
KVM_MSR_EXIT_REASON_UNKNOWN |
攔截對未知(對於 KVM)MSR 的訪問 |
KVM_MSR_EXIT_REASON_INVAL |
攔截根據 vCPU 模型和/或模式在架構上無效的訪問 |
KVM_MSR_EXIT_REASON_FILTER |
攔截使用者空間透過 KVM_X86_SET_MSR_FILTER 拒絕的訪問 |
7.22 KVM_CAP_X86_BUS_LOCK_EXIT¶
- 架構:
x86
- 目標:
VM
- 引數:
args[0] 定義了在訪客中檢測到匯流排鎖時使用的策略
- 返回值:
成功時為 0,當 args[0] 包含無效位時為 -EINVAL
args[0] 中的有效位為
#define KVM_BUS_LOCK_DETECTION_OFF (1 << 0)
#define KVM_BUS_LOCK_DETECTION_EXIT (1 << 1)
在 VM 上啟用此功能為使用者空間提供了一種選擇策略來處理訪客中檢測到的匯流排鎖的方法。 使用者空間可以從 KVM_CHECK_EXTENSION 的結果中獲取支援的模式,並透過 KVM_ENABLE_CAP 定義它。 支援的模式是互斥的。
此功能允許使用者空間強制 VM 在訪客中檢測到的匯流排鎖上退出,無論主機是否啟用了拆分鎖檢測(這將觸發 KVM 攔截的 #AC 異常)。 此功能旨在緩解惡意/有缺陷的訪客可以利用匯流排鎖來降低整個系統性能的攻擊。
如果設定了 KVM_BUS_LOCK_DETECTION_OFF,則 KVM 不會強制訪客匯流排鎖退出 VM,但如果啟用,主機核心的拆分鎖 #AC 檢測仍然適用。
如果設定了 KVM_BUS_LOCK_DETECTION_EXIT,則 KVM 會啟用一個 CPU 功能,該功能確保訪客中的匯流排鎖會觸發 VM 退出,並且 KVM 會退出到使用者空間以處理所有此類 VM 退出,例如,允許使用者空間限制違規訪客和/或應用一些其他基於策略的緩解措施。 退出到使用者空間時,KVM 會在 vcpu-run->flags 中設定 KVM_RUN_X86_BUS_LOCK,並有條件地將 exit_reason 設定為 KVM_EXIT_X86_BUS_LOCK。
由於底層硬體實現的差異,退出時 vCPU 的 RIP 在 Intel 和 AMD 之間存在差異。 在 Intel 主機上,RIP 指向下一條指令,即退出類似於陷阱。 在 AMD 主機上,RIP 指向違規指令,即退出類似於故障。
注意! 檢測到的匯流排鎖可能與其他退出到使用者空間的情況同時發生,即如果使用者空間想要對所有檢測到的匯流排鎖採取措施,則無論主要退出原因如何,都應檢查 KVM_RUN_X86_BUS_LOCK。
7.23 KVM_CAP_PPC_DAWR1¶
- 架構:
ppc
- 引數:
無
- 返回值:
成功時為 0,當 CPU 不支援第二個 DAWR 時為 -EINVAL
此功能可用於檢查/啟用 POWER10 處理器提供的第二個 DAWR 功能。
7.24 KVM_CAP_VM_COPY_ENC_CONTEXT_FROM¶
- 架構:
x86 SEV 已啟用
- 型別:
vm
- 引數:
args[0] 是源 vm 的 fd
- 返回值:
成功時為 0;出錯時為 ENOTTY
此功能使使用者空間能夠將加密上下文從 fd 指示的 vm 複製到呼叫此功能的 vm。
這旨在支援由主機排程的客戶機內工作負載。 這允許客戶機內工作負載維護其自己的 NPT,並防止兩個 vm 透過中斷等意外地相互覆蓋(單獨的 APIC/MSR/等)。
7.25 KVM_CAP_SGX_ATTRIBUTE¶
- 架構:
x86
- 目標:
VM
- 引數:
args[0] 是 securityfs 中 SGX 屬性檔案的檔案控制代碼
- 返回值:
成功時為 0,如果檔案控制代碼無效或 KVM 不支援請求的屬性,則為 -EINVAL。
KVM_CAP_SGX_ATTRIBUTE 使使用者空間 VMM 能夠授予 VM 訪問一個或多個特權 enclave 屬性的許可權。 args[0] 必須儲存一個有效 SGX 屬性檔案的檔案控制代碼,該檔案對應於 KVM 支援/限制的屬性(目前僅 PROVISIONKEY)。
SGX 子系統限制對 enclave 屬性子集的訪問,以便為未受損的核心提供額外的安全性,例如,PROVISIONKEY 的使用受到限制,以阻止惡意軟體使用 PROVISIONKEY 獲取穩定的系統指紋。 為了防止使用者空間透過在 VM 中執行 enclave 來規避此類限制,KVM 預設情況下會阻止對特權屬性的訪問。
有關更多詳細資訊,請參閱 軟體保護擴充套件 (SGX)。
7.27 KVM_CAP_EXIT_ON_EMULATION_FAILURE¶
- 架構:
x86
- 引數:
args[0] 是否應啟用該功能
啟用此功能後,模擬失敗將導致退出到使用者空間並顯示 KVM_INTERNAL_ERROR(除非呼叫模擬器來處理 VMware 後門指令)。 此外,KVM 現在將為任何因模擬失敗而導致退出到使用者空間的操作提供最多 15 個指令位元組。 當這些退出到使用者空間發生時,請使用 emulation_failure 結構而不是內部結構。 它們都具有相同的佈局,但 emulation_failure 結構與內容更匹配。 它還顯式定義了“flags”欄位,該欄位用於描述結構中有效的欄位(即:如果在“flags”欄位中設定了 KVM_INTERNAL_ERROR_EMULATION_FLAG_INSTRUCTION_BYTES,則“insn_size”和“insn_bytes”都具有有效資料)。
7.28 KVM_CAP_ARM_MTE¶
- 架構:
arm64
- 引數:
無
此功能指示 KVM(和硬體)支援向訪客公開記憶體標記擴充套件 (MTE)。 必須先由 VMM 啟用,然後才能建立任何 VCPU,以允許訪客訪問。 請注意,MTE 僅適用於以 AArch64 模式執行的訪客,並且啟用此功能將導致建立 AArch32 VCPU 的嘗試失敗。
啟用後,訪客可以訪問與分配給訪客的任何記憶體關聯的標記。 KVM 將確保在主機的交換或休眠期間維護標記;但是,如果 VM 被遷移,VMM 需要手動儲存/恢復標記(如適用)。
啟用此功能後,memslot 中的所有記憶體都必須對映為 MAP_ANONYMOUS 或使用基於 RAM 的檔案對映(tmpfs、memfd),嘗試使用無效 mmap 建立 memslot 將導致返回 -EINVAL。
啟用後,VMM 可以使用 KVM_ARM_MTE_COPY_TAGS ioctl 來執行標記與訪客之間的批次複製。
7.29 KVM_CAP_VM_MOVE_ENC_CONTEXT_FROM¶
- 架構:
x86 SEV 已啟用
- 型別:
vm
- 引數:
args[0] 是源 vm 的 fd
- 返回值:
成功時為 0
此功能使使用者空間能夠將加密上下文從 fd 指示的 VM 遷移到呼叫此功能的 VM。
這旨在支援使用者空間 VMM 之間的 VM 的主機內遷移,無需中斷訪客即可升級 VMM 程序。
7.31 KVM_CAP_DISABLE_QUIRKS2¶
- 引數:
args[0] - 要停用的 KVM 缺陷集
- 架構:
x86
- 型別:
vm
如果啟用此功能,將導致 KVM 停用某些行為缺陷。
呼叫此功能的 KVM_CHECK_EXTENSION 會返回一個可以在 KVM 中停用的缺陷的位掩碼。
此功能的 KVM_ENABLE_CAP 的引數是要停用的缺陷的位掩碼,並且必須是 KVM_CHECK_EXTENSION 返回的位掩碼的子集。
cap.args[0] 中的有效位為
KVM_X86_QUIRK_LINT0_REENABLED |
預設情況下,LVT LINT0 暫存器的重置值為 0x700 (APIC_MODE_EXTINT)。 停用此缺陷後,重置值為 0x10000 (APIC_LVT_MASKED)。 |
KVM_X86_QUIRK_CD_NW_CLEARED |
預設情況下,KVM 會清除 AMD CPU 上的 CR0.CD 和 CR0.NW,以解決以 CR0.CD(即快取處於“無填充”模式)永久執行的有缺陷的訪客韌體。 停用此缺陷後,KVM 不會更改 CR0.CD 和 CR0.NW 的值。 |
KVM_X86_QUIRK_LAPIC_MMIO_HOLE |
預設情況下,即使配置為 x2APIC 模式,MMIO LAPIC 介面也可用。 停用此缺陷後,如果 LAPIC 處於 x2APIC 模式,KVM 將停用 MMIO LAPIC 介面。 |
KVM_X86_QUIRK_OUT_7E_INC_RIP |
預設情況下,KVM 會在退出到使用者空間之前將 %rip 預先遞增到埠 0x7e 的 OUT 指令。 停用此缺陷後,KVM 不會在退出到使用者空間之前預先遞增 %rip。 |
KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT |
停用此缺陷後,如果設定了 IA32_MISC_ENABLE[位 18] (MWAIT),KVM 會設定 CPUID.01H:ECX[位 3] (MONITOR/MWAIT)。 此外,停用此缺陷後,如果清除了 IA32_MISC_ENABLE[位 18],KVM 會清除 CPUID.01H:ECX[位 3]。 |
KVM_X86_QUIRK_FIX_HYPERCALL_INSN |
預設情況下,KVM 會重寫訪客 VMMCALL/VMCALL 指令,以匹配系統的供應商管理程式呼叫指令。 停用此缺陷後,KVM 將不再重寫無效的訪客管理程式呼叫指令。 執行不正確的管理程式呼叫指令將在訪客內部生成 #UD。 |
KVM_X86_QUIRK_MWAIT_NEVER_UD_FAULTS |
預設情況下,無論根據訪客 CPUID 是否支援 MONITOR/MWAIT,KVM 都會將 MONITOR/MWAIT(如果被攔截)模擬為 NOP。 停用此缺陷且未設定 KVM_X86_DISABLE_EXITS_MWAIT(MONITOR/MWAIT 被攔截)時,如果根據訪客 CPUID 不支援 MONITOR/MWAIT,KVM 將在 MONITOR/MWAIT 上注入 #UD。 請注意,如果停用了 KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT,KVM 將在寫入 MISC_ENABLE 時修改訪客 CPUID 中的 MONITOR/MWAIT 支援。 |
KVM_X86_QUIRK_SLOT_ZAP_ALL |
預設情況下,對於 KVM_X86_DEFAULT_VM VM,當刪除或移動 memslot 時,KVM 會使所有 memslot 和地址空間中的所有 SPTE 失效。 停用此缺陷(或 VM 型別不是 KVM_X86_DEFAULT_VM)時,KVM 僅確保無法訪問已刪除或移動的 memslot 的後備記憶體,即 KVM _可以_ 僅使與 memslot 相關的 SPTE 失效。 |
KVM_X86_QUIRK_STUFF_FEATURE_MSRS |
預設情況下,在 vCPU 建立時,KVM 會將 vCPU 的 MSR_IA32_PERF_CAPABILITIES (0x345)、MSR_IA32_ARCH_CAPABILITIES (0x10a)、MSR_PLATFORM_INFO (0xce) 和所有 VMX MSR (0x480..0x492) 設定為 KVM 支援的最大功能。 KVM 還會將 MSR_IA32_UCODE_REV (0x8b) 設定為任意值(Intel 與 AMD 的值不同)。 最後,當設定訪客 CPUID(由使用者空間設定)時,KVM 會修改選定的 VMX MSR 欄位,以強制訪客 CPUID 與 L2 的有效 ISA 之間的一致性。 停用此缺陷後,KVM 會將 vCPU 的 MSR 值清零(有兩個例外,請參見下文),即像對待 CPUID 葉一樣對待功能 MSR,並使使用者空間完全控制 vCPU 模型定義。 此缺陷不會影響 VMX MSR CR0/CR4_FIXED1 (0x487 和 0x489),因為 KVM 現在不允許使用者空間設定它們(出於安全目的,KVM 會根據訪客 CPUID 設定它們)。 |
KVM_X86_QUIRK_IGNORE_GUEST_PAT |
預設情況下,在 Intel 平臺上,KVM 會忽略訪客 PAT,並強制 EPT 中的有效記憶體型別為 WB。 該缺陷在無法安全地遵守訪客 PAT 的 Intel 平臺上不可用(即,在沒有 CPU 自偵聽的情況下,KVM 始終忽略訪客 PAT 並強制有效記憶體型別為 WB)。 它在 AMD 平臺上或在 Intel 上,當 VM 分配了非一致 DMA 裝置時也會被忽略; 在這種情況下,KVM 始終遵守訪客 PAT。 需要該缺陷來避免在某些 Intel Xeon 平臺(例如 ICX、SPR)上的速度減慢,在這些平臺上支援自偵聽功能,但 UC 的速度太慢,會導致某些使用 UC 而不是 WC 對映影片 RAM 的舊訪客出現問題。 如果使用者空間知道不存在此類訪客軟體,例如,如果它不公開 bochs 圖形裝置(已知該裝置具有有缺陷的驅動程式),則可以停用該缺陷以遵守訪客 PAT。 |
7.32 KVM_CAP_MAX_VCPU_ID¶
- 架構:
x86
- 目標:
VM
- 引數:
args[0] - 為當前 VM 設定的最大 APIC ID 值
- 返回值:
成功時為 0,如果 args[0] 超出 KVM 中支援的 KVM_MAX_VCPU_IDS,或者如果已設定,則為 -EINVAL。
此功能允許使用者空間在建立 vCPU 之前指定為當前 VM 會話分配的最大可能 APIC ID,從而為按 APIC ID 索引的資料結構節省記憶體。 使用者空間能夠從指定的 CPU 拓撲計算 APIC ID 值的限制。
該值只能在 KVM_ENABLE_CAP 設定為非零值或建立 vCPU 之前更改。 建立第一個 vCPU 後,如果該值設定為零或者未呼叫 KVM_ENABLE_CAP,KVM 將使用 KVM_CHECK_EXTENSION(KVM_CAP_MAX_VCPU_ID) 的返回值作為最大 APIC ID。
7.33 KVM_CAP_X86_NOTIFY_VMEXIT¶
- 架構:
x86
- 目標:
VM
- 引數:
args[0] 是通知視窗的值以及一些標誌
- 返回值:
成功時為 0,如果 args[0] 包含無效標誌或不支援通知 VM 退出,則為 -EINVAL。
args[0] 的位 63:32 用於通知視窗。 args[0] 的位 31:0 用於某些標誌。 有效位為
#define KVM_X86_NOTIFY_VMEXIT_ENABLED (1 << 0)
#define KVM_X86_NOTIFY_VMEXIT_USER (1 << 1)
此功能允許使用者空間在 VM 建立期間按 VM 範圍配置通知 VM 退出開啟/關閉。 預設情況下停用通知 VM 退出。 當用戶空間在 args[0] 中設定 KVM_X86_NOTIFY_VMEXIT_ENABLED 位時,VMM 將啟用此功能,並提供通知視窗,如果在指定的的時間(通知視窗)內在 VM 非根模式下未發生任何事件視窗,則會生成 VM 退出。
如果在 args[0] 中設定了 KVM_X86_NOTIFY_VMEXIT_USER,則在發生通知 VM 退出時,KVM 將退出到使用者空間以進行處理。
此功能旨在緩解惡意 VM 可能導致 CPU 卡住(由於事件視窗未開啟)並使 CPU 對主機或其他 VM 不可用的威脅。
7.35 KVM_CAP_X86_APIC_BUS_CYCLES_NS¶
- 架構:
x86
- 目標:
VM
- 引數:
args[0] 是所需的 APIC 匯流排時鐘頻率,以納秒為單位
- 返回值:
成功時為 0,如果 args[0] 包含頻率的無效值,或者已建立任何 vCPU,則為 -EINVAL,如果尚未使用 KVM_CREATE_IRQCHIP 建立虛擬本地 APIC,則為 -ENXIO。
此功能設定 VM 的 APIC 匯流排時鐘頻率,KVM 的核心內虛擬 APIC 在模擬 APIC 計時器時使用該頻率。 KVM 的預設值可以透過 KVM_CHECK_EXTENSION 檢索。
注意:如果向訪客公開了非零 CPUID 0x15,使用者空間負責正確配置 CPUID 0x15,即核心晶體時鐘頻率。
7.36 KVM_CAP_DIRTY_LOG_RING/KVM_CAP_DIRTY_LOG_RING_ACQ_REL¶
- 架構:
x86, arm64
- 型別:
vm
- 引數:
args[0] - 髒日誌環的大小
KVM 能夠使用 mmapped 到使用者空間的環形緩衝區跟蹤髒記憶體; 每個 vcpu 都有一個髒環。
髒環以 struct kvm_dirty_gfn 陣列的形式提供給使用者空間。 每個髒條目的定義如下
struct kvm_dirty_gfn {
__u32 flags;
__u32 slot; /* as_id | slot_id */
__u64 offset;
};
為標誌欄位定義了以下值,以定義條目的當前狀態
#define KVM_DIRTY_GFN_F_DIRTY BIT(0)
#define KVM_DIRTY_GFN_F_RESET BIT(1)
#define KVM_DIRTY_GFN_F_MASK 0x3
使用者空間應在 KVM_CREATE_VM ioctl 之後立即呼叫 KVM_ENABLE_CAP ioctl,以啟用新訪客的此功能並設定環的大小。 僅允許在建立任何 vCPU 之前啟用該功能,並且環的大小必須是 2 的冪。 環形緩衝區越大,環越不太可能滿,並且 VM 不會被強制退出到使用者空間。 最佳大小取決於工作負載,但建議至少為 64 KiB(4096 個條目)。
與髒頁點陣圖一樣,該緩衝區跟蹤對所有使用者記憶體區域的寫入,這些區域在 KVM_SET_USER_MEMORY_REGION 中設定了 KVM_MEM_LOG_DIRTY_PAGES 標誌。 一旦使用設定的標誌註冊了記憶體區域,使用者空間就可以開始從環形緩衝區中收集髒頁。
環形緩衝區中的條目可以是未使用(標誌位 00)、髒(標誌位 01)或已收集(標誌位 1X)。 條目的狀態機如下
dirtied harvested reset
00 -----------> 01 -------------> 1X -------+
^ |
| |
+------------------------------------------+
要收集髒頁,使用者空間訪問 mmapped 環形緩衝區以讀取髒 GFN。 如果標誌設定了 DIRTY 位(在此階段必須清除 RESET 位),則表示此 GFN 是髒 GFN。 使用者空間應收集此 GFN 並將標誌從狀態 01b 標記為 1Xb(位 0 將被 KVM 忽略,但必須設定位 1 以表明已收集此 GFN 並正在等待重置),然後繼續下一個 GFN。 使用者空間應繼續執行此操作,直到 GFN 的標誌清除 DIRTY 位,這表示它已收集所有可用的髒 GFN。
請注意,在弱排序架構上,使用者空間對環形緩衝區的訪問(更具體地說,是對“flags”欄位的訪問)必須是有序的,在可用時使用 load-acquire/store-release 訪問器,或任何其他將確保此排序的記憶體屏障。
使用者空間不必一次收集所有髒 GFN。 但是,它必須按順序收集髒 GFN,即使用者空間程式不能跳過一個髒 GFN 來收集下一個髒 GFN。
在處理環形緩衝區中的一個或多個條目後,使用者空間呼叫 VM ioctl KVM_RESET_DIRTY_RINGS 以通知核心,以便核心將重新保護那些收集的 GFN。 因此,ioctl 必須在讀取髒頁的內容之前呼叫。
髒環可能會滿。 發生這種情況時,vcpu 的 KVM_RUN 將返回,退出原因為 KVM_EXIT_DIRTY_LOG_FULL。
髒環介面與 KVM_GET_DIRTY_LOG 介面的主要區別在於,從使用者空間讀取髒環時,核心仍然可能尚未將處理器的髒頁緩衝區重新整理到核心緩衝區中(使用髒點陣圖,重新整理由 KVM_GET_DIRTY_LOG ioctl 完成)。 為此,需要使用訊號將 vcpu 從 KVM_RUN 中踢出。 生成的 vmexit 確保所有髒 GFN 都已重新整理到髒環中。
注意:KVM_CAP_DIRTY_LOG_RING_ACQ_REL 是弱排序架構應公開的唯一功能,以便指示使用者空間在讀取條目的狀態並將其從 DIRTY 更改為 HARVESTED 時施加的額外記憶體排序要求。 具有類似 TSO 排序的架構(例如 x86)允許向用戶空間公開 KVM_CAP_DIRTY_LOG_RING 和 KVM_CAP_DIRTY_LOG_RING_ACQ_REL。
啟用髒環後,使用者空間需要檢測 KVM_CAP_DIRTY_LOG_RING_WITH_BITMAP 的功能,以檢視環形結構是否可以由每個插槽的點陣圖支援。 如果宣傳了此功能,則表示該架構可以在沒有 vcpu/環上下文的情況下弄髒訪客頁面,因此某些髒資訊仍將維護在點陣圖結構中。 如果尚未啟用 KVM_CAP_DIRTY_LOG_RING_ACQ_REL 的功能,或者已存在任何 memslot,則無法啟用 KVM_CAP_DIRTY_LOG_RING_WITH_BITMAP。
請注意,此處的點陣圖只是環形結構的備份。 僅當只有非常少量的記憶體在 vcpu/環上下文之外被弄髒時,使用環和點陣圖組合才有益。 否則,需要考慮獨立的每個插槽的點陣圖機制。
要收集備份點陣圖中的髒位,使用者空間可以使用相同的 KVM_GET_DIRTY_LOG ioctl。 只要所有髒位的生成都在一次傳遞中完成,就不需要 KVM_CLEAR_DIRTY_LOG。 收集髒點陣圖應該是 VMM 在考慮狀態為完整之前所做的最後一件事。 VMM 需要確保髒狀態是最終狀態,並避免丟失在點陣圖收集之後排序的另一個 ioctl 中的髒頁。
注意:使用備份點陣圖的多個示例:(1) 透過 KVM 裝置“kvm-arm-vgic-its”上的命令 KVM_DEV_ARM_{VGIC_GRP_CTRL, ITS_SAVE_TABLES} 儲存 vgic/its 表。 (2) 透過 KVM 裝置“kvm-arm-vgic-its”上的命令 KVM_DEV_ARM_{VGIC_GRP_CTRL, ITS_RESTORE_TABLES} 恢復 vgic/its 表。 恢復 VGICv3 LPI 待處理狀態。 (3) 透過 KVM 裝置“kvm-arm-vgic-v3”上的 KVM_DEV_ARM_VGIC_{GRP_CTRL, SAVE_PENDING_TABLES} 命令儲存 vgic3 待處理表。
7.37 KVM_CAP_PMU_CAPABILITY¶
- 架構:
x86
- 型別:
vm
- 引數:
arg[0] 是 PMU 虛擬化功能的位掩碼。
- 返回值:
成功時為 0,當 arg[0] 包含無效位時為 -EINVAL
此功能會更改 KVM 中的 PMU 虛擬化。
呼叫此功能的 KVM_CHECK_EXTENSION 會返回一個 PMU 虛擬化能力位掩碼,該位掩碼可以在虛擬機器上進行調整。
KVM_ENABLE_CAP 的引數也是一個位掩碼,用於選擇要應用於虛擬機器的特定 PMU 虛擬化能力。 只有在建立 VCPU 之前才能在虛擬機器上呼叫此方法。
目前,KVM_PMU_CAP_DISABLE 是唯一的能力。設定此能力將停用該虛擬機器的 PMU 虛擬化。使用者模式應調整 CPUID 葉 0xA 以反映 PMU 已被停用。
7.38 KVM_CAP_VM_DISABLE_NX_HUGE_PAGES¶
- 架構:
x86
- 型別:
vm
- 引數:
arg[0] 必須為 0。
- 返回值:
成功時返回 0,如果使用者空間程序沒有 CAP_SYS_BOOT 則返回 -EPERM,如果 args[0] 不為 0 或已建立任何 vCPU 則返回 -EINVAL。
此功能停用 iTLB MULTIHIT 的 NX 大頁緩解措施。
如果未設定 nx_huge_pages 模組引數,則該功能無效。
只能在建立任何 vCPU 之前設定此功能。
7.39 KVM_CAP_ARM_EAGER_SPLIT_CHUNK_SIZE¶
- 架構:
arm64
- 型別:
vm
- 引數:
arg[0] 是新的分割塊大小。
- 返回值:
成功時返回 0,如果已建立任何 memslot 則返回 -EINVAL。
此功能設定 Eager Page Splitting 中使用的塊大小。
當客戶機記憶體由大頁支援時,Eager Page Splitting 可提高髒日誌記錄(用於即時遷移)的效能。 它透過在啟用髒日誌記錄(對於記憶體區域使用 KVM_MEM_LOG_DIRTY_PAGES 標誌)或使用 KVM_CLEAR_DIRTY_LOG 時,主動地分割大頁,從而避免在故障時分割大頁(成 PAGE_SIZE 大小的頁)。
塊大小指定一次要分解的頁數,併為每個塊使用單個分配。 塊大小越大,需要提前分配的頁數就越多。
塊大小需要是有效的塊大小。 可接受的塊大小列表在 KVM_CAP_ARM_SUPPORTED_BLOCK_SIZES 中以 64 位點陣圖的形式公開(每位描述一個塊大小)。 預設值為 0,以停用 eager page splitting。
7.40 KVM_CAP_EXIT_HYPERCALL¶
- 架構:
x86
- 型別:
vm
如果啟用此功能,KVM 將以 KVM_EXIT_HYPERCALL 退出原因退出到使用者空間,以處理某些系統呼叫。
呼叫此功能的 KVM_CHECK_EXTENSION 將返回一個位掩碼,該位掩碼錶示可以配置為退出到使用者空間的系統呼叫。 目前,唯一的此類系統呼叫是 KVM_HC_MAP_GPA_RANGE。
KVM_ENABLE_CAP 的引數也是一個位掩碼,並且必須是 KVM_CHECK_EXTENSION 結果的子集。 KVM 將把與其位位於引數中的系統呼叫轉發到使用者空間,併為其他系統呼叫返回 ENOSYS。
7.41 KVM_CAP_ARM_SYSTEM_SUSPEND¶
- 架構:
arm64
- 型別:
vm
啟用後,KVM 將以型別為 KVM_SYSTEM_EVENT_SUSPEND 的 KVM_EXIT_SYSTEM_EVENT 退出到使用者空間,以處理客戶機掛起請求。
7.37 KVM_CAP_ARM_WRITABLE_IMP_ID_REGS¶
- 架構:
arm64
- 目標:
VM
- 引數:
無
- 返回值:
成功時返回 0,如果在啟用此功能之前已建立 vCPU 則返回 -EINVAL。
此功能更改了標識 Arm 架構 PE 實現的暫存器的行為:MIDR_EL1、REVIDR_EL1 和 AIDR_EL1。 預設情況下,這些暫存器對使用者空間可見,但被視為不變。
啟用此功能後,KVM 允許使用者空間在第一次 KVM_RUN 之前更改上述暫存器。 這些暫存器是 VM 範圍的,這意味著在給定 VM 中的所有 vCPU 上呈現相同的值集。
7.43 KVM_CAP_RISCV_MP_STATE_RESET¶
- 架構:
riscv
- 型別:
VM
- 引數:
無
- 返回值:
成功時返回 0,如果 arg[0] 不為零則返回 -EINVAL
啟用此功能後,KVM 會在透過 IOCTL 設定 MP_STATE_INIT_RECEIVED 時重置 VCPU。 原始 MP_STATE 將被保留。
8. 其他功能。¶
本節列出了提供有關 KVM 實現的其他功能的資訊的功能。
8.1 KVM_CAP_PPC_HWRNG¶
- 架構:
ppc
如果 KVM_CHECK_EXTENSION 指示此功能可用,則表示核心具有由硬體隨機數生成器支援的 H_RANDOM 系統呼叫的實現。 如果存在,則可以使用 KVM_CAP_PPC_ENABLE_HCALL 功能為客戶機啟用核心 H_RANDOM 處理程式。
8.3 KVM_CAP_PPC_MMU_RADIX¶
- 架構:
ppc
如果 KVM_CHECK_EXTENSION 指示此功能可用,則表示核心可以支援使用 Power ISA V3.00 中定義的 radix MMU(在 POWER9 處理器中實現)的客戶機。
8.4 KVM_CAP_PPC_MMU_HASH_V3¶
- 架構:
ppc
如果 KVM_CHECK_EXTENSION 指示此功能可用,則表示核心可以支援使用 Power ISA V3.00 中定義的雜湊頁表 MMU(在 POWER9 處理器中實現)的客戶機,包括記憶體中的段表。
8.5 KVM_CAP_MIPS_VZ¶
- 架構:
mips
如果主 kvm 控制代碼上的 KVM_CHECK_EXTENSION 指示此功能可用,則表示硬體的完整硬體輔助虛擬化功能可透過 KVM 使用。 必須將適當的 KVM_VM_MIPS_* 型別傳遞給 KVM_CREATE_VM,以建立一個利用它的 VM。
如果 kvm VM 控制代碼上的 KVM_CHECK_EXTENSION 指示此功能可用,則表示 VM 正在使用硬體的完整硬體輔助虛擬化功能。 這在建立具有 KVM_VM_MIPS_DEFAULT 的 VM 之後檢查非常有用。
KVM_CHECK_EXTENSION 返回的值應與已知值進行比較(請參見下文)。 所有其他值都保留。 這是為了允許其他可能與 MIPS VZ ASE 不相容的硬體輔助虛擬化實現的可能性。
0 |
陷阱 & 模擬實現用於在使用者模式下執行客戶機程式碼。 重新排列客戶機虛擬記憶體段,以使客戶機適應使用者模式地址空間。 |
1 |
正在使用 MIPS VZ ASE,提供完整的硬體輔助虛擬化,包括標準客戶機虛擬記憶體段。 |
8.7 KVM_CAP_MIPS_64BIT¶
- 架構:
mips
此功能指示客戶機支援的架構型別,即支援的暫存器和地址寬度。
當透過 kvm VM 控制代碼上的 KVM_CHECK_EXTENSION 檢查此功能時返回的值大致對應於 CP0_Config.AT 暫存器欄位,應專門針對已知值進行檢查(請參見下文)。 所有其他值都保留。
0 |
MIPS32 或 microMIPS32。 暫存器和地址的寬度均為 32 位。 只能執行 32 位客戶機程式碼。 |
1 |
MIPS64 或 microMIPS64,只能訪問 32 位相容性段。 暫存器的寬度為 64 位,但地址的寬度為 32 位。 64 位客戶機程式碼可以執行,但無法訪問 MIPS64 記憶體段。 也可以執行 32 位客戶機程式碼。 |
2 |
MIPS64 或 microMIPS64,可以訪問所有地址段。 暫存器和地址的寬度均為 64 位。 可以執行 64 位或 32 位客戶機程式碼。 |
8.9 KVM_CAP_ARM_USER_IRQ¶
- 架構:
arm64
如果 KVM_CHECK_EXTENSION 指示此功能可用,則表示如果使用者空間建立一個沒有核心中斷控制器的 VM,它將收到對核心模擬裝置的輸出級別的更改通知,這些裝置可以生成呈現給 VM 的虛擬中斷。 對於此類 VM,每次返回到使用者空間時,核心都會更新 vcpu 的 run->s.regs.device_irq_level 欄位,以表示裝置的實際輸出級別。
每當 kvm 檢測到裝置輸出級別的更改時,kvm 保證在執行 VM 之前至少返回到使用者空間一次。 此退出可以是 KVM_EXIT_INTR 或任何其他退出事件,例如 KVM_EXIT_MMIO。 這樣,使用者空間始終可以取樣裝置輸出級別並重新計算使用者空間中斷控制器的狀態。 使用者空間應始終在每次 kvm 退出時檢查 run->s.regs.device_irq_level 的狀態。 run->s.regs.device_irq_level 中的值可以表示級別和邊沿觸發的中斷訊號,具體取決於裝置。 對於每個邊沿訊號,邊沿觸發的中斷訊號將以 run->s.regs.device_irq_level 中的位僅設定一次的方式退出到使用者空間。
欄位 run->s.regs.device_irq_level 可用,與 run->kvm_valid_regs 或 run->kvm_dirty_regs 位無關。
如果支援 KVM_CAP_ARM_USER_IRQ,則 KVM_CHECK_EXTENSION ioctl 返回一個大於 0 的數字,指示此功能的已實現版本,從而指示 run->s.regs.device_irq_level 中的哪些位可以發出訊號值。
當前為 device_irq_level 點陣圖定義了以下位
KVM_CAP_ARM_USER_IRQ >= 1:
KVM_ARM_DEV_EL1_VTIMER - EL1 virtual timer
KVM_ARM_DEV_EL1_PTIMER - EL1 physical timer
KVM_ARM_DEV_PMU - ARM PMU overflow interrupt signal
kvm 的未來版本可能會實現其他事件。 這些事件將透過從 KVM_CHECK_EXTENSION 返回更高的數字來指示,並且將在上面列出。
8.10 KVM_CAP_PPC_SMT_POSSIBLE¶
- 架構:
ppc
查詢此功能會返回一個位圖,指示可以使用 KVM_CAP_PPC_SMT 設定的可能的虛擬 SMT 模式。 如果設定了位 N(從右開始計數),則 2^N 的虛擬 SMT 模式可用。
8.12 KVM_CAP_HYPERV_VP_INDEX¶
- 架構:
x86
此功能指示使用者空間可以載入 HV_X64_MSR_VP_INDEX msr。 其值用於表示 SynIC 中斷的目標 vcpu。 為了相容性,KVM 將此 msr 初始化為 KVM 的內部 vcpu 索引。 當此功能不存在時,使用者空間仍然可以查詢此 msr 的值。
8.13 KVM_CAP_S390_AIS_MIGRATION¶
- 架構:
s390
此功能指示 flic 裝置是否能夠透過 KVM_DEV_FLIC_AISM_ALL 屬性獲取/設定 AIS 狀態以進行遷移,並允許在不必建立 flic 裝置的情況下發現此功能。
8.14 KVM_CAP_S390_PSW¶
- 架構:
s390
此功能指示 PSW 透過 kvm_run 結構公開。
8.15 KVM_CAP_S390_GMAP¶
- 架構:
s390
此功能指示用作客戶機對映的使用者空間記憶體可以位於使用者記憶體地址空間的任何位置,只要記憶體插槽與段(1MB)邊界對齊並調整大小即可。
8.16 KVM_CAP_S390_COW¶
- 架構:
s390
此功能指示用作客戶機對映的使用者空間記憶體可以使用寫時複製語義以及透過只讀頁表跟蹤髒頁。
8.17 KVM_CAP_S390_BPB¶
- 架構:
s390
此功能指示 kvm 將實現用於處理分支預測阻塞的重置、遷移和巢狀 KVM 的介面。 如果沒有此功能,則不應向客戶機提供 stfle facility 82。
8.18 KVM_CAP_HYPERV_TLBFLUSH¶
- 架構:
x86
此功能指示 KVM 支援半虛擬化的 Hyper-V TLB Flush 系統呼叫:HvFlushVirtualAddressSpace、HvFlushVirtualAddressSpaceEx、HvFlushVirtualAddressList、HvFlushVirtualAddressListEx。
8.19 KVM_CAP_ARM_INJECT_SERROR_ESR¶
- 架構:
arm64
此功能指示使用者空間可以指定(透過 KVM_SET_VCPU_EVENTS ioctl)當客戶機發生虛擬 SError 中斷異常時報告給客戶機的綜合徵值。 如果 KVM 公佈此功能,則使用者空間只能指定 ESR 綜合徵的 ISS 欄位。 ESR 的其他部分(例如 EC)由 CPU 在發生異常時生成。 如果此虛擬 SError 使用 AArch64 進入 EL1,則此值將在 ESR_ELx 的 ISS 欄位中報告。
有關更多詳細資訊,請參見 KVM_CAP_VCPU_EVENTS。
8.20 KVM_CAP_HYPERV_SEND_IPI¶
- 架構:
x86
此功能指示 KVM 支援半虛擬化的 Hyper-V IPI 傳送系統呼叫:HvCallSendSyntheticClusterIpi、HvCallSendSyntheticClusterIpiEx。
8.22 KVM_CAP_S390_VCPU_RESETS¶
- 架構:
s390
此功能指示 KVM_S390_NORMAL_RESET 和 KVM_S390_CLEAR_RESET ioctl 可用。
8.23 KVM_CAP_S390_PROTECTED¶
- 架構:
s390
此功能指示 Ultravisor 已初始化,因此 KVM 可以啟動受保護的 VM。 此功能控制 KVM_S390_PV_COMMAND ioctl 和 KVM_MP_STATE_LOAD MP_STATE。 當狀態更改無效時,KVM_SET_MP_STATE 可能會針對受保護的客戶機失敗。
8.24 KVM_CAP_STEAL_TIME¶
- 架構:
arm64, x86
此功能指示 KVM 支援竊取時間核算。 當支援竊取時間核算時,可以使用特定於架構的介面啟用它。 此功能和特定於架構的介面必須一致,即,如果一個說該功能受支援,則另一個也應如此,反之亦然。 對於 arm64,請參見 通用 vcpu 介面 “KVM_ARM_VCPU_PVTIME_CTRL”。 對於 x86,請參見 KVM 特定的 MSR “MSR_KVM_STEAL_TIME”。
8.25 KVM_CAP_S390_DIAG318¶
- 架構:
s390
此功能使客戶機能夠設定有關其控制程式的資訊(即客戶機核心型別和版本)。 該資訊在系統/韌體服務事件期間非常有用,提供了有關在計算機上執行的客戶機環境的附加資料。
該資訊與 DIAGNOSE 0x318 指令相關聯,該指令設定一個 8 位元組的值,該值由一個位元組的控制程式名稱程式碼 (CPNC) 和一個 7 位元組的控制程式版本程式碼 (CPVC) 組成。 CPNC 確定控制程式在什麼環境中執行(例如 Linux、z/VM...),CPVC 用於特定於 OS 的資訊(例如 Linux 版本、Linux 發行版...)
如果此功能可用,則 CPNC 和 CPVC 可以透過同步暫存器機制(KVM_SYNC_DIAG318)在 KVM 和使用者空間之間同步。
8.26 KVM_CAP_X86_USER_SPACE_MSR¶
- 架構:
x86
此功能指示 KVM 支援將 MSR 讀取和寫入偏轉到使用者空間。 可以在 VM 級別啟用它。 如果啟用,通常會透過 KVM 將 #GP 觸發到客戶機中的 MSR 訪問將透過 KVM_EXIT_X86_RDMSR 和 KVM_EXIT_X86_WRMSR 退出通知反彈到使用者空間。
8.27 KVM_CAP_X86_MSR_FILTER¶
- 架構:
x86
此功能指示 KVM 支援拒絕訪問使用者定義的 MSR。 在公開此功能後,KVM 會匯出新的 VM ioctl KVM_X86_SET_MSR_FILTER,使用者空間可以呼叫它來指定 KVM 應拒絕訪問的 MSR 範圍的點陣圖。
與 KVM_CAP_X86_USER_SPACE_MSR 結合使用,這允許使用者空間捕獲和模擬 KVM 範圍之外的 MSR,並限制對 KVM 的 MSR 模擬程式碼的攻擊面。
8.30 KVM_CAP_XEN_HVM¶
- 架構:
x86
此功能指示 Xen 支援用於託管 Xen PVHVM 客戶機的功能。 有效標誌為
#define KVM_XEN_HVM_CONFIG_HYPERCALL_MSR (1 << 0)
#define KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL (1 << 1)
#define KVM_XEN_HVM_CONFIG_SHARED_INFO (1 << 2)
#define KVM_XEN_HVM_CONFIG_RUNSTATE (1 << 3)
#define KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL (1 << 4)
#define KVM_XEN_HVM_CONFIG_EVTCHN_SEND (1 << 5)
#define KVM_XEN_HVM_CONFIG_RUNSTATE_UPDATE_FLAG (1 << 6)
#define KVM_XEN_HVM_CONFIG_PVCLOCK_TSC_UNSTABLE (1 << 7)
KVM_XEN_HVM_CONFIG_HYPERCALL_MSR 標誌指示 KVM_XEN_HVM_CONFIG ioctl 可用,用於客戶機設定其系統呼叫頁。
如果還設定了 KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL,則可以在不提供系統呼叫頁內容的情況下,在 KVM_XEN_HVM_CONFIG 的標誌中提供相同的標誌,以請求 KVM 自動生成系統呼叫頁內容,並啟用使用 KVM_EXIT_XEN 攔截客戶機系統呼叫。
KVM_XEN_HVM_CONFIG_SHARED_INFO 標誌指示 KVM_XEN_HVM_SET_ATTR、KVM_XEN_HVM_GET_ATTR、KVM_XEN_VCPU_SET_ATTR 和 KVM_XEN_VCPU_GET_ATTR ioctl 的可用性,以及當設定了 vcpu 的 vcpu_info 的 evtchn_upcall_pending 欄位時,事件通道回撥的異常向量的傳遞。
KVM_XEN_HVM_CONFIG_RUNSTATE 標誌指示 KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADDR/_CURRENT/_DATA/_ADJUST 等執行狀態相關功能受 KVM_XEN_VCPU_SET_ATTR/KVM_XEN_VCPU_GET_ATTR ioctl 支援。
KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL 標誌指示支援型別為 KVM_IRQ_ROUTING_XEN_EVTCHN 的 IRQ 路由條目,並且優先順序欄位設定為指示 2 級事件通道傳遞。
KVM_XEN_HVM_CONFIG_EVTCHN_SEND 標誌指示 KVM 支援使用 KVM_XEN_HVM_EVTCHN_SEND ioctl 將事件通道事件直接注入到客戶機中。 它還指示支援與事件通道傳遞、計時器和 XENVER_version 攔截相關的 KVM_XEN_ATTR_TYPE_EVTCHN/XEN_VERSION HVM 屬性和 KVM_XEN_VCPU_ATTR_TYPE_VCPU_ID/TIMER/UPCALL_VECTOR vCPU 屬性。
KVM_XEN_HVM_CONFIG_RUNSTATE_UPDATE_FLAG 標誌指示 KVM 支援 KVM_XEN_SET_ATTR 和 KVM_XEN_GET_ATTR ioctl 中的 KVM_XEN_ATTR_TYPE_RUNSTATE_UPDATE_FLAG 屬性。 這控制 KVM 是否將在更新執行狀態資訊期間,在客戶機記憶體對映的 vcpu_runstate_info 中設定 XEN_RUNSTATE_UPDATE 標誌。 請注意,支援上述 RUNSTATE 功能但不支援 RUNSTATE_UPDATE_FLAG 功能的 KVM 版本在更新客戶機結構時將始終設定 XEN_RUNSTATE_UPDATE 標誌,這可能違反直覺。 當公佈此標誌時,KVM 的行為將更正確,除非專門啟用(透過客戶機進行系統呼叫,從而使 VMM 能夠啟用 KVM_XEN_ATTR_TYPE_RUNSTATE_UPDATE_FLAG 屬性),否則不會使用 XEN_RUNSTATE_UPDATE 標誌。
KVM_XEN_HVM_CONFIG_PVCLOCK_TSC_UNSTABLE 標誌指示 KVM 支援清除 Xen pvclock 源中的 PVCLOCK_TSC_STABLE_BIT 標誌。 這將在 KVM_CAP_XEN_HVM ioctl 設定 KVM_XEN_HVM_CONFIG_PVCLOCK_TSC_UNSTABLE 標誌時完成。
8.31 KVM_CAP_SPAPR_MULTITCE¶
- 架構:
ppc
- 型別:
vm
此功能表示核心能夠處理系統呼叫 H_PUT_TCE_INDIRECT 和 H_STUFF_TCE,而無需將它們傳遞到使用者空間。 這顯著加速了 PPC KVM 客戶機的 DMA 操作。 使用者空間應預期,如果使用者空間先前在 KVM 中註冊了 LIOBN(透過 KVM_CREATE_SPAPR_TCE 或類似呼叫),則其對這些系統呼叫的處理程式將不會被呼叫。
為了在客戶機中啟用 H_PUT_TCE_INDIRECT 和 H_STUFF_TCE 的使用,使用者空間可能必須為客戶機公佈它。 例如,如果在“ibm,hypertas-functions”裝置樹屬性中存在“hcall-multi-tce”,則 IBM pSeries (sPAPR) 客戶機將開始使用它們。
上述系統呼叫可能在基於核心快速路徑中成功處理,也可能未成功處理。 如果核心無法處理它們,它們將被傳遞到使用者空間。 因此,儘管有核心加速,使用者空間仍然必須對這些系統呼叫進行實現。
此功能始終啟用。
8.32 KVM_CAP_PTP_KVM¶
- 架構:
arm64
此功能指示主機中支援 KVM 虛擬 PTP 服務。 VMM 可以檢查遷移時服務是否對客戶機可用。
8.37 KVM_CAP_S390_PROTECTED_DUMP¶
- 架構:
s390
- 型別:
vm
此功能指示 KVM 和 Ultravisor 支援轉儲 PV 客戶機。 KVM_PV_DUMP 命令可用於 KVM_S390_PV_COMMAND ioctl,並且 KVM_PV_INFO 命令提供與轉儲相關的 UV 資料。 此外,vcpu ioctl KVM_S390_PV_CPU_COMMAND 可用,並且支援 KVM_PV_DUMP_CPU 子命令。
8.39 KVM_CAP_S390_CPU_TOPOLOGY¶
- 架構:
s390
- 型別:
vm
此功能指示 KVM 將提供 S390 CPU 拓撲設施,該設施包括對功能程式碼 2 的 PTF 指令的解釋以及攔截和轉發功能程式碼為 0 或 1 的 PTF 指令和 STSI(15,1,x) 指令到使用者空間虛擬機器監控程式。
如果沒有此功能,則不應向客戶機指示 stfle facility 11 CPU 拓撲設施。
當此功能存在時,KVM 在 vm fd 上提供新的屬性組 KVM_S390_VM_CPU_TOPOLOGY。 此新屬性允許透過 kvm_device_attr 結構獲取、設定或清除 SCA 的修改後的更改拓撲報告 (MTCR) 位。
當獲取修改後的更改拓撲報告值時,attr->addr 必須指向將在其中儲存或檢索該值的位元組。
8.41 KVM_CAP_VM_TYPES¶
- 架構:
x86
- 型別:
系統 ioctl
此功能返回支援的 VM 型別的點陣圖。 位 @n 的 1 設定表示支援值為 @n 的 VM 型別。 @n 的可能值為
#define KVM_X86_DEFAULT_VM 0
#define KVM_X86_SW_PROTECTED_VM 1
#define KVM_X86_SEV_VM 2
#define KVM_X86_SEV_ES_VM 3
注意,KVM_X86_SW_PROTECTED_VM 當前僅用於開發和測試。 不要將 KVM_X86_SW_PROTECTED_VM 用於“真實” VM,尤其不要在生產中使用。 軟體保護的 VM 的行為和有效 ABI 不穩定。
8.42 KVM_CAP_PPC_RPT_INVALIDATE¶
- 架構:
ppc
此功能指示核心能夠處理 H_RPT_INVALIDATE hcall。
為了在客戶機中啟用 H_RPT_INVALIDATE 的使用,使用者空間可能必須為客戶機公佈它。 例如,如果在“ibm,hypertas-functions”裝置樹屬性中存在“hcall-rpt-invalidate”,則 IBM pSeries (sPAPR) 客戶機將開始使用它。
對於 POWER9 等支援 radix MMU 的平臺上的虛擬機器監控程式,此功能已啟用。
8.43 KVM_CAP_PPC_AIL_MODE_3¶
- 架構:
ppc
此功能指示核心支援“中斷時的地址轉換模式”(也稱為“備用中斷位置”)資源的模式 3 設定,該資源由 H_SET_MODE 系統呼叫控制。
此功能允許客戶機核心使用更高效能的模式來處理中斷和系統呼叫。
8.44 KVM_CAP_MEMORY_FAULT_INFO¶
- 架構:
x86
此功能的出現表明,如果 KVM 無法解決客戶機頁面錯誤 VM-Exit,例如,如果存在有效的 memslot 但對應的宿主機虛擬地址沒有支援的 VMA,則 KVM_RUN 將填充 kvm_run.memory_fault。
僅當 KVM_RUN 返回錯誤,errno=EFAULT 或 errno=EHWPOISON 並且 kvm_run.exit_reason 設定為 KVM_EXIT_MEMORY_FAULT 時,kvm_run.memory_fault 中的資訊才有效。
注意:鼓勵嘗試解決記憶體錯誤的 Userspace 保護自己免於重複收到相同的錯誤/帶註釋的錯誤,以便他們可以重試 KVM_RUN。
有關更多資訊,請參見 KVM_EXIT_MEMORY_FAULT。
8.45 KVM_CAP_X86_GUEST_MODE¶
- 架構:
x86
此功能的出現表明 KVM_RUN 將更新 kvm_run.flags 中的 KVM_RUN_X86_GUEST_MODE 位,以指示 vCPU 在退出時是否正在執行巢狀的客戶機程式碼。
KVM 將退出時的 L1 或 L2 客戶機的暫存器狀態退出,具體取決於退出時執行的暫存器狀態。 使用者空間必須注意區分這些情況。
9. 已知的 KVM API 問題¶
在某些情況下,KVM 的 API 存在一些不一致或常見的陷阱,使用者空間需要注意。本節詳細介紹其中一些問題。
它們中的大多數是架構特定的,因此本節按架構劃分。
9.1. x86¶
KVM_GET_SUPPORTED_CPUID 問題¶
通常,KVM_GET_SUPPORTED_CPUID 的設計使得可以直接獲取其結果並將其傳遞給 KVM_SET_CPUID2。本節記錄了一些需要注意的情況。
本地 APIC 功能¶
CPU[EAX=1]:ECX[21] (X2APIC) 由 KVM_GET_SUPPORTED_CPUID 報告,但只有在使用 KVM_CREATE_IRQCHIP 或 KVM_ENABLE_CAP(KVM_CAP_IRQCHIP_SPLIT) 啟用核心中本地 APIC 的模擬時才能啟用。
對於 KVM_FEATURE_PV_UNHALT 半虛擬化功能也是如此。
在舊版本的 Linux 上,CPU[EAX=1]:ECX[24] (TSC_DEADLINE) 不由 KVM_GET_SUPPORTED_CPUID 報告,但如果存在 KVM_CAP_TSC_DEADLINE_TIMER 並且核心已啟用核心中本地 APIC 的模擬,則可以啟用它。 在較新版本上,KVM_GET_SUPPORTED_CPUID 確實報告該位可用。
CPU 拓撲¶
一些 CPUID 值包含主機 CPU 的拓撲資訊:Intel 系統的 0x0b 和 0x1f,AMD 系統的 0x8000001e。 不同版本的 KVM 為此資訊返回不同的值,使用者空間不應依賴它。 目前,它們返回全零。
如果使用者空間希望設定客戶機拓撲,則應注意這三個葉子的值對於每個 CPU 而言都不同。 特別是,APIC ID 在 0x0b 和 0x1f 的所有子葉的 EDX 中找到,在 0x8000001e 的 EAX 中找到; 後者還在 EBX 和 ECX 的位 7:0 中分別編碼核心 ID 和節點 ID。
過時的 ioctl 和 capabilities¶
KVM_CAP_DISABLE_QUIRKS 不允許使用者空間知道實際可用的 quirks。 如果可用,請改用 KVM_CHECK_EXTENSION(KVM_CAP_DISABLE_QUIRKS2)。
KVM_GET_*/KVM_SET_* ioctl 的排序¶
待定