From d26d8bec015bb1d815361b132ea32de41d776770 Mon Sep 17 00:00:00 2001 From: Kaige Fu Date: Wed, 11 Dec 2019 19:45:54 +0000 Subject: [PATCH] HV: Don't make NMI injection req when notifying vCPU The NMI for notification should not be inject to guest. So, this patch drops NMI injection request when we use NMI to notify vCPUs. Meanwhile, ACRN doesn't support vNMI well and there is no well-designed way to check if the NMI is for notification or for guest now. So, we take all the NMIs as notificaton NMI for hard rtvm temporarily. It means that the hard rtvm will never receive NMI with this patch applied. TODO: vNMI support is not ready yet. we will add it later. Tracked-On: #3886 Signed-off-by: Kaige Fu --- hypervisor/arch/x86/guest/virq.c | 15 ++++++++++++++- hypervisor/arch/x86/guest/vmexit.c | 16 ++++++++++++++-- hypervisor/arch/x86/notify.c | 23 +++++++++++++++++++++++ hypervisor/include/arch/x86/irq.h | 2 ++ 4 files changed, 53 insertions(+), 3 deletions(-) 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);