diff options
Diffstat (limited to 'arch/x86/kvm/lapic.c')
-rw-r--r-- | arch/x86/kvm/lapic.c | 34 |
1 files changed, 29 insertions, 5 deletions
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 0fc3cab48943..206cc11a1c97 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c | |||
@@ -380,6 +380,14 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, | |||
380 | } | 380 | } |
381 | break; | 381 | break; |
382 | 382 | ||
383 | case APIC_DM_EXTINT: | ||
384 | /* | ||
385 | * Should only be called by kvm_apic_local_deliver() with LVT0, | ||
386 | * before NMI watchdog was enabled. Already handled by | ||
387 | * kvm_apic_accept_pic_intr(). | ||
388 | */ | ||
389 | break; | ||
390 | |||
383 | default: | 391 | default: |
384 | printk(KERN_ERR "TODO: unsupported delivery mode %x\n", | 392 | printk(KERN_ERR "TODO: unsupported delivery mode %x\n", |
385 | delivery_mode); | 393 | delivery_mode); |
@@ -743,10 +751,13 @@ static void apic_mmio_write(struct kvm_io_device *this, | |||
743 | apic_set_reg(apic, APIC_ICR2, val & 0xff000000); | 751 | apic_set_reg(apic, APIC_ICR2, val & 0xff000000); |
744 | break; | 752 | break; |
745 | 753 | ||
754 | case APIC_LVT0: | ||
755 | if (val == APIC_DM_NMI) | ||
756 | apic_debug("Receive NMI setting on APIC_LVT0 " | ||
757 | "for cpu %d\n", apic->vcpu->vcpu_id); | ||
746 | case APIC_LVTT: | 758 | case APIC_LVTT: |
747 | case APIC_LVTTHMR: | 759 | case APIC_LVTTHMR: |
748 | case APIC_LVTPC: | 760 | case APIC_LVTPC: |
749 | case APIC_LVT0: | ||
750 | case APIC_LVT1: | 761 | case APIC_LVT1: |
751 | case APIC_LVTERR: | 762 | case APIC_LVTERR: |
752 | /* TODO: Check vector */ | 763 | /* TODO: Check vector */ |
@@ -961,12 +972,25 @@ int apic_has_pending_timer(struct kvm_vcpu *vcpu) | |||
961 | return 0; | 972 | return 0; |
962 | } | 973 | } |
963 | 974 | ||
964 | static int __inject_apic_timer_irq(struct kvm_lapic *apic) | 975 | int kvm_apic_local_deliver(struct kvm_vcpu *vcpu, int lvt_type) |
965 | { | 976 | { |
966 | int vector; | 977 | struct kvm_lapic *apic = vcpu->arch.apic; |
978 | int vector, mode, trig_mode; | ||
979 | u32 reg; | ||
980 | |||
981 | if (apic && apic_enabled(apic)) { | ||
982 | reg = apic_get_reg(apic, lvt_type); | ||
983 | vector = reg & APIC_VECTOR_MASK; | ||
984 | mode = reg & APIC_MODE_MASK; | ||
985 | trig_mode = reg & APIC_LVT_LEVEL_TRIGGER; | ||
986 | return __apic_accept_irq(apic, mode, vector, 1, trig_mode); | ||
987 | } | ||
988 | return 0; | ||
989 | } | ||
967 | 990 | ||
968 | vector = apic_lvt_vector(apic, APIC_LVTT); | 991 | static inline int __inject_apic_timer_irq(struct kvm_lapic *apic) |
969 | return __apic_accept_irq(apic, APIC_DM_FIXED, vector, 1, 0); | 992 | { |
993 | return kvm_apic_local_deliver(apic->vcpu, APIC_LVTT); | ||
970 | } | 994 | } |
971 | 995 | ||
972 | static enum hrtimer_restart apic_timer_fn(struct hrtimer *data) | 996 | static enum hrtimer_restart apic_timer_fn(struct hrtimer *data) |