From nobody Thu Nov 6 10:38:32 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) 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=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1540489247320658.7862847850851; Thu, 25 Oct 2018 10:40:47 -0700 (PDT) Received: from localhost ([::1]:56106 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gFjci-0007y3-42 for importer@patchew.org; Thu, 25 Oct 2018 13:40:44 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:40310) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gFjKg-0006hm-24 for qemu-devel@nongnu.org; Thu, 25 Oct 2018 13:22:08 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gFjKb-0000MD-R4 for qemu-devel@nongnu.org; Thu, 25 Oct 2018 13:22:03 -0400 Received: from out3-smtp.messagingengine.com ([66.111.4.27]:41217) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gFjKb-00008c-Fn for qemu-devel@nongnu.org; Thu, 25 Oct 2018 13:22:01 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id 848262222C; Thu, 25 Oct 2018 13:21:15 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute4.internal (MEProxy); Thu, 25 Oct 2018 13:21:16 -0400 Received: from localhost (flamenco.cs.columbia.edu [128.59.20.216]) by mail.messagingengine.com (Postfix) with ESMTPA id 64F4CE4A46; Thu, 25 Oct 2018 13:21:15 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=braap.org; h= from:to:cc:subject:date:message-id:in-reply-to:references; s= mesmtp; bh=8J8VIfOqFAQeLyhXTZq7723F+xZbh1AX6+hbsJEyN8I=; b=f8ToN NnaCN4yi62jmTmrDd5xBopoxDOk8YgDk7vNkBWWd3CsENNYDZKB/PVFXzuc+FJE8 Nu4SPPi9DEw4fm0AnreRAQU0rG+0jYCc0VFG7Zy+Slk+o3cLDZrWTt0OfJMI39O4 +u9GB0JcbJzxzTH6zkjKOIT5OJKHMnD4/koHj0= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:date:from:in-reply-to:message-id :references:subject:to:x-me-proxy:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm1; bh=8J8VIfOqFAQeLyhXTZq7723F+xZbh 1AX6+hbsJEyN8I=; b=DXA6+XV/+5OeWJnxV6zSijSuqdNjcT+YlABSNEOLQ46mj xiTlKgTYx94qgfmAp1DpVwkS2Kxd9uj+utQ+UR62FBYCHaEBpjvXY2mf5E2oZcUc MMbwz2w9d/QmeHGGJ8Cv/DqjIgX8rKESVAPAsvikqLRdRZqo4fAfNr4PBXE83TN3 eKdcMdloxyosimY49NADY9qsskHqr0tVFMVqRj067CcIbzYh5R55rY2ewY+9Oeay 1IJBV0aQ9PHyoB5MkOqstfcVjqNeS6G8IyfgRQbWUNlRiEHoJbdRKNlYj5wUZHfE Z4wL9/594YmjMK5CXIH2cPiL06Lp2crU4a7Z4kO2g== X-ME-Sender: X-ME-Proxy: From: "Emilio G. Cota" To: qemu-devel@nongnu.org Date: Thu, 25 Oct 2018 13:20:47 -0400 Message-Id: <20181025172057.20414-39-cota@braap.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181025172057.20414-1-cota@braap.org> References: <20181025172057.20414-1-cota@braap.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 66.111.4.27 Subject: [Qemu-devel] [RFC 38/48] translator: implement 2-pass translation 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 , =?UTF-8?q?Alex=20Benn=C3=A9e?= , =?UTF-8?q?Llu=C3=ADs=20Vilanova?= , Pavel Dovgalyuk , Stefan Hajnoczi Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The second pass only occurs when a plugin has subscribed to TB translation events. Signed-off-by: Emilio G. Cota --- tcg/tcg.h | 8 ++++ accel/tcg/translator.c | 91 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 97 insertions(+), 2 deletions(-) diff --git a/tcg/tcg.h b/tcg/tcg.h index d5afe25c97..479b57d65f 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -720,6 +720,14 @@ struct TCGContext { =20 TCGLabel *exitreq_label; =20 + /* + * We keep one plugin_tb struct per TCGContext. Note that on every TB + * translation we clear but do not free its contents; this way we + * avoid a lot of malloc/free churn, since after a few TB's it's + * unlikely that we'll need to allocate either more instructions or mo= re + * space for instructions (for variable-instruction-length ISAs). + */ + struct qemu_plugin_tb plugin_tb; struct qemu_plugin_dyn_cb_arr *plugin_mem_cb; struct qemu_plugin_insn *plugin_insn; =20 diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c index 8591e4b72a..88f9ac62a3 100644 --- a/accel/tcg/translator.c +++ b/accel/tcg/translator.c @@ -17,6 +17,7 @@ #include "exec/gen-icount.h" #include "exec/log.h" #include "exec/translator.h" +#include "exec/plugin-gen.h" =20 /* Pairs with tcg_clear_temp_count. To be called by #TranslatorOps.{translate_insn,tb_stop} if @@ -35,6 +36,21 @@ void translator_loop(const TranslatorOps *ops, DisasCont= extBase *db, CPUState *cpu, TranslationBlock *tb) { int bp_insn =3D 0; + int insn_idx =3D 0; + bool tb_trans_cb =3D false; + bool first_pass =3D true; /* second pass otherwise */ + void *saved_dc =3D g_alloca(ops->ctx_size); + /* tb->plugin_mask is a u32 */ + unsigned long plugin_mask =3D tb->plugin_mask; + struct qemu_plugin_tb *plugin_tb =3D &tcg_ctx->plugin_tb; + + if (test_bit(QEMU_PLUGIN_EV_VCPU_TB_TRANS, &plugin_mask)) { + tb_trans_cb =3D true; + plugin_tb->cbs.n =3D 0; + plugin_tb->n =3D 0; + plugin_tb->vaddr =3D tb->pc; + tcg_ctx->plugin_mem_cb =3D NULL; + } =20 /* Initialize DisasContext */ db->tb =3D tb; @@ -56,6 +72,21 @@ void translator_loop(const TranslatorOps *ops, DisasCont= extBase *db, db->max_insns =3D 1; } =20 + translate: + tcg_func_start(tcg_ctx); + + /* See the "2-pass translation" comment below */ + if (tb_trans_cb) { + void *dc =3D db; + + dc -=3D ops->ctx_base_offset; + if (first_pass) { + memcpy(saved_dc, dc, ops->ctx_size); + } else { + memcpy(dc, saved_dc, ops->ctx_size); + } + } + ops->init_disas_context(db, cpu); tcg_debug_assert(db->is_jmp =3D=3D DISAS_NEXT); /* no early exit */ =20 @@ -67,7 +98,53 @@ void translator_loop(const TranslatorOps *ops, DisasCont= extBase *db, ops->tb_start(db, cpu); tcg_debug_assert(db->is_jmp =3D=3D DISAS_NEXT); /* no early exit */ =20 + if (!first_pass && plugin_tb->cbs.n) { + qemu_plugin_gen_vcpu_udata_callbacks(&plugin_tb->cbs); + } + while (true) { + struct qemu_plugin_insn *plugin_insn =3D NULL; + bool mem_helpers =3D false; + + /* + * 2-pass translation. + * + * In the first pass we fully determine the TB. + * If no plugins have subscribed to TB translation events, we're d= one. + * + * If they have, we first share with plugins a TB descriptor so + * that plugins can subscribe to instruction-related events, e.g. + * memory accesses of particular instructions, or TB execution. + * With this info, which is kept in plugin_tb, we then do a second= pass, + * inserting the appropriate instrumentation into the translated T= B. + * + * Since all translation state is kept in DisasContext, we copy it + * before the first pass, and restore it before the second. + */ + if (tb_trans_cb) { + if (first_pass) { + plugin_insn =3D qemu_plugin_tb_insn_get(plugin_tb); + tcg_ctx->plugin_insn =3D plugin_insn; + plugin_insn->vaddr =3D db->pc_next; + g_assert(tcg_ctx->plugin_mem_cb =3D=3D NULL); + } else { + struct qemu_plugin_insn *insn =3D &plugin_tb->insns[insn_i= dx++]; + + tcg_ctx->plugin_insn =3D NULL; + if (unlikely(insn->exec_cbs.n)) { + qemu_plugin_gen_vcpu_udata_callbacks(&insn->exec_cbs); + } + if (insn->mem_cbs.n) { + tcg_ctx->plugin_mem_cb =3D &insn->mem_cbs; + if (insn->calls_helpers) { + qemu_plugin_gen_enable_mem_helpers(&insn->mem_cbs); + mem_helpers =3D true; + } + } else { + tcg_ctx->plugin_mem_cb =3D NULL; + } + } + } db->num_insns++; ops->insn_start(db, cpu); tcg_debug_assert(db->is_jmp =3D=3D DISAS_NEXT); /* no early exit = */ @@ -101,10 +178,14 @@ void translator_loop(const TranslatorOps *ops, DisasC= ontextBase *db, && (tb_cflags(db->tb) & CF_LAST_IO)) { /* Accept I/O on the last instruction. */ gen_io_start(); - ops->translate_insn(db, cpu, NULL); + ops->translate_insn(db, cpu, plugin_insn); gen_io_end(); } else { - ops->translate_insn(db, cpu, NULL); + ops->translate_insn(db, cpu, plugin_insn); + } + + if (unlikely(mem_helpers)) { + qemu_plugin_gen_disable_mem_helpers(); } =20 /* Stop translation if translate_insn so indicated. */ @@ -120,6 +201,12 @@ void translator_loop(const TranslatorOps *ops, DisasCo= ntextBase *db, } } =20 + if (tb_trans_cb && first_pass) { + qemu_plugin_tb_trans_cb(cpu, plugin_tb); + first_pass =3D false; + goto translate; + } + /* Emit code to exit the TB, as indicated by db->is_jmp. */ ops->tb_stop(db, cpu); gen_tb_end(db->tb, db->num_insns - bp_insn); --=20 2.17.1