From nobody Tue Feb 10 15:01:03 2026 Delivered-To: importer@patchew.org Received-SPF: temperror (zoho.com: Error in retrieving data from DNS) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=temperror (zoho.com: Error in retrieving data from DNS) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1510834049937620.3978618071548; Thu, 16 Nov 2017 04:07:29 -0800 (PST) Received: from localhost ([::1]:40310 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eFIwp-0007tA-IY for importer@patchew.org; Thu, 16 Nov 2017 07:07:11 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33935) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eFIpj-0001u0-J9 for qemu-devel@nongnu.org; Thu, 16 Nov 2017 06:59:52 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eFIpg-0000Kx-F1 for qemu-devel@nongnu.org; Thu, 16 Nov 2017 06:59:51 -0500 Received: from mx1.redhat.com ([209.132.183.28]:48314) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eFIpg-0000KO-5U for qemu-devel@nongnu.org; Thu, 16 Nov 2017 06:59:48 -0500 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3C45749016; Thu, 16 Nov 2017 11:59:47 +0000 (UTC) Received: from donizetti.redhat.com (ovpn-117-65.ams2.redhat.com [10.36.117.65]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5A80C18BBC; Thu, 16 Nov 2017 11:59:44 +0000 (UTC) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 16 Nov 2017 12:59:23 +0100 Message-Id: <20171116115926.16627-9-pbonzini@redhat.com> In-Reply-To: <20171116115926.16627-1-pbonzini@redhat.com> References: <20171116115926.16627-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Thu, 16 Nov 2017 11:59:47 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 08/11] cpu-exec: avoid cpu_exec_nocache infinite loop with record/replay X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Maria Klimushenkova , Pavel Dovgalyuk Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_6 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Pavel Dovgalyuk 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 Signed-off-by: Pavel Dovgalyuk Message-Id: <20171114081818.27640.33165.stgit@pasha-VirtualBox> Signed-off-by: Paolo Bonzini --- 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(CPUStat= e *cpu) =20 static inline bool cpu_handle_exception(CPUState *cpu, int *ret) { - if (cpu->exception_index >=3D 0) { - if (cpu->exception_index >=3D EXCP_INTERRUPT) { - /* exit request from the cpu execution loop */ - *ret =3D cpu->exception_index; - if (*ret =3D=3D EXCP_DEBUG) { - cpu_handle_debug_exception(cpu); - } - cpu->exception_index =3D -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 =3D=3D 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 >=3D EXCP_INTERRUPT) { + /* exit request from the cpu execution loop */ + *ret =3D cpu->exception_index; + if (*ret =3D=3D EXCP_DEBUG) { + cpu_handle_debug_exception(cpu); + } + cpu->exception_index =3D -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 =3D CPU_GET_CLASS(cpu); + cc->do_interrupt(cpu); +#endif + *ret =3D cpu->exception_index; + cpu->exception_index =3D -1; + return true; +#else + if (replay_exception()) { CPUClass *cc =3D CPU_GET_CLASS(cpu); + qemu_mutex_lock_iothread(); cc->do_interrupt(cpu); -#endif - *ret =3D cpu->exception_index; + qemu_mutex_unlock_iothread(); cpu->exception_index =3D -1; + } else if (!replay_has_interrupt()) { + /* give a chance to iothread in replay mode */ + *ret =3D EXCP_INTERRUPT; return true; -#else - if (replay_exception()) { - CPUClass *cc =3D CPU_GET_CLASS(cpu); - qemu_mutex_lock_iothread(); - cc->do_interrupt(cpu); - qemu_mutex_unlock_iothread(); - cpu->exception_index =3D -1; - } else if (!replay_has_interrupt()) { - /* give a chance to iothread in replay mode */ - *ret =3D EXCP_INTERRUPT; - return true; - } -#endif } -#ifndef CONFIG_USER_ONLY - } else if (replay_has_exception() - && cpu->icount_decr.u16.low + cpu->icount_extra =3D=3D 0) { - /* try to cause an exception pending in the log */ - cpu_exec_nocache(cpu, 1, tb_find(cpu, NULL, 0, curr_cflags()), tru= e); - *ret =3D -1; - return true; #endif } =20 @@ -522,6 +525,19 @@ static inline bool cpu_handle_interrupt(CPUState *cpu, TranslationBlock **last_tb) { CPUClass *cc =3D 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 =3D 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(); + } =20 if (unlikely(atomic_read(&cpu->interrupt_request))) { int interrupt_request; @@ -620,17 +636,14 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, Tr= anslationBlock *tb, =20 *last_tb =3D NULL; insns_left =3D 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; } =20 --=20 2.14.3