|
@@ -130,6 +130,11 @@ static inline int apic_lvtt_period(struct kvm_lapic *apic)
|
|
return apic_get_reg(apic, APIC_LVTT) & APIC_LVT_TIMER_PERIODIC;
|
|
return apic_get_reg(apic, APIC_LVTT) & APIC_LVT_TIMER_PERIODIC;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static inline int apic_lvt_nmi_mode(u32 lvt_val)
|
|
|
|
+{
|
|
|
|
+ return (lvt_val & (APIC_MODE_MASK | APIC_LVT_MASKED)) == APIC_DM_NMI;
|
|
|
|
+}
|
|
|
|
+
|
|
static unsigned int apic_lvt_mask[APIC_LVT_NUM] = {
|
|
static unsigned int apic_lvt_mask[APIC_LVT_NUM] = {
|
|
LVT_MASK | APIC_LVT_TIMER_PERIODIC, /* LVTT */
|
|
LVT_MASK | APIC_LVT_TIMER_PERIODIC, /* LVTT */
|
|
LVT_MASK | APIC_MODE_MASK, /* LVTTHMR */
|
|
LVT_MASK | APIC_MODE_MASK, /* LVTTHMR */
|
|
@@ -672,6 +677,20 @@ static void start_apic_timer(struct kvm_lapic *apic)
|
|
apic->timer.period)));
|
|
apic->timer.period)));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val)
|
|
|
|
+{
|
|
|
|
+ int nmi_wd_enabled = apic_lvt_nmi_mode(apic_get_reg(apic, APIC_LVT0));
|
|
|
|
+
|
|
|
|
+ if (apic_lvt_nmi_mode(lvt0_val)) {
|
|
|
|
+ if (!nmi_wd_enabled) {
|
|
|
|
+ apic_debug("Receive NMI setting on APIC_LVT0 "
|
|
|
|
+ "for cpu %d\n", apic->vcpu->vcpu_id);
|
|
|
|
+ apic->vcpu->kvm->arch.vapics_in_nmi_mode++;
|
|
|
|
+ }
|
|
|
|
+ } else if (nmi_wd_enabled)
|
|
|
|
+ apic->vcpu->kvm->arch.vapics_in_nmi_mode--;
|
|
|
|
+}
|
|
|
|
+
|
|
static void apic_mmio_write(struct kvm_io_device *this,
|
|
static void apic_mmio_write(struct kvm_io_device *this,
|
|
gpa_t address, int len, const void *data)
|
|
gpa_t address, int len, const void *data)
|
|
{
|
|
{
|
|
@@ -753,9 +772,7 @@ static void apic_mmio_write(struct kvm_io_device *this,
|
|
break;
|
|
break;
|
|
|
|
|
|
case APIC_LVT0:
|
|
case APIC_LVT0:
|
|
- if (val == APIC_DM_NMI)
|
|
|
|
- apic_debug("Receive NMI setting on APIC_LVT0 "
|
|
|
|
- "for cpu %d\n", apic->vcpu->vcpu_id);
|
|
|
|
|
|
+ apic_manage_nmi_watchdog(apic, val);
|
|
case APIC_LVTT:
|
|
case APIC_LVTT:
|
|
case APIC_LVTTHMR:
|
|
case APIC_LVTTHMR:
|
|
case APIC_LVTPC:
|
|
case APIC_LVTPC:
|