KVMSlot slots[32];
int fd;
int vmfd;
+ int regs_modified;
int coalesced_mmio;
int broken_set_mem_region;
int migration_log;
#ifdef KVM_CAP_SET_GUEST_DEBUG
struct kvm_sw_breakpoint_head kvm_sw_breakpoints;
#endif
+ int irqchip_in_kernel;
+ int pit_in_kernel;
};
static KVMState *kvm_state;
}
}
+int kvm_irqchip_in_kernel(void)
+{
+ return kvm_state->irqchip_in_kernel;
+}
+
+int kvm_pit_in_kernel(void)
+{
+ return kvm_state->pit_in_kernel;
+}
+
+
int kvm_init_vcpu(CPUState *env)
{
KVMState *s = kvm_state;
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) {
- unsigned long *bitmap = (unsigned long *)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);
}
}
#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)
{
return !TAILQ_EMPTY(&env->kvm_state->kvm_sw_breakpoints);
}
+struct kvm_set_guest_debug_data {
+ struct kvm_guest_debug dbg;
+ CPUState *env;
+ int err;
+};
+
+static void kvm_invoke_set_guest_debug(void *data)
+{
+ struct kvm_set_guest_debug_data *dbg_data = data;
+ dbg_data->err = kvm_vcpu_ioctl(dbg_data->env, KVM_SET_GUEST_DEBUG, &dbg_data->dbg);
+}
+
int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap)
{
- struct kvm_guest_debug dbg;
+ struct kvm_set_guest_debug_data data;
- dbg.control = 0;
+ data.dbg.control = 0;
if (env->singlestep_enabled)
- dbg.control = KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP;
+ data.dbg.control = KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP;
- kvm_arch_update_guest_debug(env, &dbg);
- dbg.control |= reinject_trap;
+ kvm_arch_update_guest_debug(env, &data.dbg);
+ data.dbg.control |= reinject_trap;
+ data.env = env;
- return kvm_vcpu_ioctl(env, KVM_SET_GUEST_DEBUG, &dbg);
+ on_vcpu(env, kvm_invoke_set_guest_debug, &data);
+ return data.err;
}
int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,