Commit 8d2ba1fb9c8e7006e10d71fa51a020977f14c8b0

Authored by Jan Kiszka
Committed by Anthony Liguori
1 parent e9283f8b

kvm: Rework VCPU synchronization

During startup and after reset we have to synchronize user space to the
in-kernel KVM state. Namely, we need to transfer the VCPU registers when
they change due to VCPU as well as APIC reset.

This patch refactors the required hooks so that kvm_init_vcpu registers
its own per-VCPU reset handler and adds a cpu_synchronize_state to the
APIC reset. That way we no longer depend on the new reset order (and can
drop this disliked interface again) and we can even drop a KVM hook in
main().

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
hw/apic.c
... ... @@ -23,6 +23,7 @@
23 23 #include "msix.h"
24 24 #include "qemu-timer.h"
25 25 #include "host-utils.h"
  26 +#include "kvm.h"
26 27  
27 28 //#define DEBUG_APIC
28 29  
... ... @@ -953,6 +954,8 @@ static void apic_reset(void *opaque)
953 954 */
954 955 s->lvt[APIC_LVT_LINT0] = 0x700;
955 956 }
  957 +
  958 + cpu_synchronize_state(s->cpu_env, 1);
956 959 }
957 960  
958 961 static CPUReadMemoryFunc *apic_mem_read[3] = {
... ...
kvm-all.c
... ... @@ -143,6 +143,15 @@ static int kvm_set_user_memory_region(KVMState *s, KVMSlot *slot)
143 143 return kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem);
144 144 }
145 145  
  146 +static void kvm_reset_vcpu(void *opaque)
  147 +{
  148 + CPUState *env = opaque;
  149 +
  150 + if (kvm_arch_put_registers(env)) {
  151 + fprintf(stderr, "Fatal: kvm vcpu reset failed\n");
  152 + abort();
  153 + }
  154 +}
146 155  
147 156 int kvm_init_vcpu(CPUState *env)
148 157 {
... ... @@ -176,7 +185,10 @@ int kvm_init_vcpu(CPUState *env)
176 185 }
177 186  
178 187 ret = kvm_arch_init_vcpu(env);
179   -
  188 + if (ret == 0) {
  189 + qemu_register_reset(kvm_reset_vcpu, 0, env);
  190 + ret = kvm_arch_put_registers(env);
  191 + }
180 192 err:
181 193 return ret;
182 194 }
... ... @@ -201,21 +213,6 @@ int kvm_get_mp_state(CPUState *env)
201 213 return 0;
202 214 }
203 215  
204   -int kvm_sync_vcpus(void)
205   -{
206   - CPUState *env;
207   -
208   - for (env = first_cpu; env != NULL; env = env->next_cpu) {
209   - int ret;
210   -
211   - ret = kvm_arch_put_registers(env);
212   - if (ret)
213   - return ret;
214   - }
215   -
216   - return 0;
217   -}
218   -
219 216 /*
220 217 * dirty pages logging control
221 218 */
... ... @@ -397,11 +394,6 @@ int kvm_check_extension(KVMState *s, unsigned int extension)
397 394 return ret;
398 395 }
399 396  
400   -static void kvm_reset_vcpus(void *opaque)
401   -{
402   - kvm_sync_vcpus();
403   -}
404   -
405 397 int kvm_init(int smp_cpus)
406 398 {
407 399 static const char upgrade_note[] =
... ... @@ -492,8 +484,6 @@ int kvm_init(int smp_cpus)
492 484 if (ret < 0)
493 485 goto err;
494 486  
495   - qemu_register_reset(kvm_reset_vcpus, INT_MAX, NULL);
496   -
497 487 kvm_state = s;
498 488  
499 489 return 0;
... ...
... ... @@ -32,7 +32,6 @@ struct kvm_run;
32 32 int kvm_init(int smp_cpus);
33 33  
34 34 int kvm_init_vcpu(CPUState *env);
35   -int kvm_sync_vcpus(void);
36 35  
37 36 int kvm_cpu_exec(CPUState *env);
38 37  
... ...
... ... @@ -6057,17 +6057,6 @@ int main(int argc, char **argv, char **envp)
6057 6057  
6058 6058 current_machine = machine;
6059 6059  
6060   - /* Set KVM's vcpu state to qemu's initial CPUState. */
6061   - if (kvm_enabled()) {
6062   - int ret;
6063   -
6064   - ret = kvm_sync_vcpus();
6065   - if (ret < 0) {
6066   - fprintf(stderr, "failed to initialize vcpus\n");
6067   - exit(1);
6068   - }
6069   - }
6070   -
6071 6060 /* init USB devices */
6072 6061 if (usb_enabled) {
6073 6062 for(i = 0; i < usb_devices_index; i++) {
... ...