aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/lapic.c
diff options
context:
space:
mode:
authorJan Kiszka <jan.kiszka@siemens.com>2008-09-26 03:30:52 -0400
committerAvi Kivity <avi@redhat.com>2008-12-31 09:51:41 -0500
commit23930f9521c9c4d4aa96cdb9d1e1703f3782bb94 (patch)
treef5bf96bdc4515cc976e1dcf1fb950454276aabf8 /arch/x86/kvm/lapic.c
parent66a5a347c2690db4c0756524a8eb5a05e0437aa8 (diff)
KVM: x86: Enable NMI Watchdog via in-kernel PIT source
LINT0 of the LAPIC can be used to route PIT events as NMI watchdog ticks into the guest. This patch aligns the in-kernel irqchip emulation with the user space irqchip with already supports this feature. The trick is to route PIT interrupts to all LAPIC's LVT0 lines. Rebased and slightly polished patch originally posted by Sheng Yang. Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Signed-off-by: Sheng Yang <sheng.yang@intel.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/lapic.c')
-rw-r--r--arch/x86/kvm/lapic.c34
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
964static int __inject_apic_timer_irq(struct kvm_lapic *apic) 975int 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); 991static 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
972static enum hrtimer_restart apic_timer_fn(struct hrtimer *data) 996static enum hrtimer_restart apic_timer_fn(struct hrtimer *data)