1 /* 2 * SPDX-License-Identifier: LGPL-2.1-or-later 3 * 4 * QEMU TCG monitor 5 * 6 * Copyright (c) 2003-2005 Fabrice Bellard 7 */ 8 9 #include "qemu/osdep.h" 10 #include "qemu/accel.h" 11 #include "qapi/error.h" 12 #include "qapi/type-helpers.h" 13 #include "qapi/qapi-commands-machine.h" 14 #include "monitor/monitor.h" 15 #include "sysemu/cpus.h" 16 #include "sysemu/cpu-timers.h" 17 #include "sysemu/tcg.h" 18 #include "internal.h" 19 20 21 static void dump_drift_info(GString *buf) 22 { 23 if (!icount_enabled()) { 24 return; 25 } 26 27 g_string_append_printf(buf, "Host - Guest clock %"PRIi64" ms\n", 28 (cpu_get_clock() - icount_get()) / SCALE_MS); 29 if (icount_align_option) { 30 g_string_append_printf(buf, "Max guest delay %"PRIi64" ms\n", 31 -max_delay / SCALE_MS); 32 g_string_append_printf(buf, "Max guest advance %"PRIi64" ms\n", 33 max_advance / SCALE_MS); 34 } else { 35 g_string_append_printf(buf, "Max guest delay NA\n"); 36 g_string_append_printf(buf, "Max guest advance NA\n"); 37 } 38 } 39 40 static void dump_accel_info(GString *buf) 41 { 42 AccelState *accel = current_accel(); 43 bool one_insn_per_tb = object_property_get_bool(OBJECT(accel), 44 "one-insn-per-tb", 45 &error_fatal); 46 47 g_string_append_printf(buf, "Accelerator settings:\n"); 48 g_string_append_printf(buf, "one-insn-per-tb: %s\n\n", 49 one_insn_per_tb ? "on" : "off"); 50 } 51 52 HumanReadableText *qmp_x_query_jit(Error **errp) 53 { 54 g_autoptr(GString) buf = g_string_new(""); 55 56 if (!tcg_enabled()) { 57 error_setg(errp, "JIT information is only available with accel=tcg"); 58 return NULL; 59 } 60 61 dump_accel_info(buf); 62 dump_exec_info(buf); 63 dump_drift_info(buf); 64 65 return human_readable_text_from_str(buf); 66 } 67 68 HumanReadableText *qmp_x_query_opcount(Error **errp) 69 { 70 g_autoptr(GString) buf = g_string_new(""); 71 72 if (!tcg_enabled()) { 73 error_setg(errp, 74 "Opcode count information is only available with accel=tcg"); 75 return NULL; 76 } 77 78 tcg_dump_op_count(buf); 79 80 return human_readable_text_from_str(buf); 81 } 82 83 #ifdef CONFIG_PROFILER 84 85 int64_t dev_time; 86 87 HumanReadableText *qmp_x_query_profile(Error **errp) 88 { 89 g_autoptr(GString) buf = g_string_new(""); 90 static int64_t last_cpu_exec_time; 91 int64_t cpu_exec_time; 92 int64_t delta; 93 94 cpu_exec_time = tcg_cpu_exec_time(); 95 delta = cpu_exec_time - last_cpu_exec_time; 96 97 g_string_append_printf(buf, "async time %" PRId64 " (%0.3f)\n", 98 dev_time, dev_time / (double)NANOSECONDS_PER_SECOND); 99 g_string_append_printf(buf, "qemu time %" PRId64 " (%0.3f)\n", 100 delta, delta / (double)NANOSECONDS_PER_SECOND); 101 last_cpu_exec_time = cpu_exec_time; 102 dev_time = 0; 103 104 return human_readable_text_from_str(buf); 105 } 106 #else 107 HumanReadableText *qmp_x_query_profile(Error **errp) 108 { 109 error_setg(errp, "Internal profiler not compiled"); 110 return NULL; 111 } 112 #endif 113 114 static void hmp_tcg_register(void) 115 { 116 monitor_register_hmp_info_hrt("jit", qmp_x_query_jit); 117 monitor_register_hmp_info_hrt("opcount", qmp_x_query_opcount); 118 } 119 120 type_init(hmp_tcg_register); 121