diff --git a/hypervisor/arch/x86/guest/nested.c b/hypervisor/arch/x86/guest/nested.c index 1afaf7188..7215469d8 100644 --- a/hypervisor/arch/x86/guest/nested.c +++ b/hypervisor/arch/x86/guest/nested.c @@ -1450,6 +1450,16 @@ int32_t nested_vmexit_handler(struct acrn_vcpu *vcpu) vcpu->arch.nested.in_l2_guest = false; } + /* + * For VM-exits that reflect to L1 hypervisor, ACRN can't advance to next guest RIP + * which is up to the L1 hypervisor to make the decision. + * + * The only case that doesn't need to be reflected is EPT violations that can be + * completely handled by ACRN, which requires L2 VM to re-execute the instruction + * after the shadow EPT is being properly setup. + + * In either case, need to set vcpu->arch.inst_len to zero. + */ vcpu_retain_rip(vcpu); return 0; } diff --git a/hypervisor/arch/x86/guest/vcpu.c b/hypervisor/arch/x86/guest/vcpu.c index 1ae5ef2e6..91cb104f1 100644 --- a/hypervisor/arch/x86/guest/vcpu.c +++ b/hypervisor/arch/x86/guest/vcpu.c @@ -657,8 +657,8 @@ static void write_cached_registers(struct acrn_vcpu *vcpu) */ int32_t run_vcpu(struct acrn_vcpu *vcpu) { - uint32_t instlen, cs_attr; - uint64_t rip, ia32_efer, cr0; + uint32_t cs_attr; + uint64_t ia32_efer, cr0; struct run_context *ctx = &vcpu->arch.contexts[vcpu->arch.cur_context].run_ctx; int32_t status = 0; @@ -718,9 +718,9 @@ int32_t run_vcpu(struct acrn_vcpu *vcpu) /* This VCPU was already launched, check if the last guest * instruction needs to be repeated and resume VCPU accordingly */ - instlen = vcpu->arch.inst_len; - rip = vcpu_get_rip(vcpu); - exec_vmwrite(VMX_GUEST_RIP, rip + instlen); + if (vcpu->arch.inst_len != 0U) { + exec_vmwrite(VMX_GUEST_RIP, vcpu_get_rip(vcpu) + vcpu->arch.inst_len); + } /* Resume the VM */ status = exec_vmentry(ctx, VM_RESUME, ibrs_type);