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 * qemu_plugin_register 12 * 13 * Which can then be passed back into the API to do additional things. 14 * As such all the public functions in here are exported in 15 * qemu-plugin.h. 16 * 17 * The general life-cycle of a plugin is: 18 * 19 * - plugin is loaded, public qemu_plugin_install called 20 * - the install func registers callbacks for events 21 * - usually an atexit_cb is registered to dump info at the end 22 * - when a registered event occurs the plugin is called 23 * - some events pass additional info 24 * - during translation the plugin can decide to instrument any 25 * instruction 26 * - when QEMU exits all the registered atexit callbacks are called 27 * 28 * Copyright (C) 2017, Emilio G. Cota <cota@braap.org> 29 * Copyright (C) 2019, Linaro 30 * 31 * License: GNU GPL, version 2 or later. 32 * See the COPYING file in the top-level directory. 33 * 34 * SPDX-License-Identifier: GPL-2.0-or-later 35 * 36 */ 37 38 #include "qemu/osdep.h" 39 #include "qemu/main-loop.h" 40 #include "qemu/plugin.h" 41 #include "qemu/log.h" 42 #include "system/memory.h" 43 #include "tcg/tcg.h" 44 #include "exec/gdbstub.h" 45 #include "exec/target_page.h" 46 #include "exec/translation-block.h" 47 #include "exec/translator.h" 48 #include "disas/disas.h" 49 #include "plugin.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 static bool tb_is_mem_only(void) 83 { 84 return tb_cflags(tcg_ctx->gen_tb) & CF_MEMI_ONLY; 85 } 86 87 void qemu_plugin_register_vcpu_tb_exec_cb(struct qemu_plugin_tb *tb, 88 qemu_plugin_vcpu_udata_cb_t cb, 89 enum qemu_plugin_cb_flags flags, 90 void *udata) 91 { 92 if (!tb_is_mem_only()) { 93 plugin_register_dyn_cb__udata(&tb->cbs, cb, flags, udata); 94 } 95 } 96 97 void qemu_plugin_register_vcpu_tb_exec_cond_cb(struct qemu_plugin_tb *tb, 98 qemu_plugin_vcpu_udata_cb_t cb, 99 enum qemu_plugin_cb_flags flags, 100 enum qemu_plugin_cond cond, 101 qemu_plugin_u64 entry, 102 uint64_t imm, 103 void *udata) 104 { 105 if (cond == QEMU_PLUGIN_COND_NEVER || tb_is_mem_only()) { 106 return; 107 } 108 if (cond == QEMU_PLUGIN_COND_ALWAYS) { 109 qemu_plugin_register_vcpu_tb_exec_cb(tb, cb, flags, udata); 110 return; 111 } 112 plugin_register_dyn_cond_cb__udata(&tb->cbs, cb, flags, 113 cond, entry, imm, udata); 114 } 115 116 void qemu_plugin_register_vcpu_tb_exec_inline_per_vcpu( 117 struct qemu_plugin_tb *tb, 118 enum qemu_plugin_op op, 119 qemu_plugin_u64 entry, 120 uint64_t imm) 121 { 122 if (!tb_is_mem_only()) { 123 plugin_register_inline_op_on_entry(&tb->cbs, 0, op, entry, imm); 124 } 125 } 126 127 void qemu_plugin_register_vcpu_insn_exec_cb(struct qemu_plugin_insn *insn, 128 qemu_plugin_vcpu_udata_cb_t cb, 129 enum qemu_plugin_cb_flags flags, 130 void *udata) 131 { 132 if (!tb_is_mem_only()) { 133 plugin_register_dyn_cb__udata(&insn->insn_cbs, cb, flags, udata); 134 } 135 } 136 137 void qemu_plugin_register_vcpu_insn_exec_cond_cb( 138 struct qemu_plugin_insn *insn, 139 qemu_plugin_vcpu_udata_cb_t cb, 140 enum qemu_plugin_cb_flags flags, 141 enum qemu_plugin_cond cond, 142 qemu_plugin_u64 entry, 143 uint64_t imm, 144 void *udata) 145 { 146 if (cond == QEMU_PLUGIN_COND_NEVER || tb_is_mem_only()) { 147 return; 148 } 149 if (cond == QEMU_PLUGIN_COND_ALWAYS) { 150 qemu_plugin_register_vcpu_insn_exec_cb(insn, cb, flags, udata); 151 return; 152 } 153 plugin_register_dyn_cond_cb__udata(&insn->insn_cbs, cb, flags, 154 cond, entry, imm, udata); 155 } 156 157 void qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu( 158 struct qemu_plugin_insn *insn, 159 enum qemu_plugin_op op, 160 qemu_plugin_u64 entry, 161 uint64_t imm) 162 { 163 if (!tb_is_mem_only()) { 164 plugin_register_inline_op_on_entry(&insn->insn_cbs, 0, op, entry, imm); 165 } 166 } 167 168 169 /* 170 * We always plant memory instrumentation because they don't finalise until 171 * after the operation has complete. 172 */ 173 void qemu_plugin_register_vcpu_mem_cb(struct qemu_plugin_insn *insn, 174 qemu_plugin_vcpu_mem_cb_t cb, 175 enum qemu_plugin_cb_flags flags, 176 enum qemu_plugin_mem_rw rw, 177 void *udata) 178 { 179 plugin_register_vcpu_mem_cb(&insn->mem_cbs, cb, flags, rw, udata); 180 } 181 182 void qemu_plugin_register_vcpu_mem_inline_per_vcpu( 183 struct qemu_plugin_insn *insn, 184 enum qemu_plugin_mem_rw rw, 185 enum qemu_plugin_op op, 186 qemu_plugin_u64 entry, 187 uint64_t imm) 188 { 189 plugin_register_inline_op_on_entry(&insn->mem_cbs, rw, op, entry, imm); 190 } 191 192 void qemu_plugin_register_vcpu_tb_trans_cb(qemu_plugin_id_t id, 193 qemu_plugin_vcpu_tb_trans_cb_t cb) 194 { 195 plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_TB_TRANS, cb); 196 } 197 198 void qemu_plugin_register_vcpu_syscall_cb(qemu_plugin_id_t id, 199 qemu_plugin_vcpu_syscall_cb_t cb) 200 { 201 plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_SYSCALL, cb); 202 } 203 204 void 205 qemu_plugin_register_vcpu_syscall_ret_cb(qemu_plugin_id_t id, 206 qemu_plugin_vcpu_syscall_ret_cb_t cb) 207 { 208 plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_SYSCALL_RET, cb); 209 } 210 211 /* 212 * Plugin Queries 213 * 214 * These are queries that the plugin can make to gauge information 215 * from our opaque data types. We do not want to leak internal details 216 * here just information useful to the plugin. 217 */ 218 219 /* 220 * Translation block information: 221 * 222 * A plugin can query the virtual address of the start of the block 223 * and the number of instructions in it. It can also get access to 224 * each translated instruction. 225 */ 226 227 size_t qemu_plugin_tb_n_insns(const struct qemu_plugin_tb *tb) 228 { 229 return tb->n; 230 } 231 232 uint64_t qemu_plugin_tb_vaddr(const struct qemu_plugin_tb *tb) 233 { 234 const DisasContextBase *db = tcg_ctx->plugin_db; 235 return db->pc_first; 236 } 237 238 struct qemu_plugin_insn * 239 qemu_plugin_tb_get_insn(const struct qemu_plugin_tb *tb, size_t idx) 240 { 241 if (unlikely(idx >= tb->n)) { 242 return NULL; 243 } 244 return g_ptr_array_index(tb->insns, idx); 245 } 246 247 /* 248 * Instruction information 249 * 250 * These queries allow the plugin to retrieve information about each 251 * instruction being translated. 252 */ 253 254 size_t qemu_plugin_insn_data(const struct qemu_plugin_insn *insn, 255 void *dest, size_t len) 256 { 257 const DisasContextBase *db = tcg_ctx->plugin_db; 258 259 len = MIN(len, insn->len); 260 return translator_st(db, dest, insn->vaddr, len) ? len : 0; 261 } 262 263 size_t qemu_plugin_insn_size(const struct qemu_plugin_insn *insn) 264 { 265 return insn->len; 266 } 267 268 uint64_t qemu_plugin_insn_vaddr(const struct qemu_plugin_insn *insn) 269 { 270 return insn->vaddr; 271 } 272 273 void *qemu_plugin_insn_haddr(const struct qemu_plugin_insn *insn) 274 { 275 const DisasContextBase *db = tcg_ctx->plugin_db; 276 vaddr page0_last = db->pc_first | ~qemu_target_page_mask(); 277 278 if (db->fake_insn) { 279 return NULL; 280 } 281 282 /* 283 * ??? The return value is not intended for use of host memory, 284 * but as a proxy for address space and physical address. 285 * Thus we are only interested in the first byte and do not 286 * care about spanning pages. 287 */ 288 if (insn->vaddr <= page0_last) { 289 if (db->host_addr[0] == NULL) { 290 return NULL; 291 } 292 return db->host_addr[0] + insn->vaddr - db->pc_first; 293 } else { 294 if (db->host_addr[1] == NULL) { 295 return NULL; 296 } 297 return db->host_addr[1] + insn->vaddr - (page0_last + 1); 298 } 299 } 300 301 char *qemu_plugin_insn_disas(const struct qemu_plugin_insn *insn) 302 { 303 return plugin_disas(tcg_ctx->cpu, tcg_ctx->plugin_db, 304 insn->vaddr, insn->len); 305 } 306 307 const char *qemu_plugin_insn_symbol(const struct qemu_plugin_insn *insn) 308 { 309 const char *sym = lookup_symbol(insn->vaddr); 310 return sym[0] != 0 ? sym : NULL; 311 } 312 313 /* 314 * The memory queries allow the plugin to query information about a 315 * memory access. 316 */ 317 318 unsigned qemu_plugin_mem_size_shift(qemu_plugin_meminfo_t info) 319 { 320 MemOp op = get_memop(info); 321 return op & MO_SIZE; 322 } 323 324 bool qemu_plugin_mem_is_sign_extended(qemu_plugin_meminfo_t info) 325 { 326 MemOp op = get_memop(info); 327 return op & MO_SIGN; 328 } 329 330 bool qemu_plugin_mem_is_big_endian(qemu_plugin_meminfo_t info) 331 { 332 MemOp op = get_memop(info); 333 return (op & MO_BSWAP) == MO_BE; 334 } 335 336 bool qemu_plugin_mem_is_store(qemu_plugin_meminfo_t info) 337 { 338 return get_plugin_meminfo_rw(info) & QEMU_PLUGIN_MEM_W; 339 } 340 341 qemu_plugin_mem_value qemu_plugin_mem_get_value(qemu_plugin_meminfo_t info) 342 { 343 uint64_t low = current_cpu->neg.plugin_mem_value_low; 344 qemu_plugin_mem_value value; 345 346 switch (qemu_plugin_mem_size_shift(info)) { 347 case 0: 348 value.type = QEMU_PLUGIN_MEM_VALUE_U8; 349 value.data.u8 = (uint8_t)low; 350 break; 351 case 1: 352 value.type = QEMU_PLUGIN_MEM_VALUE_U16; 353 value.data.u16 = (uint16_t)low; 354 break; 355 case 2: 356 value.type = QEMU_PLUGIN_MEM_VALUE_U32; 357 value.data.u32 = (uint32_t)low; 358 break; 359 case 3: 360 value.type = QEMU_PLUGIN_MEM_VALUE_U64; 361 value.data.u64 = low; 362 break; 363 case 4: 364 value.type = QEMU_PLUGIN_MEM_VALUE_U128; 365 value.data.u128.low = low; 366 value.data.u128.high = current_cpu->neg.plugin_mem_value_high; 367 break; 368 default: 369 g_assert_not_reached(); 370 } 371 return value; 372 } 373 374 int qemu_plugin_num_vcpus(void) 375 { 376 return plugin_num_vcpus(); 377 } 378 379 /* 380 * Plugin output 381 */ 382 void qemu_plugin_outs(const char *string) 383 { 384 qemu_log_mask(CPU_LOG_PLUGIN, "%s", string); 385 } 386 387 bool qemu_plugin_bool_parse(const char *name, const char *value, bool *ret) 388 { 389 return name && value && qapi_bool_parse(name, value, ret, NULL); 390 } 391 392 /* 393 * Create register handles. 394 * 395 * We need to create a handle for each register so the plugin 396 * infrastructure can call gdbstub to read a register. They are 397 * currently just a pointer encapsulation of the gdb_reg but in 398 * future may hold internal plugin state so its important plugin 399 * authors are not tempted to treat them as numbers. 400 * 401 * We also construct a result array with those handles and some 402 * ancillary data the plugin might find useful. 403 */ 404 405 static GArray *create_register_handles(GArray *gdbstub_regs) 406 { 407 GArray *find_data = g_array_new(true, true, 408 sizeof(qemu_plugin_reg_descriptor)); 409 410 for (int i = 0; i < gdbstub_regs->len; i++) { 411 GDBRegDesc *grd = &g_array_index(gdbstub_regs, GDBRegDesc, i); 412 qemu_plugin_reg_descriptor desc; 413 414 /* skip "un-named" regs */ 415 if (!grd->name) { 416 continue; 417 } 418 419 /* Create a record for the plugin */ 420 desc.handle = GINT_TO_POINTER(grd->gdb_reg + 1); 421 desc.name = g_intern_string(grd->name); 422 desc.feature = g_intern_string(grd->feature_name); 423 g_array_append_val(find_data, desc); 424 } 425 426 return find_data; 427 } 428 429 GArray *qemu_plugin_get_registers(void) 430 { 431 g_assert(current_cpu); 432 433 g_autoptr(GArray) regs = gdb_get_register_list(current_cpu); 434 return create_register_handles(regs); 435 } 436 437 int qemu_plugin_read_register(struct qemu_plugin_register *reg, GByteArray *buf) 438 { 439 g_assert(current_cpu); 440 441 if (qemu_plugin_get_cb_flags() == QEMU_PLUGIN_CB_NO_REGS) { 442 return -1; 443 } 444 445 return gdb_read_register(current_cpu, buf, GPOINTER_TO_INT(reg) - 1); 446 } 447 448 int qemu_plugin_write_register(struct qemu_plugin_register *reg, 449 GByteArray *buf) 450 { 451 g_assert(current_cpu); 452 453 if (buf->len == 0 || qemu_plugin_get_cb_flags() != QEMU_PLUGIN_CB_RW_REGS) { 454 return -1; 455 } 456 457 return gdb_write_register(current_cpu, buf->data, GPOINTER_TO_INT(reg) - 1); 458 } 459 460 bool qemu_plugin_read_memory_vaddr(uint64_t addr, GByteArray *data, size_t len) 461 { 462 g_assert(current_cpu); 463 464 if (len == 0) { 465 return false; 466 } 467 468 g_byte_array_set_size(data, len); 469 470 int result = cpu_memory_rw_debug(current_cpu, addr, data->data, 471 data->len, false); 472 473 if (result < 0) { 474 return false; 475 } 476 477 return true; 478 } 479 480 bool qemu_plugin_write_memory_vaddr(uint64_t addr, GByteArray *data) 481 { 482 g_assert(current_cpu); 483 484 if (data->len == 0) { 485 return false; 486 } 487 488 int result = cpu_memory_rw_debug(current_cpu, addr, data->data, 489 data->len, true); 490 491 if (result < 0) { 492 return false; 493 } 494 495 return true; 496 } 497 498 enum qemu_plugin_hwaddr_operation_result 499 qemu_plugin_read_memory_hwaddr(hwaddr addr, GByteArray *data, size_t len) 500 { 501 #ifdef CONFIG_SOFTMMU 502 if (len == 0) { 503 return QEMU_PLUGIN_HWADDR_OPERATION_ERROR; 504 } 505 506 g_assert(current_cpu); 507 508 509 int as_idx = cpu_asidx_from_attrs(current_cpu, MEMTXATTRS_UNSPECIFIED); 510 AddressSpace *as = cpu_get_address_space(current_cpu, as_idx); 511 512 if (as == NULL) { 513 return QEMU_PLUGIN_HWADDR_OPERATION_INVALID_ADDRESS_SPACE; 514 } 515 516 g_byte_array_set_size(data, len); 517 MemTxResult res = address_space_rw(as, addr, 518 MEMTXATTRS_UNSPECIFIED, data->data, 519 data->len, false); 520 521 switch (res) { 522 case MEMTX_OK: 523 return QEMU_PLUGIN_HWADDR_OPERATION_OK; 524 case MEMTX_ERROR: 525 return QEMU_PLUGIN_HWADDR_OPERATION_DEVICE_ERROR; 526 case MEMTX_DECODE_ERROR: 527 return QEMU_PLUGIN_HWADDR_OPERATION_INVALID_ADDRESS; 528 case MEMTX_ACCESS_ERROR: 529 return QEMU_PLUGIN_HWADDR_OPERATION_ACCESS_DENIED; 530 default: 531 return QEMU_PLUGIN_HWADDR_OPERATION_ERROR; 532 } 533 #else 534 return QEMU_PLUGIN_HWADDR_OPERATION_ERROR; 535 #endif 536 } 537 538 enum qemu_plugin_hwaddr_operation_result 539 qemu_plugin_write_memory_hwaddr(hwaddr addr, GByteArray *data) 540 { 541 #ifdef CONFIG_SOFTMMU 542 if (data->len == 0) { 543 return QEMU_PLUGIN_HWADDR_OPERATION_ERROR; 544 } 545 546 g_assert(current_cpu); 547 548 int as_idx = cpu_asidx_from_attrs(current_cpu, MEMTXATTRS_UNSPECIFIED); 549 AddressSpace *as = cpu_get_address_space(current_cpu, as_idx); 550 551 if (as == NULL) { 552 return QEMU_PLUGIN_HWADDR_OPERATION_INVALID_ADDRESS_SPACE; 553 } 554 555 MemTxResult res = address_space_rw(as, addr, 556 MEMTXATTRS_UNSPECIFIED, data->data, 557 data->len, true); 558 switch (res) { 559 case MEMTX_OK: 560 return QEMU_PLUGIN_HWADDR_OPERATION_OK; 561 case MEMTX_ERROR: 562 return QEMU_PLUGIN_HWADDR_OPERATION_DEVICE_ERROR; 563 case MEMTX_DECODE_ERROR: 564 return QEMU_PLUGIN_HWADDR_OPERATION_INVALID_ADDRESS; 565 case MEMTX_ACCESS_ERROR: 566 return QEMU_PLUGIN_HWADDR_OPERATION_ACCESS_DENIED; 567 default: 568 return QEMU_PLUGIN_HWADDR_OPERATION_ERROR; 569 } 570 #else 571 return QEMU_PLUGIN_HWADDR_OPERATION_ERROR; 572 #endif 573 } 574 575 bool qemu_plugin_translate_vaddr(uint64_t vaddr, uint64_t *hwaddr) 576 { 577 #ifdef CONFIG_SOFTMMU 578 g_assert(current_cpu); 579 580 uint64_t res = cpu_get_phys_page_debug(current_cpu, vaddr); 581 582 if (res == (uint64_t)-1) { 583 return false; 584 } 585 586 *hwaddr = res | (vaddr & ~TARGET_PAGE_MASK); 587 588 return true; 589 #else 590 return false; 591 #endif 592 } 593 594 struct qemu_plugin_scoreboard *qemu_plugin_scoreboard_new(size_t element_size) 595 { 596 return plugin_scoreboard_new(element_size); 597 } 598 599 void qemu_plugin_scoreboard_free(struct qemu_plugin_scoreboard *score) 600 { 601 plugin_scoreboard_free(score); 602 } 603 604 void *qemu_plugin_scoreboard_find(struct qemu_plugin_scoreboard *score, 605 unsigned int vcpu_index) 606 { 607 g_assert(vcpu_index < qemu_plugin_num_vcpus()); 608 /* we can't use g_array_index since entry size is not statically known */ 609 char *base_ptr = score->data->data; 610 return base_ptr + vcpu_index * g_array_get_element_size(score->data); 611 } 612 613 static uint64_t *plugin_u64_address(qemu_plugin_u64 entry, 614 unsigned int vcpu_index) 615 { 616 char *ptr = qemu_plugin_scoreboard_find(entry.score, vcpu_index); 617 return (uint64_t *)(ptr + entry.offset); 618 } 619 620 void qemu_plugin_u64_add(qemu_plugin_u64 entry, unsigned int vcpu_index, 621 uint64_t added) 622 { 623 *plugin_u64_address(entry, vcpu_index) += added; 624 } 625 626 uint64_t qemu_plugin_u64_get(qemu_plugin_u64 entry, 627 unsigned int vcpu_index) 628 { 629 return *plugin_u64_address(entry, vcpu_index); 630 } 631 632 void qemu_plugin_u64_set(qemu_plugin_u64 entry, unsigned int vcpu_index, 633 uint64_t val) 634 { 635 *plugin_u64_address(entry, vcpu_index) = val; 636 } 637 638 uint64_t qemu_plugin_u64_sum(qemu_plugin_u64 entry) 639 { 640 uint64_t total = 0; 641 for (int i = 0, n = qemu_plugin_num_vcpus(); i < n; ++i) { 642 total += qemu_plugin_u64_get(entry, i); 643 } 644 return total; 645 } 646 647