Skip to contentSkip to conversation

Prepare for more qemu-kvm merging

PATCH Applied Jan Kiszka 4 participants 35 messages Jan 4, 2011 – Jan 5, 2011 KVM

lore
Share & tools
lore

Jan Kiszka

author
#0 lore raw

v3 cover Prepare for more qemu-kvm merging

Next round, addressing review comments and new findings:
- new: Flush coalesced mmio buffer on IO window exits
- new: Do not use qemu_fair_mutex in kvm mode
- new: Implicitly clear nmi_injected/pending on reset
- new: Fix !CONFIG_KVM_PARA build
- reworked: Read kvmclock only once per stopped phase
- reworked: Consolidate must-have capability checks
- reworked: Keep TSS/identity map reservation unconditional
- fixed: qemu-user breakage of CPU_DUMP_CODE patch
- fixed: Avoid redundant reset of MSR state variables

Jan Kiszka (21):
kvm: Fix coding style violations
kvm: Drop return value of kvm_cpu_exec
kvm: Stop on all fatal exit reasons
kvm: Improve reporting of fatal errors
x86: Optionally dump code bytes on cpu_dump_state
kvm: x86: Align kvm_arch_put_registers code with comment
kvm: x86: Prepare kvm_get_mp_state for in-kernel irqchip
kvm: x86: Remove redundant mp_state initialization
kvm: x86: Fix xcr0 reset mismerge
kvm: x86: Refactor msr_star/hsave_pa setup and checks
kvm: x86: Reset paravirtual MSRs
kvm: x86: Drop MCE MSRs write back restrictions
kvm: Eliminate KVMState arguments
kvm: x86: Fix !CONFIG_KVM_PARA build
kvm: x86: Introduce kvmclock device to save/restore its state
kvm: Drop smp_cpus argument from init functions
kvm: Consolidate must-have capability checks
kvm: x86: Rework identity map and TSS setup for larger BIOS sizes
kvm: Flush coalesced mmio buffer on IO window exits
kvm: Do not use qemu_fair_mutex
kvm: x86: Implicitly clear nmi_injected/pending on reset

 configure             |   39 +++--
 cpu-all.h             |    2 +
 cpu-defs.h            |    2 -
 cpus.c                |    2 -
 kvm-all.c             |  447 +++++++++++++++++++++++--------------------------
 kvm-stub.c            |    8 +-
 kvm.h                 |   29 ++--
 target-i386/cpu.h     |    8 +-
 target-i386/cpuid.c   |   14 +-
 target-i386/helper.c  |   21 +++
 target-i386/kvm.c     |  362 +++++++++++++++++++++++++---------------
 target-i386/kvm_x86.h |    3 +
 target-ppc/kvm.c      |   20 ++-
 target-s390x/kvm.c    |   12 +-
 vl.c                  |    2 +-
 15 files changed, 546 insertions(+), 425 deletions(-)
author
#1 lore raw

PATCH v3 1/21 kvm: Fix coding style violations

From: Jan Kiszka <[email protected]>

No functional changes.

---
 kvm-all.c |  139 ++++++++++++++++++++++++++++++++++--------------------------
 1 files changed, 79 insertions(+), 60 deletions(-)
kvm-all.c +79 -60
index 35fc73c..2538283 100644
@@ -82,10 +82,12 @@ static KVMSlot *kvm_alloc_slot(KVMState *s)
 
     for (i = 0; i < ARRAY_SIZE(s->slots); i++) {
         /* KVM private memory slots */
-        if (i >= 8 && i < 12)
+        if (i >= 8 && i < 12) {
             continue;
-        if (s->slots[i].memory_size == 0)
+        }
+        if (s->slots[i].memory_size == 0) {
             return &s->slots[i];
+        }
     }
 
     fprintf(stderr, "%s: no free slot available\n", __func__);
@@ -220,9 +222,10 @@ int kvm_init_vcpu(CPUState *env)
     }
 
 #ifdef KVM_CAP_COALESCED_MMIO
-    if (s->coalesced_mmio && !s->coalesced_mmio_ring)
-        s->coalesced_mmio_ring = (void *) env->kvm_run +
-		s->coalesced_mmio * PAGE_SIZE;
+    if (s->coalesced_mmio && !s->coalesced_mmio_ring) {
+        s->coalesced_mmio_ring =
+            (void *)env->kvm_run + s->coalesced_mmio * PAGE_SIZE;
+    }
 #endif
 
     ret = kvm_arch_init_vcpu(env);
@@ -269,16 +272,14 @@ static int kvm_dirty_pages_log_change(target_phys_addr_t phys_addr,
 
 int kvm_log_start(target_phys_addr_t phys_addr, ram_addr_t size)
 {
-        return kvm_dirty_pages_log_change(phys_addr, size,
-                                          KVM_MEM_LOG_DIRTY_PAGES,
-                                          KVM_MEM_LOG_DIRTY_PAGES);
+    return kvm_dirty_pages_log_change(phys_addr, size, KVM_MEM_LOG_DIRTY_PAGES,
+                                      KVM_MEM_LOG_DIRTY_PAGES);
 }
 
 int kvm_log_stop(target_phys_addr_t phys_addr, ram_addr_t size)
 {
-        return kvm_dirty_pages_log_change(phys_addr, size,
-                                          0,
-                                          KVM_MEM_LOG_DIRTY_PAGES);
+    return kvm_dirty_pages_log_change(phys_addr, size, 0,
+                                      KVM_MEM_LOG_DIRTY_PAGES);
 }
 
 static int kvm_set_migration_log(int enable)
@@ -350,7 +351,7 @@ static int kvm_get_dirty_pages_log_range(unsigned long start_addr,
  * @end_addr: end of logged region.
  */
 static int kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
-					  target_phys_addr_t end_addr)
+                                          target_phys_addr_t end_addr)
 {
     KVMState *s = kvm_state;
     unsigned long size, allocated_size = 0;
@@ -441,9 +442,8 @@ int kvm_check_extension(KVMState *s, unsigned int extension)
     return ret;
 }
 
-static void kvm_set_phys_mem(target_phys_addr_t start_addr,
-			     ram_addr_t size,
-			     ram_addr_t phys_offset)
+static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
+                             ram_addr_t phys_offset)
 {
     KVMState *s = kvm_state;
     ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
@@ -550,13 +550,13 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr,
     }
 
     /* in case the KVM bug workaround already "consumed" the new slot */
-    if (!size)
+    if (!size) {
         return;
-
+    }
     /* KVM does not need to know about this memory */
-    if (flags >= IO_MEM_UNASSIGNED)
+    if (flags >= IO_MEM_UNASSIGNED) {
         return;
-
+    }
     mem = kvm_alloc_slot(s);
     mem->memory_size = size;
     mem->start_addr = start_addr;
@@ -572,30 +572,29 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr,
 }
 
 static void kvm_client_set_memory(struct CPUPhysMemoryClient *client,
-				  target_phys_addr_t start_addr,
-				  ram_addr_t size,
-				  ram_addr_t phys_offset)
+                                  target_phys_addr_t start_addr,
+                                  ram_addr_t size, ram_addr_t phys_offset)
 {
-	kvm_set_phys_mem(start_addr, size, phys_offset);
+    kvm_set_phys_mem(start_addr, size, phys_offset);
 }
 
 static int kvm_client_sync_dirty_bitmap(struct CPUPhysMemoryClient *client,
-					target_phys_addr_t start_addr,
-					target_phys_addr_t end_addr)
+                                        target_phys_addr_t start_addr,
+                                        target_phys_addr_t end_addr)
 {
-	return kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
+    return kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
 }
 
 static int kvm_client_migration_log(struct CPUPhysMemoryClient *client,
-				    int enable)
+                                    int enable)
 {
-	return kvm_set_migration_log(enable);
+    return kvm_set_migration_log(enable);
 }
 
 static CPUPhysMemoryClient kvm_cpu_phys_memory_client = {
-	.set_memory = kvm_client_set_memory,
-	.sync_dirty_bitmap = kvm_client_sync_dirty_bitmap,
-	.migration_log = kvm_client_migration_log,
+    .set_memory = kvm_client_set_memory,
+    .sync_dirty_bitmap = kvm_client_sync_dirty_bitmap,
+    .migration_log = kvm_client_migration_log,
 };
 
 int kvm_init(int smp_cpus)
@@ -612,9 +611,9 @@ int kvm_init(int smp_cpus)
 #ifdef KVM_CAP_SET_GUEST_DEBUG
     QTAILQ_INIT(&s->kvm_sw_breakpoints);
 #endif
-    for (i = 0; i < ARRAY_SIZE(s->slots); i++)
+    for (i = 0; i < ARRAY_SIZE(s->slots); i++) {
         s->slots[i].slot = i;
-
+    }
     s->vmfd = -1;
     s->fd = qemu_open("/dev/kvm", O_RDWR);
     if (s->fd == -1) {
@@ -625,8 +624,9 @@ int kvm_init(int smp_cpus)
 
     ret = kvm_ioctl(s, KVM_GET_API_VERSION, 0);
     if (ret < KVM_API_VERSION) {
-        if (ret > 0)
+        if (ret > 0) {
             ret = -EINVAL;
+        }
         fprintf(stderr, "kvm version too old\n");
         goto err;
     }
@@ -711,8 +711,9 @@ int kvm_init(int smp_cpus)
 #endif
 
     ret = kvm_arch_init(s, smp_cpus);
-    if (ret < 0)
+    if (ret < 0) {
         goto err;
+    }
 
     kvm_state = s;
     cpu_register_phys_memory_client(&kvm_cpu_phys_memory_client);
@@ -721,10 +722,12 @@ int kvm_init(int smp_cpus)
 
 err:
     if (s) {
-        if (s->vmfd != -1)
+        if (s->vmfd != -1) {
             close(s->vmfd);
-        if (s->fd != -1)
+        }
+        if (s->fd != -1) {
             close(s->fd);
+        }
     }
     qemu_free(s);
 
@@ -788,8 +791,9 @@ static void kvm_handle_internal_error(CPUState *env, struct kvm_run *run)
     cpu_dump_state(env, stderr, fprintf, 0);
     if (run->internal.suberror == KVM_INTERNAL_ERROR_EMULATION) {
         fprintf(stderr, "emulation failure\n");
-        if (!kvm_arch_stop_on_emulation_error(env))
-		return;
+        if (!kvm_arch_stop_on_emulation_error(env)) {
+            return;
+        }
     }
     /* FIXME: Should trigger a qmp message to let management know
      * something went wrong.
@@ -829,8 +833,9 @@ static void do_kvm_cpu_synchronize_state(void *_env)
 
 void kvm_cpu_synchronize_state(CPUState *env)
 {
-    if (!env->kvm_vcpu_dirty)
+    if (!env->kvm_vcpu_dirty) {
         run_on_cpu(env, do_kvm_cpu_synchronize_state, env);
+    }
 }
 
 void kvm_cpu_synchronize_post_reset(CPUState *env)
@@ -970,9 +975,9 @@ int kvm_ioctl(KVMState *s, int type, ...)
     va_end(ap);
 
     ret = ioctl(s->fd, type, arg);
-    if (ret == -1)
+    if (ret == -1) {
         ret = -errno;
-
+    }
     return ret;
 }
 
@@ -987,9 +992,9 @@ int kvm_vm_ioctl(KVMState *s, int type, ...)
     va_end(ap);
 
     ret = ioctl(s->vmfd, type, arg);
-    if (ret == -1)
+    if (ret == -1) {
         ret = -errno;
-
+    }
     return ret;
 }
 
@@ -1004,9 +1009,9 @@ int kvm_vcpu_ioctl(CPUState *env, int type, ...)
     va_end(ap);
 
     ret = ioctl(env->kvm_fd, type, arg);
-    if (ret == -1)
+    if (ret == -1) {
         ret = -errno;
-
+    }
     return ret;
 }
 
@@ -1067,8 +1072,9 @@ struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *env,
     struct kvm_sw_breakpoint *bp;
 
     QTAILQ_FOREACH(bp, &env->kvm_state->kvm_sw_breakpoints, entry) {
-        if (bp->pc == pc)
+        if (bp->pc == pc) {
             return bp;
+        }
     }
     return NULL;
 }
@@ -1123,8 +1129,9 @@ int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
         }
 
         bp = qemu_malloc(sizeof(struct kvm_sw_breakpoint));
-        if (!bp)
+        if (!bp) {
             return -ENOMEM;
+        }
 
         bp->pc = addr;
         bp->use_count = 1;
@@ -1138,14 +1145,16 @@ int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
                           bp, entry);
     } else {
         err = kvm_arch_insert_hw_breakpoint(addr, len, type);
-        if (err)
+        if (err) {
             return err;
+        }
     }
 
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
         err = kvm_update_guest_debug(env, 0);
-        if (err)
+        if (err) {
             return err;
+        }
     }
     return 0;
 }
@@ -1159,8 +1168,9 @@ int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr,
 
     if (type == GDB_BREAKPOINT_SW) {
         bp = kvm_find_sw_breakpoint(current_env, addr);
-        if (!bp)
+        if (!bp) {
             return -ENOENT;
+        }
 
         if (bp->use_count > 1) {
             bp->use_count--;
@@ -1168,21 +1178,24 @@ int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr,
         }
 
         err = kvm_arch_remove_sw_breakpoint(current_env, bp);
-        if (err)
+        if (err) {
             return err;
+        }
 
         QTAILQ_REMOVE(&current_env->kvm_state->kvm_sw_breakpoints, bp, entry);
         qemu_free(bp);
     } else {
         err = kvm_arch_remove_hw_breakpoint(addr, len, type);
-        if (err)
+        if (err) {
             return err;
+        }
     }
 
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
         err = kvm_update_guest_debug(env, 0);
-        if (err)
+        if (err) {
             return err;
+        }
     }
     return 0;
 }
@@ -1197,15 +1210,17 @@ void kvm_remove_all_breakpoints(CPUState *current_env)
         if (kvm_arch_remove_sw_breakpoint(current_env, bp) != 0) {
             /* Try harder to find a CPU that currently sees the breakpoint. */
             for (env = first_cpu; env != NULL; env = env->next_cpu) {
-                if (kvm_arch_remove_sw_breakpoint(env, bp) == 0)
+                if (kvm_arch_remove_sw_breakpoint(env, bp) == 0) {
                     break;
+                }
             }
         }
     }
     kvm_arch_remove_all_hw_breakpoints();
 
-    for (env = first_cpu; env != NULL; env = env->next_cpu)
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
         kvm_update_guest_debug(env, 0);
+    }
 }
 
 #else /* !KVM_CAP_SET_GUEST_DEBUG */
@@ -1237,8 +1252,9 @@ int kvm_set_signal_mask(CPUState *env, const sigset_t *sigset)
     struct kvm_signal_mask *sigmask;
     int r;
 
-    if (!sigset)
+    if (!sigset) {
         return kvm_vcpu_ioctl(env, KVM_SET_SIGNAL_MASK, NULL);
+    }
 
     sigmask = qemu_malloc(sizeof(*sigmask) + sizeof(*sigset));
 
@@ -1293,13 +1309,16 @@ int kvm_set_ioeventfd_pio_word(int fd, uint16_t addr, uint16_t val, bool assign)
         .fd = fd,
     };
     int r;
-    if (!kvm_enabled())
+    if (!kvm_enabled()) {
         return -ENOSYS;
-    if (!assign)
+    }
+    if (!assign) {
         kick.flags |= KVM_IOEVENTFD_FLAG_DEASSIGN;
+    }
     r = kvm_vm_ioctl(kvm_state, KVM_IOEVENTFD, &kick);
-    if (r < 0)
+    if (r < 0) {
         return r;
+    }
     return 0;
 #else
     return -ENOSYS;
Signature · 1 line
1.7.1
author
#2 lore raw

PATCH v3 2/21 kvm: Drop return value of kvm_cpu_exec

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

It is not used, it is not needed, so let's remove it.

---
 kvm-all.c  |    6 ++----
 kvm-stub.c |    4 ++--
 kvm.h      |    2 +-
 3 files changed, 5 insertions(+), 7 deletions(-)
kvm-all.c +2 -4
index 2538283..7518f2c 100644
@@ -850,7 +850,7 @@ void kvm_cpu_synchronize_post_init(CPUState *env)
     env->kvm_vcpu_dirty = 0;
 }
 
-int kvm_cpu_exec(CPUState *env)
+void kvm_cpu_exec(CPUState *env)
 {
     struct kvm_run *run = env->kvm_run;
     int ret;
@@ -943,7 +943,7 @@ int kvm_cpu_exec(CPUState *env)
 #ifdef KVM_CAP_SET_GUEST_DEBUG
             if (kvm_arch_debug(&run->debug.arch)) {
                 env->exception_index = EXCP_DEBUG;
-                return 0;
+                return;
             }
             /* re-enter, this exception was guest-internal */
             ret = 1;
@@ -960,8 +960,6 @@ int kvm_cpu_exec(CPUState *env)
         env->exit_request = 0;
         env->exception_index = EXCP_INTERRUPT;
     }
-
-    return ret;
 }
 
 int kvm_ioctl(KVMState *s, int type, ...)
kvm-stub.c +2 -2
index 5384a4b..352c6a6 100644
@@ -79,9 +79,9 @@ void kvm_cpu_synchronize_post_init(CPUState *env)
 {
 }
 
-int kvm_cpu_exec(CPUState *env)
+void kvm_cpu_exec(CPUState *env)
 {
-    abort ();
+    abort();
 }
 
 int kvm_has_sync_mmu(void)
kvm.h +1 -1
index 60a9b42..51ad56f 100644
@@ -46,7 +46,7 @@ int kvm_has_xcrs(void);
 #ifdef NEED_CPU_H
 int kvm_init_vcpu(CPUState *env);
 
-int kvm_cpu_exec(CPUState *env);
+void kvm_cpu_exec(CPUState *env);
 
 #if !defined(CONFIG_USER_ONLY)
 int kvm_log_start(target_phys_addr_t phys_addr, ram_addr_t size);
Signature · 1 line
1.7.1
author
#3 lore raw

PATCH v3 3/21 kvm: Stop on all fatal exit reasons

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

Ensure that we stop the guest whenever we face a fatal or unknown exit reason. If we stop, we also have to enforce a cpu loop exit.

---
 kvm-all.c         |   15 +++++++++++----
 target-i386/kvm.c |    4 ++++
 target-ppc/kvm.c  |    4 ++++
 3 files changed, 19 insertions(+), 4 deletions(-)
kvm-all.c +11 -4
index 7518f2c..a46a3b6 100644
@@ -774,7 +774,7 @@ static int kvm_handle_io(uint16_t port, void *data, int direction, int size,
 }
 
 #ifdef KVM_CAP_INTERNAL_ERROR_DATA
-static void kvm_handle_internal_error(CPUState *env, struct kvm_run *run)
+static int kvm_handle_internal_error(CPUState *env, struct kvm_run *run)
 {
 
     if (kvm_check_extension(kvm_state, KVM_CAP_INTERNAL_ERROR_DATA)) {
@@ -792,13 +792,13 @@ static void kvm_handle_internal_error(CPUState *env, struct kvm_run *run)
     if (run->internal.suberror == KVM_INTERNAL_ERROR_EMULATION) {
         fprintf(stderr, "emulation failure\n");
         if (!kvm_arch_stop_on_emulation_error(env)) {
-            return;
+            return 0;
         }
     }
     /* FIXME: Should trigger a qmp message to let management know
      * something went wrong.
      */
-    vm_stop(0);
+    return -1;
 }
 #endif
 
@@ -926,16 +926,19 @@ void kvm_cpu_exec(CPUState *env)
             break;
         case KVM_EXIT_UNKNOWN:
             DPRINTF("kvm_exit_unknown\n");
+            ret = -1;
             break;
         case KVM_EXIT_FAIL_ENTRY:
             DPRINTF("kvm_exit_fail_entry\n");
+            ret = -1;
             break;
         case KVM_EXIT_EXCEPTION:
             DPRINTF("kvm_exit_exception\n");
+            ret = -1;
             break;
 #ifdef KVM_CAP_INTERNAL_ERROR_DATA
         case KVM_EXIT_INTERNAL_ERROR:
-            kvm_handle_internal_error(env, run);
+            ret = kvm_handle_internal_error(env, run);
             break;
 #endif
         case KVM_EXIT_DEBUG:
@@ -956,6 +959,10 @@ void kvm_cpu_exec(CPUState *env)
         }
     } while (ret > 0);
 
+    if (ret < 0) {
+        vm_stop(0);
+        env->exit_request = 1;
+    }
     if (env->exit_request) {
         env->exit_request = 0;
         env->exception_index = EXCP_INTERRUPT;
target-i386/kvm.c +4 -0
index fda07d2..2431a1f 100644
@@ -1534,6 +1534,10 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
         DPRINTF("handle_hlt\n");
         ret = kvm_handle_halt(env);
         break;
+    default:
+        fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
+        ret = -1;
+        break;
     }
 
     return ret;
target-ppc/kvm.c +4 -0
index 5caa07c..849b404 100644
@@ -307,6 +307,10 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
         dprintf("handle halt\n");
         ret = kvmppc_handle_halt(env);
         break;
+    default:
+        fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
+        ret = -1;
+        break;
     }
 
     return ret;
Signature · 1 line
1.7.1
author
#4 lore raw

PATCH v3 4/21 kvm: Improve reporting of fatal errors

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

Report KVM_EXIT_UNKNOWN, KVM_EXIT_FAIL_ENTRY, and KVM_EXIT_EXCEPTION with more details to stderr. The latter two are so far x86-only, so move them into the arch-specific handler. Integrate the Intel real mode warning on KVM_EXIT_FAIL_ENTRY that qemu-kvm carries, but actually restrict it to Intel CPUs. Moreover, always dump the CPU state in case we fail.

---
 kvm-all.c           |   22 ++++++++--------------
 target-i386/cpu.h   |    2 ++
 target-i386/cpuid.c |    5 ++---
 target-i386/kvm.c   |   33 +++++++++++++++++++++++++++++++++
 4 files changed, 45 insertions(+), 17 deletions(-)
kvm-all.c +8 -14
index a46a3b6..ad1d0a8 100644
@@ -776,22 +776,22 @@ static int kvm_handle_io(uint16_t port, void *data, int direction, int size,
 #ifdef KVM_CAP_INTERNAL_ERROR_DATA
 static int kvm_handle_internal_error(CPUState *env, struct kvm_run *run)
 {
-
+    fprintf(stderr, "KVM internal error.");
     if (kvm_check_extension(kvm_state, KVM_CAP_INTERNAL_ERROR_DATA)) {
         int i;
 
-        fprintf(stderr, "KVM internal error. Suberror: %d\n",
-                run->internal.suberror);
-
+        fprintf(stderr, " Suberror: %d\n", run->internal.suberror);
         for (i = 0; i < run->internal.ndata; ++i) {
             fprintf(stderr, "extra data[%d]: %"PRIx64"\n",
                     i, (uint64_t)run->internal.data[i]);
         }
+    } else {
+        fprintf(stderr, "\n");
     }
-    cpu_dump_state(env, stderr, fprintf, 0);
     if (run->internal.suberror == KVM_INTERNAL_ERROR_EMULATION) {
         fprintf(stderr, "emulation failure\n");
         if (!kvm_arch_stop_on_emulation_error(env)) {
+            cpu_dump_state(env, stderr, fprintf, 0);
             return 0;
         }
     }
@@ -925,15 +925,8 @@ void kvm_cpu_exec(CPUState *env)
             ret = 1;
             break;
         case KVM_EXIT_UNKNOWN:
-            DPRINTF("kvm_exit_unknown\n");
-            ret = -1;
-            break;
-        case KVM_EXIT_FAIL_ENTRY:
-            DPRINTF("kvm_exit_fail_entry\n");
-            ret = -1;
-            break;
-        case KVM_EXIT_EXCEPTION:
-            DPRINTF("kvm_exit_exception\n");
+            fprintf(stderr, "KVM: unknown exit, hardware reason %" PRIx64 "\n",
+                    (uint64_t)run->hw.hardware_exit_reason);
             ret = -1;
             break;
 #ifdef KVM_CAP_INTERNAL_ERROR_DATA
@@ -960,6 +953,7 @@ void kvm_cpu_exec(CPUState *env)
     } while (ret > 0);
 
     if (ret < 0) {
+        cpu_dump_state(env, stderr, fprintf, 0);
         vm_stop(0);
         env->exit_request = 1;
     }
target-i386/cpu.h +2 -0
index dddcd74..a457423 100644
@@ -874,6 +874,8 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
                    uint32_t *ecx, uint32_t *edx);
 int cpu_x86_register (CPUX86State *env, const char *cpu_model);
 void cpu_clear_apic_feature(CPUX86State *env);
+void host_cpuid(uint32_t function, uint32_t count,
+                uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
 
 /* helper.c */
 int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
target-i386/cpuid.c +2 -3
index 165045e..5382a28 100644
@@ -103,9 +103,8 @@ typedef struct model_features_t {
 int check_cpuid = 0;
 int enforce_cpuid = 0;
 
-static void host_cpuid(uint32_t function, uint32_t count,
-                       uint32_t *eax, uint32_t *ebx,
-                       uint32_t *ecx, uint32_t *edx)
+void host_cpuid(uint32_t function, uint32_t count,
+                uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
 {
 #if defined(CONFIG_KVM)
     uint32_t vec[4];
target-i386/kvm.c +33 -0
index 2431a1f..d4f253e 100644
@@ -1525,8 +1525,19 @@ static int kvm_handle_halt(CPUState *env)
     return 1;
 }
 
+static bool host_supports_vmx(void)
+{
+    uint32_t ecx, unused;
+
+    host_cpuid(1, 0, &unused, &unused, &ecx, &unused);
+    return ecx & CPUID_EXT_VMX;
+}
+
+#define VMX_INVALID_GUEST_STATE 0x80000021
+
 int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
 {
+    uint64_t code;
     int ret = 0;
 
     switch (run->exit_reason) {
@@ -1534,6 +1545,28 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
         DPRINTF("handle_hlt\n");
         ret = kvm_handle_halt(env);
         break;
+    case KVM_EXIT_FAIL_ENTRY:
+        code = run->fail_entry.hardware_entry_failure_reason;
+        fprintf(stderr, "KVM: entry failed, hardware error 0x%" PRIx64 "\n",
+                code);
+        if (host_supports_vmx() && code == VMX_INVALID_GUEST_STATE) {
+            fprintf(stderr,
+                    "\nIf you're runnning a guest on an Intel machine without "
+                        "unrestricted mode\n"
+                    "support, the failure can be most likely due to the guest "
+                        "entering an invalid\n"
+                    "state for Intel VT. For example, the guest maybe running "
+                        "in big real mode\n"
+                    "which is not supported on less recent Intel processors."
+                        "\n\n");
+        }
+        ret = -1;
+        break;
+    case KVM_EXIT_EXCEPTION:
+        fprintf(stderr, "KVM: exception %d exit (error code 0x%x)\n",
+                run->ex.exception, run->ex.error_code);
+        ret = -1;
+        break;
     default:
         fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
         ret = -1;
Signature · 1 line
1.7.1
author
#5 lore raw

PATCH v3 5/21 x86: Optionally dump code bytes on cpu_dump_state

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

Introduce the cpu_dump_state flag CPU_DUMP_CODE and implement it for x86. This writes out the code bytes around the current instruction pointer. Make use of this feature in KVM to help debugging fatal vm exits.

---
 cpu-all.h            |    2 ++
 kvm-all.c            |    4 ++--
 target-i386/helper.c |   21 +++++++++++++++++++++
 3 files changed, 25 insertions(+), 2 deletions(-)
cpu-all.h +2 -0
index 4ce4e83..ffbd6a4 100644
@@ -765,6 +765,8 @@ int page_check_range(target_ulong start, target_ulong len, int flags);
 CPUState *cpu_copy(CPUState *env);
 CPUState *qemu_get_cpu(int cpu);
 
+#define CPU_DUMP_CODE 0x00010000
+
 void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
                     int flags);
 void cpu_dump_statistics(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
kvm-all.c +2 -2
index ad1d0a8..ef2ca3b 100644
@@ -791,7 +791,7 @@ static int kvm_handle_internal_error(CPUState *env, struct kvm_run *run)
     if (run->internal.suberror == KVM_INTERNAL_ERROR_EMULATION) {
         fprintf(stderr, "emulation failure\n");
         if (!kvm_arch_stop_on_emulation_error(env)) {
-            cpu_dump_state(env, stderr, fprintf, 0);
+            cpu_dump_state(env, stderr, fprintf, CPU_DUMP_CODE);
             return 0;
         }
     }
@@ -953,7 +953,7 @@ void kvm_cpu_exec(CPUState *env)
     } while (ret > 0);
 
     if (ret < 0) {
-        cpu_dump_state(env, stderr, fprintf, 0);
+        cpu_dump_state(env, stderr, fprintf, CPU_DUMP_CODE);
         vm_stop(0);
         env->exit_request = 1;
     }
target-i386/helper.c +21 -0
index adf9542..fa37da3 100644
@@ -249,6 +249,9 @@ done:
     cpu_fprintf(f, "\n");
 }
 
+#define DUMP_CODE_BYTES_TOTAL    50
+#define DUMP_CODE_BYTES_BACKWARD 20
+
 void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
                     int flags)
 {
@@ -434,6 +437,24 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
                 cpu_fprintf(f, " ");
         }
     }
+    if (flags & CPU_DUMP_CODE) {
+        target_ulong base = env->segs[R_CS].base + env->eip;
+        target_ulong offs = MIN(env->eip, DUMP_CODE_BYTES_BACKWARD);
+        uint8_t code;
+        char codestr[3];
+
+        cpu_fprintf(f, "Code=");
+        for (i = 0; i < DUMP_CODE_BYTES_TOTAL; i++) {
+            if (cpu_memory_rw_debug(env, base - offs + i, &code, 1, 0) == 0) {
+                snprintf(codestr, sizeof(codestr), "%02x", code);
+            } else {
+                snprintf(codestr, sizeof(codestr), "??");
+            }
+            cpu_fprintf(f, "%s%s%s%s", i > 0 ? " ": "",
+                        i == offs ? "<" : "", codestr, i == offs ? ">" : "");
+        }
+        cpu_fprintf(f, "\n");
+    }
 }
 
 /***********************************************************/
Signature · 1 line
1.7.1
author
#6 lore raw

PATCH v3 6/21 kvm: x86: Align kvm_arch_put_registers code with comment

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

The ordering doesn't matter in this case, but better keep it consistent.

---
 target-i386/kvm.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)
target-i386/kvm.c +3 -3
index d4f253e..684430f 100644
@@ -1388,12 +1388,12 @@ int kvm_arch_put_registers(CPUState *env, int level)
     if (ret < 0) {
         return ret;
     }
-    /* must be last */
-    ret = kvm_guest_debug_workarounds(env);
+    ret = kvm_put_debugregs(env);
     if (ret < 0) {
         return ret;
     }
-    ret = kvm_put_debugregs(env);
+    /* must be last */
+    ret = kvm_guest_debug_workarounds(env);
     if (ret < 0) {
         return ret;
     }
Signature · 1 line
1.7.1
author
#7 lore raw

PATCH v3 7/21 kvm: x86: Prepare kvm_get_mp_state for in-kernel irqchip

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

This code path will not yet be taken as we still lack in-kernel irqchip support. But qemu-kvm can already make use of it and drop its own mp_state access services.

---
 target-i386/kvm.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
target-i386/kvm.c +3 -0
index 684430f..30aa51c 100644
@@ -1198,6 +1198,9 @@ static int kvm_get_mp_state(CPUState *env)
         return ret;
     }
     env->mp_state = mp_state.mp_state;
+    if (kvm_irqchip_in_kernel()) {
+        env->halted = (mp_state.mp_state == KVM_MP_STATE_HALTED);
+    }
     return 0;
 }
 
Signature · 1 line
1.7.1
author
#8 lore raw

PATCH v3 8/21 kvm: x86: Remove redundant mp_state initialization

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

kvm_arch_reset_vcpu initializes mp_state, and that function is invoked right after kvm_arch_init_vcpu.

---
 target-i386/kvm.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)
target-i386/kvm.c +0 -2
index 30aa51c..1403327 100644
@@ -321,8 +321,6 @@ int kvm_arch_init_vcpu(CPUState *env)
     uint32_t signature[3];
 #endif
 
-    env->mp_state = KVM_MP_STATE_RUNNABLE;
-
     env->cpuid_features &= kvm_arch_get_supported_cpuid(env, 1, 0, R_EDX);
 
     i = env->cpuid_ext_features & CPUID_EXT_HYPERVISOR;
Signature · 1 line
1.7.1
author
#9 lore raw

PATCH v3 9/21 kvm: x86: Fix xcr0 reset mismerge

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

For unknown reasons, xcr0 reset ended up in kvm_arch_update_guest_debug on upstream merge. Fix this and also remove the misleading comment (1 is THE reset value).

---
 target-i386/kvm.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)
target-i386/kvm.c +1 -2
index 1403327..e46b901 100644
@@ -450,6 +450,7 @@ void kvm_arch_reset_vcpu(CPUState *env)
     env->interrupt_injected = -1;
     env->nmi_injected = 0;
     env->nmi_pending = 0;
+    env->xcr0 = 1;
     if (kvm_irqchip_in_kernel()) {
         env->mp_state = cpu_is_bsp(env) ? KVM_MP_STATE_RUNNABLE :
                                           KVM_MP_STATE_UNINITIALIZED;
@@ -1756,8 +1757,6 @@ void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg)
                 ((uint32_t)len_code[hw_breakpoint[n].len] << (18 + n*4));
         }
     }
-    /* Legal xcr0 for loading */
-    env->xcr0 = 1;
 }
 #endif /* KVM_CAP_SET_GUEST_DEBUG */
 
Signature · 1 line
1.7.1
author
#10 lore raw

PATCH v3 10/21 kvm: x86: Refactor msr_star/hsave_pa setup and checks

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

Simplify kvm_has_msr_star/hsave_pa to booleans and push their one-time initialization into kvm_arch_init. Also handle potential errors of that setup procedure.

---
 target-i386/kvm.c |   47 +++++++++++++++++++----------------------------
 1 files changed, 19 insertions(+), 28 deletions(-)
target-i386/kvm.c +19 -28
index e46b901..d8f26bf 100644
@@ -54,6 +54,8 @@
 #define BUS_MCEERR_AO 5
 #endif
 
+static bool has_msr_star;
+static bool has_msr_hsave_pa;
 static int lm_capable_kernel;
 
 #ifdef KVM_CAP_EXT_CPUID
@@ -459,13 +461,10 @@ void kvm_arch_reset_vcpu(CPUState *env)
     }
 }
 
-int has_msr_star;
-int has_msr_hsave_pa;
-
-static void kvm_supported_msrs(CPUState *env)
+static int kvm_get_supported_msrs(KVMState *s)
 {
     static int kvm_supported_msrs;
-    int ret;
+    int ret = 0;
 
     /* first time */
     if (kvm_supported_msrs == 0) {
@@ -476,9 +475,9 @@ static void kvm_supported_msrs(CPUState *env)
         /* Obtain MSR list from KVM.  These are the MSRs that we must
          * save/restore */
         msr_list.nmsrs = 0;
-        ret = kvm_ioctl(env->kvm_state, KVM_GET_MSR_INDEX_LIST, &msr_list);
+        ret = kvm_ioctl(s, KVM_GET_MSR_INDEX_LIST, &msr_list);
         if (ret < 0 && ret != -E2BIG) {
-            return;
+            return ret;
         }
         /* Old kernel modules had a bug and could write beyond the provided
            memory. Allocate at least a safe amount of 1K. */
@@ -487,17 +486,17 @@ static void kvm_supported_msrs(CPUState *env)
                                               sizeof(msr_list.indices[0])));
 
         kvm_msr_list->nmsrs = msr_list.nmsrs;
-        ret = kvm_ioctl(env->kvm_state, KVM_GET_MSR_INDEX_LIST, kvm_msr_list);
+        ret = kvm_ioctl(s, KVM_GET_MSR_INDEX_LIST, kvm_msr_list);
         if (ret >= 0) {
             int i;
 
             for (i = 0; i < kvm_msr_list->nmsrs; i++) {
                 if (kvm_msr_list->indices[i] == MSR_STAR) {
-                    has_msr_star = 1;
+                    has_msr_star = true;
                     continue;
                 }
                 if (kvm_msr_list->indices[i] == MSR_VM_HSAVE_PA) {
-                    has_msr_hsave_pa = 1;
+                    has_msr_hsave_pa = true;
                     continue;
                 }
             }
@@ -506,19 +505,7 @@ static void kvm_supported_msrs(CPUState *env)
         free(kvm_msr_list);
     }
 
-    return;
-}
-
-static int kvm_has_msr_hsave_pa(CPUState *env)
-{
-    kvm_supported_msrs(env);
-    return has_msr_hsave_pa;
-}
-
-static int kvm_has_msr_star(CPUState *env)
-{
-    kvm_supported_msrs(env);
-    return has_msr_star;
+    return ret;
 }
 
 static int kvm_init_identity_map_page(KVMState *s)
@@ -543,9 +530,13 @@ static int kvm_init_identity_map_page(KVMState *s)
 int kvm_arch_init(KVMState *s, int smp_cpus)
 {
     int ret;
-
     struct utsname utsname;
 
+    ret = kvm_get_supported_msrs(s);
+    if (ret < 0) {
+        return ret;
+    }
+
     uname(&utsname);
     lm_capable_kernel = strcmp(utsname.machine, "x86_64") == 0;
 
@@ -830,10 +821,10 @@ static int kvm_put_msrs(CPUState *env, int level)
     kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_CS, env->sysenter_cs);
     kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_ESP, env->sysenter_esp);
     kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_EIP, env->sysenter_eip);
-    if (kvm_has_msr_star(env)) {
+    if (has_msr_star) {
         kvm_msr_entry_set(&msrs[n++], MSR_STAR, env->star);
     }
-    if (kvm_has_msr_hsave_pa(env)) {
+    if (has_msr_hsave_pa) {
         kvm_msr_entry_set(&msrs[n++], MSR_VM_HSAVE_PA, env->vm_hsave);
     }
 #ifdef TARGET_X86_64
@@ -1076,10 +1067,10 @@ static int kvm_get_msrs(CPUState *env)
     msrs[n++].index = MSR_IA32_SYSENTER_CS;
     msrs[n++].index = MSR_IA32_SYSENTER_ESP;
     msrs[n++].index = MSR_IA32_SYSENTER_EIP;
-    if (kvm_has_msr_star(env)) {
+    if (has_msr_star) {
         msrs[n++].index = MSR_STAR;
     }
-    if (kvm_has_msr_hsave_pa(env)) {
+    if (has_msr_hsave_pa) {
         msrs[n++].index = MSR_VM_HSAVE_PA;
     }
     msrs[n++].index = MSR_IA32_TSC;
Signature · 1 line
1.7.1
author
#11 lore raw

PATCH v3 11/21 kvm: x86: Reset paravirtual MSRs

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

Make sure to write the cleared MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK, and MSR_KVM_ASYNC_PF_EN to the kernel state so that a freshly booted guest cannot be disturbed by old values.

CC Glauber Costa <[email protected]>
---
 target-i386/kvm.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)
target-i386/kvm.c +7 -0
index d8f26bf..8267655 100644
@@ -845,6 +845,13 @@ static int kvm_put_msrs(CPUState *env, int level)
         if (smp_cpus == 1 || env->tsc != 0) {
             kvm_msr_entry_set(&msrs[n++], MSR_IA32_TSC, env->tsc);
         }
+    }
+    /*
+     * The following paravirtual MSRs have side effects on the guest or are
+     * too heavy for normal writeback. Limit them to reset or full state
+     * updates.
+     */
+    if (level >= KVM_PUT_RESET_STATE) {
         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);
Signature · 1 line
1.7.1
#12 lore raw

Re: [PATCH v3 11/21] kvm: x86: Reset paravirtual MSRs

Quoted 8 lines · Jan Kiszka

From: Jan Kiszka <[email protected]>

Make sure to write the cleared MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK, and MSR_KVM_ASYNC_PF_EN to the kernel state so that a freshly booted guest cannot be disturbed by old values.

CC Glauber Costa <[email protected]>

looks good.

Quoted 21 lines
 target-i386/kvm.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)
target-i386/kvm.c +7 -0
index d8f26bf..8267655 100644
@@ -845,6 +845,13 @@ static int kvm_put_msrs(CPUState *env, int level)
         if (smp_cpus == 1 || env->tsc != 0) {
             kvm_msr_entry_set(&msrs[n++], MSR_IA32_TSC, env->tsc);
         }
+    }
+    /*
+     * The following paravirtual MSRs have side effects on the guest or are
+     * too heavy for normal writeback. Limit them to reset or full state
+     * updates.
+     */
+    if (level >= KVM_PUT_RESET_STATE) {
         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);
author
#13 lore raw

PATCH v3 12/21 kvm: x86: Drop MCE MSRs write back restrictions

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

There is no need to restrict writing back MCE MSRs to reset or full state updates as setting their values has no side effects.

---
 target-i386/kvm.c |   12 ++++--------
 1 files changed, 4 insertions(+), 8 deletions(-)
target-i386/kvm.c +4 -8
index 8267655..1789bff 100644
@@ -863,14 +863,10 @@ static int kvm_put_msrs(CPUState *env, int level)
     if (env->mcg_cap) {
         int i;
 
-        if (level == KVM_PUT_RESET_STATE) {
-            kvm_msr_entry_set(&msrs[n++], MSR_MCG_STATUS, env->mcg_status);
-        } else if (level == KVM_PUT_FULL_STATE) {
-            kvm_msr_entry_set(&msrs[n++], MSR_MCG_STATUS, env->mcg_status);
-            kvm_msr_entry_set(&msrs[n++], MSR_MCG_CTL, env->mcg_ctl);
-            for (i = 0; i < (env->mcg_cap & 0xff) * 4; i++) {
-                kvm_msr_entry_set(&msrs[n++], MSR_MC0_CTL + i, env->mce_banks[i]);
-            }
+        kvm_msr_entry_set(&msrs[n++], MSR_MCG_STATUS, env->mcg_status);
+        kvm_msr_entry_set(&msrs[n++], MSR_MCG_CTL, env->mcg_ctl);
+        for (i = 0; i < (env->mcg_cap & 0xff) * 4; i++) {
+            kvm_msr_entry_set(&msrs[n++], MSR_MC0_CTL + i, env->mce_banks[i]);
         }
     }
 #endif
Signature · 1 line
1.7.1
#14 lore raw

Re: [PATCH v3 12/21] kvm: x86: Drop MCE MSRs write back restrictions

Quoted 4 lines · Jan Kiszka

From: Jan Kiszka <[email protected]>

There is no need to restrict writing back MCE MSRs to reset or full state updates as setting their values has no side effects.

Sorry for late.

The MCE MSRs contents is sticky for warm reset except MCG_STATUS, so their content should be kept. And the following sequence may set uncorrected value in MCE registers.

savevm -> loadvm -> (OS clear MCE registers) -> reset -> (MCE registers has new (uncorrected) value)

Best Regards,
Huang Ying

Quoted 29 lines
---
 target-i386/kvm.c |   12 ++++--------
 1 files changed, 4 insertions(+), 8 deletions(-)
target-i386/kvm.c +4 -8
index 8267655..1789bff 100644
@@ -863,14 +863,10 @@ static int kvm_put_msrs(CPUState *env, int level)
     if (env->mcg_cap) {
         int i;
 
-        if (level == KVM_PUT_RESET_STATE) {
-            kvm_msr_entry_set(&msrs[n++], MSR_MCG_STATUS, env->mcg_status);
-        } else if (level == KVM_PUT_FULL_STATE) {
-            kvm_msr_entry_set(&msrs[n++], MSR_MCG_STATUS, env->mcg_status);
-            kvm_msr_entry_set(&msrs[n++], MSR_MCG_CTL, env->mcg_ctl);
-            for (i = 0; i < (env->mcg_cap & 0xff) * 4; i++) {
-                kvm_msr_entry_set(&msrs[n++], MSR_MC0_CTL + i, env->mce_banks[i]);
-            }
+        kvm_msr_entry_set(&msrs[n++], MSR_MCG_STATUS, env->mcg_status);
+        kvm_msr_entry_set(&msrs[n++], MSR_MCG_CTL, env->mcg_ctl);
+        for (i = 0; i < (env->mcg_cap & 0xff) * 4; i++) {
+            kvm_msr_entry_set(&msrs[n++], MSR_MC0_CTL + i, env->mce_banks[i]);
         }
     }
 #endif
author
#15 lore raw

Re: [PATCH v3 12/21] kvm: x86: Drop MCE MSRs write back restrictions

Quoted 7 lines · Huang Ying
Quoted 4 lines · Jan Kiszka

From: Jan Kiszka <[email protected]>

There is no need to restrict writing back MCE MSRs to reset or full state updates as setting their values has no side effects.

Sorry for late.

Don't worry.

Quoted 7 lines

The MCE MSRs contents is sticky for warm reset except MCG_STATUS, so their content should be kept. And the following sequence may set uncorrected value in MCE registers.

savevm -> loadvm -> (OS clear MCE registers) -> reset -> (MCE registers has new (uncorrected) value)

Sorry, I can't follow. Unless I miss some subtle detail, the question is not when we transfer the mcg_* CPUState fields to the kernel, but when and how we manipulate them in user space, e.g. on reset. Where are those fields touched incorrectly between get and put msrs so that we cannot write them back?

Jan

#16 lore raw

Re: [PATCH v3 12/21] kvm: x86: Drop MCE MSRs write back restrictions

Quoted 16 lines · Jan Kiszka
Quoted 7 lines · Huang Ying
Quoted 4 lines · Jan Kiszka

From: Jan Kiszka <[email protected]>

There is no need to restrict writing back MCE MSRs to reset or full state updates as setting their values has no side effects.

Sorry for late.

Don't worry.

Quoted 5 lines

The MCE MSRs contents is sticky for warm reset except MCG_STATUS, so their content should be kept. And the following sequence may set uncorrected value in MCE registers.

Quoted 8 lines
Quoted 2 lines

savevm -> loadvm -> (OS clear MCE registers) -> reset -> (MCE registers has new (uncorrected) value)

Sorry, I can't follow. Unless I miss some subtle detail, the question is not when we transfer the mcg_* CPUState fields to the kernel, but when and how we manipulate them in user space, e.g. on reset. Where are those fields touched incorrectly between get and put msrs so that we cannot write them back?

If my understanding is correct, MSRs are not saved to user space (env->mce_banks) during reset in current code. So if all MCE MSRs are restored to kernel, their user space contents from previous loadvm may be put into kernel after reset.

Best Regards,
Huang Ying

author
#17 lore raw

Re: [PATCH v3 12/21] kvm: x86: Drop MCE MSRs write back restrictions

Quoted 26 lines · Huang Ying
Quoted 16 lines · Jan Kiszka
Quoted 7 lines · Huang Ying
Quoted 4 lines · Jan Kiszka

From: Jan Kiszka <[email protected]>

There is no need to restrict writing back MCE MSRs to reset or full state updates as setting their values has no side effects.

Sorry for late.

Don't worry.

Quoted 5 lines

The MCE MSRs contents is sticky for warm reset except MCG_STATUS, so their content should be kept. And the following sequence may set uncorrected value in MCE registers.

Quoted 8 lines
Quoted 2 lines

savevm -> loadvm -> (OS clear MCE registers) -> reset -> (MCE registers has new (uncorrected) value)

Sorry, I can't follow. Unless I miss some subtle detail, the question is not when we transfer the mcg_* CPUState fields to the kernel, but when and how we manipulate them in user space, e.g. on reset. Where are those fields touched incorrectly between get and put msrs so that we cannot write them back?

Quoted 4 lines

If my understanding is correct, MSRs are not saved to user space (env->mce_banks) during reset in current code. So if all MCE MSRs are restored to kernel, their user space contents from previous loadvm may be put into kernel after reset.

Ah, good point! We need

vl.c +1 -0
index 1958e01..23d4169 100644
@@ -1353,6 +1353,7 @@ static void main_loop(void)
         }
         if (qemu_reset_requested()) {
             pause_all_vcpus();
+            cpu_synchronize_all_states();
             qemu_system_reset();
             resume_all_vcpus();
         }

and corresponding (sigh...) qemu-kvm patch. Will post them.

Jan

author
#18 lore raw

PATCH v3 13/21 kvm: Eliminate KVMState arguments

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

QEMU supports only one VM, so there is only one kvm_state per process, and we gain nothing passing a reference to it around. Eliminate any need to refer to it outside of kvm-all.c.

CC Alexander Graf <[email protected]>
---
 cpu-defs.h            |    2 -
 kvm-all.c             |  232 +++++++++++++++++++++----------------------------
 kvm-stub.c            |    2 +-
 kvm.h                 |   15 +--
 target-i386/cpuid.c   |    9 +-
 target-i386/kvm.c     |   77 ++++++++--------
 target-i386/kvm_x86.h |    3 +
 target-ppc/kvm.c      |   12 ++--
 target-s390x/kvm.c    |    8 +--
 9 files changed, 160 insertions(+), 200 deletions(-)
cpu-defs.h +0 -2
index eaed43e..ada6629 100644
@@ -131,7 +131,6 @@ typedef struct icount_decr_u16 {
 #endif
 
 struct kvm_run;
-struct KVMState;
 struct qemu_work_item;
 
 typedef struct CPUBreakpoint {
@@ -208,7 +207,6 @@ typedef struct CPUWatchpoint {
     struct QemuCond *halt_cond;                                         \
     struct qemu_work_item *queued_work_first, *queued_work_last;        \
     const char *cpu_model_str;                                          \
-    struct KVMState *kvm_state;                                         \
     struct kvm_run *kvm_run;                                            \
     int kvm_fd;                                                         \
     int kvm_vcpu_dirty;
kvm-all.c +100 -132

662 lines not on this page · raw message

kvm-stub.c +1 -1
index 352c6a6..3a058ad 100644
@@ -53,7 +53,7 @@ int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
     return -ENOSYS;
 }
 
-int kvm_check_extension(KVMState *s, unsigned int extension)
+int kvm_check_extension(unsigned int extension)
 {
     return 0;
 }
kvm.h +5 -10
index 51ad56f..26ca8c1 100644
@@ -74,12 +74,9 @@ int kvm_irqchip_in_kernel(void);
 
 /* internal API */
 
-struct KVMState;
-typedef struct KVMState KVMState;
+int kvm_ioctl(int type, ...);
 
-int kvm_ioctl(KVMState *s, int type, ...);
-
-int kvm_vm_ioctl(KVMState *s, int type, ...);
+int kvm_vm_ioctl(int type, ...);
 
 int kvm_vcpu_ioctl(CPUState *env, int type, ...);
 
@@ -104,7 +101,7 @@ int kvm_arch_get_registers(CPUState *env);
 
 int kvm_arch_put_registers(CPUState *env, int level);
 
-int kvm_arch_init(KVMState *s, int smp_cpus);
+int kvm_arch_init(int smp_cpus);
 
 int kvm_arch_init_vcpu(CPUState *env);
 
@@ -146,10 +143,8 @@ void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg);
 
 bool kvm_arch_stop_on_emulation_error(CPUState *env);
 
-int kvm_check_extension(KVMState *s, unsigned int extension);
+int kvm_check_extension(unsigned int extension);
 
-uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,
-                                      uint32_t index, int reg);
 void kvm_cpu_synchronize_state(CPUState *env);
 void kvm_cpu_synchronize_post_reset(CPUState *env);
 void kvm_cpu_synchronize_post_init(CPUState *env);
@@ -179,7 +174,7 @@ static inline void cpu_synchronize_post_init(CPUState *env)
 
 
 #if !defined(CONFIG_USER_ONLY)
-int kvm_physical_memory_addr_from_ram(KVMState *s, ram_addr_t ram_addr,
+int kvm_physical_memory_addr_from_ram(ram_addr_t ram_addr,
                                       target_phys_addr_t *phys_addr);
 #endif
 
target-i386/cpuid.c +5 -4
index 5382a28..17ab619 100644
@@ -23,6 +23,7 @@
 
 #include "cpu.h"
 #include "kvm.h"
+#include "kvm_x86.h"
 
 #include "qemu-option.h"
 #include "qemu-config.h"
@@ -1138,10 +1139,10 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
             break;
         }
         if (kvm_enabled()) {
-            *eax = kvm_arch_get_supported_cpuid(env, 0xd, count, R_EAX);
-            *ebx = kvm_arch_get_supported_cpuid(env, 0xd, count, R_EBX);
-            *ecx = kvm_arch_get_supported_cpuid(env, 0xd, count, R_ECX);
-            *edx = kvm_arch_get_supported_cpuid(env, 0xd, count, R_EDX);
+            *eax = kvm_x86_get_supported_cpuid(0xd, count, R_EAX);
+            *ebx = kvm_x86_get_supported_cpuid(0xd, count, R_EBX);
+            *ecx = kvm_x86_get_supported_cpuid(0xd, count, R_ECX);
+            *edx = kvm_x86_get_supported_cpuid(0xd, count, R_EDX);
         } else {
             *eax = 0;
             *ebx = 0;
target-i386/kvm.c +38 -39

233 lines not on this page · raw message

target-i386/kvm_x86.h +3 -0
index 9d7b584..304d0cb 100644
@@ -22,4 +22,7 @@ void kvm_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
                         uint64_t mcg_status, uint64_t addr, uint64_t misc,
                         int flag);
 
+uint32_t kvm_x86_get_supported_cpuid(uint32_t function, uint32_t index,
+                                     int reg);
+
 #endif
target-ppc/kvm.c +6 -6
index 849b404..56d30cc 100644
@@ -56,13 +56,13 @@ static void kvm_kick_env(void *env)
     qemu_cpu_kick(env);
 }
 
-int kvm_arch_init(KVMState *s, int smp_cpus)
+int kvm_arch_init(int smp_cpus)
 {
 #ifdef KVM_CAP_PPC_UNSET_IRQ
-    cap_interrupt_unset = kvm_check_extension(s, KVM_CAP_PPC_UNSET_IRQ);
+    cap_interrupt_unset = kvm_check_extension(KVM_CAP_PPC_UNSET_IRQ);
 #endif
 #ifdef KVM_CAP_PPC_IRQ_LEVEL
-    cap_interrupt_level = kvm_check_extension(s, KVM_CAP_PPC_IRQ_LEVEL);
+    cap_interrupt_level = kvm_check_extension(KVM_CAP_PPC_IRQ_LEVEL);
 #endif
 
     if (!cap_interrupt_level) {
@@ -164,7 +164,7 @@ int kvm_arch_get_registers(CPUState *env)
         env->gpr[i] = regs.gpr[i];
 
 #ifdef KVM_CAP_PPC_SEGSTATE
-    if (kvm_check_extension(env->kvm_state, KVM_CAP_PPC_SEGSTATE)) {
+    if (kvm_check_extension(KVM_CAP_PPC_SEGSTATE)) {
         env->sdr1 = sregs.u.s.sdr1;
 
         /* Sync SLB */
@@ -371,8 +371,8 @@ int kvmppc_get_hypercall(CPUState *env, uint8_t *buf, int buf_len)
 #ifdef KVM_CAP_PPC_GET_PVINFO
     struct kvm_ppc_pvinfo pvinfo;
 
-    if (kvm_check_extension(env->kvm_state, KVM_CAP_PPC_GET_PVINFO) &&
-        !kvm_vm_ioctl(env->kvm_state, KVM_PPC_GET_PVINFO, &pvinfo)) {
+    if (kvm_check_extension(KVM_CAP_PPC_GET_PVINFO) &&
+        !kvm_vm_ioctl(KVM_PPC_GET_PVINFO, &pvinfo)) {
         memcpy(buf, pvinfo.hcall, buf_len);
 
         return 0;
target-s390x/kvm.c +2 -6
index adf4a9e..927a37e 100644
@@ -70,7 +70,7 @@
 #define SCLP_CMDW_READ_SCP_INFO         0x00020001
 #define SCLP_CMDW_READ_SCP_INFO_FORCED  0x00120001
 
-int kvm_arch_init(KVMState *s, int smp_cpus)
+int kvm_arch_init(int smp_cpus)
 {
     return 0;
 }
@@ -186,10 +186,6 @@ static void kvm_s390_interrupt_internal(CPUState *env, int type, uint32_t parm,
     struct kvm_s390_interrupt kvmint;
     int r;
 
-    if (!env->kvm_state) {
-        return;
-    }
-
     env->halted = 0;
     env->exception_index = -1;
 
@@ -198,7 +194,7 @@ static void kvm_s390_interrupt_internal(CPUState *env, int type, uint32_t parm,
     kvmint.parm64 = parm64;
 
     if (vm) {
-        r = kvm_vm_ioctl(env->kvm_state, KVM_S390_INTERRUPT, &kvmint);
+        r = kvm_vm_ioctl(KVM_S390_INTERRUPT, &kvmint);
     } else {
         r = kvm_vcpu_ioctl(env, KVM_S390_INTERRUPT, &kvmint);
     }
Signature · 1 line
1.7.1
author
#19 lore raw

PATCH v3 14/21 kvm: x86: Fix !CONFIG_KVM_PARA build

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

If we lack kvm_para.h, MSR_KVM_ASYNC_PF_EN is not defined. The change in kvm_arch_init_vcpu is just for consistency reasons.

---
 target-i386/kvm.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)
target-i386/kvm.c +4 -4
index cb6883f..69b8234 100644
@@ -318,7 +318,7 @@ int kvm_arch_init_vcpu(CPUState *env)
     uint32_t limit, i, j, cpuid_i;
     uint32_t unused;
     struct kvm_cpuid_entry2 *c;
-#ifdef KVM_CPUID_SIGNATURE
+#ifdef CONFIG_KVM_PARA
     uint32_t signature[3];
 #endif
 
@@ -854,7 +854,7 @@ static int kvm_put_msrs(CPUState *env, int level)
         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);
-#ifdef KVM_CAP_ASYNC_PF
+#if defined(CONFIG_KVM_PARA) && defined(KVM_CAP_ASYNC_PF)
         kvm_msr_entry_set(&msrs[n++], MSR_KVM_ASYNC_PF_EN, env->async_pf_en_msr);
 #endif
     }
@@ -1086,7 +1086,7 @@ static int kvm_get_msrs(CPUState *env)
 #endif
     msrs[n++].index = MSR_KVM_SYSTEM_TIME;
     msrs[n++].index = MSR_KVM_WALL_CLOCK;
-#ifdef KVM_CAP_ASYNC_PF
+#if defined(CONFIG_KVM_PARA) && defined(KVM_CAP_ASYNC_PF)
     msrs[n++].index = MSR_KVM_ASYNC_PF_EN;
 #endif
 
@@ -1162,7 +1162,7 @@ static int kvm_get_msrs(CPUState *env)
             }
 #endif
             break;
-#ifdef KVM_CAP_ASYNC_PF
+#if defined(CONFIG_KVM_PARA) && defined(KVM_CAP_ASYNC_PF)
         case MSR_KVM_ASYNC_PF_EN:
             env->async_pf_en_msr = msrs[i].data;
             break;
Signature · 1 line
1.7.1
author
#20 lore raw

PATCH v3 15/21 kvm: x86: Introduce kvmclock device to save/restore its state

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

If kvmclock is used, which implies the kernel supports it, register a kvmclock device with the sysbus. Its main purpose is to save and restore the kernel state on migration, but this will also allow to visualize it one day.

CC Glauber Costa <[email protected]>
---
 target-i386/kvm.c |   92 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 91 insertions(+), 1 deletions(-)
target-i386/kvm.c +91 -1
index 69b8234..47cb22b 100644
@@ -29,6 +29,7 @@
 #include "hw/apic.h"
 #include "ioport.h"
 #include "kvm_x86.h"
+#include "hw/sysbus.h"
 
 #ifdef CONFIG_KVM_PARA
 #include <linux/kvm_para.h>
@@ -309,6 +310,85 @@ void kvm_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
 #endif
 }
 
+#if defined(CONFIG_KVM_PARA) && defined(KVM_CAP_ADJUST_CLOCK)
+typedef struct KVMClockState {
+    SysBusDevice busdev;
+    uint64_t clock;
+    bool clock_valid;
+} KVMClockState;
+
+static void kvmclock_pre_save(void *opaque)
+{
+    KVMClockState *s = opaque;
+    struct kvm_clock_data data;
+    int ret;
+
+    if (s->clock_valid) {
+        return;
+    }
+    ret = kvm_vm_ioctl(KVM_GET_CLOCK, &data);
+    if (ret < 0) {
+        fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret));
+        data.clock = 0;
+    }
+    s->clock = data.clock;
+    /*
+     * If the VM is stopped, declare the clock state valid to avoid re-reading
+     * it on next vmsave (which would return a different value). Will be reset
+     * when the VM is continued.
+     */
+    s->clock_valid = !vm_running;
+}
+
+static int kvmclock_post_load(void *opaque, int version_id)
+{
+    KVMClockState *s = opaque;
+    struct kvm_clock_data data;
+
+    data.clock = s->clock;
+    data.flags = 0;
+    return kvm_vm_ioctl(KVM_SET_CLOCK, &data);
+}
+
+static void kvmclock_vm_state_change(void *opaque, int running, int reason)
+{
+    KVMClockState *s = opaque;
+
+    if (running) {
+        s->clock_valid = false;
+    }
+}
+
+static int kvmclock_init(SysBusDevice *dev)
+{
+    KVMClockState *s = FROM_SYSBUS(KVMClockState, dev);
+
+    qemu_add_vm_change_state_handler(kvmclock_vm_state_change, s);
+    return 0;
+}
+
+static const VMStateDescription kvmclock_vmsd= {
+    .name = "kvmclock",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .pre_save = kvmclock_pre_save,
+    .post_load = kvmclock_post_load,
+    .fields = (VMStateField []) {
+        VMSTATE_UINT64(clock, KVMClockState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static SysBusDeviceInfo kvmclock_info = {
+    .qdev.name = "kvmclock",
+    .qdev.size = sizeof(KVMClockState),
+    .qdev.vmsd = &kvmclock_vmsd,
+    .qdev.no_user = 1,
+    .init = kvmclock_init,
+};
+#endif /* CONFIG_KVM_PARA && KVM_CAP_ADJUST_CLOCK */
+
 int kvm_arch_init_vcpu(CPUState *env)
 {
     struct {
@@ -335,7 +415,6 @@ int kvm_arch_init_vcpu(CPUState *env)
     env->cpuid_svm_features  &= kvm_x86_get_supported_cpuid(0x8000000A,
                                                             0, R_EDX);
 
-
     cpuid_i = 0;
 
 #ifdef CONFIG_KVM_PARA
@@ -442,6 +521,13 @@ int kvm_arch_init_vcpu(CPUState *env)
     }
 #endif
 
+#if defined(CONFIG_KVM_PARA) && defined(KVM_CAP_ADJUST_CLOCK)
+    if (cpu_is_bsp(env) &&
+        (env->cpuid_kvm_features & (1ULL << KVM_FEATURE_CLOCKSOURCE))) {
+        sysbus_create_simple("kvmclock", -1, NULL);
+    }
+#endif
+
     return kvm_vcpu_ioctl(env, KVM_SET_CPUID2, &cpuid_data);
 }
 
@@ -531,6 +617,10 @@ int kvm_arch_init(int smp_cpus)
     int ret;
     struct utsname utsname;
 
+#if defined(CONFIG_KVM_PARA) && defined(KVM_CAP_ADJUST_CLOCK)
+    sysbus_register_withprop(&kvmclock_info);
+#endif
+
     ret = kvm_get_supported_msrs();
     if (ret < 0) {
         return ret;
Signature · 1 line
1.7.1
#21 lore raw

Re: [PATCH v3 15/21] kvm: x86: Introduce kvmclock device to save/restore its state

Quoted 6 lines · Jan Kiszka

From: Jan Kiszka <[email protected]>

If kvmclock is used, which implies the kernel supports it, register a kvmclock device with the sysbus. Its main purpose is to save and restore the kernel state on migration, but this will also allow to visualize it one day.

I would prefer having no pre-save, and doing the ioctl in the state change handler. But I won't nitpick about that, if the maintainers think this is okay, all the rest of the patch looks fine as well.

author
#22 lore raw

Re: [PATCH v3 15/21] kvm: x86: Introduce kvmclock device to save/restore its state

Quoted 11 lines · Glauber Costa
Quoted 6 lines · Jan Kiszka

From: Jan Kiszka <[email protected]>

If kvmclock is used, which implies the kernel supports it, register a kvmclock device with the sysbus. Its main purpose is to save and restore the kernel state on migration, but this will also allow to visualize it one day.

I would prefer having no pre-save, and doing the ioctl in the state change handler. But I won't nitpick about that, if the maintainers think this is okay, all the rest of the patch looks fine as well.

I did this for a reason: to be able to obtain the current clock state even while the vm is running. It's cleaner IMHO.

Jan

#23 lore raw

Re: [PATCH v3 15/21] kvm: x86: Introduce kvmclock device to save/restore its state

Quoted 9 lines · Jan Kiszka
Quoted 8 lines · Glauber Costa
Quoted 6 lines · Jan Kiszka

From: Jan Kiszka <[email protected]>

If kvmclock is used, which implies the kernel supports it, register a kvmclock device with the sysbus. Its main purpose is to save and restore the kernel state on migration, but this will also allow to visualize it one day.

Quoted 6 lines
Quoted 3 lines

I would prefer having no pre-save, and doing the ioctl in the state change handler. But I won't nitpick about that, if the maintainers think this is okay, all the rest of the patch looks fine as well.

I did this for a reason: to be able to obtain the current clock state even while the vm is running. It's cleaner IMHO.

but if we're on pre-save, we are certain that the vm is stopped at this moment, no ?

author
#24 lore raw

Re: [PATCH v3 15/21] kvm: x86: Introduce kvmclock device to save/restore its state

Quoted 14 lines · Glauber Costa
Quoted 13 lines · Jan Kiszka
Quoted 11 lines · Glauber Costa
Quoted 6 lines · Jan Kiszka

From: Jan Kiszka <[email protected]>

If kvmclock is used, which implies the kernel supports it, register a kvmclock device with the sysbus. Its main purpose is to save and restore the kernel state on migration, but this will also allow to visualize it one day.

I would prefer having no pre-save, and doing the ioctl in the state change handler. But I won't nitpick about that, if the maintainers think this is okay, all the rest of the patch looks fine as well.

Quoted 5 lines
Quoted 2 lines

I did this for a reason: to be able to obtain the current clock state even while the vm is running. It's cleaner IMHO.

but if we're on pre-save, we are certain that the vm is stopped at this moment, no ?

Maybe at the moment, but not for device state dumping or maybe (dunno) for Kemari's continuous sync'ing. I simply want to avoid this implicit dependency.

Jan

#25 lore raw

Re: [PATCH v3 15/21] kvm: x86: Introduce kvmclock device to save/restore its state

Quoted 18 lines · Jan Kiszka
Quoted 17 lines · Glauber Costa
Quoted 15 lines · Jan Kiszka
Quoted 11 lines · Glauber Costa
Quoted 6 lines · Jan Kiszka

From: Jan Kiszka <[email protected]>

If kvmclock is used, which implies the kernel supports it, register a kvmclock device with the sysbus. Its main purpose is to save and restore the kernel state on migration, but this will also allow to visualize it one day.

I would prefer having no pre-save, and doing the ioctl in the state change handler. But I won't nitpick about that, if the maintainers think this is okay, all the rest of the patch looks fine as well.

I did this for a reason: to be able to obtain the current clock state even while the vm is running. It's cleaner IMHO.

Quoted 6 lines
Quoted 2 lines

but if we're on pre-save, we are certain that the vm is stopped at this moment, no ?

Maybe at the moment, but not for device state dumping or maybe (dunno) for Kemari's continuous sync'ing. I simply want to avoid this implicit dependency.

that's fine.

author
#26 lore raw

PATCH v3 16/21 kvm: Drop smp_cpus argument from init functions

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

No longer used.

---
 kvm-all.c          |    4 ++--
 kvm-stub.c         |    2 +-
 kvm.h              |    4 ++--
 target-i386/kvm.c  |    2 +-
 target-ppc/kvm.c   |    2 +-
 target-s390x/kvm.c |    2 +-
 vl.c               |    2 +-
 7 files changed, 9 insertions(+), 9 deletions(-)
kvm-all.c +2 -2
index d8820c7..190fcdf 100644
@@ -584,7 +584,7 @@ static CPUPhysMemoryClient kvm_cpu_phys_memory_client = {
     .migration_log = kvm_client_migration_log,
 };
 
-int kvm_init(int smp_cpus)
+int kvm_init(void)
 {
     static const char upgrade_note[] =
         "Please upgrade to at least kernel 2.6.29 or recent kvm-kmod\n"
@@ -687,7 +687,7 @@ int kvm_init(int smp_cpus)
     kvm_state.xcrs = kvm_check_extension(KVM_CAP_XCRS);
 #endif
 
-    ret = kvm_arch_init(smp_cpus);
+    ret = kvm_arch_init();
     if (ret < 0) {
         goto err;
     }
kvm-stub.c +1 -1
index 3a058ad..e00d7df 100644
@@ -58,7 +58,7 @@ int kvm_check_extension(unsigned int extension)
     return 0;
 }
 
-int kvm_init(int smp_cpus)
+int kvm_init(void)
 {
     return -ENOSYS;
 }
kvm.h +2 -2
index 26ca8c1..31d9f21 100644
@@ -34,7 +34,7 @@ struct kvm_run;
 
 /* external API */
 
-int kvm_init(int smp_cpus);
+int kvm_init(void);
 
 int kvm_has_sync_mmu(void);
 int kvm_has_vcpu_events(void);
@@ -101,7 +101,7 @@ int kvm_arch_get_registers(CPUState *env);
 
 int kvm_arch_put_registers(CPUState *env, int level);
 
-int kvm_arch_init(int smp_cpus);
+int kvm_arch_init(void);
 
 int kvm_arch_init_vcpu(CPUState *env);
 
target-i386/kvm.c +1 -1
index 47cb22b..a907578 100644
@@ -612,7 +612,7 @@ static int kvm_init_identity_map_page(void)
     return 0;
 }
 
-int kvm_arch_init(int smp_cpus)
+int kvm_arch_init(void)
 {
     int ret;
     struct utsname utsname;
target-ppc/kvm.c +1 -1
index 56d30cc..72f2f94 100644
@@ -56,7 +56,7 @@ static void kvm_kick_env(void *env)
     qemu_cpu_kick(env);
 }
 
-int kvm_arch_init(int smp_cpus)
+int kvm_arch_init(void)
 {
 #ifdef KVM_CAP_PPC_UNSET_IRQ
     cap_interrupt_unset = kvm_check_extension(KVM_CAP_PPC_UNSET_IRQ);
target-s390x/kvm.c +1 -1
index 927a37e..4f9075c 100644
@@ -70,7 +70,7 @@
 #define SCLP_CMDW_READ_SCP_INFO         0x00020001
 #define SCLP_CMDW_READ_SCP_INFO_FORCED  0x00120001
 
-int kvm_arch_init(int smp_cpus)
+int kvm_arch_init(void)
 {
     return 0;
 }
vl.c +1 -1
index 768dbf4..abe4af8 100644
@@ -2834,7 +2834,7 @@ int main(int argc, char **argv, char **envp)
     }
 
     if (kvm_allowed) {
-        int ret = kvm_init(smp_cpus);
+        int ret = kvm_init();
         if (ret < 0) {
             if (!kvm_available()) {
                 printf("KVM not supported for this target\n");
Signature · 1 line
1.7.1
author
#27 lore raw

PATCH v3 17/21 kvm: Consolidate must-have capability checks

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

Instead of splattering the code with #ifdefs and runtime checks for capabilities we cannot work without anyway, provide central test infrastructure for verifying their availability both at build and runtime.

---
 configure          |   39 ++++++++++++++++++++++-----------
 kvm-all.c          |   61 ++++++++++++++++++++++-----------------------------
 kvm.h              |   10 ++++++++
 target-i386/kvm.c  |   39 ++++++--------------------------
 target-ppc/kvm.c   |    4 +++
 target-s390x/kvm.c |    4 +++
 6 files changed, 78 insertions(+), 79 deletions(-)
configure +26 -13
index ec37a91..e6ee5c3 100755
@@ -1665,18 +1665,31 @@ if test "$kvm" != "no" ; then
 #if !defined(KVM_API_VERSION) || KVM_API_VERSION < 12 || KVM_API_VERSION > 12
 #error Invalid KVM version
 #endif
-#if !defined(KVM_CAP_USER_MEMORY)
-#error Missing KVM capability KVM_CAP_USER_MEMORY
-#endif
-#if !defined(KVM_CAP_SET_TSS_ADDR)
-#error Missing KVM capability KVM_CAP_SET_TSS_ADDR
-#endif
-#if !defined(KVM_CAP_DESTROY_MEMORY_REGION_WORKS)
-#error Missing KVM capability KVM_CAP_DESTROY_MEMORY_REGION_WORKS
-#endif
-#if !defined(KVM_CAP_USER_NMI)
-#error Missing KVM capability KVM_CAP_USER_NMI
+EOF
+    must_have_caps="KVM_CAP_USER_MEMORY \
+                    KVM_CAP_DESTROY_MEMORY_REGION_WORKS \
+                    KVM_CAP_COALESCED_MMIO \
+                    KVM_CAP_SYNC_MMU \
+                   "
+    if test \( "$cpu" = "i386" -o "$cpu" = "x86_64" \) ; then
+      must_have_caps="$caps \
+                      KVM_CAP_SET_TSS_ADDR \
+                      KVM_CAP_EXT_CPUID \
+                      KVM_CAP_CLOCKSOURCE \
+                      KVM_CAP_NOP_IO_DELAY \
+                      KVM_CAP_PV_MMU \
+                      KVM_CAP_MP_STATE \
+                      KVM_CAP_USER_NMI \
+                     "
+    fi
+    for c in $must_have_caps ; do
+      cat >> $TMPC <<EOF
+#if !defined($c)
+#error Missing KVM capability $c
 #endif
+EOF
+    done
+    cat >> $TMPC <<EOF
 int main(void) { return 0; }
 EOF
   if test "$kerneldir" != "" ; then
@@ -1711,8 +1724,8 @@ EOF
 	| awk -F "error: " '{if (NR>1) printf(", "); printf("%s",$2);}'`
         if test "$kvmerr" != "" ; then
           echo -e "${kvmerr}\n\
-      NOTE: To enable KVM support, update your kernel to 2.6.29+ or install \
-  recent kvm-kmod from http://sourceforge.net/projects/kvm."
+NOTE: To enable KVM support, update your kernel to 2.6.29+ or install \
+recent kvm-kmod from http://sourceforge.net/projects/kvm."
         fi
       fi
       feature_not_found "kvm"
kvm-all.c +26 -35

151 lines not on this page · raw message

kvm.h +10 -0
index 31d9f21..153d7b9 100644
@@ -32,6 +32,14 @@ extern int kvm_allowed;
 
 struct kvm_run;
 
+typedef struct KVMCapabilityInfo {
+    const char *name;
+    int value;
+} KVMCapabilityInfo;
+
+#define KVM_CAP_INFO(CAP) { "KVM_CAP_" stringify(CAP), KVM_CAP_##CAP }
+#define KVM_CAP_LAST_INFO { NULL, 0 }
+
 /* external API */
 
 int kvm_init(void);
@@ -82,6 +90,8 @@ int kvm_vcpu_ioctl(CPUState *env, int type, ...);
 
 /* Arch specific hooks */
 
+extern const KVMCapabilityInfo kvm_arch_required_capabilities[];
+
 int kvm_arch_post_run(CPUState *env, struct kvm_run *run);
 
 int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run);
target-i386/kvm.c +8 -31
index a907578..58122d9 100644
@@ -55,12 +55,17 @@
 #define BUS_MCEERR_AO 5
 #endif
 
+const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
+    KVM_CAP_INFO(SET_TSS_ADDR),
+    KVM_CAP_INFO(EXT_CPUID),
+    KVM_CAP_INFO(MP_STATE),
+    KVM_CAP_LAST_INFO
+};
+
 static bool has_msr_star;
 static bool has_msr_hsave_pa;
 static int lm_capable_kernel;
 
-#ifdef KVM_CAP_EXT_CPUID
-
 static struct kvm_cpuid2 *try_get_cpuid(int max)
 {
     struct kvm_cpuid2 *cpuid;
@@ -94,10 +99,6 @@ uint32_t kvm_x86_get_supported_cpuid(uint32_t function, uint32_t index,
     uint32_t ret = 0;
     uint32_t cpuid_1_edx;
 
-    if (!kvm_check_extension(KVM_CAP_EXT_CPUID)) {
-        return -1U;
-    }
-
     max = 1;
     while ((cpuid = try_get_cpuid(max)) == NULL) {
         max *= 2;
@@ -141,30 +142,14 @@ uint32_t kvm_x86_get_supported_cpuid(uint32_t function, uint32_t index,
     return ret;
 }
 
-#else
-
-uint32_t kvm_x86_get_supported_cpuid(uint32_t function, uint32_t index,
-                                     int reg)
-{
-    return -1U;
-}
-
-#endif
-
 #ifdef CONFIG_KVM_PARA
 struct kvm_para_features {
     int cap;
     int feature;
 } para_features[] = {
-#ifdef KVM_CAP_CLOCKSOURCE
     { KVM_CAP_CLOCKSOURCE, KVM_FEATURE_CLOCKSOURCE },
-#endif
-#ifdef KVM_CAP_NOP_IO_DELAY
     { KVM_CAP_NOP_IO_DELAY, KVM_FEATURE_NOP_IO_DELAY },
-#endif
-#ifdef KVM_CAP_PV_MMU
     { KVM_CAP_PV_MMU, KVM_FEATURE_MMU_OP },
-#endif
 #ifdef KVM_CAP_ASYNC_PF
     { KVM_CAP_ASYNC_PF, KVM_FEATURE_ASYNC_PF },
 #endif
@@ -631,15 +616,7 @@ int kvm_arch_init(void)
 
     /* create vm86 tss.  KVM uses vm86 mode to emulate 16-bit code
      * directly.  In order to use vm86 mode, a TSS is needed.  Since this
-     * must be part of guest physical memory, we need to allocate it.  Older
-     * versions of KVM just assumed that it would be at the end of physical
-     * memory but that doesn't work with more than 4GB of memory.  We simply
-     * refuse to work with those older versions of KVM. */
-    ret = kvm_check_extension(KVM_CAP_SET_TSS_ADDR);
-    if (ret <= 0) {
-        fprintf(stderr, "kvm does not support KVM_CAP_SET_TSS_ADDR\n");
-        return ret;
-    }
+     * must be part of guest physical memory, we need to allocate it. */
 
     /* this address is 3 pages before the bios, and the bios should present
      * as unavaible memory.  FIXME, need to ensure the e820 map deals with
target-ppc/kvm.c +4 -0
index 72f2f94..7918426 100644
@@ -37,6 +37,10 @@
     do { } while (0)
 #endif
 
+const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
+    KVM_CAP_LAST_INFO
+};
+
 static int cap_interrupt_unset = false;
 static int cap_interrupt_level = false;
 
target-s390x/kvm.c +4 -0
index 4f9075c..29fcd46 100644
@@ -70,6 +70,10 @@
 #define SCLP_CMDW_READ_SCP_INFO         0x00020001
 #define SCLP_CMDW_READ_SCP_INFO_FORCED  0x00120001
 
+const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
+    KVM_CAP_LAST_INFO
+};
+
 int kvm_arch_init(void)
 {
     return 0;
Signature · 1 line
1.7.1
author
#28 lore raw

PATCH v3 18/21 kvm: x86: Rework identity map and TSS setup for larger BIOS sizes

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

In order to support loading BIOSes > 256K, reorder the code, adjusting the base if the kernel supports moving the identity map.

---
 target-i386/kvm.c |   63 +++++++++++++++++++++++++---------------------------
 1 files changed, 30 insertions(+), 33 deletions(-)
target-i386/kvm.c +30 -33
index 58122d9..50d8ec8 100644
@@ -578,27 +578,9 @@ static int kvm_get_supported_msrs(void)
     return ret;
 }
 
-static int kvm_init_identity_map_page(void)
-{
-#ifdef KVM_CAP_SET_IDENTITY_MAP_ADDR
-    int ret;
-    uint64_t addr = 0xfffbc000;
-
-    if (!kvm_check_extension(KVM_CAP_SET_IDENTITY_MAP_ADDR)) {
-        return 0;
-    }
-
-    ret = kvm_vm_ioctl(KVM_SET_IDENTITY_MAP_ADDR, &addr);
-    if (ret < 0) {
-        fprintf(stderr, "kvm_set_identity_map_addr: %s\n", strerror(ret));
-        return ret;
-    }
-#endif
-    return 0;
-}
-
 int kvm_arch_init(void)
 {
+    uint64_t identity_base = 0xfffbc000;
     int ret;
     struct utsname utsname;
 
@@ -614,27 +596,42 @@ int kvm_arch_init(void)
     uname(&utsname);
     lm_capable_kernel = strcmp(utsname.machine, "x86_64") == 0;
 
-    /* create vm86 tss.  KVM uses vm86 mode to emulate 16-bit code
-     * directly.  In order to use vm86 mode, a TSS is needed.  Since this
-     * must be part of guest physical memory, we need to allocate it. */
-
-    /* this address is 3 pages before the bios, and the bios should present
-     * as unavaible memory.  FIXME, need to ensure the e820 map deals with
-     * this?
-     */
     /*
-     * Tell fw_cfg to notify the BIOS to reserve the range.
+     * On older Intel CPUs, KVM uses vm86 mode to emulate 16-bit code directly.
+     * In order to use vm86 mode, an EPT identity map and a TSS  are needed.
+     * Since these must be part of guest physical memory, we need to allocate
+     * them, both by setting their start addresses in the kernel and by
+     * creating a corresponding e820 entry. We need 4 pages before the BIOS.
+     *
+     * Older KVM versions may not support setting the identity map base. In
+     * that case we need to stick with the default, i.e. a 256K maximum BIOS
+     * size.
      */
-    if (e820_add_entry(0xfffbc000, 0x4000, E820_RESERVED) < 0) {
-        perror("e820_add_entry() table is full");
-        exit(1);
+#ifdef KVM_CAP_SET_IDENTITY_MAP_ADDR
+    if (kvm_check_extension(KVM_CAP_SET_IDENTITY_MAP_ADDR)) {
+        /* Allows up to 16M BIOSes. */
+        identity_base = 0xfeffc000;
+
+        ret = kvm_vm_ioctl(KVM_SET_IDENTITY_MAP_ADDR, &identity_base);
+        if (ret < 0) {
+            return ret;
+        }
     }
-    ret = kvm_vm_ioctl(KVM_SET_TSS_ADDR, 0xfffbd000);
+#endif
+    /* Set TSS base one page after EPT identity map. */
+    ret = kvm_vm_ioctl(KVM_SET_TSS_ADDR, identity_base + 0x1000);
+    if (ret < 0) {
+        return ret;
+    }
+
+    /* Tell fw_cfg to notify the BIOS to reserve the range. */
+    ret = e820_add_entry(identity_base, 0x4000, E820_RESERVED);
     if (ret < 0) {
+        fprintf(stderr, "e820_add_entry() table is full\n");
         return ret;
     }
 
-    return kvm_init_identity_map_page();
+    return 0;
 }
 
 static void set_v8086_seg(struct kvm_segment *lhs, const SegmentCache *rhs)
Signature · 1 line
1.7.1
author
#29 lore raw

PATCH v3 19/21 kvm: Flush coalesced mmio buffer on IO window exits

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

We must flush pending mmio writes if we leave kvm_cpu_exec for an IO window. Otherwise we risk to loose those requests when migrating to a different host during that window.

---
 kvm-all.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
kvm-all.c +2 -2
index 7a5b299..a5e9246 100644
@@ -851,6 +851,8 @@ void kvm_cpu_exec(CPUState *env)
         cpu_single_env = env;
         kvm_arch_post_run(env, run);
 
+        kvm_flush_coalesced_mmio_buffer();
+
         if (ret == -EINTR || ret == -EAGAIN) {
             cpu_exit(env);
             DPRINTF("io window exit\n");
@@ -863,8 +865,6 @@ void kvm_cpu_exec(CPUState *env)
             abort();
         }
 
-        kvm_flush_coalesced_mmio_buffer();
-
         ret = 0; /* exit loop */
         switch (run->exit_reason) {
         case KVM_EXIT_IO:
Signature · 1 line
1.7.1
author
#30 lore raw

PATCH v3 20/21 kvm: Do not use qemu_fair_mutex

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

The imbalance in the hold time of qemu_global_mutex only exists in TCG mode. In contrast to TCG VCPUs, KVM drops the global lock during guest execution. We already avoid touching the fairness lock from the IO-thread in KVM mode, so also stop using it from the VCPU threads.

---
 cpus.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)
cpus.c +0 -2
index 2847dcf..db74530 100644
@@ -740,9 +740,7 @@ static sigset_t block_io_signals(void)
 void qemu_mutex_lock_iothread(void)
 {
     if (kvm_enabled()) {
-        qemu_mutex_lock(&qemu_fair_mutex);
         qemu_mutex_lock(&qemu_global_mutex);
-        qemu_mutex_unlock(&qemu_fair_mutex);
     } else {
         qemu_mutex_lock(&qemu_fair_mutex);
         if (qemu_mutex_trylock(&qemu_global_mutex)) {
Signature · 1 line
1.7.1
author
#31 lore raw

PATCH v3 21/21 kvm: x86: Implicitly clear nmi_injected/pending on reset

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

All CPUX86State variables before CPU_COMMON are automatically cleared on reset. Reorder nmi_injected and nmi_pending to avoid having to touch them explicitly.

---
 target-i386/cpu.h |    6 ++++--
 target-i386/kvm.c |    2 --
 2 files changed, 4 insertions(+), 4 deletions(-)
target-i386/cpu.h +4 -2
index a457423..af701a4 100644
@@ -699,6 +699,10 @@ typedef struct CPUX86State {
     uint32_t smbase;
     int old_exception;  /* exception in flight */
 
+    /* KVM states, automatically cleared on reset */
+    uint8_t nmi_injected;
+    uint8_t nmi_pending;
+
     CPU_COMMON
 
     /* processor features (e.g. for CPUID insn) */
@@ -726,8 +730,6 @@ typedef struct CPUX86State {
     int32_t exception_injected;
     int32_t interrupt_injected;
     uint8_t soft_interrupt;
-    uint8_t nmi_injected;
-    uint8_t nmi_pending;
     uint8_t has_error_code;
     uint32_t sipi_vector;
     uint32_t cpuid_kvm_features;
target-i386/kvm.c +0 -2
index 50d8ec8..79a1da8 100644
@@ -520,8 +520,6 @@ void kvm_arch_reset_vcpu(CPUState *env)
 {
     env->exception_injected = -1;
     env->interrupt_injected = -1;
-    env->nmi_injected = 0;
-    env->nmi_pending = 0;
     env->xcr0 = 1;
     if (kvm_irqchip_in_kernel()) {
         env->mp_state = cpu_is_bsp(env) ? KVM_MP_STATE_RUNNABLE :
Signature · 1 line
1.7.1
author
#32 lore raw

PATCH 1/1 Synchronize VCPU states before reset

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

This is required to support keeping VCPU states across a system reset. If we do not read the current state before the reset, cpu_synchronize_all_post_reset may write back incorrect state information.

The first user of this will be MCE MSR synchronization which currently works around the missing cpu_synchronize_all_states.

---

This must be applied before "Drop MCE MSRs write back restrictions" (I don't want to resend the whole series for this).

 vl.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
vl.c +1 -0
index 768dbf4..20e5dda 100644
@@ -1422,6 +1422,7 @@ static void main_loop(void)
         }
         if (qemu_reset_requested()) {
             pause_all_vcpus();
+            cpu_synchronize_all_states();
             qemu_system_reset();
             resume_all_vcpus();
         }
author
#33 lore raw

[PATCH 22/21] kvm: x86: Only read/write MSR_KVM_ASYNC_PF_EN if supported

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

If the kernel does not support KVM_CAP_ASYNC_PF, it also does not know about the related MSR. So skip it during state synchronization in that case. Fixes annoying kernel warnings.

---
 target-i386/kvm.c |   12 ++++++++++--
 1 files changed, 10 insertions(+), 2 deletions(-)
target-i386/kvm.c +10 -2
index 79a1da8..af79526 100644
@@ -64,6 +64,9 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
 
 static bool has_msr_star;
 static bool has_msr_hsave_pa;
+#if defined(CONFIG_KVM_PARA) && defined(KVM_CAP_ASYNC_PF)
+static bool has_msr_async_pf_en;
+#endif
 static int lm_capable_kernel;
 
 static struct kvm_cpuid2 *try_get_cpuid(int max)
@@ -165,6 +168,7 @@ static int get_para_features(void)
             features |= (1 << para_features[i].feature);
         }
     }
+    has_msr_async_pf_en = features & (1 << KVM_FEATURE_ASYNC_PF);
     return features;
 }
 #endif
@@ -917,7 +921,9 @@ static int kvm_put_msrs(CPUState *env, int level)
                           env->system_time_msr);
         kvm_msr_entry_set(&msrs[n++], MSR_KVM_WALL_CLOCK, env->wall_clock_msr);
 #if defined(CONFIG_KVM_PARA) && defined(KVM_CAP_ASYNC_PF)
-        kvm_msr_entry_set(&msrs[n++], MSR_KVM_ASYNC_PF_EN, env->async_pf_en_msr);
+        if (has_msr_async_pf_en) {
+            kvm_msr_entry_set(&msrs[n++], MSR_KVM_ASYNC_PF_EN, env->async_pf_en_msr);
+        }
 #endif
     }
 #ifdef KVM_CAP_MCE
@@ -1149,7 +1155,9 @@ static int kvm_get_msrs(CPUState *env)
     msrs[n++].index = MSR_KVM_SYSTEM_TIME;
     msrs[n++].index = MSR_KVM_WALL_CLOCK;
 #if defined(CONFIG_KVM_PARA) && defined(KVM_CAP_ASYNC_PF)
-    msrs[n++].index = MSR_KVM_ASYNC_PF_EN;
+    if (has_msr_async_pf_en) {
+        msrs[n++].index = MSR_KVM_ASYNC_PF_EN;
+    }
 #endif
 
 #ifdef KVM_CAP_MCE
#34 lore raw
In reply to Jan Kiszka
Quoted 25 lines · Jan Kiszka

Next round, addressing review comments and new findings:
- new: Flush coalesced mmio buffer on IO window exits
- new: Do not use qemu_fair_mutex in kvm mode
- new: Implicitly clear nmi_injected/pending on reset
- new: Fix !CONFIG_KVM_PARA build
- reworked: Read kvmclock only once per stopped phase
- reworked: Consolidate must-have capability checks
- reworked: Keep TSS/identity map reservation unconditional
- fixed: qemu-user breakage of CPU_DUMP_CODE patch
- fixed: Avoid redundant reset of MSR state variables

Jan Kiszka (21):
kvm: Fix coding style violations
kvm: Drop return value of kvm_cpu_exec
kvm: Stop on all fatal exit reasons
kvm: Improve reporting of fatal errors
x86: Optionally dump code bytes on cpu_dump_state
kvm: x86: Align kvm_arch_put_registers code with comment
kvm: x86: Prepare kvm_get_mp_state for in-kernel irqchip
kvm: x86: Remove redundant mp_state initialization
kvm: x86: Fix xcr0 reset mismerge
kvm: x86: Refactor msr_star/hsave_pa setup and checks
kvm: x86: Reset paravirtual MSRs
kvm: x86: Drop MCE MSRs write back restrictions
kvm: Eliminate KVMState arguments

Quoted 8 lines

kvm: x86: Fix !CONFIG_KVM_PARA build
kvm: x86: Introduce kvmclock device to save/restore its state
kvm: Drop smp_cpus argument from init functions
kvm: Consolidate must-have capability checks
kvm: x86: Rework identity map and TSS setup for larger BIOS sizes
kvm: Flush coalesced mmio buffer on IO window exits
kvm: Do not use qemu_fair_mutex
kvm: x86: Implicitly clear nmi_injected/pending on reset

Applied, thanks.