From: Xiong Zhang xiong.y.zhang@linux.intel.com
KVM will register irq handler for POSTED_INTR_WAKEUP_VECTOR and KVM_GUEST_PMI_VECTOR, the existing kvm_set_posted_intr_wakeup_handler() is renamed to x86_set_kvm_irq_handler(), and vector input parameter is used to distinguish POSTED_INTR_WARKUP_VECTOR and KVM_GUEST_PMI_VECTOR.
Caller should call x86_set_kvm_irq_handler() once to register a non-dummy handler for each vector. If caller register one handler for a vector, later the caller register the same or different non-dummy handler again, the second call will output warn message.
Suggested-by: Sean Christopherson seanjc@google.com Signed-off-by: Xiong Zhang xiong.y.zhang@linux.intel.com Tested-by: Yongwei Ma yongwei.ma@intel.com Signed-off-by: Mingwei Zhang mizhang@google.com --- arch/x86/include/asm/irq.h | 2 +- arch/x86/kernel/irq.c | 18 ++++++++++++------ arch/x86/kvm/vmx/vmx.c | 4 ++-- 3 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h index 194dfff84cb1..050a247b69b4 100644 --- a/arch/x86/include/asm/irq.h +++ b/arch/x86/include/asm/irq.h @@ -30,7 +30,7 @@ struct irq_desc; extern void fixup_irqs(void);
#if IS_ENABLED(CONFIG_KVM) -extern void kvm_set_posted_intr_wakeup_handler(void (*handler)(void)); +void x86_set_kvm_irq_handler(u8 vector, void (*handler)(void)); #endif
extern void (*x86_platform_ipi_callback)(void); diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index 385e3a5fc304..18cd418fe106 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c @@ -312,16 +312,22 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_x86_platform_ipi) static void dummy_handler(void) {} static void (*kvm_posted_intr_wakeup_handler)(void) = dummy_handler;
-void kvm_set_posted_intr_wakeup_handler(void (*handler)(void)) +void x86_set_kvm_irq_handler(u8 vector, void (*handler)(void)) { - if (handler) + if (!handler) + handler = dummy_handler; + + if (vector == POSTED_INTR_WAKEUP_VECTOR && + (handler == dummy_handler || + kvm_posted_intr_wakeup_handler == dummy_handler)) kvm_posted_intr_wakeup_handler = handler; - else { - kvm_posted_intr_wakeup_handler = dummy_handler; + else + WARN_ON_ONCE(1); + + if (handler == dummy_handler) synchronize_rcu(); - } } -EXPORT_SYMBOL_GPL(kvm_set_posted_intr_wakeup_handler); +EXPORT_SYMBOL_GPL(x86_set_kvm_irq_handler);
/* * Handler for POSTED_INTERRUPT_VECTOR. diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 6c56d5235f0f..00ac94535c21 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -8279,7 +8279,7 @@ void vmx_migrate_timers(struct kvm_vcpu *vcpu)
void vmx_hardware_unsetup(void) { - kvm_set_posted_intr_wakeup_handler(NULL); + x86_set_kvm_irq_handler(POSTED_INTR_WAKEUP_VECTOR, NULL);
if (nested) nested_vmx_hardware_unsetup(); @@ -8583,7 +8583,7 @@ __init int vmx_hardware_setup(void) if (r && nested) nested_vmx_hardware_unsetup();
- kvm_set_posted_intr_wakeup_handler(pi_wakeup_handler); + x86_set_kvm_irq_handler(POSTED_INTR_WAKEUP_VECTOR, pi_wakeup_handler);
return r; }