1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 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));
}
}
|