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