From 3ed444e949cd2f0938759836c0991dfabe86f485 Mon Sep 17 00:00:00 2001 From: Dunrong Huang Date: Tue, 31 Jul 2012 19:18:17 +0800 Subject: [PATCH 1/9] kvm: Check if smp_cpus exceeds max cpus supported by kvm Add a helper function for fetching max cpus supported by kvm. Make QEMU exit with an error message if smp_cpus exceeds limit of VCPU count retrieved by invoking this helper function. Signed-off-by: Dunrong Huang Signed-off-by: Marcelo Tosatti Signed-off-by: Avi Kivity --- kvm-all.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/kvm-all.c b/kvm-all.c index 2148b20bdb..bf647614e8 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -1207,6 +1207,26 @@ static int kvm_irqchip_create(KVMState *s) return 0; } +static int kvm_max_vcpus(KVMState *s) +{ + int ret; + + /* Find number of supported CPUs using the recommended + * procedure from the kernel API documentation to cope with + * older kernels that may be missing capabilities. + */ + ret = kvm_check_extension(s, KVM_CAP_MAX_VCPUS); + if (ret) { + return ret; + } + ret = kvm_check_extension(s, KVM_CAP_NR_VCPUS); + if (ret) { + return ret; + } + + return 4; +} + int kvm_init(void) { static const char upgrade_note[] = @@ -1216,6 +1236,7 @@ int kvm_init(void) const KVMCapabilityInfo *missing_cap; int ret; int i; + int max_vcpus; s = g_malloc0(sizeof(KVMState)); @@ -1256,6 +1277,14 @@ int kvm_init(void) goto err; } + max_vcpus = kvm_max_vcpus(s); + if (smp_cpus > max_vcpus) { + ret = -EINVAL; + fprintf(stderr, "Number of SMP cpus requested (%d) exceeds max cpus " + "supported by KVM (%d)\n", smp_cpus, max_vcpus); + goto err; + } + s->vmfd = kvm_ioctl(s, KVM_CREATE_VM, 0); if (s->vmfd < 0) { #ifdef TARGET_S390X From 08312a63b77df45ad056d2e8d9e2cbe8f683a23c Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 3 Aug 2012 13:51:25 +0100 Subject: [PATCH 2/9] configure: Don't implicitly hardcode list of KVM architectures The code creating the symlink from linux-headers/asm to the architecture specific linux-headers/asm-$arch directory was implicitly hardcoding a list of KVM supporting architectures. Add a default case for the common "Linux architecture name and QEMU CPU name match" case, so future architectures will only need to add code if they've managed to get mismatched names. Signed-off-by: Peter Maydell Signed-off-by: Marcelo Tosatti Signed-off-by: Avi Kivity --- configure | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/configure b/configure index 280726c3f8..b9a0b2741e 100755 --- a/configure +++ b/configure @@ -3538,15 +3538,23 @@ if test "$linux" = "yes" ; then mkdir -p linux-headers case "$cpu" in i386|x86_64) - symlink "$source_path/linux-headers/asm-x86" linux-headers/asm + linux_arch=x86 ;; ppcemb|ppc|ppc64) - symlink "$source_path/linux-headers/asm-powerpc" linux-headers/asm + linux_arch=powerpc ;; s390x) - symlink "$source_path/linux-headers/asm-s390" linux-headers/asm + linux_arch=s390 + ;; + *) + # For most CPUs the kernel architecture name and QEMU CPU name match. + linux_arch="$cpu" ;; esac + # For non-KVM architectures we will not have asm headers + if [ -e "$source_path/linux-headers/asm-$linux_arch" ]; then + symlink "$source_path/linux-headers/asm-$linux_arch" linux-headers/asm + fi fi for target in $target_list; do From 7ae26bd484a50810f8d29cb5399bc48108e50bec Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 26 Jul 2012 15:35:11 +0100 Subject: [PATCH 3/9] kvm: Decouple 'async interrupt delivery' from 'kernel irqchip' On x86 userspace delivers interrupts to the kernel asynchronously (and therefore VCPU idle management is done in the kernel) if and only if there is an in-kernel irqchip. On other architectures this isn't necessarily true (they may always send interrupts asynchronously), so define a new kvm_async_interrupts_enabled() function instead of misusing kvm_irqchip_in_kernel(). Signed-off-by: Peter Maydell Signed-off-by: Avi Kivity --- cpus.c | 3 ++- kvm-all.c | 7 ++++++- kvm-stub.c | 1 + kvm.h | 13 +++++++++++++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/cpus.c b/cpus.c index 3de2e27f41..e476a3cd5e 100644 --- a/cpus.c +++ b/cpus.c @@ -70,7 +70,8 @@ static bool cpu_thread_is_idle(CPUArchState *env) if (env->stopped || !runstate_is_running()) { return true; } - if (!env->halted || qemu_cpu_has_work(env) || kvm_irqchip_in_kernel()) { + if (!env->halted || qemu_cpu_has_work(env) || + kvm_async_interrupts_enabled()) { return false; } return true; diff --git a/kvm-all.c b/kvm-all.c index bf647614e8..bdb5550293 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -100,6 +100,7 @@ struct KVMState KVMState *kvm_state; bool kvm_kernel_irqchip; +bool kvm_async_interrupts_allowed; static const KVMCapabilityInfo kvm_required_capabilites[] = { KVM_CAP_INFO(USER_MEMORY), @@ -857,7 +858,7 @@ int kvm_irqchip_set_irq(KVMState *s, int irq, int level) struct kvm_irq_level event; int ret; - assert(kvm_irqchip_in_kernel()); + assert(kvm_async_interrupts_enabled()); event.level = level; event.irq = irq; @@ -1201,6 +1202,10 @@ static int kvm_irqchip_create(KVMState *s) s->irqchip_inject_ioctl = KVM_IRQ_LINE_STATUS; } kvm_kernel_irqchip = true; + /* If we have an in-kernel IRQ chip then we must have asynchronous + * interrupt delivery (though the reverse is not necessarily true) + */ + kvm_async_interrupts_allowed = true; kvm_init_irq_routing(s); diff --git a/kvm-stub.c b/kvm-stub.c index d23b11c020..a7a03e14ac 100644 --- a/kvm-stub.c +++ b/kvm-stub.c @@ -19,6 +19,7 @@ KVMState *kvm_state; bool kvm_kernel_irqchip; +bool kvm_async_interrupts_allowed; int kvm_init_vcpu(CPUArchState *env) { diff --git a/kvm.h b/kvm.h index 2617dd5acd..09818f38f1 100644 --- a/kvm.h +++ b/kvm.h @@ -24,13 +24,26 @@ extern int kvm_allowed; extern bool kvm_kernel_irqchip; +extern bool kvm_async_interrupts_allowed; #if defined CONFIG_KVM || !defined NEED_CPU_H #define kvm_enabled() (kvm_allowed) #define kvm_irqchip_in_kernel() (kvm_kernel_irqchip) + +/** + * kvm_async_interrupts_enabled: + * + * Returns: true if we can deliver interrupts to KVM + * asynchronously (ie by ioctl from any thread at any time) + * rather than having to do interrupt delivery synchronously + * (where the vcpu must be stopped at a suitable point first). + */ +#define kvm_async_interrupts_enabled() (kvm_async_interrupts_allowed) + #else #define kvm_enabled() (0) #define kvm_irqchip_in_kernel() (false) +#define kvm_async_interrupts_enabled() (false) #endif struct kvm_run; From 3889c3fab10b63e170ab5193d2ce6be99a704e93 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 26 Jul 2012 15:35:12 +0100 Subject: [PATCH 4/9] kvm: Rename kvm_irqchip_set_irq() to kvm_set_irq() Rename the function kvm_irqchip_set_irq() to kvm_set_irq(), since it can be used for sending (asynchronous) interrupts whether there is a full irqchip model in the kernel or not. (We don't include 'async' in the function name since asynchronous is the normal case.) Signed-off-by: Peter Maydell Signed-off-by: Avi Kivity --- hw/kvm/i8259.c | 2 +- hw/kvm/ioapic.c | 2 +- kvm-all.c | 6 +++--- kvm.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hw/kvm/i8259.c b/hw/kvm/i8259.c index 94d1b9aa95..1e24cd4f36 100644 --- a/hw/kvm/i8259.c +++ b/hw/kvm/i8259.c @@ -94,7 +94,7 @@ static void kvm_pic_set_irq(void *opaque, int irq, int level) { int delivered; - delivered = kvm_irqchip_set_irq(kvm_state, irq, level); + delivered = kvm_set_irq(kvm_state, irq, level); apic_report_irq_delivered(delivered); } diff --git a/hw/kvm/ioapic.c b/hw/kvm/ioapic.c index 3ae3175403..6c3b8fe39a 100644 --- a/hw/kvm/ioapic.c +++ b/hw/kvm/ioapic.c @@ -82,7 +82,7 @@ static void kvm_ioapic_set_irq(void *opaque, int irq, int level) KVMIOAPICState *s = opaque; int delivered; - delivered = kvm_irqchip_set_irq(kvm_state, s->kvm_gsi_base + irq, level); + delivered = kvm_set_irq(kvm_state, s->kvm_gsi_base + irq, level); apic_report_irq_delivered(delivered); } diff --git a/kvm-all.c b/kvm-all.c index bdb5550293..002e751b3f 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -853,7 +853,7 @@ static void kvm_handle_interrupt(CPUArchState *env, int mask) } } -int kvm_irqchip_set_irq(KVMState *s, int irq, int level) +int kvm_set_irq(KVMState *s, int irq, int level) { struct kvm_irq_level event; int ret; @@ -864,7 +864,7 @@ int kvm_irqchip_set_irq(KVMState *s, int irq, int level) event.irq = irq; ret = kvm_vm_ioctl(s, s->irqchip_inject_ioctl, &event); if (ret < 0) { - perror("kvm_set_irqchip_line"); + perror("kvm_set_irq"); abort(); } @@ -1089,7 +1089,7 @@ int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg) assert(route->kroute.type == KVM_IRQ_ROUTING_MSI); - return kvm_irqchip_set_irq(s, route->kroute.gsi, 1); + return kvm_set_irq(s, route->kroute.gsi, 1); } int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg) diff --git a/kvm.h b/kvm.h index 09818f38f1..744209d961 100644 --- a/kvm.h +++ b/kvm.h @@ -146,7 +146,7 @@ int kvm_arch_on_sigbus(int code, void *addr); void kvm_arch_init_irq_routing(KVMState *s); -int kvm_irqchip_set_irq(KVMState *s, int irq, int level); +int kvm_set_irq(KVMState *s, int irq, int level); int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg); void kvm_irqchip_add_irq_route(KVMState *s, int gsi, int irqchip, int pin); From 1d31f66bbc886af56d2def349012a358dc3ada06 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 26 Jul 2012 15:35:13 +0100 Subject: [PATCH 5/9] kvm: Move kvm_allows_irq0_override() to target-i386, fix return type kvm_allows_irq0_override() is a totally x86 specific concept: move it to the target-specific source file where it belongs. This means we need a new header file for the prototype: kvm_i386.h, in line with the existing kvm_ppc.h. While we are moving it, fix the return type to be 'bool' rather than 'int'. Signed-off-by: Peter Maydell Signed-off-by: Avi Kivity --- hw/pc.c | 1 + kvm-all.c | 5 ----- kvm-stub.c | 5 ----- kvm.h | 2 -- target-i386/Makefile.objs | 1 + target-i386/kvm-stub.c | 18 ++++++++++++++++++ target-i386/kvm.c | 6 ++++++ target-i386/kvm_i386.h | 16 ++++++++++++++++ 8 files changed, 42 insertions(+), 12 deletions(-) create mode 100644 target-i386/kvm-stub.c create mode 100644 target-i386/kvm_i386.h diff --git a/hw/pc.c b/hw/pc.c index 81c391cd6a..e8bcfc0b4b 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -42,6 +42,7 @@ #include "sysbus.h" #include "sysemu.h" #include "kvm.h" +#include "kvm_i386.h" #include "xen.h" #include "blockdev.h" #include "hw/block-common.h" diff --git a/kvm-all.c b/kvm-all.c index 002e751b3f..f420dfa368 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -1701,11 +1701,6 @@ int kvm_has_gsi_routing(void) #endif } -int kvm_allows_irq0_override(void) -{ - return !kvm_irqchip_in_kernel() || kvm_has_gsi_routing(); -} - void *kvm_vmalloc(ram_addr_t size) { #ifdef TARGET_S390X diff --git a/kvm-stub.c b/kvm-stub.c index a7a03e14ac..f2b0c61983 100644 --- a/kvm-stub.c +++ b/kvm-stub.c @@ -72,11 +72,6 @@ int kvm_has_many_ioeventfds(void) return 0; } -int kvm_allows_irq0_override(void) -{ - return 1; -} - int kvm_has_pit_state2(void) { return 0; diff --git a/kvm.h b/kvm.h index 744209d961..47bf5ba2ae 100644 --- a/kvm.h +++ b/kvm.h @@ -75,8 +75,6 @@ int kvm_has_pit_state2(void); int kvm_has_many_ioeventfds(void); int kvm_has_gsi_routing(void); -int kvm_allows_irq0_override(void); - #ifdef NEED_CPU_H int kvm_init_vcpu(CPUArchState *env); diff --git a/target-i386/Makefile.objs b/target-i386/Makefile.objs index 683fd59af9..0715f58a8e 100644 --- a/target-i386/Makefile.objs +++ b/target-i386/Makefile.objs @@ -3,6 +3,7 @@ obj-y += excp_helper.o fpu_helper.o cc_helper.o int_helper.o svm_helper.o obj-y += smm_helper.o misc_helper.o mem_helper.o seg_helper.o obj-$(CONFIG_SOFTMMU) += machine.o arch_memory_mapping.o arch_dump.o obj-$(CONFIG_KVM) += kvm.o hyperv.o +obj-$(CONFIG_NO_KVM) += kvm-stub.o obj-$(CONFIG_LINUX_USER) += ioport-user.o obj-$(CONFIG_BSD_USER) += ioport-user.o diff --git a/target-i386/kvm-stub.c b/target-i386/kvm-stub.c new file mode 100644 index 0000000000..11429c461e --- /dev/null +++ b/target-i386/kvm-stub.c @@ -0,0 +1,18 @@ +/* + * QEMU KVM x86 specific function stubs + * + * Copyright Linaro Limited 2012 + * + * Author: Peter Maydell + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ +#include "qemu-common.h" +#include "kvm_i386.h" + +bool kvm_allows_irq0_override(void) +{ + return 1; +} diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 4cfb3faf01..e5decf7fc6 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -23,6 +23,7 @@ #include "qemu-common.h" #include "sysemu.h" #include "kvm.h" +#include "kvm_i386.h" #include "cpu.h" #include "gdbstub.h" #include "host-utils.h" @@ -65,6 +66,11 @@ static bool has_msr_async_pf_en; static bool has_msr_misc_enable; static int lm_capable_kernel; +bool kvm_allows_irq0_override(void) +{ + return !kvm_irqchip_in_kernel() || kvm_has_gsi_routing(); +} + static struct kvm_cpuid2 *try_get_cpuid(KVMState *s, int max) { struct kvm_cpuid2 *cpuid; diff --git a/target-i386/kvm_i386.h b/target-i386/kvm_i386.h new file mode 100644 index 0000000000..b82bbf401e --- /dev/null +++ b/target-i386/kvm_i386.h @@ -0,0 +1,16 @@ +/* + * QEMU KVM support -- x86 specific functions. + * + * Copyright (c) 2012 Linaro Limited + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef QEMU_KVM_I386_H +#define QEMU_KVM_I386_H + +bool kvm_allows_irq0_override(void); + +#endif From cc7e0ddf5a2307015eacfac2ac6a6a765898fcc3 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 26 Jul 2012 15:35:14 +0100 Subject: [PATCH 6/9] kvm: Decouple 'irqfds usable' from 'kernel irqchip' Instead of assuming that we can use irqfds if and only if kvm_irqchip_in_kernel(), add a bool to the KVMState which indicates this, and is set only on x86 and only if the irqchip is in the kernel. The kernel documentation implies that the only thing you need to use KVM_IRQFD is that KVM_CAP_IRQFD is advertised, but this seems to be untrue. In particular the kernel does not (alas) return a sensible error if you try to set up an irqfd when you haven't created an irqchip. If it did we could remove all this nonsense and let the kernel return the error code. Signed-off-by: Peter Maydell Acked-by: Jan Kiszka Signed-off-by: Avi Kivity --- kvm-all.c | 3 ++- kvm-stub.c | 1 + kvm.h | 11 +++++++++++ target-i386/kvm.c | 4 ++++ 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/kvm-all.c b/kvm-all.c index f420dfa368..0704055ce4 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -101,6 +101,7 @@ struct KVMState KVMState *kvm_state; bool kvm_kernel_irqchip; bool kvm_async_interrupts_allowed; +bool kvm_irqfds_allowed; static const KVMCapabilityInfo kvm_required_capabilites[] = { KVM_CAP_INFO(USER_MEMORY), @@ -1126,7 +1127,7 @@ static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int virq, bool assign) .flags = assign ? 0 : KVM_IRQFD_FLAG_DEASSIGN, }; - if (!kvm_irqchip_in_kernel()) { + if (!kvm_irqfds_enabled()) { return -ENOSYS; } diff --git a/kvm-stub.c b/kvm-stub.c index f2b0c61983..02e7fe0507 100644 --- a/kvm-stub.c +++ b/kvm-stub.c @@ -20,6 +20,7 @@ KVMState *kvm_state; bool kvm_kernel_irqchip; bool kvm_async_interrupts_allowed; +bool kvm_irqfds_allowed; int kvm_init_vcpu(CPUArchState *env) { diff --git a/kvm.h b/kvm.h index 47bf5ba2ae..21436ef5d2 100644 --- a/kvm.h +++ b/kvm.h @@ -25,6 +25,7 @@ extern int kvm_allowed; extern bool kvm_kernel_irqchip; extern bool kvm_async_interrupts_allowed; +extern bool kvm_irqfds_allowed; #if defined CONFIG_KVM || !defined NEED_CPU_H #define kvm_enabled() (kvm_allowed) @@ -40,10 +41,20 @@ extern bool kvm_async_interrupts_allowed; */ #define kvm_async_interrupts_enabled() (kvm_async_interrupts_allowed) +/** + * kvm_irqfds_enabled: + * + * Returns: true if we can use irqfds to inject interrupts into + * a KVM CPU (ie the kernel supports irqfds and we are running + * with a configuration where it is meaningful to use them). + */ +#define kvm_irqfds_enabled() (kvm_irqfds_allowed) + #else #define kvm_enabled() (0) #define kvm_irqchip_in_kernel() (false) #define kvm_async_interrupts_enabled() (false) +#define kvm_irqfds_enabled() (false) #endif struct kvm_run; diff --git a/target-i386/kvm.c b/target-i386/kvm.c index e5decf7fc6..8c28fca4b6 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -2047,4 +2047,8 @@ void kvm_arch_init_irq_routing(KVMState *s) */ no_hpet = 1; } + /* We know at this point that we're using the in-kernel + * irqchip, so we can use irqfds. + */ + kvm_irqfds_allowed = true; } From 614e41bc26dda751321da47acb1f9cb287b52085 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 26 Jul 2012 15:35:15 +0100 Subject: [PATCH 7/9] kvm: Decouple 'MSI routing via irqfds' from 'kernel irqchip' Decouple another x86-specific assumption about what irqchips imply. Signed-off-by: Peter Maydell Signed-off-by: Avi Kivity --- hw/virtio-pci.c | 4 ++-- kvm-all.c | 1 + kvm-stub.c | 1 + kvm.h | 11 +++++++++++ target-i386/kvm.c | 4 +++- 5 files changed, 18 insertions(+), 3 deletions(-) diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index 125eded9ca..5e6e09efb7 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -627,7 +627,7 @@ static int virtio_pci_set_guest_notifiers(void *opaque, bool assign) int r, n; /* Must unset vector notifier while guest notifier is still assigned */ - if (kvm_irqchip_in_kernel() && !assign) { + if (kvm_msi_via_irqfd_enabled() && !assign) { msix_unset_vector_notifiers(&proxy->pci_dev); g_free(proxy->vector_irqfd); proxy->vector_irqfd = NULL; @@ -645,7 +645,7 @@ static int virtio_pci_set_guest_notifiers(void *opaque, bool assign) } /* Must set vector notifier after guest notifier has been assigned */ - if (kvm_irqchip_in_kernel() && assign) { + if (kvm_msi_via_irqfd_enabled() && assign) { proxy->vector_irqfd = g_malloc0(sizeof(*proxy->vector_irqfd) * msix_nr_vectors_allocated(&proxy->pci_dev)); diff --git a/kvm-all.c b/kvm-all.c index 0704055ce4..b9a613ee15 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -102,6 +102,7 @@ KVMState *kvm_state; bool kvm_kernel_irqchip; bool kvm_async_interrupts_allowed; bool kvm_irqfds_allowed; +bool kvm_msi_via_irqfd_allowed; static const KVMCapabilityInfo kvm_required_capabilites[] = { KVM_CAP_INFO(USER_MEMORY), diff --git a/kvm-stub.c b/kvm-stub.c index 02e7fe0507..158bb7bee8 100644 --- a/kvm-stub.c +++ b/kvm-stub.c @@ -21,6 +21,7 @@ KVMState *kvm_state; bool kvm_kernel_irqchip; bool kvm_async_interrupts_allowed; bool kvm_irqfds_allowed; +bool kvm_msi_via_irqfd_allowed; int kvm_init_vcpu(CPUArchState *env) { diff --git a/kvm.h b/kvm.h index 21436ef5d2..34d32c7ccd 100644 --- a/kvm.h +++ b/kvm.h @@ -26,6 +26,7 @@ extern int kvm_allowed; extern bool kvm_kernel_irqchip; extern bool kvm_async_interrupts_allowed; extern bool kvm_irqfds_allowed; +extern bool kvm_msi_via_irqfd_allowed; #if defined CONFIG_KVM || !defined NEED_CPU_H #define kvm_enabled() (kvm_allowed) @@ -50,11 +51,21 @@ extern bool kvm_irqfds_allowed; */ #define kvm_irqfds_enabled() (kvm_irqfds_allowed) +/** + * kvm_msi_via_irqfd_enabled: + * + * Returns: true if we can route a PCI MSI (Message Signaled Interrupt) + * to a KVM CPU via an irqfd. This requires that the kernel supports + * this and that we're running in a configuration that permits it. + */ +#define kvm_msi_via_irqfd_enabled() (kvm_msi_via_irqfd_allowed) + #else #define kvm_enabled() (0) #define kvm_irqchip_in_kernel() (false) #define kvm_async_interrupts_enabled() (false) #define kvm_irqfds_enabled() (false) +#define kvm_msi_via_irqfd_enabled() (false) #endif struct kvm_run; diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 8c28fca4b6..7a874ea73b 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -2048,7 +2048,9 @@ void kvm_arch_init_irq_routing(KVMState *s) no_hpet = 1; } /* We know at this point that we're using the in-kernel - * irqchip, so we can use irqfds. + * irqchip, so we can use irqfds, and on x86 we know + * we can use msi via irqfd. */ kvm_irqfds_allowed = true; + kvm_msi_via_irqfd_allowed = true; } From f3e1bed8daa35726d2731dd2a010fb91a5bb3792 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 26 Jul 2012 15:35:16 +0100 Subject: [PATCH 8/9] kvm: Decouple 'GSI routing' from 'kernel irqchip' Don't assume having an in-kernel irqchip means that GSI routing is enabled. Signed-off-by: Peter Maydell Signed-off-by: Avi Kivity --- kvm-all.c | 3 ++- kvm-stub.c | 1 + kvm.h | 10 ++++++++++ target-i386/kvm.c | 3 ++- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/kvm-all.c b/kvm-all.c index b9a613ee15..34b02c1fba 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -103,6 +103,7 @@ bool kvm_kernel_irqchip; bool kvm_async_interrupts_allowed; bool kvm_irqfds_allowed; bool kvm_msi_via_irqfd_allowed; +bool kvm_gsi_routing_allowed; static const KVMCapabilityInfo kvm_required_capabilites[] = { KVM_CAP_INFO(USER_MEMORY), @@ -1099,7 +1100,7 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg) struct kvm_irq_routing_entry kroute; int virq; - if (!kvm_irqchip_in_kernel()) { + if (!kvm_gsi_routing_enabled()) { return -ENOSYS; } diff --git a/kvm-stub.c b/kvm-stub.c index 158bb7bee8..94c9ea15b0 100644 --- a/kvm-stub.c +++ b/kvm-stub.c @@ -22,6 +22,7 @@ bool kvm_kernel_irqchip; bool kvm_async_interrupts_allowed; bool kvm_irqfds_allowed; bool kvm_msi_via_irqfd_allowed; +bool kvm_gsi_routing_allowed; int kvm_init_vcpu(CPUArchState *env) { diff --git a/kvm.h b/kvm.h index 34d32c7ccd..444ed2e704 100644 --- a/kvm.h +++ b/kvm.h @@ -27,6 +27,7 @@ extern bool kvm_kernel_irqchip; extern bool kvm_async_interrupts_allowed; extern bool kvm_irqfds_allowed; extern bool kvm_msi_via_irqfd_allowed; +extern bool kvm_gsi_routing_allowed; #if defined CONFIG_KVM || !defined NEED_CPU_H #define kvm_enabled() (kvm_allowed) @@ -60,12 +61,21 @@ extern bool kvm_msi_via_irqfd_allowed; */ #define kvm_msi_via_irqfd_enabled() (kvm_msi_via_irqfd_allowed) +/** + * kvm_gsi_routing_enabled: + * + * Returns: true if GSI routing is enabled (ie the kernel supports + * it and we're running in a configuration that permits it). + */ +#define kvm_gsi_routing_enabled() (kvm_gsi_routing_allowed) + #else #define kvm_enabled() (0) #define kvm_irqchip_in_kernel() (false) #define kvm_async_interrupts_enabled() (false) #define kvm_irqfds_enabled() (false) #define kvm_msi_via_irqfd_enabled() (false) +#define kvm_gsi_routing_allowed() (false) #endif struct kvm_run; diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 7a874ea73b..696b14a04a 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -2049,8 +2049,9 @@ void kvm_arch_init_irq_routing(KVMState *s) } /* We know at this point that we're using the in-kernel * irqchip, so we can use irqfds, and on x86 we know - * we can use msi via irqfd. + * we can use msi via irqfd and GSI routing. */ kvm_irqfds_allowed = true; kvm_msi_via_irqfd_allowed = true; + kvm_gsi_routing_allowed = true; } From 96fda35ac477e954eee989d6a3ae9e686cc361d6 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 26 Jul 2012 15:35:17 +0100 Subject: [PATCH 9/9] kvm: Add documentation comment for kvm_irqchip_in_kernel() Now we've cleared out the architecture-independent uses of kvm_irqchip_in_kernel(), we can add a doc comment describing what it means. Signed-off-by: Peter Maydell Signed-off-by: Avi Kivity --- kvm.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/kvm.h b/kvm.h index 444ed2e704..5b8f588813 100644 --- a/kvm.h +++ b/kvm.h @@ -31,6 +31,17 @@ extern bool kvm_gsi_routing_allowed; #if defined CONFIG_KVM || !defined NEED_CPU_H #define kvm_enabled() (kvm_allowed) +/** + * kvm_irqchip_in_kernel: + * + * Returns: true if the user asked us to create an in-kernel + * irqchip via the "kernel_irqchip=on" machine option. + * What this actually means is architecture and machine model + * specific: on PC, for instance, it means that the LAPIC, + * IOAPIC and PIT are all in kernel. This function should never + * be used from generic target-independent code: use one of the + * following functions or some other specific check instead. + */ #define kvm_irqchip_in_kernel() (kvm_kernel_irqchip) /**