1 /* 2 * QEMU Plugin API 3 * 4 * This provides the API that is available to the plugins to interact 5 * with QEMU. We have to be careful not to expose internal details of 6 * how QEMU works so we abstract out things like translation and 7 * instructions to anonymous data types: 8 * 9 * qemu_plugin_tb 10 * qemu_plugin_insn 11 * 12 * Which can then be passed back into the API to do additional things. 13 * As such all the public functions in here are exported in 14 * qemu-plugin.h. 15 * 16 * The general life-cycle of a plugin is: 17 * 18 * - plugin is loaded, public qemu_plugin_install called 19 * - the install func registers callbacks for events 20 * - usually an atexit_cb is registered to dump info at the end 21 * - when a registered event occurs the plugin is called 22 * - some events pass additional info 23 * - during translation the plugin can decide to instrument any 24 * instruction 25 * - when QEMU exits all the registered atexit callbacks are called 26 * 27 * Copyright (C) 2017, Emilio G. Cota <cota@braap.org> 28 * Copyright (C) 2019, Linaro 29 * 30 * License: GNU GPL, version 2 or later. 31 * See the COPYING file in the top-level directory. 32 * 33 * SPDX-License-Identifier: GPL-2.0-or-later 34 * 35 */ 36 37 #include "qemu/osdep.h" 38 #include "qemu/plugin.h" 39 #include "cpu.h" 40 #include "sysemu/sysemu.h" 41 #include "tcg/tcg.h" 42 #include "trace/mem-internal.h" /* mem_info macros */ 43 #include "plugin.h" 44 #ifndef CONFIG_USER_ONLY 45 #include "qemu/plugin-memory.h" 46 #include "hw/boards.h" 47 #endif 48 49 /* Uninstall and Reset handlers */ 50 51 void qemu_plugin_uninstall(qemu_plugin_id_t id, qemu_plugin_simple_cb_t cb) 52 { 53 plugin_reset_uninstall(id, cb, false); 54 } 55 56 void qemu_plugin_reset(qemu_plugin_id_t id, qemu_plugin_simple_cb_t cb) 57 { 58 plugin_reset_uninstall(id, cb, true); 59 } 60 61 /* 62 * Plugin Register Functions 63 * 64 * This allows the plugin to register callbacks for various events 65 * during the translation. 66 */ 67 68 void qemu_plugin_register_vcpu_init_cb(qemu_plugin_id_t id, 69 qemu_plugin_vcpu_simple_cb_t cb) 70 { 71 plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_INIT, cb); 72 } 73 74 void qemu_plugin_register_vcpu_exit_cb(qemu_plugin_id_t id, 75 qemu_plugin_vcpu_simple_cb_t cb) 76 { 77 plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_EXIT, cb); 78 } 79 80 void qemu_plugin_register_vcpu_tb_exec_cb(struct qemu_plugin_tb *tb, 81 qemu_plugin_vcpu_udata_cb_t cb, 82 enum qemu_plugin_cb_flags flags, 83 void *udata) 84 { 85 plugin_register_dyn_cb__udata(&tb->cbs[PLUGIN_CB_REGULAR], 86 cb, flags, udata); 87 } 88 89 void qemu_plugin_register_vcpu_tb_exec_inline(struct qemu_plugin_tb *tb, 90 enum qemu_plugin_op op, 91 void *ptr, uint64_t imm) 92 { 93 plugin_register_inline_op(&tb->cbs[PLUGIN_CB_INLINE], 0, op, ptr, imm); 94 } 95 96 void qemu_plugin_register_vcpu_insn_exec_cb(struct qemu_plugin_insn *insn, 97 qemu_plugin_vcpu_udata_cb_t cb, 98 enum qemu_plugin_cb_flags flags, 99 void *udata) 100 { 101 plugin_register_dyn_cb__udata(&insn->cbs[PLUGIN_CB_INSN][PLUGIN_CB_REGULAR], 102 cb, flags, udata); 103 } 104 105 void qemu_plugin_register_vcpu_insn_exec_inline(struct qemu_plugin_insn *insn, 106 enum qemu_plugin_op op, 107 void *ptr, uint64_t imm) 108 { 109 plugin_register_inline_op(&insn->cbs[PLUGIN_CB_INSN][PLUGIN_CB_INLINE], 110 0, op, ptr, imm); 111 } 112 113 114 115 void qemu_plugin_register_vcpu_mem_cb(struct qemu_plugin_insn *insn, 116 qemu_plugin_vcpu_mem_cb_t cb, 117 enum qemu_plugin_cb_flags flags, 118 enum qemu_plugin_mem_rw rw, 119 void *udata) 120 { 121 plugin_register_vcpu_mem_cb(&insn->cbs[PLUGIN_CB_MEM][PLUGIN_CB_REGULAR], 122 cb, flags, rw, udata); 123 } 124 125 void qemu_plugin_register_vcpu_mem_inline(struct qemu_plugin_insn *insn, 126 enum qemu_plugin_mem_rw rw, 127 enum qemu_plugin_op op, void *ptr, 128 uint64_t imm) 129 { 130 plugin_register_inline_op(&insn->cbs[PLUGIN_CB_MEM][PLUGIN_CB_INLINE], 131 rw, op, ptr, imm); 132 } 133 134 void qemu_plugin_register_vcpu_tb_trans_cb(qemu_plugin_id_t id, 135 qemu_plugin_vcpu_tb_trans_cb_t cb) 136 { 137 plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_TB_TRANS, cb); 138 } 139 140 void qemu_plugin_register_vcpu_syscall_cb(qemu_plugin_id_t id, 141 qemu_plugin_vcpu_syscall_cb_t cb) 142 { 143 plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_SYSCALL, cb); 144 } 145 146 void 147 qemu_plugin_register_vcpu_syscall_ret_cb(qemu_plugin_id_t id, 148 qemu_plugin_vcpu_syscall_ret_cb_t cb) 149 { 150 plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_SYSCALL_RET, cb); 151 } 152 153 /* 154 * Plugin Queries 155 * 156 * These are queries that the plugin can make to gauge information 157 * from our opaque data types. We do not want to leak internal details 158 * here just information useful to the plugin. 159 */ 160 161 /* 162 * Translation block information: 163 * 164 * A plugin can query the virtual address of the start of the block 165 * and the number of instructions in it. It can also get access to 166 * each translated instruction. 167 */ 168 169 size_t qemu_plugin_tb_n_insns(const struct qemu_plugin_tb *tb) 170 { 171 return tb->n; 172 } 173 174 uint64_t qemu_plugin_tb_vaddr(const struct qemu_plugin_tb *tb) 175 { 176 return tb->vaddr; 177 } 178 179 struct qemu_plugin_insn * 180 qemu_plugin_tb_get_insn(const struct qemu_plugin_tb *tb, size_t idx) 181 { 182 if (unlikely(idx >= tb->n)) { 183 return NULL; 184 } 185 return g_ptr_array_index(tb->insns, idx); 186 } 187 188 /* 189 * Instruction information 190 * 191 * These queries allow the plugin to retrieve information about each 192 * instruction being translated. 193 */ 194 195 const void *qemu_plugin_insn_data(const struct qemu_plugin_insn *insn) 196 { 197 return insn->data->data; 198 } 199 200 size_t qemu_plugin_insn_size(const struct qemu_plugin_insn *insn) 201 { 202 return insn->data->len; 203 } 204 205 uint64_t qemu_plugin_insn_vaddr(const struct qemu_plugin_insn *insn) 206 { 207 return insn->vaddr; 208 } 209 210 void *qemu_plugin_insn_haddr(const struct qemu_plugin_insn *insn) 211 { 212 return insn->haddr; 213 } 214 215 /* 216 * The memory queries allow the plugin to query information about a 217 * memory access. 218 */ 219 220 unsigned qemu_plugin_mem_size_shift(qemu_plugin_meminfo_t info) 221 { 222 return info & TRACE_MEM_SZ_SHIFT_MASK; 223 } 224 225 bool qemu_plugin_mem_is_sign_extended(qemu_plugin_meminfo_t info) 226 { 227 return !!(info & TRACE_MEM_SE); 228 } 229 230 bool qemu_plugin_mem_is_big_endian(qemu_plugin_meminfo_t info) 231 { 232 return !!(info & TRACE_MEM_BE); 233 } 234 235 bool qemu_plugin_mem_is_store(qemu_plugin_meminfo_t info) 236 { 237 return !!(info & TRACE_MEM_ST); 238 } 239 240 /* 241 * Virtual Memory queries 242 */ 243 244 #ifdef CONFIG_SOFTMMU 245 static __thread struct qemu_plugin_hwaddr hwaddr_info; 246 247 struct qemu_plugin_hwaddr *qemu_plugin_get_hwaddr(qemu_plugin_meminfo_t info, 248 uint64_t vaddr) 249 { 250 CPUState *cpu = current_cpu; 251 unsigned int mmu_idx = info >> TRACE_MEM_MMU_SHIFT; 252 hwaddr_info.is_store = info & TRACE_MEM_ST; 253 254 if (!tlb_plugin_lookup(cpu, vaddr, mmu_idx, 255 info & TRACE_MEM_ST, &hwaddr_info)) { 256 error_report("invalid use of qemu_plugin_get_hwaddr"); 257 return NULL; 258 } 259 260 return &hwaddr_info; 261 } 262 #else 263 struct qemu_plugin_hwaddr *qemu_plugin_get_hwaddr(qemu_plugin_meminfo_t info, 264 uint64_t vaddr) 265 { 266 return NULL; 267 } 268 #endif 269 270 bool qemu_plugin_hwaddr_is_io(struct qemu_plugin_hwaddr *hwaddr) 271 { 272 #ifdef CONFIG_SOFTMMU 273 return hwaddr->is_io; 274 #else 275 return false; 276 #endif 277 } 278 279 uint64_t qemu_plugin_hwaddr_device_offset(const struct qemu_plugin_hwaddr *haddr) 280 { 281 #ifdef CONFIG_SOFTMMU 282 if (haddr) { 283 if (!haddr->is_io) { 284 ram_addr_t ram_addr = qemu_ram_addr_from_host((void *) haddr->v.ram.hostaddr); 285 if (ram_addr == RAM_ADDR_INVALID) { 286 error_report("Bad ram pointer %"PRIx64"", haddr->v.ram.hostaddr); 287 abort(); 288 } 289 return ram_addr; 290 } else { 291 return haddr->v.io.offset; 292 } 293 } 294 #endif 295 return 0; 296 } 297 298 /* 299 * Queries to the number and potential maximum number of vCPUs there 300 * will be. This helps the plugin dimension per-vcpu arrays. 301 */ 302 303 #ifndef CONFIG_USER_ONLY 304 static MachineState * get_ms(void) 305 { 306 return MACHINE(qdev_get_machine()); 307 } 308 #endif 309 310 int qemu_plugin_n_vcpus(void) 311 { 312 #ifdef CONFIG_USER_ONLY 313 return -1; 314 #else 315 return get_ms()->smp.cpus; 316 #endif 317 } 318 319 int qemu_plugin_n_max_vcpus(void) 320 { 321 #ifdef CONFIG_USER_ONLY 322 return -1; 323 #else 324 return get_ms()->smp.max_cpus; 325 #endif 326 } 327