diff options
author | Marcelo Tosatti <mtosatti@redhat.com> | 2011-04-14 01:15:24 -0300 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2011-04-14 01:15:24 -0300 |
commit | 44a67a7c0e7a60aab03e09737cb8667a029b6ad7 (patch) | |
tree | 1242be58eb271a62e40284406e389c13a047a9c4 | |
parent | df85c051d780bca0ee2462cfeb8ef6d9552a19b0 (diff) | |
parent | 419fb20a8eab0376d86790a9907553307b1654c5 (diff) |
Merge commit '419fb20a8eab0376d86790a9907553307b1654c5' into upstream-merge
* commit '419fb20a8eab0376d86790a9907553307b1654c5':
kvm: x86: Move MCE functions together
Synchronize VCPU states before reset
x86: Optionally avoid injecting AO MCEs while others are pending
x86: Refine error reporting of MCE injection services
x86: Small cleanups of MCE helpers
x86: Perform implicit mcg_status reset
x86: Account for MCE in cpu_has_work
kvm: Fix build warning when KVM_CAP_SET_GUEST_DEBUG is lacking
kvm: ppc: Fix breakage of kvm_arch_pre_run/process_irqchip_events
Conflicts:
target-i386/kvm.c
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
-rw-r--r-- | cpu-all.h | 4 | ||||
-rw-r--r-- | kvm-all.c | 2 | ||||
-rw-r--r-- | monitor.c | 11 | ||||
-rw-r--r-- | qemu-common.h | 6 | ||||
-rw-r--r-- | target-i386/cpu.h | 11 | ||||
-rw-r--r-- | target-i386/exec.h | 15 | ||||
-rw-r--r-- | target-i386/helper.c | 120 | ||||
-rw-r--r-- | target-i386/kvm.c | 346 | ||||
-rw-r--r-- | target-ppc/kvm.c | 6 | ||||
-rw-r--r-- | vl.c | 1 |
10 files changed, 278 insertions, 244 deletions
@@ -971,8 +971,4 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf); int cpu_memory_rw_debug(CPUState *env, target_ulong addr, uint8_t *buf, int len, int is_write); -void cpu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status, - uint64_t mcg_status, uint64_t addr, uint64_t misc, - int broadcast); - #endif /* CPU_ALL_H */ @@ -1019,7 +1019,9 @@ int kvm_cpu_exec(CPUState *env) } ret = EXCP_INTERRUPT; +#ifdef KVM_CAP_SET_GUEST_DEBUG out: +#endif env->exit_request = 0; cpu_single_env = NULL; return ret; @@ -2737,12 +2737,15 @@ static void do_inject_mce(Monitor *mon, const QDict *qdict) uint64_t mcg_status = qdict_get_int(qdict, "mcg_status"); uint64_t addr = qdict_get_int(qdict, "addr"); uint64_t misc = qdict_get_int(qdict, "misc"); - int broadcast = qdict_get_try_bool(qdict, "broadcast", 0); + int flags = MCE_INJECT_UNCOND_AO; + if (qdict_get_try_bool(qdict, "broadcast", 0)) { + flags |= MCE_INJECT_BROADCAST; + } for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) { - if (cenv->cpu_index == cpu_index && cenv->mcg_cap) { - cpu_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc, - broadcast); + if (cenv->cpu_index == cpu_index) { + cpu_x86_inject_mce(mon, cenv, bank, status, mcg_status, addr, misc, + flags); break; } } diff --git a/qemu-common.h b/qemu-common.h index 3fe1719d0..7a96dd14e 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -18,6 +18,9 @@ typedef struct QEMUFile QEMUFile; typedef struct QEMUBH QEMUBH; typedef struct DeviceState DeviceState; +struct Monitor; +typedef struct Monitor Monitor; + /* we put basic includes here to avoid repeating them in device drivers */ #include <stdlib.h> #include <stdio.h> @@ -327,9 +330,6 @@ void qemu_iovec_memset(QEMUIOVector *qiov, int c, size_t count); void qemu_iovec_memset_skip(QEMUIOVector *qiov, int c, size_t count, size_t skip); -struct Monitor; -typedef struct Monitor Monitor; - /* Convert a byte between binary and BCD. */ static inline uint8_t to_bcd(uint8_t val) { diff --git a/target-i386/cpu.h b/target-i386/cpu.h index cfd7f003d..497474f84 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -687,6 +687,8 @@ typedef struct CPUX86State { uint64_t pat; + uint64_t mcg_status; + /* exception/interrupt handling */ int error_code; int exception_is_int; @@ -741,7 +743,6 @@ typedef struct CPUX86State { struct DeviceState *apic_state; uint64_t mcg_cap; - uint64_t mcg_status; uint64_t mcg_ctl; uint64_t mce_banks[MCE_BANKS_DEF*4]; @@ -988,4 +989,12 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc, void do_cpu_init(CPUState *env); void do_cpu_sipi(CPUState *env); + +#define MCE_INJECT_BROADCAST 1 +#define MCE_INJECT_UNCOND_AO 2 + +void cpu_x86_inject_mce(Monitor *mon, CPUState *cenv, int bank, + uint64_t status, uint64_t mcg_status, uint64_t addr, + uint64_t misc, int flags); + #endif /* CPU_I386_H */ diff --git a/target-i386/exec.h b/target-i386/exec.h index 3e7386e91..6f9f709d8 100644 --- a/target-i386/exec.h +++ b/target-i386/exec.h @@ -293,15 +293,12 @@ static inline void load_eflags(int eflags, int update_mask) static inline int cpu_has_work(CPUState *env) { - int work; - - work = (env->interrupt_request & CPU_INTERRUPT_HARD) && - (env->eflags & IF_MASK); - work |= env->interrupt_request & CPU_INTERRUPT_NMI; - work |= env->interrupt_request & CPU_INTERRUPT_INIT; - work |= env->interrupt_request & CPU_INTERRUPT_SIPI; - - return work; + return ((env->interrupt_request & CPU_INTERRUPT_HARD) && + (env->eflags & IF_MASK)) || + (env->interrupt_request & (CPU_INTERRUPT_NMI | + CPU_INTERRUPT_INIT | + CPU_INTERRUPT_SIPI | + CPU_INTERRUPT_MCE)); } /* load efer and update the corresponding hflags. XXX: do consistency diff --git a/target-i386/helper.c b/target-i386/helper.c index 86202e684..af4582000 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -28,6 +28,10 @@ #include "qemu-common.h" #include "kvm.h" #include "kvm_x86.h" +#ifndef CONFIG_USER_ONLY +#include "sysemu.h" +#include "monitor.h" +#endif #include "qemu-kvm.h" @@ -103,8 +107,6 @@ void cpu_reset(CPUX86State *env) env->dr[7] = DR7_FIXED_1; cpu_breakpoint_remove_all(env, BP_CPU); cpu_watchpoint_remove_all(env, BP_CPU); - - env->mcg_status = 0; } void cpu_x86_close(CPUX86State *env) @@ -1067,40 +1069,55 @@ static void breakpoint_handler(CPUState *env) prev_debug_excp_handler(env); } -/* This should come from sysemu.h - if we could include it here... */ -void qemu_system_reset_request(void); - -static void qemu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status, - uint64_t mcg_status, uint64_t addr, uint64_t misc) +static void +qemu_inject_x86_mce(Monitor *mon, CPUState *cenv, int bank, uint64_t status, + uint64_t mcg_status, uint64_t addr, uint64_t misc, + int flags) { uint64_t mcg_cap = cenv->mcg_cap; - uint64_t *banks = cenv->mce_banks; + uint64_t *banks = cenv->mce_banks + 4 * bank; /* - * if MSR_MCG_CTL is not all 1s, the uncorrected error - * reporting is disabled + * If there is an MCE exception being processed, ignore this SRAO MCE + * unless unconditional injection was requested. */ - if ((status & MCI_STATUS_UC) && (mcg_cap & MCG_CTL_P) && - cenv->mcg_ctl != ~(uint64_t)0) - return; - banks += 4 * bank; - /* - * if MSR_MCi_CTL is not all 1s, the uncorrected error - * reporting is disabled for the bank - */ - if ((status & MCI_STATUS_UC) && banks[0] != ~(uint64_t)0) + if (!(flags & MCE_INJECT_UNCOND_AO) && !(status & MCI_STATUS_AR) + && (cenv->mcg_status & MCG_STATUS_MCIP)) { return; + } if (status & MCI_STATUS_UC) { + /* + * if MSR_MCG_CTL is not all 1s, the uncorrected error + * reporting is disabled + */ + if ((mcg_cap & MCG_CTL_P) && cenv->mcg_ctl != ~(uint64_t)0) { + monitor_printf(mon, + "CPU %d: Uncorrected error reporting disabled\n", + cenv->cpu_index); + return; + } + + /* + * if MSR_MCi_CTL is not all 1s, the uncorrected error + * reporting is disabled for the bank + */ + if (banks[0] != ~(uint64_t)0) { + monitor_printf(mon, "CPU %d: Uncorrected error reporting disabled " + "for bank %d\n", cenv->cpu_index, bank); + return; + } + if ((cenv->mcg_status & MCG_STATUS_MCIP) || !(cenv->cr[4] & CR4_MCE_MASK)) { - fprintf(stderr, "injects mce exception while previous " - "one is in progress!\n"); + monitor_printf(mon, "CPU %d: Previous MCE still in progress, " + "raising triple fault\n", cenv->cpu_index); qemu_log_mask(CPU_LOG_RESET, "Triple fault\n"); qemu_system_reset_request(); return; } - if (banks[1] & MCI_STATUS_VAL) + if (banks[1] & MCI_STATUS_VAL) { status |= MCI_STATUS_OVER; + } banks[2] = addr; banks[3] = misc; cenv->mcg_status = mcg_status; @@ -1108,49 +1125,61 @@ static void qemu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status, cpu_interrupt(cenv, CPU_INTERRUPT_MCE); } else if (!(banks[1] & MCI_STATUS_VAL) || !(banks[1] & MCI_STATUS_UC)) { - if (banks[1] & MCI_STATUS_VAL) + if (banks[1] & MCI_STATUS_VAL) { status |= MCI_STATUS_OVER; + } banks[2] = addr; banks[3] = misc; banks[1] = status; - } else + } else { banks[1] |= MCI_STATUS_OVER; + } } -void cpu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status, - uint64_t mcg_status, uint64_t addr, uint64_t misc, - int broadcast) +void cpu_x86_inject_mce(Monitor *mon, CPUState *cenv, int bank, + uint64_t status, uint64_t mcg_status, uint64_t addr, + uint64_t misc, int flags) { unsigned bank_num = cenv->mcg_cap & 0xff; CPUState *env; int flag = 0; - if (bank >= bank_num || !(status & MCI_STATUS_VAL)) { + if (!cenv->mcg_cap) { + monitor_printf(mon, "MCE injection not supported\n"); return; } - - if (broadcast) { - if (!cpu_x86_support_mca_broadcast(cenv)) { - fprintf(stderr, "Current CPU does not support broadcast\n"); - return; - } + if (bank >= bank_num) { + monitor_printf(mon, "Invalid MCE bank number\n"); + return; + } + if (!(status & MCI_STATUS_VAL)) { + monitor_printf(mon, "Invalid MCE status code\n"); + return; + } + if ((flags & MCE_INJECT_BROADCAST) + && !cpu_x86_support_mca_broadcast(cenv)) { + monitor_printf(mon, "Guest CPU does not support MCA broadcast\n"); + return; } if (kvm_enabled()) { - if (broadcast) { + if (flags & MCE_INJECT_BROADCAST) { flag |= MCE_BROADCAST; } kvm_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc, flag); } else { - qemu_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc); - if (broadcast) { + qemu_inject_x86_mce(mon, cenv, bank, status, mcg_status, addr, misc, + flags); + if (flags & MCE_INJECT_BROADCAST) { for (env = first_cpu; env != NULL; env = env->next_cpu) { if (cenv == env) { continue; } - qemu_inject_x86_mce(env, 1, MCI_STATUS_VAL | MCI_STATUS_UC, - MCG_STATUS_MCIP | MCG_STATUS_RIPV, 0, 0); + qemu_inject_x86_mce(mon, env, 1, + MCI_STATUS_VAL | MCI_STATUS_UC, + MCG_STATUS_MCIP | MCG_STATUS_RIPV, 0, 0, + flags); } } } @@ -1159,15 +1188,16 @@ void cpu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status, static void mce_init(CPUX86State *cenv) { - unsigned int bank, bank_num; + unsigned int bank; - if (((cenv->cpuid_version >> 8)&0xf) >= 6 - && (cenv->cpuid_features&(CPUID_MCE|CPUID_MCA)) == (CPUID_MCE|CPUID_MCA)) { + if (((cenv->cpuid_version >> 8) & 0xf) >= 6 + && (cenv->cpuid_features & (CPUID_MCE | CPUID_MCA)) == + (CPUID_MCE | CPUID_MCA)) { cenv->mcg_cap = MCE_CAP_DEF | MCE_BANKS_DEF; cenv->mcg_ctl = ~(uint64_t)0; - bank_num = MCE_BANKS_DEF; - for (bank = 0; bank < bank_num; bank++) - cenv->mce_banks[bank*4] = ~(uint64_t)0; + for (bank = 0; bank < MCE_BANKS_DEF; bank++) { + cenv->mce_banks[bank * 4] = ~(uint64_t)0; + } } } diff --git a/target-i386/kvm.c b/target-i386/kvm.c index da757fa97..7fac2e5dd 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -174,7 +174,7 @@ static int get_para_features(CPUState *env) #endif return features; } -#endif +#endif /* CONFIG_KVM_PARA */ #ifdef KVM_CAP_MCE static int kvm_get_mce_cap_supported(KVMState *s, uint64_t *mce_cap, @@ -275,8 +275,174 @@ static void kvm_inject_x86_mce_on(CPUState *env, struct kvm_x86_mce *mce, on_vcpu(env, kvm_do_inject_x86_mce, &data); } -static void kvm_mce_broadcast_rest(CPUState *env); -#endif +static void kvm_mce_broadcast_rest(CPUState *env) +{ + struct kvm_x86_mce mce = { + .bank = 1, + .status = MCI_STATUS_VAL | MCI_STATUS_UC, + .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV, + .addr = 0, + .misc = 0, + }; + CPUState *cenv; + + /* Broadcast MCA signal for processor version 06H_EH and above */ + if (cpu_x86_support_mca_broadcast(env)) { + for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) { + if (cenv == env) { + continue; + } + kvm_inject_x86_mce_on(cenv, &mce, ABORT_ON_ERROR); + } + } +} + +static void kvm_mce_inj_srar_dataload(CPUState *env, target_phys_addr_t paddr) +{ + struct kvm_x86_mce mce = { + .bank = 9, + .status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN + | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S + | MCI_STATUS_AR | 0x134, + .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_EIPV, + .addr = paddr, + .misc = (MCM_ADDR_PHYS << 6) | 0xc, + }; + int r; + + r = kvm_set_mce(env, &mce); + if (r < 0) { + fprintf(stderr, "kvm_set_mce: %s\n", strerror(errno)); + abort(); + } + kvm_mce_broadcast_rest(env); +} + +static void kvm_mce_inj_srao_memscrub(CPUState *env, target_phys_addr_t paddr) +{ + struct kvm_x86_mce mce = { + .bank = 9, + .status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN + | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S + | 0xc0, + .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV, + .addr = paddr, + .misc = (MCM_ADDR_PHYS << 6) | 0xc, + }; + int r; + + r = kvm_set_mce(env, &mce); + if (r < 0) { + fprintf(stderr, "kvm_set_mce: %s\n", strerror(errno)); + abort(); + } + kvm_mce_broadcast_rest(env); +} + +static void kvm_mce_inj_srao_memscrub2(CPUState *env, target_phys_addr_t paddr) +{ + struct kvm_x86_mce mce = { + .bank = 9, + .status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN + | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S + | 0xc0, + .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV, + .addr = paddr, + .misc = (MCM_ADDR_PHYS << 6) | 0xc, + }; + + kvm_inject_x86_mce_on(env, &mce, ABORT_ON_ERROR); + kvm_mce_broadcast_rest(env); +} +#endif /* KVM_CAP_MCE */ + +static void hardware_memory_error(void) +{ + fprintf(stderr, "Hardware memory error!\n"); + exit(1); +} + +int kvm_arch_on_sigbus_vcpu(CPUState *env, int code, void *addr) +{ +#ifdef KVM_CAP_MCE + void *vaddr; + ram_addr_t ram_addr; + target_phys_addr_t paddr; + + if ((env->mcg_cap & MCG_SER_P) && addr + && (code == BUS_MCEERR_AR + || code == BUS_MCEERR_AO)) { + 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"); + /* Hope we are lucky for AO MCE */ + if (code == BUS_MCEERR_AO) { + return 0; + } else { + hardware_memory_error(); + } + } + + if (code == BUS_MCEERR_AR) { + /* Fake an Intel architectural Data Load SRAR UCR */ + kvm_mce_inj_srar_dataload(env, paddr); + } else { + /* + * If there is an MCE excpetion being processed, ignore + * this SRAO MCE + */ + if (!kvm_mce_in_progress(env)) { + /* Fake an Intel architectural Memory scrubbing UCR */ + kvm_mce_inj_srao_memscrub(env, paddr); + } + } + } else +#endif /* KVM_CAP_MCE */ + { + if (code == BUS_MCEERR_AO) { + return 0; + } else if (code == BUS_MCEERR_AR) { + hardware_memory_error(); + } else { + return 1; + } + } + return 0; +} + +int kvm_arch_on_sigbus(int code, void *addr) +{ +#ifdef KVM_CAP_MCE + if ((first_cpu->mcg_cap & MCG_SER_P) && addr && code == BUS_MCEERR_AO) { + void *vaddr; + ram_addr_t ram_addr; + target_phys_addr_t paddr; + + /* 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); + return 0; + } + kvm_mce_inj_srao_memscrub2(first_cpu, paddr); + } else +#endif /* KVM_CAP_MCE */ + { + if (code == BUS_MCEERR_AO) { + return 0; + } else if (code == BUS_MCEERR_AR) { + hardware_memory_error(); + } else { + return 1; + } + } + return 0; +} void kvm_inject_x86_mce(CPUState *cenv, int bank, uint64_t status, uint64_t mcg_status, uint64_t addr, uint64_t misc, @@ -296,11 +462,11 @@ void kvm_inject_x86_mce(CPUState *cenv, int bank, uint64_t status, } kvm_inject_x86_mce_on(cenv, &mce, flag); -#else +#else /* !KVM_CAP_MCE*/ if (flag & ABORT_ON_ERROR) { abort(); } -#endif +#endif /* !KVM_CAP_MCE*/ } static void cpu_update_state(void *opaque, int running, int reason) @@ -1818,174 +1984,4 @@ 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); -} - -#ifdef KVM_CAP_MCE -static void kvm_mce_broadcast_rest(CPUState *env) -{ - struct kvm_x86_mce mce = { - .bank = 1, - .status = MCI_STATUS_VAL | MCI_STATUS_UC, - .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV, - .addr = 0, - .misc = 0, - }; - CPUState *cenv; - - /* Broadcast MCA signal for processor version 06H_EH and above */ - if (cpu_x86_support_mca_broadcast(env)) { - for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) { - if (cenv == env) { - continue; - } - kvm_inject_x86_mce_on(cenv, &mce, ABORT_ON_ERROR); - } - } -} - -static void kvm_mce_inj_srar_dataload(CPUState *env, target_phys_addr_t paddr) -{ - struct kvm_x86_mce mce = { - .bank = 9, - .status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN - | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S - | MCI_STATUS_AR | 0x134, - .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_EIPV, - .addr = paddr, - .misc = (MCM_ADDR_PHYS << 6) | 0xc, - }; - int r; - - r = kvm_set_mce(env, &mce); - if (r < 0) { - fprintf(stderr, "kvm_set_mce: %s\n", strerror(errno)); - abort(); - } - kvm_mce_broadcast_rest(env); -} - -static void kvm_mce_inj_srao_memscrub(CPUState *env, target_phys_addr_t paddr) -{ - struct kvm_x86_mce mce = { - .bank = 9, - .status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN - | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S - | 0xc0, - .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV, - .addr = paddr, - .misc = (MCM_ADDR_PHYS << 6) | 0xc, - }; - int r; - - r = kvm_set_mce(env, &mce); - if (r < 0) { - fprintf(stderr, "kvm_set_mce: %s\n", strerror(errno)); - abort(); - } - kvm_mce_broadcast_rest(env); -} - -static void kvm_mce_inj_srao_memscrub2(CPUState *env, target_phys_addr_t paddr) -{ - struct kvm_x86_mce mce = { - .bank = 9, - .status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN - | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S - | 0xc0, - .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV, - .addr = paddr, - .misc = (MCM_ADDR_PHYS << 6) | 0xc, - }; - - kvm_inject_x86_mce_on(env, &mce, ABORT_ON_ERROR); - kvm_mce_broadcast_rest(env); -} - -#endif - -int kvm_arch_on_sigbus_vcpu(CPUState *env, int code, void *addr) -{ -#if defined(KVM_CAP_MCE) - void *vaddr; - ram_addr_t ram_addr; - target_phys_addr_t paddr; - - if ((env->mcg_cap & MCG_SER_P) && addr - && (code == BUS_MCEERR_AR - || code == BUS_MCEERR_AO)) { - 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"); - /* Hope we are lucky for AO MCE */ - if (code == BUS_MCEERR_AO) { - return 0; - } else { - hardware_memory_error(); - } - } - - if (code == BUS_MCEERR_AR) { - /* Fake an Intel architectural Data Load SRAR UCR */ - kvm_mce_inj_srar_dataload(env, paddr); - } else { - /* - * If there is an MCE excpetion being processed, ignore - * this SRAO MCE - */ - if (!kvm_mce_in_progress(env)) { - /* Fake an Intel architectural Memory scrubbing UCR */ - kvm_mce_inj_srao_memscrub(env, paddr); - } - } - } else -#endif - { - if (code == BUS_MCEERR_AO) { - return 0; - } else if (code == BUS_MCEERR_AR) { - hardware_memory_error(); - } else { - return 1; - } - } - return 0; -} - -int kvm_arch_on_sigbus(int code, void *addr) -{ -#if defined(KVM_CAP_MCE) - if ((first_cpu->mcg_cap & MCG_SER_P) && addr && code == BUS_MCEERR_AO) { - void *vaddr; - ram_addr_t ram_addr; - target_phys_addr_t paddr; - - /* 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); - return 0; - } - kvm_mce_inj_srao_memscrub2(first_cpu, paddr); - } else -#endif - { - if (code == BUS_MCEERR_AO) { - return 0; - } else if (code == BUS_MCEERR_AR) { - hardware_memory_error(); - } else { - return 1; - } - } - return 0; -} - #include "qemu-kvm-x86.c" diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index bd4012a4e..3924f4bed 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -222,7 +222,7 @@ int kvmppc_set_interrupt(CPUState *env, int irq, int level) #define PPC_INPUT_INT PPC6xx_INPUT_INT #endif -int kvm_arch_pre_run(CPUState *env, struct kvm_run *run) +void kvm_arch_pre_run(CPUState *env, struct kvm_run *run) { int r; unsigned irq; @@ -253,15 +253,15 @@ int kvm_arch_pre_run(CPUState *env, struct kvm_run *run) /* We don't know if there are more interrupts pending after this. However, * the guest will return to userspace in the course of handling this one * anyways, so we will get a chance to deliver the rest. */ - return 0; } void kvm_arch_post_run(CPUState *env, struct kvm_run *run) { } -void kvm_arch_process_irqchip_events(CPUState *env) +int kvm_arch_process_irqchip_events(CPUState *env) { + return 0; } static int kvmppc_handle_halt(CPUState *env) @@ -1474,6 +1474,7 @@ static void main_loop(void) } if (qemu_reset_requested()) { pause_all_vcpus(); + cpu_synchronize_all_states(); qemu_system_reset(); resume_all_vcpus(); } |