[RFC PATCH part-5 13/22] pkvm: x86: Initialize emulated fields for vmcs emulation

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

 



For vmcs shadow fields, Host VM directly access through VMREAD/WMWRITE
without vmexit.

Meanwhile for other vmcs fields, the VMREAD/WMWRITE from host VM cause
vmread/wmwrite vmexit, pKVM need to handle them. Such fields can be
divided into two categories: one is host fields, pKVM just need to
record them as the value host VM set, the other one is emulated fields
which pKVM need to do emulation to ensure the isolation/security.

Introduce a MACRO EMULATED_FIELD_RW in pkvm_nested_vmcs_fields.h to
help pre-define the emulated fields for vmcs emulation, based on
it, initialize emulated_fields[] array for future emulation.

Signed-off-by: Jason Chen CJ <jason.cj.chen@xxxxxxxxx>
---
 arch/x86/kvm/vmx/pkvm/hyp/nested.c            | 23 +++++++++++
 .../vmx/pkvm/hyp/pkvm_nested_vmcs_fields.h    | 41 ++++++++++++++++++-
 2 files changed, 63 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kvm/vmx/pkvm/hyp/nested.c b/arch/x86/kvm/vmx/pkvm/hyp/nested.c
index 8ae37feda5ff..8e6d0f01819a 100644
--- a/arch/x86/kvm/vmx/pkvm/hyp/nested.c
+++ b/arch/x86/kvm/vmx/pkvm/hyp/nested.c
@@ -149,6 +149,12 @@ static struct shadow_vmcs_field shadow_read_write_fields[] = {
 };
 static int max_shadow_read_write_fields =
 	ARRAY_SIZE(shadow_read_write_fields);
+static struct shadow_vmcs_field emulated_fields[] = {
+#define EMULATED_FIELD_RW(x, y) { x, offsetof(struct vmcs12, y) },
+#include "pkvm_nested_vmcs_fields.h"
+};
+static int max_emulated_fields =
+	ARRAY_SIZE(emulated_fields);
 
 static void init_vmcs_shadow_fields(void)
 {
@@ -201,6 +207,22 @@ static void init_vmcs_shadow_fields(void)
 	max_shadow_read_write_fields = j;
 }
 
+static void init_emulated_vmcs_fields(void)
+{
+	int i, j;
+
+	for (i = j = 0; i < max_emulated_fields; i++) {
+		struct shadow_vmcs_field entry = emulated_fields[i];
+		u16 field = entry.encoding;
+
+		if (!has_vmcs_field(field))
+			continue;
+
+		emulated_fields[j++] = entry;
+	}
+	max_emulated_fields = j;
+}
+
 static void nested_vmx_result(enum VMXResult result, int error_number)
 {
 	u64 rflags = vmcs_readl(GUEST_RFLAGS);
@@ -384,4 +406,5 @@ int handle_vmxoff(struct kvm_vcpu *vcpu)
 void pkvm_init_nest(void)
 {
 	init_vmcs_shadow_fields();
+	init_emulated_vmcs_fields();
 }
diff --git a/arch/x86/kvm/vmx/pkvm/hyp/pkvm_nested_vmcs_fields.h b/arch/x86/kvm/vmx/pkvm/hyp/pkvm_nested_vmcs_fields.h
index 4380d415428f..8666cda4ee6d 100644
--- a/arch/x86/kvm/vmx/pkvm/hyp/pkvm_nested_vmcs_fields.h
+++ b/arch/x86/kvm/vmx/pkvm/hyp/pkvm_nested_vmcs_fields.h
@@ -2,10 +2,13 @@
 /*
  * Copyright (C) 2022 Intel Corporation
  */
-#if !defined(SHADOW_FIELD_RW) && !defined(SHADOW_FIELD_RO)
+#if !defined(EMULATED_FIELD_RW) && !defined(SHADOW_FIELD_RW) && !defined(SHADOW_FIELD_RO)
 BUILD_BUG_ON(1)
 #endif
 
+#ifndef EMULATED_FIELD_RW
+#define EMULATED_FIELD_RW(x, y)
+#endif
 #ifndef SHADOW_FIELD_RW
 #define SHADOW_FIELD_RW(x, y)
 #endif
@@ -13,6 +16,41 @@ BUILD_BUG_ON(1)
 #define SHADOW_FIELD_RO(x, y)
 #endif
 
+/*
+ * Emulated fields for vmcs02:
+ *
+ * These fields are recorded in cached_vmcs12, and should be emulated to
+ * real value in vmcs02 before vmcs01 active.
+ */
+/* 16-bits */
+EMULATED_FIELD_RW(VIRTUAL_PROCESSOR_ID, virtual_processor_id)
+
+/* 32-bits */
+EMULATED_FIELD_RW(VM_EXIT_CONTROLS, vm_exit_controls)
+EMULATED_FIELD_RW(VM_ENTRY_CONTROLS, vm_entry_controls)
+
+/* 64-bits, what about their HIGH 32 fields?  */
+EMULATED_FIELD_RW(IO_BITMAP_A, io_bitmap_a)
+EMULATED_FIELD_RW(IO_BITMAP_B, io_bitmap_b)
+EMULATED_FIELD_RW(MSR_BITMAP, msr_bitmap)
+EMULATED_FIELD_RW(VM_EXIT_MSR_STORE_ADDR, vm_exit_msr_store_addr)
+EMULATED_FIELD_RW(VM_EXIT_MSR_LOAD_ADDR, vm_exit_msr_load_addr)
+EMULATED_FIELD_RW(VM_ENTRY_MSR_LOAD_ADDR, vm_entry_msr_load_addr)
+EMULATED_FIELD_RW(XSS_EXIT_BITMAP, xss_exit_bitmap)
+EMULATED_FIELD_RW(POSTED_INTR_DESC_ADDR, posted_intr_desc_addr)
+EMULATED_FIELD_RW(PML_ADDRESS, pml_address)
+EMULATED_FIELD_RW(VM_FUNCTION_CONTROL, vm_function_control)
+EMULATED_FIELD_RW(EPT_POINTER, ept_pointer)
+EMULATED_FIELD_RW(EOI_EXIT_BITMAP0, eoi_exit_bitmap0)
+EMULATED_FIELD_RW(EOI_EXIT_BITMAP1, eoi_exit_bitmap1)
+EMULATED_FIELD_RW(EOI_EXIT_BITMAP2, eoi_exit_bitmap2)
+EMULATED_FIELD_RW(EOI_EXIT_BITMAP3, eoi_exit_bitmap3)
+EMULATED_FIELD_RW(EPTP_LIST_ADDRESS, eptp_list_address)
+EMULATED_FIELD_RW(VMREAD_BITMAP, vmread_bitmap)
+EMULATED_FIELD_RW(VMWRITE_BITMAP, vmwrite_bitmap)
+EMULATED_FIELD_RW(ENCLS_EXITING_BITMAP, encls_exiting_bitmap)
+EMULATED_FIELD_RW(VMCS_LINK_POINTER, vmcs_link_pointer)
+
 /*
  * Shadow fields for vmcs02:
  *
@@ -152,5 +190,6 @@ SHADOW_FIELD_RO(GUEST_LINEAR_ADDRESS, guest_linear_address)
 SHADOW_FIELD_RO(GUEST_PHYSICAL_ADDRESS, guest_physical_address)
 SHADOW_FIELD_RO(GUEST_PHYSICAL_ADDRESS_HIGH, guest_physical_address)
 
+#undef EMULATED_FIELD_RW
 #undef SHADOW_FIELD_RW
 #undef SHADOW_FIELD_RO
-- 
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