|
51 | 51 | #include <linux/pci.h> |
52 | 52 | #include <linux/timekeeper_internal.h> |
53 | 53 | #include <linux/pvclock_gtod.h> |
| 54 | +#include <linux/kvm_irqfd.h> |
| 55 | +#include <linux/irqbypass.h> |
54 | 56 | #include <trace/events/kvm.h> |
55 | 57 |
|
56 | 58 | #define CREATE_TRACE_POINTS |
@@ -8079,6 +8081,57 @@ bool kvm_arch_has_noncoherent_dma(struct kvm *kvm) |
8079 | 8081 | } |
8080 | 8082 | EXPORT_SYMBOL_GPL(kvm_arch_has_noncoherent_dma); |
8081 | 8083 |
|
| 8084 | +int kvm_arch_irq_bypass_add_producer(struct irq_bypass_consumer *cons, |
| 8085 | + struct irq_bypass_producer *prod) |
| 8086 | +{ |
| 8087 | + struct kvm_kernel_irqfd *irqfd = |
| 8088 | + container_of(cons, struct kvm_kernel_irqfd, consumer); |
| 8089 | + |
| 8090 | + if (kvm_x86_ops->update_pi_irte) { |
| 8091 | + irqfd->producer = prod; |
| 8092 | + return kvm_x86_ops->update_pi_irte(irqfd->kvm, |
| 8093 | + prod->irq, irqfd->gsi, 1); |
| 8094 | + } |
| 8095 | + |
| 8096 | + return -EINVAL; |
| 8097 | +} |
| 8098 | + |
| 8099 | +void kvm_arch_irq_bypass_del_producer(struct irq_bypass_consumer *cons, |
| 8100 | + struct irq_bypass_producer *prod) |
| 8101 | +{ |
| 8102 | + int ret; |
| 8103 | + struct kvm_kernel_irqfd *irqfd = |
| 8104 | + container_of(cons, struct kvm_kernel_irqfd, consumer); |
| 8105 | + |
| 8106 | + if (!kvm_x86_ops->update_pi_irte) { |
| 8107 | + WARN_ON(irqfd->producer != NULL); |
| 8108 | + return; |
| 8109 | + } |
| 8110 | + |
| 8111 | + WARN_ON(irqfd->producer != prod); |
| 8112 | + irqfd->producer = NULL; |
| 8113 | + |
| 8114 | + /* |
| 8115 | + * When producer of consumer is unregistered, we change back to |
| 8116 | + * remapped mode, so we can re-use the current implementation |
| 8117 | + * when the irq is masked/disabed or the consumer side (KVM |
| 8118 | + * int this case doesn't want to receive the interrupts. |
| 8119 | + */ |
| 8120 | + ret = kvm_x86_ops->update_pi_irte(irqfd->kvm, prod->irq, irqfd->gsi, 0); |
| 8121 | + if (ret) |
| 8122 | + printk(KERN_INFO "irq bypass consumer (token %p) unregistration" |
| 8123 | + " fails: %d\n", irqfd->consumer.token, ret); |
| 8124 | +} |
| 8125 | + |
| 8126 | +int kvm_arch_update_irqfd_routing(struct kvm *kvm, unsigned int host_irq, |
| 8127 | + uint32_t guest_irq, bool set) |
| 8128 | +{ |
| 8129 | + if (!kvm_x86_ops->update_pi_irte) |
| 8130 | + return -EINVAL; |
| 8131 | + |
| 8132 | + return kvm_x86_ops->update_pi_irte(kvm, host_irq, guest_irq, set); |
| 8133 | +} |
| 8134 | + |
8082 | 8135 | EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_exit); |
8083 | 8136 | EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_fast_mmio); |
8084 | 8137 | EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_inj_virq); |
|
0 commit comments