From: "Xin Li (Intel)" <[email protected]>

Add support for secondary VM exit controls in nested VMX to facilitate
future FRED integration.

Signed-off-by: Xin Li (Intel) <[email protected]>
Signed-off-by: Sohil Mehta <[email protected]>
---
v10:
 - Add MSR_IA32_VMX_EXIT_CTLS2 to emulated_msrs_all[] for live
   migration. (Chao Gao)
 - Reject vmcs12's secondary VM exit controls that KVM doesn't advertise
   to L1 in MSR_IA32_VMX_EXIT_CTLS2.
---
 arch/x86/kvm/msrs.c             |  1 +
 arch/x86/kvm/msrs.h             |  2 +-
 arch/x86/kvm/vmx/capabilities.h |  1 +
 arch/x86/kvm/vmx/nested.c       | 29 ++++++++++++++++++++++++++++-
 arch/x86/kvm/vmx/nested.h       |  5 +++++
 arch/x86/kvm/vmx/vmcs12.c       |  1 +
 arch/x86/kvm/vmx/vmcs12.h       |  3 ++-
 7 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kvm/msrs.c b/arch/x86/kvm/msrs.c
index 9eabb7b02cb5..3260bddb5f52 100644
--- a/arch/x86/kvm/msrs.c
+++ b/arch/x86/kvm/msrs.c
@@ -317,6 +317,7 @@ static const u32 emulated_msrs_all[] = {
        MSR_IA32_VMX_PROCBASED_CTLS2,
        MSR_IA32_VMX_EPT_VPID_CAP,
        MSR_IA32_VMX_VMFUNC,
+       MSR_IA32_VMX_EXIT_CTLS2,
 
        MSR_K7_HWCR,
        MSR_KVM_POLL_CONTROL,
diff --git a/arch/x86/kvm/msrs.h b/arch/x86/kvm/msrs.h
index 7cc182a15b3b..845d2cbe80e5 100644
--- a/arch/x86/kvm/msrs.h
+++ b/arch/x86/kvm/msrs.h
@@ -31,7 +31,7 @@ static inline void kvm_pr_unimpl_rdmsr(struct kvm_vcpu *vcpu, 
u32 msr)
  * associated feature that KVM supports for nested virtualization.
  */
 #define KVM_FIRST_EMULATED_VMX_MSR     MSR_IA32_VMX_BASIC
-#define KVM_LAST_EMULATED_VMX_MSR      MSR_IA32_VMX_VMFUNC
+#define KVM_LAST_EMULATED_VMX_MSR      MSR_IA32_VMX_EXIT_CTLS2
 
 /*
  * KVM's internal, non-ABI indices for synthetic MSRs. The values themselves
diff --git a/arch/x86/kvm/vmx/capabilities.h b/arch/x86/kvm/vmx/capabilities.h
index 95d22a54f856..9cca65b226fd 100644
--- a/arch/x86/kvm/vmx/capabilities.h
+++ b/arch/x86/kvm/vmx/capabilities.h
@@ -36,6 +36,7 @@ struct nested_vmx_msrs {
        u32 pinbased_ctls_high;
        u32 exit_ctls_low;
        u32 exit_ctls_high;
+       u64 secondary_exit_ctls;
        u32 entry_ctls_low;
        u32 entry_ctls_high;
        u32 misc_low;
diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
index 151873407abd..6576935b9d43 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -1596,6 +1596,11 @@ int vmx_set_vmx_msr(struct kvm_vcpu *vcpu, u32 
msr_index, u64 data)
                        return -EINVAL;
                vmx->nested.msrs.vmfunc_controls = data;
                return 0;
+       case MSR_IA32_VMX_EXIT_CTLS2:
+               if (data & ~vmcs_config.nested.secondary_exit_ctls)
+                       return -EINVAL;
+               vmx->nested.msrs.secondary_exit_ctls = data;
+               return 0;
        default:
                /*
                 * The rest of the VMX capability MSRs do not support restore.
@@ -1635,6 +1640,9 @@ int vmx_get_vmx_msr(struct nested_vmx_msrs *msrs, u32 
msr_index, u64 *pdata)
                if (msr_index == MSR_IA32_VMX_EXIT_CTLS)
                        *pdata |= VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR;
                break;
+       case MSR_IA32_VMX_EXIT_CTLS2:
+               *pdata = msrs->secondary_exit_ctls;
+               break;
        case MSR_IA32_VMX_TRUE_ENTRY_CTLS:
        case MSR_IA32_VMX_ENTRY_CTLS:
                *pdata = vmx_control_msr(
@@ -2576,6 +2584,9 @@ static void prepare_vmcs02_early(struct vcpu_vmx *vmx, 
struct loaded_vmcs *vmcs0
                exec_control &= ~VM_EXIT_LOAD_IA32_EFER;
        vm_exit_controls_set(vmx, exec_control);
 
+       if (exec_control & VM_EXIT_ACTIVATE_SECONDARY_CONTROLS)
+               secondary_vm_exit_controls_set(vmx, 
__secondary_vm_exit_controls_get(vmcs01));
+
        /*
         * Interrupt/Exception Fields
         */
@@ -3040,6 +3051,11 @@ static int nested_check_vm_exit_controls(struct kvm_vcpu 
*vcpu,
            CC(nested_vmx_check_exit_msr_switch_controls(vcpu, vmcs12)))
                return -EINVAL;
 
+       if (nested_cpu_has_secondary_vm_exit_controls(vmcs12) &&
+           CC(vmcs12->secondary_vm_exit_controls &
+              ~vmx->nested.msrs.secondary_exit_ctls))
+               return -EINVAL;
+
        return 0;
 }
 
@@ -7152,7 +7168,8 @@ static void nested_vmx_setup_exit_ctls(struct vmcs_config 
*vmcs_conf,
                VM_EXIT_HOST_ADDR_SPACE_SIZE |
 #endif
                VM_EXIT_LOAD_IA32_PAT | VM_EXIT_SAVE_IA32_PAT |
-               VM_EXIT_CLEAR_BNDCFGS | VM_EXIT_LOAD_CET_STATE;
+               VM_EXIT_CLEAR_BNDCFGS | VM_EXIT_LOAD_CET_STATE |
+               VM_EXIT_ACTIVATE_SECONDARY_CONTROLS;
        msrs->exit_ctls_high |=
                VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR |
                VM_EXIT_LOAD_IA32_EFER | VM_EXIT_SAVE_IA32_EFER |
@@ -7165,6 +7182,16 @@ static void nested_vmx_setup_exit_ctls(struct 
vmcs_config *vmcs_conf,
 
        /* We support free control of debug control saving. */
        msrs->exit_ctls_low &= ~VM_EXIT_SAVE_DEBUG_CONTROLS;
+
+       if (msrs->exit_ctls_high & VM_EXIT_ACTIVATE_SECONDARY_CONTROLS) {
+               msrs->secondary_exit_ctls = vmcs_conf->vmexit_2nd_ctrl;
+               /*
+                * As the secondary VM exit control is always loaded, do not
+                * advertise any feature in it to nVMX until its nVMX support
+                * is ready.
+                */
+               msrs->secondary_exit_ctls &= 0;
+       }
 }
 
 static void nested_vmx_setup_entry_ctls(struct vmcs_config *vmcs_conf,
diff --git a/arch/x86/kvm/vmx/nested.h b/arch/x86/kvm/vmx/nested.h
index c6de848bd9ce..371fc3498b12 100644
--- a/arch/x86/kvm/vmx/nested.h
+++ b/arch/x86/kvm/vmx/nested.h
@@ -247,6 +247,11 @@ static inline bool 
nested_cpu_has_save_preemption_timer(struct vmcs12 *vmcs12)
            VM_EXIT_SAVE_VMX_PREEMPTION_TIMER;
 }
 
+static inline bool nested_cpu_has_secondary_vm_exit_controls(struct vmcs12 
*vmcs12)
+{
+       return vmcs12->vm_exit_controls & VM_EXIT_ACTIVATE_SECONDARY_CONTROLS;
+}
+
 static inline bool nested_exit_on_nmi(struct kvm_vcpu *vcpu)
 {
        return nested_cpu_has_nmi_exiting(get_vmcs12(vcpu));
diff --git a/arch/x86/kvm/vmx/vmcs12.c b/arch/x86/kvm/vmx/vmcs12.c
index 1ebe67c384ad..9d64a89aff00 100644
--- a/arch/x86/kvm/vmx/vmcs12.c
+++ b/arch/x86/kvm/vmx/vmcs12.c
@@ -66,6 +66,7 @@ static const u16 kvm_supported_vmcs12_field_offsets[] 
__initconst = {
        FIELD64(HOST_IA32_PAT, host_ia32_pat),
        FIELD64(HOST_IA32_EFER, host_ia32_efer),
        FIELD64(HOST_IA32_PERF_GLOBAL_CTRL, host_ia32_perf_global_ctrl),
+       FIELD64(SECONDARY_VM_EXIT_CONTROLS, secondary_vm_exit_controls),
        FIELD(PIN_BASED_VM_EXEC_CONTROL, pin_based_vm_exec_control),
        FIELD(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control),
        FIELD(EXCEPTION_BITMAP, exception_bitmap),
diff --git a/arch/x86/kvm/vmx/vmcs12.h b/arch/x86/kvm/vmx/vmcs12.h
index 21cd1b75e4fd..bb2f406be63d 100644
--- a/arch/x86/kvm/vmx/vmcs12.h
+++ b/arch/x86/kvm/vmx/vmcs12.h
@@ -71,7 +71,7 @@ struct __packed vmcs12 {
        u64 pml_address;
        u64 encls_exiting_bitmap;
        u64 tsc_multiplier;
-       u64 padding64[1]; /* room for future expansion */
+       u64 secondary_vm_exit_controls;
        /*
         * To allow migration of L1 (complete with its L2 guests) between
         * machines of different natural widths (32 or 64 bit), we cannot have
@@ -261,6 +261,7 @@ static inline void vmx_check_vmcs12_offsets(void)
        CHECK_OFFSET(pml_address, 312);
        CHECK_OFFSET(encls_exiting_bitmap, 320);
        CHECK_OFFSET(tsc_multiplier, 328);
+       CHECK_OFFSET(secondary_vm_exit_controls, 336);
        CHECK_OFFSET(cr0_guest_host_mask, 344);
        CHECK_OFFSET(cr4_guest_host_mask, 352);
        CHECK_OFFSET(cr0_read_shadow, 360);
-- 
2.43.0


Reply via email to