From patchwork Fri May 13 00:13:31 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 9087281 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 63019BF29F for ; Fri, 13 May 2016 00:36:38 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6EC8D20219 for ; Fri, 13 May 2016 00:36:37 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0CD0120211 for ; Fri, 13 May 2016 00:36:36 +0000 (UTC) Received: from localhost ([::1]:60495 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b115n-0003Pm-6T for patchwork-qemu-devel@patchwork.kernel.org; Thu, 12 May 2016 20:36:35 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38771) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b10li-0002jy-FY for qemu-devel@nongnu.org; Thu, 12 May 2016 20:15:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1b10ld-000367-HC for qemu-devel@nongnu.org; Thu, 12 May 2016 20:15:50 -0400 Received: from mail-qk0-x244.google.com ([2607:f8b0:400d:c09::244]:34833) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b10ld-00035z-9y for qemu-devel@nongnu.org; Thu, 12 May 2016 20:15:45 -0400 Received: by mail-qk0-x244.google.com with SMTP id n62so1261462qkc.2 for ; Thu, 12 May 2016 17:15:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=4Yme/IEHRfh687ClqT7woG7h1Wqs1wo5zHR5mF5CQIQ=; b=ex8I2a9O6N17yE9i3RxHAuipxe2PRu8kzjDwcOLTH8+iAb1tXyi2YA0r+bU1NkMPNX ojmBuM3Dn/XqRSsJPcCphcWVIJLPeDDI2Zd3IkF7AJQd9wwm98XXjouQkbwa97Jz8vxW 6ZBizXA1eqmRXqjdflhBtnQbi1vwsVrcwfo92TXZ2nnR6p1JunuE7zODv3Bmy+Tucsku eSTcaIcMeCxFeBzQLPNcweeJoyqXwor2gIQqmSgCM9lZfRb/z+YSne8b7nA8bTt8/evV Zz+mCKZ/k5pwtHWddWZceAXE02vwI4TrXTKnW+61Ja78hmzFC5O5gEUiOMvJgZMajIyr P9og== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=4Yme/IEHRfh687ClqT7woG7h1Wqs1wo5zHR5mF5CQIQ=; b=exaZfahxjiHqkiSSmvSEzT+ibp6nUS87cCyiAOHMvR6qIaxa6xTRtw98aKUEnHynwn 0ObTuoiyXzA6+fGjYPZc2knVxJQwF/f6GCCesuTiSkqzc2KTXG79c0R/hyLwTajdpLji Vih7WD8tNoZLG1yxJ/hnB8b/IznQQuzzcp8uqyZrSFm/szZ+t46uSgAvEkH7x5hCAFGP pkSkYsvTvG+zmpPEp8k6ouOB30GvfTc9uFyxEWFjXxu8Kt+imGdlwaAnN5eQ+PigLwyV 5VHW/f7QBQDueipXAP1TEFxEeaS98jFg1hD9v5s/xJxgk2KN4LxhI566HYbwNeeTVo01 RSRw== X-Gm-Message-State: AOPr4FUMRzgwpo1vUkzXTU4REbR05ttH9JNdndECsjjkqTHJW+xiwwIO5SxeAxa/AzGdiA== X-Received: by 10.55.221.205 with SMTP id u74mr13216257qku.86.1463098545013; Thu, 12 May 2016 17:15:45 -0700 (PDT) Received: from bigtime.com ([172.56.44.137]) by smtp.gmail.com with ESMTPSA id w16sm7171321qka.35.2016.05.12.17.15.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 12 May 2016 17:15:44 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 12 May 2016 14:13:31 -1000 Message-Id: <1463098420-29113-31-git-send-email-rth@twiddle.net> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1463098420-29113-1-git-send-email-rth@twiddle.net> References: <1463098420-29113-1-git-send-email-rth@twiddle.net> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2607:f8b0:400d:c09::244 Subject: [Qemu-devel] [PULL 30/39] tcg: Rework tb_invalidated_flag 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: peter.maydell@linaro.org, Sergey Fedorov , Sergey Fedorov Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Sergey Fedorov 'tb_invalidated_flag' was meant to catch two events: * some TB has been invalidated by tb_phys_invalidate(); * the whole translation buffer has been flushed by tb_flush(). Then it was checked: * in cpu_exec() to ensure that the last executed TB can be safely linked to directly call the next one; * in cpu_exec_nocache() to decide if the original TB should be provided for further possible invalidation along with the temporarily generated TB. It is always safe to patch an invalidated TB since it is not going to be used anyway. It is also safe to call tb_phys_invalidate() for an already invalidated TB. Thus, setting this flag in tb_phys_invalidate() is simply unnecessary. Moreover, it can prevent from pretty proper linking of TBs, if any arbitrary TB has been invalidated. So just don't touch it in tb_phys_invalidate(). If this flag is only used to catch whether tb_flush() has been called then rename it to 'tb_flushed'. Declare it as 'bool' and stick to using only 'true' and 'false' to set its value. Also, instead of setting it in tb_gen_code(), just after tb_flush() has been called, do it right inside of tb_flush(). In cpu_exec(), this flag is used to track if tb_flush() has been called and have made 'next_tb' (a reference to the last executed TB) invalid for linking it to directly call the next TB. tb_flush() can be called during the CPU execution loop from tb_gen_code(), during TB execution or by another thread while 'tb_lock' is released. Catch for translation buffer flush reliably by resetting this flag once before first TB lookup and each time we find it set before trying to add a direct jump. Don't touch in in tb_find_physical(). Each vCPU has its own execution loop in multithreaded mode and thus should have its own copy of the flag to be able to reset it with its own 'next_tb' and don't affect any other vCPU execution thread. So make this flag per-vCPU and move it to CPUState. In cpu_exec_nocache(), we only need to check if tb_flush() has been called from tb_gen_code() called by cpu_exec_nocache() itself. To do this reliably, preserve the old value of the flag, reset it before calling tb_gen_code(), check afterwards, and combine the saved value back to the flag. This patch is based on the patch "tcg: move tb_invalidated_flag to CPUState" from Paolo Bonzini . Signed-off-by: Sergey Fedorov Signed-off-by: Sergey Fedorov Signed-off-by: Richard Henderson --- cpu-exec.c | 21 +++++++++++---------- include/exec/exec-all.h | 2 -- include/qom/cpu.h | 2 ++ translate-all.c | 5 +---- 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/cpu-exec.c b/cpu-exec.c index 9407c66..f49a436 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -202,16 +202,20 @@ static void cpu_exec_nocache(CPUState *cpu, int max_cycles, TranslationBlock *orig_tb, bool ignore_icount) { TranslationBlock *tb; + bool old_tb_flushed; /* Should never happen. We only end up here when an existing TB is too long. */ if (max_cycles > CF_COUNT_MASK) max_cycles = CF_COUNT_MASK; + old_tb_flushed = cpu->tb_flushed; + cpu->tb_flushed = false; tb = tb_gen_code(cpu, orig_tb->pc, orig_tb->cs_base, orig_tb->flags, max_cycles | CF_NOCACHE | (ignore_icount ? CF_IGNORE_ICOUNT : 0)); - tb->orig_tb = tcg_ctx.tb_ctx.tb_invalidated_flag ? NULL : orig_tb; + tb->orig_tb = cpu->tb_flushed ? NULL : orig_tb; + cpu->tb_flushed |= old_tb_flushed; cpu->current_tb = tb; /* execute the generated code */ trace_exec_tb_nocache(tb, tb->pc); @@ -232,8 +236,6 @@ static TranslationBlock *tb_find_physical(CPUState *cpu, unsigned int h; tb_page_addr_t phys_pc, phys_page1; - tcg_ctx.tb_ctx.tb_invalidated_flag = 0; - /* find translated block using physical mappings */ phys_pc = get_page_addr_code(env, pc); phys_page1 = phys_pc & TARGET_PAGE_MASK; @@ -446,6 +448,7 @@ int cpu_exec(CPUState *cpu) } last_tb = NULL; /* forget the last executed TB after exception */ + cpu->tb_flushed = false; /* reset before first TB lookup */ for(;;) { interrupt_request = cpu->interrupt_request; if (unlikely(interrupt_request)) { @@ -510,14 +513,12 @@ int cpu_exec(CPUState *cpu) } tb_lock(); tb = tb_find_fast(cpu); - /* Note: we do it here to avoid a gcc bug on Mac OS X when - doing it in tb_find_slow */ - if (tcg_ctx.tb_ctx.tb_invalidated_flag) { - /* as some TB could have been invalidated because - of memory exceptions while generating the code, we - must recompute the hash index here */ + if (cpu->tb_flushed) { + /* Ensure that no TB jump will be modified as the + * translation buffer has been flushed. + */ last_tb = NULL; - tcg_ctx.tb_ctx.tb_invalidated_flag = 0; + cpu->tb_flushed = false; } /* See if we can patch the calling TB. */ if (last_tb && !qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) { diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 06da1bc..85528f9 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -304,8 +304,6 @@ struct TBContext { /* statistics */ int tb_flush_count; int tb_phys_invalidate_count; - - int tb_invalidated_flag; }; void tb_free(TranslationBlock *tb); diff --git a/include/qom/cpu.h b/include/qom/cpu.h index b7a10f7..c1ae24d 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -238,6 +238,7 @@ struct kvm_run; * @crash_occurred: Indicates the OS reported a crash (panic) for this CPU * @tcg_exit_req: Set to force TCG to stop executing linked TBs for this * CPU and return to its top level loop. + * @tb_flushed: Indicates the translation buffer has been flushed. * @singlestep_enabled: Flags for single-stepping. * @icount_extra: Instructions until next timer event. * @icount_decr: Number of cycles left, with interrupt flag in high bit. @@ -289,6 +290,7 @@ struct CPUState { bool stopped; bool crash_occurred; bool exit_request; + bool tb_flushed; uint32_t interrupt_request; int singlestep_enabled; int64_t icount_extra; diff --git a/translate-all.c b/translate-all.c index d5d2bbe..2d1957b 100644 --- a/translate-all.c +++ b/translate-all.c @@ -843,6 +843,7 @@ void tb_flush(CPUState *cpu) CPU_FOREACH(cpu) { memset(cpu->tb_jmp_cache, 0, sizeof(cpu->tb_jmp_cache)); + cpu->tb_flushed = true; } memset(tcg_ctx.tb_ctx.tb_phys_hash, 0, sizeof(tcg_ctx.tb_ctx.tb_phys_hash)); @@ -1011,8 +1012,6 @@ void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr) invalidate_page_bitmap(p); } - tcg_ctx.tb_ctx.tb_invalidated_flag = 1; - /* remove the TB from the hash list */ h = tb_jmp_cache_hash_func(tb->pc); CPU_FOREACH(cpu) { @@ -1178,8 +1177,6 @@ TranslationBlock *tb_gen_code(CPUState *cpu, /* cannot fail at this point */ tb = tb_alloc(pc); assert(tb != NULL); - /* Don't forget to invalidate previous TB info. */ - tcg_ctx.tb_ctx.tb_invalidated_flag = 1; } gen_code_buf = tcg_ctx.code_gen_ptr;