diff options
Diffstat (limited to 'target')
-rw-r--r-- | target/arm/helper.c | 2 | ||||
-rw-r--r-- | target/i386/cpu.h | 5 | ||||
-rw-r--r-- | target/i386/seg_helper.c | 20 | ||||
-rw-r--r-- | target/i386/svm_helper.c | 22 | ||||
-rw-r--r-- | target/mips/op_helper.c | 21 | ||||
-rw-r--r-- | target/s390x/misc_helper.c | 21 | ||||
-rw-r--r-- | target/sparc/int64_helper.c | 3 | ||||
-rw-r--r-- | target/sparc/win_helper.c | 13 | ||||
-rw-r--r-- | target/xtensa/helper.c | 1 | ||||
-rw-r--r-- | target/xtensa/op_helper.c | 7 |
10 files changed, 93 insertions, 22 deletions
diff --git a/target/arm/helper.c b/target/arm/helper.c index 3f4211b572..76b608f0ba 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -6857,7 +6857,7 @@ void arm_cpu_do_interrupt(CPUState *cs) new_el); if (qemu_loglevel_mask(CPU_LOG_INT) && !excp_is_internal(cs->exception_index)) { - qemu_log_mask(CPU_LOG_INT, "...with ESR %x/0x%" PRIx32 "\n", + qemu_log_mask(CPU_LOG_INT, "...with ESR 0x%x/0x%" PRIx32 "\n", env->exception.syndrome >> ARM_EL_EC_SHIFT, env->exception.syndrome); } diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 385dcc8fea..07401ad9fe 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -30,6 +30,9 @@ #define TARGET_LONG_BITS 32 #endif +/* The x86 has a strong memory model with some store-after-load re-ordering */ +#define TCG_GUEST_DEFAULT_MO (TCG_MO_ALL & ~TCG_MO_ST_LD) + /* Maximum instruction code size */ #define TARGET_MAX_INSN_SIZE 16 @@ -694,6 +697,7 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; #define EXCP_SYSCALL 0x100 /* only happens in user only emulation for syscall instruction */ +#define EXCP_VMEXIT 0x100 /* i386-specific interrupt pending bits. */ #define CPU_INTERRUPT_POLL CPU_INTERRUPT_TGT_EXT_1 @@ -1630,6 +1634,7 @@ void cpu_svm_check_intercept_param(CPUX86State *env1, uint32_t type, uint64_t param, uintptr_t retaddr); void cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, uint64_t exit_info_1, uintptr_t retaddr); +void do_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1); /* seg_helper.c */ void do_interrupt_x86_hardirq(CPUX86State *env, int intno, int is_hw); diff --git a/target/i386/seg_helper.c b/target/i386/seg_helper.c index 5c845dc25c..0374031ea2 100644 --- a/target/i386/seg_helper.c +++ b/target/i386/seg_helper.c @@ -1297,15 +1297,17 @@ void x86_cpu_do_interrupt(CPUState *cs) /* successfully delivered */ env->old_exception = -1; #else - /* simulate a real cpu exception. On i386, it can - trigger new exceptions, but we do not handle - double or triple faults yet. */ - do_interrupt_all(cpu, cs->exception_index, - env->exception_is_int, - env->error_code, - env->exception_next_eip, 0); - /* successfully delivered */ - env->old_exception = -1; + if (cs->exception_index >= EXCP_VMEXIT) { + assert(env->old_exception == -1); + do_vmexit(env, cs->exception_index - EXCP_VMEXIT, env->error_code); + } else { + do_interrupt_all(cpu, cs->exception_index, + env->exception_is_int, + env->error_code, + env->exception_next_eip, 0); + /* successfully delivered */ + env->old_exception = -1; + } #endif } diff --git a/target/i386/svm_helper.c b/target/i386/svm_helper.c index 78d8df4af6..59e8b5091c 100644 --- a/target/i386/svm_helper.c +++ b/target/i386/svm_helper.c @@ -580,12 +580,10 @@ void helper_svm_check_io(CPUX86State *env, uint32_t port, uint32_t param, } } -/* Note: currently only 32 bits of exit_code are used */ void cpu_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1, uintptr_t retaddr) { CPUState *cs = CPU(x86_env_get_cpu(env)); - uint32_t int_ctl; if (retaddr) { cpu_restore_state(cs, retaddr); @@ -598,6 +596,19 @@ void cpu_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1, control.exit_info_2)), env->eip); + cs->exception_index = EXCP_VMEXIT + exit_code; + env->error_code = exit_info_1; + + /* remove any pending exception */ + env->old_exception = -1; + cpu_loop_exit(cs); +} + +void do_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1) +{ + CPUState *cs = CPU(x86_env_get_cpu(env)); + uint32_t int_ctl; + if (env->hflags & HF_INHIBIT_IRQ_MASK) { x86_stl_phys(cs, env->vm_vmcb + offsetof(struct vmcb, control.int_state), @@ -759,13 +770,6 @@ void cpu_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1, /* If the host's rIP reloaded by #VMEXIT is outside the limit of the host's code segment or non-canonical (in the case of long mode), a #GP fault is delivered inside the host. */ - - /* remove any pending exception */ - cs->exception_index = -1; - env->error_code = 0; - env->old_exception = -1; - - cpu_loop_exit(cs); } #endif diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c index b683fcb025..e5f3ea4042 100644 --- a/target/mips/op_helper.c +++ b/target/mips/op_helper.c @@ -17,6 +17,7 @@ * License along with this library; if not, see <http://www.gnu.org/licenses/>. */ #include "qemu/osdep.h" +#include "qemu/main-loop.h" #include "cpu.h" #include "qemu/host-utils.h" #include "exec/helper-proto.h" @@ -827,7 +828,11 @@ target_ulong helper_mftc0_tcschefback(CPUMIPSState *env) target_ulong helper_mfc0_count(CPUMIPSState *env) { - return (int32_t)cpu_mips_get_count(env); + int32_t count; + qemu_mutex_lock_iothread(); + count = (int32_t) cpu_mips_get_count(env); + qemu_mutex_unlock_iothread(); + return count; } target_ulong helper_mftc0_entryhi(CPUMIPSState *env) @@ -1375,7 +1380,9 @@ void helper_mtc0_hwrena(CPUMIPSState *env, target_ulong arg1) void helper_mtc0_count(CPUMIPSState *env, target_ulong arg1) { + qemu_mutex_lock_iothread(); cpu_mips_store_count(env, arg1); + qemu_mutex_unlock_iothread(); } void helper_mtc0_entryhi(CPUMIPSState *env, target_ulong arg1) @@ -1424,7 +1431,9 @@ void helper_mttc0_entryhi(CPUMIPSState *env, target_ulong arg1) void helper_mtc0_compare(CPUMIPSState *env, target_ulong arg1) { + qemu_mutex_lock_iothread(); cpu_mips_store_compare(env, arg1); + qemu_mutex_unlock_iothread(); } void helper_mtc0_status(CPUMIPSState *env, target_ulong arg1) @@ -1475,7 +1484,9 @@ void helper_mtc0_srsctl(CPUMIPSState *env, target_ulong arg1) void helper_mtc0_cause(CPUMIPSState *env, target_ulong arg1) { + qemu_mutex_lock_iothread(); cpu_mips_store_cause(env, arg1); + qemu_mutex_unlock_iothread(); } void helper_mttc0_cause(CPUMIPSState *env, target_ulong arg1) @@ -2296,12 +2307,16 @@ target_ulong helper_rdhwr_synci_step(CPUMIPSState *env) target_ulong helper_rdhwr_cc(CPUMIPSState *env) { + int32_t count; check_hwrena(env, 2, GETPC()); #ifdef CONFIG_USER_ONLY - return env->CP0_Count; + count = env->CP0_Count; #else - return (int32_t)cpu_mips_get_count(env); + qemu_mutex_lock_iothread(); + count = (int32_t)cpu_mips_get_count(env); + qemu_mutex_unlock_iothread(); #endif + return count; } target_ulong helper_rdhwr_ccres(CPUMIPSState *env) diff --git a/target/s390x/misc_helper.c b/target/s390x/misc_helper.c index 3cb942e8bb..93b0e61366 100644 --- a/target/s390x/misc_helper.c +++ b/target/s390x/misc_helper.c @@ -19,6 +19,7 @@ */ #include "qemu/osdep.h" +#include "qemu/main-loop.h" #include "cpu.h" #include "exec/memory.h" #include "qemu/host-utils.h" @@ -551,61 +552,81 @@ uint32_t HELPER(sigp)(CPUS390XState *env, uint64_t order_code, uint32_t r1, void HELPER(xsch)(CPUS390XState *env, uint64_t r1) { S390CPU *cpu = s390_env_get_cpu(env); + qemu_mutex_lock_iothread(); ioinst_handle_xsch(cpu, r1); + qemu_mutex_unlock_iothread(); } void HELPER(csch)(CPUS390XState *env, uint64_t r1) { S390CPU *cpu = s390_env_get_cpu(env); + qemu_mutex_lock_iothread(); ioinst_handle_csch(cpu, r1); + qemu_mutex_unlock_iothread(); } void HELPER(hsch)(CPUS390XState *env, uint64_t r1) { S390CPU *cpu = s390_env_get_cpu(env); + qemu_mutex_lock_iothread(); ioinst_handle_hsch(cpu, r1); + qemu_mutex_unlock_iothread(); } void HELPER(msch)(CPUS390XState *env, uint64_t r1, uint64_t inst) { S390CPU *cpu = s390_env_get_cpu(env); + qemu_mutex_lock_iothread(); ioinst_handle_msch(cpu, r1, inst >> 16); + qemu_mutex_unlock_iothread(); } void HELPER(rchp)(CPUS390XState *env, uint64_t r1) { S390CPU *cpu = s390_env_get_cpu(env); + qemu_mutex_lock_iothread(); ioinst_handle_rchp(cpu, r1); + qemu_mutex_unlock_iothread(); } void HELPER(rsch)(CPUS390XState *env, uint64_t r1) { S390CPU *cpu = s390_env_get_cpu(env); + qemu_mutex_lock_iothread(); ioinst_handle_rsch(cpu, r1); + qemu_mutex_unlock_iothread(); } void HELPER(ssch)(CPUS390XState *env, uint64_t r1, uint64_t inst) { S390CPU *cpu = s390_env_get_cpu(env); + qemu_mutex_lock_iothread(); ioinst_handle_ssch(cpu, r1, inst >> 16); + qemu_mutex_unlock_iothread(); } void HELPER(stsch)(CPUS390XState *env, uint64_t r1, uint64_t inst) { S390CPU *cpu = s390_env_get_cpu(env); + qemu_mutex_lock_iothread(); ioinst_handle_stsch(cpu, r1, inst >> 16); + qemu_mutex_unlock_iothread(); } void HELPER(tsch)(CPUS390XState *env, uint64_t r1, uint64_t inst) { S390CPU *cpu = s390_env_get_cpu(env); + qemu_mutex_lock_iothread(); ioinst_handle_tsch(cpu, r1, inst >> 16); + qemu_mutex_unlock_iothread(); } void HELPER(chsc)(CPUS390XState *env, uint64_t inst) { S390CPU *cpu = s390_env_get_cpu(env); + qemu_mutex_lock_iothread(); ioinst_handle_chsc(cpu, inst >> 16); + qemu_mutex_unlock_iothread(); } #endif diff --git a/target/sparc/int64_helper.c b/target/sparc/int64_helper.c index 605747c93c..f942973c22 100644 --- a/target/sparc/int64_helper.c +++ b/target/sparc/int64_helper.c @@ -18,6 +18,7 @@ */ #include "qemu/osdep.h" +#include "qemu/main-loop.h" #include "cpu.h" #include "exec/helper-proto.h" #include "exec/log.h" @@ -208,7 +209,9 @@ static bool do_modify_softint(CPUSPARCState *env, uint32_t value) env->softint = value; #if !defined(CONFIG_USER_ONLY) if (cpu_interrupts_enabled(env)) { + qemu_mutex_lock_iothread(); cpu_check_irqs(env); + qemu_mutex_unlock_iothread(); } #endif return true; diff --git a/target/sparc/win_helper.c b/target/sparc/win_helper.c index 71b3dd37e8..154279ecda 100644 --- a/target/sparc/win_helper.c +++ b/target/sparc/win_helper.c @@ -18,6 +18,7 @@ */ #include "qemu/osdep.h" +#include "qemu/main-loop.h" #include "cpu.h" #include "exec/exec-all.h" #include "exec/helper-proto.h" @@ -82,6 +83,7 @@ void cpu_put_psr_raw(CPUSPARCState *env, target_ulong val) #endif } +/* Called with BQL held */ void cpu_put_psr(CPUSPARCState *env, target_ulong val) { cpu_put_psr_raw(env, val); @@ -153,7 +155,10 @@ void helper_wrpsr(CPUSPARCState *env, target_ulong new_psr) if ((new_psr & PSR_CWP) >= env->nwindows) { cpu_raise_exception_ra(env, TT_ILL_INSN, GETPC()); } else { + /* cpu_put_psr may trigger interrupts, hence BQL */ + qemu_mutex_lock_iothread(); cpu_put_psr(env, new_psr); + qemu_mutex_unlock_iothread(); } } @@ -368,7 +373,9 @@ void helper_wrpstate(CPUSPARCState *env, target_ulong new_state) #if !defined(CONFIG_USER_ONLY) if (cpu_interrupts_enabled(env)) { + qemu_mutex_lock_iothread(); cpu_check_irqs(env); + qemu_mutex_unlock_iothread(); } #endif } @@ -381,7 +388,9 @@ void helper_wrpil(CPUSPARCState *env, target_ulong new_pil) env->psrpil = new_pil; if (cpu_interrupts_enabled(env)) { + qemu_mutex_lock_iothread(); cpu_check_irqs(env); + qemu_mutex_unlock_iothread(); } #endif } @@ -408,7 +417,9 @@ void helper_done(CPUSPARCState *env) #if !defined(CONFIG_USER_ONLY) if (cpu_interrupts_enabled(env)) { + qemu_mutex_lock_iothread(); cpu_check_irqs(env); + qemu_mutex_unlock_iothread(); } #endif } @@ -435,7 +446,9 @@ void helper_retry(CPUSPARCState *env) #if !defined(CONFIG_USER_ONLY) if (cpu_interrupts_enabled(env)) { + qemu_mutex_lock_iothread(); cpu_check_irqs(env); + qemu_mutex_unlock_iothread(); } #endif } diff --git a/target/xtensa/helper.c b/target/xtensa/helper.c index c67d715c4b..bcd0b7738d 100644 --- a/target/xtensa/helper.c +++ b/target/xtensa/helper.c @@ -217,6 +217,7 @@ static void handle_interrupt(CPUXtensaState *env) } } +/* Called from cpu_handle_interrupt with BQL held */ void xtensa_cpu_do_interrupt(CPUState *cs) { XtensaCPU *cpu = XTENSA_CPU(cs); diff --git a/target/xtensa/op_helper.c b/target/xtensa/op_helper.c index af2723445d..519fbeddd6 100644 --- a/target/xtensa/op_helper.c +++ b/target/xtensa/op_helper.c @@ -26,6 +26,7 @@ */ #include "qemu/osdep.h" +#include "qemu/main-loop.h" #include "cpu.h" #include "exec/helper-proto.h" #include "qemu/host-utils.h" @@ -381,7 +382,11 @@ void HELPER(waiti)(CPUXtensaState *env, uint32_t pc, uint32_t intlevel) env->pc = pc; env->sregs[PS] = (env->sregs[PS] & ~PS_INTLEVEL) | (intlevel << PS_INTLEVEL_SHIFT); + + qemu_mutex_lock_iothread(); check_interrupts(env); + qemu_mutex_unlock_iothread(); + if (env->pending_irq_level) { cpu_loop_exit(CPU(xtensa_env_get_cpu(env))); return; @@ -426,7 +431,9 @@ void HELPER(update_ccompare)(CPUXtensaState *env, uint32_t i) void HELPER(check_interrupts)(CPUXtensaState *env) { + qemu_mutex_lock_iothread(); check_interrupts(env); + qemu_mutex_unlock_iothread(); } void HELPER(itlb_hit_test)(CPUXtensaState *env, uint32_t vaddr) |