|
33 | 33 | #include <hypervisor.h>
|
34 | 34 |
|
35 | 35 | #define RTBL_RO_BITS (uint32_t)(IOAPIC_RTE_REM_IRR | IOAPIC_RTE_DELIVS)
|
36 |
| -#define NEED_TMR_UPDATE (IOAPIC_RTE_TRGRMOD | IOAPIC_RTE_DELMOD | IOAPIC_RTE_INTVEC) |
| 36 | +#define NEED_EOI_EXIT_UPDATE (IOAPIC_RTE_TRGRMOD | IOAPIC_RTE_DELMOD | IOAPIC_RTE_DEST_MASK | IOAPIC_RTE_INTVEC) |
37 | 37 |
|
38 | 38 | #define ACRN_DBG_IOAPIC 6U
|
39 | 39 | #define ACRN_IOAPIC_VERSION 0x11U
|
@@ -171,6 +171,66 @@ vioapic_set_irqline_lock(const struct acrn_vm *vm, uint32_t irqline, uint32_t op
|
171 | 171 | spinlock_release(&(vioapic->mtx));
|
172 | 172 | }
|
173 | 173 |
|
| 174 | +/* |
| 175 | + * Generate eoi_exit_bitmap and request each VCPU to update VMCS fields |
| 176 | + * To be called with vioapic->mtx |
| 177 | + * @pre vioapic != NULL |
| 178 | + */ |
| 179 | +static void |
| 180 | +vioapic_update_eoi_exit(const struct acrn_vioapic *vioapic) |
| 181 | +{ |
| 182 | + struct acrn_vcpu *vcpu; |
| 183 | + union ioapic_rte rte; |
| 184 | + uint64_t mask; |
| 185 | + uint32_t vector, delmode, dest; |
| 186 | + uint32_t pin, pincount; |
| 187 | + uint16_t vcpu_id; |
| 188 | + bool level, phys; |
| 189 | + |
| 190 | + dev_dbg(ACRN_DBG_IOAPIC, "%s", __func__); |
| 191 | + |
| 192 | + /* clear old bitmap to generate new bitmap */ |
| 193 | + foreach_vcpu(vcpu_id, vioapic->vm, vcpu) { |
| 194 | + spinlock_obtain(&(vcpu->arch.lock)); |
| 195 | + vcpu_reset_eoi_exit_all(vcpu); |
| 196 | + } |
| 197 | + |
| 198 | + /* go through RTEs and set corresponding bits of eoi_exit_bitmap */ |
| 199 | + pincount = vioapic_pincount(vioapic->vm); |
| 200 | + for (pin = 0U; pin < pincount; pin++) { |
| 201 | + rte = vioapic->rtbl[pin]; |
| 202 | + |
| 203 | + level = ((rte.full & IOAPIC_RTE_TRGRLVL) != 0UL); |
| 204 | + vector = rte.u.lo_32 & IOAPIC_RTE_LOW_INTVEC; |
| 205 | + |
| 206 | + if (level && ((vector >= 0x20U) && (vector < NR_MAX_VECTOR))) { |
| 207 | + /* if level-trigger and vector is valid */ |
| 208 | + delmode = (uint32_t)(rte.full & IOAPIC_RTE_DELMOD); |
| 209 | + |
| 210 | + if ((delmode != APIC_DELMODE_FIXED) && (delmode != APIC_DELMODE_LOWPRIO)) { |
| 211 | + dev_dbg(ACRN_DBG_IOAPIC, |
| 212 | + "Ignoring level trigger-mode for delivery-mode 0x%x", delmode); |
| 213 | + } else { |
| 214 | + dest = (uint32_t)((rte.full) >> IOAPIC_RTE_DEST_SHIFT); |
| 215 | + phys = ((rte.full & IOAPIC_RTE_DESTLOG) == 0UL); |
| 216 | + calcvdest(vioapic->vm, &mask, dest, phys); |
| 217 | + |
| 218 | + for (vcpu_id = ffs64(mask); vcpu_id != INVALID_BIT_INDEX; vcpu_id = ffs64(mask)) { |
| 219 | + vcpu = vcpu_from_vid(vioapic->vm, vcpu_id); |
| 220 | + vcpu_set_eoi_exit(vcpu, vector); |
| 221 | + bitmap_clear_nolock(vcpu_id, &mask); |
| 222 | + } |
| 223 | + } |
| 224 | + } |
| 225 | + } |
| 226 | + |
| 227 | + /* make request if eoi_exit_bitmap changed */ |
| 228 | + foreach_vcpu(vcpu_id, vioapic->vm, vcpu) { |
| 229 | + spinlock_release(&(vcpu->arch.lock)); |
| 230 | + vcpu_make_request(vcpu, ACRN_REQUEST_EOI_EXIT_UPDATE); |
| 231 | + } |
| 232 | +} |
| 233 | + |
174 | 234 | /*
|
175 | 235 | * Reset the vlapic's trigger-mode register to reflect the ioapic pin
|
176 | 236 | * configuration.
|
@@ -358,15 +418,9 @@ static void vioapic_indirect_write(struct acrn_vioapic *vioapic, uint32_t addr,
|
358 | 418 | * rendezvous all the vcpus to update their vlapic
|
359 | 419 | * trigger-mode registers.
|
360 | 420 | */
|
361 |
| - if ((changed & NEED_TMR_UPDATE) != 0UL) { |
362 |
| - uint16_t i; |
363 |
| - struct acrn_vcpu *vcpu; |
364 |
| - |
365 |
| - dev_dbg(ACRN_DBG_IOAPIC, "ioapic pin%hhu: recalculate vlapic trigger-mode reg", pin); |
366 |
| - |
367 |
| - foreach_vcpu(i, vioapic->vm, vcpu) { |
368 |
| - vcpu_make_request(vcpu, ACRN_REQUEST_TMR_UPDATE); |
369 |
| - } |
| 421 | + if ((changed & NEED_EOI_EXIT_UPDATE) != 0UL) { |
| 422 | + dev_dbg(ACRN_DBG_IOAPIC, "ioapic pin%hhu: recalculate vlapic trigger-mode reg", pin); |
| 423 | + vioapic_update_eoi_exit(vioapic); |
370 | 424 | }
|
371 | 425 |
|
372 | 426 | /*
|
|
0 commit comments