From patchwork Tue Oct 22 10:56:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Alex_Benn=C3=A9e?= X-Patchwork-Id: 837548 Delivered-To: patch@linaro.org Received: by 2002:a5d:50c9:0:b0:37d:45d0:187 with SMTP id f9csp2475848wrt; Tue, 22 Oct 2024 03:59:10 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCX2+qsaH5Uq46SuXorF/UVAVyfIZOPIPGWeHTQ2SyFV+ebtDVGQ62kORDGFhfGRQCWDOHQhcQ==@linaro.org X-Google-Smtp-Source: AGHT+IHd68q326rnAvYCEKYXaDyHNhEW3QM4RCqgZCYnLETMnP0WmeO6Hjg2vvTjCcLWM6uLfIB9 X-Received: by 2002:a05:6102:3f4a:b0:4a3:a7a0:889a with SMTP id ada2fe7eead31-4a742e41930mr2503187137.19.1729594750742; Tue, 22 Oct 2024 03:59:10 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1729594750; cv=none; d=google.com; s=arc-20240605; b=C2WFhBjDkJKaYSeNov3c4UxzZwOutBX34++3z0fun4r2JXPSPcmAMoOEQVi2/vGhnl 8DVU3AJ2sSSA0RXxNkY/Y2TJB6ODpxqMxx8rdajyjPnsc9v+UQB+II/Df/cWFKnfDwrt ugtNg8pNQqxkQKo4Escgh+l18/atks2Wqlb+C492lao5iJDsefzUPFhJB4BALIwuEMcA lmMZ3HXUQe4QZZ/POxBpfO7T2NRAQ/yAwsyhdry+zITPoT6wVsuGB9el8ylnpTLXkZLn +VsjSOqDfhJwBL5CUZsALbfL5T6caPCVyezAfBFSVH9KuYUzrsx8eI8Bhb9KZaXF5sqJ hsFw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=ncBC08IoBkP10ef5QDpG5SV+FPj/pwrW84Mb8BGJC6M=; fh=pVjH8310hlVyksknvNC3/D3AfgLq4a8e+T5MCg3/MHg=; b=crV7GzvzQmUS3h2ETc39OkE+5bivuQJSy/Fm+LzQ8l2dlEUR9lt6vMFZxEDjB1XEB4 iqoPMzcZiL2t6dmi7KjKfFORQsVsFGciS8Bcoi+ljixVLn9jnu3MB3aakL1U4fta7ewt OxDaQCUf/9oX6Hibgd6bw8N4dD8hrEQDUBm/F72yHSibCdymRag+5FtcaL6YNmdvNzEw 5pVINUHAWuV/sPGofXQk6EWYbR6N3mVR4MCx+A1g4KQtTjm1wp7Cd8YBxYm5hChJr6PX HYmVMHIrX5nrNm0kdtJKEjN76eqvqRGQBVdtGyFTI+2taVP3k0Ur5LXMrDASeCMOVd/C GmpA==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=ANmHrUZh; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org; dara=neutral header.i=@linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [209.51.188.17]) by mx.google.com with ESMTPS id d75a77b69052e-460d3b380c8si61035931cf.2.2024.10.22.03.59.10 for (version=TLS1_2 cipher=ECDHE-ECDSA-CHACHA20-POLY1305 bits=256/256); Tue, 22 Oct 2024 03:59:10 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=ANmHrUZh; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org; dara=neutral header.i=@linaro.org Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1t3CZl-0002n7-CY; Tue, 22 Oct 2024 06:57:21 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1t3CZ4-0001qk-PK for qemu-devel@nongnu.org; Tue, 22 Oct 2024 06:56:38 -0400 Received: from mail-ej1-x634.google.com ([2a00:1450:4864:20::634]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1t3CZ2-000260-Mc for qemu-devel@nongnu.org; Tue, 22 Oct 2024 06:56:38 -0400 Received: by mail-ej1-x634.google.com with SMTP id a640c23a62f3a-a86e9db75b9so710440466b.1 for ; Tue, 22 Oct 2024 03:56:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1729594595; x=1730199395; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ncBC08IoBkP10ef5QDpG5SV+FPj/pwrW84Mb8BGJC6M=; b=ANmHrUZhQRwGwzgFbQBxlEKpB/wrKEFGuckawy2mwC4MfaX8BW92MyY/mCGboH7M1B DriFw2NMOSgdbRhJoZXPoE/4jXmKLmKhIRlAKGryOZMWwz6gDyfnzC6bdWWeLCq1AFB/ uoJRNtCs4BSks536GKGBtWQnq3dJXbDcRGWXByqwi7pFjnmzBhaqOoovUAwkTl2s5JcW U6vBzPHkZoTUenTm+FuTU2hcTyHu/RYKX5FfwzbfUU87azXxBG6aFCUh6WamRVjzuXgF 5nA02UA3BOIR9qxyp/vZytKG+vQNI2HXMxjVfYGcN6nTizwFekGSnJz0XGkFm+oBPqKX 39eg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1729594595; x=1730199395; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ncBC08IoBkP10ef5QDpG5SV+FPj/pwrW84Mb8BGJC6M=; b=PVcCtbZqNfp3u3Nw6alqBE7FAYXiQxJUJynN1PU+X/wokTJuoqVYptjPA5af9lKDxb weWvhkv/D17g96gvmbbh5RnCS5MRJyuSQKNGHfxUopJCyzB12Lxd3ErRaRB64ppU8Nif wPas0WFrJQmVvfqc7smC4Z+y6EbYtU9AtwkV8/0DXAz3oXeB1UhLc0q4bzoaaIghA9Qv UA0U/sAvopsA7bqx6KcdisuXoKvfeBForEpNO2aewE3mr/5HChZsjKETeFTAMyKAhQAK Uc3MIYVkiZJ3n3+RtOTUgNSCcuicepwPq3wnvPXGZzxbD4LcIOnhvSlIeDRKBZgTLb3R beuA== X-Gm-Message-State: AOJu0Yx3qlSVxerQXM5gtTTJy29qXKAtBh5AQuZftKK0ArZ0DJxthUDk tGoAmTUyq63Ekymv43Ke61bwxygkCeCRrW90RBbisHrXTYp48w7v4R7TYiAb4ZU= X-Received: by 2002:a17:906:c10b:b0:a9a:6bd:95dc with SMTP id a640c23a62f3a-a9aad3715ccmr189373366b.46.1729594594783; Tue, 22 Oct 2024 03:56:34 -0700 (PDT) Received: from draig.lan ([85.9.250.243]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a9a91559951sm321731866b.106.2024.10.22.03.56.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 22 Oct 2024 03:56:28 -0700 (PDT) Received: from draig.lan (localhost [IPv6:::1]) by draig.lan (Postfix) with ESMTP id 2565B5FC34; Tue, 22 Oct 2024 11:56:16 +0100 (BST) From: =?utf-8?q?Alex_Benn=C3=A9e?= To: qemu-devel@nongnu.org Cc: Beraldo Leal , Laurent Vivier , Wainer dos Santos Moschetta , Mahmoud Mandour , Jiaxun Yang , =?utf-8?q?Alex_Benn=C3=A9e?= , Yanan Wang , Thomas Huth , John Snow , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , qemu-arm@nongnu.org, =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , Eduardo Habkost , devel@lists.libvirt.org, Cleber Rosa , kvm@vger.kernel.org, =?utf-8?q?Philippe_Mat?= =?utf-8?q?hieu-Daud=C3=A9?= , Alexandre Iooss , Peter Maydell , Richard Henderson , Riku Voipio , Zhao Liu , Marcelo Tosatti , "Edgar E. Iglesias" , Marcel Apfelbaum , Pierrick Bouvier , Paolo Bonzini Subject: [PATCH v2 17/20] plugins: add ability to register a GDB triggered callback Date: Tue, 22 Oct 2024 11:56:11 +0100 Message-Id: <20241022105614.839199-18-alex.bennee@linaro.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20241022105614.839199-1-alex.bennee@linaro.org> References: <20241022105614.839199-1-alex.bennee@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::634; envelope-from=alex.bennee@linaro.org; helo=mail-ej1-x634.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: qemu-devel-bounces+patch=linaro.org@nongnu.org Now gdbstub has gained the ability to extend its command tables we can allow it to trigger plugin callbacks. This is probably most useful for QEMU developers debugging plugins themselves but might be useful for other stuff. Trigger the callback by sending: maintenance packet Qqemu.plugin_cb I've extended the memory plugin to report on the packet. Signed-off-by: Alex Bennée --- include/qemu/plugin-event.h | 1 + include/qemu/qemu-plugin.h | 16 ++++++++++++++++ plugins/plugin.h | 9 +++++++++ plugins/api.c | 18 ++++++++++++++++++ plugins/core.c | 37 ++++++++++++++++++++++++++++++++++++ tests/tcg/plugins/mem.c | 11 +++++++++-- plugins/qemu-plugins.symbols | 1 + 7 files changed, 91 insertions(+), 2 deletions(-) diff --git a/include/qemu/plugin-event.h b/include/qemu/plugin-event.h index 7056d8427b..d9aa56cf4f 100644 --- a/include/qemu/plugin-event.h +++ b/include/qemu/plugin-event.h @@ -20,6 +20,7 @@ enum qemu_plugin_event { QEMU_PLUGIN_EV_VCPU_SYSCALL_RET, QEMU_PLUGIN_EV_FLUSH, QEMU_PLUGIN_EV_ATEXIT, + QEMU_PLUGIN_EV_GDBSTUB, QEMU_PLUGIN_EV_MAX, /* total number of plugin events we support */ }; diff --git a/include/qemu/qemu-plugin.h b/include/qemu/qemu-plugin.h index 622c9a0232..99c3b365aa 100644 --- a/include/qemu/qemu-plugin.h +++ b/include/qemu/qemu-plugin.h @@ -802,6 +802,22 @@ QEMU_PLUGIN_API void qemu_plugin_register_atexit_cb(qemu_plugin_id_t id, qemu_plugin_udata_cb_t cb, void *userdata); + +/** + * qemu_plugin_register_gdb_cb() - register a gdb callback + * @id: plugin ID + * @cb: callback + * @userdata: user data for callback + * + * When using the gdbstub to debug a guest you can send a command that + * will trigger the callback. This is useful if you want the plugin to + * print out collected state at particular points when debugging a + * program. + */ +QEMU_PLUGIN_API +void qemu_plugin_register_gdb_cb(qemu_plugin_id_t id, + qemu_plugin_udata_cb_t cb, void *userdata); + /* returns how many vcpus were started at this point */ int qemu_plugin_num_vcpus(void); diff --git a/plugins/plugin.h b/plugins/plugin.h index 30e2299a54..f37667c9fb 100644 --- a/plugins/plugin.h +++ b/plugins/plugin.h @@ -118,4 +118,13 @@ struct qemu_plugin_scoreboard *plugin_scoreboard_new(size_t element_size); void plugin_scoreboard_free(struct qemu_plugin_scoreboard *score); +/** + * plugin_register_gdbstub_commands - register gdbstub commands + * + * This should only be called once to register gdbstub commands so we + * can trigger callbacks if needed. + */ +void plugin_register_gdbstub_commands(void); + + #endif /* PLUGIN_H */ diff --git a/plugins/api.c b/plugins/api.c index 24ea64e2de..62141616f4 100644 --- a/plugins/api.c +++ b/plugins/api.c @@ -681,3 +681,21 @@ void qemu_plugin_update_ns(const void *handle, int64_t new_time) } #endif } + +/* + * gdbstub hooks + */ + +static bool gdbstub_callbacks; + +void qemu_plugin_register_gdb_cb(qemu_plugin_id_t id, + qemu_plugin_udata_cb_t cb, + void *udata) +{ + plugin_register_cb_udata(id, QEMU_PLUGIN_EV_GDBSTUB, cb, udata); + + if (!gdbstub_callbacks) { + plugin_register_gdbstub_commands(); + gdbstub_callbacks = true; + } +} diff --git a/plugins/core.c b/plugins/core.c index bb105e8e68..e7fce08799 100644 --- a/plugins/core.c +++ b/plugins/core.c @@ -23,6 +23,7 @@ #include "qemu/xxhash.h" #include "qemu/rcu.h" #include "hw/core/cpu.h" +#include "gdbstub/commands.h" #include "exec/exec-all.h" #include "exec/tb-flush.h" @@ -147,6 +148,7 @@ static void plugin_cb__udata(enum qemu_plugin_event ev) switch (ev) { case QEMU_PLUGIN_EV_ATEXIT: + case QEMU_PLUGIN_EV_GDBSTUB: QLIST_FOREACH_SAFE_RCU(cb, &plugin.cb_lists[ev], entry, next) { qemu_plugin_udata_cb_t func = cb->f.udata; @@ -768,3 +770,38 @@ void plugin_scoreboard_free(struct qemu_plugin_scoreboard *score) g_array_free(score->data, TRUE); g_free(score); } + +/* + * gdbstub integration + */ + +static void handle_plugin_cb(GArray *params, void *user_ctx) +{ + plugin_cb__udata(QEMU_PLUGIN_EV_GDBSTUB); + gdb_put_packet("OK"); +} + +enum Command { + PluginCallback, + NUM_GDB_CMDS +}; + +static const GdbCmdParseEntry cmd_handler_table[NUM_GDB_CMDS] = { + [PluginCallback] = { + .handler = handle_plugin_cb, + .cmd_startswith = true, + .cmd = "qemu.plugin_cb", + .schema = "s?", + }, +}; + +void plugin_register_gdbstub_commands(void) +{ + g_autoptr(GPtrArray) set_table = g_ptr_array_new(); + + for (int i = 0; i < NUM_GDB_CMDS; i++) { + g_ptr_array_add(set_table, (gpointer) &cmd_handler_table[PluginCallback]); + } + + gdb_extend_set_table(set_table); +} diff --git a/tests/tcg/plugins/mem.c b/tests/tcg/plugins/mem.c index b0fa8a9f27..d416d92fc2 100644 --- a/tests/tcg/plugins/mem.c +++ b/tests/tcg/plugins/mem.c @@ -75,8 +75,7 @@ static gint addr_order(gconstpointer a, gconstpointer b) return na->region_address > nb->region_address ? 1 : -1; } - -static void plugin_exit(qemu_plugin_id_t id, void *p) +static void plugin_report(qemu_plugin_id_t id, void *p) { g_autoptr(GString) out = g_string_new(""); @@ -90,6 +89,7 @@ static void plugin_exit(qemu_plugin_id_t id, void *p) } qemu_plugin_outs(out->str); + g_mutex_lock(&lock); if (do_region_summary) { GList *counts = g_hash_table_get_values(regions); @@ -114,6 +114,12 @@ static void plugin_exit(qemu_plugin_id_t id, void *p) qemu_plugin_outs(out->str); } + g_mutex_unlock(&lock); +} + +static void plugin_exit(qemu_plugin_id_t id, void *p) +{ + plugin_report(id, p); qemu_plugin_scoreboard_free(counts); } @@ -400,6 +406,7 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, counts, CPUCount, mem_count); io_count = qemu_plugin_scoreboard_u64_in_struct(counts, CPUCount, io_count); qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans); + qemu_plugin_register_gdb_cb(id, plugin_report, NULL); qemu_plugin_register_atexit_cb(id, plugin_exit, NULL); return 0; } diff --git a/plugins/qemu-plugins.symbols b/plugins/qemu-plugins.symbols index 032661f9ea..d272e8e0f3 100644 --- a/plugins/qemu-plugins.symbols +++ b/plugins/qemu-plugins.symbols @@ -25,6 +25,7 @@ qemu_plugin_read_register; qemu_plugin_register_atexit_cb; qemu_plugin_register_flush_cb; + qemu_plugin_register_gdb_cb; qemu_plugin_register_vcpu_exit_cb; qemu_plugin_register_vcpu_idle_cb; qemu_plugin_register_vcpu_init_cb;