[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC PATCH 1/1] QEMU plugin interface extension
From: |
Florian Hauschild |
Subject: |
[RFC PATCH 1/1] QEMU plugin interface extension |
Date: |
Sat, 21 Aug 2021 11:45:27 +0200 |
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 <florian.hauschild@fs.ei.tum.de>
---
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);
+
+/**
+ * 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 address.
+ * @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_size,
char write);
+
+/**
+ * plugin_single_step() - Function to change single step behaviour from the
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 <cota@braap.org>
+ * Copyright (C) 2019, Linaro
+ *
+ * Copyright (C) 2021 Florian Hauschild <florian.hauschild@tum.de>
+ *
+ * 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_size,
char write)
+{
+ return cpu_memory_rw_debug(current_cpu, address, buffer, buf_size, write);
+
+}
+
+
+void plugin_flush_tb(void)
+{
+ async_safe_run_on_cpu(current_cpu, plugin_async_flush_tb, RUN_ON_CPU_NULL);
+}
+
+static int plugin_read_register(CPUState *cpu, GByteArray *buf, int reg)
+{
+ CPUClass *cc = 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 = g_byte_array_new();
+ uint64_t reg_ret = 0;
+ int ret_bytes = plugin_read_register(current_cpu, val, reg);
+ if (ret_bytes == 1) {
+ reg_ret = val->data[0];
+ }
+ if (ret_bytes == 2) {
+ reg_ret = *(uint16_t *) &(val->data[0]);
+ }
+ if (ret_bytes == 4) {
+ reg_ret = *(uint32_t *) &(val->data[0]);
+ }
+ if (ret_bytes == 8) {
+ reg_ret = *(uint64_t *) &(val->data[0]);
+ }
+ return reg_ret;
+}
+
+void write_reg(int reg, uint64_t val)
+{
+ CPUState *cpu = current_cpu;
+ CPUClass *cc = 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 = 1;
+
+ if (unlikely(executed == 1)) {
+ orig_value = singlestep;
+ executed = 2;
+ }
+
+ if (enable == 1) {
+ singlestep = 1;
+ } else {
+ singlestep = orig_value;
+ }
+
+ tb_flush(current_cpu);
+}
--
2.25.1
Re: [RFC PATCH 0/1] QEMU TCG plugin interface extensions, Alexandre IOOSS, 2021/08/21