mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-07-04 11:07:51 +00:00
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>
This commit is contained in:
parent
a68dadb74a
commit
86f5993bc9
@ -2212,6 +2212,7 @@ static bool apicv_basic_inject_intr(struct acrn_vlapic *vlapic,
|
|||||||
uint32_t vector = 0U;
|
uint32_t vector = 0U;
|
||||||
bool ret = injected;
|
bool ret = injected;
|
||||||
if (guest_irq_enabled && (!injected)) {
|
if (guest_irq_enabled && (!injected)) {
|
||||||
|
vlapic_update_ppr(vlapic);
|
||||||
if (vlapic_find_deliverable_intr(vlapic, &vector)) {
|
if (vlapic_find_deliverable_intr(vlapic, &vector)) {
|
||||||
exec_vmwrite32(VMX_ENTRY_INT_INFO_FIELD, VMX_INT_INFO_VALID | vector);
|
exec_vmwrite32(VMX_ENTRY_INT_INFO_FIELD, VMX_INT_INFO_VALID | vector);
|
||||||
vlapic_get_deliverable_intr(vlapic, 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;
|
uint32_t vector;
|
||||||
struct acrn_vlapic *vlapic = vcpu_vlapic(vcpu);
|
struct acrn_vlapic *vlapic = vcpu_vlapic(vcpu);
|
||||||
|
|
||||||
|
vlapic_update_ppr(vlapic);
|
||||||
|
|
||||||
/* check and raise request if we have a deliverable irq in LAPIC IRR */
|
/* check and raise request if we have a deliverable irq in LAPIC IRR */
|
||||||
if (vlapic_find_deliverable_intr(vlapic, &vector)) {
|
if (vlapic_find_deliverable_intr(vlapic, &vector)) {
|
||||||
/* we have pending IRR */
|
/* 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)
|
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_make_request(vcpu, ACRN_REQUEST_EVENT);
|
||||||
|
vcpu_retain_rip(vcpu);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user