^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * irq.c: API for in kernel interrupt controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (c) 2007, Intel Corporation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 2009 Red Hat, Inc. and/or its affiliates.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Authors:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Yaozu (Eddie) Dong <Eddie.dong@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/kvm_host.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "irq.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "i8254.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "x86.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * check if there are pending timer events
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * to be processed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) if (lapic_in_kernel(vcpu))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) return apic_has_pending_timer(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) EXPORT_SYMBOL(kvm_cpu_has_pending_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * check if there is a pending userspace external interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static int pending_userspace_extint(struct kvm_vcpu *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) return v->arch.pending_external_vector != -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * check if there is pending interrupt from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * non-APIC source without intack.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) int kvm_cpu_has_extint(struct kvm_vcpu *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * FIXME: interrupt.injected represents an interrupt whose
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * side-effects have already been applied (e.g. bit from IRR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * already moved to ISR). Therefore, it is incorrect to rely
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * on interrupt.injected to know if there is a pending
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * interrupt in the user-mode LAPIC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * This leads to nVMX/nSVM not be able to distinguish
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * if it should exit from L2 to L1 on EXTERNAL_INTERRUPT on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * pending interrupt or should re-inject an injected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (!lapic_in_kernel(v))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return v->arch.interrupt.injected;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (!kvm_apic_accept_pic_intr(v))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (irqchip_split(v->kvm))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return pending_userspace_extint(v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return v->kvm->arch.vpic->output;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * check if there is injectable interrupt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * when virtual interrupt delivery enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * interrupt from apic will handled by hardware,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * we don't need to check it here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (kvm_cpu_has_extint(v))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (!is_guest_mode(v) && kvm_vcpu_apicv_active(v))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return kvm_apic_has_interrupt(v) != -1; /* LAPIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) EXPORT_SYMBOL_GPL(kvm_cpu_has_injectable_intr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * check if there is pending interrupt without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * intack.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) int kvm_cpu_has_interrupt(struct kvm_vcpu *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (kvm_cpu_has_extint(v))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return kvm_apic_has_interrupt(v) != -1; /* LAPIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) EXPORT_SYMBOL_GPL(kvm_cpu_has_interrupt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * Read pending interrupt(from non-APIC source)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * vector and intack.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static int kvm_cpu_get_extint(struct kvm_vcpu *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (!kvm_cpu_has_extint(v)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) WARN_ON(!lapic_in_kernel(v));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (!lapic_in_kernel(v))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return v->arch.interrupt.nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (irqchip_split(v->kvm)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) int vector = v->arch.pending_external_vector;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) v->arch.pending_external_vector = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return vector;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return kvm_pic_read_irq(v->kvm); /* PIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * Read pending interrupt vector and intack.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) int kvm_cpu_get_interrupt(struct kvm_vcpu *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) int vector = kvm_cpu_get_extint(v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (vector != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return vector; /* PIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) return kvm_get_apic_interrupt(v); /* APIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) EXPORT_SYMBOL_GPL(kvm_cpu_get_interrupt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (lapic_in_kernel(vcpu))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) kvm_inject_apic_timer_irqs(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) EXPORT_SYMBOL_GPL(kvm_inject_pending_timer_irqs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) void __kvm_migrate_timers(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) __kvm_migrate_apic_timer(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) __kvm_migrate_pit_timer(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (kvm_x86_ops.migrate_timers)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) kvm_x86_ops.migrate_timers(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) bool kvm_arch_irqfd_allowed(struct kvm *kvm, struct kvm_irqfd *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) bool resample = args->flags & KVM_IRQFD_FLAG_RESAMPLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return resample ? irqchip_kernel(kvm) : irqchip_in_kernel(kvm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }