Skip to content

Commit ee146c1

Browse files
ladiprobonzini
authored andcommitted
KVM: nVMX: propagate errors from prepare_vmcs02
It is possible that prepare_vmcs02 fails to load the guest state. This patch adds the proper error handling for such a case. L1 will receive an INVALID_STATE vmexit with the appropriate exit qualification if it happens. A failure to set guest CR3 is the only error propagated from prepare_vmcs02 at the moment. Signed-off-by: Ladi Prosek <[email protected]> Signed-off-by: Radim Krčmář <[email protected]>
1 parent 7ca29de commit ee146c1

File tree

1 file changed

+19
-4
lines changed

1 file changed

+19
-4
lines changed

arch/x86/kvm/vmx.c

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9976,8 +9976,11 @@ static int nested_vmx_store_msr(struct kvm_vcpu *vcpu, u64 gpa, u32 count)
99769976
* needs. In addition to modifying the active vmcs (which is vmcs02), this
99779977
* function also has additional necessary side-effects, like setting various
99789978
* vcpu->arch fields.
9979+
* Returns 0 on success, 1 on failure. Invalid state exit qualification code
9980+
* is assigned to entry_failure_code on failure.
99799981
*/
9980-
static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
9982+
static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
9983+
unsigned long *entry_failure_code)
99819984
{
99829985
struct vcpu_vmx *vmx = to_vmx(vcpu);
99839986
u32 exec_control;
@@ -10306,8 +10309,12 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
1030610309
nested_ept_enabled) {
1030710310
vcpu->arch.cr3 = vmcs12->guest_cr3;
1030810311
__set_bit(VCPU_EXREG_CR3, (ulong *)&vcpu->arch.regs_avail);
10309-
} else
10310-
kvm_set_cr3(vcpu, vmcs12->guest_cr3);
10312+
} else {
10313+
if (kvm_set_cr3(vcpu, vmcs12->guest_cr3)) {
10314+
*entry_failure_code = ENTRY_FAIL_DEFAULT;
10315+
return 1;
10316+
}
10317+
}
1031110318

1031210319
kvm_mmu_reset_context(vcpu);
1031310320

@@ -10326,6 +10333,7 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
1032610333

1032710334
kvm_register_write(vcpu, VCPU_REGS_RSP, vmcs12->guest_rsp);
1032810335
kvm_register_write(vcpu, VCPU_REGS_RIP, vmcs12->guest_rip);
10336+
return 0;
1032910337
}
1033010338

1033110339
/*
@@ -10340,6 +10348,7 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
1034010348
struct loaded_vmcs *vmcs02;
1034110349
bool ia32e;
1034210350
u32 msr_entry_idx;
10351+
unsigned long exit_qualification;
1034310352

1034410353
if (!nested_vmx_check_permission(vcpu))
1034510354
return 1;
@@ -10502,7 +10511,13 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
1050210511

1050310512
vmx_segment_cache_clear(vmx);
1050410513

10505-
prepare_vmcs02(vcpu, vmcs12);
10514+
if (prepare_vmcs02(vcpu, vmcs12, &exit_qualification)) {
10515+
leave_guest_mode(vcpu);
10516+
vmx_load_vmcs01(vcpu);
10517+
nested_vmx_entry_failure(vcpu, vmcs12,
10518+
EXIT_REASON_INVALID_STATE, exit_qualification);
10519+
return 1;
10520+
}
1050610521

1050710522
msr_entry_idx = nested_vmx_load_msr(vcpu,
1050810523
vmcs12->vm_entry_msr_load_addr,

0 commit comments

Comments
 (0)