control.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /*
  2. * Interface for configuring and controlling the state of tracing events.
  3. *
  4. * Copyright (C) 2011-2016 Lluís Vilanova <vilanova@ac.upc.edu>
  5. *
  6. * This work is licensed under the terms of the GNU GPL, version 2 or later.
  7. * See the COPYING file in the top-level directory.
  8. */
  9. #include "qemu/osdep.h"
  10. #include "trace/control.h"
  11. #include "qemu/help_option.h"
  12. #include "qemu/option.h"
  13. #ifdef CONFIG_TRACE_SIMPLE
  14. #include "trace/simple.h"
  15. #endif
  16. #ifdef CONFIG_TRACE_FTRACE
  17. #include "trace/ftrace.h"
  18. #endif
  19. #ifdef CONFIG_TRACE_LOG
  20. #include "qemu/log.h"
  21. #endif
  22. #ifdef CONFIG_TRACE_SYSLOG
  23. #include <syslog.h>
  24. #endif
  25. #include "qapi/error.h"
  26. #include "qemu/error-report.h"
  27. #include "qemu/config-file.h"
  28. #include "monitor/monitor.h"
  29. #include "trace/trace-root.h"
  30. int trace_events_enabled_count;
  31. typedef struct TraceEventGroup {
  32. TraceEvent **events;
  33. } TraceEventGroup;
  34. static TraceEventGroup *event_groups;
  35. static size_t nevent_groups;
  36. static uint32_t next_id;
  37. static uint32_t next_vcpu_id;
  38. static bool init_trace_on_startup;
  39. static char *trace_opts_file;
  40. QemuOptsList qemu_trace_opts = {
  41. .name = "trace",
  42. .implied_opt_name = "enable",
  43. .head = QTAILQ_HEAD_INITIALIZER(qemu_trace_opts.head),
  44. .desc = {
  45. {
  46. .name = "enable",
  47. .type = QEMU_OPT_STRING,
  48. },
  49. {
  50. .name = "events",
  51. .type = QEMU_OPT_STRING,
  52. },{
  53. .name = "file",
  54. .type = QEMU_OPT_STRING,
  55. },
  56. { /* end of list */ }
  57. },
  58. };
  59. void trace_event_register_group(TraceEvent **events)
  60. {
  61. size_t i;
  62. for (i = 0; events[i] != NULL; i++) {
  63. events[i]->id = next_id++;
  64. if (events[i]->vcpu_id == TRACE_VCPU_EVENT_NONE) {
  65. continue;
  66. }
  67. if (likely(next_vcpu_id < CPU_TRACE_DSTATE_MAX_EVENTS)) {
  68. events[i]->vcpu_id = next_vcpu_id++;
  69. } else {
  70. warn_report("too many vcpu trace events; dropping '%s'",
  71. events[i]->name);
  72. }
  73. }
  74. event_groups = g_renew(TraceEventGroup, event_groups, nevent_groups + 1);
  75. event_groups[nevent_groups].events = events;
  76. nevent_groups++;
  77. #ifdef CONFIG_TRACE_SIMPLE
  78. st_init_group(nevent_groups - 1);
  79. #endif
  80. }
  81. TraceEvent *trace_event_name(const char *name)
  82. {
  83. assert(name != NULL);
  84. TraceEventIter iter;
  85. TraceEvent *ev;
  86. trace_event_iter_init_all(&iter);
  87. while ((ev = trace_event_iter_next(&iter)) != NULL) {
  88. if (strcmp(trace_event_get_name(ev), name) == 0) {
  89. return ev;
  90. }
  91. }
  92. return NULL;
  93. }
  94. void trace_event_iter_init_all(TraceEventIter *iter)
  95. {
  96. iter->event = 0;
  97. iter->group = 0;
  98. iter->group_id = -1;
  99. iter->pattern = NULL;
  100. }
  101. void trace_event_iter_init_pattern(TraceEventIter *iter, const char *pattern)
  102. {
  103. trace_event_iter_init_all(iter);
  104. iter->pattern = pattern;
  105. }
  106. void trace_event_iter_init_group(TraceEventIter *iter, size_t group_id)
  107. {
  108. trace_event_iter_init_all(iter);
  109. iter->group_id = group_id;
  110. }
  111. TraceEvent *trace_event_iter_next(TraceEventIter *iter)
  112. {
  113. while (iter->group < nevent_groups &&
  114. event_groups[iter->group].events[iter->event] != NULL) {
  115. TraceEvent *ev = event_groups[iter->group].events[iter->event];
  116. size_t group = iter->group;
  117. iter->event++;
  118. if (event_groups[iter->group].events[iter->event] == NULL) {
  119. iter->event = 0;
  120. iter->group++;
  121. }
  122. if (iter->pattern &&
  123. !g_pattern_match_simple(iter->pattern, trace_event_get_name(ev))) {
  124. continue;
  125. }
  126. if (iter->group_id != -1 &&
  127. iter->group_id != group) {
  128. continue;
  129. }
  130. return ev;
  131. }
  132. return NULL;
  133. }
  134. void trace_list_events(FILE *f)
  135. {
  136. TraceEventIter iter;
  137. TraceEvent *ev;
  138. trace_event_iter_init_all(&iter);
  139. while ((ev = trace_event_iter_next(&iter)) != NULL) {
  140. fprintf(f, "%s\n", trace_event_get_name(ev));
  141. }
  142. #ifdef CONFIG_TRACE_DTRACE
  143. fprintf(f, "This list of names of trace points may be incomplete "
  144. "when using the DTrace/SystemTap backends.\n"
  145. "Run 'qemu-trace-stap list %s' to print the full list.\n",
  146. g_get_prgname());
  147. #endif
  148. }
  149. static void do_trace_enable_events(const char *line_buf)
  150. {
  151. const bool enable = ('-' != line_buf[0]);
  152. const char *line_ptr = enable ? line_buf : line_buf + 1;
  153. TraceEventIter iter;
  154. TraceEvent *ev;
  155. bool is_pattern = trace_event_is_pattern(line_ptr);
  156. trace_event_iter_init_pattern(&iter, line_ptr);
  157. while ((ev = trace_event_iter_next(&iter)) != NULL) {
  158. if (!trace_event_get_state_static(ev)) {
  159. if (!is_pattern) {
  160. warn_report("trace event '%s' is not traceable",
  161. line_ptr);
  162. return;
  163. }
  164. continue;
  165. }
  166. /* start tracing */
  167. trace_event_set_state_dynamic(ev, enable);
  168. if (!is_pattern) {
  169. return;
  170. }
  171. }
  172. if (!is_pattern) {
  173. warn_report("trace event '%s' does not exist",
  174. line_ptr);
  175. }
  176. }
  177. void trace_enable_events(const char *line_buf)
  178. {
  179. if (is_help_option(line_buf)) {
  180. trace_list_events(stdout);
  181. if (monitor_cur() == NULL) {
  182. exit(0);
  183. }
  184. } else {
  185. do_trace_enable_events(line_buf);
  186. }
  187. }
  188. static void trace_init_events(const char *fname)
  189. {
  190. Location loc;
  191. FILE *fp;
  192. char line_buf[1024];
  193. size_t line_idx = 0;
  194. if (fname == NULL) {
  195. return;
  196. }
  197. loc_push_none(&loc);
  198. loc_set_file(fname, 0);
  199. fp = fopen(fname, "r");
  200. if (!fp) {
  201. error_report("%s", strerror(errno));
  202. exit(1);
  203. }
  204. while (fgets(line_buf, sizeof(line_buf), fp)) {
  205. loc_set_file(fname, ++line_idx);
  206. size_t len = strlen(line_buf);
  207. if (len > 1) { /* skip empty lines */
  208. line_buf[len - 1] = '\0';
  209. if ('#' == line_buf[0]) { /* skip commented lines */
  210. continue;
  211. }
  212. trace_enable_events(line_buf);
  213. }
  214. }
  215. if (fclose(fp) != 0) {
  216. loc_set_file(fname, 0);
  217. error_report("%s", strerror(errno));
  218. exit(1);
  219. }
  220. loc_pop(&loc);
  221. }
  222. void trace_init_file(void)
  223. {
  224. #ifdef CONFIG_TRACE_SIMPLE
  225. st_set_trace_file(trace_opts_file);
  226. if (init_trace_on_startup) {
  227. st_set_trace_file_enabled(true);
  228. }
  229. #elif defined CONFIG_TRACE_LOG
  230. /*
  231. * If both the simple and the log backends are enabled, "--trace file"
  232. * only applies to the simple backend; use "-D" for the log
  233. * backend. However we should only override -D if we actually have
  234. * something to override it with.
  235. */
  236. if (trace_opts_file) {
  237. qemu_set_log_filename(trace_opts_file, &error_fatal);
  238. }
  239. #else
  240. if (trace_opts_file) {
  241. fprintf(stderr, "error: --trace file=...: "
  242. "option not supported by the selected tracing backends\n");
  243. exit(1);
  244. }
  245. #endif
  246. }
  247. void trace_fini_vcpu(CPUState *vcpu)
  248. {
  249. TraceEventIter iter;
  250. TraceEvent *ev;
  251. trace_guest_cpu_exit(vcpu);
  252. trace_event_iter_init_all(&iter);
  253. while ((ev = trace_event_iter_next(&iter)) != NULL) {
  254. if (trace_event_is_vcpu(ev) &&
  255. trace_event_get_state_static(ev) &&
  256. trace_event_get_vcpu_state_dynamic(vcpu, ev)) {
  257. /* must disable to affect the global counter */
  258. trace_event_set_vcpu_state_dynamic(vcpu, ev, false);
  259. }
  260. }
  261. }
  262. bool trace_init_backends(void)
  263. {
  264. #ifdef CONFIG_TRACE_SIMPLE
  265. if (!st_init()) {
  266. fprintf(stderr, "failed to initialize simple tracing backend.\n");
  267. return false;
  268. }
  269. #endif
  270. #ifdef CONFIG_TRACE_FTRACE
  271. if (!ftrace_init()) {
  272. fprintf(stderr, "failed to initialize ftrace backend.\n");
  273. return false;
  274. }
  275. #endif
  276. #ifdef CONFIG_TRACE_SYSLOG
  277. openlog(NULL, LOG_PID, LOG_DAEMON);
  278. #endif
  279. return true;
  280. }
  281. void trace_opt_parse(const char *optarg)
  282. {
  283. QemuOpts *opts = qemu_opts_parse_noisily(qemu_find_opts("trace"),
  284. optarg, true);
  285. if (!opts) {
  286. exit(1);
  287. }
  288. if (qemu_opt_get(opts, "enable")) {
  289. trace_enable_events(qemu_opt_get(opts, "enable"));
  290. }
  291. trace_init_events(qemu_opt_get(opts, "events"));
  292. init_trace_on_startup = true;
  293. g_free(trace_opts_file);
  294. trace_opts_file = g_strdup(qemu_opt_get(opts, "file"));
  295. qemu_opts_del(opts);
  296. }
  297. uint32_t trace_get_vcpu_event_count(void)
  298. {
  299. return next_vcpu_id;
  300. }