1 /* 2 * QEMU Plugin Core code 3 * 4 * This is the core code that deals with injecting instrumentation into the code 5 * 6 * Copyright (C) 2017, Emilio G. Cota <cota@braap.org> 7 * Copyright (C) 2019, Linaro 8 * 9 * License: GNU GPL, version 2 or later. 10 * See the COPYING file in the top-level directory. 11 * 12 * SPDX-License-Identifier: GPL-2.0-or-later 13 */ 14 #include "qemu/osdep.h" 15 #include "qemu/error-report.h" 16 #include "qemu/config-file.h" 17 #include "qapi/error.h" 18 #include "qemu/lockable.h" 19 #include "qemu/option.h" 20 #include "qemu/rcu_queue.h" 21 #include "qemu/xxhash.h" 22 #include "qemu/rcu.h" 23 #include "hw/core/cpu.h" 24 #include "exec/cpu-common.h" 25 26 #include "cpu.h" 27 #include "exec/exec-all.h" 28 #include "exec/helper-proto.h" 29 #include "tcg/tcg.h" 30 #include "tcg/tcg-op.h" 31 #include "trace/mem-internal.h" /* mem_info macros */ 32 #include "plugin.h" 33 #include "qemu/compiler.h" 34 35 struct qemu_plugin_cb { 36 struct qemu_plugin_ctx *ctx; 37 union qemu_plugin_cb_sig f; 38 void *udata; 39 QLIST_ENTRY(qemu_plugin_cb) entry; 40 }; 41 42 struct qemu_plugin_state plugin; 43 44 struct qemu_plugin_ctx *plugin_id_to_ctx_locked(qemu_plugin_id_t id) 45 { 46 struct qemu_plugin_ctx *ctx; 47 qemu_plugin_id_t *id_p; 48 49 id_p = g_hash_table_lookup(plugin.id_ht, &id); 50 ctx = container_of(id_p, struct qemu_plugin_ctx, id); 51 if (ctx == NULL) { 52 error_report("plugin: invalid plugin id %" PRIu64, id); 53 abort(); 54 } 55 return ctx; 56 } 57 58 static void plugin_cpu_update__async(CPUState *cpu, run_on_cpu_data data) 59 { 60 bitmap_copy(cpu->plugin_mask, &data.host_ulong, QEMU_PLUGIN_EV_MAX); 61 cpu_tb_jmp_cache_clear(cpu); 62 } 63 64 static void plugin_cpu_update__locked(gpointer k, gpointer v, gpointer udata) 65 { 66 CPUState *cpu = container_of(k, CPUState, cpu_index); 67 run_on_cpu_data mask = RUN_ON_CPU_HOST_ULONG(*plugin.mask); 68 69 if (cpu->created) { 70 async_run_on_cpu(cpu, plugin_cpu_update__async, mask); 71 } else { 72 plugin_cpu_update__async(cpu, mask); 73 } 74 } 75 76 void plugin_unregister_cb__locked(struct qemu_plugin_ctx *ctx, 77 enum qemu_plugin_event ev) 78 { 79 struct qemu_plugin_cb *cb = ctx->callbacks[ev]; 80 81 if (cb == NULL) { 82 return; 83 } 84 QLIST_REMOVE_RCU(cb, entry); 85 g_free(cb); 86 ctx->callbacks[ev] = NULL; 87 if (QLIST_EMPTY_RCU(&plugin.cb_lists[ev])) { 88 clear_bit(ev, plugin.mask); 89 g_hash_table_foreach(plugin.cpu_ht, plugin_cpu_update__locked, NULL); 90 } 91 } 92 93 /* 94 * Disable CFI checks. 95 * The callback function has been loaded from an external library so we do not 96 * have type information 97 */ 98 QEMU_DISABLE_CFI 99 static void plugin_vcpu_cb__simple(CPUState *cpu, enum qemu_plugin_event ev) 100 { 101 struct qemu_plugin_cb *cb, *next; 102 103 switch (ev) { 104 case QEMU_PLUGIN_EV_VCPU_INIT: 105 case QEMU_PLUGIN_EV_VCPU_EXIT: 106 case QEMU_PLUGIN_EV_VCPU_IDLE: 107 case QEMU_PLUGIN_EV_VCPU_RESUME: 108 /* iterate safely; plugins might uninstall themselves at any time */ 109 QLIST_FOREACH_SAFE_RCU(cb, &plugin.cb_lists[ev], entry, next) { 110 qemu_plugin_vcpu_simple_cb_t func = cb->f.vcpu_simple; 111 112 func(cb->ctx->id, cpu->cpu_index); 113 } 114 break; 115 default: 116 g_assert_not_reached(); 117 } 118 } 119 120 /* 121 * Disable CFI checks. 122 * The callback function has been loaded from an external library so we do not 123 * have type information 124 */ 125 QEMU_DISABLE_CFI 126 static void plugin_cb__simple(enum qemu_plugin_event ev) 127 { 128 struct qemu_plugin_cb *cb, *next; 129 130 switch (ev) { 131 case QEMU_PLUGIN_EV_FLUSH: 132 QLIST_FOREACH_SAFE_RCU(cb, &plugin.cb_lists[ev], entry, next) { 133 qemu_plugin_simple_cb_t func = cb->f.simple; 134 135 func(cb->ctx->id); 136 } 137 break; 138 default: 139 g_assert_not_reached(); 140 } 141 } 142 143 /* 144 * Disable CFI checks. 145 * The callback function has been loaded from an external library so we do not 146 * have type information 147 */ 148 QEMU_DISABLE_CFI 149 static void plugin_cb__udata(enum qemu_plugin_event ev) 150 { 151 struct qemu_plugin_cb *cb, *next; 152 153 switch (ev) { 154 case QEMU_PLUGIN_EV_ATEXIT: 155 QLIST_FOREACH_SAFE_RCU(cb, &plugin.cb_lists[ev], entry, next) { 156 qemu_plugin_udata_cb_t func = cb->f.udata; 157 158 func(cb->ctx->id, cb->udata); 159 } 160 break; 161 default: 162 g_assert_not_reached(); 163 } 164 } 165 166 static void 167 do_plugin_register_cb(qemu_plugin_id_t id, enum qemu_plugin_event ev, 168 void *func, void *udata) 169 { 170 struct qemu_plugin_ctx *ctx; 171 172 QEMU_LOCK_GUARD(&plugin.lock); 173 ctx = plugin_id_to_ctx_locked(id); 174 /* if the plugin is on its way out, ignore this request */ 175 if (unlikely(ctx->uninstalling)) { 176 return; 177 } 178 if (func) { 179 struct qemu_plugin_cb *cb = ctx->callbacks[ev]; 180 181 if (cb) { 182 cb->f.generic = func; 183 cb->udata = udata; 184 } else { 185 cb = g_new(struct qemu_plugin_cb, 1); 186 cb->ctx = ctx; 187 cb->f.generic = func; 188 cb->udata = udata; 189 ctx->callbacks[ev] = cb; 190 QLIST_INSERT_HEAD_RCU(&plugin.cb_lists[ev], cb, entry); 191 if (!test_bit(ev, plugin.mask)) { 192 set_bit(ev, plugin.mask); 193 g_hash_table_foreach(plugin.cpu_ht, plugin_cpu_update__locked, 194 NULL); 195 } 196 } 197 } else { 198 plugin_unregister_cb__locked(ctx, ev); 199 } 200 } 201 202 void plugin_register_cb(qemu_plugin_id_t id, enum qemu_plugin_event ev, 203 void *func) 204 { 205 do_plugin_register_cb(id, ev, func, NULL); 206 } 207 208 void 209 plugin_register_cb_udata(qemu_plugin_id_t id, enum qemu_plugin_event ev, 210 void *func, void *udata) 211 { 212 do_plugin_register_cb(id, ev, func, udata); 213 } 214 215 void qemu_plugin_vcpu_init_hook(CPUState *cpu) 216 { 217 bool success; 218 219 qemu_rec_mutex_lock(&plugin.lock); 220 plugin_cpu_update__locked(&cpu->cpu_index, NULL, NULL); 221 success = g_hash_table_insert(plugin.cpu_ht, &cpu->cpu_index, 222 &cpu->cpu_index); 223 g_assert(success); 224 qemu_rec_mutex_unlock(&plugin.lock); 225 226 plugin_vcpu_cb__simple(cpu, QEMU_PLUGIN_EV_VCPU_INIT); 227 } 228 229 void qemu_plugin_vcpu_exit_hook(CPUState *cpu) 230 { 231 bool success; 232 233 plugin_vcpu_cb__simple(cpu, QEMU_PLUGIN_EV_VCPU_EXIT); 234 235 qemu_rec_mutex_lock(&plugin.lock); 236 success = g_hash_table_remove(plugin.cpu_ht, &cpu->cpu_index); 237 g_assert(success); 238 qemu_rec_mutex_unlock(&plugin.lock); 239 } 240 241 struct plugin_for_each_args { 242 struct qemu_plugin_ctx *ctx; 243 qemu_plugin_vcpu_simple_cb_t cb; 244 }; 245 246 static void plugin_vcpu_for_each(gpointer k, gpointer v, gpointer udata) 247 { 248 struct plugin_for_each_args *args = udata; 249 int cpu_index = *(int *)k; 250 251 args->cb(args->ctx->id, cpu_index); 252 } 253 254 void qemu_plugin_vcpu_for_each(qemu_plugin_id_t id, 255 qemu_plugin_vcpu_simple_cb_t cb) 256 { 257 struct plugin_for_each_args args; 258 259 if (cb == NULL) { 260 return; 261 } 262 qemu_rec_mutex_lock(&plugin.lock); 263 args.ctx = plugin_id_to_ctx_locked(id); 264 args.cb = cb; 265 g_hash_table_foreach(plugin.cpu_ht, plugin_vcpu_for_each, &args); 266 qemu_rec_mutex_unlock(&plugin.lock); 267 } 268 269 /* Allocate and return a callback record */ 270 static struct qemu_plugin_dyn_cb *plugin_get_dyn_cb(GArray **arr) 271 { 272 GArray *cbs = *arr; 273 274 if (!cbs) { 275 cbs = g_array_sized_new(false, false, 276 sizeof(struct qemu_plugin_dyn_cb), 1); 277 *arr = cbs; 278 } 279 280 g_array_set_size(cbs, cbs->len + 1); 281 return &g_array_index(cbs, struct qemu_plugin_dyn_cb, cbs->len - 1); 282 } 283 284 void plugin_register_inline_op(GArray **arr, 285 enum qemu_plugin_mem_rw rw, 286 enum qemu_plugin_op op, void *ptr, 287 uint64_t imm) 288 { 289 struct qemu_plugin_dyn_cb *dyn_cb; 290 291 dyn_cb = plugin_get_dyn_cb(arr); 292 dyn_cb->userp = ptr; 293 dyn_cb->type = PLUGIN_CB_INLINE; 294 dyn_cb->rw = rw; 295 dyn_cb->inline_insn.op = op; 296 dyn_cb->inline_insn.imm = imm; 297 } 298 299 static inline uint32_t cb_to_tcg_flags(enum qemu_plugin_cb_flags flags) 300 { 301 uint32_t ret; 302 303 switch (flags) { 304 case QEMU_PLUGIN_CB_RW_REGS: 305 ret = 0; 306 break; 307 case QEMU_PLUGIN_CB_R_REGS: 308 ret = TCG_CALL_NO_WG; 309 break; 310 case QEMU_PLUGIN_CB_NO_REGS: 311 default: 312 ret = TCG_CALL_NO_RWG; 313 } 314 return ret; 315 } 316 317 inline void 318 plugin_register_dyn_cb__udata(GArray **arr, 319 qemu_plugin_vcpu_udata_cb_t cb, 320 enum qemu_plugin_cb_flags flags, void *udata) 321 { 322 struct qemu_plugin_dyn_cb *dyn_cb = plugin_get_dyn_cb(arr); 323 324 dyn_cb->userp = udata; 325 dyn_cb->tcg_flags = cb_to_tcg_flags(flags); 326 dyn_cb->f.vcpu_udata = cb; 327 dyn_cb->type = PLUGIN_CB_REGULAR; 328 } 329 330 void plugin_register_vcpu_mem_cb(GArray **arr, 331 void *cb, 332 enum qemu_plugin_cb_flags flags, 333 enum qemu_plugin_mem_rw rw, 334 void *udata) 335 { 336 struct qemu_plugin_dyn_cb *dyn_cb; 337 338 dyn_cb = plugin_get_dyn_cb(arr); 339 dyn_cb->userp = udata; 340 dyn_cb->tcg_flags = cb_to_tcg_flags(flags); 341 dyn_cb->type = PLUGIN_CB_REGULAR; 342 dyn_cb->rw = rw; 343 dyn_cb->f.generic = cb; 344 } 345 346 /* 347 * Disable CFI checks. 348 * The callback function has been loaded from an external library so we do not 349 * have type information 350 */ 351 QEMU_DISABLE_CFI 352 void qemu_plugin_tb_trans_cb(CPUState *cpu, struct qemu_plugin_tb *tb) 353 { 354 struct qemu_plugin_cb *cb, *next; 355 enum qemu_plugin_event ev = QEMU_PLUGIN_EV_VCPU_TB_TRANS; 356 357 /* no plugin_mask check here; caller should have checked */ 358 359 QLIST_FOREACH_SAFE_RCU(cb, &plugin.cb_lists[ev], entry, next) { 360 qemu_plugin_vcpu_tb_trans_cb_t func = cb->f.vcpu_tb_trans; 361 362 func(cb->ctx->id, tb); 363 } 364 } 365 366 /* 367 * Disable CFI checks. 368 * The callback function has been loaded from an external library so we do not 369 * have type information 370 */ 371 QEMU_DISABLE_CFI 372 void 373 qemu_plugin_vcpu_syscall(CPUState *cpu, int64_t num, uint64_t a1, uint64_t a2, 374 uint64_t a3, uint64_t a4, uint64_t a5, 375 uint64_t a6, uint64_t a7, uint64_t a8) 376 { 377 struct qemu_plugin_cb *cb, *next; 378 enum qemu_plugin_event ev = QEMU_PLUGIN_EV_VCPU_SYSCALL; 379 380 if (!test_bit(ev, cpu->plugin_mask)) { 381 return; 382 } 383 384 QLIST_FOREACH_SAFE_RCU(cb, &plugin.cb_lists[ev], entry, next) { 385 qemu_plugin_vcpu_syscall_cb_t func = cb->f.vcpu_syscall; 386 387 func(cb->ctx->id, cpu->cpu_index, num, a1, a2, a3, a4, a5, a6, a7, a8); 388 } 389 } 390 391 /* 392 * Disable CFI checks. 393 * The callback function has been loaded from an external library so we do not 394 * have type information 395 */ 396 QEMU_DISABLE_CFI 397 void qemu_plugin_vcpu_syscall_ret(CPUState *cpu, int64_t num, int64_t ret) 398 { 399 struct qemu_plugin_cb *cb, *next; 400 enum qemu_plugin_event ev = QEMU_PLUGIN_EV_VCPU_SYSCALL_RET; 401 402 if (!test_bit(ev, cpu->plugin_mask)) { 403 return; 404 } 405 406 QLIST_FOREACH_SAFE_RCU(cb, &plugin.cb_lists[ev], entry, next) { 407 qemu_plugin_vcpu_syscall_ret_cb_t func = cb->f.vcpu_syscall_ret; 408 409 func(cb->ctx->id, cpu->cpu_index, num, ret); 410 } 411 } 412 413 void qemu_plugin_vcpu_idle_cb(CPUState *cpu) 414 { 415 plugin_vcpu_cb__simple(cpu, QEMU_PLUGIN_EV_VCPU_IDLE); 416 } 417 418 void qemu_plugin_vcpu_resume_cb(CPUState *cpu) 419 { 420 plugin_vcpu_cb__simple(cpu, QEMU_PLUGIN_EV_VCPU_RESUME); 421 } 422 423 void qemu_plugin_register_vcpu_idle_cb(qemu_plugin_id_t id, 424 qemu_plugin_vcpu_simple_cb_t cb) 425 { 426 plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_IDLE, cb); 427 } 428 429 void qemu_plugin_register_vcpu_resume_cb(qemu_plugin_id_t id, 430 qemu_plugin_vcpu_simple_cb_t cb) 431 { 432 plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_RESUME, cb); 433 } 434 435 void qemu_plugin_register_flush_cb(qemu_plugin_id_t id, 436 qemu_plugin_simple_cb_t cb) 437 { 438 plugin_register_cb(id, QEMU_PLUGIN_EV_FLUSH, cb); 439 } 440 441 static bool free_dyn_cb_arr(void *p, uint32_t h, void *userp) 442 { 443 g_array_free((GArray *) p, true); 444 return true; 445 } 446 447 void qemu_plugin_flush_cb(void) 448 { 449 qht_iter_remove(&plugin.dyn_cb_arr_ht, free_dyn_cb_arr, NULL); 450 qht_reset(&plugin.dyn_cb_arr_ht); 451 452 plugin_cb__simple(QEMU_PLUGIN_EV_FLUSH); 453 } 454 455 void exec_inline_op(struct qemu_plugin_dyn_cb *cb) 456 { 457 uint64_t *val = cb->userp; 458 459 switch (cb->inline_insn.op) { 460 case QEMU_PLUGIN_INLINE_ADD_U64: 461 *val += cb->inline_insn.imm; 462 break; 463 default: 464 g_assert_not_reached(); 465 } 466 } 467 468 void qemu_plugin_vcpu_mem_cb(CPUState *cpu, uint64_t vaddr, uint32_t info) 469 { 470 GArray *arr = cpu->plugin_mem_cbs; 471 size_t i; 472 473 if (arr == NULL) { 474 return; 475 } 476 for (i = 0; i < arr->len; i++) { 477 struct qemu_plugin_dyn_cb *cb = 478 &g_array_index(arr, struct qemu_plugin_dyn_cb, i); 479 int w = !!(info & TRACE_MEM_ST) + 1; 480 481 if (!(w & cb->rw)) { 482 break; 483 } 484 switch (cb->type) { 485 case PLUGIN_CB_REGULAR: 486 cb->f.vcpu_mem(cpu->cpu_index, info, vaddr, cb->userp); 487 break; 488 case PLUGIN_CB_INLINE: 489 exec_inline_op(cb); 490 break; 491 default: 492 g_assert_not_reached(); 493 } 494 } 495 } 496 497 void qemu_plugin_atexit_cb(void) 498 { 499 plugin_cb__udata(QEMU_PLUGIN_EV_ATEXIT); 500 } 501 502 void qemu_plugin_register_atexit_cb(qemu_plugin_id_t id, 503 qemu_plugin_udata_cb_t cb, 504 void *udata) 505 { 506 plugin_register_cb_udata(id, QEMU_PLUGIN_EV_ATEXIT, cb, udata); 507 } 508 509 /* 510 * Call this function after longjmp'ing to the main loop. It's possible that the 511 * last instruction of a TB might have used helpers, and therefore the 512 * "disable" instruction will never execute because it ended up as dead code. 513 */ 514 void qemu_plugin_disable_mem_helpers(CPUState *cpu) 515 { 516 cpu->plugin_mem_cbs = NULL; 517 } 518 519 static bool plugin_dyn_cb_arr_cmp(const void *ap, const void *bp) 520 { 521 return ap == bp; 522 } 523 524 static void __attribute__((__constructor__)) plugin_init(void) 525 { 526 int i; 527 528 for (i = 0; i < QEMU_PLUGIN_EV_MAX; i++) { 529 QLIST_INIT(&plugin.cb_lists[i]); 530 } 531 qemu_rec_mutex_init(&plugin.lock); 532 plugin.id_ht = g_hash_table_new(g_int64_hash, g_int64_equal); 533 plugin.cpu_ht = g_hash_table_new(g_int_hash, g_int_equal); 534 QTAILQ_INIT(&plugin.ctxs); 535 qht_init(&plugin.dyn_cb_arr_ht, plugin_dyn_cb_arr_cmp, 16, 536 QHT_MODE_AUTO_RESIZE); 537 atexit(qemu_plugin_atexit_cb); 538 } 539