@@ -375,6 +375,50 @@ static const struct hvm_mmio_ops vioapic_mmio_ops = {
.write = vioapic_write
};
+static void eoi_callback(struct vcpu *v, unsigned int vector, void *data)
+{
+ struct domain *d = v->domain;
+ struct hvm_irq *hvm_irq = hvm_domain_irq(d);
+ union vioapic_redir_entry *ent;
+ unsigned int i;
+
+ ASSERT(has_vioapic(d));
+
+ spin_lock(&d->arch.hvm.irq_lock);
+
+ for ( i = 0; i < d->arch.hvm.nr_vioapics; i++ )
+ {
+ struct hvm_vioapic *vioapic = domain_vioapic(d, i);
+ unsigned int pin;
+
+ for ( pin = 0; pin < vioapic->nr_pins; pin++ )
+ {
+ ent = &vioapic->redirtbl[pin];
+ if ( ent->fields.vector != vector )
+ continue;
+
+ ent->fields.remote_irr = 0;
+
+ if ( is_iommu_enabled(d) )
+ {
+ spin_unlock(&d->arch.hvm.irq_lock);
+ hvm_dpci_eoi(d, vioapic->base_gsi + pin, ent);
+ spin_lock(&d->arch.hvm.irq_lock);
+ }
+
+ if ( (ent->fields.trig_mode == VIOAPIC_LEVEL_TRIG) &&
+ !ent->fields.mask &&
+ hvm_irq->gsi_assert_count[vioapic->base_gsi + pin] )
+ {
+ ent->fields.remote_irr = 1;
+ vioapic_deliver(vioapic, pin);
+ }
+ }
+ }
+
+ spin_unlock(&d->arch.hvm.irq_lock);
+}
+
static void ioapic_inj_irq(
struct hvm_vioapic *vioapic,
struct vlapic *target,
@@ -388,7 +432,8 @@ static void ioapic_inj_irq(
ASSERT((delivery_mode == dest_Fixed) ||
(delivery_mode == dest_LowestPrio));
- vlapic_set_irq(target, vector, trig_mode);
+ vlapic_set_irq_callback(target, vector, trig_mode,
+ trig_mode ? eoi_callback : NULL, NULL);
}
static void vioapic_deliver(struct hvm_vioapic *vioapic, unsigned int pin)
@@ -495,49 +540,6 @@ void vioapic_irq_positive_edge(struct domain *d, unsigned int irq)
}
}
-void vioapic_update_EOI(struct domain *d, u8 vector)
-{
- struct hvm_irq *hvm_irq = hvm_domain_irq(d);
- union vioapic_redir_entry *ent;
- unsigned int i;
-
- ASSERT(has_vioapic(d));
-
- spin_lock(&d->arch.hvm.irq_lock);
-
- for ( i = 0; i < d->arch.hvm.nr_vioapics; i++ )
- {
- struct hvm_vioapic *vioapic = domain_vioapic(d, i);
- unsigned int pin;
-
- for ( pin = 0; pin < vioapic->nr_pins; pin++ )
- {
- ent = &vioapic->redirtbl[pin];
- if ( ent->fields.vector != vector )
- continue;
-
- ent->fields.remote_irr = 0;
-
- if ( is_iommu_enabled(d) )
- {
- spin_unlock(&d->arch.hvm.irq_lock);
- hvm_dpci_eoi(d, vioapic->base_gsi + pin, ent);
- spin_lock(&d->arch.hvm.irq_lock);
- }
-
- if ( (ent->fields.trig_mode == VIOAPIC_LEVEL_TRIG) &&
- !ent->fields.mask &&
- hvm_irq->gsi_assert_count[vioapic->base_gsi + pin] )
- {
- ent->fields.remote_irr = 1;
- vioapic_deliver(vioapic, pin);
- }
- }
- }
-
- spin_unlock(&d->arch.hvm.irq_lock);
-}
-
int vioapic_get_mask(const struct domain *d, unsigned int gsi)
{
unsigned int pin = 0; /* See gsi_vioapic */
@@ -483,22 +483,17 @@ void vlapic_EOI_set(struct vlapic *vlapic)
void vlapic_handle_EOI(struct vlapic *vlapic, u8 vector)
{
- struct vcpu *v = vlapic_vcpu(vlapic);
- struct domain *d = v->domain;
vlapic_eoi_callback_t *callback;
void *data;
unsigned long flags;
- if ( vlapic_test_vector(vector, &vlapic->regs->data[APIC_TMR]) )
- vioapic_update_EOI(d, vector);
-
spin_lock_irqsave(&vlapic->callback_lock, flags);
callback = vlapic->callbacks[vector].callback;
data = vlapic->callbacks[vector].data;
spin_unlock_irqrestore(&vlapic->callback_lock, flags);
if ( callback )
- callback(v, vector, data);
+ callback(vlapic_vcpu(vlapic), vector, data);
}
static bool_t is_multicast_dest(struct vlapic *vlapic, unsigned int short_hand,
Switch the emulated IO-APIC code to use the local APIC EOI callback mechanism. This allows to remove the last hardcoded callback from vlapic_handle_EOI. Move and rename the vioapic_update_EOI now that it can be made static. Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> --- xen/arch/x86/hvm/vioapic.c | 90 +++++++++++++++++++------------------- xen/arch/x86/hvm/vlapic.c | 7 +-- 2 files changed, 47 insertions(+), 50 deletions(-)