diff options
Diffstat (limited to 'plugins')
| -rw-r--r-- | plugins/api-system.c | 131 | ||||
| -rw-r--r-- | plugins/api-user.c | 57 | ||||
| -rw-r--r-- | plugins/api.c | 171 | ||||
| -rw-r--r-- | plugins/core.c | 10 | ||||
| -rw-r--r-- | plugins/loader.c | 15 | ||||
| -rw-r--r-- | plugins/meson.build | 11 | ||||
| -rw-r--r-- | plugins/plugin.h | 7 | ||||
| -rw-r--r-- | plugins/system.c | 24 | ||||
| -rw-r--r-- | plugins/user.c | 19 |
9 files changed, 250 insertions, 195 deletions
diff --git a/plugins/api-system.c b/plugins/api-system.c new file mode 100644 index 0000000000..cc190b167e --- /dev/null +++ b/plugins/api-system.c @@ -0,0 +1,131 @@ +/* + * QEMU Plugin API - System specific implementations + * + * This provides the APIs that have a specific system implementation + * or are only relevant to system-mode. + * + * Copyright (C) 2017, Emilio G. Cota <cota@braap.org> + * Copyright (C) 2019-2025, Linaro + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/main-loop.h" +#include "qapi/error.h" +#include "migration/blocker.h" +#include "hw/boards.h" +#include "qemu/plugin-memory.h" +#include "qemu/plugin.h" + +/* + * In system mode we cannot trace the binary being executed so the + * helpers all return NULL/0. + */ +const char *qemu_plugin_path_to_binary(void) +{ + return NULL; +} + +uint64_t qemu_plugin_start_code(void) +{ + return 0; +} + +uint64_t qemu_plugin_end_code(void) +{ + return 0; +} + +uint64_t qemu_plugin_entry_code(void) +{ + return 0; +} + +/* + * Virtual Memory queries + */ + +static __thread struct qemu_plugin_hwaddr hwaddr_info; + +struct qemu_plugin_hwaddr *qemu_plugin_get_hwaddr(qemu_plugin_meminfo_t info, + uint64_t vaddr) +{ + CPUState *cpu = current_cpu; + unsigned int mmu_idx = get_mmuidx(info); + enum qemu_plugin_mem_rw rw = get_plugin_meminfo_rw(info); + hwaddr_info.is_store = (rw & QEMU_PLUGIN_MEM_W) != 0; + + assert(mmu_idx < NB_MMU_MODES); + + if (!tlb_plugin_lookup(cpu, vaddr, mmu_idx, + hwaddr_info.is_store, &hwaddr_info)) { + error_report("invalid use of qemu_plugin_get_hwaddr"); + return NULL; + } + + return &hwaddr_info; +} + +bool qemu_plugin_hwaddr_is_io(const struct qemu_plugin_hwaddr *haddr) +{ + return haddr->is_io; +} + +uint64_t qemu_plugin_hwaddr_phys_addr(const struct qemu_plugin_hwaddr *haddr) +{ + if (haddr) { + return haddr->phys_addr; + } + return 0; +} + +const char *qemu_plugin_hwaddr_device_name(const struct qemu_plugin_hwaddr *h) +{ + if (h && h->is_io) { + MemoryRegion *mr = h->mr; + if (!mr->name) { + unsigned maddr = (uintptr_t)mr; + g_autofree char *temp = g_strdup_printf("anon%08x", maddr); + return g_intern_string(temp); + } else { + return g_intern_string(mr->name); + } + } else { + return g_intern_static_string("RAM"); + } +} + +/* + * Time control + */ +static bool has_control; +static Error *migration_blocker; + +const void *qemu_plugin_request_time_control(void) +{ + if (!has_control) { + has_control = true; + error_setg(&migration_blocker, + "TCG plugin time control does not support migration"); + migrate_add_blocker(&migration_blocker, NULL); + return &has_control; + } + return NULL; +} + +static void advance_virtual_time__async(CPUState *cpu, run_on_cpu_data data) +{ + int64_t new_time = data.host_ulong; + qemu_clock_advance_virtual_time(new_time); +} + +void qemu_plugin_update_ns(const void *handle, int64_t new_time) +{ + if (handle == &has_control) { + /* Need to execute out of cpu_exec, so bql can be locked. */ + async_run_on_cpu(current_cpu, + advance_virtual_time__async, + RUN_ON_CPU_HOST_ULONG(new_time)); + } +} diff --git a/plugins/api-user.c b/plugins/api-user.c new file mode 100644 index 0000000000..28704a89e8 --- /dev/null +++ b/plugins/api-user.c @@ -0,0 +1,57 @@ +/* + * QEMU Plugin API - user-mode only implementations + * + * This provides the APIs that have a user-mode specific + * implementations or are only relevant to user-mode. + * + * Copyright (C) 2017, Emilio G. Cota <cota@braap.org> + * Copyright (C) 2019-2025, Linaro + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/plugin.h" +#include "exec/log.h" + +/* + * Virtual Memory queries - these are all NOPs for user-mode which + * only ever has visibility of virtual addresses. + */ + +struct qemu_plugin_hwaddr *qemu_plugin_get_hwaddr(qemu_plugin_meminfo_t info, + uint64_t vaddr) +{ + return NULL; +} + +bool qemu_plugin_hwaddr_is_io(const struct qemu_plugin_hwaddr *haddr) +{ + return false; +} + +uint64_t qemu_plugin_hwaddr_phys_addr(const struct qemu_plugin_hwaddr *haddr) +{ + return 0; +} + +const char *qemu_plugin_hwaddr_device_name(const struct qemu_plugin_hwaddr *h) +{ + return g_intern_static_string("Invalid"); +} + +/* + * Time control - for user mode the only real time is wall clock time + * so realistically all you can do in user mode is slow down execution + * which doesn't require the ability to mess with the clock. + */ + +const void *qemu_plugin_request_time_control(void) +{ + return NULL; +} + +void qemu_plugin_update_ns(const void *handle, int64_t new_time) +{ + qemu_log_mask(LOG_UNIMP, "user-mode can't control time"); +} diff --git a/plugins/api.c b/plugins/api.c index cf8cdf076a..604ce06802 100644 --- a/plugins/api.c +++ b/plugins/api.c @@ -39,26 +39,13 @@ #include "qemu/main-loop.h" #include "qemu/plugin.h" #include "qemu/log.h" -#include "qemu/timer.h" #include "tcg/tcg.h" -#include "exec/exec-all.h" #include "exec/gdbstub.h" +#include "exec/target_page.h" #include "exec/translation-block.h" #include "exec/translator.h" #include "disas/disas.h" #include "plugin.h" -#ifndef CONFIG_USER_ONLY -#include "qapi/error.h" -#include "migration/blocker.h" -#include "exec/ram_addr.h" -#include "qemu/plugin-memory.h" -#include "hw/boards.h" -#else -#include "qemu.h" -#ifdef CONFIG_LINUX -#include "loader.h" -#endif -#endif /* Uninstall and Reset handlers */ @@ -287,7 +274,7 @@ uint64_t qemu_plugin_insn_vaddr(const struct qemu_plugin_insn *insn) void *qemu_plugin_insn_haddr(const struct qemu_plugin_insn *insn) { const DisasContextBase *db = tcg_ctx->plugin_db; - vaddr page0_last = db->pc_first | ~TARGET_PAGE_MASK; + vaddr page0_last = db->pc_first | ~qemu_target_page_mask(); if (db->fake_insn) { return NULL; @@ -385,76 +372,6 @@ qemu_plugin_mem_value qemu_plugin_mem_get_value(qemu_plugin_meminfo_t info) return value; } -/* - * Virtual Memory queries - */ - -#ifdef CONFIG_SOFTMMU -static __thread struct qemu_plugin_hwaddr hwaddr_info; -#endif - -struct qemu_plugin_hwaddr *qemu_plugin_get_hwaddr(qemu_plugin_meminfo_t info, - uint64_t vaddr) -{ -#ifdef CONFIG_SOFTMMU - CPUState *cpu = current_cpu; - unsigned int mmu_idx = get_mmuidx(info); - enum qemu_plugin_mem_rw rw = get_plugin_meminfo_rw(info); - hwaddr_info.is_store = (rw & QEMU_PLUGIN_MEM_W) != 0; - - assert(mmu_idx < NB_MMU_MODES); - - if (!tlb_plugin_lookup(cpu, vaddr, mmu_idx, - hwaddr_info.is_store, &hwaddr_info)) { - error_report("invalid use of qemu_plugin_get_hwaddr"); - return NULL; - } - - return &hwaddr_info; -#else - return NULL; -#endif -} - -bool qemu_plugin_hwaddr_is_io(const struct qemu_plugin_hwaddr *haddr) -{ -#ifdef CONFIG_SOFTMMU - return haddr->is_io; -#else - return false; -#endif -} - -uint64_t qemu_plugin_hwaddr_phys_addr(const struct qemu_plugin_hwaddr *haddr) -{ -#ifdef CONFIG_SOFTMMU - if (haddr) { - return haddr->phys_addr; - } -#endif - return 0; -} - -const char *qemu_plugin_hwaddr_device_name(const struct qemu_plugin_hwaddr *h) -{ -#ifdef CONFIG_SOFTMMU - if (h && h->is_io) { - MemoryRegion *mr = h->mr; - if (!mr->name) { - unsigned maddr = (uintptr_t)mr; - g_autofree char *temp = g_strdup_printf("anon%08x", maddr); - return g_intern_string(temp); - } else { - return g_intern_string(mr->name); - } - } else { - return g_intern_static_string("RAM"); - } -#else - return g_intern_static_string("Invalid"); -#endif -} - int qemu_plugin_num_vcpus(void) { return plugin_num_vcpus(); @@ -474,49 +391,6 @@ bool qemu_plugin_bool_parse(const char *name, const char *value, bool *ret) } /* - * Binary path, start and end locations - */ -const char *qemu_plugin_path_to_binary(void) -{ - char *path = NULL; -#ifdef CONFIG_USER_ONLY - TaskState *ts = get_task_state(current_cpu); - path = g_strdup(ts->bprm->filename); -#endif - return path; -} - -uint64_t qemu_plugin_start_code(void) -{ - uint64_t start = 0; -#ifdef CONFIG_USER_ONLY - TaskState *ts = get_task_state(current_cpu); - start = ts->info->start_code; -#endif - return start; -} - -uint64_t qemu_plugin_end_code(void) -{ - uint64_t end = 0; -#ifdef CONFIG_USER_ONLY - TaskState *ts = get_task_state(current_cpu); - end = ts->info->end_code; -#endif - return end; -} - -uint64_t qemu_plugin_entry_code(void) -{ - uint64_t entry = 0; -#ifdef CONFIG_USER_ONLY - TaskState *ts = get_task_state(current_cpu); - entry = ts->info->entry; -#endif - return entry; -} - -/* * Create register handles. * * We need to create a handle for each register so the plugin @@ -641,44 +515,3 @@ uint64_t qemu_plugin_u64_sum(qemu_plugin_u64 entry) return total; } -/* - * Time control - */ -static bool has_control; -#ifdef CONFIG_SOFTMMU -static Error *migration_blocker; -#endif - -const void *qemu_plugin_request_time_control(void) -{ - if (!has_control) { - has_control = true; -#ifdef CONFIG_SOFTMMU - error_setg(&migration_blocker, - "TCG plugin time control does not support migration"); - migrate_add_blocker(&migration_blocker, NULL); -#endif - return &has_control; - } - return NULL; -} - -#ifdef CONFIG_SOFTMMU -static void advance_virtual_time__async(CPUState *cpu, run_on_cpu_data data) -{ - int64_t new_time = data.host_ulong; - qemu_clock_advance_virtual_time(new_time); -} -#endif - -void qemu_plugin_update_ns(const void *handle, int64_t new_time) -{ -#ifdef CONFIG_SOFTMMU - if (handle == &has_control) { - /* Need to execute out of cpu_exec, so bql can be locked. */ - async_run_on_cpu(current_cpu, - advance_virtual_time__async, - RUN_ON_CPU_HOST_ULONG(new_time)); - } -#endif -} diff --git a/plugins/core.c b/plugins/core.c index bb105e8e68..eb9281fe54 100644 --- a/plugins/core.c +++ b/plugins/core.c @@ -12,22 +12,14 @@ * SPDX-License-Identifier: GPL-2.0-or-later */ #include "qemu/osdep.h" -#include "qemu/error-report.h" -#include "qemu/config-file.h" -#include "qapi/error.h" #include "qemu/lockable.h" #include "qemu/option.h" #include "qemu/plugin.h" #include "qemu/queue.h" #include "qemu/rcu_queue.h" -#include "qemu/xxhash.h" #include "qemu/rcu.h" -#include "hw/core/cpu.h" - -#include "exec/exec-all.h" #include "exec/tb-flush.h" -#include "tcg/tcg.h" -#include "tcg/tcg-op.h" +#include "tcg/tcg-op-common.h" #include "plugin.h" struct qemu_plugin_cb { diff --git a/plugins/loader.c b/plugins/loader.c index 99686b5466..7523d554f0 100644 --- a/plugins/loader.c +++ b/plugins/loader.c @@ -31,9 +31,6 @@ #include "qemu/memalign.h" #include "hw/core/cpu.h" #include "exec/tb-flush.h" -#ifndef CONFIG_USER_ONLY -#include "hw/boards.h" -#endif #include "plugin.h" @@ -297,17 +294,11 @@ int qemu_plugin_load_list(QemuPluginList *head, Error **errp) struct qemu_plugin_desc *desc, *next; g_autofree qemu_info_t *info = g_new0(qemu_info_t, 1); - info->target_name = TARGET_NAME; + info->target_name = target_name(); info->version.min = QEMU_PLUGIN_MIN_VERSION; info->version.cur = QEMU_PLUGIN_VERSION; -#ifndef CONFIG_USER_ONLY - MachineState *ms = MACHINE(qdev_get_machine()); - info->system_emulation = true; - info->system.smp_vcpus = ms->smp.cpus; - info->system.max_vcpus = ms->smp.max_cpus; -#else - info->system_emulation = false; -#endif + + qemu_plugin_fillin_mode_info(info); QTAILQ_FOREACH_SAFE(desc, head, entry, next) { int err; diff --git a/plugins/meson.build b/plugins/meson.build index d60be2a4d6..3be8245a69 100644 --- a/plugins/meson.build +++ b/plugins/meson.build @@ -57,8 +57,9 @@ if host_os == 'windows' command: dlltool_cmd ) endif -specific_ss.add(files( - 'loader.c', - 'core.c', - 'api.c', -)) + +user_ss.add(files('user.c', 'api-user.c')) +system_ss.add(files('system.c', 'api-system.c')) + +common_ss.add(files('loader.c', 'api.c', 'core.c')) + diff --git a/plugins/plugin.h b/plugins/plugin.h index 30e2299a54..6fbc443b96 100644 --- a/plugins/plugin.h +++ b/plugins/plugin.h @@ -13,6 +13,7 @@ #define PLUGIN_H #include <gmodule.h> +#include "qemu/queue.h" #include "qemu/qht.h" #define QEMU_PLUGIN_MIN_VERSION 2 @@ -118,4 +119,10 @@ struct qemu_plugin_scoreboard *plugin_scoreboard_new(size_t element_size); void plugin_scoreboard_free(struct qemu_plugin_scoreboard *score); +/** + * qemu_plugin_fillin_mode_info() - populate mode specific info + * info: pointer to qemu_info_t structure + */ +void qemu_plugin_fillin_mode_info(qemu_info_t *info); + #endif /* PLUGIN_H */ diff --git a/plugins/system.c b/plugins/system.c new file mode 100644 index 0000000000..b3ecc33ba5 --- /dev/null +++ b/plugins/system.c @@ -0,0 +1,24 @@ +/* + * QEMU Plugin system-emulation helpers + * + * Helpers that are specific to system emulation. + * + * Copyright (C) 2017, Emilio G. Cota <cota@braap.org> + * Copyright (C) 2019-2025, Linaro + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/plugin.h" +#include "hw/boards.h" + +#include "plugin.h" + +void qemu_plugin_fillin_mode_info(qemu_info_t *info) +{ + MachineState *ms = MACHINE(qdev_get_machine()); + info->system_emulation = true; + info->system.smp_vcpus = ms->smp.cpus; + info->system.max_vcpus = ms->smp.max_cpus; +} diff --git a/plugins/user.c b/plugins/user.c new file mode 100644 index 0000000000..250d542502 --- /dev/null +++ b/plugins/user.c @@ -0,0 +1,19 @@ +/* + * QEMU Plugin user-mode helpers + * + * Helpers that are specific to user-mode. + * + * Copyright (C) 2017, Emilio G. Cota <cota@braap.org> + * Copyright (C) 2019-2025, Linaro + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/plugin.h" +#include "plugin.h" + +void qemu_plugin_fillin_mode_info(qemu_info_t *info) +{ + info->system_emulation = false; +} |