/* SPDX-License-Identifier: GPL-2.0 */12#include <linux/entry-common.h>3#include <linux/kvm_types.h>4#include <linux/hrtimer_rearm.h>5#include <asm/fred.h>6#include <asm/desc.h>78#if IS_ENABLED(CONFIG_KVM_INTEL)9/*10* On VMX, NMIs and IRQs (as configured by KVM) are acknowledged by hardware as11* part of the VM-Exit, i.e. the event itself is consumed as part the VM-Exit.12* x86_entry_from_kvm() is invoked by KVM to effectively forward NMIs and IRQs13* to the kernel for servicing. On SVM, a.k.a. AMD, the NMI/IRQ VM-Exit is14* purely a signal that an NMI/IRQ is pending, i.e. the event that triggered15* the VM-Exit is held pending until it's unblocked in the host.16*/17noinstr void x86_entry_from_kvm(unsigned int event_type, unsigned int vector)18{19if (event_type == EVENT_TYPE_EXTINT) {20#ifdef CONFIG_X86_6421/*22* Use FRED dispatch, even when running IDT. The dispatch23* tables are kept in sync between FRED and IDT, and the FRED24* dispatch works well with CFI.25*/26fred_entry_from_kvm(event_type, vector);27#else28idt_entry_from_kvm(vector);29#endif30/*31* Strictly speaking, only the NMI path requires noinstr.32*/33instrumentation_begin();34/*35* KVM/VMX will dispatch from IRQ-disabled but for a context36* that will have IRQs-enabled. This confuses the entry code37* and it will not have reprogrammed the timer. Do so now.38*/39hrtimer_rearm_deferred();40instrumentation_end();4142return;43}4445WARN_ON_ONCE(event_type != EVENT_TYPE_NMI);4647#ifdef CONFIG_X86_6448if (cpu_feature_enabled(X86_FEATURE_FRED))49return fred_entry_from_kvm(event_type, vector);50#endif5152/*53* Notably, we must use IDT dispatch for NMI when running in IDT mode.54* The FRED NMI context is significantly different and will not work55* right (specifically FRED fixed the NMI recursion issue).56*/57idt_entry_from_kvm(vector);58}59EXPORT_SYMBOL_FOR_KVM(x86_entry_from_kvm);60#endif616263