|
@@ -7558,6 +7558,7 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
|
|
|
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
|
|
int cpu;
|
|
|
struct loaded_vmcs *vmcs02;
|
|
|
+ bool ia32e;
|
|
|
|
|
|
if (!nested_vmx_check_permission(vcpu) ||
|
|
|
!nested_vmx_check_vmcs12(vcpu))
|
|
@@ -7648,6 +7649,45 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
+ /*
|
|
|
+ * If the “load IA32_EFER” VM-entry control is 1, the following checks
|
|
|
+ * are performed on the field for the IA32_EFER MSR:
|
|
|
+ * - Bits reserved in the IA32_EFER MSR must be 0.
|
|
|
+ * - Bit 10 (corresponding to IA32_EFER.LMA) must equal the value of
|
|
|
+ * the IA-32e mode guest VM-exit control. It must also be identical
|
|
|
+ * to bit 8 (LME) if bit 31 in the CR0 field (corresponding to
|
|
|
+ * CR0.PG) is 1.
|
|
|
+ */
|
|
|
+ if (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_EFER) {
|
|
|
+ ia32e = (vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE) != 0;
|
|
|
+ if (!kvm_valid_efer(vcpu, vmcs12->guest_ia32_efer) ||
|
|
|
+ ia32e != !!(vmcs12->guest_ia32_efer & EFER_LMA) ||
|
|
|
+ ((vmcs12->guest_cr0 & X86_CR0_PG) &&
|
|
|
+ ia32e != !!(vmcs12->guest_ia32_efer & EFER_LME))) {
|
|
|
+ nested_vmx_entry_failure(vcpu, vmcs12,
|
|
|
+ EXIT_REASON_INVALID_STATE, ENTRY_FAIL_DEFAULT);
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * If the load IA32_EFER VM-exit control is 1, bits reserved in the
|
|
|
+ * IA32_EFER MSR must be 0 in the field for that register. In addition,
|
|
|
+ * the values of the LMA and LME bits in the field must each be that of
|
|
|
+ * the host address-space size VM-exit control.
|
|
|
+ */
|
|
|
+ if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_EFER) {
|
|
|
+ ia32e = (vmcs12->vm_exit_controls &
|
|
|
+ VM_EXIT_HOST_ADDR_SPACE_SIZE) != 0;
|
|
|
+ if (!kvm_valid_efer(vcpu, vmcs12->host_ia32_efer) ||
|
|
|
+ ia32e != !!(vmcs12->host_ia32_efer & EFER_LMA) ||
|
|
|
+ ia32e != !!(vmcs12->host_ia32_efer & EFER_LME)) {
|
|
|
+ nested_vmx_entry_failure(vcpu, vmcs12,
|
|
|
+ EXIT_REASON_INVALID_STATE, ENTRY_FAIL_DEFAULT);
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/*
|
|
|
* We're finally done with prerequisite checking, and can start with
|
|
|
* the nested entry.
|