From nobody Mon Apr 29 08:36:20 2024 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 1504730121987847.4833041558461; Wed, 6 Sep 2017 13:35:21 -0700 (PDT) Received: from localhost ([::1]:37690 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dph2f-0006ej-2N for importer@patchew.org; Wed, 06 Sep 2017 16:35:21 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53493) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpgxU-0002Zo-BR for qemu-devel@nongnu.org; Wed, 06 Sep 2017 16:30:05 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dpgxR-00013f-5c for qemu-devel@nongnu.org; Wed, 06 Sep 2017 16:30:00 -0400 Received: from out1-smtp.messagingengine.com ([66.111.4.25]:41599) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dpgxQ-00011q-VR for qemu-devel@nongnu.org; Wed, 06 Sep 2017 16:29:57 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id 1E34A20B2E; Wed, 6 Sep 2017 16:29:55 -0400 (EDT) Received: from frontend2 ([10.202.2.161]) by compute4.internal (MEProxy); Wed, 06 Sep 2017 16:29:55 -0400 Received: from localhost (flamenco.cs.columbia.edu [128.59.20.216]) by mail.messagingengine.com (Postfix) with ESMTPA id CCF49240A4; Wed, 6 Sep 2017 16:29:54 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=braap.org; h=cc :date:from:in-reply-to:message-id:references:subject:to :x-me-sender:x-me-sender:x-sasl-enc:x-sasl-enc; s=mesmtp; bh=uIf 9wyJY0a1xB9NEfA/yIJaXWVhupRaB6ow59U4DkJ4=; b=btcYliQKQlUNyulF/PM Ksl25z107DGuMhf+D0fKVpmJ9rP/wksP/ECcLbMJ9LZuksiPE2K7wZ17cMEQxhsX tiB7LD55lDS1dihjOw87KUATv7JgAsegkrywUbcu6lHubxpUteMENEnQHNh3cn2w gSB8RAd8xqGKTYjVMccrAINc= 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-sender:x-me-sender:x-sasl-enc :x-sasl-enc; s=fm1; bh=uIf9wyJY0a1xB9NEfA/yIJaXWVhupRaB6ow59U4Dk J4=; b=QnBeaSxVqZDvUeNPej0m0gwr65aDv616XuLyeoA9MwHGSg7vXwSFeGp9X oxURzB0lRYFXDUpIVv72UTwziM2ScW+1cba9/Hl3XfF9qObcAk43ePxePU3mqBUU Bx2TaiQt3JM2mdMxQqIjy6yiarJ8Z3KlXDZPBI0mEEDvsGGIH3EYKRuboA3MIP8F BMSn+hokAhVY2XRZTNrkKjtMg3N7/gSV7aXCishE20prKT4vydnVQeR8rAZZ0j5+ kdn5Fn/t016qZcyRem0Oc48B2ARdOZWTt6g8aith/0GS6dnZnKnGX6ijEnOvGveZ HQ28UIisUzPNlZBztB6ZobJfnSPQg== X-ME-Sender: X-Sasl-enc: siU69U5WVz7GPr1InDXiOUOueonVQIisbKO7R20WO30e 1504729794 From: "Emilio G. Cota" To: qemu-devel@nongnu.org Date: Wed, 6 Sep 2017 16:28:43 -0400 Message-Id: <1504729728-23279-2-git-send-email-cota@braap.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1504729728-23279-1-git-send-email-cota@braap.org> References: <1504729728-23279-1-git-send-email-cota@braap.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.111.4.25 Subject: [Qemu-devel] [RFC 1/6] tcg: keep a pointer to the current TB in TCGContext 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: =?UTF-8?q?Llu=C3=ADs=20Vilanova?= , Stefan Hajnoczi Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Instead of just a copy of tb->cflags. This gives access in TCG to other fields in TB, which will be needed when we implement callbacks from memory accesses performed by TCG-translated code. Signed-off-by: Emilio G. Cota --- tcg/tcg.h | 2 +- accel/tcg/translate-all.c | 3 ++- tcg/tcg-op.c | 10 +++++----- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/tcg/tcg.h b/tcg/tcg.h index cf4eeaf..86ca604 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -676,7 +676,7 @@ struct TCGContext { uintptr_t *tb_jmp_target_addr; /* tb->jmp_target_addr if !USE_DIRECT_J= UMP */ =20 TCGRegSet reserved_regs; - uint32_t tb_cflags; /* cflags of the current TB */ + const TranslationBlock *tb; intptr_t current_frame_offset; intptr_t frame_start; intptr_t frame_end; diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 69cc7dc..7332afc 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -1600,7 +1600,6 @@ TranslationBlock *tb_gen_code(CPUState *cpu, tb->flags =3D flags; tb->cflags =3D cflags; tb->trace_vcpu_dstate =3D *cpu->trace_dstate; - tcg_ctx->tb_cflags =3D cflags; =20 #ifdef CONFIG_PROFILER /* includes aborted translations because of exceptions */ @@ -1610,9 +1609,11 @@ TranslationBlock *tb_gen_code(CPUState *cpu, =20 tcg_func_start(tcg_ctx); =20 + tcg_ctx->tb =3D tb; tcg_ctx->cpu =3D ENV_GET_CPU(env); gen_intermediate_code(cpu, tb); tcg_ctx->cpu =3D NULL; + tcg_ctx->tb =3D NULL; =20 trace_translate_block(tb, tb->pc, tb->tc.ptr); =20 diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c index 2a8bf90..32449d2 100644 --- a/tcg/tcg-op.c +++ b/tcg/tcg-op.c @@ -150,7 +150,7 @@ void tcg_gen_op6(TCGContext *ctx, TCGOpcode opc, TCGArg= a1, TCGArg a2, =20 void tcg_gen_mb(TCGBar mb_type) { - if (tcg_ctx->tb_cflags & CF_PARALLEL) { + if (tb_cflags(tcg_ctx->tb) & CF_PARALLEL) { tcg_gen_op1(tcg_ctx, INDEX_op_mb, mb_type); } } @@ -2794,7 +2794,7 @@ void tcg_gen_atomic_cmpxchg_i32(TCGv_i32 retv, TCGv a= ddr, TCGv_i32 cmpv, { memop =3D tcg_canonicalize_memop(memop, 0, 0); =20 - if (!(tcg_ctx->tb_cflags & CF_PARALLEL)) { + if (!(tb_cflags(tcg_ctx->tb) & CF_PARALLEL)) { TCGv_i32 t1 =3D tcg_temp_new_i32(); TCGv_i32 t2 =3D tcg_temp_new_i32(); =20 @@ -2838,7 +2838,7 @@ void tcg_gen_atomic_cmpxchg_i64(TCGv_i64 retv, TCGv a= ddr, TCGv_i64 cmpv, { memop =3D tcg_canonicalize_memop(memop, 1, 0); =20 - if (!(tcg_ctx->tb_cflags & CF_PARALLEL)) { + if (!(tb_cflags(tcg_ctx->tb) & CF_PARALLEL)) { TCGv_i64 t1 =3D tcg_temp_new_i64(); TCGv_i64 t2 =3D tcg_temp_new_i64(); =20 @@ -3015,7 +3015,7 @@ static void * const table_##NAME[16] =3D { = \ void tcg_gen_atomic_##NAME##_i32 \ (TCGv_i32 ret, TCGv addr, TCGv_i32 val, TCGArg idx, TCGMemOp memop) \ { \ - if (tcg_ctx->tb_cflags & CF_PARALLEL) { \ + if (tb_cflags(tcg_ctx->tb) & CF_PARALLEL) { \ do_atomic_op_i32(ret, addr, val, idx, memop, table_##NAME); \ } else { \ do_nonatomic_op_i32(ret, addr, val, idx, memop, NEW, \ @@ -3025,7 +3025,7 @@ void tcg_gen_atomic_##NAME##_i32 = \ void tcg_gen_atomic_##NAME##_i64 \ (TCGv_i64 ret, TCGv addr, TCGv_i64 val, TCGArg idx, TCGMemOp memop) \ { \ - if (tcg_ctx->tb_cflags & CF_PARALLEL) { \ + if (tb_cflags(tcg_ctx->tb) & CF_PARALLEL) { \ do_atomic_op_i64(ret, addr, val, idx, memop, table_##NAME); \ } else { \ do_nonatomic_op_i64(ret, addr, val, idx, memop, NEW, \ --=20 2.7.4 From nobody Mon Apr 29 08:36:20 2024 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 1504730230081697.7288867368169; Wed, 6 Sep 2017 13:37:10 -0700 (PDT) Received: from localhost ([::1]:37703 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dph4O-0007vB-KA for importer@patchew.org; Wed, 06 Sep 2017 16:37:08 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53529) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpgxZ-0002dX-4X for qemu-devel@nongnu.org; Wed, 06 Sep 2017 16:30:12 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dpgxR-00013n-68 for qemu-devel@nongnu.org; Wed, 06 Sep 2017 16:30:05 -0400 Received: from out1-smtp.messagingengine.com ([66.111.4.25]:45713) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dpgxQ-000128-TA for qemu-devel@nongnu.org; Wed, 06 Sep 2017 16:29:57 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id 68A4721304; Wed, 6 Sep 2017 16:29:55 -0400 (EDT) Received: from frontend1 ([10.202.2.160]) by compute4.internal (MEProxy); Wed, 06 Sep 2017 16:29:55 -0400 Received: from localhost (flamenco.cs.columbia.edu [128.59.20.216]) by mail.messagingengine.com (Postfix) with ESMTPA id 126DE7FA80; Wed, 6 Sep 2017 16:29:55 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=braap.org; h=cc :date:from:in-reply-to:message-id:references:subject:to :x-me-sender:x-me-sender:x-sasl-enc:x-sasl-enc; s=mesmtp; bh=1dC 8PmYFPpLhEUN/CeOPTKNIqndyr/2UFlNMdR7VilE=; b=yXIqLCuww6Uh/JEwfy6 IswA+fFeKO9swPESP0kqNxVTxGHJyIK+Rlk9030uv/jXayZptPGHRNo8J8q3m8rb uKiG+8CDgbhXimdzfwIL4jmIv8aiznwreID1n1z+7e8AAgqxptWi4TolUAk3JmSH x/acx/wkdYU/8pHciCj8vDbw= 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-sender:x-me-sender:x-sasl-enc :x-sasl-enc; s=fm1; bh=1dC8PmYFPpLhEUN/CeOPTKNIqndyr/2UFlNMdR7Vi lE=; b=F4kslIL6VVx4nkdLtM7MFsE7CVeRPCfqN5A2EVKCsqmmZTtmCz7JKIxBv aaM6yDJUOIxsJLrT2nW4pWrLX21Vmwoh5aUEw2cm9ZPR2OdUsNK+D0pARItHY92O syJpRDQK0iqdPzqBBbufj5KXmdonrvAkXZsbU+MGeKQooO7OrasGYqY9JBQuDHCk 3xQrWeBOSB1ewWadj4nrhTmtkePRh7gMQr8qQEnNaVxBpgc/EU/rEIv7GGaT8zAH U8ZK8FjL1+/Rgjh1hfuZy1TUAxSkk7eIqdq3GXMKy99UzalC41ajqa/SVgh8yJkY cQBmJxIQdfN5vkhfbVkXfU5/tu4AQ== X-ME-Sender: X-Sasl-enc: jV0QI1HwOnL72ggVXoJV6yCbq/jBHlqur6TLXMXi5kC/ 1504729795 From: "Emilio G. Cota" To: qemu-devel@nongnu.org Date: Wed, 6 Sep 2017 16:28:44 -0400 Message-Id: <1504729728-23279-3-git-send-email-cota@braap.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1504729728-23279-1-git-send-email-cota@braap.org> References: <1504729728-23279-1-git-send-email-cota@braap.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.111.4.25 Subject: [Qemu-devel] [RFC 2/6] plugin: add initial plugin support 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: =?UTF-8?q?Llu=C3=ADs=20Vilanova?= , Stefan Hajnoczi Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This is still a work in progress, hence the limited public-facing API. I wanted to add more events (e.g. memory and basic block callbacks), but before spending more time on time I'd like to see whether this direction is appreciated by others. The goals are to: - Have a simple implementation that shares nothing with tracing code. - Make sure we cannot deadlock, particularly under MTTCG. For this, we acquire a lock when called from plugin code, and keep RCU lists of callbacks so that we do not have to hold the lock when calling the callbacks. This is also for performance, since some callbacks (e.g. memory access callbacks) might be called very frequently. * A consequence of this is that we keep our own list of CPUs, so that we do not have to worry about locking order wrt cpu_list_lock. * Some functions such as vcpu_for_each will call plugin code with the lock held. Instead of making the lock recursive, just document that the function called by vcpu_for_each cannot call any other plugin API. - Support as many plugins as the user wants (e.g. -plugin foo -plugin bar), just like other tools (e.g. dynamorio) do. - Support the installation/uninstallation of a plugin any time (i.e. from any callback from the guest, or from QAPI/QMP). - Avoid malicious plugins from abusing the API. This is done by: * Adding a qemu_plugin_id_t that all calls need to use. This is a unique id per plugin. * Hiding CPUState * under cpu_index. Plugin code can keep per-vcpu data by using said index (say to index an array). * Only exporting the relevant qemu_plugin symbols to the plugins by passing --dynamic-file to the linker (when supported), instead of exporting all symbols with -rdynamic. - Performance: registering/unregistering callbacks is slow. But this is very infrequent; we want performance when calling (or not) callbacks. Using RCU is great for this. The only difficulty is when uninstalling a plugin, where some callbacks might still be called after the uninstall returns. An alternative would be to use r/w locks, but that would complicate code quite a bit for very little gain; I suspect most plugins will just run until QEMU exits. Some design decisions: - I considered registering callbacks per-vcpu, but really I don't see the use case for it (would complicate the API and 99% of plugins won't care, = so I'd rather make that 1% slower by letting them discard unwanted callbacks= ). - Using a per-vcpu mask is key to allow for maximum performance/scalability. With RCU callbacks and async work we can ensure no events are missed, and we keep maximum scalability (again, we assume callbacks are a lot more common than callback registration). - Last, 'plugin' vs. 'instrumentation' naming: I think instrumentation is a subset of the functionality that plugins can provide. IOW, in the future not all plugins might be considered instrumentation, even if currently my goal is to use them for that purpose. Signed-off-by: Emilio G. Cota --- Makefile.objs | 1 + include/exec/exec-all.h | 2 + include/exec/tb-hash-xx.h | 26 ++- include/exec/tb-hash.h | 6 +- include/exec/tb-lookup.h | 1 + include/qemu/plugin-api.h | 105 ++++++++++ include/qemu/plugin.h | 74 +++++++ include/qom/cpu.h | 4 + accel/tcg/cpu-exec.c | 6 +- accel/tcg/translate-all.c | 6 +- plugin.c | 519 ++++++++++++++++++++++++++++++++++++++++++= ++++ qom/cpu.c | 3 + tests/qht-bench.c | 2 +- qemu-plugins.symbols | 6 + 14 files changed, 746 insertions(+), 15 deletions(-) create mode 100644 include/qemu/plugin-api.h create mode 100644 include/qemu/plugin.h create mode 100644 plugin.c create mode 100644 qemu-plugins.symbols diff --git a/Makefile.objs b/Makefile.objs index 24a4ea0..52cc89c 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -84,6 +84,7 @@ endif ####################################################################### # Target-independent parts used in system and user emulation common-obj-y +=3D cpus-common.o +common-obj-$(CONFIG_PLUGINS) +=3D plugin.o common-obj-y +=3D hw/ common-obj-y +=3D qom/ common-obj-y +=3D disas/ diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 1d4e977..add9423 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -346,6 +346,8 @@ struct TranslationBlock { /* Per-vCPU dynamic tracing state used to generate this TB */ uint32_t trace_vcpu_dstate; =20 + uint32_t plugin_mask; + struct tb_tc tc; =20 /* original tb when cflags has CF_NOCACHE */ diff --git a/include/exec/tb-hash-xx.h b/include/exec/tb-hash-xx.h index 747a9a6..4015d6a 100644 --- a/include/exec/tb-hash-xx.h +++ b/include/exec/tb-hash-xx.h @@ -49,7 +49,8 @@ * contiguous in memory. */ static inline uint32_t -tb_hash_func7(uint64_t a0, uint64_t b0, uint32_t e, uint32_t f, uint32_t g) +tb_hash_func8(uint64_t a0, uint64_t b0, uint32_t e, uint32_t f, uint32_t g, + uint32_t h) { uint32_t v1 =3D TB_HASH_XX_SEED + PRIME32_1 + PRIME32_2; uint32_t v2 =3D TB_HASH_XX_SEED + PRIME32_2; @@ -77,17 +78,24 @@ tb_hash_func7(uint64_t a0, uint64_t b0, uint32_t e, uin= t32_t f, uint32_t g) v4 =3D rol32(v4, 13); v4 *=3D PRIME32_1; =20 - h32 =3D rol32(v1, 1) + rol32(v2, 7) + rol32(v3, 12) + rol32(v4, 18); - h32 +=3D 28; + v1 +=3D e * PRIME32_2; + v1 =3D rol32(v1, 13); + v1 *=3D PRIME32_1; =20 - h32 +=3D e * PRIME32_3; - h32 =3D rol32(h32, 17) * PRIME32_4; + v2 +=3D f * PRIME32_2; + v2 =3D rol32(v2, 13); + v2 *=3D PRIME32_1; =20 - h32 +=3D f * PRIME32_3; - h32 =3D rol32(h32, 17) * PRIME32_4; + v3 +=3D g * PRIME32_2; + v3 =3D rol32(v3, 13); + v3 *=3D PRIME32_1; =20 - h32 +=3D g * PRIME32_3; - h32 =3D rol32(h32, 17) * PRIME32_4; + v4 +=3D h * PRIME32_2; + v4 =3D rol32(v4, 13); + v4 *=3D PRIME32_1; + + h32 =3D rol32(v1, 1) + rol32(v2, 7) + rol32(v3, 12) + rol32(v4, 18); + h32 +=3D 32; =20 h32 ^=3D h32 >> 15; h32 *=3D PRIME32_2; diff --git a/include/exec/tb-hash.h b/include/exec/tb-hash.h index 0526c4f..f501dd1 100644 --- a/include/exec/tb-hash.h +++ b/include/exec/tb-hash.h @@ -59,9 +59,11 @@ static inline unsigned int tb_jmp_cache_hash_func(target= _ulong pc) =20 static inline uint32_t tb_hash_func(tb_page_addr_t phys_pc, target_ulong pc, uint32_t fl= ags, - uint32_t cf_mask, uint32_t trace_vcpu_dstate) + uint32_t cf_mask, uint32_t trace_vcpu_dstate, + uint32_t plugin_mask) { - return tb_hash_func7(phys_pc, pc, flags, cf_mask, trace_vcpu_dstate); + return tb_hash_func8(phys_pc, pc, flags, cf_mask, trace_vcpu_dstate, + plugin_mask); } =20 #endif diff --git a/include/exec/tb-lookup.h b/include/exec/tb-lookup.h index 2961385..c879903 100644 --- a/include/exec/tb-lookup.h +++ b/include/exec/tb-lookup.h @@ -35,6 +35,7 @@ tb_lookup__cpu_state(CPUState *cpu, target_ulong *pc, tar= get_ulong *cs_base, tb->cs_base =3D=3D *cs_base && tb->flags =3D=3D *flags && tb->trace_vcpu_dstate =3D=3D *cpu->trace_dstate && + tb->plugin_mask =3D=3D *cpu->plugin_mask && (tb_cflags(tb) & (CF_HASH_MASK | CF_INVALID)) =3D=3D cf_mas= k)) { return tb; } diff --git a/include/qemu/plugin-api.h b/include/qemu/plugin-api.h new file mode 100644 index 0000000..85f827a --- /dev/null +++ b/include/qemu/plugin-api.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2017, Emilio G. Cota + * + * License: GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#ifndef QEMU_PLUGIN_API_H +#define QEMU_PLUGIN_API_H + +#include + +/* + * For best performance, build the plugin with -fvisibility=3Dhidden so th= at + * QEMU_PLUGIN_LOCAL is implicit. Then, just mark qemu_plugin_install with + * QEMU_PLUGIN_EXPORT. For more info, see + * https://gcc.gnu.org/wiki/Visibility + */ +#if defined _WIN32 || defined __CYGWIN__ + #ifdef BUILDING_DLL + #define QEMU_PLUGIN_EXPORT __declspec(dllexport) + #else + #define QEMU_PLUGIN_EXPORT __declspec(dllimport) + #endif + #define QEMU_PLUGIN_LOCAL +#else + #if __GNUC__ >=3D 4 + #define QEMU_PLUGIN_EXPORT __attribute__((visibility("default"))) + #define QEMU_PLUGIN_LOCAL __attribute__((visibility("hidden"))) + #else + #define QEMU_PLUGIN_EXPORT + #define QEMU_PLUGIN_LOCAL + #endif +#endif + +typedef uint64_t qemu_plugin_id_t; + +/** + * qemu_plugin_install - Install a plugin + * @id: this plugin's opaque ID + * @argc: number of arguments + * @argv: array of arguments (@argc elements) + * + * All plugins must export this symbol. + * + * Note: @argv is freed after this function returns. + */ +QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, int argc, + char **argv); + +/** + * qemu_plugin_uninstall - Uninstall a plugin + * @id: this plugin's opaque ID + * + * Removes all callbacks and unloads the plugin. + * + * Once this function returns, no further API calls from it are allowed. + * + * Note: if the plugin is multi-threaded (e.g. it is subscribed to callbac= ks + * from vCPUs running in parallel), some time will elapse before changes + * propagate to all threads, and therefore some callbacks might still be c= alled + * for a short period of time after this function returns. + */ +void qemu_plugin_uninstall(qemu_plugin_id_t id); + +typedef void (*qemu_plugin_vcpu_simple_cb_t)(qemu_plugin_id_t id, + unsigned int vcpu_index); + +/** + * qemu_plugin_register_vcpu_init_cb - register a vCPU initialization call= back + * @id: plugin ID + * @cb: callback function + * + * The @cb function is called every time a vCPU is initialized. + * + * See also: qemu_plugin_register_vcpu_exit_cb() + */ +void qemu_plugin_register_vcpu_init_cb(qemu_plugin_id_t id, + qemu_plugin_vcpu_simple_cb_t cb); + +/** + * qemu_plugin_register_vcpu_exit_cb - register a vCPU exit callback + * @id: plugin ID + * @cb: callback function + * + * The @cb function is called every time a vCPU exits. + * + * See also: qemu_plugin_register_vcpu_init_cb() + */ +void qemu_plugin_register_vcpu_exit_cb(qemu_plugin_id_t id, + qemu_plugin_vcpu_simple_cb_t cb); + +/** + * qemu_plugin_vcpu_for_each - iterate over the existing vCPU + * @id: plugin ID + * @cb: callback function + * + * The @cb function is called once for each existing vCPU. + * Note: to avoid deadlock, @cb cannot make any other qemu_plugin_*() call. + * + * See also: qemu_plugin_register_vcpu_init_cb() + */ +void qemu_plugin_vcpu_for_each(qemu_plugin_id_t id, + qemu_plugin_vcpu_simple_cb_t cb); + +#endif /* QEMU_PLUGIN_API_H */ diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h new file mode 100644 index 0000000..a73540b --- /dev/null +++ b/include/qemu/plugin.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2017, Emilio G. Cota + * + * License: GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#ifndef QEMU_PLUGIN_H +#define QEMU_PLUGIN_H + +#include "qemu/config-file.h" +#include "qemu/plugin-api.h" +#include "qemu/error-report.h" +#include "qemu/queue.h" +#include "qemu/option.h" + +/* + * Option parsing/processing. + * Note that we can load an arbitrary number of plugins. + */ +struct qemu_plugin_desc; +QTAILQ_HEAD(qemu_plugin_list, qemu_plugin_desc); + +#ifdef CONFIG_PLUGINS +extern QemuOptsList qemu_plugin_opts; + +static inline void qemu_plugin_add_opts(void) +{ + qemu_add_opts(&qemu_plugin_opts); +} + +void qemu_plugin_opt_parse(const char *optarg, struct qemu_plugin_list *he= ad); +int qemu_plugin_load_list(struct qemu_plugin_list *head); +#else /* !CONFIG_PLUGINS */ +static inline void qemu_plugin_add_opts(void) +{ } + +static inline void qemu_plugin_opt_parse(const char *optarg, + struct qemu_plugin_list *head) +{ + error_report("plugin interface not enabled in this build"); + exit(1); +} + +static inline int qemu_plugin_load_list(struct qemu_plugin_list *head) +{ + return 0; +} +#endif /* !CONFIG_PLUGINS */ + +/* + * Events that plugins can subscribe to. + */ +enum qemu_plugin_event { + QEMU_PLUGIN_EV_VCPU_INIT, + QEMU_PLUGIN_EV_VCPU_EXIT, + QEMU_PLUGIN_EV_MAX, +}; + +#ifdef CONFIG_PLUGINS + +void qemu_plugin_vcpu_init_hook(CPUState *cpu); +void qemu_plugin_vcpu_exit_hook(CPUState *cpu); + +#else /* !CONFIG_PLUGINS */ + +static inline void qemu_plugin_vcpu_init_hook(CPUState *cpu) +{ } + +static inline void qemu_plugin_vcpu_exit_hook(CPUState *cpu) +{ } + +#endif /* !CONFIG_PLUGINS */ + +#endif /* QEMU_PLUGIN_H */ diff --git a/include/qom/cpu.h b/include/qom/cpu.h index 25eefea..899b2d6 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -27,6 +27,7 @@ #include "qemu/bitmap.h" #include "qemu/queue.h" #include "qemu/thread.h" +#include "qemu/plugin.h" =20 typedef int (*WriteCoreDumpFunction)(const void *buf, size_t size, void *opaque); @@ -305,6 +306,7 @@ struct qemu_work_item; * @trace_dstate_delayed: Delayed changes to trace_dstate (includes all ch= anges * to @trace_dstate). * @trace_dstate: Dynamic tracing state of events for this vCPU (bitmask). + * @plugin_mask: Plugin event bitmap. Modified only via async work. * * State of one CPU core or thread. */ @@ -377,6 +379,8 @@ struct CPUState { DECLARE_BITMAP(trace_dstate_delayed, CPU_TRACE_DSTATE_MAX_EVENTS); DECLARE_BITMAP(trace_dstate, CPU_TRACE_DSTATE_MAX_EVENTS); =20 + DECLARE_BITMAP(plugin_mask, QEMU_PLUGIN_EV_MAX); + /* TODO Move common fields from CPUArchState here. */ int cpu_index; /* used by alpha TCG */ uint32_t halted; /* used by alpha, cris, ppc TCG */ diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index e38479b..5523c44 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -271,6 +271,7 @@ struct tb_desc { uint32_t flags; uint32_t cf_mask; uint32_t trace_vcpu_dstate; + uint32_t plugin_mask; }; =20 static bool tb_lookup_cmp(const void *p, const void *d) @@ -283,6 +284,7 @@ static bool tb_lookup_cmp(const void *p, const void *d) tb->cs_base =3D=3D desc->cs_base && tb->flags =3D=3D desc->flags && tb->trace_vcpu_dstate =3D=3D desc->trace_vcpu_dstate && + tb->plugin_mask =3D=3D desc->plugin_mask && (tb_cflags(tb) & (CF_HASH_MASK | CF_INVALID)) =3D=3D desc->cf_mask= ) { /* check next page if needed */ if (tb->page_addr[1] =3D=3D -1) { @@ -314,10 +316,12 @@ TranslationBlock *tb_htable_lookup(CPUState *cpu, tar= get_ulong pc, desc.flags =3D flags; desc.cf_mask =3D cf_mask; desc.trace_vcpu_dstate =3D *cpu->trace_dstate; + desc.plugin_mask =3D *cpu->plugin_mask; desc.pc =3D pc; phys_pc =3D get_page_addr_code(desc.env, pc); desc.phys_page1 =3D phys_pc & TARGET_PAGE_MASK; - h =3D tb_hash_func(phys_pc, pc, flags, cf_mask, *cpu->trace_dstate); + h =3D tb_hash_func(phys_pc, pc, flags, cf_mask, *cpu->trace_dstate, + *cpu->plugin_mask); return qht_lookup_custom(&tb_ctx.htable, tb_lookup_cmp, &desc, h); } =20 diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 7332afc..17abfcc 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -1027,6 +1027,7 @@ static bool tb_cmp(const void *ap, const void *bp) a->flags =3D=3D b->flags && (tb_cflags(a) & CF_HASH_MASK) =3D=3D (tb_cflags(b) & CF_HASH_MASK)= && a->trace_vcpu_dstate =3D=3D b->trace_vcpu_dstate && + a->plugin_mask =3D=3D b->plugin_mask && a->page_addr[0] =3D=3D b->page_addr[0] && a->page_addr[1] =3D=3D b->page_addr[1]; } @@ -1344,7 +1345,7 @@ static void do_tb_phys_invalidate(TranslationBlock *t= b, bool rm_from_page_list) /* remove the TB from the hash list */ phys_pc =3D tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK); h =3D tb_hash_func(phys_pc, tb->pc, tb->flags, tb->cflags & CF_HASH_MA= SK, - tb->trace_vcpu_dstate); + tb->trace_vcpu_dstate, tb->plugin_mask); if (!qht_remove(&tb_ctx.htable, tb, h)) { return; } @@ -1533,7 +1534,7 @@ tb_link_page(TranslationBlock *tb, tb_page_addr_t phy= s_pc, =20 /* add in the hash table */ h =3D tb_hash_func(phys_pc, tb->pc, tb->flags, tb->cflags & CF_HASH_MA= SK, - tb->trace_vcpu_dstate); + tb->trace_vcpu_dstate, tb->plugin_mask); existing_tb =3D qht_insert(&tb_ctx.htable, tb, h); =20 /* remove TB from the page(s) if we couldn't insert it */ @@ -1600,6 +1601,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu, tb->flags =3D flags; tb->cflags =3D cflags; tb->trace_vcpu_dstate =3D *cpu->trace_dstate; + tb->plugin_mask =3D *cpu->plugin_mask; =20 #ifdef CONFIG_PROFILER /* includes aborted translations because of exceptions */ diff --git a/plugin.c b/plugin.c new file mode 100644 index 0000000..3cd19df --- /dev/null +++ b/plugin.c @@ -0,0 +1,519 @@ +/* plugin.c - QEMU Plugin interface + * + * Copyright (C) 2017, Emilio G. Cota + * + * License: GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qemu/plugin.h" +#include "qemu/config-file.h" +#include "qapi/error.h" +#include "qemu/option.h" +#include "qemu/rcu_queue.h" +#include "qemu/rcu.h" +#include "qom/cpu.h" +#include "exec/cpu-common.h" +#include + +struct qemu_plugin_cb { + struct qemu_plugin_ctx *ctx; + union { + qemu_plugin_vcpu_simple_cb_t vcpu_simple_cb; + void *func; + }; + QLIST_ENTRY(qemu_plugin_cb) entry; +}; + +QLIST_HEAD(qemu_plugin_cb_head, qemu_plugin_cb); + +struct qemu_plugin_ctx { + /* @rcu: keep at the top to help valgrind find the whole struct */ + struct rcu_head rcu; + void *handle; /* dlopen */ + qemu_plugin_id_t id; + struct qemu_plugin_cb *callbacks[QEMU_PLUGIN_EV_MAX]; + QTAILQ_ENTRY(qemu_plugin_ctx) entry; + bool uninstalling; /* protected by plugin.lock */ +}; + +/* global state */ +struct qemu_plugin_state { + QTAILQ_HEAD(, qemu_plugin_ctx) ctxs; + struct qemu_plugin_cb_head cb_lists[QEMU_PLUGIN_EV_MAX]; + /* + * Use the HT as a hash map by inserting k =3D=3D v, which saves memor= y as + * documented by GLib. The parent struct is obtained with container_of= (). + */ + GHashTable *id_ht; + /* + * Use the HT as a hash map. Note that we could use a list here, + * but with the HT we avoid adding a field to CPUState. + */ + GHashTable *cpu_ht; + DECLARE_BITMAP(mask, QEMU_PLUGIN_EV_MAX); + /* + * @lock protects the struct as well as ctx->uninstalling. + * The lock must be acquired by all API ops. Since some API ops + * call plugin code repeatedly (e.g. vcpu_for_each), we keep + * a counter to allow for recursive acquisitions. + */ + QemuMutex lock; +}; + +/* + * For convenience we use a bitmap for plugin.mask, but really all we need= is a + * u32, which is what we store in TranslationBlock. + */ +QEMU_BUILD_BUG_ON(QEMU_PLUGIN_EV_MAX > 32); + +struct qemu_plugin_desc { + char *path; + char **argv; + QTAILQ_ENTRY(qemu_plugin_desc) entry; + int argc; +}; + +struct qemu_plugin_parse_arg { + struct qemu_plugin_list *head; + struct qemu_plugin_desc *curr; +}; + +QemuOptsList qemu_plugin_opts =3D { + .name =3D "plugin", + .implied_opt_name =3D "file", + .head =3D QTAILQ_HEAD_INITIALIZER(qemu_plugin_opts.head), + .desc =3D { + /* do our own parsing to support multiple plugins */ + { /* end of list */ } + }, +}; + +typedef int (*qemu_plugin_install_func_t)(qemu_plugin_id_t, int, char **); + +static struct qemu_plugin_state plugin; +static __thread bool plugin_lock_held; + +static inline void plugin_lock(void) +{ + g_assert(!plugin_lock_held); + qemu_mutex_lock(&plugin.lock); + plugin_lock_held =3D true; +} + +static inline void plugin_unlock(void) +{ + plugin_lock_held =3D false; + qemu_mutex_unlock(&plugin.lock); +} + +static struct qemu_plugin_desc *plugin_find_desc(struct qemu_plugin_list *= head, + const char *path) +{ + struct qemu_plugin_desc *desc; + + QTAILQ_FOREACH(desc, head, entry) { + if (strcmp(desc->path, path) =3D=3D 0) { + return desc; + } + } + return NULL; +} + +static int plugin_add(void *opaque, const char *name, const char *value, + Error **errp) +{ + struct qemu_plugin_parse_arg *arg =3D opaque; + struct qemu_plugin_desc *p; + + if (strcmp(name, "file") =3D=3D 0) { + if (strcmp(value, "") =3D=3D 0) { + error_setg(errp, "requires a non-empty argument"); + return 1; + } + p =3D plugin_find_desc(arg->head, value); + if (p =3D=3D NULL) { + p =3D g_new0(struct qemu_plugin_desc, 1); + p->path =3D g_strdup(value); + QTAILQ_INSERT_TAIL(arg->head, p, entry); + } + arg->curr =3D p; + } else if (strcmp(name, "arg") =3D=3D 0) { + if (arg->curr =3D=3D NULL) { + error_setg(errp, "missing earlier '-plugin file=3D' option"); + return 1; + } + p =3D arg->curr; + p->argc++; + p->argv =3D g_realloc_n(p->argv, p->argc, sizeof(char *)); + p->argv[p->argc - 1] =3D g_strdup(value); + } else { + g_assert_not_reached(); + } + return 0; +} + +void qemu_plugin_opt_parse(const char *optarg, struct qemu_plugin_list *he= ad) +{ + struct qemu_plugin_parse_arg arg; + QemuOpts *opts; + + opts =3D qemu_opts_parse_noisily(qemu_find_opts("plugin"), optarg, tru= e); + if (opts =3D=3D NULL) { + exit(1); + } + arg.head =3D head; + arg.curr =3D NULL; + qemu_opt_foreach(opts, plugin_add, &arg, &error_fatal); + qemu_opts_del(opts); +} + +/* + * From: https://en.wikipedia.org/wiki/Xorshift + * This is faster than rand_r(), and gives us a wider range (RAND_MAX is o= nly + * guaranteed to be >=3D INT_MAX). + */ +static uint64_t xorshift64star(uint64_t x) +{ + x ^=3D x >> 12; /* a */ + x ^=3D x << 25; /* b */ + x ^=3D x >> 27; /* c */ + return x * UINT64_C(2685821657736338717); +} + +static int plugin_load(struct qemu_plugin_desc *desc) +{ + qemu_plugin_install_func_t install; + struct qemu_plugin_ctx *ctx; + char *err; + int rc; + + ctx =3D qemu_memalign(qemu_dcache_linesize, sizeof(*ctx)); + memset(ctx, 0, sizeof(*ctx)); + ctx->handle =3D dlopen(desc->path, RTLD_NOW); + if (ctx->handle =3D=3D NULL) { + error_report("%s: %s", __func__, dlerror()); + goto err_dlopen; + } + + /* clear any previous dlerror, call dlsym, then check dlerror */ + dlerror(); + install =3D dlsym(ctx->handle, "qemu_plugin_install"); + err =3D dlerror(); + if (err) { + error_report("%s: %s", __func__, err); + goto err_symbol; + } + /* symbol was found; it could be NULL though */ + if (install =3D=3D NULL) { + error_report("%s: %s: qemu_plugin_install is NULL", + __func__, desc->path); + goto err_symbol; + } + + plugin_lock(); + + /* find an unused random id with &ctx as the seed */ + ctx->id =3D (uint64_t)ctx; + for (;;) { + void *existing; + + ctx->id =3D xorshift64star(ctx->id); + existing =3D g_hash_table_lookup(plugin.id_ht, &ctx->id); + if (likely(existing =3D=3D NULL)) { + bool success; + + success =3D g_hash_table_insert(plugin.id_ht, &ctx->id, &ctx->= id); + g_assert(success); + break; + } + } + QTAILQ_INSERT_TAIL(&plugin.ctxs, ctx, entry); + plugin_unlock(); + + rc =3D install(ctx->id, desc->argc, desc->argv); + if (rc) { + error_report("%s: qemu_plugin_install returned error code %d", + __func__, rc); + /* + * we cannot rely on the plugin doing its own cleanup, so + * call a full uninstall if the plugin did not already call it. + */ + plugin_lock(); + if (!ctx->uninstalling) { + qemu_plugin_uninstall(ctx->id); + } + plugin_unlock(); + return 1; + } + return 0; + + err_symbol: + if (dlclose(ctx->handle)) { + warn_report("%s: %s", __func__, dlerror()); + } + err_dlopen: + qemu_vfree(ctx); + return 1; +} + +/* call after having removed @desc from the list */ +static void plugin_desc_free(struct qemu_plugin_desc *desc) +{ + int i; + + for (i =3D 0; i < desc->argc; i++) { + g_free(desc->argv[i]); + } + g_free(desc->argv); + g_free(desc->path); + g_free(desc); +} + +/** + * qemu_plugin_load_list - load a list of plugins + * @head: head of the list of descriptors of the plugins to be loaded + * + * Returns 0 if all plugins in the list are installed, !0 otherwise. + * + * Note: the descriptor of each successfully installed plugin is removed + * from the list given by @head and then freed. + */ +int qemu_plugin_load_list(struct qemu_plugin_list *head) +{ + struct qemu_plugin_desc *desc, *next; + + QTAILQ_FOREACH_SAFE(desc, head, entry, next) { + int err; + + err =3D plugin_load(desc); + if (err) { + return err; + } + QTAILQ_REMOVE(head, desc, entry); + plugin_desc_free(desc); + } + return 0; +} + +static struct qemu_plugin_ctx *id_to_ctx(qemu_plugin_id_t id) +{ + struct qemu_plugin_ctx *ctx; + qemu_plugin_id_t *id_p; + + g_assert(plugin_lock_held); + id_p =3D g_hash_table_lookup(plugin.id_ht, &id); + ctx =3D container_of(id_p, struct qemu_plugin_ctx, id); + if (ctx =3D=3D NULL) { + error_report("plugin: invalid plugin id %" PRIu64, id); + abort(); + } + return ctx; +} + +static void plugin_cpu_update__async(CPUState *cpu, run_on_cpu_data data) +{ + bitmap_copy(cpu->plugin_mask, &data.host_ulong, QEMU_PLUGIN_EV_MAX); + cpu_tb_jmp_cache_clear(cpu); +} + +static void plugin_cpu_update(gpointer k, gpointer v, gpointer udata) +{ + CPUState *cpu =3D container_of(k, CPUState, cpu_index); + run_on_cpu_data mask =3D RUN_ON_CPU_HOST_ULONG(*plugin.mask); + + g_assert(plugin_lock_held); + + if (cpu->created) { + async_run_on_cpu(cpu, plugin_cpu_update__async, mask); + } else { + plugin_cpu_update__async(cpu, mask); + } +} + +static void plugin_unregister_cb(struct qemu_plugin_ctx *ctx, + enum qemu_plugin_event ev) +{ + struct qemu_plugin_cb *cb =3D ctx->callbacks[ev]; + + g_assert(plugin_lock_held); + + if (cb =3D=3D NULL) { + return; + } + QLIST_REMOVE_RCU(cb, entry); + g_free(cb); + ctx->callbacks[ev] =3D NULL; + if (QLIST_EMPTY_RCU(&plugin.cb_lists[ev])) { + clear_bit(ev, plugin.mask); + g_hash_table_foreach(plugin.cpu_ht, plugin_cpu_update, NULL); + } +} + +static void plugin_destroy__rcuthread(struct qemu_plugin_ctx *ctx) +{ + plugin_lock(); + QTAILQ_REMOVE(&plugin.ctxs, ctx, entry); + g_assert(ctx->uninstalling); + plugin_unlock(); + + if (dlclose(ctx->handle)) { + warn_report("%s: %s", __func__, dlerror()); + } + qemu_vfree(ctx); +} + +void qemu_plugin_uninstall(qemu_plugin_id_t id) +{ + struct qemu_plugin_ctx *ctx; + enum qemu_plugin_event ev; + bool success; + + plugin_lock(); + ctx =3D id_to_ctx(id); + if (unlikely(ctx->uninstalling)) { + error_report("plugin: called %s more than once", __func__); + abort(); + } + ctx->uninstalling =3D true; + /* + * Unregister all callbacks. This is an RCU list so it is possible tha= t some + * callbacks will still be called in this RCU grace period. For this r= eason + * we cannot yet free the context nor invalidate its id. + */ + for (ev =3D 0; ev < QEMU_PLUGIN_EV_MAX; ev++) { + plugin_unregister_cb(ctx, ev); + } + success =3D g_hash_table_remove(plugin.id_ht, &ctx->id); + g_assert(success); + plugin_unlock(); + + call_rcu(ctx, plugin_destroy__rcuthread, rcu); +} + +static void plugin_vcpu_cb__simple(CPUState *cpu, enum qemu_plugin_event e= v) +{ + struct qemu_plugin_cb *cb, *next; + + switch (ev) { + case QEMU_PLUGIN_EV_VCPU_INIT: + case QEMU_PLUGIN_EV_VCPU_EXIT: + /* iterate safely; plugins might uninstall themselves at any time = */ + QLIST_FOREACH_SAFE_RCU(cb, &plugin.cb_lists[ev], entry, next) { + qemu_plugin_vcpu_simple_cb_t func =3D cb->vcpu_simple_cb; + + func(cb->ctx->id, cpu->cpu_index); + } + break; + default: + g_assert_not_reached(); + } +} + +static void plugin_register_cb(qemu_plugin_id_t id, enum qemu_plugin_event= ev, + void *func) +{ + struct qemu_plugin_ctx *ctx; + + plugin_lock(); + ctx =3D id_to_ctx(id); + if (func) { + struct qemu_plugin_cb *cb =3D ctx->callbacks[ev]; + + if (cb) { + cb->func =3D func; + } else { + cb =3D g_new(struct qemu_plugin_cb, 1); + cb->ctx =3D ctx; + cb->func =3D func; + ctx->callbacks[ev] =3D cb; + QLIST_INSERT_HEAD_RCU(&plugin.cb_lists[ev], cb, entry); + if (!test_bit(ev, plugin.mask)) { + set_bit(ev, plugin.mask); + g_hash_table_foreach(plugin.cpu_ht, plugin_cpu_update, NUL= L); + } + } + } else { + plugin_unregister_cb(ctx, ev); + } + plugin_unlock(); +} + +void qemu_plugin_register_vcpu_init_cb(qemu_plugin_id_t id, + qemu_plugin_vcpu_simple_cb_t cb) +{ + plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_INIT, cb); +} + +void qemu_plugin_register_vcpu_exit_cb(qemu_plugin_id_t id, + qemu_plugin_vcpu_simple_cb_t cb) +{ + plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_EXIT, cb); +} + +void qemu_plugin_vcpu_init_hook(CPUState *cpu) +{ + bool success; + + plugin_lock(); + success =3D g_hash_table_insert(plugin.cpu_ht, &cpu->cpu_index, + &cpu->cpu_index); + g_assert(success); + plugin_unlock(); + + plugin_vcpu_cb__simple(cpu, QEMU_PLUGIN_EV_VCPU_INIT); +} + +void qemu_plugin_vcpu_exit_hook(CPUState *cpu) +{ + bool success; + + plugin_vcpu_cb__simple(cpu, QEMU_PLUGIN_EV_VCPU_EXIT); + + plugin_lock(); + success =3D g_hash_table_remove(plugin.cpu_ht, &cpu->cpu_index); + g_assert(success); + plugin_unlock(); +} + +struct plugin_for_each_args { + struct qemu_plugin_ctx *ctx; + qemu_plugin_vcpu_simple_cb_t cb; +}; + +static void plugin_vcpu_for_each(gpointer k, gpointer v, gpointer udata) +{ + struct plugin_for_each_args *args =3D udata; + int cpu_index =3D *(int *)k; + + args->cb(args->ctx->id, cpu_index); +} + +void qemu_plugin_vcpu_for_each(qemu_plugin_id_t id, + qemu_plugin_vcpu_simple_cb_t cb) +{ + struct plugin_for_each_args args; + + if (cb =3D=3D NULL) { + return; + } + plugin_lock(); + args.ctx =3D id_to_ctx(id); + args.cb =3D cb; + g_hash_table_foreach(plugin.cpu_ht, plugin_vcpu_for_each, &args); + plugin_unlock(); +} + +static void __attribute__((__constructor__)) plugin_init(void) +{ + int i; + + for (i =3D 0; i < QEMU_PLUGIN_EV_MAX; i++) { + QLIST_INIT(&plugin.cb_lists[i]); + } + qemu_mutex_init(&plugin.lock); + plugin.id_ht =3D g_hash_table_new(g_int64_hash, g_int64_equal); + plugin.cpu_ht =3D g_hash_table_new(g_int_hash, g_int_equal); + QTAILQ_INIT(&plugin.ctxs); +} diff --git a/qom/cpu.c b/qom/cpu.c index 4f38db0..60b4a56 100644 --- a/qom/cpu.c +++ b/qom/cpu.c @@ -31,6 +31,7 @@ #include "sysemu/sysemu.h" #include "hw/qdev-properties.h" #include "trace-root.h" +#include "qemu/plugin.h" =20 CPUInterruptHandler cpu_interrupt_handler; =20 @@ -368,6 +369,7 @@ static void cpu_common_realizefn(DeviceState *dev, Erro= r **errp) =20 /* NOTE: latest generic point where the cpu is fully realized */ trace_init_vcpu(cpu); + qemu_plugin_vcpu_init_hook(cpu); } =20 static void cpu_common_unrealizefn(DeviceState *dev, Error **errp) @@ -375,6 +377,7 @@ static void cpu_common_unrealizefn(DeviceState *dev, Er= ror **errp) CPUState *cpu =3D CPU(dev); /* NOTE: latest generic point before the cpu is fully unrealized */ trace_fini_vcpu(cpu); + qemu_plugin_vcpu_exit_hook(cpu); cpu_exec_unrealizefn(cpu); } =20 diff --git a/tests/qht-bench.c b/tests/qht-bench.c index 6c2eb8e..86cd85a 100644 --- a/tests/qht-bench.c +++ b/tests/qht-bench.c @@ -103,7 +103,7 @@ static bool is_equal(const void *ap, const void *bp) =20 static inline uint32_t h(unsigned long v) { - return tb_hash_func7(v, 0, 0, 0, 0); + return tb_hash_func8(v, 0, 0, 0, 0, 0); } =20 /* diff --git a/qemu-plugins.symbols b/qemu-plugins.symbols new file mode 100644 index 0000000..2b8463e --- /dev/null +++ b/qemu-plugins.symbols @@ -0,0 +1,6 @@ +{ + qemu_plugin_uninstall; + qemu_plugin_register_vcpu_init_cb; + qemu_plugin_register_vcpu_exit_cb; + qemu_plugin_vcpu_for_each; +}; --=20 2.7.4 From nobody Mon Apr 29 08:36:20 2024 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 1504729925079588.6702174768618; Wed, 6 Sep 2017 13:32:05 -0700 (PDT) Received: from localhost ([::1]:37681 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpgzU-0003mn-4Z for importer@patchew.org; Wed, 06 Sep 2017 16:32:04 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53488) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpgxU-0002Zm-AS for qemu-devel@nongnu.org; Wed, 06 Sep 2017 16:30:01 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dpgxR-00013l-5n for qemu-devel@nongnu.org; Wed, 06 Sep 2017 16:30:00 -0400 Received: from out1-smtp.messagingengine.com ([66.111.4.25]:50383) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dpgxR-00012D-07 for qemu-devel@nongnu.org; Wed, 06 Sep 2017 16:29:57 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id 867F021333; Wed, 6 Sep 2017 16:29:55 -0400 (EDT) Received: from frontend2 ([10.202.2.161]) by compute4.internal (MEProxy); Wed, 06 Sep 2017 16:29:55 -0400 Received: from localhost (flamenco.cs.columbia.edu [128.59.20.216]) by mail.messagingengine.com (Postfix) with ESMTPA id 4A4D3240A4; Wed, 6 Sep 2017 16:29:55 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=braap.org; h=cc :date:from:in-reply-to:message-id:references:subject:to :x-me-sender:x-me-sender:x-sasl-enc:x-sasl-enc; s=mesmtp; bh=0Tg p9O/DXyYzJ0E8AdBm7s9h5NAXuRN+n2/EOxZa2Xo=; b=dNMMscphVxdEpKWvW60 P/CTb9YBTanAe9hU98qSCN+BAH7BBcJqP71tNUaHpaCSAxfMKAhHgRwEIEyrUPvL allxCaD9R26KEBKKnShtDlAdRQoN/BAQQWwi0qjOYVPKTPTDfJ88+p7pF3GxuIZa 3oCI2Fc6QGYh9rTfBRSJnI9A= 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-sender:x-me-sender:x-sasl-enc :x-sasl-enc; s=fm1; bh=0Tgp9O/DXyYzJ0E8AdBm7s9h5NAXuRN+n2/EOxZa2 Xo=; b=KSxkxq9ZnhN4zPCjfw1ZD6bz16PtZoAHBSNvlWy8+H2I9BWwArSxb9/l6 th+eL8vKtOpzIvL9vklj903SDKEy9Jhxd++sVMjddfXtv68xLoigYvN7MB9z0all U0EWF3jvFtA/HK7eUMTli2FbA0zvtVpgoQDbvkiybWX3aTG5V2lTGUwz7UjVxTtK G7+802M+Yboxssehmhh1RXdPhyoxur9WazXn057/cnKBnlBqKcYYo2DAepEc9Yk9 eKLZNfsYA0BKdouK1t0sD+K8h96Z/M7eiLjbzbbv9T8/11L0mEih4fQpqQqeBt1V x1HMSwK4gODpLlTIUF7icBctLFbnQ== X-ME-Sender: X-Sasl-enc: jV0PJFLzLnfqwBIVV4BV6yCbq/jBHlqur6TLXMXi5kC/ 1504729795 From: "Emilio G. Cota" To: qemu-devel@nongnu.org Date: Wed, 6 Sep 2017 16:28:45 -0400 Message-Id: <1504729728-23279-4-git-send-email-cota@braap.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1504729728-23279-1-git-send-email-cota@braap.org> References: <1504729728-23279-1-git-send-email-cota@braap.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.111.4.25 Subject: [Qemu-devel] [RFC 3/6] configure: add --enable-plugins 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: =?UTF-8?q?Llu=C3=ADs=20Vilanova?= , Stefan Hajnoczi Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" For now only add it for ELF platforms, since we rely on the linker's --dynamic-list flag to pass a list of symbols to be exported to the executable. An alternative would be to use -rdynamic, but that would expose all of QEMU's objects to plugins. I have no experience with non-ELF systems but I suspect adding support for those should be pretty easy. Signed-off-by: Emilio G. Cota --- configure | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/configure b/configure index 987f59b..45f7af5 100755 --- a/configure +++ b/configure @@ -30,6 +30,7 @@ TMPO=3D"${TMPDIR1}/${TMPB}.o" TMPCXX=3D"${TMPDIR1}/${TMPB}.cxx" TMPE=3D"${TMPDIR1}/${TMPB}.exe" TMPMO=3D"${TMPDIR1}/${TMPB}.mo" +TMPTXT=3D"${TMPDIR1}/${TMPB}.txt" =20 rm -f config.log =20 @@ -404,6 +405,8 @@ tcmalloc=3D"no" jemalloc=3D"no" replication=3D"yes" vxhs=3D"" +plugins=3D"no" +ld_dynamic_list=3D"no" =20 supported_cpu=3D"no" supported_os=3D"no" @@ -1282,6 +1285,10 @@ for opt do ;; --enable-vxhs) vxhs=3D"yes" ;; + --enable-plugins) plugins=3D"yes" + ;; + --disable-plugins) plugins=3D"no" + ;; *) echo "ERROR: unknown option $opt" echo "Try '$0 --help' for more information" @@ -1442,6 +1449,8 @@ Advanced options (experts only): xen pv domain builder --enable-debug-stack-usage track the maximum stack usage of stacks created= by qemu_alloc_stack + --enable-plugins + enable plugins via shared library loading =20 Optional features, enabled with --enable-FEATURE and disabled with --disable-FEATURE, default is enabled if available: @@ -4745,6 +4754,42 @@ if compile_prog "" "" ; then atomic64=3Dyes fi =20 +######################################### +# See if --dynamic-list is supported by the linker + +cat > $TMPTXT < $TMPC < +void foo(void); + +void foo(void) +{ + printf("foo\n"); +} + +int main(void) +{ + foo(); + return 0; +} +EOF + +if compile_prog "" "-Wl,--dynamic-list=3D$TMPTXT" ; then + ld_dynamic_list=3D"yes" +else + if test "$plugins" =3D "yes" ; then + error_exit \ + "Plugin support requires specifying a set of symbols that " \ + "are exported to plugins. Unfortunately your linker doesn't " \ + "support the flag (--dynamic-list) used for this purpose." + fi +fi + ######################################## # check if getauxval is available. =20 @@ -5388,6 +5433,7 @@ echo "jemalloc support $jemalloc" echo "avx2 optimization $avx2_opt" echo "replication support $replication" echo "VxHS block device $vxhs" +echo "plugin support $plugins" =20 if test "$sdl_too_old" =3D "yes"; then echo "-> Your SDL version is too old - please upgrade to have SDL support" @@ -6053,6 +6099,12 @@ if test "$vxhs" =3D "yes" ; then echo "VXHS_LIBS=3D$vxhs_libs" >> $config_host_mak fi =20 +if test "$plugins" =3D "yes" ; then + echo "CONFIG_PLUGINS=3Dy" >> $config_host_mak + LIBS=3D"-ldl $LIBS" + LDFLAGS=3D"-Wl,--dynamic-list=3D\$(SRC_PATH)/qemu-plugins.symbols $LDF= LAGS" +fi + if test "$tcg_interpreter" =3D "yes"; then QEMU_INCLUDES=3D"-I\$(SRC_PATH)/tcg/tci $QEMU_INCLUDES" elif test "$ARCH" =3D "sparc64" ; then --=20 2.7.4 From nobody Mon Apr 29 08:36:20 2024 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 1504729983347927.0727038349185; Wed, 6 Sep 2017 13:33:03 -0700 (PDT) Received: from localhost ([::1]:37683 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dph0Q-0004o3-A9 for importer@patchew.org; Wed, 06 Sep 2017 16:33:02 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53491) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpgxU-0002Zn-B9 for qemu-devel@nongnu.org; Wed, 06 Sep 2017 16:30:05 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dpgxR-000149-AS for qemu-devel@nongnu.org; Wed, 06 Sep 2017 16:30:00 -0400 Received: from out1-smtp.messagingengine.com ([66.111.4.25]:48845) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dpgxR-00012V-7Z for qemu-devel@nongnu.org; Wed, 06 Sep 2017 16:29:57 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id C5AE220D89; Wed, 6 Sep 2017 16:29:55 -0400 (EDT) Received: from frontend1 ([10.202.2.160]) by compute4.internal (MEProxy); Wed, 06 Sep 2017 16:29:55 -0400 Received: from localhost (flamenco.cs.columbia.edu [128.59.20.216]) by mail.messagingengine.com (Postfix) with ESMTPA id 80E3B7E68E; Wed, 6 Sep 2017 16:29:55 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=braap.org; h=cc :date:from:in-reply-to:message-id:references:subject:to :x-me-sender:x-me-sender:x-sasl-enc:x-sasl-enc; s=mesmtp; bh=CXz Tq/phlZidKiS+9OWIObBN4o4WgkdYrLlnCSJenCE=; b=RFOtInrbB7xxmq11NTL zIGHgrW8pEWnwK+UEZgAL8451EZBj5P6X2zr26Ogg4rLYfEhve97BCQM+gFc7uoM crLyq6/xxmrsRxCQbU3BN89g9acTCplZLLO3/3NlQhYpMlGXNyTcZoeyS+KETBNt hARfXqFPf7xKh1t9xb2H2nhA= 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-sender:x-me-sender:x-sasl-enc :x-sasl-enc; s=fm1; bh=CXzTq/phlZidKiS+9OWIObBN4o4WgkdYrLlnCSJen CE=; b=LZGlyxknpXNWm4dhVaRitXpjPPMZQC8kUV31v17bm9rb2GCd6TTkvCjpI YIJ7su9ZpLsstkIW0PRI2krmAFmyfla+C/oQ+h4uLmpO4RJnmCvGXOcsJhwuguKP 3w2jG2bm6dcPOA5zijf9PR5MRV7sXw5eSJ5gBDGnzAR6kQMSukWECWe2QXG8se2c sID0V+Ete946yqwOperCVlM6T0W9m8kCxkdZ5wJUDnavyNFllzu8LMTSfd0+Mf18 vqWl92v9PcvrhpMR4Pg/dvKSXmW/sATqgvLCYf/r+Jc74McCEQkavUbMZnrM+6qR hyrnrk6MuHR6aeMITCIFVHxIdxv9g== X-ME-Sender: X-Sasl-enc: jV0TK13/MXXi2BkTSYBV6yCbq/jBHlqur6TLXMXi5kC/ 1504729795 From: "Emilio G. Cota" To: qemu-devel@nongnu.org Date: Wed, 6 Sep 2017 16:28:46 -0400 Message-Id: <1504729728-23279-5-git-send-email-cota@braap.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1504729728-23279-1-git-send-email-cota@braap.org> References: <1504729728-23279-1-git-send-email-cota@braap.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.111.4.25 Subject: [Qemu-devel] [RFC 4/6] Makefile: install qemu-api.h as include/qemu-plugin.h 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: =?UTF-8?q?Llu=C3=ADs=20Vilanova?= , Stefan Hajnoczi Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Emilio G. Cota --- Makefile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ef72148..326867e 100644 --- a/Makefile +++ b/Makefile @@ -602,8 +602,10 @@ ifneq (,$(findstring qemu-ga,$(TOOLS))) endif endif =20 +install-includedir: + $(INSTALL_DIR) "$(DESTDIR)$(includedir)" =20 -install: all $(if $(BUILD_DOCS),install-doc) install-datadir install-local= statedir +install: all $(if $(BUILD_DOCS),install-doc) install-datadir install-local= statedir install-includedir ifneq ($(TOOLS),) $(call install-prog,$(subst qemu-ga,qemu-ga$(EXESUF),$(TOOLS)),$(DESTDIR)= $(bindir)) endif @@ -626,6 +628,9 @@ endif ifeq ($(CONFIG_GTK),y) $(MAKE) -C po $@ endif +ifeq ($(CONFIG_PLUGINS),y) + $(INSTALL_DATA) $(SRC_PATH)/include/qemu/plugin-api.h "$(DESTDIR)$(includ= edir)/qemu-plugin.h" +endif $(INSTALL_DIR) "$(DESTDIR)$(qemu_datadir)/keymaps" set -e; for x in $(KEYMAPS); do \ $(INSTALL_DATA) $(SRC_PATH)/pc-bios/keymaps/$$x "$(DESTDIR)$(qemu_datadi= r)/keymaps"; \ --=20 2.7.4 From nobody Mon Apr 29 08:36:20 2024 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 150472993168550.4667230986156; Wed, 6 Sep 2017 13:32:11 -0700 (PDT) Received: from localhost ([::1]:37682 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpgza-0003ws-MN for importer@patchew.org; Wed, 06 Sep 2017 16:32:10 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53522) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpgxW-0002az-9R for qemu-devel@nongnu.org; Wed, 06 Sep 2017 16:30:07 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dpgxR-00014Q-ED for qemu-devel@nongnu.org; Wed, 06 Sep 2017 16:30:02 -0400 Received: from out1-smtp.messagingengine.com ([66.111.4.25]:47575) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dpgxR-00013Z-Ah for qemu-devel@nongnu.org; Wed, 06 Sep 2017 16:29:57 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id 0695621381; Wed, 6 Sep 2017 16:29:56 -0400 (EDT) Received: from frontend2 ([10.202.2.161]) by compute4.internal (MEProxy); Wed, 06 Sep 2017 16:29:56 -0400 Received: from localhost (flamenco.cs.columbia.edu [128.59.20.216]) by mail.messagingengine.com (Postfix) with ESMTPA id B6A60240A4; Wed, 6 Sep 2017 16:29:55 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=braap.org; h=cc :content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to:x-me-sender :x-me-sender:x-sasl-enc:x-sasl-enc; s=mesmtp; bh=x0JbfsYyMba4lSY RKAzEGTsWVAnkmZG4UE+PytUI0TM=; b=D9n3IRdxl39oZ1Cz7TbR5omn9cJnsBL Y5lFpu4zlmOrTozaF73tJvSNRDp4EvvCzXkMNNtx4JStsi54StXIckwqbFbNjib+ 5PrtGz91HGWDZnQt+x2VZrtxy5ZB1Bcor2caADtwvO7bUDrP7mEF7l8zGZjJ2xyT SXPfr/2w5xDI= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:content-type :date:from:in-reply-to:message-id:mime-version:references :subject:to:x-me-sender:x-me-sender:x-sasl-enc:x-sasl-enc; s= fm1; bh=x0JbfsYyMba4lSYRKAzEGTsWVAnkmZG4UE+PytUI0TM=; b=RP0w2JxB odF+ranZ+BXBzSu7nYh0ldWxMJqIUdZObaH1b4owDX2oJ9BhhT9tgeJEchE5vRSl WgBQwjXXUzc70INeawnEp8RAodJyi8seVKDq32q29GUr5sQ8L2+WsV8ffyz0nDW2 m/xJ4QlYQB1hPSZr9SQyAcD4N5MV1pAa91Ae7nYd9IyfmtCCfw/h52pKgXKHz+PU 1b+J8MdOQ5VtrsNYADMbnYKdz36fRFrau5zfAvAC0HqmaKgANkZPBAOinJUp/tUG aNDcDX2PHAOSKsfFXzeuvKaztRFqt6hXfgPayYyRUN1+Zlfu/CEFePnQJ43vB8id L/lt0XkB3R4u9g== X-ME-Sender: X-Sasl-enc: jV0UP1/vM27xwQwUQoFV6yCbq/jBHlqur6TLXMXi5kC/ 1504729795 From: "Emilio G. Cota" To: qemu-devel@nongnu.org Date: Wed, 6 Sep 2017 16:28:47 -0400 Message-Id: <1504729728-23279-6-git-send-email-cota@braap.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1504729728-23279-1-git-send-email-cota@braap.org> References: <1504729728-23279-1-git-send-email-cota@braap.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.111.4.25 Subject: [Qemu-devel] [RFC 5/6] vl: support -plugin option 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: =?UTF-8?q?Llu=C3=ADs=20Vilanova?= , Stefan Hajnoczi Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 From: Llu=C3=ADs Vilanova Signed-off-by: Llu=C3=ADs Vilanova [ cota: s/instrument/plugin ] Signed-off-by: Emilio G. Cota --- vl.c | 10 ++++++++++ qemu-options.hx | 17 +++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/vl.c b/vl.c index fb6b2ef..d3d8adc 100644 --- a/vl.c +++ b/vl.c @@ -118,6 +118,7 @@ int main(int argc, char **argv) =20 #include "trace-root.h" #include "trace/control.h" +#include "qemu/plugin.h" #include "qemu/queue.h" #include "sysemu/arch_init.h" =20 @@ -3031,6 +3032,7 @@ int main(int argc, char **argv, char **envp) } BlockdevOptions_queue; QSIMPLEQ_HEAD(, BlockdevOptions_queue) bdo_queue =3D QSIMPLEQ_HEAD_INITIALIZER(bdo_queue); + struct qemu_plugin_list plugin_list =3D QTAILQ_HEAD_INITIALIZER(plugin= _list); =20 module_call_init(MODULE_INIT_TRACE); =20 @@ -3058,6 +3060,7 @@ int main(int argc, char **argv, char **envp) qemu_add_opts(&qemu_global_opts); qemu_add_opts(&qemu_mon_opts); qemu_add_opts(&qemu_trace_opts); + qemu_plugin_add_opts(); qemu_add_opts(&qemu_option_rom_opts); qemu_add_opts(&qemu_machine_opts); qemu_add_opts(&qemu_accel_opts); @@ -3999,6 +4002,9 @@ int main(int argc, char **argv, char **envp) g_free(trace_file); trace_file =3D trace_opt_parse(optarg); break; + case QEMU_OPTION_plugin: + qemu_plugin_opt_parse(optarg, &plugin_list); + break; case QEMU_OPTION_readconfig: { int ret =3D qemu_read_config_file(optarg); @@ -4185,6 +4191,10 @@ int main(int argc, char **argv, char **envp) } trace_init_file(trace_file); =20 + if (qemu_plugin_load_list(&plugin_list)) { + exit(1); + } + /* Open the logfile at this point and set the log mask if necessary. */ if (log_file) { diff --git a/qemu-options.hx b/qemu-options.hx index 746b5fa..34557e6 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -4064,6 +4064,23 @@ HXCOMM HX does not support conditional compilation o= f text. @findex -trace @include qemu-option-trace.texi ETEXI +DEF("plugin", HAS_ARG, QEMU_OPTION_plugin, + "-plugin [file=3D][,arg=3D]\n" + " load a plugin\n", + QEMU_ARCH_ALL) +STEXI +@item -plugin file=3D@var{file}[,arg=3D@var{string}] +@findex -plugin + +Load a plugin. + +@table @option +@item file=3D@var{file} +Load the given plugin from a shared library file. +@item arg=3D@var{string} +Argument string passed to the plugin. (Can be given multiple times.) +@end table +ETEXI =20 HXCOMM Internal use DEF("qtest", HAS_ARG, QEMU_OPTION_qtest, "", QEMU_ARCH_ALL) --=20 2.7.4 From nobody Mon Apr 29 08:36:20 2024 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 1504730072042599.3769107069156; Wed, 6 Sep 2017 13:34:32 -0700 (PDT) Received: from localhost ([::1]:37688 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dph1q-000617-LA for importer@patchew.org; Wed, 06 Sep 2017 16:34:30 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53487) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpgxU-0002Zl-A5 for qemu-devel@nongnu.org; Wed, 06 Sep 2017 16:30:01 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dpgxR-00014W-FA for qemu-devel@nongnu.org; Wed, 06 Sep 2017 16:30:00 -0400 Received: from out1-smtp.messagingengine.com ([66.111.4.25]:52465) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dpgxR-00013a-Ap for qemu-devel@nongnu.org; Wed, 06 Sep 2017 16:29:57 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id 376FC2135C; Wed, 6 Sep 2017 16:29:56 -0400 (EDT) Received: from frontend1 ([10.202.2.160]) by compute4.internal (MEProxy); Wed, 06 Sep 2017 16:29:56 -0400 Received: from localhost (flamenco.cs.columbia.edu [128.59.20.216]) by mail.messagingengine.com (Postfix) with ESMTPA id E901F7E68E; Wed, 6 Sep 2017 16:29:55 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=braap.org; h=cc :content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to:x-me-sender :x-me-sender:x-sasl-enc:x-sasl-enc; s=mesmtp; bh=CuUZxpc2+MOssTU KcsIeePkVSwoD1ldwyN+BjWX4BAw=; b=J3lfqaGuErc21iD4KniiO3+eguwL8jd L19HnoGfW07Ly/Jc5n1bS8mkyE3LmrONtm0Eg0wafQLDkDvvlyMivD06TEXgKu7G J7QZS0YvoH/v6iQCuHd9JJoTZ4H6Z3hrwIl2B9m9jtA5FTSv+I0ARbQo5Ar4mOmR wYAsV8T09gSQ= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:content-type :date:from:in-reply-to:message-id:mime-version:references :subject:to:x-me-sender:x-me-sender:x-sasl-enc:x-sasl-enc; s= fm1; bh=CuUZxpc2+MOssTUKcsIeePkVSwoD1ldwyN+BjWX4BAw=; b=b2SZMLjw n1v0XJ0D7wPtqfYv30Ca+6W+DOGiXsIT9EKHX1Aap61fK8vYQKle7wwUjSmCTfQD 1h1KiirZjkxpkpGCQo3ocULP5eHLol83rk0CjbkKYAIJ5qgyeAmnu3s77+sRUjrN KmabFPdibbRSYK4fYXA9IarsD7lHrLP+zpnDARs8aIiL3uUHPFgl9cCCcky0+DoH uXboS7v/twy1jRC/JAISOn7/CEzVbbYp1845Q/oFPxrz4/6jgp1w0uf30qSeLJXK C8SI/NGfjugot44R6jFFOVS/oMyCeLIY1J5zpDdlFw1hdSEPJ1dId/74k6gXCFFZ nS5hWnspeW5YBg== X-ME-Sender: X-Sasl-enc: jV0FO1X5MXXq0wsfS5RV6yCbq/jBHlqur6TLXMXi5kC/ 1504729795 From: "Emilio G. Cota" To: qemu-devel@nongnu.org Date: Wed, 6 Sep 2017 16:28:48 -0400 Message-Id: <1504729728-23279-7-git-send-email-cota@braap.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1504729728-23279-1-git-send-email-cota@braap.org> References: <1504729728-23279-1-git-send-email-cota@braap.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.111.4.25 Subject: [Qemu-devel] [RFC 6/6] linux-user: support -plugin option 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: =?UTF-8?q?Llu=C3=ADs=20Vilanova?= , Stefan Hajnoczi Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 From: Llu=C3=ADs Vilanova Signed-off-by: Llu=C3=ADs Vilanova [ cota: s/instrument/plugin ] Signed-off-by: Emilio G. Cota --- linux-user/main.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/linux-user/main.c b/linux-user/main.c index 31c8f1a..211ee02 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -27,6 +27,7 @@ #include "qemu/config-file.h" #include "qemu/cutils.h" #include "qemu/help_option.h" +#include "qemu/plugin.h" #include "cpu.h" #include "exec/exec-all.h" #include "tcg.h" @@ -4014,6 +4015,15 @@ static void handle_arg_trace(const char *arg) trace_file =3D trace_opt_parse(arg); } =20 +static struct qemu_plugin_list plugins =3D QTAILQ_HEAD_INITIALIZER(plugins= ); + +#ifdef CONFIG_PLUGINS +static void handle_arg_plugin(const char *arg) +{ + qemu_plugin_opt_parse(arg, &plugins); +} +#endif + struct qemu_argument { const char *argv; const char *env; @@ -4063,6 +4073,10 @@ static const struct qemu_argument arg_table[] =3D { "", "Seed for pseudo-random number generator"}, {"trace", "QEMU_TRACE", true, handle_arg_trace, "", "[[enable=3D]][,events=3D][,file=3D]"}, +#ifdef CONFIG_PLUGINS + {"plugin", "QEMU_PLUGIN", true, handle_arg_plugin, + "", "[file=3D][,arg=3D]"}, +#endif {"version", "QEMU_VERSION", false, handle_arg_version, "", "display version information and exit"}, {NULL, NULL, false, NULL, NULL, NULL} @@ -4252,6 +4266,7 @@ int main(int argc, char **argv, char **envp) srand(time(NULL)); =20 qemu_add_opts(&qemu_trace_opts); + qemu_plugin_add_opts(); =20 optind =3D parse_args(argc, argv); =20 @@ -4259,6 +4274,9 @@ int main(int argc, char **argv, char **envp) exit(1); } trace_init_file(trace_file); + if (qemu_plugin_load_list(&plugins)) { + exit(1); + } =20 /* Zero out regs */ memset(regs, 0, sizeof(struct target_pt_regs)); --=20 2.7.4