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