qmp.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /*
  2. * QMP commands for tracing events.
  3. *
  4. * Copyright (C) 2014-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 "qmp-commands.h"
  11. #include "trace/control.h"
  12. static CPUState *get_cpu(bool has_vcpu, int vcpu, Error **errp)
  13. {
  14. if (has_vcpu) {
  15. CPUState *cpu = qemu_get_cpu(vcpu);
  16. if (cpu == NULL) {
  17. error_setg(errp, "invalid vCPU index %u", vcpu);
  18. }
  19. return cpu;
  20. } else {
  21. return NULL;
  22. }
  23. }
  24. static bool check_events(bool has_vcpu, bool ignore_unavailable, bool is_pattern,
  25. const char *name, Error **errp)
  26. {
  27. if (!is_pattern) {
  28. TraceEvent *ev = trace_event_name(name);
  29. /* error for non-existing event */
  30. if (ev == NULL) {
  31. error_setg(errp, "unknown event \"%s\"", name);
  32. return false;
  33. }
  34. /* error for non-vcpu event */
  35. if (has_vcpu && !trace_event_is_vcpu(ev)) {
  36. error_setg(errp, "event \"%s\" is not vCPU-specific", name);
  37. return false;
  38. }
  39. /* error for unavailable event */
  40. if (!ignore_unavailable && !trace_event_get_state_static(ev)) {
  41. error_setg(errp, "event \"%s\" is disabled", name);
  42. return false;
  43. }
  44. return true;
  45. } else {
  46. /* error for unavailable events */
  47. TraceEventIter iter;
  48. TraceEvent *ev;
  49. trace_event_iter_init(&iter, name);
  50. while ((ev = trace_event_iter_next(&iter)) != NULL) {
  51. if (!ignore_unavailable && !trace_event_get_state_static(ev)) {
  52. error_setg(errp, "event \"%s\" is disabled", trace_event_get_name(ev));
  53. return false;
  54. }
  55. }
  56. return true;
  57. }
  58. }
  59. TraceEventInfoList *qmp_trace_event_get_state(const char *name,
  60. bool has_vcpu, int64_t vcpu,
  61. Error **errp)
  62. {
  63. Error *err = NULL;
  64. TraceEventInfoList *events = NULL;
  65. TraceEventIter iter;
  66. TraceEvent *ev;
  67. bool is_pattern = trace_event_is_pattern(name);
  68. CPUState *cpu;
  69. /* Check provided vcpu */
  70. cpu = get_cpu(has_vcpu, vcpu, &err);
  71. if (err) {
  72. error_propagate(errp, err);
  73. return NULL;
  74. }
  75. /* Check events */
  76. if (!check_events(has_vcpu, true, is_pattern, name, errp)) {
  77. return NULL;
  78. }
  79. /* Get states (all errors checked above) */
  80. trace_event_iter_init(&iter, name);
  81. while ((ev = trace_event_iter_next(&iter)) != NULL) {
  82. TraceEventInfoList *elem;
  83. bool is_vcpu = trace_event_is_vcpu(ev);
  84. if (has_vcpu && !is_vcpu) {
  85. continue;
  86. }
  87. elem = g_new(TraceEventInfoList, 1);
  88. elem->value = g_new(TraceEventInfo, 1);
  89. elem->value->vcpu = is_vcpu;
  90. elem->value->name = g_strdup(trace_event_get_name(ev));
  91. if (!trace_event_get_state_static(ev)) {
  92. elem->value->state = TRACE_EVENT_STATE_UNAVAILABLE;
  93. } else {
  94. if (has_vcpu) {
  95. if (is_vcpu) {
  96. if (trace_event_get_vcpu_state_dynamic(cpu, ev)) {
  97. elem->value->state = TRACE_EVENT_STATE_ENABLED;
  98. } else {
  99. elem->value->state = TRACE_EVENT_STATE_DISABLED;
  100. }
  101. }
  102. /* else: already skipped above */
  103. } else {
  104. if (trace_event_get_state_dynamic(ev)) {
  105. elem->value->state = TRACE_EVENT_STATE_ENABLED;
  106. } else {
  107. elem->value->state = TRACE_EVENT_STATE_DISABLED;
  108. }
  109. }
  110. }
  111. elem->next = events;
  112. events = elem;
  113. }
  114. return events;
  115. }
  116. void qmp_trace_event_set_state(const char *name, bool enable,
  117. bool has_ignore_unavailable, bool ignore_unavailable,
  118. bool has_vcpu, int64_t vcpu,
  119. Error **errp)
  120. {
  121. Error *err = NULL;
  122. TraceEventIter iter;
  123. TraceEvent *ev;
  124. bool is_pattern = trace_event_is_pattern(name);
  125. CPUState *cpu;
  126. /* Check provided vcpu */
  127. cpu = get_cpu(has_vcpu, vcpu, &err);
  128. if (err) {
  129. error_propagate(errp, err);
  130. return;
  131. }
  132. /* Check events */
  133. if (!check_events(has_vcpu, has_ignore_unavailable && ignore_unavailable,
  134. is_pattern, name, errp)) {
  135. return;
  136. }
  137. /* Apply changes (all errors checked above) */
  138. trace_event_iter_init(&iter, name);
  139. while ((ev = trace_event_iter_next(&iter)) != NULL) {
  140. if (!trace_event_get_state_static(ev) ||
  141. (has_vcpu && !trace_event_is_vcpu(ev))) {
  142. continue;
  143. }
  144. if (has_vcpu) {
  145. trace_event_set_vcpu_state_dynamic(cpu, ev, enable);
  146. } else {
  147. trace_event_set_state_dynamic(ev, enable);
  148. }
  149. }
  150. }