Skip to content
Permalink
Browse files

hv: vlapic: fix tpr virtualization when VID is not enabled.

1) According SDM Vol 3, Chap 29.1.2, Any VM exit caused by TPR virtualization
is trap-like: the instruction causing TPR virtualization completes before the VM
exit occurs (for example, the value of CS:RIP saved in the guest-state area of
the VMCS references the next instruction). So we need to retain the RIP.
2) The previous implement only consides the situation the guest will reduce the
TPR. However, the guest will increase it. So we need to update the PPR before we
find a deliverable interrupt. For examples: a) if the guest increase the TPR before
a irq windows vmexit, we need to update the PPR when check whether there has a pending
delivery interrupt or not; b) if the guest increase the TPR, then an external irq raised,
we need to update the PPR when check whether there has a deliverable interrupt to inject
to guest.

Tracked-On: #1842
Signed-off-by: Li, Fei1 <fei1.li@intel.com>
Reviewed-by: Yu Wang <yu1.wang@intel.com>
Reviewed-by: Jason Chen CJ <jason.cj.chen@intel.com>
Acked-by: Anthony Xu <anthony.xu@intel.com>
  • Loading branch information...
lifeix authored and wenlingz committed May 9, 2019
1 parent a68dadb commit 86f5993bc9aac58bb3fa504296d95fad8d4f7f27
Showing with 4 additions and 9 deletions.
  1. +4 −9 hypervisor/arch/x86/guest/vlapic.c
@@ -2212,6 +2212,7 @@ static bool apicv_basic_inject_intr(struct acrn_vlapic *vlapic,
uint32_t vector = 0U;
bool ret = injected;
if (guest_irq_enabled && (!injected)) {
vlapic_update_ppr(vlapic);
if (vlapic_find_deliverable_intr(vlapic, &vector)) {
exec_vmwrite32(VMX_ENTRY_INT_INFO_FIELD, VMX_INT_INFO_VALID | vector);
vlapic_get_deliverable_intr(vlapic, vector);
@@ -2321,6 +2322,8 @@ static bool apicv_basic_has_pending_delivery_intr(struct acrn_vcpu *vcpu)
uint32_t vector;
struct acrn_vlapic *vlapic = vcpu_vlapic(vcpu);

vlapic_update_ppr(vlapic);

/* check and raise request if we have a deliverable irq in LAPIC IRR */
if (vlapic_find_deliverable_intr(vlapic, &vector)) {
/* we have pending IRR */
@@ -2535,16 +2538,8 @@ void vlapic_update_tpr_threshold(const struct acrn_vlapic *vlapic)

int32_t tpr_below_threshold_vmexit_handler(struct acrn_vcpu *vcpu)
{
struct acrn_vlapic *vlapic = vcpu_vlapic(vcpu);

vlapic_update_ppr(vlapic);
/*
* Once we come here, the vTPR must small than IRR.
* set TPR threshold to 0 to bypass VM-Execution Control Fields check
* since vcpu_inject_vlapic_int will update TPR threshold aright.
*/
exec_vmwrite32(VMX_TPR_THRESHOLD, 0U);
vcpu_make_request(vcpu, ACRN_REQUEST_EVENT);
vcpu_retain_rip(vcpu);

return 0;
}

0 comments on commit 86f5993

Please sign in to comment.
You can’t perform that action at this time.