mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-02 23:33:54 -06:00
multi-process: create IOHUB object to handle irq
IOHUB object is added to manage PCI IRQs. It uses KVM_IRQFD ioctl to create irqfd to injecting PCI interrupts to the guest. IOHUB object forwards the irqfd to the remote process. Remote process uses this fd to directly send interrupts to the guest, bypassing QEMU. Signed-off-by: John G Johnson <john.g.johnson@oracle.com> Signed-off-by: Jagannathan Raman <jag.raman@oracle.com> Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Message-id: 51d5c3d54e28a68b002e3875c59599c9f5a424a1.1611938319.git.jag.raman@oracle.com Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
parent
c746b74a7d
commit
bd36adb8df
12 changed files with 249 additions and 0 deletions
|
@ -21,6 +21,57 @@
|
|||
#include "qemu/error-report.h"
|
||||
#include "hw/remote/proxy-memory-listener.h"
|
||||
#include "qom/object.h"
|
||||
#include "qemu/event_notifier.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "util/event_notifier-posix.c"
|
||||
|
||||
static void proxy_intx_update(PCIDevice *pci_dev)
|
||||
{
|
||||
PCIProxyDev *dev = PCI_PROXY_DEV(pci_dev);
|
||||
PCIINTxRoute route;
|
||||
int pin = pci_get_byte(pci_dev->config + PCI_INTERRUPT_PIN) - 1;
|
||||
|
||||
if (dev->virq != -1) {
|
||||
kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, &dev->intr, dev->virq);
|
||||
dev->virq = -1;
|
||||
}
|
||||
|
||||
route = pci_device_route_intx_to_irq(pci_dev, pin);
|
||||
|
||||
dev->virq = route.irq;
|
||||
|
||||
if (dev->virq != -1) {
|
||||
kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, &dev->intr,
|
||||
&dev->resample, dev->virq);
|
||||
}
|
||||
}
|
||||
|
||||
static void setup_irqfd(PCIProxyDev *dev)
|
||||
{
|
||||
PCIDevice *pci_dev = PCI_DEVICE(dev);
|
||||
MPQemuMsg msg;
|
||||
Error *local_err = NULL;
|
||||
|
||||
event_notifier_init(&dev->intr, 0);
|
||||
event_notifier_init(&dev->resample, 0);
|
||||
|
||||
memset(&msg, 0, sizeof(MPQemuMsg));
|
||||
msg.cmd = MPQEMU_CMD_SET_IRQFD;
|
||||
msg.num_fds = 2;
|
||||
msg.fds[0] = event_notifier_get_fd(&dev->intr);
|
||||
msg.fds[1] = event_notifier_get_fd(&dev->resample);
|
||||
msg.size = 0;
|
||||
|
||||
if (!mpqemu_msg_send(&msg, dev->ioc, &local_err)) {
|
||||
error_report_err(local_err);
|
||||
}
|
||||
|
||||
dev->virq = -1;
|
||||
|
||||
proxy_intx_update(pci_dev);
|
||||
|
||||
pci_device_set_intx_routing_notifier(pci_dev, proxy_intx_update);
|
||||
}
|
||||
|
||||
static void pci_proxy_dev_realize(PCIDevice *device, Error **errp)
|
||||
{
|
||||
|
@ -56,6 +107,8 @@ static void pci_proxy_dev_realize(PCIDevice *device, Error **errp)
|
|||
qio_channel_set_blocking(dev->ioc, true, NULL);
|
||||
|
||||
proxy_memory_listener_configure(&dev->proxy_listener, dev->ioc);
|
||||
|
||||
setup_irqfd(dev);
|
||||
}
|
||||
|
||||
static void pci_proxy_dev_exit(PCIDevice *pdev)
|
||||
|
@ -71,6 +124,9 @@ static void pci_proxy_dev_exit(PCIDevice *pdev)
|
|||
error_free(dev->migration_blocker);
|
||||
|
||||
proxy_memory_listener_deconfigure(&dev->proxy_listener);
|
||||
|
||||
event_notifier_cleanup(&dev->intr);
|
||||
event_notifier_cleanup(&dev->resample);
|
||||
}
|
||||
|
||||
static void config_op_send(PCIProxyDev *pdev, uint32_t addr, uint32_t *val,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue