|
@@ -10035,7 +10035,7 @@ static bool nested_cr3_valid(struct kvm_vcpu *vcpu, unsigned long val)
|
|
* is assigned to entry_failure_code on failure.
|
|
* is assigned to entry_failure_code on failure.
|
|
*/
|
|
*/
|
|
static int nested_vmx_load_cr3(struct kvm_vcpu *vcpu, unsigned long cr3, bool nested_ept,
|
|
static int nested_vmx_load_cr3(struct kvm_vcpu *vcpu, unsigned long cr3, bool nested_ept,
|
|
- unsigned long *entry_failure_code)
|
|
|
|
|
|
+ u32 *entry_failure_code)
|
|
{
|
|
{
|
|
if (cr3 != kvm_read_cr3(vcpu) || (!nested_ept && pdptrs_changed(vcpu))) {
|
|
if (cr3 != kvm_read_cr3(vcpu) || (!nested_ept && pdptrs_changed(vcpu))) {
|
|
if (!nested_cr3_valid(vcpu, cr3)) {
|
|
if (!nested_cr3_valid(vcpu, cr3)) {
|
|
@@ -10075,7 +10075,7 @@ static int nested_vmx_load_cr3(struct kvm_vcpu *vcpu, unsigned long cr3, bool ne
|
|
* is assigned to entry_failure_code on failure.
|
|
* is assigned to entry_failure_code on failure.
|
|
*/
|
|
*/
|
|
static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
|
|
static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
|
|
- bool from_vmentry, unsigned long *entry_failure_code)
|
|
|
|
|
|
+ bool from_vmentry, u32 *entry_failure_code)
|
|
{
|
|
{
|
|
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
|
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
|
u32 exec_control;
|
|
u32 exec_control;
|
|
@@ -10411,68 +10411,22 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-/*
|
|
|
|
- * nested_vmx_run() handles a nested entry, i.e., a VMLAUNCH or VMRESUME on L1
|
|
|
|
- * for running an L2 nested guest.
|
|
|
|
- */
|
|
|
|
-static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
|
|
|
|
|
|
+static int check_vmentry_prereqs(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
|
|
{
|
|
{
|
|
- struct vmcs12 *vmcs12;
|
|
|
|
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
|
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
|
- int cpu;
|
|
|
|
- struct loaded_vmcs *vmcs02;
|
|
|
|
- bool ia32e;
|
|
|
|
- u32 msr_entry_idx;
|
|
|
|
- unsigned long exit_qualification;
|
|
|
|
-
|
|
|
|
- if (!nested_vmx_check_permission(vcpu))
|
|
|
|
- return 1;
|
|
|
|
-
|
|
|
|
- if (!nested_vmx_check_vmcs12(vcpu))
|
|
|
|
- goto out;
|
|
|
|
-
|
|
|
|
- vmcs12 = get_vmcs12(vcpu);
|
|
|
|
-
|
|
|
|
- if (enable_shadow_vmcs)
|
|
|
|
- copy_shadow_to_vmcs12(vmx);
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * The nested entry process starts with enforcing various prerequisites
|
|
|
|
- * on vmcs12 as required by the Intel SDM, and act appropriately when
|
|
|
|
- * they fail: As the SDM explains, some conditions should cause the
|
|
|
|
- * instruction to fail, while others will cause the instruction to seem
|
|
|
|
- * to succeed, but return an EXIT_REASON_INVALID_STATE.
|
|
|
|
- * To speed up the normal (success) code path, we should avoid checking
|
|
|
|
- * for misconfigurations which will anyway be caught by the processor
|
|
|
|
- * when using the merged vmcs02.
|
|
|
|
- */
|
|
|
|
- if (vmcs12->launch_state == launch) {
|
|
|
|
- nested_vmx_failValid(vcpu,
|
|
|
|
- launch ? VMXERR_VMLAUNCH_NONCLEAR_VMCS
|
|
|
|
- : VMXERR_VMRESUME_NONLAUNCHED_VMCS);
|
|
|
|
- goto out;
|
|
|
|
- }
|
|
|
|
|
|
|
|
if (vmcs12->guest_activity_state != GUEST_ACTIVITY_ACTIVE &&
|
|
if (vmcs12->guest_activity_state != GUEST_ACTIVITY_ACTIVE &&
|
|
- vmcs12->guest_activity_state != GUEST_ACTIVITY_HLT) {
|
|
|
|
- nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
|
|
|
|
- goto out;
|
|
|
|
- }
|
|
|
|
|
|
+ vmcs12->guest_activity_state != GUEST_ACTIVITY_HLT)
|
|
|
|
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
|
|
|
|
|
|
- if (nested_vmx_check_msr_bitmap_controls(vcpu, vmcs12)) {
|
|
|
|
- nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
|
|
|
|
- goto out;
|
|
|
|
- }
|
|
|
|
|
|
+ if (nested_vmx_check_msr_bitmap_controls(vcpu, vmcs12))
|
|
|
|
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
|
|
|
|
|
|
- if (nested_vmx_check_apicv_controls(vcpu, vmcs12)) {
|
|
|
|
- nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
|
|
|
|
- goto out;
|
|
|
|
- }
|
|
|
|
|
|
+ if (nested_vmx_check_apicv_controls(vcpu, vmcs12))
|
|
|
|
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
|
|
|
|
|
|
- if (nested_vmx_check_msr_switch_controls(vcpu, vmcs12)) {
|
|
|
|
- nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
|
|
|
|
- goto out;
|
|
|
|
- }
|
|
|
|
|
|
+ if (nested_vmx_check_msr_switch_controls(vcpu, vmcs12))
|
|
|
|
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
|
|
|
|
|
|
if (!vmx_control_verify(vmcs12->cpu_based_vm_exec_control,
|
|
if (!vmx_control_verify(vmcs12->cpu_based_vm_exec_control,
|
|
vmx->nested.nested_vmx_procbased_ctls_low,
|
|
vmx->nested.nested_vmx_procbased_ctls_low,
|
|
@@ -10489,28 +10443,30 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
|
|
!vmx_control_verify(vmcs12->vm_entry_controls,
|
|
!vmx_control_verify(vmcs12->vm_entry_controls,
|
|
vmx->nested.nested_vmx_entry_ctls_low,
|
|
vmx->nested.nested_vmx_entry_ctls_low,
|
|
vmx->nested.nested_vmx_entry_ctls_high))
|
|
vmx->nested.nested_vmx_entry_ctls_high))
|
|
- {
|
|
|
|
- nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
|
|
|
|
- goto out;
|
|
|
|
- }
|
|
|
|
|
|
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
|
|
|
|
|
|
if (!nested_host_cr0_valid(vcpu, vmcs12->host_cr0) ||
|
|
if (!nested_host_cr0_valid(vcpu, vmcs12->host_cr0) ||
|
|
!nested_host_cr4_valid(vcpu, vmcs12->host_cr4) ||
|
|
!nested_host_cr4_valid(vcpu, vmcs12->host_cr4) ||
|
|
- !nested_cr3_valid(vcpu, vmcs12->host_cr3)) {
|
|
|
|
- nested_vmx_failValid(vcpu,
|
|
|
|
- VMXERR_ENTRY_INVALID_HOST_STATE_FIELD);
|
|
|
|
- goto out;
|
|
|
|
- }
|
|
|
|
|
|
+ !nested_cr3_valid(vcpu, vmcs12->host_cr3))
|
|
|
|
+ return VMXERR_ENTRY_INVALID_HOST_STATE_FIELD;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int check_vmentry_postreqs(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
|
|
|
|
+ u32 *exit_qual)
|
|
|
|
+{
|
|
|
|
+ bool ia32e;
|
|
|
|
+
|
|
|
|
+ *exit_qual = ENTRY_FAIL_DEFAULT;
|
|
|
|
|
|
if (!nested_guest_cr0_valid(vcpu, vmcs12->guest_cr0) ||
|
|
if (!nested_guest_cr0_valid(vcpu, vmcs12->guest_cr0) ||
|
|
- !nested_guest_cr4_valid(vcpu, vmcs12->guest_cr4)) {
|
|
|
|
- nested_vmx_entry_failure(vcpu, vmcs12,
|
|
|
|
- EXIT_REASON_INVALID_STATE, ENTRY_FAIL_DEFAULT);
|
|
|
|
|
|
+ !nested_guest_cr4_valid(vcpu, vmcs12->guest_cr4))
|
|
return 1;
|
|
return 1;
|
|
- }
|
|
|
|
- if (vmcs12->vmcs_link_pointer != -1ull) {
|
|
|
|
- nested_vmx_entry_failure(vcpu, vmcs12,
|
|
|
|
- EXIT_REASON_INVALID_STATE, ENTRY_FAIL_VMCS_LINK_PTR);
|
|
|
|
|
|
+
|
|
|
|
+ if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_SHADOW_VMCS) &&
|
|
|
|
+ vmcs12->vmcs_link_pointer != -1ull) {
|
|
|
|
+ *exit_qual = ENTRY_FAIL_VMCS_LINK_PTR;
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -10523,16 +10479,14 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
|
|
* to bit 8 (LME) if bit 31 in the CR0 field (corresponding to
|
|
* to bit 8 (LME) if bit 31 in the CR0 field (corresponding to
|
|
* CR0.PG) is 1.
|
|
* CR0.PG) is 1.
|
|
*/
|
|
*/
|
|
- if (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_EFER) {
|
|
|
|
|
|
+ if (to_vmx(vcpu)->nested.nested_run_pending &&
|
|
|
|
+ (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_EFER)) {
|
|
ia32e = (vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE) != 0;
|
|
ia32e = (vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE) != 0;
|
|
if (!kvm_valid_efer(vcpu, vmcs12->guest_ia32_efer) ||
|
|
if (!kvm_valid_efer(vcpu, vmcs12->guest_ia32_efer) ||
|
|
ia32e != !!(vmcs12->guest_ia32_efer & EFER_LMA) ||
|
|
ia32e != !!(vmcs12->guest_ia32_efer & EFER_LMA) ||
|
|
((vmcs12->guest_cr0 & X86_CR0_PG) &&
|
|
((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);
|
|
|
|
|
|
+ ia32e != !!(vmcs12->guest_ia32_efer & EFER_LME)))
|
|
return 1;
|
|
return 1;
|
|
- }
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -10546,11 +10500,75 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
|
|
VM_EXIT_HOST_ADDR_SPACE_SIZE) != 0;
|
|
VM_EXIT_HOST_ADDR_SPACE_SIZE) != 0;
|
|
if (!kvm_valid_efer(vcpu, vmcs12->host_ia32_efer) ||
|
|
if (!kvm_valid_efer(vcpu, vmcs12->host_ia32_efer) ||
|
|
ia32e != !!(vmcs12->host_ia32_efer & EFER_LMA) ||
|
|
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);
|
|
|
|
|
|
+ ia32e != !!(vmcs12->host_ia32_efer & EFER_LME))
|
|
return 1;
|
|
return 1;
|
|
- }
|
|
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * nested_vmx_run() handles a nested entry, i.e., a VMLAUNCH or VMRESUME on L1
|
|
|
|
+ * for running an L2 nested guest.
|
|
|
|
+ */
|
|
|
|
+static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
|
|
|
|
+{
|
|
|
|
+ struct vmcs12 *vmcs12;
|
|
|
|
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
|
|
|
|
+ int cpu;
|
|
|
|
+ struct loaded_vmcs *vmcs02;
|
|
|
|
+ u32 msr_entry_idx;
|
|
|
|
+ u32 exit_qual;
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ if (!nested_vmx_check_permission(vcpu))
|
|
|
|
+ return 1;
|
|
|
|
+
|
|
|
|
+ if (!nested_vmx_check_vmcs12(vcpu))
|
|
|
|
+ goto out;
|
|
|
|
+
|
|
|
|
+ vmcs12 = get_vmcs12(vcpu);
|
|
|
|
+
|
|
|
|
+ if (enable_shadow_vmcs)
|
|
|
|
+ copy_shadow_to_vmcs12(vmx);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * The nested entry process starts with enforcing various prerequisites
|
|
|
|
+ * on vmcs12 as required by the Intel SDM, and act appropriately when
|
|
|
|
+ * they fail: As the SDM explains, some conditions should cause the
|
|
|
|
+ * instruction to fail, while others will cause the instruction to seem
|
|
|
|
+ * to succeed, but return an EXIT_REASON_INVALID_STATE.
|
|
|
|
+ * To speed up the normal (success) code path, we should avoid checking
|
|
|
|
+ * for misconfigurations which will anyway be caught by the processor
|
|
|
|
+ * when using the merged vmcs02.
|
|
|
|
+ */
|
|
|
|
+ if (vmcs12->launch_state == launch) {
|
|
|
|
+ nested_vmx_failValid(vcpu,
|
|
|
|
+ launch ? VMXERR_VMLAUNCH_NONCLEAR_VMCS
|
|
|
|
+ : VMXERR_VMRESUME_NONLAUNCHED_VMCS);
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ret = check_vmentry_prereqs(vcpu, vmcs12);
|
|
|
|
+ if (ret) {
|
|
|
|
+ nested_vmx_failValid(vcpu, ret);
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * After this point, the trap flag no longer triggers a singlestep trap
|
|
|
|
+ * on the vm entry instructions; don't call kvm_skip_emulated_instruction.
|
|
|
|
+ * This is not 100% correct; for performance reasons, we delegate most
|
|
|
|
+ * of the checks on host state to the processor. If those fail,
|
|
|
|
+ * the singlestep trap is missed.
|
|
|
|
+ */
|
|
|
|
+ skip_emulated_instruction(vcpu);
|
|
|
|
+
|
|
|
|
+ ret = check_vmentry_postreqs(vcpu, vmcs12, &exit_qual);
|
|
|
|
+ if (ret) {
|
|
|
|
+ nested_vmx_entry_failure(vcpu, vmcs12,
|
|
|
|
+ EXIT_REASON_INVALID_STATE, exit_qual);
|
|
|
|
+ return 1;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -10562,12 +10580,6 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
|
|
if (!vmcs02)
|
|
if (!vmcs02)
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
|
|
|
|
- /*
|
|
|
|
- * After this point, the trap flag no longer triggers a singlestep trap
|
|
|
|
- * on the vm entry instructions. Don't call
|
|
|
|
- * kvm_skip_emulated_instruction.
|
|
|
|
- */
|
|
|
|
- skip_emulated_instruction(vcpu);
|
|
|
|
enter_guest_mode(vcpu);
|
|
enter_guest_mode(vcpu);
|
|
|
|
|
|
if (!(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS))
|
|
if (!(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS))
|
|
@@ -10582,11 +10594,11 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
|
|
|
|
|
|
vmx_segment_cache_clear(vmx);
|
|
vmx_segment_cache_clear(vmx);
|
|
|
|
|
|
- if (prepare_vmcs02(vcpu, vmcs12, true, &exit_qualification)) {
|
|
|
|
|
|
+ if (prepare_vmcs02(vcpu, vmcs12, true, &exit_qual)) {
|
|
leave_guest_mode(vcpu);
|
|
leave_guest_mode(vcpu);
|
|
vmx_load_vmcs01(vcpu);
|
|
vmx_load_vmcs01(vcpu);
|
|
nested_vmx_entry_failure(vcpu, vmcs12,
|
|
nested_vmx_entry_failure(vcpu, vmcs12,
|
|
- EXIT_REASON_INVALID_STATE, exit_qualification);
|
|
|
|
|
|
+ EXIT_REASON_INVALID_STATE, exit_qual);
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -10937,7 +10949,7 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
|
|
struct vmcs12 *vmcs12)
|
|
struct vmcs12 *vmcs12)
|
|
{
|
|
{
|
|
struct kvm_segment seg;
|
|
struct kvm_segment seg;
|
|
- unsigned long entry_failure_code;
|
|
|
|
|
|
+ u32 entry_failure_code;
|
|
|
|
|
|
if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_EFER)
|
|
if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_EFER)
|
|
vcpu->arch.efer = vmcs12->host_ia32_efer;
|
|
vcpu->arch.efer = vmcs12->host_ia32_efer;
|