1 /* 2 * QEMU Plugin API - System specific implementations 3 * 4 * This provides the APIs that have a specific system implementation 5 * or are only relevant to system-mode. 6 * 7 * Copyright (C) 2017, Emilio G. Cota <cota@braap.org> 8 * Copyright (C) 2019-2025, Linaro 9 * 10 * SPDX-License-Identifier: GPL-2.0-or-later 11 */ 12 13 #include "qemu/osdep.h" 14 #include "qemu/main-loop.h" 15 #include "qapi/error.h" 16 #include "migration/blocker.h" 17 #include "hw/boards.h" 18 #include "qemu/plugin-memory.h" 19 #include "qemu/plugin.h" 20 21 /* 22 * In system mode we cannot trace the binary being executed so the 23 * helpers all return NULL/0. 24 */ 25 const char *qemu_plugin_path_to_binary(void) 26 { 27 return NULL; 28 } 29 30 uint64_t qemu_plugin_start_code(void) 31 { 32 return 0; 33 } 34 35 uint64_t qemu_plugin_end_code(void) 36 { 37 return 0; 38 } 39 40 uint64_t qemu_plugin_entry_code(void) 41 { 42 return 0; 43 } 44 45 /* 46 * Virtual Memory queries 47 */ 48 49 static __thread struct qemu_plugin_hwaddr hwaddr_info; 50 51 struct qemu_plugin_hwaddr *qemu_plugin_get_hwaddr(qemu_plugin_meminfo_t info, 52 uint64_t vaddr) 53 { 54 CPUState *cpu = current_cpu; 55 unsigned int mmu_idx = get_mmuidx(info); 56 enum qemu_plugin_mem_rw rw = get_plugin_meminfo_rw(info); 57 hwaddr_info.is_store = (rw & QEMU_PLUGIN_MEM_W) != 0; 58 59 assert(mmu_idx < NB_MMU_MODES); 60 61 if (!tlb_plugin_lookup(cpu, vaddr, mmu_idx, 62 hwaddr_info.is_store, &hwaddr_info)) { 63 error_report("invalid use of qemu_plugin_get_hwaddr"); 64 return NULL; 65 } 66 67 return &hwaddr_info; 68 } 69 70 bool qemu_plugin_hwaddr_is_io(const struct qemu_plugin_hwaddr *haddr) 71 { 72 return haddr->is_io; 73 } 74 75 uint64_t qemu_plugin_hwaddr_phys_addr(const struct qemu_plugin_hwaddr *haddr) 76 { 77 if (haddr) { 78 return haddr->phys_addr; 79 } 80 return 0; 81 } 82 83 const char *qemu_plugin_hwaddr_device_name(const struct qemu_plugin_hwaddr *h) 84 { 85 if (h && h->is_io) { 86 MemoryRegion *mr = h->mr; 87 if (!mr->name) { 88 unsigned maddr = (uintptr_t)mr; 89 g_autofree char *temp = g_strdup_printf("anon%08x", maddr); 90 return g_intern_string(temp); 91 } else { 92 return g_intern_string(mr->name); 93 } 94 } else { 95 return g_intern_static_string("RAM"); 96 } 97 } 98 99 /* 100 * Time control 101 */ 102 static bool has_control; 103 static Error *migration_blocker; 104 105 const void *qemu_plugin_request_time_control(void) 106 { 107 if (!has_control) { 108 has_control = true; 109 error_setg(&migration_blocker, 110 "TCG plugin time control does not support migration"); 111 migrate_add_blocker(&migration_blocker, NULL); 112 return &has_control; 113 } 114 return NULL; 115 } 116 117 static void advance_virtual_time__async(CPUState *cpu, run_on_cpu_data data) 118 { 119 int64_t new_time = data.host_ulong; 120 qemu_clock_advance_virtual_time(new_time); 121 } 122 123 void qemu_plugin_update_ns(const void *handle, int64_t new_time) 124 { 125 if (handle == &has_control) { 126 /* Need to execute out of cpu_exec, so bql can be locked. */ 127 async_run_on_cpu(current_cpu, 128 advance_virtual_time__async, 129 RUN_ON_CPU_HOST_ULONG(new_time)); 130 } 131 } 132