@@ -521,14 +521,14 @@ static void cpu_common_pre_save(void *opaque)
{
CPUState *env = opaque;
- cpu_synchronize_state(env);
+ cpu_synchronize_state(env, CPU_MODIFY_NONE);
}
static int cpu_common_pre_load(void *opaque)
{
CPUState *env = opaque;
- cpu_synchronize_state(env);
+ cpu_synchronize_state(env, CPU_MODIFY_INIT);
return 0;
}
@@ -1653,7 +1653,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_MODIFY_RUNTIME);
s->c_cpu->eip = pc;
#elif defined (TARGET_PPC)
s->c_cpu->nip = pc;
@@ -1678,7 +1678,7 @@ static void gdb_set_cpu_pc(GDBState *s, target_ulong pc)
#elif defined (TARGET_ALPHA)
s->c_cpu->pc = pc;
#elif defined (TARGET_S390X)
- cpu_synchronize_state(s->c_cpu);
+ cpu_synchronize_state(s->c_cpu, CPU_MODIFY_RUNTIME);
s->c_cpu->psw.addr = pc;
#endif
}
@@ -1848,7 +1848,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_MODIFY_NONE);
len = 0;
for (addr = 0; addr < num_g_regs; addr++) {
reg_size = gdb_read_register(s->g_cpu, mem_buf + len, addr);
@@ -1858,7 +1858,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_MODIFY_RUNTIME);
registers = mem_buf;
len = strlen(p) / 2;
hextomem((uint8_t *)registers, p, len);
@@ -2022,7 +2022,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_MODIFY_NONE);
len = snprintf((char *)mem_buf, sizeof(mem_buf),
"CPU#%d [%s]", env->cpu_index,
env->halted ? "halted " : "running");
@@ -938,7 +938,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_MODIFY_RESET);
bsp = cpu_is_bsp(s->cpu_env);
s->apicbase = 0xfee00000 |
@@ -140,7 +140,7 @@ static void ppc_core99_init (ram_addr_t ram_size,
}
/* Make sure all register sets take effect */
- cpu_synchronize_state(env);
+ cpu_synchronize_state(env, CPU_MODIFY_INIT);
/* allocate RAM */
ram_offset = qemu_ram_alloc(ram_size);
@@ -165,7 +165,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
}
/* Make sure all register sets take effect */
- cpu_synchronize_state(env);
+ cpu_synchronize_state(env, CPU_MODIFY_INIT);
/* allocate RAM */
if (ram_size > (2047 << 20)) {
@@ -185,7 +185,7 @@ static void s390_init(ram_addr_t ram_size,
exit(1);
}
- cpu_synchronize_state(env);
+ cpu_synchronize_state(env, CPU_MODIFY_INIT);
env->psw.addr = KERN_IMAGE_START;
env->psw.mask = 0x0000000180000000ULL;
}
@@ -57,7 +57,8 @@ struct KVMState
KVMSlot slots[32];
int fd;
int vmfd;
- int regs_modified;
+ int synchronized;
+ int pending_modifications;
int coalesced_mmio;
#ifdef KVM_CAP_COALESCED_MMIO
struct kvm_coalesced_mmio_ring *coalesced_mmio_ring;
@@ -155,10 +156,12 @@ static void kvm_reset_vcpu(void *opaque)
CPUState *env = opaque;
kvm_arch_reset_vcpu(env);
- if (kvm_arch_put_registers(env)) {
+ if (kvm_arch_put_registers(env, env->kvm_state->pending_modifications
+ | CPU_MODIFY_RESET)) {
fprintf(stderr, "Fatal: kvm vcpu reset failed\n");
abort();
}
+ env->kvm_state->pending_modifications = CPU_MODIFY_NONE;
}
int kvm_irqchip_in_kernel(void)
@@ -213,7 +216,8 @@ int kvm_init_vcpu(CPUState *env)
if (ret == 0) {
qemu_register_reset(kvm_reset_vcpu, env);
kvm_arch_reset_vcpu(env);
- ret = kvm_arch_put_registers(env);
+ ret = kvm_arch_put_registers(env, CPU_MODIFY_INIT);
+ env->kvm_state->pending_modifications = CPU_MODIFY_NONE;
}
err:
return ret;
@@ -572,12 +576,13 @@ void kvm_flush_coalesced_mmio_buffer(void)
#endif
}
-void kvm_cpu_synchronize_state(CPUState *env)
+void kvm_cpu_synchronize_state(CPUState *env, int modifications)
{
- if (!env->kvm_state->regs_modified) {
+ if (!env->kvm_state->synchronized) {
kvm_arch_get_registers(env);
- env->kvm_state->regs_modified = 1;
+ env->kvm_state->synchronized = 1;
}
+ env->kvm_state->pending_modifications |= modifications;
}
int kvm_cpu_exec(CPUState *env)
@@ -594,9 +599,9 @@ int kvm_cpu_exec(CPUState *env)
break;
}
- if (env->kvm_state->regs_modified) {
- kvm_arch_put_registers(env);
- env->kvm_state->regs_modified = 0;
+ if (env->kvm_state->pending_modifications) {
+ kvm_arch_put_registers(env, env->kvm_state->pending_modifications);
+ env->kvm_state->pending_modifications = CPU_MODIFY_NONE;
}
kvm_arch_pre_run(env, run);
@@ -605,6 +610,8 @@ int kvm_cpu_exec(CPUState *env)
qemu_mutex_lock_iothread();
kvm_arch_post_run(env, run);
+ env->kvm_state->synchronized = 0;
+
if (ret == -EINTR || ret == -EAGAIN) {
dprintf("io window exit\n");
ret = 0;
@@ -946,9 +953,9 @@ static void kvm_invoke_set_guest_debug(void *data)
struct kvm_set_guest_debug_data *dbg_data = data;
CPUState *env = dbg_data->env;
- if (env->kvm_state->regs_modified) {
- kvm_arch_put_registers(env);
- env->kvm_state->regs_modified = 0;
+ if (env->kvm_state->pending_modifications) {
+ kvm_arch_put_registers(env, env->kvm_state->pending_modifications);
+ env->kvm_state->pending_modifications = CPU_MODIFY_NONE;
}
dbg_data->err = kvm_vcpu_ioctl(env, KVM_SET_GUEST_DEBUG, &dbg_data->dbg);
}
@@ -86,7 +86,7 @@ int kvm_arch_pre_run(CPUState *env, struct kvm_run *run);
int kvm_arch_get_registers(CPUState *env);
-int kvm_arch_put_registers(CPUState *env);
+int kvm_arch_put_registers(CPUState *env, int modifications);
int kvm_arch_init(KVMState *s, int smp_cpus);
@@ -129,14 +129,19 @@ 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);
+void kvm_cpu_synchronize_state(CPUState *env, int modifications);
/* generic hooks - to be moved/refactored once there are more users */
-static inline void cpu_synchronize_state(CPUState *env)
+#define CPU_MODIFY_NONE 0
+#define CPU_MODIFY_RUNTIME (1 << 0)
+#define CPU_MODIFY_RESET ((1 << 1) | CPU_MODIFY_RUNTIME)
+#define CPU_MODIFY_INIT ((1 << 2) | CPU_MODIFY_RESET)
+
+static inline void cpu_synchronize_state(CPUState *env, int modifications)
{
if (kvm_enabled()) {
- kvm_cpu_synchronize_state(env);
+ kvm_cpu_synchronize_state(env, modifications);
}
}
@@ -684,7 +684,7 @@ static CPUState *mon_get_cpu(void)
if (!cur_mon->mon_cpu) {
mon_set_cpu(0);
}
- cpu_synchronize_state(cur_mon->mon_cpu);
+ cpu_synchronize_state(cur_mon->mon_cpu, CPU_MODIFY_NONE);
return cur_mon->mon_cpu;
}
@@ -783,7 +783,7 @@ static void do_info_cpus(Monitor *mon, QObject **ret_data)
QDict *cpu;
QObject *obj;
- cpu_synchronize_state(env);
+ cpu_synchronize_state(env, CPU_MODIFY_NONE);
obj = qobject_from_jsonf("{ 'CPU': %d, 'current': %i, 'halted': %i }",
env->cpu_index, env == mon->mon_cpu,
@@ -766,7 +766,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_MODIFY_NONE);
eflags = env->eflags;
#ifdef TARGET_X86_64
@@ -534,7 +534,7 @@ static void kvm_msr_entry_set(struct kvm_msr_entry *entry,
entry->data = value;
}
-static int kvm_put_msrs(CPUState *env)
+static int kvm_put_msrs(CPUState *env, int modifications)
{
struct {
struct kvm_msrs info;
@@ -548,7 +548,9 @@ static int kvm_put_msrs(CPUState *env)
kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_EIP, env->sysenter_eip);
if (kvm_has_msr_star(env))
kvm_msr_entry_set(&msrs[n++], MSR_STAR, env->star);
- kvm_msr_entry_set(&msrs[n++], MSR_IA32_TSC, env->tsc);
+ if (modifications & CPU_MODIFY_INIT) {
+ kvm_msr_entry_set(&msrs[n++], MSR_IA32_TSC, env->tsc);
+ }
#ifdef TARGET_X86_64
/* FIXME if lm capable */
kvm_msr_entry_set(&msrs[n++], MSR_CSTAR, env->cstar);
@@ -556,8 +558,11 @@ static int kvm_put_msrs(CPUState *env)
kvm_msr_entry_set(&msrs[n++], MSR_FMASK, env->fmask);
kvm_msr_entry_set(&msrs[n++], MSR_LSTAR, env->lstar);
#endif
- kvm_msr_entry_set(&msrs[n++], MSR_KVM_SYSTEM_TIME, env->system_time_msr);
- kvm_msr_entry_set(&msrs[n++], MSR_KVM_WALL_CLOCK, env->wall_clock_msr);
+ if (modifications & CPU_MODIFY_INIT) {
+ kvm_msr_entry_set(&msrs[n++], MSR_KVM_SYSTEM_TIME,
+ env->system_time_msr);
+ kvm_msr_entry_set(&msrs[n++], MSR_KVM_WALL_CLOCK, env->wall_clock_msr);
+ }
msr_data.info.nmsrs = n;
@@ -837,7 +842,7 @@ static int kvm_get_vcpu_events(CPUState *env)
return 0;
}
-int kvm_arch_put_registers(CPUState *env)
+int kvm_arch_put_registers(CPUState *env, int modifications)
{
int ret;
@@ -853,17 +858,19 @@ int kvm_arch_put_registers(CPUState *env)
if (ret < 0)
return ret;
- ret = kvm_put_msrs(env);
+ ret = kvm_put_msrs(env, modifications);
if (ret < 0)
return ret;
- ret = kvm_put_mp_state(env);
- if (ret < 0)
- return ret;
+ if (modifications & CPU_MODIFY_RESET) {
+ ret = kvm_put_mp_state(env);
+ if (ret < 0)
+ return ret;
- ret = kvm_put_vcpu_events(env);
- if (ret < 0)
- return ret;
+ ret = kvm_put_vcpu_events(env);
+ if (ret < 0)
+ return ret;
+ }
return 0;
}
@@ -321,7 +321,7 @@ static void cpu_pre_save(void *opaque)
CPUState *env = opaque;
int i;
- cpu_synchronize_state(env);
+ cpu_synchronize_state(env, CPU_MODIFY_NONE);
/* FPU */
env->fpus_vmstate = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
@@ -341,7 +341,7 @@ static int cpu_pre_load(void *opaque)
{
CPUState *env = opaque;
- cpu_synchronize_state(env);
+ cpu_synchronize_state(env, CPU_MODIFY_INIT);
return 0;
}
@@ -57,7 +57,7 @@ void kvm_arch_reset_vcpu(CPUState *env)
{
}
-int kvm_arch_put_registers(CPUState *env)
+int kvm_arch_put_registers(CPUState *env, int modifications)
{
struct kvm_regs regs;
int ret;
@@ -7,7 +7,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_MODIFY_NONE);
for (i = 0; i < 32; i++)
qemu_put_betls(f, &env->gpr[i]);
@@ -96,7 +96,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_MODIFY_INIT);
for (i = 0; i < 32; i++)
qemu_get_betls(f, &env->gpr[i]);
@@ -91,7 +91,7 @@ void kvm_arch_reset_vcpu(CPUState *env)
/* FIXME: add code to reset vcpu. */
}
-int kvm_arch_put_registers(CPUState *env)
+int kvm_arch_put_registers(CPUState *env, int modifications)
{
struct kvm_regs regs;
int ret;
@@ -235,7 +235,7 @@ static int sclp_service_call(CPUState *env, struct kvm_run *run, uint16_t ipbh0)
uint64_t code;
int r = 0;
- cpu_synchronize_state(env);
+ cpu_synchronize_state(env, CPU_MODIFY_RUNTIME);
sccb = env->regs[ipbh0 & 0xf];
code = env->regs[(ipbh0 & 0xf0) >> 4];
@@ -294,9 +294,16 @@ static int handle_hypercall(CPUState *env, struct kvm_run *run)
{
int r;
- cpu_synchronize_state(env);
+ cpu_synchronize_state(env, CPU_MODIFY_RUNTIME);
r = s390_virtio_hypercall(env);
- kvm_arch_put_registers(env);
+
+ /*
+ * FIXME: The following two lines look misplaced. They should be redundant
+ * because of automatic writeback on guest resume.
+ */
+ kvm_arch_put_registers(env, env->kvm_state->pending_modifications
+ | CPU_MODIFY_RUNTIME);
+ env->kvm_state->pending_modifications = CPU_MODIFY_NONE;
return r;
}
@@ -354,7 +361,7 @@ static int handle_sigp(CPUState *env, struct kvm_run *run, uint8_t ipa1)
int r = -1;
CPUState *target_env;
- cpu_synchronize_state(env);
+ cpu_synchronize_state(env, CPU_MODIFY_RUNTIME);
/* get order code */
order_code = run->s390_sieic.ipb >> 28;