aboutsummaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorRowan Hart <rowanbhart@gmail.com>2025-06-27 12:25:05 +0100
committerAlex Bennée <alex.bennee@linaro.org>2025-07-02 10:09:48 +0100
commit30424b8d4299d7dc50f90a6909e41a3c7ce94ccb (patch)
tree415feb0f071ce35d29e31e89f8b5570a8c759e18 /plugins
parentf00373b895da830ef6d0ee9a518e336e8252a4a3 (diff)
downloadqemu-30424b8d4299d7dc50f90a6909e41a3c7ce94ccb.zip
qemu-30424b8d4299d7dc50f90a6909e41a3c7ce94ccb.tar.gz
qemu-30424b8d4299d7dc50f90a6909e41a3c7ce94ccb.tar.bz2
plugins: Add memory hardware address read/write API
This patch adds functions to the plugins API to allow plugins to read and write memory via hardware addresses. The functions use the current address space of the current CPU in order to avoid exposing address space information to users. A later patch may want to add a function to permit a specified address space, for example to facilitate architecture-specific plugins that want to operate on them, for example reading ARM secure memory. Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Signed-off-by: Rowan Hart <rowanbhart@gmail.com> Message-ID: <20250624175351.440780-6-rowanbhart@gmail.com> Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Message-ID: <20250627112512.1880708-10-alex.bennee@linaro.org>
Diffstat (limited to 'plugins')
-rw-r--r--plugins/api.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/plugins/api.c b/plugins/api.c
index 1f64a9e..eac04cc 100644
--- a/plugins/api.c
+++ b/plugins/api.c
@@ -39,6 +39,7 @@
#include "qemu/main-loop.h"
#include "qemu/plugin.h"
#include "qemu/log.h"
+#include "system/memory.h"
#include "tcg/tcg.h"
#include "exec/gdbstub.h"
#include "exec/target_page.h"
@@ -494,6 +495,102 @@ bool qemu_plugin_write_memory_vaddr(uint64_t addr, GByteArray *data)
return true;
}
+enum qemu_plugin_hwaddr_operation_result
+qemu_plugin_read_memory_hwaddr(hwaddr addr, GByteArray *data, size_t len)
+{
+#ifdef CONFIG_SOFTMMU
+ if (len == 0) {
+ return QEMU_PLUGIN_HWADDR_OPERATION_ERROR;
+ }
+
+ g_assert(current_cpu);
+
+
+ int as_idx = cpu_asidx_from_attrs(current_cpu, MEMTXATTRS_UNSPECIFIED);
+ AddressSpace *as = cpu_get_address_space(current_cpu, as_idx);
+
+ if (as == NULL) {
+ return QEMU_PLUGIN_HWADDR_OPERATION_INVALID_ADDRESS_SPACE;
+ }
+
+ g_byte_array_set_size(data, len);
+ MemTxResult res = address_space_rw(as, addr,
+ MEMTXATTRS_UNSPECIFIED, data->data,
+ data->len, false);
+
+ switch (res) {
+ case MEMTX_OK:
+ return QEMU_PLUGIN_HWADDR_OPERATION_OK;
+ case MEMTX_ERROR:
+ return QEMU_PLUGIN_HWADDR_OPERATION_DEVICE_ERROR;
+ case MEMTX_DECODE_ERROR:
+ return QEMU_PLUGIN_HWADDR_OPERATION_INVALID_ADDRESS;
+ case MEMTX_ACCESS_ERROR:
+ return QEMU_PLUGIN_HWADDR_OPERATION_ACCESS_DENIED;
+ default:
+ return QEMU_PLUGIN_HWADDR_OPERATION_ERROR;
+ }
+#else
+ return QEMU_PLUGIN_HWADDR_OPERATION_ERROR;
+#endif
+}
+
+enum qemu_plugin_hwaddr_operation_result
+qemu_plugin_write_memory_hwaddr(hwaddr addr, GByteArray *data)
+{
+#ifdef CONFIG_SOFTMMU
+ if (data->len == 0) {
+ return QEMU_PLUGIN_HWADDR_OPERATION_ERROR;
+ }
+
+ g_assert(current_cpu);
+
+ int as_idx = cpu_asidx_from_attrs(current_cpu, MEMTXATTRS_UNSPECIFIED);
+ AddressSpace *as = cpu_get_address_space(current_cpu, as_idx);
+
+ if (as == NULL) {
+ return QEMU_PLUGIN_HWADDR_OPERATION_INVALID_ADDRESS_SPACE;
+ }
+
+ MemTxResult res = address_space_rw(as, addr,
+ MEMTXATTRS_UNSPECIFIED, data->data,
+ data->len, true);
+ switch (res) {
+ case MEMTX_OK:
+ return QEMU_PLUGIN_HWADDR_OPERATION_OK;
+ case MEMTX_ERROR:
+ return QEMU_PLUGIN_HWADDR_OPERATION_DEVICE_ERROR;
+ case MEMTX_DECODE_ERROR:
+ return QEMU_PLUGIN_HWADDR_OPERATION_INVALID_ADDRESS;
+ case MEMTX_ACCESS_ERROR:
+ return QEMU_PLUGIN_HWADDR_OPERATION_ACCESS_DENIED;
+ default:
+ return QEMU_PLUGIN_HWADDR_OPERATION_ERROR;
+ }
+#else
+ return QEMU_PLUGIN_HWADDR_OPERATION_ERROR;
+#endif
+}
+
+bool qemu_plugin_translate_vaddr(uint64_t vaddr, uint64_t *hwaddr)
+{
+#ifdef CONFIG_SOFTMMU
+ g_assert(current_cpu);
+
+ uint64_t res = cpu_get_phys_page_debug(current_cpu, vaddr);
+
+ if (res == (uint64_t)-1) {
+ return false;
+ }
+
+ *hwaddr = res | (vaddr & ~TARGET_PAGE_MASK);
+
+ return true;
+#else
+ return false;
+#endif
+}
+
struct qemu_plugin_scoreboard *qemu_plugin_scoreboard_new(size_t element_size)
{
return plugin_scoreboard_new(element_size);