mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-22 00:40:03 +00:00
![Alex Williamson](/assets/img/avatar_default.png)
When a physical I/O device is assigned to a virtual machine through facilities like VFIO and KVM, the interrupt for the device generally bounces through the host system before being injected into the VM. However, hardware technologies exist that often allow the host to be bypassed for some of these scenarios. Intel Posted Interrupts allow the specified physical edge interrupts to be directly injected into a guest when delivered to a physical processor while the vCPU is running. ARM IRQ Forwarding allows forwarded physical interrupts to be directly deactivated by the guest. The IRQ bypass manager here is meant to provide the shim to connect interrupt producers, generally the host physical device driver, with interrupt consumers, generally the hypervisor, in order to configure these bypass mechanism. To do this, we base the connection on a shared, opaque token. For KVM-VFIO this is expected to be an eventfd_ctx since this is the connection we already use to connect an eventfd to an irqfd on the in-kernel path. When a producer and consumer with matching tokens is found, callbacks via both registered participants allow the bypass facilities to be automatically enabled. Signed-off-by: Alex Williamson <alex.williamson@redhat.com> Reviewed-by: Eric Auger <eric.auger@linaro.org> Tested-by: Eric Auger <eric.auger@linaro.org> Tested-by: Feng Wu <feng.wu@intel.com> Signed-off-by: Feng Wu <feng.wu@intel.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
90 lines
3.6 KiB
C
90 lines
3.6 KiB
C
/*
|
|
* IRQ offload/bypass manager
|
|
*
|
|
* Copyright (C) 2015 Red Hat, Inc.
|
|
* Copyright (c) 2015 Linaro Ltd.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*/
|
|
#ifndef IRQBYPASS_H
|
|
#define IRQBYPASS_H
|
|
|
|
#include <linux/list.h>
|
|
|
|
struct irq_bypass_consumer;
|
|
|
|
/*
|
|
* Theory of operation
|
|
*
|
|
* The IRQ bypass manager is a simple set of lists and callbacks that allows
|
|
* IRQ producers (ex. physical interrupt sources) to be matched to IRQ
|
|
* consumers (ex. virtualization hardware that allows IRQ bypass or offload)
|
|
* via a shared token (ex. eventfd_ctx). Producers and consumers register
|
|
* independently. When a token match is found, the optional @stop callback
|
|
* will be called for each participant. The pair will then be connected via
|
|
* the @add_* callbacks, and finally the optional @start callback will allow
|
|
* any final coordination. When either participant is unregistered, the
|
|
* process is repeated using the @del_* callbacks in place of the @add_*
|
|
* callbacks. Match tokens must be unique per producer/consumer, 1:N pairings
|
|
* are not supported.
|
|
*/
|
|
|
|
/**
|
|
* struct irq_bypass_producer - IRQ bypass producer definition
|
|
* @node: IRQ bypass manager private list management
|
|
* @token: opaque token to match between producer and consumer
|
|
* @irq: Linux IRQ number for the producer device
|
|
* @add_consumer: Connect the IRQ producer to an IRQ consumer (optional)
|
|
* @del_consumer: Disconnect the IRQ producer from an IRQ consumer (optional)
|
|
* @stop: Perform any quiesce operations necessary prior to add/del (optional)
|
|
* @start: Perform any startup operations necessary after add/del (optional)
|
|
*
|
|
* The IRQ bypass producer structure represents an interrupt source for
|
|
* participation in possible host bypass, for instance an interrupt vector
|
|
* for a physical device assigned to a VM.
|
|
*/
|
|
struct irq_bypass_producer {
|
|
struct list_head node;
|
|
void *token;
|
|
int irq;
|
|
int (*add_consumer)(struct irq_bypass_producer *,
|
|
struct irq_bypass_consumer *);
|
|
void (*del_consumer)(struct irq_bypass_producer *,
|
|
struct irq_bypass_consumer *);
|
|
void (*stop)(struct irq_bypass_producer *);
|
|
void (*start)(struct irq_bypass_producer *);
|
|
};
|
|
|
|
/**
|
|
* struct irq_bypass_consumer - IRQ bypass consumer definition
|
|
* @node: IRQ bypass manager private list management
|
|
* @token: opaque token to match between producer and consumer
|
|
* @add_producer: Connect the IRQ consumer to an IRQ producer
|
|
* @del_producer: Disconnect the IRQ consumer from an IRQ producer
|
|
* @stop: Perform any quiesce operations necessary prior to add/del (optional)
|
|
* @start: Perform any startup operations necessary after add/del (optional)
|
|
*
|
|
* The IRQ bypass consumer structure represents an interrupt sink for
|
|
* participation in possible host bypass, for instance a hypervisor may
|
|
* support offloads to allow bypassing the host entirely or offload
|
|
* portions of the interrupt handling to the VM.
|
|
*/
|
|
struct irq_bypass_consumer {
|
|
struct list_head node;
|
|
void *token;
|
|
int (*add_producer)(struct irq_bypass_consumer *,
|
|
struct irq_bypass_producer *);
|
|
void (*del_producer)(struct irq_bypass_consumer *,
|
|
struct irq_bypass_producer *);
|
|
void (*stop)(struct irq_bypass_consumer *);
|
|
void (*start)(struct irq_bypass_consumer *);
|
|
};
|
|
|
|
int irq_bypass_register_producer(struct irq_bypass_producer *);
|
|
void irq_bypass_unregister_producer(struct irq_bypass_producer *);
|
|
int irq_bypass_register_consumer(struct irq_bypass_consumer *);
|
|
void irq_bypass_unregister_consumer(struct irq_bypass_consumer *);
|
|
|
|
#endif /* IRQBYPASS_H */
|