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 f01392f51e8..a2edfd177fa 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 | } |
