From 618a568da4eda5c2e41fc4e58059546806afff6b Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Mon, 3 May 2010 18:12:23 -0300 Subject: [PATCH 01/12] Fix -mem-path with hugetlbfs Fallback to qemu_vmalloc in case file_ram_alloc fails. Signed-off-by: Marcelo Tosatti Signed-off-by: Avi Kivity --- exec.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/exec.c b/exec.c index 3416aed08..56b556188 100644 --- a/exec.c +++ b/exec.c @@ -2775,8 +2775,12 @@ ram_addr_t qemu_ram_alloc(ram_addr_t size) if (mem_path) { #if defined (__linux__) && !defined(TARGET_S390X) new_block->host = file_ram_alloc(size, mem_path); - if (!new_block->host) - exit(1); + if (!new_block->host) { + new_block->host = qemu_vmalloc(size); +#ifdef MADV_MERGEABLE + madvise(new_block->host, size, MADV_MERGEABLE); +#endif + } #else fprintf(stderr, "-mem-path option unsupported\n"); exit(1); From 273faf1b6dbdedd0fe9fc519ec73380eced667c2 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Tue, 4 May 2010 09:45:19 -0300 Subject: [PATCH 02/12] kvm: set cpu_single_env around KVM_RUN ioctl Zero cpu_single_env before leaving global lock protection, and restore on return. Signed-off-by: Marcelo Tosatti Signed-off-by: Avi Kivity --- kvm-all.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kvm-all.c b/kvm-all.c index 6962b2bbe..fbd084cd6 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -838,9 +838,11 @@ int kvm_cpu_exec(CPUState *env) } kvm_arch_pre_run(env, run); + cpu_single_env = NULL; qemu_mutex_unlock_iothread(); ret = kvm_vcpu_ioctl(env, KVM_RUN, 0); qemu_mutex_lock_iothread(); + cpu_single_env = env; kvm_arch_post_run(env, run); if (ret == -EINTR || ret == -EAGAIN) { From 1a28cac3161f8a85ee0256776068eaed2da025e5 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Tue, 4 May 2010 09:45:20 -0300 Subject: [PATCH 03/12] make SIG_IPI to tcg vcpu thread reliable Store tcg loop exit request on a global variable, and transfer it to per-CPUState exit_request after assignment of cpu_single_env. This makes exit request signal from robust. Drop the timedlock hack. Signed-off-by: Marcelo Tosatti Signed-off-by: Avi Kivity --- cpu-exec.c | 7 +++++++ cpus.c | 23 +++++++++-------------- exec-all.h | 3 +++ 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/cpu-exec.c b/cpu-exec.c index dc81e7943..c776605e0 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -213,6 +213,8 @@ static void cpu_handle_debug_exception(CPUState *env) /* main execution loop */ +volatile sig_atomic_t exit_request; + int cpu_exec(CPUState *env1) { volatile host_reg_t saved_env_reg; @@ -234,6 +236,11 @@ int cpu_exec(CPUState *env1) asm(""); env = env1; + if (exit_request) { + env->exit_request = 1; + exit_request = 0; + } + #if defined(TARGET_I386) if (!kvm_enabled()) { /* put eflags in CPU temporary format */ diff --git a/cpus.c b/cpus.c index 29462e5c9..53226b3d9 100644 --- a/cpus.c +++ b/cpus.c @@ -472,6 +472,7 @@ static void cpu_signal(int sig) { if (cpu_single_env) cpu_exit(cpu_single_env); + exit_request = 1; } static void tcg_block_io_signals(void) @@ -542,26 +543,20 @@ static void unblock_io_signals(void) pthread_sigmask(SIG_BLOCK, &set, NULL); } -static void qemu_signal_lock(unsigned int msecs) -{ - qemu_mutex_lock(&qemu_fair_mutex); - - while (qemu_mutex_trylock(&qemu_global_mutex)) { - qemu_thread_signal(tcg_cpu_thread, SIG_IPI); - if (!qemu_mutex_timedlock(&qemu_global_mutex, msecs)) - break; - } - qemu_mutex_unlock(&qemu_fair_mutex); -} - 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_signal_lock(100); + } else { + qemu_mutex_lock(&qemu_fair_mutex); + if (qemu_mutex_trylock(&qemu_global_mutex)) { + qemu_thread_signal(tcg_cpu_thread, SIG_IPI); + qemu_mutex_lock(&qemu_global_mutex); + } + qemu_mutex_unlock(&qemu_fair_mutex); + } } void qemu_mutex_unlock_iothread(void) diff --git a/exec-all.h b/exec-all.h index 1016de2a4..4565dd060 100644 --- a/exec-all.h +++ b/exec-all.h @@ -351,4 +351,7 @@ CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler); /* vl.c */ extern int singlestep; +/* cpu-exec.c */ +extern volatile sig_atomic_t exit_request; + #endif From 1fbb22e5f8be9f7793251e5258b23936643f677c Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Tue, 4 May 2010 09:45:21 -0300 Subject: [PATCH 04/12] standardize on qemu_cpu_kick for signalling cpu thread(s) Signed-off-by: Marcelo Tosatti Signed-off-by: Avi Kivity --- cpus.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/cpus.c b/cpus.c index 53226b3d9..5afdb4ad7 100644 --- a/cpus.c +++ b/cpus.c @@ -454,8 +454,7 @@ void qemu_cpu_kick(void *_env) { CPUState *env = _env; qemu_cond_broadcast(env->halt_cond); - if (kvm_enabled()) - qemu_thread_signal(env->thread, SIG_IPI); + qemu_thread_signal(env->thread, SIG_IPI); } int qemu_cpu_self(void *_env) @@ -583,7 +582,6 @@ void pause_all_vcpus(void) while (penv) { penv->stop = 1; - qemu_thread_signal(penv->thread, SIG_IPI); qemu_cpu_kick(penv); penv = (CPUState *)penv->next_cpu; } @@ -592,7 +590,7 @@ void pause_all_vcpus(void) qemu_cond_timedwait(&qemu_pause_cond, &qemu_global_mutex, 100); penv = first_cpu; while (penv) { - qemu_thread_signal(penv->thread, SIG_IPI); + qemu_cpu_kick(penv); penv = (CPUState *)penv->next_cpu; } } @@ -605,7 +603,6 @@ void resume_all_vcpus(void) while (penv) { penv->stop = 0; penv->stopped = 0; - qemu_thread_signal(penv->thread, SIG_IPI); qemu_cpu_kick(penv); penv = (CPUState *)penv->next_cpu; } From e82bcec25f19846bfb899d55c9fb5915516b378a Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Tue, 4 May 2010 09:45:22 -0300 Subject: [PATCH 05/12] port qemu-kvm's on_vcpu code run_on_cpu allows to execute work on a given CPUState context. Signed-off-by: Marcelo Tosatti Signed-off-by: Avi Kivity --- cpu-all.h | 1 + cpu-defs.h | 2 ++ cpus.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++ qemu-common.h | 8 ++++++++ 4 files changed, 64 insertions(+) diff --git a/cpu-all.h b/cpu-all.h index 52a1817bd..9efb8a923 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -821,6 +821,7 @@ void cpu_watchpoint_remove_all(CPUState *env, int mask); void cpu_single_step(CPUState *env, int enabled); void cpu_reset(CPUState *s); +void run_on_cpu(CPUState *env, void (*func)(void *data), void *data); #define CPU_LOG_TB_OUT_ASM (1 << 0) #define CPU_LOG_TB_IN_ASM (1 << 1) diff --git a/cpu-defs.h b/cpu-defs.h index 01405967d..c764d675e 100644 --- a/cpu-defs.h +++ b/cpu-defs.h @@ -132,6 +132,7 @@ typedef struct icount_decr_u16 { struct kvm_run; struct KVMState; +struct qemu_work_item; typedef struct CPUBreakpoint { target_ulong pc; @@ -204,6 +205,7 @@ typedef struct CPUWatchpoint { uint32_t created; \ struct QemuThread *thread; \ 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; \ diff --git a/cpus.c b/cpus.c index 5afdb4ad7..af87007d4 100644 --- a/cpus.c +++ b/cpus.c @@ -115,6 +115,8 @@ static int cpu_has_work(CPUState *env) { if (env->stop) return 1; + if (env->queued_work_first) + return 1; if (env->stopped || !vm_running) return 0; if (!env->halted) @@ -252,6 +254,11 @@ int qemu_cpu_self(void *env) return 1; } +void run_on_cpu(CPUState *env, void (*func)(void *data), void *data) +{ + func(data); +} + void resume_all_vcpus(void) { } @@ -304,6 +311,7 @@ static QemuCond qemu_cpu_cond; /* system init */ static QemuCond qemu_system_cond; static QemuCond qemu_pause_cond; +static QemuCond qemu_work_cond; static void tcg_block_io_signals(void); static void kvm_block_io_signals(CPUState *env); @@ -334,6 +342,50 @@ void qemu_main_loop_start(void) qemu_cond_broadcast(&qemu_system_cond); } +void run_on_cpu(CPUState *env, void (*func)(void *data), void *data) +{ + struct qemu_work_item wi; + + if (qemu_cpu_self(env)) { + func(data); + return; + } + + wi.func = func; + wi.data = data; + if (!env->queued_work_first) + env->queued_work_first = &wi; + else + env->queued_work_last->next = &wi; + env->queued_work_last = &wi; + wi.next = NULL; + wi.done = false; + + qemu_cpu_kick(env); + while (!wi.done) { + CPUState *self_env = cpu_single_env; + + qemu_cond_wait(&qemu_work_cond, &qemu_global_mutex); + cpu_single_env = self_env; + } +} + +static void flush_queued_work(CPUState *env) +{ + struct qemu_work_item *wi; + + if (!env->queued_work_first) + return; + + while ((wi = env->queued_work_first)) { + env->queued_work_first = wi->next; + wi->func(wi->data); + wi->done = true; + } + env->queued_work_last = NULL; + qemu_cond_broadcast(&qemu_work_cond); +} + static void qemu_wait_io_event_common(CPUState *env) { if (env->stop) { @@ -341,6 +393,7 @@ static void qemu_wait_io_event_common(CPUState *env) env->stopped = 1; qemu_cond_signal(&qemu_pause_cond); } + flush_queued_work(env); } static void qemu_wait_io_event(CPUState *env) diff --git a/qemu-common.h b/qemu-common.h index 4ba0cdad0..a4888e5e5 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -249,6 +249,14 @@ void qemu_notify_event(void); void qemu_cpu_kick(void *env); int qemu_cpu_self(void *env); +/* work queue */ +struct qemu_work_item { + struct qemu_work_item *next; + void (*func)(void *data); + void *data; + int done; +}; + #ifdef CONFIG_USER_ONLY #define qemu_init_vcpu(env) do { } while (0) #else From 2705d56a6a7e9c7833e04d33aedbc01d2280a280 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 4 May 2010 09:45:23 -0300 Subject: [PATCH 06/12] kvm: synchronize state from cpu context It is not safe to retrieve the KVM internal state of a given cpu while its potentially modifying it. Queue the request to run on cpu context, similarly to qemu-kvm. Signed-off-by: Marcelo Tosatti Signed-off-by: Avi Kivity --- kvm-all.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/kvm-all.c b/kvm-all.c index fbd084cd6..e76620229 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -796,14 +796,22 @@ void kvm_flush_coalesced_mmio_buffer(void) #endif } -void kvm_cpu_synchronize_state(CPUState *env) +static void do_kvm_cpu_synchronize_state(void *_env) { + CPUState *env = _env; + if (!env->kvm_vcpu_dirty) { kvm_arch_get_registers(env); env->kvm_vcpu_dirty = 1; } } +void kvm_cpu_synchronize_state(CPUState *env) +{ + if (!env->kvm_vcpu_dirty) + run_on_cpu(env, do_kvm_cpu_synchronize_state, env); +} + void kvm_cpu_synchronize_post_reset(CPUState *env) { kvm_arch_put_registers(env, KVM_PUT_RESET_STATE); From 3ae9501c5bfe874017a385ca437583f5cf66a40a Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Tue, 4 May 2010 09:45:24 -0300 Subject: [PATCH 07/12] add cpu_is_stopped helper Signed-off-by: Marcelo Tosatti Signed-off-by: Avi Kivity --- cpu-all.h | 1 + cpus.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/cpu-all.h b/cpu-all.h index 9efb8a923..47a5722a1 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -821,6 +821,7 @@ void cpu_watchpoint_remove_all(CPUState *env, int mask); void cpu_single_step(CPUState *env, int enabled); void cpu_reset(CPUState *s); +int cpu_is_stopped(CPUState *env); void run_on_cpu(CPUState *env, void (*func)(void *data), void *data); #define CPU_LOG_TB_OUT_ASM (1 << 0) diff --git a/cpus.c b/cpus.c index af87007d4..826886cbb 100644 --- a/cpus.c +++ b/cpus.c @@ -91,6 +91,11 @@ void cpu_synchronize_all_post_init(void) } } +int cpu_is_stopped(CPUState *env) +{ + return !vm_running || env->stopped; +} + static void do_vm_stop(int reason) { if (vm_running) { From ced6c05143b49a910342862ed9c14204e1177ee4 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Tue, 4 May 2010 09:45:25 -0300 Subject: [PATCH 08/12] move stop/stopped CPU_COMMON fields after area zeroed by reset cpu_reset zeroes CPUState upto breakpoints member. Contents of stop/stopped should not be zeroed on cpu_reset. Signed-off-by: Marcelo Tosatti Signed-off-by: Avi Kivity --- cpu-defs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpu-defs.h b/cpu-defs.h index c764d675e..8d4bf86c5 100644 --- a/cpu-defs.h +++ b/cpu-defs.h @@ -159,8 +159,6 @@ typedef struct CPUWatchpoint { target_ulong mem_io_vaddr; /* target virtual addr at which the \ memory was accessed */ \ uint32_t halted; /* Nonzero if the CPU is in suspend state */ \ - uint32_t stop; /* Stop request */ \ - uint32_t stopped; /* Artificially stopped */ \ uint32_t interrupt_request; \ volatile sig_atomic_t exit_request; \ CPU_COMMON_TLB \ @@ -203,6 +201,8 @@ typedef struct CPUWatchpoint { void *opaque; \ \ uint32_t created; \ + uint32_t stop; /* Stop request */ \ + uint32_t stopped; /* Artificially stopped */ \ struct QemuThread *thread; \ struct QemuCond *halt_cond; \ struct qemu_work_item *queued_work_first, *queued_work_last; \ From dbaa07c404d05676df8a081e60b6e66344eafc51 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 4 May 2010 09:45:26 -0300 Subject: [PATCH 09/12] kvm: validate context for kvm cpu get/put operations Validate that KVM vcpu state is only read/written from cpu thread itself or that cpu is stopped. Signed-off-by: Marcelo Tosatti Signed-off-by: Avi Kivity --- target-i386/kvm.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index f73b47b97..c9ec72eee 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -949,6 +949,8 @@ int kvm_arch_put_registers(CPUState *env, int level) { int ret; + assert(cpu_is_stopped(env) || qemu_cpu_self(env)); + ret = kvm_getput_regs(env, 1); if (ret < 0) return ret; @@ -991,6 +993,8 @@ int kvm_arch_get_registers(CPUState *env) { int ret; + assert(cpu_is_stopped(env) || qemu_cpu_self(env)); + ret = kvm_getput_regs(env, 0); if (ret < 0) return ret; From 0af691d779965663abdd7bc708c2ad7bce2f6da0 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Tue, 4 May 2010 09:45:27 -0300 Subject: [PATCH 10/12] kvm: enable smp > 1 Process INIT/SIPI requests and enable -smp > 1. Signed-off-by: Marcelo Tosatti Signed-off-by: Avi Kivity --- kvm-all.c | 10 +++++----- kvm.h | 2 ++ target-i386/kvm.c | 16 ++++++++++++++++ target-ppc/kvm.c | 5 +++++ target-s390x/kvm.c | 5 +++++ 5 files changed, 33 insertions(+), 5 deletions(-) diff --git a/kvm-all.c b/kvm-all.c index e76620229..d06980c00 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -593,11 +593,6 @@ int kvm_init(int smp_cpus) int ret; int i; - if (smp_cpus > 1) { - fprintf(stderr, "No SMP KVM support, use '-smp 1'\n"); - return -EINVAL; - } - s = qemu_mallocz(sizeof(KVMState)); #ifdef KVM_CAP_SET_GUEST_DEBUG @@ -840,6 +835,11 @@ int kvm_cpu_exec(CPUState *env) } #endif + if (kvm_arch_process_irqchip_events(env)) { + ret = 0; + break; + } + if (env->kvm_vcpu_dirty) { kvm_arch_put_registers(env, KVM_PUT_RUNTIME_STATE); env->kvm_vcpu_dirty = 0; diff --git a/kvm.h b/kvm.h index 70bfbf8ab..5071a31de 100644 --- a/kvm.h +++ b/kvm.h @@ -90,6 +90,8 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run); int kvm_arch_pre_run(CPUState *env, struct kvm_run *run); +int kvm_arch_process_irqchip_events(CPUState *env); + int kvm_arch_get_registers(CPUState *env); /* state subset only touched by the VCPU itself during runtime */ diff --git a/target-i386/kvm.c b/target-i386/kvm.c index c9ec72eee..bd7a19067 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -1073,6 +1073,22 @@ int kvm_arch_post_run(CPUState *env, struct kvm_run *run) return 0; } +int kvm_arch_process_irqchip_events(CPUState *env) +{ + if (env->interrupt_request & CPU_INTERRUPT_INIT) { + kvm_cpu_synchronize_state(env); + do_cpu_init(env); + env->exception_index = EXCP_HALTED; + } + + if (env->interrupt_request & CPU_INTERRUPT_SIPI) { + kvm_cpu_synchronize_state(env); + do_cpu_sipi(env); + } + + return env->halted; +} + static int kvm_handle_halt(CPUState *env) { if (!((env->interrupt_request & CPU_INTERRUPT_HARD) && diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index aa3d43247..91c0963f8 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -224,6 +224,11 @@ int kvm_arch_post_run(CPUState *env, struct kvm_run *run) return 0; } +int kvm_arch_process_irqchip_events(CPUState *env) +{ + return 0; +} + static int kvmppc_handle_halt(CPUState *env) { if (!(env->interrupt_request & CPU_INTERRUPT_HARD) && (msr_ee)) { diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 72e77b0cd..a2c00acf0 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -175,6 +175,11 @@ int kvm_arch_post_run(CPUState *env, struct kvm_run *run) return 0; } +int kvm_arch_process_irqchip_events(CPUState *env) +{ + return 0; +} + static void kvm_s390_interrupt_internal(CPUState *env, int type, uint32_t parm, uint64_t parm64, int vm) { From 4513d9232badcc5039d69dae946054ba2682c258 Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Mon, 10 May 2010 11:21:34 +0300 Subject: [PATCH 11/12] Do not stop VM if emulation failed in userspace. Continue vcpu execution in case emulation failure happened while vcpu was in userspace. In this case #UD will be injected into the guest allowing guest OS to kill offending process and continue. Signed-off-by: Gleb Natapov Signed-off-by: Marcelo Tosatti --- kvm-all.c | 2 ++ kvm.h | 2 ++ target-i386/kvm.c | 7 +++++++ target-ppc/kvm.c | 5 +++++ target-s390x/kvm.c | 5 +++++ 5 files changed, 21 insertions(+) diff --git a/kvm-all.c b/kvm-all.c index d06980c00..c238f5421 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -764,6 +764,8 @@ 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; } /* FIXME: Should trigger a qmp message to let management know * something went wrong. diff --git a/kvm.h b/kvm.h index 5071a31de..a28e7aab5 100644 --- a/kvm.h +++ b/kvm.h @@ -140,6 +140,8 @@ void kvm_arch_remove_all_hw_breakpoints(void); 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); uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function, diff --git a/target-i386/kvm.c b/target-i386/kvm.c index bd7a19067..676aa6079 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -1289,3 +1289,10 @@ void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg) } } #endif /* KVM_CAP_SET_GUEST_DEBUG */ + +bool kvm_arch_stop_on_emulation_error(CPUState *env) +{ + return !(env->cr[0] & CR0_PE_MASK) || + ((env->segs[R_CS].selector & 3) != 3); +} + diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 91c0963f8..2625cb8bd 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -326,3 +326,8 @@ uint32_t kvmppc_get_tbfreq(void) retval = atoi(ns); return retval; } + +bool kvm_arch_stop_on_emulation_error(CPUState *env) +{ + return true; +} diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index a2c00acf0..a2d77419b 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -485,3 +485,8 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run) return ret; } + +bool kvm_arch_stop_on_emulation_error(CPUState *env) +{ + return true; +} From c1667e409764bb43a8196e40d01c409326d54a96 Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Tue, 11 May 2010 09:41:25 +0300 Subject: [PATCH 12/12] kvm: fix 80000001.EDX supported bit filtering On AMD some bits from 1.EDX are reported in 80000001.EDX. The mask used to copy bits from 1.EDX to 80000001.EDX is incorrect resulting in unsupported features passed into a guest. Signed-off-by: Gleb Natapov Signed-off-by: Marcelo Tosatti --- target-i386/kvm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 676aa6079..d6b12edab 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -111,7 +111,7 @@ uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function, int reg) * so add missing bits according to the AMD spec: */ cpuid_1_edx = kvm_arch_get_supported_cpuid(env, 1, R_EDX); - ret |= cpuid_1_edx & 0xdfeff7ff; + ret |= cpuid_1_edx & 0x183f7ff; break; } break;