[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 08/11] cpu-exec: avoid cpu_exec_nocache infinite loop
From: |
Paolo Bonzini |
Subject: |
[Qemu-devel] [PULL 08/11] cpu-exec: avoid cpu_exec_nocache infinite loop with record/replay |
Date: |
Thu, 16 Nov 2017 12:59:23 +0100 |
From: Pavel Dovgalyuk <address@hidden>
This patch ensures that icount_decr.u32.high is clear before calling
cpu_exec_nocache when exception is pending. Because the exception is
caused by the first instruction in the block and it cannot be executed
without resetting the flag.
There are two parts in the fix. First, clear icount_decr.u32.high in
cpu_handle_interrupt (just before processing the "dependent" request,
stored in cpu->interrupt_request or cpu->exit_request) rather than
cpu_loop_exec_tb; this ensures that cpu_handle_exception is always
reached with zero icount_decr.u32.high unless another interrupt has
happened in the meanwhile.
Second, try to cause the exception at the beginning of
cpu_handle_exception, and exit immediately if the TB cannot
execute. With this change, interrupts are processed and
cpu_exec_nocache can make process.
Signed-off-by: Maria Klimushenkova <address@hidden>
Signed-off-by: Pavel Dovgalyuk <address@hidden>
Message-Id: <address@hidden>
Signed-off-by: Paolo Bonzini <address@hidden>
---
accel/tcg/cpu-exec.c | 95 +++++++++++++++++++++++++++++-----------------------
1 file changed, 54 insertions(+), 41 deletions(-)
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
index 0473055a08..f3de96f346 100644
--- a/accel/tcg/cpu-exec.c
+++ b/accel/tcg/cpu-exec.c
@@ -470,48 +470,51 @@ static inline void cpu_handle_debug_exception(CPUState
*cpu)
static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
{
- if (cpu->exception_index >= 0) {
- if (cpu->exception_index >= EXCP_INTERRUPT) {
- /* exit request from the cpu execution loop */
- *ret = cpu->exception_index;
- if (*ret == EXCP_DEBUG) {
- cpu_handle_debug_exception(cpu);
- }
- cpu->exception_index = -1;
- return true;
- } else {
+ if (cpu->exception_index < 0) {
+#ifndef CONFIG_USER_ONLY
+ if (replay_has_exception()
+ && cpu->icount_decr.u16.low + cpu->icount_extra == 0) {
+ /* try to cause an exception pending in the log */
+ cpu_exec_nocache(cpu, 1, tb_find(cpu, NULL, 0, curr_cflags()),
true);
+ }
+#endif
+ if (cpu->exception_index < 0) {
+ return false;
+ }
+ }
+
+ if (cpu->exception_index >= EXCP_INTERRUPT) {
+ /* exit request from the cpu execution loop */
+ *ret = cpu->exception_index;
+ if (*ret == EXCP_DEBUG) {
+ cpu_handle_debug_exception(cpu);
+ }
+ cpu->exception_index = -1;
+ return true;
+ } else {
#if defined(CONFIG_USER_ONLY)
- /* if user mode only, we simulate a fake exception
- which will be handled outside the cpu execution
- loop */
+ /* if user mode only, we simulate a fake exception
+ which will be handled outside the cpu execution
+ loop */
#if defined(TARGET_I386)
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+ cc->do_interrupt(cpu);
+#endif
+ *ret = cpu->exception_index;
+ cpu->exception_index = -1;
+ return true;
+#else
+ if (replay_exception()) {
CPUClass *cc = CPU_GET_CLASS(cpu);
+ qemu_mutex_lock_iothread();
cc->do_interrupt(cpu);
-#endif
- *ret = cpu->exception_index;
+ qemu_mutex_unlock_iothread();
cpu->exception_index = -1;
+ } else if (!replay_has_interrupt()) {
+ /* give a chance to iothread in replay mode */
+ *ret = EXCP_INTERRUPT;
return true;
-#else
- if (replay_exception()) {
- CPUClass *cc = CPU_GET_CLASS(cpu);
- qemu_mutex_lock_iothread();
- cc->do_interrupt(cpu);
- qemu_mutex_unlock_iothread();
- cpu->exception_index = -1;
- } else if (!replay_has_interrupt()) {
- /* give a chance to iothread in replay mode */
- *ret = EXCP_INTERRUPT;
- return true;
- }
-#endif
}
-#ifndef CONFIG_USER_ONLY
- } else if (replay_has_exception()
- && cpu->icount_decr.u16.low + cpu->icount_extra == 0) {
- /* try to cause an exception pending in the log */
- cpu_exec_nocache(cpu, 1, tb_find(cpu, NULL, 0, curr_cflags()), true);
- *ret = -1;
- return true;
#endif
}
@@ -522,6 +525,19 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
TranslationBlock **last_tb)
{
CPUClass *cc = CPU_GET_CLASS(cpu);
+ int32_t insns_left;
+
+ /* Clear the interrupt flag now since we're processing
+ * cpu->interrupt_request and cpu->exit_request.
+ */
+ insns_left = atomic_read(&cpu->icount_decr.u32);
+ atomic_set(&cpu->icount_decr.u16.high, 0);
+ if (unlikely(insns_left < 0)) {
+ /* Ensure the zeroing of icount_decr comes before the next read
+ * of cpu->exit_request or cpu->interrupt_request.
+ */
+ smp_mb();
+ }
if (unlikely(atomic_read(&cpu->interrupt_request))) {
int interrupt_request;
@@ -620,17 +636,14 @@ static inline void cpu_loop_exec_tb(CPUState *cpu,
TranslationBlock *tb,
*last_tb = NULL;
insns_left = atomic_read(&cpu->icount_decr.u32);
- atomic_set(&cpu->icount_decr.u16.high, 0);
if (insns_left < 0) {
/* Something asked us to stop executing chained TBs; just
* continue round the main loop. Whatever requested the exit
* will also have set something else (eg exit_request or
- * interrupt_request) which we will handle next time around
- * the loop. But we need to ensure the zeroing of icount_decr
- * comes before the next read of cpu->exit_request
- * or cpu->interrupt_request.
+ * interrupt_request) which will be handled by
+ * cpu_handle_interrupt. cpu_handle_interrupt will also
+ * clear cpu->icount_decr.u16.high.
*/
- smp_mb();
return;
}
--
2.14.3
- [Qemu-devel] [PULL 00/11] Miscellaneous patches for QEMU 2.11-rc2, Paolo Bonzini, 2017/11/16
- [Qemu-devel] [PULL 01/11] Enable 8-byte wide MMIO for 16550 serial devices, Paolo Bonzini, 2017/11/16
- [Qemu-devel] [PULL 03/11] Makefile: simpler/faster "make help", Paolo Bonzini, 2017/11/16
- [Qemu-devel] [PULL 04/11] thread-posix: fix qemu_rec_mutex_trylock macro, Paolo Bonzini, 2017/11/16
- [Qemu-devel] [PULL 02/11] ioapic/tracing: Remove last DPRINTFs, Paolo Bonzini, 2017/11/16
- [Qemu-devel] [PULL 06/11] vhost-user-scsi: add missing virtqueue_size param, Paolo Bonzini, 2017/11/16
- [Qemu-devel] [PULL 05/11] target-i386: adds PV_TLB_FLUSH CPUID feature bit, Paolo Bonzini, 2017/11/16
- [Qemu-devel] [PULL 07/11] cpu-exec: don't overwrite exception_index, Paolo Bonzini, 2017/11/16
- [Qemu-devel] [PULL 09/11] util/stats64: Fix min/max comparisons, Paolo Bonzini, 2017/11/16
- [Qemu-devel] [PULL 08/11] cpu-exec: avoid cpu_exec_nocache infinite loop with record/replay,
Paolo Bonzini <=
- [Qemu-devel] [PULL 10/11] exec: Do not resolve subpage in mru_section, Paolo Bonzini, 2017/11/16
- [Qemu-devel] [PULL 11/11] fix scripts/update-linux-headers.sh here document, Paolo Bonzini, 2017/11/16
- Re: [Qemu-devel] [PULL 00/11] Miscellaneous patches for QEMU 2.11-rc2, Peter Maydell, 2017/11/16