summaryrefslogtreecommitdiff
path: root/libkvm
diff options
context:
space:
mode:
Diffstat (limited to 'libkvm')
-rw-r--r--libkvm/libkvm.c31
-rw-r--r--libkvm/libkvm.h23
2 files changed, 54 insertions, 0 deletions
diff --git a/libkvm/libkvm.c b/libkvm/libkvm.c
index dfa63bb8..4f23eaee 100644
--- a/libkvm/libkvm.c
+++ b/libkvm/libkvm.c
@@ -766,6 +766,11 @@ int try_push_interrupts(kvm_context_t kvm)
return kvm->callbacks->try_push_interrupts(kvm->opaque);
}
+int try_push_nmi(kvm_context_t kvm)
+{
+ return kvm->callbacks->try_push_nmi(kvm->opaque);
+}
+
void post_kvm_run(kvm_context_t kvm, int vcpu)
{
kvm->callbacks->post_kvm_run(kvm->opaque, vcpu);
@@ -790,6 +795,17 @@ int kvm_is_ready_for_interrupt_injection(kvm_context_t kvm, int vcpu)
return run->ready_for_interrupt_injection;
}
+int kvm_is_ready_for_nmi_injection(kvm_context_t kvm, int vcpu)
+{
+#ifdef KVM_CAP_NMI
+ struct kvm_run *run = kvm->run[vcpu];
+
+ return run->ready_for_nmi_injection;
+#else
+ return 0;
+#endif
+}
+
int kvm_run(kvm_context_t kvm, int vcpu)
{
int r;
@@ -797,6 +813,9 @@ int kvm_run(kvm_context_t kvm, int vcpu)
struct kvm_run *run = kvm->run[vcpu];
again:
+#ifdef KVM_CAP_NMI
+ run->request_nmi_window = try_push_nmi(kvm);
+#endif
#if !defined(__s390__)
if (!kvm->irqchip_in_kernel)
run->request_interrupt_window = try_push_interrupts(kvm);
@@ -872,6 +891,9 @@ again:
r = handle_halt(kvm, vcpu);
break;
case KVM_EXIT_IRQ_WINDOW_OPEN:
+#ifdef KVM_CAP_NMI
+ case KVM_EXIT_NMI_WINDOW_OPEN:
+#endif
break;
case KVM_EXIT_SHUTDOWN:
r = handle_shutdown(kvm, vcpu);
@@ -956,6 +978,15 @@ int kvm_has_sync_mmu(kvm_context_t kvm)
return r;
}
+int kvm_inject_nmi(kvm_context_t kvm, int vcpu)
+{
+#ifdef KVM_CAP_NMI
+ return ioctl(kvm->vcpu_fd[vcpu], KVM_NMI);
+#else
+ return -ENOSYS;
+#endif
+}
+
int kvm_init_coalesced_mmio(kvm_context_t kvm)
{
int r = 0;
diff --git a/libkvm/libkvm.h b/libkvm/libkvm.h
index 14ea93bb..60d6d08c 100644
--- a/libkvm/libkvm.h
+++ b/libkvm/libkvm.h
@@ -66,6 +66,7 @@ struct kvm_callbacks {
int (*shutdown)(void *opaque, int vcpu);
int (*io_window)(void *opaque);
int (*try_push_interrupts)(void *opaque);
+ int (*try_push_nmi)(void *opaque);
void (*post_kvm_run)(void *opaque, int vcpu);
int (*pre_kvm_run)(void *opaque, int vcpu);
int (*tpr_access)(void *opaque, int vcpu, uint64_t rip, int is_write);
@@ -216,6 +217,17 @@ uint64_t kvm_get_apic_base(kvm_context_t kvm, int vcpu);
int kvm_is_ready_for_interrupt_injection(kvm_context_t kvm, int vcpu);
/*!
+ * \brief Check if a vcpu is ready for NMI injection
+ *
+ * This checks if vcpu is not already running in NMI context.
+ *
+ * \param kvm Pointer to the current kvm_context
+ * \param vcpu Which virtual CPU should get dumped
+ * \return boolean indicating NMI injection readiness
+ */
+int kvm_is_ready_for_nmi_injection(kvm_context_t kvm, int vcpu);
+
+/*!
* \brief Read VCPU registers
*
* This gets the GP registers from the VCPU and outputs them
@@ -578,6 +590,17 @@ int kvm_set_lapic(kvm_context_t kvm, int vcpu, struct kvm_lapic_state *s);
#endif
+/*!
+ * \brief Simulate an NMI
+ *
+ * This allows you to simulate a non-maskable interrupt.
+ *
+ * \param kvm Pointer to the current kvm_context
+ * \param vcpu Which virtual CPU should get dumped
+ * \return 0 on success
+ */
+int kvm_inject_nmi(kvm_context_t kvm, int vcpu);
+
#endif
/*!