diff options
Diffstat (limited to 'virt/kvm/ioapic.c')
-rw-r--r-- | virt/kvm/ioapic.c | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c index f01392f51e86..a2edfd177faf 100644 --- a/virt/kvm/ioapic.c +++ b/virt/kvm/ioapic.c | |||
@@ -100,6 +100,19 @@ static int ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx) | |||
100 | return injected; | 100 | return injected; |
101 | } | 101 | } |
102 | 102 | ||
103 | static void update_handled_vectors(struct kvm_ioapic *ioapic) | ||
104 | { | ||
105 | DECLARE_BITMAP(handled_vectors, 256); | ||
106 | int i; | ||
107 | |||
108 | memset(handled_vectors, 0, sizeof(handled_vectors)); | ||
109 | for (i = 0; i < IOAPIC_NUM_PINS; ++i) | ||
110 | __set_bit(ioapic->redirtbl[i].fields.vector, handled_vectors); | ||
111 | memcpy(ioapic->handled_vectors, handled_vectors, | ||
112 | sizeof(handled_vectors)); | ||
113 | smp_wmb(); | ||
114 | } | ||
115 | |||
103 | static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) | 116 | static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) |
104 | { | 117 | { |
105 | unsigned index; | 118 | unsigned index; |
@@ -134,6 +147,7 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) | |||
134 | e->bits |= (u32) val; | 147 | e->bits |= (u32) val; |
135 | e->fields.remote_irr = 0; | 148 | e->fields.remote_irr = 0; |
136 | } | 149 | } |
150 | update_handled_vectors(ioapic); | ||
137 | mask_after = e->fields.mask; | 151 | mask_after = e->fields.mask; |
138 | if (mask_before != mask_after) | 152 | if (mask_before != mask_after) |
139 | kvm_fire_mask_notifiers(ioapic->kvm, index, mask_after); | 153 | 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) | |||
241 | { | 255 | { |
242 | struct kvm_ioapic *ioapic = kvm->arch.vioapic; | 256 | struct kvm_ioapic *ioapic = kvm->arch.vioapic; |
243 | 257 | ||
258 | smp_rmb(); | ||
259 | if (!test_bit(vector, ioapic->handled_vectors)) | ||
260 | return; | ||
244 | mutex_lock(&ioapic->lock); | 261 | mutex_lock(&ioapic->lock); |
245 | __kvm_ioapic_update_eoi(ioapic, vector, trigger_mode); | 262 | __kvm_ioapic_update_eoi(ioapic, vector, trigger_mode); |
246 | mutex_unlock(&ioapic->lock); | 263 | mutex_unlock(&ioapic->lock); |
@@ -352,6 +369,7 @@ void kvm_ioapic_reset(struct kvm_ioapic *ioapic) | |||
352 | ioapic->ioregsel = 0; | 369 | ioapic->ioregsel = 0; |
353 | ioapic->irr = 0; | 370 | ioapic->irr = 0; |
354 | ioapic->id = 0; | 371 | ioapic->id = 0; |
372 | update_handled_vectors(ioapic); | ||
355 | } | 373 | } |
356 | 374 | ||
357 | static const struct kvm_io_device_ops ioapic_mmio_ops = { | 375 | 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) | |||
401 | 419 | ||
402 | mutex_lock(&ioapic->lock); | 420 | mutex_lock(&ioapic->lock); |
403 | memcpy(ioapic, state, sizeof(struct kvm_ioapic_state)); | 421 | memcpy(ioapic, state, sizeof(struct kvm_ioapic_state)); |
422 | update_handled_vectors(ioapic); | ||
404 | mutex_unlock(&ioapic->lock); | 423 | mutex_unlock(&ioapic->lock); |
405 | return 0; | 424 | return 0; |
406 | } | 425 | } |