[RFC PATCH part-2 03/17] pkvm: x86: Add vmx capability check and vmx config setup

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Check minimal vmx capabilities requirement for pKVM on Intel platform.
Setup vmcs config and vmx cap for later run VCPUs of deprivileged
host VM.

The vmx capabilities are checked through setup_vmcs_config_common,
the same API as KVM. pKVM tries to pass-thru resource to host VM as
much as possible, so it does not need to do a lot of emulations;
but some capabilities are still required for pKVM's emulations
(e.g. EPT, SHADOW_VMCS, MSR_BITMAP etc.), so pKVM has its own
different check-set from KVM.

Signed-off-by: Chuanxiao Dong <chuanxiao.dong@xxxxxxxxx>
Signed-off-by: Jason Chen CJ <jason.cj.chen@xxxxxxxxx>
---
 arch/x86/kvm/vmx/pkvm/Makefile       |  1 +
 arch/x86/kvm/vmx/pkvm/include/pkvm.h |  5 +++
 arch/x86/kvm/vmx/pkvm/pkvm_host.c    | 66 ++++++++++++++++++++++++++++
 3 files changed, 72 insertions(+)

diff --git a/arch/x86/kvm/vmx/pkvm/Makefile b/arch/x86/kvm/vmx/pkvm/Makefile
index 493bec8501c9..1795d5f9b4b0 100644
--- a/arch/x86/kvm/vmx/pkvm/Makefile
+++ b/arch/x86/kvm/vmx/pkvm/Makefile
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 
+ccflags-y += -I $(srctree)/arch/x86/kvm
 ccflags-y += -I $(srctree)/arch/x86/kvm/vmx/pkvm/include
 
 pkvm-obj		:= pkvm_host.o
diff --git a/arch/x86/kvm/vmx/pkvm/include/pkvm.h b/arch/x86/kvm/vmx/pkvm/include/pkvm.h
index 3fb76665e785..cda599194588 100644
--- a/arch/x86/kvm/vmx/pkvm/include/pkvm.h
+++ b/arch/x86/kvm/vmx/pkvm/include/pkvm.h
@@ -6,8 +6,13 @@
 #ifndef _PKVM_H_
 #define _PKVM_H_
 
+#include <vmx/vmx.h>
+
 struct pkvm_hyp {
 	int num_cpus;
+
+	struct vmx_capability vmx_cap;
+	struct vmcs_config vmcs_config;
 };
 
 #define PKVM_PAGES (ALIGN(sizeof(struct pkvm_hyp), PAGE_SIZE) >> PAGE_SHIFT)
diff --git a/arch/x86/kvm/vmx/pkvm/pkvm_host.c b/arch/x86/kvm/vmx/pkvm/pkvm_host.c
index 7677df6a2b34..8fd31360faf8 100644
--- a/arch/x86/kvm/vmx/pkvm/pkvm_host.c
+++ b/arch/x86/kvm/vmx/pkvm/pkvm_host.c
@@ -17,6 +17,64 @@ static void *pkvm_early_alloc_contig(int pages)
 	return alloc_pages_exact(pages << PAGE_SHIFT, GFP_KERNEL | __GFP_ZERO);
 }
 
+static void pkvm_early_free(void *ptr, int pages)
+{
+	free_pages_exact(ptr, pages << PAGE_SHIFT);
+}
+
+static __init int pkvm_host_check_and_setup_vmx_cap(struct pkvm_hyp *pkvm)
+{
+	struct vmcs_config *vmcs_config = &pkvm->vmcs_config;
+	struct vmx_capability *vmx_cap = &pkvm->vmx_cap;
+	int ret = 0;
+	struct vmcs_config_setting setting = {
+		.cpu_based_vm_exec_ctrl_req =
+			CPU_BASED_INTR_WINDOW_EXITING |
+			CPU_BASED_USE_MSR_BITMAPS |
+			CPU_BASED_ACTIVATE_SECONDARY_CONTROLS,
+		.cpu_based_vm_exec_ctrl_opt = 0,
+		.secondary_vm_exec_ctrl_req =
+			SECONDARY_EXEC_ENABLE_EPT |
+			SECONDARY_EXEC_SHADOW_VMCS,
+		.secondary_vm_exec_ctrl_opt =
+			SECONDARY_EXEC_ENABLE_VPID |
+			SECONDARY_EXEC_ENABLE_INVPCID |
+			SECONDARY_EXEC_XSAVES |
+			SECONDARY_EXEC_ENABLE_RDTSCP |
+			SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE,
+		.tertiary_vm_exec_ctrl_opt = 0,
+		.pin_based_vm_exec_ctrl_req = 0,
+		.pin_based_vm_exec_ctrl_opt = 0,
+		.vmexit_ctrl_req =
+			VM_EXIT_HOST_ADDR_SPACE_SIZE |
+			VM_EXIT_LOAD_IA32_PAT |
+			VM_EXIT_LOAD_IA32_EFER |
+			VM_EXIT_SAVE_IA32_PAT |
+			VM_EXIT_SAVE_IA32_EFER |
+			VM_EXIT_SAVE_DEBUG_CONTROLS,
+		.vmexit_ctrl_opt = 0,
+		.vmentry_ctrl_req =
+			VM_ENTRY_LOAD_DEBUG_CONTROLS |
+			VM_ENTRY_IA32E_MODE |
+			VM_ENTRY_LOAD_IA32_EFER |
+			VM_ENTRY_LOAD_IA32_PAT,
+		.vmentry_ctrl_opt = 0,
+	};
+
+	ret = setup_vmcs_config_common(vmcs_config, vmx_cap, &setting);
+	if (ret) {
+		pr_err("%s: fail with ret %d\n", __func__, ret);
+	} else {
+		pr_info("pin_based_exec_ctrl 0x%x\n", vmcs_config->pin_based_exec_ctrl);
+		pr_info("cpu_based_exec_ctrl 0x%x\n", vmcs_config->cpu_based_exec_ctrl);
+		pr_info("cpu_based_2nd_exec_ctrl 0x%x\n", vmcs_config->cpu_based_2nd_exec_ctrl);
+		pr_info("vmexit_ctrl 0x%x\n", vmcs_config->vmexit_ctrl);
+		pr_info("vmentry_ctrl 0x%x\n", vmcs_config->vmentry_ctrl);
+	}
+
+	return ret;
+}
+
 __init int pkvm_init(void)
 {
 	int ret = 0;
@@ -27,8 +85,16 @@ __init int pkvm_init(void)
 		goto out;
 	}
 
+	ret = pkvm_host_check_and_setup_vmx_cap(pkvm);
+	if (ret)
+		goto out_free_pkvm;
+
 	pkvm->num_cpus = num_possible_cpus();
 
+	return 0;
+
+out_free_pkvm:
+	pkvm_early_free(pkvm, PKVM_PAGES);
 out:
 	return ret;
 }
-- 
2.25.1




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux