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 "tcg/tcg.h" 41 #include "exec/exec-all.h" 42 #include "exec/ram_addr.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 #endif 269 270 struct qemu_plugin_hwaddr *qemu_plugin_get_hwaddr(qemu_plugin_meminfo_t info, 271 uint64_t vaddr) 272 { 273 #ifdef CONFIG_SOFTMMU 274 CPUState *cpu = current_cpu; 275 unsigned int mmu_idx = info >> TRACE_MEM_MMU_SHIFT; 276 hwaddr_info.is_store = info & TRACE_MEM_ST; 277 278 if (!tlb_plugin_lookup(cpu, vaddr, mmu_idx, 279 info & TRACE_MEM_ST, &hwaddr_info)) { 280 error_report("invalid use of qemu_plugin_get_hwaddr"); 281 return NULL; 282 } 283 284 return &hwaddr_info; 285 #else 286 return NULL; 287 #endif 288 } 289 290 bool qemu_plugin_hwaddr_is_io(const struct qemu_plugin_hwaddr *haddr) 291 { 292 #ifdef CONFIG_SOFTMMU 293 return haddr->is_io; 294 #else 295 return false; 296 #endif 297 } 298 299 uint64_t qemu_plugin_hwaddr_phys_addr(const struct qemu_plugin_hwaddr *haddr) 300 { 301 #ifdef CONFIG_SOFTMMU 302 if (haddr) { 303 if (!haddr->is_io) { 304 RAMBlock *block; 305 ram_addr_t offset; 306 void *hostaddr = (void *) haddr->v.ram.hostaddr; 307 308 block = qemu_ram_block_from_host(hostaddr, false, &offset); 309 if (!block) { 310 error_report("Bad ram pointer %"PRIx64"", haddr->v.ram.hostaddr); 311 abort(); 312 } 313 314 return block->offset + offset + block->mr->addr; 315 } else { 316 MemoryRegionSection *mrs = haddr->v.io.section; 317 return haddr->v.io.offset + mrs->mr->addr; 318 } 319 } 320 #endif 321 return 0; 322 } 323 324 const char *qemu_plugin_hwaddr_device_name(const struct qemu_plugin_hwaddr *h) 325 { 326 #ifdef CONFIG_SOFTMMU 327 if (h && h->is_io) { 328 MemoryRegionSection *mrs = h->v.io.section; 329 if (!mrs->mr->name) { 330 unsigned long maddr = 0xffffffff & (uintptr_t) mrs->mr; 331 g_autofree char *temp = g_strdup_printf("anon%08lx", maddr); 332 return g_intern_string(temp); 333 } else { 334 return g_intern_string(mrs->mr->name); 335 } 336 } else { 337 return g_intern_static_string("RAM"); 338 } 339 #else 340 return g_intern_static_string("Invalid"); 341 #endif 342 } 343 344 /* 345 * Queries to the number and potential maximum number of vCPUs there 346 * will be. This helps the plugin dimension per-vcpu arrays. 347 */ 348 349 #ifndef CONFIG_USER_ONLY 350 static MachineState * get_ms(void) 351 { 352 return MACHINE(qdev_get_machine()); 353 } 354 #endif 355 356 int qemu_plugin_n_vcpus(void) 357 { 358 #ifdef CONFIG_USER_ONLY 359 return -1; 360 #else 361 return get_ms()->smp.cpus; 362 #endif 363 } 364 365 int qemu_plugin_n_max_vcpus(void) 366 { 367 #ifdef CONFIG_USER_ONLY 368 return -1; 369 #else 370 return get_ms()->smp.max_cpus; 371 #endif 372 } 373 374 /* 375 * Plugin output 376 */ 377 void qemu_plugin_outs(const char *string) 378 { 379 qemu_log_mask(CPU_LOG_PLUGIN, "%s", string); 380 } 381