@@ -142,7 +142,7 @@ struct KVMCPUState {
pthread_t thread;
int signalled;
struct qemu_work_item *queued_work_first, *queued_work_last;
- int regs_modified;
+ int writeback_scope;
};
#define CPU_TEMP_BUF_NLONGS 128
@@ -529,14 +529,14 @@ static void cpu_common_pre_save(void *opaque)
{
CPUState *env = opaque;
- cpu_synchronize_state(env);
+ cpu_synchronize_state(env, CPU_SYNC_RUNTIME);
}
static int cpu_common_pre_load(void *opaque)
{
CPUState *env = opaque;
- cpu_synchronize_state(env);
+ cpu_synchronize_state(env, CPU_SYNC_RESET);
return 0;
}
@@ -1598,7 +1598,7 @@ 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);
+ cpu_synchronize_state(s->c_cpu, CPU_SYNC_RUNTIME);
s->c_cpu->eip = pc;
#elif defined (TARGET_PPC)
s->c_cpu->nip = pc;
@@ -1785,7 +1785,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
}
break;
case 'g':
- cpu_synchronize_state(s->g_cpu);
+ cpu_synchronize_state(s->g_cpu, CPU_SYNC_RUNTIME);
len = 0;
for (addr = 0; addr < num_g_regs; addr++) {
reg_size = gdb_read_register(s->g_cpu, mem_buf + len, addr);
@@ -1795,7 +1795,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);
+ cpu_synchronize_state(s->g_cpu, CPU_SYNC_RUNTIME);
registers = mem_buf;
len = strlen(p) / 2;
hextomem((uint8_t *)registers, p, len);
@@ -1959,7 +1959,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);
+ cpu_synchronize_state(env, CPU_SYNC_RUNTIME);
len = snprintf((char *)mem_buf, sizeof(mem_buf),
"CPU#%d [%s]", env->cpu_index,
env->halted ? "halted " : "running");
@@ -488,7 +488,7 @@ void apic_init_reset(CPUState *env)
if (!s)
return;
- cpu_synchronize_state(env);
+ cpu_synchronize_state(env, CPU_SYNC_RESET);
s->tpr = 0;
s->spurious_vec = 0xff;
s->log_dest = 0;
@@ -512,7 +512,6 @@ void apic_init_reset(CPUState *env)
if (kvm_enabled() && kvm_irqchip_in_kernel()) {
env->mp_state
= env->halted ? KVM_MP_STATE_UNINITIALIZED : KVM_MP_STATE_RUNNABLE;
- kvm_load_mpstate(env);
}
#endif
}
@@ -1070,7 +1069,7 @@ static void apic_reset(void *opaque)
APICState *s = opaque;
int bsp;
- cpu_synchronize_state(s->cpu_env);
+ cpu_synchronize_state(s->cpu_env, CPU_SYNC_RESET);
bsp = cpu_is_bsp(s->cpu_env);
s->apicbase = 0xfee00000 |
@@ -1021,7 +1021,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;
+ env->kvm_cpu_state.writeback_scope = CPU_SYNC_RESET;
if ((env->cpuid_features & CPUID_APIC) || smp_cpus > 1) {
env->cpuid_apic_id = env->cpu_index;
/* APIC reset callback resets cpu */
@@ -394,8 +394,7 @@ static CPUState *mon_get_cpu(void)
if (!cur_mon->mon_cpu) {
mon_set_cpu(0);
}
- cpu_synchronize_state(cur_mon->mon_cpu);
- kvm_save_mpstate(cur_mon->mon_cpu);
+ cpu_synchronize_state(cur_mon->mon_cpu, CPU_SYNC_RUNTIME);
return cur_mon->mon_cpu;
}
@@ -486,8 +485,7 @@ static void do_info_cpus(Monitor *mon, QObject **ret_data)
const char *answer;
QDict *cpu = qdict_new();
- cpu_synchronize_state(env);
- kvm_save_mpstate(env);
+ cpu_synchronize_state(env, CPU_SYNC_RUNTIME);
qdict_put(cpu, "CPU", qint_from_int(env->cpu_index));
answer = (env == mon->mon_cpu) ? "yes" : "no";
@@ -103,6 +103,8 @@ void kvm_arch_save_mpstate(CPUState *env)
env->mp_state = -1;
else
env->mp_state = mp_state.mp_state;
+ if (kvm_irqchip_in_kernel(kvm_context))
+ env->halted = (env->mp_state == KVM_MP_STATE_HALTED);
#endif
}
@@ -1040,6 +1040,8 @@ void kvm_arch_save_mpstate(CPUState *env)
env->mp_state = -1;
else
env->mp_state = mp_state.mp_state;
+ if (kvm_irqchip_in_kernel())
+ env->halted = (env->mp_state == KVM_MP_STATE_HALTED);
#else
env->mp_state = -1;
#endif
@@ -1675,11 +1677,11 @@ uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,
void kvm_arch_process_irqchip_events(CPUState *env)
{
if (env->interrupt_request & CPU_INTERRUPT_INIT) {
- kvm_cpu_synchronize_state(env);
+ kvm_cpu_synchronize_state(env, CPU_SYNC_RESET);
do_cpu_init(env);
}
if (env->interrupt_request & CPU_INTERRUPT_SIPI) {
- kvm_cpu_synchronize_state(env);
+ kvm_cpu_synchronize_state(env, CPU_SYNC_RESET);
do_cpu_sipi(env);
}
}
@@ -906,9 +906,9 @@ int kvm_run(CPUState *env)
run->request_interrupt_window = kvm_arch_try_push_interrupts(env);
#endif
- if (env->kvm_cpu_state.regs_modified) {
- kvm_arch_put_registers(env);
- env->kvm_cpu_state.regs_modified = 0;
+ if (env->kvm_cpu_state.writeback_scope) {
+ kvm_arch_put_registers(env, env->kvm_cpu_state.writeback_scope);
+ env->kvm_cpu_state.writeback_scope = 0;
}
r = pre_kvm_run(kvm, env);
@@ -1533,22 +1533,31 @@ static void on_vcpu(CPUState *env, void (*func)(void *data), void *data)
void kvm_arch_get_registers(CPUState *env)
{
- kvm_arch_save_regs(env);
+ kvm_arch_save_regs(env);
+ kvm_arch_save_mpstate(env);
}
-static void do_kvm_cpu_synchronize_state(void *_env)
+void kvm_arch_put_registers(CPUState *env, int scope)
{
- CPUState *env = _env;
- if (!env->kvm_cpu_state.regs_modified) {
- kvm_arch_get_registers(env);
- env->kvm_cpu_state.regs_modified = 1;
+ kvm_load_registers(env);
+ if (scope & CPU_SYNC_RESET) {
+ kvm_load_mpstate(env);
}
}
-void kvm_cpu_synchronize_state(CPUState *env)
+static void kvm_do_synchronize_state(void *_env)
{
- if (!env->kvm_cpu_state.regs_modified)
- on_vcpu(env, do_kvm_cpu_synchronize_state, env);
+ CPUState *env = _env;
+
+ kvm_arch_get_registers(env);
+}
+
+void kvm_cpu_synchronize_state(CPUState *env, int writeback_scope)
+{
+ if (!env->kvm_cpu_state.writeback_scope) {
+ on_vcpu(env, kvm_do_synchronize_state, env);
+ env->kvm_cpu_state.writeback_scope |= writeback_scope;
+ }
}
static void inject_interrupt(void *data)
@@ -1627,10 +1636,6 @@ static void kvm_do_save_mpstate(void *_env)
CPUState *env = _env;
kvm_arch_save_mpstate(env);
-#ifdef KVM_CAP_MP_STATE
- if (kvm_irqchip_in_kernel())
- env->halted = (env->mp_state == KVM_MP_STATE_HALTED);
-#endif
}
void kvm_save_mpstate(CPUState *env)
@@ -2369,9 +2374,10 @@ static void kvm_invoke_set_guest_debug(void *data)
{
struct kvm_set_guest_debug_data *dbg_data = data;
- if (cpu_single_env->kvm_cpu_state.regs_modified) {
- kvm_arch_put_registers(cpu_single_env);
- cpu_single_env->kvm_cpu_state.regs_modified = 0;
+ if (cpu_single_env->kvm_cpu_state.writeback_scope) {
+ kvm_arch_put_registers(cpu_single_env,
+ cpu_single_env->kvm_cpu_state.writeback_scope);
+ cpu_single_env->kvm_cpu_state.writeback_scope = 0;
}
dbg_data->err =
kvm_set_guest_debug(cpu_single_env,
@@ -1098,18 +1098,17 @@ static inline int kvm_sync_vcpus(void)
#ifndef QEMU_KVM_NO_CPU
void kvm_arch_get_registers(CPUState *env);
+void kvm_arch_put_registers(CPUState *env, int scope);
-static inline void kvm_arch_put_registers(CPUState *env)
-{
- kvm_load_registers(env);
-}
+void kvm_cpu_synchronize_state(CPUState *env, int writeback_scope);
-void kvm_cpu_synchronize_state(CPUState *env);
+#define CPU_SYNC_RUNTIME (1 << 0)
+#define CPU_SYNC_RESET (1 << 1)
-static inline void cpu_synchronize_state(CPUState *env)
+static inline void cpu_synchronize_state(CPUState *env, int writeback_scope)
{
if (kvm_enabled()) {
- kvm_cpu_synchronize_state(env);
+ kvm_cpu_synchronize_state(env, writeback_scope);
}
}
@@ -745,7 +745,7 @@ void cpu_dump_state(CPUState *env, FILE *f,
char cc_op_name[32];
static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
- cpu_synchronize_state(env);
+ cpu_synchronize_state(env, CPU_SYNC_RUNTIME);
eflags = env->eflags;
#ifdef TARGET_X86_64
@@ -323,8 +323,7 @@ static void cpu_pre_save(void *opaque)
CPUState *env = opaque;
int i, bit;
- cpu_synchronize_state(env);
- kvm_save_mpstate(env);
+ cpu_synchronize_state(env, CPU_SYNC_RUNTIME);
/* FPU */
env->fpus_vmstate = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
@@ -355,7 +354,7 @@ static int cpu_pre_load(void *opaque)
{
CPUState *env = opaque;
- cpu_synchronize_state(env);
+ cpu_synchronize_state(env, CPU_SYNC_RESET);
return 0;
}
@@ -386,8 +385,6 @@ static int cpu_post_load(void *opaque, int version_id)
}
tlb_flush(env, 1);
- kvm_load_mpstate(env);
-
return 0;
}
@@ -8,7 +8,7 @@ void cpu_save(QEMUFile *f, void *opaque)
CPUState *env = (CPUState *)opaque;
unsigned int i, j;
- cpu_synchronize_state(env);
+ cpu_synchronize_state(env, CPU_SYNC_RUNTIME);
for (i = 0; i < 32; i++)
qemu_put_betls(f, &env->gpr[i]);
@@ -97,7 +97,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
CPUState *env = (CPUState *)opaque;
unsigned int i, j;
- cpu_synchronize_state(env);
+ cpu_synchronize_state(env, CPU_SYNC_RESET);
for (i = 0; i < 32; i++)
qemu_get_betls(f, &env->gpr[i]);