diff options
Diffstat (limited to 'libkvm')
-rw-r--r-- | libkvm/libkvm.c | 31 | ||||
-rw-r--r-- | libkvm/libkvm.h | 23 |
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 /*! |