hv: vlapic: kick targeted vCPU off if interrupt trigger mode has changed

In APICv advanced mode, an targeted vCPU, running in non-root mode, may get outdated
TMR and EOI exit bitmap if another vCPU sends an interrupt to it if the trigger mode
of this interrupt has changed.
This patch try to kick vCPU off to let it get the latest TMR and EOI exit bitmap when
it enters non-root mode again if new coming interrupt trigger mode has changed. Then
fill the interrupt to PIR.

Tracked-On: #4200
Signed-off-by: Li Fei1 <fei1.li@intel.com>
This commit is contained in:
Li Fei1 2019-12-05 23:18:32 +08:00 committed by wenlingz
parent ed65ae61c6
commit c2c05a29da
1 changed files with 10 additions and 14 deletions

View File

@ -90,7 +90,7 @@ static inline void vlapic_dump_isr(__unused const struct acrn_vlapic *vlapic, __
const struct acrn_apicv_ops *apicv_ops;
static int32_t
static bool
apicv_set_intr_ready(struct acrn_vlapic *vlapic, uint32_t vector);
static void apicv_post_intr(uint16_t dest_pcpu_id);
@ -507,11 +507,7 @@ vlapic_esr_write_handler(struct acrn_vlapic *vlapic)
static void
vlapic_set_tmr(struct acrn_vlapic *vlapic, uint32_t vector, bool level)
{
struct lapic_regs *lapic;
struct lapic_reg *tmrptr;
lapic = &(vlapic->apic_page);
tmrptr = &lapic->tmr[0];
struct lapic_reg *tmrptr = &(vlapic->apic_page.tmr[0]);
if (level) {
if (!bitmap32_test_and_set_lock((uint16_t)(vector & 0x1fU), &tmrptr[(vector & 0xffU) >> 5U].v)) {
vcpu_set_eoi_exit_bitmap(vlapic->vcpu, vector);
@ -552,7 +548,7 @@ static void apicv_basic_accept_intr(struct acrn_vlapic *vlapic, uint32_t vector,
/* If the interrupt is set, don't try to do it again */
if (!bitmap32_test_and_set_lock((uint16_t)(vector & 0x1fU), &irrptr[idx].v)) {
/* set tmr if corresponding irr bit changes from 0 to 1 */
/* update TMR if interrupt trigger mode has changed */
vlapic_set_tmr(vlapic, vector, level);
vcpu_make_request(vlapic->vcpu, ACRN_REQUEST_EVENT);
}
@ -560,11 +556,10 @@ static void apicv_basic_accept_intr(struct acrn_vlapic *vlapic, uint32_t vector,
static void apicv_advanced_accept_intr(struct acrn_vlapic *vlapic, uint32_t vector, bool level)
{
int32_t pending_intr = apicv_set_intr_ready(vlapic, vector);
/* update TMR if interrupt trigger mode has changed */
vlapic_set_tmr(vlapic, vector, level);
if (pending_intr != 0) {
if (apicv_set_intr_ready(vlapic, vector)) {
/*
* Send interrupt to vCPU via posted interrupt way:
* 1. If target vCPU is in root mode(isn't running),
@ -2208,19 +2203,20 @@ void vlapic_free(struct acrn_vcpu *vcpu)
/**
* APIC-v functions
* **/
static int32_t
static bool
apicv_set_intr_ready(struct acrn_vlapic *vlapic, uint32_t vector)
{
struct vlapic_pir_desc *pir_desc;
uint32_t idx;
int32_t notify;
bool notify = false;
pir_desc = &(vlapic->pir_desc);
idx = vector >> 6U;
bitmap_set_lock((uint16_t)(vector & 0x3fU), &pir_desc->pir[idx]);
notify = (atomic_cmpxchg64(&pir_desc->pending, 0UL, 1UL) == 0UL) ? 1 : 0;
if (!bitmap_test_and_set_lock((uint16_t)(vector & 0x3fU), &pir_desc->pir[idx])) {
notify = (atomic_cmpxchg64(&pir_desc->pending, 0UL, 1UL) == 0UL);
}
return notify;
}