[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v3 09/11] target-i386: defer VMEXIT to do_interrupt
From: |
Alex Bennée |
Subject: |
[Qemu-devel] [PATCH v3 09/11] target-i386: defer VMEXIT to do_interrupt |
Date: |
Tue, 7 Mar 2017 15:50:52 +0000 |
From: Paolo Bonzini <address@hidden>
Paths through the softmmu code during code generation now need to be audited
to check for double locking of tb_lock. In particular, VMEXIT can take tb_lock
through cpu_vmexit -> cpu_x86_update_cr4 -> tlb_flush.
To avoid this, split VMEXIT delivery in two parts, similar to what is done with
exceptions. cpu_vmexit only records the VMEXIT exit code and information, and
cc->do_interrupt can then deliver it when it is safe to take the lock.
Reported-by: Alexander Boettcher <address@hidden>
Suggested-by: Richard Henderson <address@hidden>
Tested-by: Alexander Boettcher <address@hidden>
Signed-off-by: Paolo Bonzini <address@hidden>
Signed-off-by: Alex Bennée <address@hidden>
---
target/i386/cpu.h | 2 ++
target/i386/seg_helper.c | 20 +++++++++++---------
target/i386/svm_helper.c | 22 +++++++++++++---------
3 files changed, 26 insertions(+), 18 deletions(-)
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index fb09aee7f8..406cb24301 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -697,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
@@ -1632,6 +1633,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
--
2.11.0
- [Qemu-devel] [PATCH v3 00/11] MTTCG fix-ups for 2.9, Alex Bennée, 2017/03/07
- [Qemu-devel] [PATCH v3 01/11] vl/cpus: be smarter with icount and MTTCG, Alex Bennée, 2017/03/07
- [Qemu-devel] [PATCH v3 02/11] target/i386/cpu.h: declare TCG_GUEST_DEFAULT_MO, Alex Bennée, 2017/03/07
- [Qemu-devel] [PATCH v3 03/11] cpus.c: add additional error_report when !TARGET_SUPPORT_MTTCG, Alex Bennée, 2017/03/07
- [Qemu-devel] [PATCH v3 04/11] sparc/sparc64: grab BQL before calling cpu_check_irqs, Alex Bennée, 2017/03/07
- [Qemu-devel] [PATCH v3 06/11] target/xtensa: hold BQL for interrupt processing, Alex Bennée, 2017/03/07
- [Qemu-devel] [PATCH v3 10/11] target/arm/helper: make it clear the EC field is also in hex, Alex Bennée, 2017/03/07
- [Qemu-devel] [PATCH v3 09/11] target-i386: defer VMEXIT to do_interrupt,
Alex Bennée <=
- [Qemu-devel] [PATCH v3 11/11] hw/intc/arm_gic: modernise the DPRINTF, Alex Bennée, 2017/03/07
- [Qemu-devel] [PATCH v3 05/11] s390x/misc_helper.c: wrap IO instructions in BQL, Alex Bennée, 2017/03/07
- [Qemu-devel] [PATCH v3 07/11] translate-all: exit cpu_restore_state early if translating, Alex Bennée, 2017/03/07
- [Qemu-devel] [PATCH v3 08/11] target/mips: hold BQL for timer interrupts, Alex Bennée, 2017/03/07
- Re: [Qemu-devel] [PATCH v3 00/11] MTTCG fix-ups for 2.9, Pranith Kumar, 2017/03/07