static uint32_t ioapic_get_delivery_bitmask( struct hvm_hw_vioapic *vioapic, uint16_t dest, uint8_t dest_mode) { uint32_t mask = 0; struct vcpu *v; HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "dest %d dest_mode %d", dest, dest_mode); if ( dest_mode == 0 ) /* Physical mode. */ { if ( dest == 0xFF ) /* Broadcast. */ { for_each_vcpu ( vioapic_domain(vioapic), v ) mask |= 1 << v->vcpu_id; goto out; } for_each_vcpu ( vioapic_domain(vioapic), v ) { if ( VLAPIC_ID(vcpu_vlapic(v)) == dest ) { mask = 1 << v->vcpu_id; break; } } } else if ( dest != 0 ) /* Logical mode, MDA non-zero. */
static void vioapic_write_redirent( struct hvm_hw_vioapic *vioapic, unsigned int idx, int top_word, uint32_t val) { struct domain *d = vioapic_domain(vioapic); struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; union vioapic_redir_entry *pent, ent; spin_lock(&d->arch.hvm_domain.irq_lock); pent = &vioapic->redirtbl[idx]; ent = *pent; if ( top_word ) { /* Contains only the dest_id. */ ent.bits = (uint32_t)ent.bits | ((uint64_t)val << 32); } else { /* Remote IRR and Delivery Status are read-only. */ ent.bits = ((ent.bits >> 32) << 32) | val; ent.fields.delivery_status = 0; ent.fields.remote_irr = pent->fields.remote_irr; } *pent = ent; if ( (ent.fields.trig_mode == VIOAPIC_LEVEL_TRIG) && !ent.fields.mask && !ent.fields.remote_irr && hvm_irq->gsi_assert_count[idx] ) { pent->fields.remote_irr = 1; vioapic_deliver(vioapic, idx); } spin_unlock(&d->arch.hvm_domain.irq_lock); }