X-Git-Url: http://git.maemo.org/git/?p=qemu;a=blobdiff_plain;f=kvm-all.c;h=b24d8766f46f1069ce79dac2ea991669ddbd64a3;hp=f4851c00782a01db377887e76351f34b0985df47;hb=HEAD;hpb=4495d6a74575b4ee7e9aabdc66e67b6c9e19a698 diff --git a/kvm-all.c b/kvm-all.c index f4851c0..b24d876 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -22,6 +22,7 @@ #include "qemu-common.h" #include "sysemu.h" +#include "hw/hw.h" #include "gdbstub.h" #include "kvm.h" @@ -180,6 +181,26 @@ err: return ret; } +int kvm_put_mp_state(CPUState *env) +{ + struct kvm_mp_state mp_state = { .mp_state = env->mp_state }; + + return kvm_vcpu_ioctl(env, KVM_SET_MP_STATE, &mp_state); +} + +int kvm_get_mp_state(CPUState *env) +{ + struct kvm_mp_state mp_state; + int ret; + + ret = kvm_vcpu_ioctl(env, KVM_GET_MP_STATE, &mp_state); + if (ret < 0) { + return ret; + } + env->mp_state = mp_state.mp_state; + return 0; +} + int kvm_sync_vcpus(void) { CPUState *env; @@ -272,47 +293,58 @@ int kvm_set_migration_log(int enable) * @start_add: start of logged region. * @end_addr: end of logged region. */ -void kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, - target_phys_addr_t end_addr) +int kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, + target_phys_addr_t end_addr) { KVMState *s = kvm_state; - KVMDirtyLog d; - KVMSlot *mem = kvm_lookup_matching_slot(s, start_addr, end_addr); - unsigned long alloc_size; + unsigned long size, allocated_size = 0; + target_phys_addr_t phys_addr; ram_addr_t addr; - target_phys_addr_t phys_addr = start_addr; + KVMDirtyLog d; + KVMSlot *mem; + int ret = 0; - dprintf("sync addr: " TARGET_FMT_lx " into %lx\n", start_addr, - mem->phys_offset); - if (mem == NULL) { - fprintf(stderr, "BUG: %s: invalid parameters " TARGET_FMT_plx "-" - TARGET_FMT_plx "\n", __func__, phys_addr, end_addr - 1); - return; - } + d.dirty_bitmap = NULL; + while (start_addr < end_addr) { + mem = kvm_lookup_overlapping_slot(s, start_addr, end_addr); + if (mem == NULL) { + break; + } + + size = ((mem->memory_size >> TARGET_PAGE_BITS) + 7) / 8; + if (!d.dirty_bitmap) { + d.dirty_bitmap = qemu_malloc(size); + } else if (size > allocated_size) { + d.dirty_bitmap = qemu_realloc(d.dirty_bitmap, size); + } + allocated_size = size; + memset(d.dirty_bitmap, 0, allocated_size); - alloc_size = mem->memory_size >> TARGET_PAGE_BITS / sizeof(d.dirty_bitmap); - d.dirty_bitmap = qemu_mallocz(alloc_size); + d.slot = mem->slot; - d.slot = mem->slot; - dprintf("slot %d, phys_addr %llx, uaddr: %llx\n", - d.slot, mem->start_addr, mem->phys_offset); + if (kvm_vm_ioctl(s, KVM_GET_DIRTY_LOG, &d) == -1) { + dprintf("ioctl failed %d\n", errno); + ret = -1; + break; + } - if (kvm_vm_ioctl(s, KVM_GET_DIRTY_LOG, &d) == -1) { - dprintf("ioctl failed %d\n", errno); - goto out; - } + for (phys_addr = mem->start_addr, addr = mem->phys_offset; + phys_addr < mem->start_addr + mem->memory_size; + phys_addr += TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) { + unsigned long *bitmap = (unsigned long *)d.dirty_bitmap; + unsigned nr = (phys_addr - mem->start_addr) >> TARGET_PAGE_BITS; + unsigned word = nr / (sizeof(*bitmap) * 8); + unsigned bit = nr % (sizeof(*bitmap) * 8); - phys_addr = start_addr; - for (addr = mem->phys_offset; phys_addr < end_addr; phys_addr+= TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) { - unsigned long *bitmap = (unsigned long *)d.dirty_bitmap; - unsigned nr = (phys_addr - start_addr) >> TARGET_PAGE_BITS; - unsigned word = nr / (sizeof(*bitmap) * 8); - unsigned bit = nr % (sizeof(*bitmap) * 8); - if ((bitmap[word] >> bit) & 1) - cpu_physical_memory_set_dirty(addr); + if ((bitmap[word] >> bit) & 1) { + cpu_physical_memory_set_dirty(addr); + } + } + start_addr = phys_addr; } -out: qemu_free(d.dirty_bitmap); + + return ret; } int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size) @@ -365,8 +397,16 @@ int kvm_check_extension(KVMState *s, unsigned int extension) return ret; } +static void kvm_reset_vcpus(void *opaque) +{ + kvm_sync_vcpus(); +} + int kvm_init(int smp_cpus) { + static const char upgrade_note[] = + "Please upgrade to at least kernel 2.6.29 or recent kvm-kmod\n" + "(see http://sourceforge.net/projects/kvm).\n"; KVMState *s; int ret; int i; @@ -417,7 +457,8 @@ int kvm_init(int smp_cpus) */ if (!kvm_check_extension(s, KVM_CAP_USER_MEMORY)) { ret = -EINVAL; - fprintf(stderr, "kvm does not support KVM_CAP_USER_MEMORY\n"); + fprintf(stderr, "kvm does not support KVM_CAP_USER_MEMORY\n%s", + upgrade_note); goto err; } @@ -428,8 +469,8 @@ int kvm_init(int smp_cpus) ret = -EINVAL; fprintf(stderr, - "KVM kernel module broken (DESTROY_MEMORY_REGION)\n" - "Please upgrade to at least kvm-81.\n"); + "KVM kernel module broken (DESTROY_MEMORY_REGION).\n%s", + upgrade_note); goto err; } @@ -451,6 +492,8 @@ int kvm_init(int smp_cpus) if (ret < 0) goto err; + qemu_register_reset(kvm_reset_vcpus, INT_MAX, NULL); + kvm_state = s; return 0;