From f801ba4ed77aaf858d19f52c197db07947f14726 Mon Sep 17 00:00:00 2001 From: Zide Chen Date: Mon, 27 Sep 2021 17:09:31 -0700 Subject: [PATCH] hv: update guest RIP only if vcpu->arch.inst_len is non zero In very large number of VM extis, the VM-exit instruction length could be zero, and it's no need to update VMX_GUEST_RIP. Some examples: - all external interrupt VM exits in non LAPIC passthru setup. - for all the nested VM-exits that are reflecting to L1 hypervisor. Tracked-On: #6289 Signed-off-by: Zide Chen Acked-by: Eddie Dong --- hypervisor/arch/x86/guest/nested.c | 10 ++++++++++ hypervisor/arch/x86/guest/vcpu.c | 10 +++++----- 2 files changed, 15 insertions(+), 5 deletions(-) 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);