kvm: test for ioeventfd support on old kernels

There used to be a limit of 6 KVM io bus devices in the kernel.
On such a kernel, we can't use many ioeventfds for host notification
since the limit is reached too easily.

Add an API to test for this condition.

Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2011-01-10 13:50:05 +02:00 committed by Michael S. Tsirkin
parent 85cf2a8d74
commit d2f2b8a740
3 changed files with 55 additions and 0 deletions

View File

@ -28,6 +28,11 @@
#include "kvm.h" #include "kvm.h"
#include "bswap.h" #include "bswap.h"
/* This check must be after config-host.h is included */
#ifdef CONFIG_EVENTFD
#include <sys/eventfd.h>
#endif
/* KVM uses PAGE_SIZE in it's definition of COALESCED_MMIO_MAX */ /* KVM uses PAGE_SIZE in it's definition of COALESCED_MMIO_MAX */
#define PAGE_SIZE TARGET_PAGE_SIZE #define PAGE_SIZE TARGET_PAGE_SIZE
@ -72,6 +77,7 @@ struct KVMState
int irqchip_in_kernel; int irqchip_in_kernel;
int pit_in_kernel; int pit_in_kernel;
int xsave, xcrs; int xsave, xcrs;
int many_ioeventfds;
}; };
static KVMState *kvm_state; static KVMState *kvm_state;
@ -441,6 +447,39 @@ int kvm_check_extension(KVMState *s, unsigned int extension)
return ret; return ret;
} }
static int kvm_check_many_ioeventfds(void)
{
/* Older kernels have a 6 device limit on the KVM io bus. Find out so we
* can avoid creating too many ioeventfds.
*/
#ifdef CONFIG_EVENTFD
int ioeventfds[7];
int i, ret = 0;
for (i = 0; i < ARRAY_SIZE(ioeventfds); i++) {
ioeventfds[i] = eventfd(0, EFD_CLOEXEC);
if (ioeventfds[i] < 0) {
break;
}
ret = kvm_set_ioeventfd_pio_word(ioeventfds[i], 0, i, true);
if (ret < 0) {
close(ioeventfds[i]);
break;
}
}
/* Decide whether many devices are supported or not */
ret = i == ARRAY_SIZE(ioeventfds);
while (i-- > 0) {
kvm_set_ioeventfd_pio_word(ioeventfds[i], 0, i, false);
close(ioeventfds[i]);
}
return ret;
#else
return 0;
#endif
}
static void kvm_set_phys_mem(target_phys_addr_t start_addr, static void kvm_set_phys_mem(target_phys_addr_t start_addr,
ram_addr_t size, ram_addr_t size,
ram_addr_t phys_offset) ram_addr_t phys_offset)
@ -717,6 +756,8 @@ int kvm_init(int smp_cpus)
kvm_state = s; kvm_state = s;
cpu_register_phys_memory_client(&kvm_cpu_phys_memory_client); cpu_register_phys_memory_client(&kvm_cpu_phys_memory_client);
s->many_ioeventfds = kvm_check_many_ioeventfds();
return 0; return 0;
err: err:
@ -1046,6 +1087,14 @@ int kvm_has_xcrs(void)
return kvm_state->xcrs; return kvm_state->xcrs;
} }
int kvm_has_many_ioeventfds(void)
{
if (!kvm_enabled()) {
return 0;
}
return kvm_state->many_ioeventfds;
}
void kvm_setup_guest_memory(void *start, size_t size) void kvm_setup_guest_memory(void *start, size_t size)
{ {
if (!kvm_has_sync_mmu()) { if (!kvm_has_sync_mmu()) {

View File

@ -99,6 +99,11 @@ int kvm_has_robust_singlestep(void)
return 0; return 0;
} }
int kvm_has_many_ioeventfds(void)
{
return 0;
}
void kvm_setup_guest_memory(void *start, size_t size) void kvm_setup_guest_memory(void *start, size_t size)
{ {
} }

1
kvm.h
View File

@ -42,6 +42,7 @@ int kvm_has_robust_singlestep(void);
int kvm_has_debugregs(void); int kvm_has_debugregs(void);
int kvm_has_xsave(void); int kvm_has_xsave(void);
int kvm_has_xcrs(void); int kvm_has_xcrs(void);
int kvm_has_many_ioeventfds(void);
#ifdef NEED_CPU_H #ifdef NEED_CPU_H
int kvm_init_vcpu(CPUState *env); int kvm_init_vcpu(CPUState *env);