From 702a71639fa2d6b5a56423762d1078ce0923b854 Mon Sep 17 00:00:00 2001 From: Yifan Liu Date: Thu, 2 Dec 2021 09:18:03 +0000 Subject: [PATCH] hv: Add two vlapic APIs Sometimes HV would like to know if there are specific interrupt pending in vIRR, and clears them if necessary (such as in x86_tee case). This patch adds two APIs: get_next_pending_intr and clear_pending_intr. This patch also moves the inline api prio() from vlapic.c to vlapic.h v3: Remove apicv_get_next_pending_intr and apicv_clear_pending_intr and use vlapic_get_next_pending_intr and vlapic_clear_pending_intr directly. v2: get_pending_intr -> get_next_pending_intr apicv_basic/advanced_clear_pending_intr -> apicv_clear_pending_intr apicv_basic/advanced_get_pending_intr -> apicv_get_next_pending_intr has_pending_intr kept Tracked-On: #6571 Signed-off-by: Yifan Liu Reviewed-by: Wang, Yu1 Acked-by: Anthony Xu --- hypervisor/arch/x86/guest/vlapic.c | 21 ++++++++++++------- .../include/arch/x86/asm/guest/vlapic.h | 17 +++++++++++++++ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/hypervisor/arch/x86/guest/vlapic.c b/hypervisor/arch/x86/guest/vlapic.c index 9d762b4f0..eb23f55ba 100644 --- a/hypervisor/arch/x86/guest/vlapic.c +++ b/hypervisor/arch/x86/guest/vlapic.c @@ -51,11 +51,6 @@ #define VLAPIC_VERBOS 0 -static inline uint32_t prio(uint32_t x) -{ - return (x >> 4U); -} - #define VLAPIC_VERSION (16U) #define APICBASE_BSP 0x00000100UL #define APICBASE_X2APIC 0x00000400UL @@ -2342,14 +2337,19 @@ bool vlapic_has_pending_delivery_intr(struct acrn_vcpu *vcpu) return vlapic->ops->has_pending_delivery_intr(vcpu); } -static bool apicv_basic_has_pending_intr(struct acrn_vcpu *vcpu) +uint32_t vlapic_get_next_pending_intr(struct acrn_vcpu *vcpu) { struct acrn_vlapic *vlapic = vcpu_vlapic(vcpu); uint32_t vector; vector = vlapic_find_highest_irr(vlapic); - return vector != 0UL; + return vector; +} + +static bool apicv_basic_has_pending_intr(struct acrn_vcpu *vcpu) +{ + return vlapic_get_next_pending_intr(vcpu) != 0UL; } static bool apicv_advanced_has_pending_intr(struct acrn_vcpu *vcpu) @@ -2357,6 +2357,13 @@ static bool apicv_advanced_has_pending_intr(struct acrn_vcpu *vcpu) return apicv_basic_has_pending_intr(vcpu); } +bool vlapic_clear_pending_intr(struct acrn_vcpu *vcpu, uint32_t vector) +{ + struct lapic_reg *irrptr = &(vcpu->arch.vlapic.apic_page.irr[0]); + uint32_t idx = vector >> 5U; + return bitmap32_test_and_clear_lock((uint16_t)(vector & 0x1fU), &irrptr[idx].v); +} + bool vlapic_has_pending_intr(struct acrn_vcpu *vcpu) { struct acrn_vlapic *vlapic = vcpu_vlapic(vcpu); diff --git a/hypervisor/include/arch/x86/asm/guest/vlapic.h b/hypervisor/include/arch/x86/asm/guest/vlapic.h index 800c4e610..68c85ab15 100644 --- a/hypervisor/include/arch/x86/asm/guest/vlapic.h +++ b/hypervisor/include/arch/x86/asm/guest/vlapic.h @@ -114,6 +114,18 @@ void vlapic_inject_intr(struct acrn_vlapic *vlapic, bool guest_irq_enabled, bool bool vlapic_has_pending_delivery_intr(struct acrn_vcpu *vcpu); bool vlapic_has_pending_intr(struct acrn_vcpu *vcpu); +/** + * Returns the highest priority pending vector on vLAPIC, or + * 0 if there is no pending vector. + */ +uint32_t vlapic_get_next_pending_intr(struct acrn_vcpu *vcpu); + +/** + * Clears a pending vector from vIRR. Returns true if + * the bit was previously present, false otherwise. + */ +bool vlapic_clear_pending_intr(struct acrn_vcpu *vcpu, uint32_t vector); + uint64_t vlapic_get_tsc_deadline_msr(const struct acrn_vlapic *vlapic); void vlapic_set_tsc_deadline_msr(struct acrn_vlapic *vlapic, uint64_t val_arg); uint64_t vlapic_get_apicbase(const struct acrn_vlapic *vlapic); @@ -132,6 +144,11 @@ void vlapic_set_intr(struct acrn_vcpu *vcpu, uint32_t vector, bool level); #define LAPIC_TRIG_LEVEL true #define LAPIC_TRIG_EDGE false +static inline uint32_t prio(uint32_t x) +{ + return (x >> 4U); +} + /** * @brief Triggers LAPIC local interrupt(LVT). *