aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/ia64/include/asm/kvm_host.h1
-rw-r--r--arch/ia64/kvm/kvm-ia64.c8
-rw-r--r--arch/ia64/kvm/lapic.h2
-rw-r--r--arch/x86/kvm/lapic.c47
-rw-r--r--arch/x86/kvm/lapic.h2
-rw-r--r--virt/kvm/ioapic.c40
-rw-r--r--virt/kvm/irq_comm.c1
7 files changed, 42 insertions, 59 deletions
diff --git a/arch/ia64/include/asm/kvm_host.h b/arch/ia64/include/asm/kvm_host.h
index 4542651e6ac..5608488dc2d 100644
--- a/arch/ia64/include/asm/kvm_host.h
+++ b/arch/ia64/include/asm/kvm_host.h
@@ -585,7 +585,6 @@ int kvm_emulate_halt(struct kvm_vcpu *vcpu);
585int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run); 585int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run);
586void kvm_sal_emul(struct kvm_vcpu *vcpu); 586void kvm_sal_emul(struct kvm_vcpu *vcpu);
587 587
588static inline void kvm_inject_nmi(struct kvm_vcpu *vcpu) {}
589#endif /* __ASSEMBLY__*/ 588#endif /* __ASSEMBLY__*/
590 589
591#endif 590#endif
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index 774f0d78a58..99d6d174d93 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -292,13 +292,13 @@ static void vcpu_deliver_ipi(struct kvm_vcpu *vcpu, uint64_t dm,
292{ 292{
293 switch (dm) { 293 switch (dm) {
294 case SAPIC_FIXED: 294 case SAPIC_FIXED:
295 kvm_apic_set_irq(vcpu, vector, 0); 295 kvm_apic_set_irq(vcpu, vector, dm, 0);
296 break; 296 break;
297 case SAPIC_NMI: 297 case SAPIC_NMI:
298 kvm_apic_set_irq(vcpu, 2, 0); 298 kvm_apic_set_irq(vcpu, 2, dm, 0);
299 break; 299 break;
300 case SAPIC_EXTINT: 300 case SAPIC_EXTINT:
301 kvm_apic_set_irq(vcpu, 0, 0); 301 kvm_apic_set_irq(vcpu, 0, dm, 0);
302 break; 302 break;
303 case SAPIC_INIT: 303 case SAPIC_INIT:
304 case SAPIC_PMI: 304 case SAPIC_PMI:
@@ -1813,7 +1813,7 @@ void kvm_vcpu_kick(struct kvm_vcpu *vcpu)
1813 put_cpu(); 1813 put_cpu();
1814} 1814}
1815 1815
1816int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig) 1816int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 dmode, u8 trig)
1817{ 1817{
1818 1818
1819 struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd); 1819 struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd);
diff --git a/arch/ia64/kvm/lapic.h b/arch/ia64/kvm/lapic.h
index 6d6cbcb1489..cbcfaa6195c 100644
--- a/arch/ia64/kvm/lapic.h
+++ b/arch/ia64/kvm/lapic.h
@@ -20,6 +20,6 @@ void kvm_free_lapic(struct kvm_vcpu *vcpu);
20 20
21int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest); 21int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest);
22int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda); 22int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda);
23int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig); 23int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 dmode, u8 trig);
24 24
25#endif 25#endif
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 27ca43e4e44..a42f968a23e 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -196,20 +196,30 @@ int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu)
196} 196}
197EXPORT_SYMBOL_GPL(kvm_lapic_find_highest_irr); 197EXPORT_SYMBOL_GPL(kvm_lapic_find_highest_irr);
198 198
199int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig) 199static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
200 int vector, int level, int trig_mode);
201
202int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 dmode, u8 trig)
200{ 203{
201 struct kvm_lapic *apic = vcpu->arch.apic; 204 struct kvm_lapic *apic = vcpu->arch.apic;
205 int lapic_dmode;
202 206
203 if (!apic_test_and_set_irr(vec, apic)) { 207 switch (dmode) {
204 /* a new pending irq is set in IRR */ 208 case IOAPIC_LOWEST_PRIORITY:
205 if (trig) 209 lapic_dmode = APIC_DM_LOWEST;
206 apic_set_vector(vec, apic->regs + APIC_TMR); 210 break;
207 else 211 case IOAPIC_FIXED:
208 apic_clear_vector(vec, apic->regs + APIC_TMR); 212 lapic_dmode = APIC_DM_FIXED;
209 kvm_vcpu_kick(apic->vcpu); 213 break;
210 return 1; 214 case IOAPIC_NMI:
215 lapic_dmode = APIC_DM_NMI;
216 break;
217 default:
218 printk(KERN_DEBUG"Ignoring delivery mode %d\n", dmode);
219 return 0;
220 break;
211 } 221 }
212 return 0; 222 return __apic_accept_irq(apic, lapic_dmode, vec, 1, trig);
213} 223}
214 224
215static inline int apic_find_highest_isr(struct kvm_lapic *apic) 225static inline int apic_find_highest_isr(struct kvm_lapic *apic)
@@ -327,7 +337,7 @@ static int apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
327static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, 337static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
328 int vector, int level, int trig_mode) 338 int vector, int level, int trig_mode)
329{ 339{
330 int orig_irr, result = 0; 340 int result = 0;
331 struct kvm_vcpu *vcpu = apic->vcpu; 341 struct kvm_vcpu *vcpu = apic->vcpu;
332 342
333 switch (delivery_mode) { 343 switch (delivery_mode) {
@@ -337,10 +347,11 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
337 if (unlikely(!apic_enabled(apic))) 347 if (unlikely(!apic_enabled(apic)))
338 break; 348 break;
339 349
340 orig_irr = apic_test_and_set_irr(vector, apic); 350 result = !apic_test_and_set_irr(vector, apic);
341 if (orig_irr && trig_mode) { 351 if (!result) {
342 apic_debug("level trig mode repeatedly for vector %d", 352 if (trig_mode)
343 vector); 353 apic_debug("level trig mode repeatedly for "
354 "vector %d", vector);
344 break; 355 break;
345 } 356 }
346 357
@@ -349,10 +360,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
349 apic_set_vector(vector, apic->regs + APIC_TMR); 360 apic_set_vector(vector, apic->regs + APIC_TMR);
350 } else 361 } else
351 apic_clear_vector(vector, apic->regs + APIC_TMR); 362 apic_clear_vector(vector, apic->regs + APIC_TMR);
352
353 kvm_vcpu_kick(vcpu); 363 kvm_vcpu_kick(vcpu);
354
355 result = (orig_irr == 0);
356 break; 364 break;
357 365
358 case APIC_DM_REMRD: 366 case APIC_DM_REMRD:
@@ -364,12 +372,14 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
364 break; 372 break;
365 373
366 case APIC_DM_NMI: 374 case APIC_DM_NMI:
375 result = 1;
367 kvm_inject_nmi(vcpu); 376 kvm_inject_nmi(vcpu);
368 kvm_vcpu_kick(vcpu); 377 kvm_vcpu_kick(vcpu);
369 break; 378 break;
370 379
371 case APIC_DM_INIT: 380 case APIC_DM_INIT:
372 if (level) { 381 if (level) {
382 result = 1;
373 if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE) 383 if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE)
374 printk(KERN_DEBUG 384 printk(KERN_DEBUG
375 "INIT on a runnable vcpu %d\n", 385 "INIT on a runnable vcpu %d\n",
@@ -386,6 +396,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
386 apic_debug("SIPI to vcpu %d vector 0x%02x\n", 396 apic_debug("SIPI to vcpu %d vector 0x%02x\n",
387 vcpu->vcpu_id, vector); 397 vcpu->vcpu_id, vector);
388 if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) { 398 if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) {
399 result = 1;
389 vcpu->arch.sipi_vector = vector; 400 vcpu->arch.sipi_vector = vector;
390 vcpu->arch.mp_state = KVM_MP_STATE_SIPI_RECEIVED; 401 vcpu->arch.mp_state = KVM_MP_STATE_SIPI_RECEIVED;
391 kvm_vcpu_kick(vcpu); 402 kvm_vcpu_kick(vcpu);
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 2fc0d3c1b19..1b0e3c03cb3 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -31,7 +31,7 @@ u64 kvm_lapic_get_base(struct kvm_vcpu *vcpu);
31 31
32int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest); 32int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest);
33int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda); 33int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda);
34int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig); 34int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 dmode, u8 trig);
35 35
36u64 kvm_get_apic_base(struct kvm_vcpu *vcpu); 36u64 kvm_get_apic_base(struct kvm_vcpu *vcpu);
37void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data); 37void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data);
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index ea268a8c37d..d4a7948b010 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -142,25 +142,6 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
142 } 142 }
143} 143}
144 144
145static int ioapic_inj_irq(struct kvm_ioapic *ioapic,
146 struct kvm_vcpu *vcpu,
147 u8 vector, u8 trig_mode, u8 delivery_mode)
148{
149 ioapic_debug("irq %d trig %d deliv %d\n", vector, trig_mode,
150 delivery_mode);
151
152 ASSERT((delivery_mode == IOAPIC_FIXED) ||
153 (delivery_mode == IOAPIC_LOWEST_PRIORITY));
154
155 return kvm_apic_set_irq(vcpu, vector, trig_mode);
156}
157
158static void ioapic_inj_nmi(struct kvm_vcpu *vcpu)
159{
160 kvm_inject_nmi(vcpu);
161 kvm_vcpu_kick(vcpu);
162}
163
164static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq) 145static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
165{ 146{
166 union kvm_ioapic_redirect_entry entry = ioapic->redirtbl[irq]; 147 union kvm_ioapic_redirect_entry entry = ioapic->redirtbl[irq];
@@ -193,21 +174,12 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
193 __clear_bit(vcpu_id, deliver_bitmask); 174 __clear_bit(vcpu_id, deliver_bitmask);
194 vcpu = ioapic->kvm->vcpus[vcpu_id]; 175 vcpu = ioapic->kvm->vcpus[vcpu_id];
195 if (vcpu) { 176 if (vcpu) {
196 if (entry.fields.delivery_mode == 177 if (r < 0)
197 IOAPIC_LOWEST_PRIORITY || 178 r = 0;
198 entry.fields.delivery_mode == IOAPIC_FIXED) { 179 r += kvm_apic_set_irq(vcpu,
199 if (r < 0) 180 entry.fields.vector,
200 r = 0; 181 entry.fields.trig_mode,
201 r += ioapic_inj_irq(ioapic, vcpu, 182 entry.fields.delivery_mode);
202 entry.fields.vector,
203 entry.fields.trig_mode,
204 entry.fields.delivery_mode);
205 } else if (entry.fields.delivery_mode == IOAPIC_NMI) {
206 r = 1;
207 ioapic_inj_nmi(vcpu);
208 } else
209 ioapic_debug("unsupported delivery mode %x!\n",
210 entry.fields.delivery_mode);
211 } else 183 } else
212 ioapic_debug("null destination vcpu: " 184 ioapic_debug("null destination vcpu: "
213 "mask=%x vector=%x delivery_mode=%x\n", 185 "mask=%x vector=%x delivery_mode=%x\n",
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c
index 1c6ff6d1b84..325c6685f20 100644
--- a/virt/kvm/irq_comm.c
+++ b/virt/kvm/irq_comm.c
@@ -148,6 +148,7 @@ static int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
148 if (r < 0) 148 if (r < 0)
149 r = 0; 149 r = 0;
150 r += kvm_apic_set_irq(vcpu, entry.fields.vector, 150 r += kvm_apic_set_irq(vcpu, entry.fields.vector,
151 entry.fields.dest_mode,
151 entry.fields.trig_mode); 152 entry.fields.trig_mode);
152 } 153 }
153 } 154 }