From nobody Mon Feb 9 20:51:52 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=fs.ei.tum.de ARC-Seal: i=1; a=rsa-sha256; t=1629539261; cv=none; d=zohomail.com; s=zohoarc; b=J+6RhlStM8ZM+8hMPsYLc0F3tU8vP9qNJJzmdikXGek2Yx/6scFl3xGw7Ec0IW0f+Y7QWOKAQ69i0TZYH7pKIUBxXWlCZeGsiTFLk9KvSzlKuhCfXo2Wa+6dEjNS9uP2Fex+yuzfufH4qMk/Yfx/u4Y2hpGhbYNjFhbcYTB/BaA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1629539261; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=+6FLYj+lO+b0G3U4Y0LY0+7mi7lkTs3Ad3aclqUq/zU=; b=IVKd/OsYkUJMuY07hpnPPA6eWIIaVtoYqf3Xl5k5lpI2eW+GVt/UM0/h7Qd4yGw/ihmojA3p+/JXlEhij5HuDzYWdJiBjfWBO8L4L5ziB4DDx8/oukT0QXsZDrgvyNZSGu3xqj4XwRrGrNwsO82L8XCSgrLlvRigA6NjThnvl4I= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 162953926134753.078836224862584; Sat, 21 Aug 2021 02:47:41 -0700 (PDT) Received: from localhost ([::1]:58664 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mHNbI-00088x-4f for importer@patchew.org; Sat, 21 Aug 2021 05:47:40 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:36282) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mHNZi-0006kD-Dx for qemu-devel@nongnu.org; Sat, 21 Aug 2021 05:46:02 -0400 Received: from mail.fs.ei.tum.de ([2001:4ca0:22ff:10::7]:56053) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mHNZf-00034t-5S for qemu-devel@nongnu.org; Sat, 21 Aug 2021 05:46:02 -0400 Received: from Lucy.fritz.box (pc19f2504.dip0.t-ipconnect.de [193.159.37.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mail.fs.ei.tum.de (Postfix) with ESMTPSA id 20095118756E; Sat, 21 Aug 2021 11:45:49 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=fs.ei.tum.de; s=default; t=1629539156; bh=Ale4YdJ/3XGyRiYreWclPMN0cqwTrntQtHuld0rV+Pw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=A/fRb08ftvnF7UAolN8AY0LB39HNdG2NPOwX2Ctxawvj98KTOQH8v+EziuUQKI10C V9cEWtGwXOVY/f+MWsldMDxxq+AeZ8h684JmMWgth3byEu9pxSGyarnRZRnhSnNvRc wpSSlGJoOFprEooUKk0bQk1tY3LEng2honeMaMNM= From: Florian Hauschild To: qemu-devel@nongnu.org Cc: =?UTF-8?q?Alex=20Benn=C3=A9e?= , Alexandre Iooss , Mahmoud Mandour , Florian Hauschild Subject: [RFC PATCH 1/1] QEMU plugin interface extension Date: Sat, 21 Aug 2021 11:45:27 +0200 Message-Id: <20210821094527.491232-2-florian.hauschild@fs.ei.tum.de> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210821094527.491232-1-florian.hauschild@fs.ei.tum.de> References: <20210821094527.491232-1-florian.hauschild@fs.ei.tum.de> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2001:4ca0:22ff:10::7; envelope-from=florian.hauschild@fs.ei.tum.de; helo=mail.fs.ei.tum.de X-Spam_score_int: -19 X-Spam_score: -2.0 X-Spam_bar: -- X-Spam_report: (-2.0 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: pass (identity @fs.ei.tum.de) X-ZM-MESSAGEID: 1629539262973100001 Content-Type: text/plain; charset="utf-8" This extension covers functions: * to read and write guest memory * to read and write guest registers * to flush tb cache * to control single stepping of qemu from plugin These changes allow the user to * collect more information about the behaviour of the system * change the guest state with a plugin during execution * control cache of tcg * allow for precise instrumentation in execution flow Signed-off-by: Florian Hauschild --- include/qemu/qemu-plugin.h | 35 ++++++++++++ plugins/meson.build | 1 + plugins/readwriteextension.c | 106 +++++++++++++++++++++++++++++++++++ 3 files changed, 142 insertions(+) create mode 100644 plugins/readwriteextension.c diff --git a/include/qemu/qemu-plugin.h b/include/qemu/qemu-plugin.h index e6e815abc5..c7a0c5f379 100644 --- a/include/qemu/qemu-plugin.h +++ b/include/qemu/qemu-plugin.h @@ -577,4 +577,39 @@ int qemu_plugin_n_max_vcpus(void); */ void qemu_plugin_outs(const char *string); =20 + +/** + * read_reg() read a register + * @reg: Number of the register + * + * Returns the value of the register + */ +uint64_t read_reg(int reg); + +/** + * write_reg() - write to a register + * @reg: number of the register + * @val: value written to register + */ +void write_reg(int reg, uint64_t val); + +/** + * plugin_flush_tb() - Flush the tb cache + */ +void plugin_flush_tb(void); + +/** + * plugin_rw_memory_cpu() - Function to read from and write to a guest add= ress. + * @address: baseaddress of the memory section + * @buffer: buffer managed by caller the value should be written to + * @buf_size: size of the buffer and memory size read/written. + * @write: 1 if write, 0 if read + */ +int plugin_rw_memory_cpu(uint64_t address, uint8_t buffer[], size_t buf_si= ze, char write); + +/** + * plugin_single_step() - Function to change single step behaviour from th= e plugin. + */ +void plugin_single_step(int enable); + #endif /* QEMU_PLUGIN_API_H */ diff --git a/plugins/meson.build b/plugins/meson.build index e77723010e..b95cbab0b1 100644 --- a/plugins/meson.build +++ b/plugins/meson.build @@ -10,4 +10,5 @@ specific_ss.add(when: 'CONFIG_PLUGIN', if_true: [files( 'loader.c', 'core.c', 'api.c', + 'readwriteextension.c', ), declare_dependency(link_args: plugin_ldflags)]) diff --git a/plugins/readwriteextension.c b/plugins/readwriteextension.c new file mode 100644 index 0000000000..47460c396f --- /dev/null +++ b/plugins/readwriteextension.c @@ -0,0 +1,106 @@ +/** + * QEMU Plugin read write extension code + * + * This is the code that allows the plugin to read and write + * memory and registers and flush the tb cache. Also allows + * to set QEMU into singlestep mode from Plugin. + * + * Based on plugin interface: + * Copyright (C) 2017, Emilio G. Cota + * Copyright (C) 2019, Linaro + * + * Copyright (C) 2021 Florian Hauschild + * + * License: GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + + + +#include "qemu/osdep.h" +#include "qemu/plugin.h" +#include "hw/core/cpu.h" +#include "cpu.h" +#include "exec/exec-all.h" + +void plugin_async_flush_tb(CPUState *cpu, run_on_cpu_data arg); +void plugin_async_flush_tb(CPUState *cpu, run_on_cpu_data arg) +{ + g_assert(cpu_in_exclusive_context(cpu)); + tb_flush(cpu); +} + + + +int plugin_rw_memory_cpu(uint64_t address, uint8_t buffer[], size_t buf_si= ze, char write) +{ + return cpu_memory_rw_debug(current_cpu, address, buffer, buf_size, wri= te); + +} + + +void plugin_flush_tb(void) +{ + async_safe_run_on_cpu(current_cpu, plugin_async_flush_tb, RUN_ON_CPU_N= ULL); +} + +static int plugin_read_register(CPUState *cpu, GByteArray *buf, int reg) +{ + CPUClass *cc =3D CPU_GET_CLASS(cpu); + if (reg < cc->gdb_num_core_regs) { + return cc->gdb_read_register(cpu, buf, reg); + } + return 0; +} + +uint64_t read_reg(int reg) +{ + GByteArray *val =3D g_byte_array_new(); + uint64_t reg_ret =3D 0; + int ret_bytes =3D plugin_read_register(current_cpu, val, reg); + if (ret_bytes =3D=3D 1) { + reg_ret =3D val->data[0]; + } + if (ret_bytes =3D=3D 2) { + reg_ret =3D *(uint16_t *) &(val->data[0]); + } + if (ret_bytes =3D=3D 4) { + reg_ret =3D *(uint32_t *) &(val->data[0]); + } + if (ret_bytes =3D=3D 8) { + reg_ret =3D *(uint64_t *) &(val->data[0]); + } + return reg_ret; +} + +void write_reg(int reg, uint64_t val) +{ + CPUState *cpu =3D current_cpu; + CPUClass *cc =3D CPU_GET_CLASS(cpu); + + if (reg < cc->gdb_num_core_regs) { + cc->gdb_write_register(cpu, (uint8_t *) &val, reg); + } +} + +void plugin_single_step(int enable) +{ + /* singlestep is set in softmmu/vl.c*/ + static int orig_value; + static int executed =3D 1; + + if (unlikely(executed =3D=3D 1)) { + orig_value =3D singlestep; + executed =3D 2; + } + + if (enable =3D=3D 1) { + singlestep =3D 1; + } else { + singlestep =3D orig_value; + } + + tb_flush(current_cpu); +} --=20 2.25.1