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 "exec/exec-all.h" 43 #include "exec/ram_addr.h" 44 #include "disas/disas.h" 45 #include "plugin.h" 46 #ifndef CONFIG_USER_ONLY 47 #include "qemu/plugin-memory.h" 48 #include "hw/boards.h" 49 #endif 50 #include "trace/mem.h" 51 52 /* Uninstall and Reset handlers */ 53 54 void qemu_plugin_uninstall(qemu_plugin_id_t id, qemu_plugin_simple_cb_t cb) 55 { 56 plugin_reset_uninstall(id, cb, false); 57 } 58 59 void qemu_plugin_reset(qemu_plugin_id_t id, qemu_plugin_simple_cb_t cb) 60 { 61 plugin_reset_uninstall(id, cb, true); 62 } 63 64 /* 65 * Plugin Register Functions 66 * 67 * This allows the plugin to register callbacks for various events 68 * during the translation. 69 */ 70 71 void qemu_plugin_register_vcpu_init_cb(qemu_plugin_id_t id, 72 qemu_plugin_vcpu_simple_cb_t cb) 73 { 74 plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_INIT, cb); 75 } 76 77 void qemu_plugin_register_vcpu_exit_cb(qemu_plugin_id_t id, 78 qemu_plugin_vcpu_simple_cb_t cb) 79 { 80 plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_EXIT, cb); 81 } 82 83 void qemu_plugin_register_vcpu_tb_exec_cb(struct qemu_plugin_tb *tb, 84 qemu_plugin_vcpu_udata_cb_t cb, 85 enum qemu_plugin_cb_flags flags, 86 void *udata) 87 { 88 if (!tb->mem_only) { 89 plugin_register_dyn_cb__udata(&tb->cbs[PLUGIN_CB_REGULAR], 90 cb, flags, udata); 91 } 92 } 93 94 void qemu_plugin_register_vcpu_tb_exec_inline(struct qemu_plugin_tb *tb, 95 enum qemu_plugin_op op, 96 void *ptr, uint64_t imm) 97 { 98 if (!tb->mem_only) { 99 plugin_register_inline_op(&tb->cbs[PLUGIN_CB_INLINE], 0, op, ptr, imm); 100 } 101 } 102 103 void qemu_plugin_register_vcpu_insn_exec_cb(struct qemu_plugin_insn *insn, 104 qemu_plugin_vcpu_udata_cb_t cb, 105 enum qemu_plugin_cb_flags flags, 106 void *udata) 107 { 108 if (!insn->mem_only) { 109 plugin_register_dyn_cb__udata(&insn->cbs[PLUGIN_CB_INSN][PLUGIN_CB_REGULAR], 110 cb, flags, udata); 111 } 112 } 113 114 void qemu_plugin_register_vcpu_insn_exec_inline(struct qemu_plugin_insn *insn, 115 enum qemu_plugin_op op, 116 void *ptr, uint64_t imm) 117 { 118 if (!insn->mem_only) { 119 plugin_register_inline_op(&insn->cbs[PLUGIN_CB_INSN][PLUGIN_CB_INLINE], 120 0, op, ptr, imm); 121 } 122 } 123 124 125 /* 126 * We always plant memory instrumentation because they don't finalise until 127 * after the operation has complete. 128 */ 129 void qemu_plugin_register_vcpu_mem_cb(struct qemu_plugin_insn *insn, 130 qemu_plugin_vcpu_mem_cb_t cb, 131 enum qemu_plugin_cb_flags flags, 132 enum qemu_plugin_mem_rw rw, 133 void *udata) 134 { 135 plugin_register_vcpu_mem_cb(&insn->cbs[PLUGIN_CB_MEM][PLUGIN_CB_REGULAR], 136 cb, flags, rw, udata); 137 } 138 139 void qemu_plugin_register_vcpu_mem_inline(struct qemu_plugin_insn *insn, 140 enum qemu_plugin_mem_rw rw, 141 enum qemu_plugin_op op, void *ptr, 142 uint64_t imm) 143 { 144 plugin_register_inline_op(&insn->cbs[PLUGIN_CB_MEM][PLUGIN_CB_INLINE], 145 rw, op, ptr, imm); 146 } 147 148 void qemu_plugin_register_vcpu_tb_trans_cb(qemu_plugin_id_t id, 149 qemu_plugin_vcpu_tb_trans_cb_t cb) 150 { 151 plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_TB_TRANS, cb); 152 } 153 154 void qemu_plugin_register_vcpu_syscall_cb(qemu_plugin_id_t id, 155 qemu_plugin_vcpu_syscall_cb_t cb) 156 { 157 plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_SYSCALL, cb); 158 } 159 160 void 161 qemu_plugin_register_vcpu_syscall_ret_cb(qemu_plugin_id_t id, 162 qemu_plugin_vcpu_syscall_ret_cb_t cb) 163 { 164 plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_SYSCALL_RET, cb); 165 } 166 167 /* 168 * Plugin Queries 169 * 170 * These are queries that the plugin can make to gauge information 171 * from our opaque data types. We do not want to leak internal details 172 * here just information useful to the plugin. 173 */ 174 175 /* 176 * Translation block information: 177 * 178 * A plugin can query the virtual address of the start of the block 179 * and the number of instructions in it. It can also get access to 180 * each translated instruction. 181 */ 182 183 size_t qemu_plugin_tb_n_insns(const struct qemu_plugin_tb *tb) 184 { 185 return tb->n; 186 } 187 188 uint64_t qemu_plugin_tb_vaddr(const struct qemu_plugin_tb *tb) 189 { 190 return tb->vaddr; 191 } 192 193 struct qemu_plugin_insn * 194 qemu_plugin_tb_get_insn(const struct qemu_plugin_tb *tb, size_t idx) 195 { 196 struct qemu_plugin_insn *insn; 197 if (unlikely(idx >= tb->n)) { 198 return NULL; 199 } 200 insn = g_ptr_array_index(tb->insns, idx); 201 insn->mem_only = tb->mem_only; 202 return insn; 203 } 204 205 /* 206 * Instruction information 207 * 208 * These queries allow the plugin to retrieve information about each 209 * instruction being translated. 210 */ 211 212 const void *qemu_plugin_insn_data(const struct qemu_plugin_insn *insn) 213 { 214 return insn->data->data; 215 } 216 217 size_t qemu_plugin_insn_size(const struct qemu_plugin_insn *insn) 218 { 219 return insn->data->len; 220 } 221 222 uint64_t qemu_plugin_insn_vaddr(const struct qemu_plugin_insn *insn) 223 { 224 return insn->vaddr; 225 } 226 227 void *qemu_plugin_insn_haddr(const struct qemu_plugin_insn *insn) 228 { 229 return insn->haddr; 230 } 231 232 char *qemu_plugin_insn_disas(const struct qemu_plugin_insn *insn) 233 { 234 CPUState *cpu = current_cpu; 235 return plugin_disas(cpu, insn->vaddr, insn->data->len); 236 } 237 238 /* 239 * The memory queries allow the plugin to query information about a 240 * memory access. 241 */ 242 243 unsigned qemu_plugin_mem_size_shift(qemu_plugin_meminfo_t info) 244 { 245 return info & TRACE_MEM_SZ_SHIFT_MASK; 246 } 247 248 bool qemu_plugin_mem_is_sign_extended(qemu_plugin_meminfo_t info) 249 { 250 return !!(info & TRACE_MEM_SE); 251 } 252 253 bool qemu_plugin_mem_is_big_endian(qemu_plugin_meminfo_t info) 254 { 255 return !!(info & TRACE_MEM_BE); 256 } 257 258 bool qemu_plugin_mem_is_store(qemu_plugin_meminfo_t info) 259 { 260 return !!(info & TRACE_MEM_ST); 261 } 262 263 /* 264 * Virtual Memory queries 265 */ 266 267 #ifdef CONFIG_SOFTMMU 268 static __thread struct qemu_plugin_hwaddr hwaddr_info; 269 #endif 270 271 struct qemu_plugin_hwaddr *qemu_plugin_get_hwaddr(qemu_plugin_meminfo_t info, 272 uint64_t vaddr) 273 { 274 #ifdef CONFIG_SOFTMMU 275 CPUState *cpu = current_cpu; 276 unsigned int mmu_idx = info >> TRACE_MEM_MMU_SHIFT; 277 hwaddr_info.is_store = info & TRACE_MEM_ST; 278 279 if (!tlb_plugin_lookup(cpu, vaddr, mmu_idx, 280 info & TRACE_MEM_ST, &hwaddr_info)) { 281 error_report("invalid use of qemu_plugin_get_hwaddr"); 282 return NULL; 283 } 284 285 return &hwaddr_info; 286 #else 287 return NULL; 288 #endif 289 } 290 291 bool qemu_plugin_hwaddr_is_io(const struct qemu_plugin_hwaddr *haddr) 292 { 293 #ifdef CONFIG_SOFTMMU 294 return haddr->is_io; 295 #else 296 return false; 297 #endif 298 } 299 300 uint64_t qemu_plugin_hwaddr_phys_addr(const struct qemu_plugin_hwaddr *haddr) 301 { 302 #ifdef CONFIG_SOFTMMU 303 if (haddr) { 304 if (!haddr->is_io) { 305 RAMBlock *block; 306 ram_addr_t offset; 307 void *hostaddr = (void *) haddr->v.ram.hostaddr; 308 309 block = qemu_ram_block_from_host(hostaddr, false, &offset); 310 if (!block) { 311 error_report("Bad ram pointer %"PRIx64"", haddr->v.ram.hostaddr); 312 abort(); 313 } 314 315 return block->offset + offset + block->mr->addr; 316 } else { 317 MemoryRegionSection *mrs = haddr->v.io.section; 318 return haddr->v.io.offset + mrs->mr->addr; 319 } 320 } 321 #endif 322 return 0; 323 } 324 325 const char *qemu_plugin_hwaddr_device_name(const struct qemu_plugin_hwaddr *h) 326 { 327 #ifdef CONFIG_SOFTMMU 328 if (h && h->is_io) { 329 MemoryRegionSection *mrs = h->v.io.section; 330 if (!mrs->mr->name) { 331 unsigned long maddr = 0xffffffff & (uintptr_t) mrs->mr; 332 g_autofree char *temp = g_strdup_printf("anon%08lx", maddr); 333 return g_intern_string(temp); 334 } else { 335 return g_intern_string(mrs->mr->name); 336 } 337 } else { 338 return g_intern_static_string("RAM"); 339 } 340 #else 341 return g_intern_static_string("Invalid"); 342 #endif 343 } 344 345 /* 346 * Queries to the number and potential maximum number of vCPUs there 347 * will be. This helps the plugin dimension per-vcpu arrays. 348 */ 349 350 #ifndef CONFIG_USER_ONLY 351 static MachineState * get_ms(void) 352 { 353 return MACHINE(qdev_get_machine()); 354 } 355 #endif 356 357 int qemu_plugin_n_vcpus(void) 358 { 359 #ifdef CONFIG_USER_ONLY 360 return -1; 361 #else 362 return get_ms()->smp.cpus; 363 #endif 364 } 365 366 int qemu_plugin_n_max_vcpus(void) 367 { 368 #ifdef CONFIG_USER_ONLY 369 return -1; 370 #else 371 return get_ms()->smp.max_cpus; 372 #endif 373 } 374 375 /* 376 * Plugin output 377 */ 378 void qemu_plugin_outs(const char *string) 379 { 380 qemu_log_mask(CPU_LOG_PLUGIN, "%s", string); 381 } 382