diff --git a/hypervisor/arch/x86/guest/virq.c b/hypervisor/arch/x86/guest/virq.c index a0be3c3d8..f6ed5a9f8 100644 --- a/hypervisor/arch/x86/guest/virq.c +++ b/hypervisor/arch/x86/guest/virq.c @@ -202,7 +202,20 @@ int32_t vcpu_queue_exception(struct acrn_vcpu *vcpu, uint32_t vector_arg, uint32 } else { arch->exception_info.error = 0U; } - vcpu_make_request(vcpu, ACRN_REQUEST_EXCP); + + if ((vector == IDT_NMI) && is_notification_nmi(vcpu->vm)) { + /* + * Currently, ACRN doesn't support vNMI well and there is no well-designed + * way to check if the NMI is for notification or not. Here we take all the + * NMIs as notification NMI for lapic-pt VMs temporarily. + * + * TODO: Add a way in is_notification_nmi to check the NMI is for notification + * or not in order to support vNMI. + */ + pr_dbg("This NMI is used as notification signal. So ignore it."); + } else { + vcpu_make_request(vcpu, ACRN_REQUEST_EXCP); + } } } diff --git a/hypervisor/arch/x86/guest/vmexit.c b/hypervisor/arch/x86/guest/vmexit.c index 43c979f80..8042e1191 100644 --- a/hypervisor/arch/x86/guest/vmexit.c +++ b/hypervisor/arch/x86/guest/vmexit.c @@ -194,8 +194,20 @@ int32_t vmexit_handler(struct acrn_vcpu *vcpu) (void)vcpu_queue_exception(vcpu, vector, err_code); vcpu->arch.idt_vectoring_info = 0U; } else if (type == VMX_INT_TYPE_NMI) { - vcpu_make_request(vcpu, ACRN_REQUEST_NMI); - vcpu->arch.idt_vectoring_info = 0U; + if (is_notification_nmi(vcpu->vm)) { + /* + * Currently, ACRN doesn't support vNMI well and there is no well-designed + * way to check if the NMI is for notification or not. Here we take all the + * NMIs as notification NMI for lapic-pt VMs temporarily. + * + * TODO: Add a way in is_notification_nmi to check the NMI is for notification + * or not in order to support vNMI. + */ + pr_dbg("This NMI is used as notification signal. So ignore it."); + } else { + vcpu_make_request(vcpu, ACRN_REQUEST_NMI); + vcpu->arch.idt_vectoring_info = 0U; + } } else { /* No action on EXT_INT or SW exception. */ } diff --git a/hypervisor/arch/x86/notify.c b/hypervisor/arch/x86/notify.c index 6c8aafd02..c56bb3cf1 100644 --- a/hypervisor/arch/x86/notify.c +++ b/hypervisor/arch/x86/notify.c @@ -12,6 +12,7 @@ #include #include #include +#include static uint32_t notification_irq = IRQ_INVALID; @@ -114,3 +115,25 @@ void setup_posted_intr_notification(void) pr_err("Failed to setup posted-intr notification"); } } + +/** + * @brief Check if the NMI is for notification purpose + * + * @return true, if the NMI is triggered for notifying vCPU + * @return false, if the NMI is triggered for other purpose + */ +bool is_notification_nmi(const struct acrn_vm *vm) +{ + bool ret; + + /* + * Currently, ACRN doesn't support vNMI well and there is no well-designed + * way to check if the NMI is for notification or not. Here we take all the + * NMIs as notification NMI for lapic-pt VMs temporarily. + * + * TODO: Add a way to check the NMI is for notification or not in order to support vNMI. + */ + ret = is_lapic_pt_configured(vm); + + return ret; +} diff --git a/hypervisor/include/arch/x86/irq.h b/hypervisor/include/arch/x86/irq.h index cb8a7c612..4eac7dce7 100644 --- a/hypervisor/include/arch/x86/irq.h +++ b/hypervisor/include/arch/x86/irq.h @@ -65,6 +65,7 @@ #define IRQF_PT (1U << 2U) /* 1: for passthrough dev */ struct acrn_vcpu; +struct acrn_vm; /* * Definition of the stack frame layout @@ -87,6 +88,7 @@ struct smp_call_info_data { }; void smp_call_function(uint64_t mask, smp_call_func_t func, void *data); +bool is_notification_nmi(const struct acrn_vm *vm); void init_default_irqs(uint16_t cpu_id);