diff options
-rw-r--r-- | cpu-defs.h | 1 | ||||
-rw-r--r-- | exec.c | 4 | ||||
-rw-r--r-- | gdbstub.c | 8 | ||||
-rw-r--r-- | hw/apic.c | 6 | ||||
-rw-r--r-- | hw/pc.c | 1 | ||||
-rw-r--r-- | kvm-all.c | 13 | ||||
-rw-r--r-- | kvm.h | 8 | ||||
-rw-r--r-- | monitor.c | 4 | ||||
-rw-r--r-- | qemu-kvm.c | 17 | ||||
-rw-r--r-- | qemu-kvm.h | 9 | ||||
-rw-r--r-- | target-i386/machine.c | 7 | ||||
-rw-r--r-- | target-ppc/machine.c | 6 |
12 files changed, 56 insertions, 28 deletions
diff --git a/cpu-defs.h b/cpu-defs.h index a7d6d94e4..b7a6d8cb2 100644 --- a/cpu-defs.h +++ b/cpu-defs.h @@ -143,6 +143,7 @@ struct KVMCPUState { int signalled; void *vcpu_ctx; struct qemu_work_item *queued_work_first, *queued_work_last; + int regs_modified; }; #define CPU_TEMP_BUF_NLONGS 128 @@ -531,7 +531,7 @@ static void cpu_common_save(QEMUFile *f, void *opaque) { CPUState *env = opaque; - cpu_synchronize_state(env, 0); + cpu_synchronize_state(env); qemu_put_be32s(f, &env->halted); qemu_put_be32s(f, &env->interrupt_request); @@ -541,6 +541,7 @@ static int cpu_common_load(QEMUFile *f, void *opaque, int version_id) { CPUState *env = opaque; + cpu_synchronize_state(env); if (version_id != CPU_COMMON_SAVE_VERSION) return -EINVAL; @@ -550,7 +551,6 @@ static int cpu_common_load(QEMUFile *f, void *opaque, int version_id) version_id is increased. */ env->interrupt_request &= ~0x01; tlb_flush(env, 1); - cpu_synchronize_state(env, 1); return 0; } @@ -1569,8 +1569,8 @@ static void gdb_breakpoint_remove_all(void) static void gdb_set_cpu_pc(GDBState *s, target_ulong pc) { #if defined(TARGET_I386) + cpu_synchronize_state(s->c_cpu); s->c_cpu->eip = pc; - cpu_synchronize_state(s->c_cpu, 1); #elif defined (TARGET_PPC) s->c_cpu->nip = pc; #elif defined (TARGET_SPARC) @@ -1756,7 +1756,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) } break; case 'g': - cpu_synchronize_state(s->g_cpu, 0); + cpu_synchronize_state(s->g_cpu); len = 0; for (addr = 0; addr < num_g_regs; addr++) { reg_size = gdb_read_register(s->g_cpu, mem_buf + len, addr); @@ -1766,6 +1766,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) put_packet(s, buf); break; case 'G': + cpu_synchronize_state(s->g_cpu); registers = mem_buf; len = strlen(p) / 2; hextomem((uint8_t *)registers, p, len); @@ -1774,7 +1775,6 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) len -= reg_size; registers += reg_size; } - cpu_synchronize_state(s->g_cpu, 1); put_packet(s, "OK"); break; case 'm': @@ -1930,7 +1930,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) thread = strtoull(p+16, (char **)&p, 16); env = find_cpu(thread); if (env != NULL) { - cpu_synchronize_state(env, 0); + cpu_synchronize_state(env); len = snprintf((char *)mem_buf, sizeof(mem_buf), "CPU#%d [%s]", env->cpu_index, env->halted ? "halted " : "running"); @@ -1059,8 +1059,11 @@ static const VMStateDescription vmstate_apic = { static void apic_reset(void *opaque) { APICState *s = opaque; - int bsp = cpu_is_bsp(s->cpu_env); + int bsp; + cpu_synchronize_state(s->cpu_env); + + bsp = cpu_is_bsp(s->cpu_env); s->apicbase = 0xfee00000 | (bsp ? MSR_IA32_APICBASE_BSP : 0) | MSR_IA32_APICBASE_ENABLE; @@ -1075,7 +1078,6 @@ static void apic_reset(void *opaque) */ s->lvt[APIC_LVT_LINT0] = 0x700; } - cpu_synchronize_state(s->cpu_env, 1); qemu_kvm_load_lapic(s->cpu_env); } @@ -1099,6 +1099,7 @@ CPUState *pc_new_cpu(const char *cpu_model) fprintf(stderr, "Unable to find x86 CPU definition\n"); exit(1); } + env->kvm_cpu_state.regs_modified = 1; if ((env->cpuid_features & CPUID_APIC) || smp_cpus > 1) { env->cpuid_apic_id = env->cpu_index; /* APIC reset callback resets cpu */ @@ -579,6 +579,14 @@ static void kvm_run_coalesced_mmio(CPUState *env, struct kvm_run *run) #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; @@ -593,6 +601,11 @@ int kvm_cpu_exec(CPUState *env) 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); @@ -131,16 +131,14 @@ int kvm_check_extension(KVMState *s, unsigned int extension); uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function, int reg); +void kvm_cpu_synchronize_state(CPUState *env); /* generic hooks - to be moved/refactored once there are more users */ -static inline void cpu_synchronize_state(CPUState *env, int modified) +static inline void cpu_synchronize_state(CPUState *env) { if (kvm_enabled()) { - if (modified) - kvm_arch_put_registers(env); - else - kvm_arch_get_registers(env); + kvm_cpu_synchronize_state(env); } } @@ -334,7 +334,7 @@ static CPUState *mon_get_cpu(void) if (!cur_mon->mon_cpu) { mon_set_cpu(0); } - cpu_synchronize_state(cur_mon->mon_cpu, 0); + cpu_synchronize_state(cur_mon->mon_cpu); return cur_mon->mon_cpu; } @@ -361,7 +361,7 @@ static void do_info_cpus(Monitor *mon) mon_get_cpu(); for(env = first_cpu; env != NULL; env = env->next_cpu) { - cpu_synchronize_state(env, 0); + cpu_synchronize_state(env); monitor_printf(mon, "%c CPU #%d:", (env == mon->mon_cpu) ? '*' : ' ', env->cpu_index); diff --git a/qemu-kvm.c b/qemu-kvm.c index b59e40370..2d3ca7166 100644 --- a/qemu-kvm.c +++ b/qemu-kvm.c @@ -874,6 +874,15 @@ int kvm_set_mpstate(kvm_vcpu_context_t vcpu, struct kvm_mp_state *mp_state) } #endif +void kvm_cpu_synchronize_state(CPUState *env) +{ + if (!env->kvm_cpu_state.regs_modified) { + kvm_arch_get_registers(env); + kvm_arch_save_mpstate(env); + env->kvm_cpu_state.regs_modified = 1; + } +} + static int handle_mmio(kvm_vcpu_context_t vcpu) { unsigned long addr = vcpu->run->mmio.phys_addr; @@ -947,6 +956,7 @@ int kvm_run(kvm_vcpu_context_t vcpu, void *env) int fd = vcpu->fd; struct kvm_run *run = vcpu->run; kvm_context_t kvm = vcpu->kvm; + CPUState *_env = env; again: push_nmi(kvm); @@ -954,6 +964,13 @@ int kvm_run(kvm_vcpu_context_t vcpu, void *env) if (!kvm->irqchip_in_kernel) run->request_interrupt_window = kvm_arch_try_push_interrupts(env); #endif + + if (_env->kvm_cpu_state.regs_modified) { + kvm_arch_put_registers(_env); + kvm_arch_load_mpstate(_env); + _env->kvm_cpu_state.regs_modified = 0; + } + r = pre_kvm_run(kvm, env); if (r) return r; diff --git a/qemu-kvm.h b/qemu-kvm.h index 6476e6f0a..2c1730b11 100644 --- a/qemu-kvm.h +++ b/qemu-kvm.h @@ -1165,13 +1165,12 @@ static inline void kvm_arch_put_registers(CPUState *env) kvm_load_mpstate(env); } -static inline void cpu_synchronize_state(CPUState *env, int modified) +void kvm_cpu_synchronize_state(CPUState *env); + +static inline void cpu_synchronize_state(CPUState *env) { if (kvm_enabled()) { - if (modified) - kvm_arch_put_registers(env); - else - kvm_arch_get_registers(env); + kvm_cpu_synchronize_state(env); } } diff --git a/target-i386/machine.c b/target-i386/machine.c index ca32a92a0..a4f2d22fb 100644 --- a/target-i386/machine.c +++ b/target-i386/machine.c @@ -33,10 +33,7 @@ void cpu_save(QEMUFile *f, void *opaque) int32_t pending_irq; int i, bit; - if (kvm_enabled()) { - kvm_save_registers(env); - kvm_arch_save_mpstate(env); - } + cpu_synchronize_state(env); for(i = 0; i < CPU_NB_REGS; i++) qemu_put_betls(f, &env->regs[i]); @@ -209,6 +206,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) int32_t a20_mask; int32_t pending_irq; + cpu_synchronize_state(env); if (version_id < 3 || version_id > CPU_SAVE_VERSION) return -EINVAL; for(i = 0; i < CPU_NB_REGS; i++) @@ -383,7 +381,6 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) /* XXX: compute redundant hflags bits */ env->hflags = hflags; tlb_flush(env, 1); - cpu_synchronize_state(env, 1); if (kvm_enabled()) { /* when in-kernel irqchip is used, env->halted causes deadlock because no userspace IRQs will ever clear this flag */ diff --git a/target-ppc/machine.c b/target-ppc/machine.c index 101f408b5..ead38e180 100644 --- a/target-ppc/machine.c +++ b/target-ppc/machine.c @@ -8,7 +8,7 @@ void cpu_save(QEMUFile *f, void *opaque) CPUState *env = (CPUState *)opaque; unsigned int i, j; - cpu_synchronize_state(env, 0); + cpu_synchronize_state(env); for (i = 0; i < 32; i++) qemu_put_betls(f, &env->gpr[i]); @@ -97,6 +97,8 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) CPUState *env = (CPUState *)opaque; unsigned int i, j; + cpu_synchronize_state(env); + for (i = 0; i < 32; i++) qemu_get_betls(f, &env->gpr[i]); #if !defined(TARGET_PPC64) @@ -178,7 +180,5 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) qemu_get_sbe32s(f, &env->mmu_idx); qemu_get_sbe32s(f, &env->power_mode); - cpu_synchronize_state(env, 1); - return 0; } |