|
@@ -100,6 +100,19 @@ static int ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx)
|
|
return injected;
|
|
return injected;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void update_handled_vectors(struct kvm_ioapic *ioapic)
|
|
|
|
+{
|
|
|
|
+ DECLARE_BITMAP(handled_vectors, 256);
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ memset(handled_vectors, 0, sizeof(handled_vectors));
|
|
|
|
+ for (i = 0; i < IOAPIC_NUM_PINS; ++i)
|
|
|
|
+ __set_bit(ioapic->redirtbl[i].fields.vector, handled_vectors);
|
|
|
|
+ memcpy(ioapic->handled_vectors, handled_vectors,
|
|
|
|
+ sizeof(handled_vectors));
|
|
|
|
+ smp_wmb();
|
|
|
|
+}
|
|
|
|
+
|
|
static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
|
|
static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
|
|
{
|
|
{
|
|
unsigned index;
|
|
unsigned index;
|
|
@@ -134,6 +147,7 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
|
|
e->bits |= (u32) val;
|
|
e->bits |= (u32) val;
|
|
e->fields.remote_irr = 0;
|
|
e->fields.remote_irr = 0;
|
|
}
|
|
}
|
|
|
|
+ update_handled_vectors(ioapic);
|
|
mask_after = e->fields.mask;
|
|
mask_after = e->fields.mask;
|
|
if (mask_before != mask_after)
|
|
if (mask_before != mask_after)
|
|
kvm_fire_mask_notifiers(ioapic->kvm, index, mask_after);
|
|
kvm_fire_mask_notifiers(ioapic->kvm, index, mask_after);
|
|
@@ -241,6 +255,9 @@ void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode)
|
|
{
|
|
{
|
|
struct kvm_ioapic *ioapic = kvm->arch.vioapic;
|
|
struct kvm_ioapic *ioapic = kvm->arch.vioapic;
|
|
|
|
|
|
|
|
+ smp_rmb();
|
|
|
|
+ if (!test_bit(vector, ioapic->handled_vectors))
|
|
|
|
+ return;
|
|
mutex_lock(&ioapic->lock);
|
|
mutex_lock(&ioapic->lock);
|
|
__kvm_ioapic_update_eoi(ioapic, vector, trigger_mode);
|
|
__kvm_ioapic_update_eoi(ioapic, vector, trigger_mode);
|
|
mutex_unlock(&ioapic->lock);
|
|
mutex_unlock(&ioapic->lock);
|
|
@@ -352,6 +369,7 @@ void kvm_ioapic_reset(struct kvm_ioapic *ioapic)
|
|
ioapic->ioregsel = 0;
|
|
ioapic->ioregsel = 0;
|
|
ioapic->irr = 0;
|
|
ioapic->irr = 0;
|
|
ioapic->id = 0;
|
|
ioapic->id = 0;
|
|
|
|
+ update_handled_vectors(ioapic);
|
|
}
|
|
}
|
|
|
|
|
|
static const struct kvm_io_device_ops ioapic_mmio_ops = {
|
|
static const struct kvm_io_device_ops ioapic_mmio_ops = {
|
|
@@ -401,6 +419,7 @@ int kvm_set_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state)
|
|
|
|
|
|
mutex_lock(&ioapic->lock);
|
|
mutex_lock(&ioapic->lock);
|
|
memcpy(ioapic, state, sizeof(struct kvm_ioapic_state));
|
|
memcpy(ioapic, state, sizeof(struct kvm_ioapic_state));
|
|
|
|
+ update_handled_vectors(ioapic);
|
|
mutex_unlock(&ioapic->lock);
|
|
mutex_unlock(&ioapic->lock);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|