aboutsummaryrefslogtreecommitdiffstats
path: root/virt/kvm/ioapic.c
diff options
context:
space:
mode:
Diffstat (limited to 'virt/kvm/ioapic.c')
-rw-r--r--virt/kvm/ioapic.c39
1 files changed, 27 insertions, 12 deletions
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index 23b81cf242af..c3b99def9cbc 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -83,24 +83,28 @@ static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic,
83 return result; 83 return result;
84} 84}
85 85
86static void ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx) 86static int ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx)
87{ 87{
88 union ioapic_redir_entry *pent; 88 union ioapic_redir_entry *pent;
89 int injected = -1;
89 90
90 pent = &ioapic->redirtbl[idx]; 91 pent = &ioapic->redirtbl[idx];
91 92
92 if (!pent->fields.mask) { 93 if (!pent->fields.mask) {
93 int injected = ioapic_deliver(ioapic, idx); 94 injected = ioapic_deliver(ioapic, idx);
94 if (injected && pent->fields.trig_mode == IOAPIC_LEVEL_TRIG) 95 if (injected && pent->fields.trig_mode == IOAPIC_LEVEL_TRIG)
95 pent->fields.remote_irr = 1; 96 pent->fields.remote_irr = 1;
96 } 97 }
97 if (!pent->fields.trig_mode) 98 if (!pent->fields.trig_mode)
98 ioapic->irr &= ~(1 << idx); 99 ioapic->irr &= ~(1 << idx);
100
101 return injected;
99} 102}
100 103
101static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) 104static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
102{ 105{
103 unsigned index; 106 unsigned index;
107 bool mask_before, mask_after;
104 108
105 switch (ioapic->ioregsel) { 109 switch (ioapic->ioregsel) {
106 case IOAPIC_REG_VERSION: 110 case IOAPIC_REG_VERSION:
@@ -120,6 +124,7 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
120 ioapic_debug("change redir index %x val %x\n", index, val); 124 ioapic_debug("change redir index %x val %x\n", index, val);
121 if (index >= IOAPIC_NUM_PINS) 125 if (index >= IOAPIC_NUM_PINS)
122 return; 126 return;
127 mask_before = ioapic->redirtbl[index].fields.mask;
123 if (ioapic->ioregsel & 1) { 128 if (ioapic->ioregsel & 1) {
124 ioapic->redirtbl[index].bits &= 0xffffffff; 129 ioapic->redirtbl[index].bits &= 0xffffffff;
125 ioapic->redirtbl[index].bits |= (u64) val << 32; 130 ioapic->redirtbl[index].bits |= (u64) val << 32;
@@ -128,6 +133,9 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
128 ioapic->redirtbl[index].bits |= (u32) val; 133 ioapic->redirtbl[index].bits |= (u32) val;
129 ioapic->redirtbl[index].fields.remote_irr = 0; 134 ioapic->redirtbl[index].fields.remote_irr = 0;
130 } 135 }
136 mask_after = ioapic->redirtbl[index].fields.mask;
137 if (mask_before != mask_after)
138 kvm_fire_mask_notifiers(ioapic->kvm, index, mask_after);
131 if (ioapic->irr & (1 << index)) 139 if (ioapic->irr & (1 << index))
132 ioapic_service(ioapic, index); 140 ioapic_service(ioapic, index);
133 break; 141 break;
@@ -202,7 +210,7 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
202 u8 trig_mode = ioapic->redirtbl[irq].fields.trig_mode; 210 u8 trig_mode = ioapic->redirtbl[irq].fields.trig_mode;
203 u32 deliver_bitmask; 211 u32 deliver_bitmask;
204 struct kvm_vcpu *vcpu; 212 struct kvm_vcpu *vcpu;
205 int vcpu_id, r = 0; 213 int vcpu_id, r = -1;
206 214
207 ioapic_debug("dest=%x dest_mode=%x delivery_mode=%x " 215 ioapic_debug("dest=%x dest_mode=%x delivery_mode=%x "
208 "vector=%x trig_mode=%x\n", 216 "vector=%x trig_mode=%x\n",
@@ -242,7 +250,9 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
242 deliver_bitmask &= ~(1 << vcpu_id); 250 deliver_bitmask &= ~(1 << vcpu_id);
243 vcpu = ioapic->kvm->vcpus[vcpu_id]; 251 vcpu = ioapic->kvm->vcpus[vcpu_id];
244 if (vcpu) { 252 if (vcpu) {
245 r = ioapic_inj_irq(ioapic, vcpu, vector, 253 if (r < 0)
254 r = 0;
255 r += ioapic_inj_irq(ioapic, vcpu, vector,
246 trig_mode, delivery_mode); 256 trig_mode, delivery_mode);
247 } 257 }
248 } 258 }
@@ -253,8 +263,10 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
253 continue; 263 continue;
254 deliver_bitmask &= ~(1 << vcpu_id); 264 deliver_bitmask &= ~(1 << vcpu_id);
255 vcpu = ioapic->kvm->vcpus[vcpu_id]; 265 vcpu = ioapic->kvm->vcpus[vcpu_id];
256 if (vcpu) 266 if (vcpu) {
257 ioapic_inj_nmi(vcpu); 267 ioapic_inj_nmi(vcpu);
268 r = 1;
269 }
258 else 270 else
259 ioapic_debug("NMI to vcpu %d failed\n", 271 ioapic_debug("NMI to vcpu %d failed\n",
260 vcpu->vcpu_id); 272 vcpu->vcpu_id);
@@ -268,11 +280,12 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
268 return r; 280 return r;
269} 281}
270 282
271void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level) 283int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level)
272{ 284{
273 u32 old_irr = ioapic->irr; 285 u32 old_irr = ioapic->irr;
274 u32 mask = 1 << irq; 286 u32 mask = 1 << irq;
275 union ioapic_redir_entry entry; 287 union ioapic_redir_entry entry;
288 int ret = 1;
276 289
277 if (irq >= 0 && irq < IOAPIC_NUM_PINS) { 290 if (irq >= 0 && irq < IOAPIC_NUM_PINS) {
278 entry = ioapic->redirtbl[irq]; 291 entry = ioapic->redirtbl[irq];
@@ -283,25 +296,26 @@ void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level)
283 ioapic->irr |= mask; 296 ioapic->irr |= mask;
284 if ((!entry.fields.trig_mode && old_irr != ioapic->irr) 297 if ((!entry.fields.trig_mode && old_irr != ioapic->irr)
285 || !entry.fields.remote_irr) 298 || !entry.fields.remote_irr)
286 ioapic_service(ioapic, irq); 299 ret = ioapic_service(ioapic, irq);
287 } 300 }
288 } 301 }
302 return ret;
289} 303}
290 304
291static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int gsi, 305static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int pin,
292 int trigger_mode) 306 int trigger_mode)
293{ 307{
294 union ioapic_redir_entry *ent; 308 union ioapic_redir_entry *ent;
295 309
296 ent = &ioapic->redirtbl[gsi]; 310 ent = &ioapic->redirtbl[pin];
297 311
298 kvm_notify_acked_irq(ioapic->kvm, gsi); 312 kvm_notify_acked_irq(ioapic->kvm, KVM_IRQCHIP_IOAPIC, pin);
299 313
300 if (trigger_mode == IOAPIC_LEVEL_TRIG) { 314 if (trigger_mode == IOAPIC_LEVEL_TRIG) {
301 ASSERT(ent->fields.trig_mode == IOAPIC_LEVEL_TRIG); 315 ASSERT(ent->fields.trig_mode == IOAPIC_LEVEL_TRIG);
302 ent->fields.remote_irr = 0; 316 ent->fields.remote_irr = 0;
303 if (!ent->fields.mask && (ioapic->irr & (1 << gsi))) 317 if (!ent->fields.mask && (ioapic->irr & (1 << pin)))
304 ioapic_service(ioapic, gsi); 318 ioapic_service(ioapic, pin);
305 } 319 }
306} 320}
307 321
@@ -426,3 +440,4 @@ int kvm_ioapic_init(struct kvm *kvm)
426 kvm_io_bus_register_dev(&kvm->mmio_bus, &ioapic->dev); 440 kvm_io_bus_register_dev(&kvm->mmio_bus, &ioapic->dev);
427 return 0; 441 return 0;
428} 442}
443