diff --git a/hypervisor/arch/x86/guest/vcpu.c b/hypervisor/arch/x86/guest/vcpu.c index 7214a7608..ac67ed1c0 100644 --- a/hypervisor/arch/x86/guest/vcpu.c +++ b/hypervisor/arch/x86/guest/vcpu.c @@ -601,7 +601,7 @@ void reset_vcpu(struct acrn_vcpu *vcpu) vcpu->arch.cur_context = NORMAL_WORLD; vlapic = vcpu_vlapic(vcpu); - vlapic_reset(vlapic); + vlapic_reset(vlapic, apicv_ops); reset_vcpu_regs(vcpu); } diff --git a/hypervisor/arch/x86/guest/vlapic.c b/hypervisor/arch/x86/guest/vlapic.c index 97d61c47d..c82e67e04 100644 --- a/hypervisor/arch/x86/guest/vlapic.c +++ b/hypervisor/arch/x86/guest/vlapic.c @@ -88,7 +88,7 @@ static inline void vlapic_dump_irr(__unused const struct acrn_vlapic *vlapic, __ static inline void vlapic_dump_isr(__unused const struct acrn_vlapic *vlapic, __unused const char *msg) {} #endif -static const struct acrn_apicv_ops *apicv_ops; +const struct acrn_apicv_ops *apicv_ops; static int32_t apicv_set_intr_ready(struct acrn_vlapic *vlapic, uint32_t vector); @@ -565,7 +565,7 @@ static void vlapic_accept_intr(struct acrn_vlapic *vlapic, uint32_t vector, bool if ((lapic->svr.v & APIC_SVR_ENABLE) == 0U) { dev_dbg(ACRN_DBG_LAPIC, "vlapic is software disabled, ignoring interrupt %u", vector); } else { - apicv_ops->accept_intr(vlapic, vector, level); + vlapic->ops->accept_intr(vlapic, vector, level); } } @@ -1609,8 +1609,11 @@ static int32_t vlapic_write(struct acrn_vlapic *vlapic, uint32_t offset, uint64_ return ret; } +/* + * @pre vlapic != NULL && ops != NULL + */ void -vlapic_reset(struct acrn_vlapic *vlapic) +vlapic_reset(struct acrn_vlapic *vlapic, const struct acrn_apicv_ops *ops) { uint32_t i; struct lapic_regs *lapic; @@ -1648,6 +1651,8 @@ vlapic_reset(struct acrn_vlapic *vlapic) } vlapic->isrv = 0U; + + vlapic->ops = ops; } /** @@ -1659,7 +1664,7 @@ vlapic_init(struct acrn_vlapic *vlapic) { vlapic_init_timer(vlapic); - vlapic_reset(vlapic); + vlapic_reset(vlapic, apicv_ops); } void vlapic_restore(struct acrn_vlapic *vlapic, const struct lapic_regs *regs) @@ -2056,7 +2061,7 @@ int32_t vlapic_x2apic_read(struct acrn_vcpu *vcpu, uint32_t msr, uint64_t *val) } } else { offset = x2apic_msr_to_regoff(msr); - if (apicv_ops->x2apic_read_msr_may_valid(offset)) { + if (vlapic->ops->x2apic_read_msr_may_valid(offset)) { error = vlapic_read(vlapic, offset, val); } } @@ -2088,7 +2093,7 @@ int32_t vlapic_x2apic_write(struct acrn_vcpu *vcpu, uint32_t msr, uint64_t val) } } else { offset = x2apic_msr_to_regoff(msr); - if (apicv_ops->x2apic_write_msr_may_valid(offset)) { + if (vlapic->ops->x2apic_write_msr_may_valid(offset)) { error = vlapic_write(vlapic, offset, val); } } @@ -2280,7 +2285,7 @@ static bool apicv_advanced_inject_intr(struct acrn_vlapic *vlapic, bool vlapic_inject_intr(struct acrn_vlapic *vlapic, bool guest_irq_enabled, bool injected) { - return apicv_ops->inject_intr(vlapic, guest_irq_enabled, injected); + return vlapic->ops->inject_intr(vlapic, guest_irq_enabled, injected); } static bool apicv_basic_has_pending_delivery_intr(struct acrn_vcpu *vcpu) @@ -2306,7 +2311,8 @@ static bool apicv_advanced_has_pending_delivery_intr(__unused struct acrn_vcpu * bool vlapic_has_pending_delivery_intr(struct acrn_vcpu *vcpu) { - return apicv_ops->has_pending_delivery_intr(vcpu); + struct acrn_vlapic *vlapic = vcpu_vlapic(vcpu); + return vlapic->ops->has_pending_delivery_intr(vcpu); } static bool apicv_basic_apic_read_access_may_valid(__unused uint32_t offset) @@ -2363,12 +2369,12 @@ int32_t apic_access_vmexit_handler(struct acrn_vcpu *vcpu) if (access_type == TYPE_LINEAR_APIC_INST_WRITE) { err = emulate_instruction(vcpu); if (err == 0) { - if (apicv_ops->apic_write_access_may_valid(offset)) { + if (vlapic->ops->apic_write_access_may_valid(offset)) { (void)vlapic_write(vlapic, offset, mmio->value); } } } else { - if (apicv_ops->apic_read_access_may_valid(offset)) { + if (vlapic->ops->apic_read_access_may_valid(offset)) { (void)vlapic_read(vlapic, offset, &mmio->value); } else { mmio->value = 0UL; diff --git a/hypervisor/arch/x86/guest/vlapic_priv.h b/hypervisor/arch/x86/guest/vlapic_priv.h index ef585b585..9a233eec6 100644 --- a/hypervisor/arch/x86/guest/vlapic_priv.h +++ b/hypervisor/arch/x86/guest/vlapic_priv.h @@ -82,14 +82,4 @@ #define APIC_OFFSET_TIMER_DCR 0x3E0U /* Timer's Divide Configuration */ #define APIC_OFFSET_SELF_IPI 0x3F0U /* Self IPI Register */ -struct acrn_apicv_ops { - void (*accept_intr)(struct acrn_vlapic *vlapic, uint32_t vector, bool level); - bool (*inject_intr)(struct acrn_vlapic *vlapic, bool guest_irq_enabled, bool injected); - bool (*has_pending_delivery_intr)(struct acrn_vcpu *vcpu); - bool (*apic_read_access_may_valid)(uint32_t offset); - bool (*apic_write_access_may_valid)(uint32_t offset); - bool (*x2apic_read_msr_may_valid)(uint32_t offset); - bool (*x2apic_write_msr_may_valid)(uint32_t offset); -}; - #endif /* VLAPIC_PRIV_H */ diff --git a/hypervisor/include/arch/x86/guest/vlapic.h b/hypervisor/include/arch/x86/guest/vlapic.h index d3a7e1973..8933e7522 100644 --- a/hypervisor/include/arch/x86/guest/vlapic.h +++ b/hypervisor/include/arch/x86/guest/vlapic.h @@ -34,7 +34,6 @@ #include #include - /** * @file vlapic.h * @@ -85,6 +84,8 @@ struct acrn_vlapic { uint64_t msr_apicbase; + const struct acrn_apicv_ops *ops; + /* * Copies of some registers in the virtual APIC page. We do this for * a couple of different reasons: @@ -95,6 +96,17 @@ struct acrn_vlapic { uint32_t lvt_last[VLAPIC_MAXLVT_INDEX + 1]; } __aligned(PAGE_SIZE); +struct acrn_apicv_ops { + void (*accept_intr)(struct acrn_vlapic *vlapic, uint32_t vector, bool level); + bool (*inject_intr)(struct acrn_vlapic *vlapic, bool guest_irq_enabled, bool injected); + bool (*has_pending_delivery_intr)(struct acrn_vcpu *vcpu); + bool (*apic_read_access_may_valid)(uint32_t offset); + bool (*apic_write_access_may_valid)(uint32_t offset); + bool (*x2apic_read_msr_may_valid)(uint32_t offset); + bool (*x2apic_write_msr_may_valid)(uint32_t offset); +}; + +extern const struct acrn_apicv_ops *apicv_ops; void vlapic_set_apicv_ops(void); /** @@ -182,7 +194,7 @@ void vlapic_free(struct acrn_vcpu *vcpu); * @pre vlapic->vcpu->vcpu_id < CONFIG_MAX_VCPUS_PER_VM */ void vlapic_init(struct acrn_vlapic *vlapic); -void vlapic_reset(struct acrn_vlapic *vlapic); +void vlapic_reset(struct acrn_vlapic *vlapic, const struct acrn_apicv_ops *ops); void vlapic_restore(struct acrn_vlapic *vlapic, const struct lapic_regs *regs); uint64_t vlapic_apicv_get_apic_access_addr(void); uint64_t vlapic_apicv_get_apic_page_addr(struct acrn_vlapic *vlapic);