Skip to content

Commit 86f5993

Browse files
lifeixwenlingz
authored andcommitted
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>
1 parent a68dadb commit 86f5993

File tree

1 file changed

+4
-9
lines changed

1 file changed

+4
-9
lines changed

hypervisor/arch/x86/guest/vlapic.c

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2212,6 +2212,7 @@ static bool apicv_basic_inject_intr(struct acrn_vlapic *vlapic,
22122212
uint32_t vector = 0U;
22132213
bool ret = injected;
22142214
if (guest_irq_enabled && (!injected)) {
2215+
vlapic_update_ppr(vlapic);
22152216
if (vlapic_find_deliverable_intr(vlapic, &vector)) {
22162217
exec_vmwrite32(VMX_ENTRY_INT_INFO_FIELD, VMX_INT_INFO_VALID | vector);
22172218
vlapic_get_deliverable_intr(vlapic, vector);
@@ -2321,6 +2322,8 @@ static bool apicv_basic_has_pending_delivery_intr(struct acrn_vcpu *vcpu)
23212322
uint32_t vector;
23222323
struct acrn_vlapic *vlapic = vcpu_vlapic(vcpu);
23232324

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

25362539
int32_t tpr_below_threshold_vmexit_handler(struct acrn_vcpu *vcpu)
25372540
{
2538-
struct acrn_vlapic *vlapic = vcpu_vlapic(vcpu);
2539-
2540-
vlapic_update_ppr(vlapic);
2541-
/*
2542-
* Once we come here, the vTPR must small than IRR.
2543-
* set TPR threshold to 0 to bypass VM-Execution Control Fields check
2544-
* since vcpu_inject_vlapic_int will update TPR threshold aright.
2545-
*/
2546-
exec_vmwrite32(VMX_TPR_THRESHOLD, 0U);
25472541
vcpu_make_request(vcpu, ACRN_REQUEST_EVENT);
2542+
vcpu_retain_rip(vcpu);
25482543

25492544
return 0;
25502545
}

0 commit comments

Comments
 (0)