aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/lapic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kvm/lapic.c')
-rw-r--r--arch/x86/kvm/lapic.c47
1 files changed, 29 insertions, 18 deletions
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 27ca43e4e440..a42f968a23e1 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);