KVMSlot slots[32];
int fd;
int vmfd;
+ int regs_modified;
int coalesced_mmio;
int broken_set_mem_region;
int migration_log;
}
}
-static void on_vcpu(CPUState *env, void (*func)(void *data), void *data)
-{
- if (env == cpu_single_env) {
- func(data);
- return;
- }
- abort();
-}
-
int kvm_irqchip_in_kernel(void)
{
return kvm_state->irqchip_in_kernel;
return 0;
}
+static int test_le_bit(unsigned long nr, unsigned char *addr)
+{
+ return (addr[nr >> 3] >> (nr & 7)) & 1;
+}
+
/**
* kvm_physical_sync_dirty_bitmap - Grab dirty bitmap from kernel space
* This function updates qemu's dirty bitmap using cpu_physical_memory_set_dirty().
KVMDirtyLog d;
KVMSlot *mem;
int ret = 0;
- int r;
d.dirty_bitmap = NULL;
while (start_addr < end_addr) {
break;
}
- /* We didn't activate dirty logging? Don't care then. */
- if(!(mem->flags & KVM_MEM_LOG_DIRTY_PAGES)) {
- continue;
- }
-
size = ((mem->memory_size >> TARGET_PAGE_BITS) + 7) / 8;
if (!d.dirty_bitmap) {
d.dirty_bitmap = qemu_malloc(size);
d.slot = mem->slot;
- r = kvm_vm_ioctl(s, KVM_GET_DIRTY_LOG, &d);
- if (r == -EINVAL) {
+ if (kvm_vm_ioctl(s, KVM_GET_DIRTY_LOG, &d) == -1) {
dprintf("ioctl failed %d\n", errno);
ret = -1;
break;
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) {
- uint64_t *bitmap = (uint64_t *)d.dirty_bitmap;
+ unsigned char *bitmap = (unsigned char *)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);
- if ((bitmap[word] >> bit) & 1) {
- cpu_physical_memory_set_dirty(addr);
- } else if (r < 0) {
- /* When our KVM implementation doesn't know about dirty logging
- * we can just assume it's always dirty and be fine. */
+ if (test_le_bit(nr, bitmap)) {
cpu_physical_memory_set_dirty(addr);
}
}
s = qemu_mallocz(sizeof(KVMState));
#ifdef KVM_CAP_SET_GUEST_DEBUG
- TAILQ_INIT(&s->kvm_sw_breakpoints);
+ QTAILQ_INIT(&s->kvm_sw_breakpoints);
#endif
for (i = 0; i < ARRAY_SIZE(s->slots); i++)
s->slots[i].slot = i;
#endif
}
+void kvm_cpu_synchronize_state(CPUState *env)
+{
+ if (!env->kvm_state->regs_modified) {
+ kvm_arch_get_registers(env);
+ env->kvm_state->regs_modified = 1;
+ }
+}
+
int kvm_cpu_exec(CPUState *env)
{
struct kvm_run *run = env->kvm_run;
break;
}
+ if (env->kvm_state->regs_modified) {
+ kvm_arch_put_registers(env);
+ env->kvm_state->regs_modified = 0;
+ }
+
kvm_arch_pre_run(env, run);
ret = kvm_vcpu_ioctl(env, KVM_RUN, 0);
kvm_arch_post_run(env, run);
}
#ifdef KVM_CAP_SET_GUEST_DEBUG
+static void on_vcpu(CPUState *env, void (*func)(void *data), void *data)
+{
+ if (env == cpu_single_env) {
+ func(data);
+ return;
+ }
+ abort();
+}
+
struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *env,
target_ulong pc)
{
struct kvm_sw_breakpoint *bp;
- TAILQ_FOREACH(bp, &env->kvm_state->kvm_sw_breakpoints, entry) {
+ QTAILQ_FOREACH(bp, &env->kvm_state->kvm_sw_breakpoints, entry) {
if (bp->pc == pc)
return bp;
}
int kvm_sw_breakpoints_active(CPUState *env)
{
- return !TAILQ_EMPTY(&env->kvm_state->kvm_sw_breakpoints);
+ return !QTAILQ_EMPTY(&env->kvm_state->kvm_sw_breakpoints);
}
struct kvm_set_guest_debug_data {
return err;
}
- TAILQ_INSERT_HEAD(¤t_env->kvm_state->kvm_sw_breakpoints,
+ QTAILQ_INSERT_HEAD(¤t_env->kvm_state->kvm_sw_breakpoints,
bp, entry);
} else {
err = kvm_arch_insert_hw_breakpoint(addr, len, type);
if (err)
return err;
- TAILQ_REMOVE(¤t_env->kvm_state->kvm_sw_breakpoints, bp, entry);
+ QTAILQ_REMOVE(¤t_env->kvm_state->kvm_sw_breakpoints, bp, entry);
qemu_free(bp);
} else {
err = kvm_arch_remove_hw_breakpoint(addr, len, type);
KVMState *s = current_env->kvm_state;
CPUState *env;
- TAILQ_FOREACH_SAFE(bp, &s->kvm_sw_breakpoints, entry, next) {
+ QTAILQ_FOREACH_SAFE(bp, &s->kvm_sw_breakpoints, entry, next) {
if (kvm_arch_remove_sw_breakpoint(current_env, bp) != 0) {
/* Try harder to find a CPU that currently sees the breakpoint. */
for (env = first_cpu; env != NULL; env = env->next_cpu) {