int fd;
int vmfd;
int coalesced_mmio;
+ int broken_set_mem_region;
#ifdef KVM_CAP_SET_GUEST_DEBUG
struct kvm_sw_breakpoint_head kvm_sw_breakpoints;
#endif
return ret;
}
+int kvm_check_extension(KVMState *s, unsigned int extension)
+{
+ int ret;
+
+ ret = kvm_ioctl(s, KVM_CHECK_EXTENSION, extension);
+ if (ret < 0) {
+ ret = 0;
+ }
+
+ return ret;
+}
+
int kvm_init(int smp_cpus)
{
KVMState *s;
int ret;
int i;
- if (smp_cpus > 1)
+ if (smp_cpus > 1) {
+ fprintf(stderr, "No SMP KVM support, use '-smp 1'\n");
return -EINVAL;
+ }
s = qemu_mallocz(sizeof(KVMState));
* just use a user allocated buffer so we can use regular pages
* unmodified. Make sure we have a sufficiently modern version of KVM.
*/
- ret = kvm_ioctl(s, KVM_CHECK_EXTENSION, KVM_CAP_USER_MEMORY);
- if (ret <= 0) {
- if (ret == 0)
- ret = -EINVAL;
+ if (!kvm_check_extension(s, KVM_CAP_USER_MEMORY)) {
+ ret = -EINVAL;
fprintf(stderr, "kvm does not support KVM_CAP_USER_MEMORY\n");
goto err;
}
/* There was a nasty bug in < kvm-80 that prevents memory slots from being
* destroyed properly. Since we rely on this capability, refuse to work
* with any kernel without this capability. */
- ret = kvm_ioctl(s, KVM_CHECK_EXTENSION,
- KVM_CAP_DESTROY_MEMORY_REGION_WORKS);
- if (ret <= 0) {
- if (ret == 0)
- ret = -EINVAL;
+ if (!kvm_check_extension(s, KVM_CAP_DESTROY_MEMORY_REGION_WORKS)) {
+ ret = -EINVAL;
fprintf(stderr,
"KVM kernel module broken (DESTROY_MEMORY_REGION)\n"
goto err;
}
- s->coalesced_mmio = 0;
#ifdef KVM_CAP_COALESCED_MMIO
- ret = kvm_ioctl(s, KVM_CHECK_EXTENSION, KVM_CAP_COALESCED_MMIO);
- if (ret > 0)
- s->coalesced_mmio = ret;
+ s->coalesced_mmio = kvm_check_extension(s, KVM_CAP_COALESCED_MMIO);
+#else
+ s->coalesced_mmio = 0;
+#endif
+
+ s->broken_set_mem_region = 1;
+#ifdef KVM_CAP_JOIN_MEMORY_REGIONS_WORKS
+ ret = kvm_ioctl(s, KVM_CHECK_EXTENSION, KVM_CAP_JOIN_MEMORY_REGIONS_WORKS);
+ if (ret > 0) {
+ s->broken_set_mem_region = 0;
+ }
#endif
ret = kvm_arch_init(s, smp_cpus);
* address as the first existing one. If not or if some overlapping
* slot comes around later, we will fail (not seen in practice so far)
* - and actually require a recent KVM version. */
- if (old.start_addr == start_addr && old.memory_size < size &&
+ if (s->broken_set_mem_region &&
+ old.start_addr == start_addr && old.memory_size < size &&
flags < IO_MEM_UNASSIGNED) {
mem = kvm_alloc_slot(s);
mem->memory_size = old.memory_size;
#ifdef KVM_CAP_SYNC_MMU
KVMState *s = kvm_state;
- if (kvm_ioctl(s, KVM_CHECK_EXTENSION, KVM_CAP_SYNC_MMU) > 0)
- return 1;
-#endif
-
+ return kvm_check_extension(s, KVM_CAP_SYNC_MMU);
+#else
return 0;
+#endif
}
void kvm_setup_guest_memory(void *start, size_t size)