qemu-kvm.git uq/master queue
The following changes since commit 38cc9b607f85017b095793cab6c129bc9844f441:
issue snd_pcm_start() when capturing audio (2010-10-18 00:39:06 +0400)
are available in the git repository at:
git://git.kernel.org/pub/scm/virt/kvm/qemu-kvm.git uq/master
Huang Ying (1):
Add RAM -> physical addr mapping in MCE simulation
Joerg Roedel (2):
Set cpuid definition to 0 before initializing it Add svm cpuid features
Marcelo Tosatti (7):
signalfd compatibility
iothread: use signalfd
kvm: x86: add mce support
Export qemu_ram_addr_from_host
MCE: Relay UCR MCE to guest
Add savevm/loadvm support for MCE
Fix memory leak in register save load due to xsave support
Makefile.objs | 1 + compatfd.c | 117 ++++++++++++++++++ compatfd.h | 43 +++++++ configure | 18 +++ cpu-common.h | 3 +- cpus.c | 156 ++++++++++++++++++++++-- exec-all.h | 2 +- exec.c | 26 +++-- kvm-all.c | 18 +++ kvm-stub.c | 5 + kvm.h | 9 ++ target-i386/cpu.h | 32 +++++- target-i386/cpuid.c | 79 ++++++++++--- target-i386/helper.c | 6 + target-i386/kvm.c | 311 ++++++++++++++++++++++++++++++++++++++++++++++++- target-i386/kvm_x86.h | 22 ++++ 16 files changed, 801 insertions(+), 47 deletions(-) create mode 100644 compatfd.c create mode 100644 compatfd.h create mode 100644 target-i386/kvm_x86.h
PATCH 1/10 Set cpuid definition to 0 before initializing it
From: Joerg Roedel <[email protected]>
This patch cleans the (stack-allocated) cpuid definition to 0 before actually initializing it.
--- target-i386/cpuid.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
target-i386/cpuid.c +2 -0
@@ -788,6 +788,8 @@ int cpu_x86_register (CPUX86State *env, const char *cpu_model) {x86_def_t def1, *def = &def1; +memset (def,0 ,sizeof (*def)); +if (cpu_x86_find_by_name (def, cpu_model) <0 )return -1 ;if (def->vendor1) {
Signature · 1 line
1.7.2.1
PATCH 2/10 Add svm cpuid features
In reply to Marcelo TosattiFrom: Joerg Roedel <[email protected]>
This patch adds the svm cpuid feature flags to the qemu intialization path. It also adds the svm features available on phenom to its cpu-definition and extends the host cpu type to support all svm features KVM can provide.
--- target-i386/cpu.h | 12 ++++++++ target-i386/cpuid.c | 77 +++++++++++++++++++++++++++++++++++++++----------- target-i386/kvm.c | 3 ++ 3 files changed, 75 insertions(+), 17 deletions(-)
target-i386/cpu.h +12 -0
@@ -405,6 +405,17 @@#define CPUID_EXT3_IBS (1 << 10)#define CPUID_EXT3_SKINIT (1 << 12) +#define CPUID_SVM_NPT (1 << 0) +#define CPUID_SVM_LBRV (1 << 1) +#define CPUID_SVM_SVMLOCK (1 << 2) +#define CPUID_SVM_NRIPSAVE (1 << 3) +#define CPUID_SVM_TSCSCALE (1 << 4) +#define CPUID_SVM_VMCBCLEAN (1 << 5) +#define CPUID_SVM_FLUSHASID (1 << 6) +#define CPUID_SVM_DECODEASSIST (1 << 7) +#define CPUID_SVM_PAUSEFILTER (1 << 10) +#define CPUID_SVM_PFTHRESHOLD (1 << 12) +#define CPUID_VENDOR_INTEL_1 0x756e6547/* "Genu" */ #define CPUID_VENDOR_INTEL_2 0x49656e69/* "ineI" */ #define CPUID_VENDOR_INTEL_3 0x6c65746e/* "ntel" */
@@ -702,6 +713,7 @@ typedef struct CPUX86State {uint8_t has_error_code;uint32_t sipi_vector;uint32_t cpuid_kvm_features; +uint32_t cpuid_svm_features;/* in order to simplify APIC support, we leave this pointer to the user */
target-i386/cpuid.c +60 -17
172 lines not on this page · raw message
target-i386/kvm.c +3 -0
@@ -192,6 +192,9 @@ int kvm_arch_init_vcpu(CPUState *env) 0, R_EDX); env->cpuid_ext3_features &=kvm_arch_get_supported_cpuid (env,0x80000001 ,0 ,R_ECX ); + env->cpuid_svm_features &=kvm_arch_get_supported_cpuid (env,0x8000000A , +0 ,R_EDX ); + cpuid_i =0 ;
Signature · 1 line
1.7.2.1
PATCH 3/10 signalfd compatibility
In reply to Marcelo TosattiPort qemu-kvm's signalfd compat code.
commit 5a7fdd0abd7cd24dac205317a4195446ab8748b5
Author: Anthony Liguori <[email protected]> Date: Wed May 7 11:55:47 2008 -0500
Use signalfd() in io-thread
This patch reworks the IO thread to use signalfd() instead of sigtimedwait() This will eliminate the need to use SIGIO everywhere.
--- Makefile.objs | 1 + compatfd.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ compatfd.h | 43 +++++++++++++++++++++ configure | 18 +++++++++ 4 files changed, 179 insertions(+), 0 deletions(-) create mode 100644 compatfd.c create mode 100644 compatfd.h
Makefile.objs +1 -0
@@ -125,6 +125,7 @@ common-obj-y += $(addprefix ui/, $(ui-obj-y)) common-obj-y += iov.o acl.o common-obj-$(CONFIG_THREAD) += qemu-thread.o +common-obj-$(CONFIG_IOTHREAD) += compatfd.o common-obj-y += notify.o event_notifier.o common-obj-y += qemu-timer.o
compatfd.c new file +117 -0
117 lines not on this page · raw message
compatfd.h new file +43 -0
43 lines not on this page · raw message
configure +18 -0
@@ -1957,6 +1957,21 @@ if compile_prog "" "" ; then splice=yes fi +########################################## +# signalfd probe +signalfd="no" +cat > $TMPC << EOF +#define _GNU_SOURCE +#include <unistd.h> +#include <sys/syscall.h> +#include <signal.h> +int main(void) { return syscall(SYS_signalfd, -1, NULL, _NSIG / 8); } +EOF + +if compile_prog "" "" ; then + signalfd=yes +fi + # check if eventfd is supported eventfd=no cat > $TMPC << EOF
@@ -2559,6 +2574,9 @@ fi if test "$fdt" = "yes" ; then echo "CONFIG_FDT=y" >> $config_host_mak fi +if test "$signalfd" = "yes" ; then + echo "CONFIG_SIGNALFD=y" >> $config_host_mak +fi if test "$need_offsetof" = "yes" ; then echo "CONFIG_NEED_OFFSETOF=y" >> $config_host_mak fi
Signature · 1 line
1.7.2.1
PATCH 4/10 iothread: use signalfd
In reply to Marcelo TosattiBlock SIGALRM, SIGIO and consume them via signalfd.
--- cpus.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 69 insertions(+), 5 deletions(-)
cpus.c +69 -5
@@ -33,6 +33,7 @@#include "exec-all.h" #include "cpus.h" +#include "compatfd.h" #ifdef SIGRTMIN #define SIG_IPI (SIGRTMIN+4)
@@ -329,14 +330,75 @@ static QemuCond qemu_work_cond;static void tcg_init_ipi (void );static void kvm_init_ipi (CPUState *env); -static void unblock_io_signals (void ); +static sigset_t block_io_signals (void ); + +/* If we have signalfd, we mask out the signals we want to handle and then +* use signalfd to listen for them. We rely on whatever the current signal +* handler is to dispatch the signals when we receive them. +*/ +static void sigfd_handler (void *opaque) +{ +int fd = (unsigned long ) opaque; +struct qemu_signalfd_siginfo info; +struct sigaction action; +ssize_t len; + +while (1 ) { +do { + len =read (fd, &info,sizeof (info)); + }while (len ==-1 && errno ==EINTR ); + +if (len ==-1 && errno ==EAGAIN ) { +break ; + } + +if (len !=sizeof (info)) { +printf ("read from sigfd returned %zd: %m\n" , len); +return ; + } + +sigaction (info.ssi_signo,NULL , &action); +if ((action.sa_flags &SA_SIGINFO ) && action.sa_sigaction) { + action.sa_sigaction (info.ssi_signo, + (siginfo_t *)&info,NULL ); + }else if (action.sa_handler) { + action.sa_handler (info.ssi_signo); + } + } +} + +static int qemu_signalfd_init (sigset_t mask) +{ +int sigfd; + + sigfd =qemu_signalfd (&mask); +if (sigfd ==-1 ) { +fprintf (stderr,"failed to create signalfd\n" ); +return -errno; + } + +fcntl_setfl (sigfd,O_NONBLOCK ); + +qemu_set_fd_handler2 (sigfd,NULL , sigfd_handler,NULL , + (void *)(unsigned long ) sigfd); + +return 0 ; +}int qemu_init_main_loop (void ) {int ret; +sigset_t blocked_signals;cpu_set_debug_excp_handler (cpu_debug_handler); + blocked_signals =block_io_signals (); + + ret =qemu_signalfd_init (blocked_signals); +if (ret) +return ret; + +/* Note eventfd must be drained before signalfd handlers run */ ret =qemu_event_init ();if (ret)return ret;
@@ -347,7 +409,6 @@ int qemu_init_main_loop(void)qemu_mutex_init (&qemu_global_mutex);qemu_mutex_lock (&qemu_global_mutex); -unblock_io_signals ();qemu_thread_self (&io_thread);return 0 ;
@@ -586,19 +647,22 @@ static void kvm_init_ipi(CPUState *env) } } -static void unblock_io_signals (void ) +static sigset_t block_io_signals (void ) {sigset_t set; +/* SIGUSR2 used by posix-aio-compat.c */ sigemptyset (&set);sigaddset (&set,SIGUSR2 ); -sigaddset (&set,SIGIO ); -sigaddset (&set,SIGALRM );pthread_sigmask (SIG_UNBLOCK , &set,NULL );sigemptyset (&set); +sigaddset (&set,SIGIO ); +sigaddset (&set,SIGALRM );sigaddset (&set,SIG_IPI );pthread_sigmask (SIG_BLOCK , &set,NULL ); + +return set; }void qemu_mutex_lock_iothread (void )
Signature · 1 line
1.7.2.1
PATCH 5/10 kvm: x86: add mce support
In reply to Marcelo TosattiPort qemu-kvm's MCE support
commit c68b2374c9048812f488e00ffb95db66c0bc07a7
Author: Huang Ying <[email protected]> Date: Mon Jul 20 10:00:53 2009 +0800
Add MCE simulation support to qemu/kvm
KVM ioctls are used to initialize MCE simulation and inject MCE. The real MCE simulation is implemented in Linux kernel. The Kernel part has been merged.
--- target-i386/helper.c | 6 +++ target-i386/kvm.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++ target-i386/kvm_x86.h | 21 ++++++++++++ 3 files changed, 111 insertions(+), 0 deletions(-) create mode 100644 target-i386/kvm_x86.h
target-i386/helper.c +6 -0
@@ -27,6 +27,7 @@#include "exec-all.h" #include "qemu-common.h" #include "kvm.h" +#include "kvm_x86.h" //#define DEBUG_MMU
@@ -1030,6 +1031,11 @@ void cpu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,if (bank >= bank_num || !(status &MCI_STATUS_VAL ))return ; +if (kvm_enabled ()) { +kvm_inject_x86_mce (cenv, bank, status, mcg_status, addr, misc); +return ; + } +/* * if MSR_MCG_CTL is not all 1s, the uncorrected error * reporting is disabled
target-i386/kvm.c +84 -0
102 lines not on this page · raw message
target-i386/kvm_x86.h new file +21 -0
@@ -0,0 +1,21 @@ +/* +* QEMU KVM support +* +* Copyright (C) 2009 Red Hat Inc. +* Copyright IBM, Corp. 2008 +* +* Authors: +* Anthony Liguori <[email protected]> +* +* This work is licensed under the terms of the GNU GPL, version 2 or later. +* See the COPYING file in the top-level directory. +* +*/ + +#ifndef __KVM_X86_H__ +#define __KVM_X86_H__ + +void kvm_inject_x86_mce (CPUState *cenv,int bank,uint64_t status, +uint64_t mcg_status,uint64_t addr,uint64_t misc); + +#endif
Signature · 1 line
1.7.2.1
Re: [PATCH 05/10] kvm: x86: add mce support
Quoted 81 lines · Marcelo Tosatti
Port qemu-kvm's MCE support
commit
c68b2374c9048812f488e00ffb95db66c0bc07a7Author: Huang Ying<[email protected]> Date: Mon Jul 20 10:00:53 2009 +0800Add MCE simulation support to qemu/kvm
KVM ioctls are used to initialize MCE simulation and inject MCE. The real MCE simulation is implemented in Linux kernel. The Kernel part has been merged.
Signed-off-by Marcelo Tosatti<[email protected]>Signed-off-by Avi Kivity<[email protected]>--- target-i386/helper.c | 6 +++ target-i386/kvm.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++ target-i386/kvm_x86.h | 21 ++++++++++++ 3 files changed, 111 insertions(+), 0 deletions(-)create mode 100644
target-i386/kvm_x86.htarget-i386/helper.c +6
-0@@ -27,6 +27,7 @@#include "exec-all.h" #include "qemu-common.h" #include "kvm.h" +#include "kvm_x86.h" //#define DEBUG_MMU @@ -1030,6 +1031,11 @@ void cpu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,if (bank>= bank_num || !(status&MCI_STATUS_VAL ))return ; +if (kvm_enabled ()) { +kvm_inject_x86_mce (cenv, bank, status, mcg_status, addr, misc); +return ; + } +/* * if MSR_MCG_CTL is not all 1s, the uncorrected error * reporting is disabled target-i386/kvm.c +21
-0@@ -27,6 +27,7 @@#include "hw/pc.h" #include "hw/apic.h" #include "ioport.h" +#include "kvm_x86.h" #ifdef CONFIG_KVM_PARA #include <linux/kvm_para.h> @@ -167,6 +168,67 @@ static int get_para_features(CPUState *env) }#endif +#ifdef KVM_CAP_MCE +static int kvm_get_mce_cap_supported (KVMState *s,uint64_t *mce_cap, +int *max_banks) +{ +int r; + + r =kvm_ioctl (s,KVM_CHECK_EXTENSION ,KVM_CAP_MCE ); +if (r>0 ) { + *max_banks = r; +return kvm_ioctl (s,KVM_X86_GET_MCE_CAP_SUPPORTED , mce_cap); + } +return -ENOSYS ; +} + +static int kvm_setup_mce (CPUState *env,uint64_t *mcg_cap) +{ +return kvm_vcpu_ioctl (env,KVM_X86_SETUP_MCE , mcg_cap); +} + +static int kvm_set_mce (CPUState *env,struct kvm_x86_mce *m)
target-i386/kvm.c static int get_para_features(CPUState *env) · line 200
Quoted 10 lines
target-i386/kvm.c +9
-0+{ +return kvm_vcpu_ioctl (env,KVM_X86_SET_MCE , m); +} + +struct kvm_x86_mce_data +{ +CPUState *env; +struct kvm_x86_mce *mce; +};
CODING_STYLE.
target-i386/kvm.c static int get_para_features(CPUState *env)
Quoted 9 lines
target-i386/kvm.c +8
-0+static void kvm_do_inject_x86_mce (void *_data) +{ +struct kvm_x86_mce_data *data = _data; +int r; + + r =kvm_set_mce (data->env, data->mce); +if (r<0 ) +perror ("kvm_set_mce FAILED" );
CODING_STYLE.
Quoted 39 lines
target-i386/kvm.c +32
-0+} +#endif + +void kvm_inject_x86_mce (CPUState *cenv,int bank,uint64_t status, +uint64_t mcg_status,uint64_t addr,uint64_t misc) +{ +#ifdef KVM_CAP_MCE +struct kvm_x86_mce mce = { + .bank = bank, + .status = status, + .mcg_status = mcg_status, + .addr = addr, + .misc = misc, + }; +struct kvm_x86_mce_data data = { + .env = cenv, + .mce =&mce, + }; + +run_on_cpu (cenv, kvm_do_inject_x86_mce,&data); +#endif +} +int kvm_arch_init_vcpu (CPUState *env) {struct {@@ -277,6 +339,28 @@ int kvm_arch_init_vcpu(CPUState *env) cpuid_data.cpuid.nent = cpuid_i; +#ifdef KVM_CAP_MCE +if (((env->cpuid_version>>8 )&0xF )>=6 +&& (env->cpuid_features&(CPUID_MCE |CPUID_MCA )) == (CPUID_MCE |CPUID_MCA ) +&&kvm_check_extension (env->kvm_state,KVM_CAP_MCE )>0 ) { +uint64_t mcg_cap; +int banks; + +if (kvm_get_mce_cap_supported (env->kvm_state,&mcg_cap,&banks)) +perror ("kvm_get_mce_cap_supported FAILED" );
target-i386/kvm.c int kvm_arch_init_vcpu(CPUState *env) · line 360
Quoted 10 lines
target-i386/kvm.c +9
-0+else { +if (banks>MCE_BANKS_DEF ) + banks =MCE_BANKS_DEF ; + mcg_cap&=MCE_CAP_DEF ; + mcg_cap |= banks; +if (kvm_setup_mce (env,&mcg_cap)) +perror ("kvm_setup_mce FAILED" ); +else + env->mcg_cap = mcg_cap;
CODING_STYLE.
Quoted 35 lines
target-i386/kvm.c +4
-0+ } + } +#endif +return kvm_vcpu_ioctl (env,KVM_SET_CPUID2 ,&cpuid_data); }target-i386/kvm_x86.h new file +21
-0@@ -0,0 +1,21 @@ +/* +* QEMU KVM support +* +* Copyright (C) 2009 Red Hat Inc. +* Copyright IBM, Corp. 2008 +* +* Authors: +* Anthony Liguori<[email protected]> +* +* This work is licensed under the terms of the GNU GPL, version 2 or later. +* See the COPYING file in the top-level directory. +* +*/ + +#ifndef __KVM_X86_H__ +#define __KVM_X86_H__ + +void kvm_inject_x86_mce (CPUState *cenv,int bank,uint64_t status, +uint64_t mcg_status,uint64_t addr,uint64_t misc); + +#endif
PATCH 6/10 Export qemu_ram_addr_from_host
In reply to Marcelo TosattiTo be used by next patches.
--- cpu-common.h | 3 ++- exec-all.h | 2 +- exec.c | 26 +++++++++++++++++--------- 3 files changed, 20 insertions(+), 11 deletions(-)
cpu-common.h +2 -1
@@ -47,7 +47,8 @@ void qemu_ram_free(ram_addr_t addr);/* This should only be used for ram local to a device. */ void *qemu_get_ram_ptr (ram_addr_t addr);/* This should not be used by devices. */ -ram_addr_t qemu_ram_addr_from_host (void *ptr); +int qemu_ram_addr_from_host (void *ptr,ram_addr_t *ram_addr); +ram_addr_t qemu_ram_addr_from_host_nofail (void *ptr); int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read, CPUWriteMemoryFunc * const *mem_write,
exec-all.h +1 -1
@@ -334,7 +334,7 @@ static inline tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong add } p = (void *)(unsigned long )addr + env1->tlb_table[mmu_idx][page_index].addend; -return qemu_ram_addr_from_host (p); +return qemu_ram_addr_from_host_nofail (p); }#endif
exec.c +17 -9
@@ -2085,7 +2085,7 @@ static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK ) ==IO_MEM_RAM ) { p = (void *)(unsigned long )((tlb_entry->addr_write &TARGET_PAGE_MASK ) + tlb_entry->addend); - ram_addr =qemu_ram_addr_from_host (p); + ram_addr =qemu_ram_addr_from_host_nofail (p);if (!cpu_physical_memory_is_dirty (ram_addr)) { tlb_entry->addr_write |=TLB_NOTDIRTY ; }
@@ -2938,23 +2938,31 @@ void *qemu_get_ram_ptr(ram_addr_t addr)return NULL ; } -/* Some of the softmmu routines need to translate from a host pointer -(typically a TLB entry) back to a ram offset. */ -ram_addr_t qemu_ram_addr_from_host (void *ptr) +int qemu_ram_addr_from_host (void *ptr,ram_addr_t *ram_addr) {RAMBlock *block;uint8_t *host = ptr; QLIST_FOREACH(block, &ram_list.blocks, next) {if (host - block->host < block->length) { -return block->offset + (host - block->host); + *ram_addr = block->offset + (host - block->host); +return 0 ; } } +return -1 ; +} -fprintf (stderr,"Bad ram pointer %p\n" , ptr); -abort (); +/* Some of the softmmu routines need to translate from a host pointer +(typically a TLB entry) back to a ram offset. */ +ram_addr_t qemu_ram_addr_from_host_nofail (void *ptr) +{ +ram_addr_t ram_addr; -return 0 ; +if (qemu_ram_addr_from_host (ptr, &ram_addr)) { +fprintf (stderr,"Bad ram pointer %p\n" , ptr); +abort (); + } +return ram_addr; }static uint32_t unassigned_mem_readb (void *opaque,target_phys_addr_t addr)
@@ -3703,7 +3711,7 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len, {if (buffer != bounce.buffer) {if (is_write) { -ram_addr_t addr1 =qemu_ram_addr_from_host (buffer); +ram_addr_t addr1 =qemu_ram_addr_from_host_nofail (buffer);while (access_len) {unsigned l; l =TARGET_PAGE_SIZE ;
Signature · 1 line
1.7.2.1
PATCH 7/10 Add RAM -> physical addr mapping in MCE simulation
In reply to Marcelo TosattiFrom: Huang Ying <[email protected]>
In QEMU-KVM, physical address != RAM address. While MCE simulation needs physical address instead of RAM address. So kvm_physical_memory_addr_from_ram() is implemented to do the conversion, and it is invoked before being filled in the IA32_MCi_ADDR MSR.
--- kvm-all.c | 18 ++++++++++++++++++ kvm.h | 6 ++++++ 2 files changed, 24 insertions(+), 0 deletions(-)
kvm-all.c +18 -0
@@ -137,6 +137,24 @@ static KVMSlot *kvm_lookup_overlapping_slot(KVMState *s,return found; } +int kvm_physical_memory_addr_from_ram (KVMState *s,ram_addr_t ram_addr, +target_phys_addr_t *phys_addr) +{ +int i; + +for (i =0 ; i <ARRAY_SIZE (s->slots); i++) { +KVMSlot *mem = &s->slots[i]; + +if (ram_addr >= mem->phys_offset && + ram_addr < mem->phys_offset + mem->memory_size) { + *phys_addr = mem->start_addr + (ram_addr - mem->phys_offset); +return 1 ; + } + } + +return 0 ; +} +static int kvm_set_user_memory_region (KVMState *s,KVMSlot *slot) {struct kvm_userspace_memory_region mem;
kvm.h +6 -0
@@ -174,6 +174,12 @@ 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, +target_phys_addr_t *phys_addr); +#endif +#endif int kvm_set_ioeventfd_mmio_long (int fd,uint32_t adr,uint32_t val,bool assign);
Signature · 1 line
1.7.2.1
Re: [PATCH 07/10] Add RAM -> physical addr mapping in MCE simulation
Quoted 30 lines · Marcelo Tosatti
From: Huang Ying<[email protected]>
In QEMU-KVM, physical address != RAM address. While MCE simulation needs physical address instead of RAM address. So
kvm_physical_memory_addr_from_ram()is implemented to do the conversion, and it is invoked before being filled in theIA32_MCi_ADDRMSR.Reported-by Dean Nelson<[email protected]>Signed-off-by Huang Ying<[email protected]>Signed-off-by Marcelo Tosatti<[email protected]>Signed-off-by Avi Kivity<[email protected]>--- kvm-all.c | 18 ++++++++++++++++++ kvm.h | 6 ++++++ 2 files changed, 24 insertions(+), 0 deletions(-)kvm-all.c +5
-0@@ -137,6 +137,24 @@ static KVMSlot *kvm_lookup_overlapping_slot(KVMState *s,return found; } +int kvm_physical_memory_addr_from_ram (KVMState *s,ram_addr_t ram_addr, +target_phys_addr_t *phys_addr) +{ +int i; +
kvm-all.c static KVMSlot *kvm_lookup_overlapping_slot(KVMState *s, · line 154
Quoted 10 lines
kvm-all.c +9
-0+for (i =0 ; i<ARRAY_SIZE (s->slots); i++) { +KVMSlot *mem =&s->slots[i]; + +if (ram_addr>= mem->phys_offset&& + ram_addr< mem->phys_offset + mem->memory_size) { + *phys_addr = mem->start_addr + (ram_addr - mem->phys_offset); +return 1 ; + } + }
This is bogus.
There isn't one mapping from ram_addr_t to target_phys_addr_t. There may be many because or RAM aliasing.
Using KVMSlot is also wrong. This is a function that belongs in exec.c.
Regards,
Anthony Liguori
Quoted 24 lines
kvm-all.c +3
-0+return 0 ; +} +static int kvm_set_user_memory_region (KVMState *s,KVMSlot *slot) {struct kvm_userspace_memory_region mem;kvm.h +6
-0@@ -174,6 +174,12 @@ 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, +target_phys_addr_t *phys_addr); +#endif +#endif int kvm_set_ioeventfd_mmio_long (int fd,uint32_t adr,uint32_t val,bool assign);
PATCH 8/10 MCE: Relay UCR MCE to guest
In reply to Marcelo TosattiPort qemu-kvm's
commit 4b62fff1101a7ad77553147717a8bd3bf79df7ef
Author: Huang Ying <[email protected]> Date: Mon Sep 21 10:43:25 2009 +0800
MCE: Relay UCR MCE to guest
UCR (uncorrected recovery) MCE is supported in recent Intel CPUs, where some hardware error such as some memory error can be reported without PCC (processor context corrupted). To recover from such MCE, the corresponding memory will be unmapped, and all processes accessing the memory will be killed via SIGBUS.
For KVM, if QEMU/KVM is killed, all guest processes will be killed too. So we relay SIGBUS from host OS to guest system via a UCR MCE injection. Then guest OS can isolate corresponding memory and kill necessary guest processes only. SIGBUS sent to main thread (not VCPU threads) will be broadcast to all VCPU threads as UCR MCE.
--- cpus.c | 82 ++++++++++++++++++++-- kvm-stub.c | 5 ++ kvm.h | 3 + target-i386/cpu.h | 20 +++++- target-i386/helper.c | 2 +- target-i386/kvm.c | 178 ++++++++++++++++++++++++++++++++++++++++++++++++- target-i386/kvm_x86.h | 3 +- 7 files changed, 279 insertions(+), 14 deletions(-)
cpus.c +74 -8
@@ -34,6 +34,10 @@#include "cpus.h" #include "compatfd.h" +#ifdef CONFIG_LINUX +#include <sys/prctl.h> +#include <sys/signalfd.h> +#endif #ifdef SIGRTMIN #define SIG_IPI (SIGRTMIN+4)
@@ -41,6 +45,10 @@#define SIG_IPI SIGUSR1#endif +#ifndef PR_MCE_KILL +#define PR_MCE_KILL 33 +#endif +static CPUState *next_cpu;/***********************************************************/
@@ -498,28 +506,77 @@ static void qemu_tcg_wait_io_event(void) } } +static void sigbus_reraise (void ) +{ +sigset_t set; +struct sigaction action; + +memset (&action,0 ,sizeof (action)); + action.sa_handler =SIG_DFL ; +if (!sigaction (SIGBUS , &action,NULL )) { +raise (SIGBUS ); +sigemptyset (&set); +sigaddset (&set,SIGBUS ); +sigprocmask (SIG_UNBLOCK , &set,NULL ); + } +perror ("Failed to re-raise SIGBUS!\n" ); +abort (); +} + +static void sigbus_handler (int n,struct qemu_signalfd_siginfo *siginfo, +void *ctx) +{ +#if defined(TARGET_I386 ) + if (kvm_on_sigbus(siginfo->ssi_code, (void *)(intptr_t)siginfo->ssi_addr)) +#endif +sigbus_reraise (); +} +static void qemu_kvm_eat_signal (CPUState *env,int timeout) {struct timespec ts;int r, e;siginfo_t siginfo;sigset_t waitset; +sigset_t chkset; ts.tv_sec = timeout /1000 ; ts.tv_nsec = (timeout %1000 ) *1000000 ;sigemptyset (&waitset);sigaddset (&waitset,SIG_IPI ); +sigaddset (&waitset,SIGBUS ); -qemu_mutex_unlock (&qemu_global_mutex); - r =sigtimedwait (&waitset, &siginfo, &ts); - e = errno; -qemu_mutex_lock (&qemu_global_mutex); +do { +qemu_mutex_unlock (&qemu_global_mutex); -if (r ==-1 && !(e ==EAGAIN || e ==EINTR )) { -fprintf (stderr,"sigtimedwait: %s\n" ,strerror (e)); -exit (1 ); - } + r =sigtimedwait (&waitset, &siginfo, &ts); + e = errno; + +qemu_mutex_lock (&qemu_global_mutex); + +if (r ==-1 && !(e ==EAGAIN || e ==EINTR )) { +fprintf (stderr,"sigtimedwait: %s\n" ,strerror (e)); +exit (1 ); + } + +switch (r) { +case SIGBUS : +#ifdef TARGET_I386 + if (kvm_on_sigbus_vcpu(env, siginfo.si_code, siginfo.si_addr)) +#endif +sigbus_reraise (); +break ; +default : +break ; + } + + r =sigpending (&chkset); +if (r ==-1 ) { +fprintf (stderr,"sigpending: %s\n" ,strerror (e)); +exit (1 ); + } + }while (sigismember (&chkset,SIG_IPI ) ||sigismember (&chkset,SIGBUS )); }static void qemu_kvm_wait_io_event (CPUState *env)
@@ -640,6 +697,7 @@ static void kvm_init_ipi(CPUState *env)pthread_sigmask (SIG_BLOCK ,NULL , &set);sigdelset (&set,SIG_IPI ); +sigdelset (&set,SIGBUS ); r =kvm_set_signal_mask (env, &set);if (r) {fprintf (stderr,"kvm_set_signal_mask: %s\n" ,strerror (r));
@@ -650,6 +708,7 @@ static void kvm_init_ipi(CPUState *env)static sigset_t block_io_signals (void ) {sigset_t set; +struct sigaction action;/* SIGUSR2 used by posix-aio-compat.c */ sigemptyset (&set);
@@ -660,8 +719,15 @@ static sigset_t block_io_signals(void)sigaddset (&set,SIGIO );sigaddset (&set,SIGALRM );sigaddset (&set,SIG_IPI ); +sigaddset (&set,SIGBUS );pthread_sigmask (SIG_BLOCK , &set,NULL ); +memset (&action,0 ,sizeof (action)); + action.sa_flags =SA_SIGINFO ; + action.sa_sigaction = (void (*)(int ,siginfo_t *,void *))sigbus_handler; +sigaction (SIGBUS , &action,NULL ); +prctl (PR_MCE_KILL ,1 ,1 ,0 ,0 ); +return set; }
kvm-stub.c +5 -0
@@ -141,3 +141,8 @@ int kvm_set_ioeventfd_mmio_long(int fd, uint32_t adr, uint32_t val, bool assign) {return -ENOSYS ; } + +int kvm_on_sigbus (int code,void *addr) +{ +return 1 ; +}
kvm.h +3 -0
@@ -110,6 +110,9 @@ int kvm_arch_init_vcpu(CPUState *env);void kvm_arch_reset_vcpu (CPUState *env); +int kvm_on_sigbus_vcpu (CPUState *env,int code,void *addr); +int kvm_on_sigbus (int code,void *addr); +struct kvm_guest_debug ;struct kvm_debug_exit_arch ;
target-i386/cpu.h +18 -2
@@ -250,16 +250,32 @@#define PG_ERROR_RSVD_MASK 0x08#define PG_ERROR_I_D_MASK 0x10 -#define MCG_CTL_P (1UL<<8)/* MCG_CAP register available */ +#define MCG_CTL_P (1ULL<<8)/* MCG_CAP register available */ +#define MCG_SER_P (1ULL<<24)/* MCA recovery/new status bits */ -#define MCE_CAP_DEF MCG_CTL_P +#define MCE_CAP_DEF (MCG_CTL_P|MCG_SER_P)#define MCE_BANKS_DEF 10 +#define MCG_STATUS_RIPV (1ULL<<0)/* restart ip valid */ +#define MCG_STATUS_EIPV (1ULL<<1)/* ip points to correct instruction */ #define MCG_STATUS_MCIP (1ULL<<2)/* machine check in progress */ #define MCI_STATUS_VAL (1ULL<<63)/* valid error */ #define MCI_STATUS_OVER (1ULL<<62)/* previous errors lost */ #define MCI_STATUS_UC (1ULL<<61)/* uncorrected error */ +#define MCI_STATUS_EN (1ULL<<60)/* error enabled */ +#define MCI_STATUS_MISCV (1ULL<<59)/* misc error reg. valid */ +#define MCI_STATUS_ADDRV (1ULL<<58)/* addr reg. valid */ +#define MCI_STATUS_PCC (1ULL<<57)/* processor context corrupt */ +#define MCI_STATUS_S (1ULL<<56)/* Signaled machine check */ +#define MCI_STATUS_AR (1ULL<<55)/* Action required */ + +/* MISC register defines */ +#define MCM_ADDR_SEGOFF 0/* segment offset */ +#define MCM_ADDR_LINEAR 1/* linear address */ +#define MCM_ADDR_PHYS 2/* physical address */ +#define MCM_ADDR_MEM 3/* memory address */ +#define MCM_ADDR_GENERIC 7/* generic */ #define MSR_IA32_TSC 0x10#define MSR_IA32_APICBASE 0x1b
target-i386/helper.c +1 -1
@@ -1032,7 +1032,7 @@ void cpu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,return ;if (kvm_enabled ()) { -kvm_inject_x86_mce (cenv, bank, status, mcg_status, addr, misc); +kvm_inject_x86_mce (cenv, bank, status, mcg_status, addr, misc,0 );return ; }
target-i386/kvm.c +176 -2
216 lines not on this page · raw message
target-i386/kvm_x86.h +2 -1
@@ -16,6 +16,7 @@#define __KVM_X86_H__void kvm_inject_x86_mce (CPUState *cenv,int bank,uint64_t status, -uint64_t mcg_status,uint64_t addr,uint64_t misc); +uint64_t mcg_status,uint64_t addr,uint64_t misc, +int abort_on_error);#endif
Signature · 1 line
1.7.2.1
Re: [PATCH 08/10] MCE: Relay UCR MCE to guest
Quoted 37 lines · Marcelo Tosatti
Port qemu-kvm's
commit
4b62fff1101a7ad77553147717a8bd3bf79df7efAuthor: Huang Ying<[email protected]> Date: Mon Sep 21 10:43:25 2009 +0800MCE: Relay UCR MCE to guest
UCR (uncorrected recovery) MCE is supported in recent Intel CPUs, where some hardware error such as some memory error can be reported without PCC (processor context corrupted). To recover from such MCE, the corresponding memory will be unmapped, and all processes accessing the memory will be killed via SIGBUS.
For KVM, if QEMU/KVM is killed, all guest processes will be killed too. So we relay SIGBUS from host OS to guest system via a UCR MCE injection. Then guest OS can isolate corresponding memory and kill necessary guest processes only. SIGBUS sent to main thread (not VCPU threads) will be broadcast to all VCPU threads as UCR MCE.
Signed-off-by Marcelo Tosatti<[email protected]>Signed-off-by Avi Kivity<[email protected]>--- cpus.c | 82 ++++++++++++++++++++-- kvm-stub.c | 5 ++ kvm.h | 3 + target-i386/cpu.h | 20 +++++- target-i386/helper.c | 2 +- target-i386/kvm.c | 178 ++++++++++++++++++++++++++++++++++++++++++++++++- target-i386/kvm_x86.h | 3 +- 7 files changed, 279 insertions(+), 14 deletions(-)cpus.c +0
-0
cpus.c line 41
Quoted 8 lines
cpus.c +4
-0@@ -34,6 +34,10 @@#include "cpus.h" #include "compatfd.h" +#ifdef CONFIG_LINUX +#include <sys/prctl.h> +#include <sys/signalfd.h> +#endif
signalfd() was introduced in 2.6.22 but this is unconditionally included. This is going to break the build on any old Linux systems.
Quoted 32 lines
cpus.c +19
-0#ifdef SIGRTMIN #define SIG_IPI (SIGRTMIN+4)@@ -41,6 +45,10 @@#define SIG_IPI SIGUSR1#endif +#ifndef PR_MCE_KILL +#define PR_MCE_KILL 33 +#endif +static CPUState *next_cpu;/***********************************************************/ @@ -498,28 +506,77 @@ static void qemu_tcg_wait_io_event(void) } } +static void sigbus_reraise (void ) +{ +sigset_t set; +struct sigaction action; + +memset (&action,0 ,sizeof (action)); + action.sa_handler =SIG_DFL ; +if (!sigaction (SIGBUS ,&action,NULL )) { +raise (SIGBUS ); +sigemptyset (&set); +sigaddset (&set,SIGBUS ); +sigprocmask (SIG_UNBLOCK ,&set,NULL ); + } +perror ("Failed to re-raise SIGBUS!\n" ); +abort ();
cpus.c static void qemu_tcg_wait_io_event(void) · line 533
Quoted 10 lines
cpus.c +9
-0+} + +static void sigbus_handler (int n,struct qemu_signalfd_siginfo *siginfo, +void *ctx) +{ +#if defined(TARGET_I386 ) + if (kvm_on_sigbus(siginfo->ssi_code, (void *)(intptr_t)siginfo->ssi_addr)) +#endif +sigbus_reraise ();
This violates CODING style. Why not just get rid of the sigbus handler when not on TARGET_I386?
Quoted 47 lines
cpus.c +25
-8+} +static void qemu_kvm_eat_signal (CPUState *env,int timeout) {struct timespec ts;int r, e;siginfo_t siginfo;sigset_t waitset; +sigset_t chkset; ts.tv_sec = timeout /1000 ; ts.tv_nsec = (timeout %1000 ) *1000000 ;sigemptyset (&waitset);sigaddset (&waitset,SIG_IPI ); +sigaddset (&waitset,SIGBUS ); -qemu_mutex_unlock (&qemu_global_mutex); - r =sigtimedwait (&waitset,&siginfo,&ts); - e = errno; -qemu_mutex_lock (&qemu_global_mutex); + do { + qemu_mutex_unlock(&qemu_global_mutex); -if (r ==-1 && !(e ==EAGAIN || e ==EINTR )) { -fprintf (stderr,"sigtimedwait: %s\n" ,strerror (e)); -exit (1 ); - } + r = sigtimedwait(&waitset,&siginfo,&ts); + e = errno; + + qemu_mutex_lock(&qemu_global_mutex); + + if (r == -1&& !(e == EAGAIN || e == EINTR)) { + fprintf(stderr, "sigtimedwait: %s\n", strerror(e)); + exit(1); + } + + switch (r) { + case SIGBUS: +#ifdef TARGET_I386 + if (kvm_on_sigbus_vcpu(env, siginfo.si_code, siginfo.si_addr)) +#endif + sigbus_reraise(); + break; + default: + break;
cpus.c static void qemu_tcg_wait_io_event(void) · line 581
Quoted 10 lines
cpus.c +8
-0+ } + + r =sigpending (&chkset); +if (r ==-1 ) { +fprintf (stderr,"sigpending: %s\n" ,strerror (e)); +exit (1 ); + } + }while (sigismember (&chkset,SIG_IPI ) ||sigismember (&chkset,SIGBUS )); }
I don't understand why this loop is needed but we specifically wait for a signal to get delivered that's either SIG_IPI or SIGBUS. We then check whether a SIG_IPI or SIGBUS is pending and loop waiting for signals again.
Shouldn't we be looping on just sigismember(SIGBUS)?
BTW, we're no longer respecting timeout because we're not adjusting ts after each iteration.
Quoted 20 lines
static void
qemu_kvm_wait_io_event(CPUState *env)cpus.c +2
-0@@ -640,6 +697,7 @@ static void kvm_init_ipi(CPUState *env)pthread_sigmask (SIG_BLOCK ,NULL ,&set);sigdelset (&set,SIG_IPI ); +sigdelset (&set,SIGBUS ); r =kvm_set_signal_mask (env,&set);if (r) {fprintf (stderr,"kvm_set_signal_mask: %s\n" ,strerror (r));@@ -650,6 +708,7 @@ static void kvm_init_ipi(CPUState *env)static sigset_t block_io_signals (void ) {sigset_t set; +struct sigaction action;/* SIGUSR2 used by posix-aio-compat.c */ sigemptyset (&set);@@ -660,8 +719,15 @@ static sigset_t block_io_signals(void)sigaddset (&set,SIGIO );sigaddset (&set,SIGALRM );
cpus.c static sigset_t block_io_signals(void) · line 730
Quoted 10 lines
cpus.c +6
-0sigaddset (&set,SIG_IPI ); +sigaddset (&set,SIGBUS );pthread_sigmask (SIG_BLOCK ,&set,NULL ); +memset (&action,0 ,sizeof (action)); + action.sa_flags =SA_SIGINFO ; + action.sa_sigaction = (void (*)(int ,siginfo_t *,void *))sigbus_handler; +sigaction (SIGBUS ,&action,NULL ); +prctl (PR_MCE_KILL ,1 ,1 ,0 ,0 );
We don't seem to do any checking of the return value here. EINVAL seems like an expected error to me.
Quoted 101 lines
cpus.c +0
-0return set; }kvm-stub.c +5
-0@@ -141,3 +141,8 @@ int kvm_set_ioeventfd_mmio_long(int fd, uint32_t adr, uint32_t val, bool assign) {return -ENOSYS ; } + +int kvm_on_sigbus (int code,void *addr) +{ +return 1 ; +}kvm.h +3
-0@@ -110,6 +110,9 @@ int kvm_arch_init_vcpu(CPUState *env);void kvm_arch_reset_vcpu (CPUState *env); +int kvm_on_sigbus_vcpu (CPUState *env,int code,void *addr); +int kvm_on_sigbus (int code,void *addr); +struct kvm_guest_debug ;struct kvm_debug_exit_arch ;target-i386/cpu.h +18
-2@@ -250,16 +250,32 @@#define PG_ERROR_RSVD_MASK 0x08#define PG_ERROR_I_D_MASK 0x10 -#define MCG_CTL_P (1UL<<8)/* MCG_CAP register available */ +#define MCG_CTL_P (1ULL<<8)/* MCG_CAP register available */ +#define MCG_SER_P (1ULL<<24)/* MCA recovery/new status bits */ -#define MCE_CAP_DEF MCG_CTL_P +#define MCE_CAP_DEF (MCG_CTL_P|MCG_SER_P)#define MCE_BANKS_DEF 10 +#define MCG_STATUS_RIPV (1ULL<<0)/* restart ip valid */ +#define MCG_STATUS_EIPV (1ULL<<1)/* ip points to correct instruction */ #define MCG_STATUS_MCIP (1ULL<<2)/* machine check in progress */ #define MCI_STATUS_VAL (1ULL<<63)/* valid error */ #define MCI_STATUS_OVER (1ULL<<62)/* previous errors lost */ #define MCI_STATUS_UC (1ULL<<61)/* uncorrected error */ +#define MCI_STATUS_EN (1ULL<<60)/* error enabled */ +#define MCI_STATUS_MISCV (1ULL<<59)/* misc error reg. valid */ +#define MCI_STATUS_ADDRV (1ULL<<58)/* addr reg. valid */ +#define MCI_STATUS_PCC (1ULL<<57)/* processor context corrupt */ +#define MCI_STATUS_S (1ULL<<56)/* Signaled machine check */ +#define MCI_STATUS_AR (1ULL<<55)/* Action required */ + +/* MISC register defines */ +#define MCM_ADDR_SEGOFF 0/* segment offset */ +#define MCM_ADDR_LINEAR 1/* linear address */ +#define MCM_ADDR_PHYS 2/* physical address */ +#define MCM_ADDR_MEM 3/* memory address */ +#define MCM_ADDR_GENERIC 7/* generic */ #define MSR_IA32_TSC 0x10#define MSR_IA32_APICBASE 0x1btarget-i386/helper.c +1
-1@@ -1032,7 +1032,7 @@ void cpu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,return ;if (kvm_enabled ()) { -kvm_inject_x86_mce (cenv, bank, status, mcg_status, addr, misc); +kvm_inject_x86_mce (cenv, bank, status, mcg_status, addr, misc,0 );return ; }target-i386/kvm.c +7
-0@@ -46,6 +46,13 @@#define MSR_KVM_WALL_CLOCK 0x11#define MSR_KVM_SYSTEM_TIME 0x12 +#ifndef BUS_MCEERR_AR +#define BUS_MCEERR_AR 4 +#endif +#ifndef BUS_MCEERR_AO +#define BUS_MCEERR_AO 5 +#endif +#ifdef KVM_CAP_EXT_CPUID static struct kvm_cpuid2 *try_get_cpuid (KVMState *s,int max)
target-i386/kvm.c static int kvm_set_mce(CPUState *env, struct kvm_x86_mce *m) · line 205
Quoted 7 lines
target-i386/kvm.c +3
-0@@ -192,10 +199,39 @@ static int kvm_set_mce(CPUState *env, struct kvm_x86_mce *m)return kvm_vcpu_ioctl (env,KVM_X86_SET_MCE , m); } +static int kvm_get_msr (CPUState *env,struct kvm_msr_entry *msrs,int n) +{ +struct kvm_msrs *kmsrs =qemu_malloc (sizeof *kmsrs + n *sizeof *msrs);
sizeof should take ()s.
Quoted 35 lines
target-i386/kvm.c +26
-0+int r; + + kmsrs->nmsrs = n; +memcpy (kmsrs->entries, msrs, n *sizeof *msrs); + r =kvm_vcpu_ioctl (env,KVM_GET_MSRS , kmsrs); +memcpy (msrs, kmsrs->entries, n *sizeof *msrs); +free (kmsrs); +return r; +} + +/* FIXME: kill this and kvm_get_msr, use env->mcg_status instead */ +static int kvm_mce_in_exception (CPUState *env) +{ +struct kvm_msr_entry msr_mcg_status = { + .index =MSR_MCG_STATUS , + }; +int r; + + r =kvm_get_msr (env,&msr_mcg_status,1 ); +if (r ==-1 || r ==0 ) { +return -1 ; + } +return !!(msr_mcg_status.data&MCG_STATUS_MCIP ); +} +struct kvm_x86_mce_data {CPUState *env;struct kvm_x86_mce *mce; +int abort_on_error; };static void
kvm_do_inject_x86_mce(void *_data)target-i386/kvm.c +0
-0@@ -203,14 +239,26 @@ static void kvm_do_inject_x86_mce(void *_data)struct kvm_x86_mce_data *data = _data;
target-i386/kvm.c static void kvm_do_inject_x86_mce(void *_data) · line 249
Quoted 10 lines
target-i386/kvm.c +7
-0int r; +/* If there is an MCE excpetion being processed, ignore this SRAO MCE */ + r =kvm_mce_in_exception (data->env); +if (r ==-1 ) +fprintf (stderr,"Failed to get MCE status\n" ); +else if (r&& !(data->mce->status&MCI_STATUS_AR )) +return ; +
CODING_STYLE.
Quoted 19 lines
target-i386/kvm.c +7
-2r =kvm_set_mce (data->env, data->mce); -if (r<0 ) +if (r<0 ) {perror ("kvm_set_mce FAILED" ); +if (data->abort_on_error) { +abort (); + } + } }#endif void kvm_inject_x86_mce (CPUState *cenv,int bank,uint64_t status, -uint64_t mcg_status,uint64_t addr,uint64_t misc) +uint64_t mcg_status,uint64_t addr,uint64_t misc, +int abort_on_error) {#ifdef KVM_CAP_MCE struct kvm_x86_mce mce = {
target-i386/kvm.c void kvm_inject_x86_mce(CPUState *cenv, int bank, uint64_t status, · line 279
Quoted 7 lines
target-i386/kvm.c +3
-0@@ -225,7 +273,15 @@ void kvm_inject_x86_mce(CPUState *cenv, int bank, uint64_t status, .mce =&mce, }; +if (!cenv->mcg_cap) { +fprintf (stderr,"MCE support is not enabled!\n" ); +return ;
But we unconditionally enable this functionality so that means we're going to get spammed on stderr whenever an MCE occurs.
We really should not register a sigbus handler unless KVM supports injection and let the process get killed.
target-i386/kvm.c void kvm_inject_x86_mce(CPUState *cenv, int bank, uint64_t status, · line 287
Quoted 7 lines
target-i386/kvm.c +5
-0+ } +run_on_cpu (cenv, kvm_do_inject_x86_mce,&data); +#else +if (abort_on_error) +abort ();
CODING_STYLE
target-i386/kvm.c bool kvm_arch_stop_on_emulation_error(CPUState *env) · line 1591
Quoted 13 lines
target-i386/kvm.c +0
-0#endif }target-i386/kvm.c +5
-0@@ -1528,3 +1584,121 @@ bool kvm_arch_stop_on_emulation_error(CPUState *env) ((env->segs[R_CS ].selector&3 ) !=3 ); } +static void hardware_memory_error (void ) +{ +fprintf (stderr,"Hardware memory error!\n" ); +exit (1 ); +}
This shouldn't be here.
Quoted 35 lines
target-i386/kvm.c +34
-0+int kvm_on_sigbus_vcpu (CPUState *env,int code,void *addr) +{ +#if defined(KVM_CAP_MCE ) +struct kvm_x86_mce mce = { + .bank =9 , + }; +void *vaddr; +ram_addr_t ram_addr; +target_phys_addr_t paddr; +int r; + +if ((env->mcg_cap&MCG_SER_P )&& addr +&& (code ==BUS_MCEERR_AR + || code ==BUS_MCEERR_AO )) { +if (code ==BUS_MCEERR_AR ) { +/* Fake an Intel architectural Data Load SRAR UCR */ + mce.status =MCI_STATUS_VAL |MCI_STATUS_UC |MCI_STATUS_EN + |MCI_STATUS_MISCV |MCI_STATUS_ADDRV |MCI_STATUS_S + |MCI_STATUS_AR |0x134 ; + mce.misc = (MCM_ADDR_PHYS <<6 ) |0xc ; + mce.mcg_status =MCG_STATUS_MCIP |MCG_STATUS_EIPV ; + }else { +/* +* If there is an MCE excpetion being processed, ignore +* this SRAO MCE +*/ + r =kvm_mce_in_exception (env); +if (r ==-1 ) { +fprintf (stderr,"Failed to get MCE status\n" ); + }else if (r) { +return 0 ; + } +/* Fake an Intel architectural Memory scrubbing UCR */ + mce.status =MCI_STATUS_VAL |MCI_STATUS_UC |MCI_STATUS_EN
target-i386/kvm.c bool kvm_arch_stop_on_emulation_error(CPUState *env) · line 1636
Quoted 10 lines
target-i386/kvm.c +10
-0+ | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S + |0xc0 ; + mce.misc = (MCM_ADDR_PHYS <<6 ) |0xc ; + mce.mcg_status =MCG_STATUS_MCIP |MCG_STATUS_RIPV ; + } + vaddr = (void *)addr; +if (qemu_ram_addr_from_host (vaddr,&ram_addr) || + !kvm_physical_memory_addr_from_ram (env->kvm_state, ram_addr,&paddr)) { +fprintf (stderr,"Hardware memory error for memory used by " +"QEMU itself instead of guest system!\n" );
This is not a very useful way to handle this condition. why not at least reraise a SIGBUS so that we have a proper core?
target-i386/kvm.c bool kvm_arch_stop_on_emulation_error(CPUState *env) · line 1648
Quoted 13 lines
target-i386/kvm.c +12
-0+/* Hope we are lucky for AO MCE */ +if (code ==BUS_MCEERR_AO ) { +return 0 ; + }else { +hardware_memory_error (); + } + } + mce.addr = paddr; + r =kvm_set_mce (env,&mce); +if (r<0 ) { +fprintf (stderr,"kvm_set_mce: %s\n" ,strerror (errno)); +abort ();
There are calls to hardware_memory_error() and fprintf() in the same function. It all should be error_report().
Quoted 14 lines
target-i386/kvm.c +13
-0+ } + } else +#endif + { +if (code ==BUS_MCEERR_AO ) { +return 0 ; + }else if (code ==BUS_MCEERR_AR ) { +hardware_memory_error (); + }else { +return 1 ; + } + } +return 0 ;
target-i386/kvm.c bool kvm_arch_stop_on_emulation_error(CPUState *env) · line 1671
Quoted 10 lines
target-i386/kvm.c +10
-0+} + +int kvm_on_sigbus (int code,void *addr) +{ +#if defined(KVM_CAP_MCE ) +if ((first_cpu->mcg_cap&MCG_SER_P )&& addr&& code ==BUS_MCEERR_AO ) { +uint64_t status; +void *vaddr; +target_phys_addr_t ram_addr; +unsigned long paddr;
ram_addr should be ram_addr_t and paddr should be target_phys_addr_t.
target-i386/kvm.c bool kvm_arch_stop_on_emulation_error(CPUState *env) · line 1679
Quoted 9 lines
target-i386/kvm.c +8
-0+CPUState *cenv; + +/* Hope we are lucky for AO MCE */ + vaddr = addr; +if (qemu_ram_addr_from_host (vaddr,&ram_addr) || + !kvm_physical_memory_addr_from_ram (first_cpu->kvm_state, ram_addr,&paddr)) { +fprintf (stderr,"Hardware memory error for memory used by " +"QEMU itself instead of guest system!: %p\n" , addr);
Again, this is not a useful way to handle this.
Quoted 31 lines
target-i386/kvm.c +25
-0+ return 0; + } + status =MCI_STATUS_VAL |MCI_STATUS_UC |MCI_STATUS_EN + |MCI_STATUS_MISCV |MCI_STATUS_ADDRV |MCI_STATUS_S + |0xc0 ; +kvm_inject_x86_mce (first_cpu,9 , status, +MCG_STATUS_MCIP |MCG_STATUS_RIPV , paddr, + (MCM_ADDR_PHYS <<6 ) |0xc ,1 ); +for (cenv = first_cpu->next_cpu; cenv !=NULL ; cenv = cenv->next_cpu) { +kvm_inject_x86_mce (cenv,1 ,MCI_STATUS_VAL |MCI_STATUS_UC , +MCG_STATUS_MCIP |MCG_STATUS_RIPV ,0 ,0 ,1 ); + } + } else +#endif + { +if (code ==BUS_MCEERR_AO ) { +return 0 ; + }else if (code ==BUS_MCEERR_AR ) { +hardware_memory_error (); + }else { +return 1 ; + } + } +return 0 ; +}target-i386/kvm_x86.h +0
-0
target-i386/kvm_x86.h line 22
Quoted 8 lines
target-i386/kvm_x86.h +2
-1@@ -16,6 +16,7 @@#define __KVM_X86_H__void kvm_inject_x86_mce (CPUState *cenv,int bank,uint64_t status, -uint64_t mcg_status,uint64_t addr,uint64_t misc); +uint64_t mcg_status,uint64_t addr,uint64_t misc, +int abort_on_error);#endif
Regards,
Anthony Liguori
Re: [PATCH 08/10] MCE: Relay UCR MCE to guest
Quoted 62 lines · Anthony Liguori
Quoted 57 lines
cpus.c +20
-8+} + static void qemu_kvm_eat_signal(CPUState *env, int timeout) { struct timespec ts; int r, e; siginfo_t siginfo; sigset_t waitset; + sigset_t chkset; ts.tv_sec = timeout / 1000; ts.tv_nsec = (timeout % 1000) * 1000000; sigemptyset(&waitset); sigaddset(&waitset, SIG_IPI); + sigaddset(&waitset, SIGBUS); -qemu_mutex_unlock (&qemu_global_mutex); - r =sigtimedwait (&waitset,&siginfo,&ts); - e = errno; -qemu_mutex_lock (&qemu_global_mutex); + do { + qemu_mutex_unlock(&qemu_global_mutex); -if (r ==-1 && !(e ==EAGAIN || e ==EINTR )) { -fprintf (stderr,"sigtimedwait: %s\n" ,strerror (e)); -exit (1 ); - } + r = sigtimedwait(&waitset,&siginfo,&ts); + e = errno; + + qemu_mutex_lock(&qemu_global_mutex); + + if (r == -1&& !(e == EAGAIN || e == EINTR)) { + fprintf(stderr, "sigtimedwait: %s\n", strerror(e)); + exit(1); + } + + switch (r) { + case SIGBUS: +#ifdef TARGET_I386 + if (kvm_on_sigbus_vcpu(env, siginfo.si_code,siginfo.si_addr))
cpus.c +13
-0+#endif +sigbus_reraise (); +break ; +default : +break ; + } + + r =sigpending (&chkset); +if (r ==-1 ) { +fprintf (stderr,"sigpending: %s\n" ,strerror (e)); +exit (1 ); + } + } while (sigismember(&chkset, SIG_IPI) || sigismember(&chkset,Quoted 2 lines
SIGBUS));
}I don't understand why this loop is needed but we specifically wait for a signal to get delivered that's either
SIG_IPIor SIGBUS. We then check whether aSIG_IPIor SIGBUS is pending and loop waiting for signals again.
Quoted 3 lines
Shouldn't we be looping on just sigismember(SIGBUS)?
BTW, we're no longer respecting timeout because we're not adjusting ts after each iteration.
I think this is important too. The last time I went through the code and played around here, it wasn't possible to set timeout to a very, very large value because there are still things that we poll for (like whether shutdown has occurred). If we loop indefinitely without reducing ts, we can potentially recreate an infinite timeout which means we won't catch any of the events we poll for. This would be a very, very subtle bug to track down.
Regards,
Anthony Liguori
Re: [Qemu-devel] Re: [PATCH 08/10] MCE: Relay UCR MCE to guest
Quoted 71 lines · Anthony Liguori
Quoted 65 lines · Anthony Liguori
Quoted 57 lines
cpus.c +20
-8+} + static void qemu_kvm_eat_signal(CPUState *env, int timeout) { struct timespec ts; int r, e; siginfo_t siginfo; sigset_t waitset; + sigset_t chkset; ts.tv_sec = timeout / 1000; ts.tv_nsec = (timeout % 1000) * 1000000; sigemptyset(&waitset); sigaddset(&waitset, SIG_IPI); + sigaddset(&waitset, SIGBUS); -qemu_mutex_unlock (&qemu_global_mutex); - r =sigtimedwait (&waitset,&siginfo,&ts); - e = errno; -qemu_mutex_lock (&qemu_global_mutex); + do { + qemu_mutex_unlock(&qemu_global_mutex); -if (r ==-1 && !(e ==EAGAIN || e ==EINTR )) { -fprintf (stderr,"sigtimedwait: %s\n" ,strerror (e)); -exit (1 ); - } + r = sigtimedwait(&waitset,&siginfo,&ts); + e = errno; + + qemu_mutex_lock(&qemu_global_mutex); + + if (r == -1&& !(e == EAGAIN || e == EINTR)) { + fprintf(stderr, "sigtimedwait: %s\n", strerror(e)); + exit(1); + } + + switch (r) { + case SIGBUS: +#ifdef TARGET_I386 + if (kvm_on_sigbus_vcpu(env, siginfo.si_code,siginfo.si_addr))
cpus.c +13
-0+#endif +sigbus_reraise (); +break ; +default : +break ; + } + + r =sigpending (&chkset); +if (r ==-1 ) { +fprintf (stderr,"sigpending: %s\n" ,strerror (e)); +exit (1 ); + } + } while (sigismember(&chkset, SIG_IPI) ||Quoted 2 lines
sigismember(&chkset, SIGBUS));
}I don't understand why this loop is needed but we specifically wait for a signal to get delivered that's either
SIG_IPIor SIGBUS. We then check whether aSIG_IPIor SIGBUS is pending and loop waiting for signals again.Quoted 4 lines
Shouldn't we be looping on just sigismember(SIGBUS)?
BTW, we're no longer respecting timeout because we're not adjusting ts after each iteration.
Quoted 7 lines
I think this is important too. The last time I went through the code and played around here, it wasn't possible to set timeout to a very, very large value because there are still things that we poll
for (like whether shutdown has occurred). If we loop indefinitely
without reducing ts, we can potentially recreate an infinite timeout which means we won't catch any of the events we poll for. This would be a very, very subtle bug to track down.
We should just kill timeout parameter, i don't see any use for it.
Re: [Qemu-devel] Re: [PATCH 08/10] MCE: Relay UCR MCE to guest
In reply to Anthony LiguoriQuoted 33 lines · Anthony Liguori
Quoted 17 lines
cpus.c +17
-0+ e = errno; + +qemu_mutex_lock (&qemu_global_mutex); + +if (r ==-1 && !(e ==EAGAIN || e ==EINTR )) { +fprintf (stderr,"sigtimedwait: %s\n" ,strerror (e)); +exit (1 ); + } + +switch (r) { +case SIGBUS : +#ifdef TARGET_I386 + if (kvm_on_sigbus_vcpu(env, siginfo.si_code, siginfo.si_addr)) +#endif +sigbus_reraise (); +break ; +default :cpus.c static void qemu_tcg_wait_io_event(void) · line 580
Quoted 10 lines
cpus.c +9
-0+break ; + } + + r =sigpending (&chkset); +if (r ==-1 ) { +fprintf (stderr,"sigpending: %s\n" ,strerror (e)); +exit (1 ); + } + }while (sigismember (&chkset,SIG_IPI ) ||sigismember (&chkset,SIGBUS )); }I don't understand why this loop is needed but we specifically wait for a signal to get delivered that's either
SIG_IPIor SIGBUS. We then check whether aSIG_IPIor SIGBUS is pending and loop waiting for signals again.
Quoted 1 line
Shouldn't we be looping on just sigismember(SIGBUS)?
Think of SIG_IPI and SIGBUS pending. SIGBUS must be processed immediately.
Yes, sigismember(SIGBUS) would be fine. But the current code too.
Quoted 2 lines
BTW, we're no longer respecting timeout because we're not adjusting ts after each iteration.
Right, timeout not used at the moment.
Paolo Bonzini
maintainerRe: [PATCH 08/10] MCE: Relay UCR MCE to guest
In reply to Anthony LiguoriQuoted 5 lines · Anthony Liguori
I don't understand why this loop is needed but we specifically wait for a signal to get delivered that's either
SIG_IPIor SIGBUS. We then check whether aSIG_IPIor SIGBUS is pending and loop waiting for signals again.Shouldn't we be looping on just sigismember(SIGBUS)?
You mean because SIG_IPI is a real-time signal and standard signals are delivered first? OTOH, real-time signals can be queued multiple times so it makes sense to loop on SIG_IPI as well.
Quoted 2 lines
BTW, we're no longer respecting timeout because we're not adjusting ts after each iteration.
The timeout of qemu_kvm_eat_signal is always zero.
Paolo
Re: [PATCH 08/10] MCE: Relay UCR MCE to guest
Quoted 5 lines · Paolo Bonzini
Quoted 4 lines · Anthony Liguori
I don't understand why this loop is needed but we specifically wait for a signal to get delivered that's either
SIG_IPIor SIGBUS. We then check whether aSIG_IPIor SIGBUS is pending and loop waiting for signals again.
Quoted 8 lines
Quoted 1 line
Shouldn't we be looping on just sigismember(SIGBUS)?
You mean because
SIG_IPIis a real-time signal and standard signals are delivered first? OTOH, real-time signals can be queued multiple times so it makes sense to loop onSIG_IPIas well.Quoted 2 lines
BTW, we're no longer respecting timeout because we're not adjusting ts after each iteration.
The timeout of
qemu_kvm_eat_signalis always zero.
So then qemu_kvm_eat_signal purely polls and it will happily keep polling as long as there is a signal pending.
So what's the point of doing a sigtimedwait() and dropping qemu_mutex? Why not just check sigpending in a loop?
Regards,
Anthony Liguori
Quoted 1 line
Paolo
Paolo Bonzini
maintainerRe: [PATCH 08/10] MCE: Relay UCR MCE to guest
Quoted 7 lines · Anthony Liguori
Quoted 2 lines
The timeout of
qemu_kvm_eat_signalis always zero.So then
qemu_kvm_eat_signalpurely polls and it will happily keep polling as long as there is a signal pending.So what's the point of doing a
sigtimedwait()and droppingqemu_mutex?
I agree that keeping the qemu_mutex makes sense if you remove the timeout argument (which I even have a patch for, as part of my Win32 iothread series). Until there is the theoretical possibility of suspending the process, qemu_kvm_eat_signal should drop the mutex.
Quoted 1 line
Why not just check sigpending in a loop?
Because sigtimedwait eats the signal, unlike sigpending (and sigsuspend).
PATCH 9/10 Add savevm/loadvm support for MCE
In reply to Marcelo TosattiPort qemu-kvm's
commit 1bab5d11545d8de5facf46c28630085a2f9651ae
Author: Huang Ying <[email protected]> Date: Wed Mar 3 16:52:46 2010 +0800
Add savevm/loadvm support for MCE
MCE registers are saved/load into/from CPUState in kvm_arch_save/load_regs. To simulate the MCG_STATUS clearing upon reset, MSR_MCG_STATUS is set to 0 for KVM_PUT_RESET_STATE.
--- target-i386/kvm.c | 39 ++++++++++++++++++++++++++++++++++++++- 1 files changed, 38 insertions(+), 1 deletions(-)
target-i386/kvm.c +38 -1
@@ -777,7 +777,7 @@ static int kvm_put_msrs(CPUState *env, int level)struct kvm_msr_entry entries[100 ]; } msr_data;struct kvm_msr_entry *msrs = msr_data.entries; -int n =0 ; +int i, n =0 ;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);
@@ -797,6 +797,18 @@ 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); } +#ifdef KVM_CAP_MCE +if (env->mcg_cap) { +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]); + } + } +#endif msr_data.info.nmsrs = n;
@@ -1004,6 +1016,15 @@ static int kvm_get_msrs(CPUState *env) msrs[n++].index =MSR_KVM_SYSTEM_TIME ; msrs[n++].index =MSR_KVM_WALL_CLOCK ; +#ifdef KVM_CAP_MCE +if (env->mcg_cap) { + msrs[n++].index =MSR_MCG_STATUS ; + msrs[n++].index =MSR_MCG_CTL ; +for (i =0 ; i < (env->mcg_cap &0xff ) *4 ; i++) + msrs[n++].index =MSR_MC0_CTL + i; + } +#endif + msr_data.info.nmsrs = n; ret =kvm_vcpu_ioctl (env,KVM_GET_MSRS , &msr_data);if (ret <0 )
@@ -1046,6 +1067,22 @@ static int kvm_get_msrs(CPUState *env)case MSR_KVM_WALL_CLOCK : env->wall_clock_msr = msrs[i].data;break ; +#ifdef KVM_CAP_MCE +case MSR_MCG_STATUS : + env->mcg_status = msrs[i].data; +break ; +case MSR_MCG_CTL : + env->mcg_ctl = msrs[i].data; +break ; +#endif +default : +#ifdef KVM_CAP_MCE +if (msrs[i].index >=MSR_MC0_CTL && + msrs[i].index <MSR_MC0_CTL + (env->mcg_cap &0xff ) *4 ) { + env->mce_banks[msrs[i].index -MSR_MC0_CTL ] = msrs[i].data; +break ; + } +#endif } }
Signature · 1 line
1.7.2.1
Re: [PATCH 09/10] Add savevm/loadvm support for MCE
Quoted 38 lines · Marcelo Tosatti
Port qemu-kvm's
commit
1bab5d11545d8de5facf46c28630085a2f9651aeAuthor: Huang Ying<[email protected]> Date: Wed Mar 3 16:52:46 2010 +0800Add savevm/loadvm support for MCE
MCE registers are saved/load into/from CPUState in kvm_arch_save/load_regs. To simulate the
MCG_STATUSclearing upon reset,MSR_MCG_STATUSis set to 0 forKVM_PUT_RESET_STATE.Signed-off-by Marcelo Tosatti<[email protected]>Signed-off-by Avi Kivity<[email protected]>--- target-i386/kvm.c | 39 ++++++++++++++++++++++++++++++++++++++- 1 files changed, 38 insertions(+), 1 deletions(-)target-i386/kvm.c +4
-1@@ -777,7 +777,7 @@ static int kvm_put_msrs(CPUState *env, int level)struct kvm_msr_entry entries[100 ]; } msr_data;struct kvm_msr_entry *msrs = msr_data.entries; -int n =0 ; +int i, n =0 ;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);@@ -797,6 +797,18 @@ 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); } +#ifdef KVM_CAP_MCE +if (env->mcg_cap) { +if (level ==KVM_PUT_RESET_STATE )
target-i386/kvm.c static int kvm_put_msrs(CPUState *env, int level) · line 812
Quoted 10 lines
target-i386/kvm.c +9
-0+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]); + } + } +#endif
What happens if we live migration from a kernel with KVM_CAP_MCE to a kernel without KVM_CAP_MCE. Don't we need to bump a version somewhere?
Quoted 6 lines
target-i386/kvm.c +0
-0msr_data.info.nmsrs = n;@@ -1004,6 +1016,15 @@ static int kvm_get_msrs(CPUState *env) msrs[n++].index =MSR_KVM_SYSTEM_TIME ; msrs[n++].index =MSR_KVM_WALL_CLOCK ;
target-i386/kvm.c static int kvm_get_msrs(CPUState *env) · line 1028
Quoted 10 lines
target-i386/kvm.c +9
-0+#ifdef KVM_CAP_MCE +if (env->mcg_cap) { + msrs[n++].index =MSR_MCG_STATUS ; + msrs[n++].index =MSR_MCG_CTL ; +for (i =0 ; i< (env->mcg_cap&0xff ) *4 ; i++) + msrs[n++].index =MSR_MC0_CTL + i; + } +#endif +
This patch does not respect CODING_STYLE with respect to single line ifs at all.
Regards,
Anthony Liguori
Quoted 27 lines
target-i386/kvm.c +0
-0msr_data.info.nmsrs = n; ret =kvm_vcpu_ioctl (env,KVM_GET_MSRS ,&msr_data);if (ret< 0)target-i386/kvm.c +16
-0@@ -1046,6 +1067,22 @@ static int kvm_get_msrs(CPUState *env)case MSR_KVM_WALL_CLOCK : env->wall_clock_msr = msrs[i].data;break ; +#ifdef KVM_CAP_MCE +case MSR_MCG_STATUS : + env->mcg_status = msrs[i].data; +break ; +case MSR_MCG_CTL : + env->mcg_ctl = msrs[i].data; +break ; +#endif +default : +#ifdef KVM_CAP_MCE +if (msrs[i].index>=MSR_MC0_CTL && + msrs[i].index<MSR_MC0_CTL + (env->mcg_cap&0xff ) *4 ) { + env->mce_banks[msrs[i].index -MSR_MC0_CTL ] = msrs[i].data; +break ; + } +#endif } }
PATCH 10/10 Fix memory leak in register save load due to xsave support
In reply to Marcelo TosattiFrom: Avi Kivity <[email protected]>
--- target-i386/kvm.c | 11 ++++++++--- 1 files changed, 8 insertions(+), 3 deletions(-)
target-i386/kvm.c +8 -3
@@ -660,7 +660,7 @@ static int kvm_put_fpu(CPUState *env)static int kvm_put_xsave (CPUState *env) {#ifdef KVM_CAP_XSAVE -int i; +int i, r;struct kvm_xsave * xsave;uint16_t cwd, swd, twd, fop;
@@ -685,7 +685,9 @@ static int kvm_put_xsave(CPUState *env) *(uint64_t *)&xsave->region[XSAVE_XSTATE_BV ] = env->xstate_bv;memcpy (&xsave->region[XSAVE_YMMH_SPACE ], env->ymmh_regs,sizeof env->ymmh_regs); -return kvm_vcpu_ioctl (env,KVM_SET_XSAVE , xsave); + r =kvm_vcpu_ioctl (env,KVM_SET_XSAVE , xsave); +qemu_free (xsave); +return r;#else return kvm_put_fpu (env);#endif
@@ -850,8 +852,10 @@ static int kvm_get_xsave(CPUState *env) xsave =qemu_memalign (4096 ,sizeof (struct kvm_xsave )); ret =kvm_vcpu_ioctl (env,KVM_GET_XSAVE , xsave); -if (ret <0 ) +if (ret <0 ) { +qemu_free (xsave);return ret; + } cwd = (uint16_t )xsave->region[0 ]; swd = (uint16_t )(xsave->region[0 ] >>16 );
@@ -870,6 +874,7 @@ static int kvm_get_xsave(CPUState *env) env->xstate_bv = *(uint64_t *)&xsave->region[XSAVE_XSTATE_BV ];memcpy (env->ymmh_regs, &xsave->region[XSAVE_YMMH_SPACE ],sizeof env->ymmh_regs); +qemu_free (xsave);return 0 ;#else return kvm_get_fpu (env);
Signature · 1 line
1.7.2.1
Quoted 14 lines · Marcelo Tosatti
The following changes since commit
38cc9b607f85017b095793cab6c129bc9844f441:issue snd_pcm_start() when capturing audio (2010-10-18 00:39:06 +0400)are available in the git repository at:
git://git.kernel.org/pub/scm/virt/kvm/qemu-kvm.gituq/masterHuang Ying (1):
Add RAM -> physical addr mapping in MCE simulationJoerg Roedel (2):
Set cpuid definition to 0 before initializing it Add svm cpuid features
Quoted 9 lines
Marcelo Tosatti (7):
signalfd compatibility
iothread: use signalfd
kvm: x86: add mce support
Exportqemu_ram_addr_from_host
MCE: Relay UCR MCE to guest
Add savevm/loadvm support for MCE
Fix memory leak in register save load due to xsave support
Does this fix the second build issue too is this is just with v2 of hte Relay UCR MCE to guest?
Regards,
ANthony Liguori
Quoted 25 lines
Makefile.objs | 1 + compatfd.c | 117 ++++++++++++++++++ compatfd.h | 43 +++++++ configure | 18 +++ cpu-common.h | 3 +- cpus.c | 156 ++++++++++++++++++++++-- exec-all.h | 2 +- exec.c | 26 +++-- kvm-all.c | 18 +++ kvm-stub.c | 5 + kvm.h | 9 ++ target-i386/cpu.h | 32 +++++- target-i386/cpuid.c | 79 ++++++++++--- target-i386/helper.c | 6 + target-i386/kvm.c | 311 ++++++++++++++++++++++++++++++++++++++++++++++++- target-i386/kvm_x86.h | 22 ++++ 16 files changed, 801 insertions(+), 47 deletions(-)create mode 100644
compatfd.c
create mode 100644compatfd.h
create mode 100644target-i386/kvm_x86.h
--
To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 24 lines · Anthony Liguori
Quoted 14 lines · Marcelo Tosatti
The following changes since commit
38cc9b607f85017b095793cab6c129bc9844f441:issue
snd_pcm_start()when capturing audio (2010-10-18 00:39:06 +0400)are available in the git repository at:
git://git.kernel.org/pub/scm/virt/kvm/qemu-kvm.gituq/masterHuang Ying (1):
Add RAM -> physical addr mapping in MCE simulationJoerg Roedel (2):
Set cpuid definition to 0 before initializing it Add svm cpuid featuresQuoted 8 lines
Marcelo Tosatti (7):
signalfd compatibility
iothread: use signalfd
kvm: x86: add mce support
Exportqemu_ram_addr_from_host
MCE: Relay UCR MCE to guest
Add savevm/loadvm support for MCE
Fix memory leak in register save load due to xsave support
Quoted 2 lines
Does this fix the second build issue too is this is just with v2 of hte Relay UCR MCE to guest?
Yes, second and third...
Quoted 27 lines · Marcelo Tosatti
Quoted 25 lines · Anthony Liguori
Quoted 23 lines · Marcelo Tosatti
The following changes since commit
38cc9b607f85017b095793cab6c129bc9844f441:issue snd_pcm_start() when capturing audio (2010-10-18 00:39:06 +0400)are available in the git repository at:
git://git.kernel.org/pub/scm/virt/kvm/qemu-kvm.gituq/masterHuang Ying (1):
Add RAM -> physical addr mapping in MCE simulationJoerg Roedel (2):
Set cpuid definition to 0 before initializing it Add svm cpuid featuresMarcelo Tosatti (7):
signalfd compatibility
iothread: use signalfd
kvm: x86: add mce support
Exportqemu_ram_addr_from_host
MCE: Relay UCR MCE to guest
Add savevm/loadvm support for MCE
Fix memory leak in register save load due to xsave support
Quoted 5 lines
Quoted 3 lines
Does this fix the second build issue too is this is just with v2 of hte Relay UCR MCE to guest?
Yes, second and third...
That wasn't enough either. The types used in this code aren't correct.
I've fixed up the build and pushed http://repo.or.cz/w/qemu/aliguori.git qemu-kvm-20101020
Let me test a little bit and look a bit more closely at the code and then I'll push to the main tree.
Regards,
Anthony Liguori
Quoted 14 lines · Marcelo Tosatti
The following changes since commit
38cc9b607f85017b095793cab6c129bc9844f441:issue snd_pcm_start() when capturing audio (2010-10-18 00:39:06 +0400)are available in the git repository at:
git://git.kernel.org/pub/scm/virt/kvm/qemu-kvm.gituq/masterHuang Ying (1):
Add RAM -> physical addr mapping in MCE simulationJoerg Roedel (2):
Set cpuid definition to 0 before initializing it Add svm cpuid features
Quoted 9 lines
Marcelo Tosatti (7):
signalfd compatibility
iothread: use signalfd
kvm: x86: add mce support
Exportqemu_ram_addr_from_host
MCE: Relay UCR MCE to guest
Add savevm/loadvm support for MCE
Fix memory leak in register save load due to xsave support
The MCE doesn't look to be ready for prime time yet.
Regards,
Anthony Liguori
Quoted 21 lines
Makefile.objs | 1 + compatfd.c | 117 ++++++++++++++++++ compatfd.h | 43 +++++++ configure | 18 +++ cpu-common.h | 3 +- cpus.c | 156 ++++++++++++++++++++++-- exec-all.h | 2 +- exec.c | 26 +++-- kvm-all.c | 18 +++ kvm-stub.c | 5 + kvm.h | 9 ++ target-i386/cpu.h | 32 +++++- target-i386/cpuid.c | 79 ++++++++++--- target-i386/helper.c | 6 + target-i386/kvm.c | 311 ++++++++++++++++++++++++++++++++++++++++++++++++- target-i386/kvm_x86.h | 22 ++++ 16 files changed, 801 insertions(+), 47 deletions(-)create mode 100644
compatfd.c
create mode 100644compatfd.h
create mode 100644target-i386/kvm_x86.h
Quoted 7 lines · Marcelo Tosatti
The following changes since commit
38cc9b607f85017b095793cab6c129bc9844f441:issue snd_pcm_start() when capturing audio (2010-10-18 00:39:06 +0400)are available in the git repository at:
git://git.kernel.org/pub/scm/virt/kvm/qemu-kvm.gituq/master
Pulled (with additional build fixes).
Regards,
Anthony Liguori
Quoted 37 lines
Huang Ying (1):
Add RAM -> physical addr mapping in MCE simulationJoerg Roedel (2):
Set cpuid definition to 0 before initializing it Add svm cpuid featuresMarcelo Tosatti (7):
signalfd compatibility
iothread: use signalfd
kvm: x86: add mce support
Exportqemu_ram_addr_from_host
MCE: Relay UCR MCE to guest
Add savevm/loadvm support for MCE
Fix memory leak in register save load due to xsave supportMakefile.objs | 1 + compatfd.c | 117 ++++++++++++++++++ compatfd.h | 43 +++++++ configure | 18 +++ cpu-common.h | 3 +- cpus.c | 156 ++++++++++++++++++++++-- exec-all.h | 2 +- exec.c | 26 +++-- kvm-all.c | 18 +++ kvm-stub.c | 5 + kvm.h | 9 ++ target-i386/cpu.h | 32 +++++- target-i386/cpuid.c | 79 ++++++++++--- target-i386/helper.c | 6 + target-i386/kvm.c | 311 ++++++++++++++++++++++++++++++++++++++++++++++++- target-i386/kvm_x86.h | 22 ++++ 16 files changed, 801 insertions(+), 47 deletions(-)create mode 100644
compatfd.c
create mode 100644compatfd.h
create mode 100644target-i386/kvm_x86.h