This removes the dependency on CONFIG_KVM. Signed-off-by: Avi Kivity <avi@xxxxxxxxxx> --- hw/msix.c | 137 ------------------------------------------------------------ kvm-all.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ kvm-stub.c | 28 ++++++++++++ kvm.h | 16 +++++++ 4 files changed, 168 insertions(+), 137 deletions(-) diff --git a/hw/msix.c b/hw/msix.c index dda1a24..bdec0b3 100644 --- a/hw/msix.c +++ b/hw/msix.c @@ -19,143 +19,6 @@ /* Flag for interrupt controller to declare MSI-X support */ int msix_supported; -#ifdef CONFIG_KVM -/* KVM specific MSIX helpers */ - -static void kvm_msix_init(PCIDevice *dev) -{ -#ifdef KVM_CAP_IRQCHIP - if (kvm_enabled() && kvm_irqchip_in_kernel()) { - dev->msix_irq_entries = qemu_malloc(dev->msix_entries_nr * - sizeof *dev->msix_irq_entries); - } -#endif -} - -static void kvm_msix_free(PCIDevice *dev) -{ - int vector, changed = 0; - for (vector = 0; vector < dev->msix_entries_nr; ++vector) { - if (dev->msix_entry_used[vector]) { - kvm_del_routing_entry(kvm_context, &dev->msix_irq_entries[vector]); - changed = 1; - } - } - if (changed) { - kvm_commit_irq_routes(kvm_context); - } -} - -static void kvm_msix_routing_entry(PCIDevice *dev, unsigned vector, - struct kvm_irq_routing_entry *entry) -{ - uint8_t *table_entry = dev->msix_table_page + vector * MSIX_ENTRY_SIZE; - entry->type = KVM_IRQ_ROUTING_MSI; - entry->flags = 0; - entry->u.msi.address_lo = pci_get_long(table_entry + MSIX_MSG_ADDR); - entry->u.msi.address_hi = pci_get_long(table_entry + MSIX_MSG_UPPER_ADDR); - entry->u.msi.data = pci_get_long(table_entry + MSIX_MSG_DATA); -} - -static void kvm_msix_update(PCIDevice *dev, int vector, - int was_masked, int is_masked) -{ - struct kvm_irq_routing_entry e = {}, *entry; - int mask_cleared = was_masked && !is_masked; - /* It is only legal to change an entry when it is masked. Therefore, it is - * enough to update the routing in kernel when mask is being cleared. */ - if (!mask_cleared) { - return; - } - if (!dev->msix_entry_used[vector]) { - return; - } - entry = dev->msix_irq_entries + vector; - e.gsi = entry->gsi; - kvm_msix_routing_entry(dev, vector, &e); - if (memcmp(&entry->u.msi, &e.u.msi, sizeof entry->u.msi)) { - int r; - r = kvm_update_routing_entry(kvm_context, entry, &e); - if (r) { - fprintf(stderr, "%s: kvm_update_routing_entry failed: %s\n", __func__, - strerror(-r)); - exit(1); - } - memcpy(&entry->u.msi, &e.u.msi, sizeof entry->u.msi); - r = kvm_commit_irq_routes(kvm_context); - if (r) { - fprintf(stderr, "%s: kvm_commit_irq_routes failed: %s\n", __func__, - strerror(-r)); - exit(1); - } - } -} - -static int kvm_msix_add(PCIDevice *dev, unsigned vector) -{ - struct kvm_irq_routing_entry *entry = dev->msix_irq_entries + vector; - int r; - - if (!kvm_has_gsi_routing(kvm_context)) { - fprintf(stderr, "Warning: no MSI-X support found. " - "At least kernel 2.6.30 is required for MSI-X support.\n" - ); - return -EOPNOTSUPP; - } - - r = kvm_get_irq_route_gsi(kvm_context); - if (r < 0) { - fprintf(stderr, "%s: kvm_get_irq_route_gsi failed: %s\n", __func__, strerror(-r)); - return r; - } - entry->gsi = r; - kvm_msix_routing_entry(dev, vector, entry); - r = kvm_add_routing_entry(kvm_context, entry); - if (r < 0) { - fprintf(stderr, "%s: kvm_add_routing_entry failed: %s\n", __func__, strerror(-r)); - return r; - } - - r = kvm_commit_irq_routes(kvm_context); - if (r < 0) { - fprintf(stderr, "%s: kvm_commit_irq_routes failed: %s\n", __func__, strerror(-r)); - return r; - } - return 0; -} - -static void kvm_msix_del(PCIDevice *dev, unsigned vector) -{ - if (dev->msix_entry_used[vector]) { - return; - } - kvm_del_routing_entry(kvm_context, &dev->msix_irq_entries[vector]); - kvm_commit_irq_routes(kvm_context); -} - -static bool kvm_msix_notify(PCIDevice *dev, unsigned vector) -{ -#ifdef KVM_CAP_IRQCHIP - if (kvm_enabled() && kvm_irqchip_in_kernel()) { - kvm_set_irq(dev->msix_irq_entries[vector].gsi, 1, NULL); - return true; - } -#endif - return false; -} - -#else - -static void kvm_msix_init(PCIDevice *dev) {} -static void kvm_msix_free(PCIDevice *dev) {} -static void kvm_msix_update(PCIDevice *dev, int vector, - int was_masked, int is_masked) {} -static int kvm_msix_add(PCIDevice *dev, unsigned vector) { return -1; } -static void kvm_msix_del(PCIDevice *dev, unsigned vector) {} -static bool kvm_msix_notify(PCIDevice *dev, unsigned vector) { return false; } - -#endif - /* Add MSI-X capability to the config space for the device. */ /* Given a bar and its size, add MSI-X table on top of it * and fill MSI-X capability in the config space. diff --git a/kvm-all.c b/kvm-all.c index d4b0861..0860a16 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -24,6 +24,8 @@ #include "qemu-barrier.h" #include "sysemu.h" #include "hw/hw.h" +#include "hw/pci.h" +#include "hw/msix.h" #include "gdbstub.h" #include "kvm.h" #include "bswap.h" @@ -1338,5 +1340,127 @@ int kvm_set_irqfd(int gsi, int fd, bool assigned) } #endif +void kvm_msix_init(PCIDevice *dev) +{ +#ifdef KVM_CAP_IRQCHIP + if (kvm_enabled() && kvm_irqchip_in_kernel()) { + dev->msix_irq_entries = qemu_malloc(dev->msix_entries_nr * + sizeof *dev->msix_irq_entries); + } +#endif +} + +void kvm_msix_free(PCIDevice *dev) +{ + int vector, changed = 0; + for (vector = 0; vector < dev->msix_entries_nr; ++vector) { + if (dev->msix_entry_used[vector]) { + kvm_del_routing_entry(kvm_context, &dev->msix_irq_entries[vector]); + changed = 1; + } + } + if (changed) { + kvm_commit_irq_routes(kvm_context); + } +} + +static void kvm_msix_routing_entry(PCIDevice *dev, unsigned vector, + struct kvm_irq_routing_entry *entry) +{ + uint8_t *table_entry = dev->msix_table_page + vector * MSIX_ENTRY_SIZE; + entry->type = KVM_IRQ_ROUTING_MSI; + entry->flags = 0; + entry->u.msi.address_lo = pci_get_long(table_entry + MSIX_MSG_ADDR); + entry->u.msi.address_hi = pci_get_long(table_entry + MSIX_MSG_UPPER_ADDR); + entry->u.msi.data = pci_get_long(table_entry + MSIX_MSG_DATA); +} + +void kvm_msix_update(PCIDevice *dev, int vector, + int was_masked, int is_masked) +{ + struct kvm_irq_routing_entry e = {}, *entry; + int mask_cleared = was_masked && !is_masked; + /* It is only legal to change an entry when it is masked. Therefore, it is + * enough to update the routing in kernel when mask is being cleared. */ + if (!mask_cleared) { + return; + } + if (!dev->msix_entry_used[vector]) { + return; + } + entry = dev->msix_irq_entries + vector; + e.gsi = entry->gsi; + kvm_msix_routing_entry(dev, vector, &e); + if (memcmp(&entry->u.msi, &e.u.msi, sizeof entry->u.msi)) { + int r; + r = kvm_update_routing_entry(kvm_context, entry, &e); + if (r) { + fprintf(stderr, "%s: kvm_update_routing_entry failed: %s\n", __func__, + strerror(-r)); + exit(1); + } + memcpy(&entry->u.msi, &e.u.msi, sizeof entry->u.msi); + r = kvm_commit_irq_routes(kvm_context); + if (r) { + fprintf(stderr, "%s: kvm_commit_irq_routes failed: %s\n", __func__, + strerror(-r)); + exit(1); + } + } +} + +int kvm_msix_add(PCIDevice *dev, unsigned vector) +{ + struct kvm_irq_routing_entry *entry = dev->msix_irq_entries + vector; + int r; + + if (!kvm_has_gsi_routing(kvm_context)) { + fprintf(stderr, "Warning: no MSI-X support found. " + "At least kernel 2.6.30 is required for MSI-X support.\n" + ); + return -EOPNOTSUPP; + } + + r = kvm_get_irq_route_gsi(kvm_context); + if (r < 0) { + fprintf(stderr, "%s: kvm_get_irq_route_gsi failed: %s\n", __func__, strerror(-r)); + return r; + } + entry->gsi = r; + kvm_msix_routing_entry(dev, vector, entry); + r = kvm_add_routing_entry(kvm_context, entry); + if (r < 0) { + fprintf(stderr, "%s: kvm_add_routing_entry failed: %s\n", __func__, strerror(-r)); + return r; + } + + r = kvm_commit_irq_routes(kvm_context); + if (r < 0) { + fprintf(stderr, "%s: kvm_commit_irq_routes failed: %s\n", __func__, strerror(-r)); + return r; + } + return 0; +} + +void kvm_msix_del(PCIDevice *dev, unsigned vector) +{ + if (dev->msix_entry_used[vector]) { + return; + } + kvm_del_routing_entry(kvm_context, &dev->msix_irq_entries[vector]); + kvm_commit_irq_routes(kvm_context); +} + +bool kvm_msix_notify(PCIDevice *dev, unsigned vector) +{ +#ifdef KVM_CAP_IRQCHIP + if (kvm_enabled() && kvm_irqchip_in_kernel()) { + kvm_set_irq(dev->msix_irq_entries[vector].gsi, 1, NULL); + return true; + } +#endif + return false; +} + #undef PAGE_SIZE #include "qemu-kvm.c" diff --git a/kvm-stub.c b/kvm-stub.c index d45f9fa..1c54020 100644 --- a/kvm-stub.c +++ b/kvm-stub.c @@ -13,6 +13,7 @@ #include "qemu-common.h" #include "sysemu.h" #include "hw/hw.h" +#include "hw/pci.h" #include "exec-all.h" #include "gdbstub.h" #include "kvm.h" @@ -141,3 +142,30 @@ int kvm_set_ioeventfd_mmio_long(int fd, uint32_t adr, uint32_t val, bool assign) { return -ENOSYS; } + +void kvm_msix_init(PCIDevice *dev) +{ +} + +void kvm_msix_free(PCIDevice *dev) +{ +} + +void kvm_msix_update(PCIDevice *dev, int vector, + int was_masked, int is_masked) +{ +} + +int kvm_msix_add(PCIDevice *dev, unsigned vector) +{ + return -1; +} + +void kvm_msix_del(PCIDevice *dev, unsigned vector) +{ +} + +bool kvm_msix_notify(PCIDevice *dev, unsigned vector) +{ + return false; +} diff --git a/kvm.h b/kvm.h index 56236ae..62dc039 100644 --- a/kvm.h +++ b/kvm.h @@ -18,6 +18,9 @@ #include "config-host.h" #include "qemu-queue.h" #include "qemu-kvm.h" +#ifndef __DYNGEN_EXEC_H__ +#include "hw/pci.h" +#endif #ifdef CONFIG_KVM #include <linux/kvm.h> @@ -194,5 +197,18 @@ int kvm_set_irqfd(int gsi, int fd, bool assigned) } #endif +#ifndef __DYNGEN_EXEC_H__ + int kvm_set_ioeventfd_pio_word(int fd, uint16_t adr, uint16_t val, bool assign); + +void kvm_msix_init(PCIDevice *dev); +void kvm_msix_free(PCIDevice *dev); +void kvm_msix_update(PCIDevice *dev, int vector, + int was_masked, int is_masked); +int kvm_msix_add(PCIDevice *dev, unsigned vector); +void kvm_msix_del(PCIDevice *dev, unsigned vector); +bool kvm_msix_notify(PCIDevice *dev, unsigned vector); + +#endif + #endif -- 1.7.2.3 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html