root/arch/x86/kvm/irq.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. kvm_cpu_has_pending_timer
  2. pending_userspace_extint
  3. kvm_cpu_has_extint
  4. kvm_cpu_has_injectable_intr
  5. kvm_cpu_has_interrupt
  6. kvm_cpu_get_extint
  7. kvm_cpu_get_interrupt
  8. kvm_inject_pending_timer_irqs
  9. __kvm_migrate_timers
  10. kvm_arch_irqfd_allowed

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

/* [<][>][^][v][top][bottom][index][help] */