@@ -204,6 +204,39 @@ void apic_deliver_pic_intr(DeviceState *d, int level)
}
}
+static inline uint32_t kapic_reg(struct kvm_lapic_state *kapic, int reg_id);
+
+static void kvm_irqchip_deliver_nmi(void *p)
+{
+ APICState *s = p;
+ struct kvm_lapic_state klapic;
+ uint32_t lvt;
+
+ kvm_get_lapic(s->cpu_env, &klapic);
+ lvt = kapic_reg(&klapic, 0x32 + APIC_LVT_LINT1);
+
+ if (lvt & APIC_LVT_MASKED) {
+ return;
+ }
+
+ if (((lvt >> 8) & 7) != APIC_DM_NMI) {
+ return;
+ }
+
+ kvm_vcpu_ioctl(s->cpu_env, KVM_NMI);
+}
+
+void apic_deliver_nmi(DeviceState *d)
+{
+ APICState *s = DO_UPCAST(APICState, busdev.qdev, d);
+
+ if (kvm_irqchip_in_kernel()) {
+ run_on_cpu(s->cpu_env, kvm_irqchip_deliver_nmi, s);
+ } else {
+ apic_local_deliver(s, APIC_LVT_LINT1);
+ }
+}
+
#define foreach_apic(apic, deliver_bitmask, code) \
{\
int __i, __j, __mask;\
@@ -10,6 +10,7 @@ void apic_deliver_irq(uint8_t dest, uint8_t dest_mode,
uint8_t trigger_mode);
int apic_accept_pic_intr(DeviceState *s);
void apic_deliver_pic_intr(DeviceState *s, int level);
+void apic_deliver_nmi(DeviceState *d);
int apic_get_interrupt(DeviceState *s);
void apic_reset_irq_delivered(void);
int apic_get_irq_delivered(void);
@@ -2604,7 +2604,11 @@ static int do_inject_nmi(Monitor *mon, const QDict *qdict, QObject **ret_data)
CPUState *env;
for (env = first_cpu; env != NULL; env = env->next_cpu) {
- cpu_interrupt(env, CPU_INTERRUPT_NMI);
+ if (!env->apic_state) {
+ cpu_interrupt(env, CPU_INTERRUPT_NMI);
+ } else {
+ apic_deliver_nmi(env->apic_state);
+ }
}
return 0;