control-target.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /*
  2. * Interface for configuring and controlling the state of tracing events.
  3. *
  4. * Copyright (C) 2014-2017 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 "cpu.h"
  11. #include "trace-root.h"
  12. #include "trace/control.h"
  13. void trace_event_set_state_dynamic_init(TraceEvent *ev, bool state)
  14. {
  15. bool state_pre;
  16. assert(trace_event_get_state_static(ev));
  17. /*
  18. * We ignore the "vcpu" property here, since no vCPUs have been created
  19. * yet. Then dstate can only be 1 or 0.
  20. */
  21. state_pre = *ev->dstate;
  22. if (state_pre != state) {
  23. if (state) {
  24. trace_events_enabled_count++;
  25. *ev->dstate = 1;
  26. } else {
  27. trace_events_enabled_count--;
  28. *ev->dstate = 0;
  29. }
  30. }
  31. }
  32. void trace_event_set_state_dynamic(TraceEvent *ev, bool state)
  33. {
  34. CPUState *vcpu;
  35. assert(trace_event_get_state_static(ev));
  36. if (trace_event_is_vcpu(ev) && likely(first_cpu != NULL)) {
  37. CPU_FOREACH(vcpu) {
  38. trace_event_set_vcpu_state_dynamic(vcpu, ev, state);
  39. }
  40. } else {
  41. /*
  42. * Without the "vcpu" property, dstate can only be 1 or 0. With it, we
  43. * haven't instantiated any vCPU yet, so we will set a global state
  44. * instead, and trace_init_vcpu will reconcile it afterwards.
  45. */
  46. bool state_pre = *ev->dstate;
  47. if (state_pre != state) {
  48. if (state) {
  49. trace_events_enabled_count++;
  50. *ev->dstate = 1;
  51. } else {
  52. trace_events_enabled_count--;
  53. *ev->dstate = 0;
  54. }
  55. }
  56. }
  57. }
  58. static void trace_event_synchronize_vcpu_state_dynamic(
  59. CPUState *vcpu, run_on_cpu_data ignored)
  60. {
  61. bitmap_copy(vcpu->trace_dstate, vcpu->trace_dstate_delayed,
  62. CPU_TRACE_DSTATE_MAX_EVENTS);
  63. cpu_tb_jmp_cache_clear(vcpu);
  64. }
  65. void trace_event_set_vcpu_state_dynamic(CPUState *vcpu,
  66. TraceEvent *ev, bool state)
  67. {
  68. uint32_t vcpu_id;
  69. bool state_pre;
  70. assert(trace_event_get_state_static(ev));
  71. assert(trace_event_is_vcpu(ev));
  72. vcpu_id = trace_event_get_vcpu_id(ev);
  73. state_pre = test_bit(vcpu_id, vcpu->trace_dstate);
  74. if (state_pre != state) {
  75. if (state) {
  76. trace_events_enabled_count++;
  77. set_bit(vcpu_id, vcpu->trace_dstate_delayed);
  78. (*ev->dstate)++;
  79. } else {
  80. trace_events_enabled_count--;
  81. clear_bit(vcpu_id, vcpu->trace_dstate_delayed);
  82. (*ev->dstate)--;
  83. }
  84. if (vcpu->created) {
  85. /*
  86. * Delay changes until next TB; we want all TBs to be built from a
  87. * single set of dstate values to ensure consistency of generated
  88. * tracing code.
  89. */
  90. async_run_on_cpu(vcpu, trace_event_synchronize_vcpu_state_dynamic,
  91. RUN_ON_CPU_NULL);
  92. } else {
  93. trace_event_synchronize_vcpu_state_dynamic(vcpu, RUN_ON_CPU_NULL);
  94. }
  95. }
  96. }
  97. static bool adding_first_cpu1(void)
  98. {
  99. CPUState *cpu;
  100. size_t count = 0;
  101. CPU_FOREACH(cpu) {
  102. count++;
  103. if (count > 1) {
  104. return false;
  105. }
  106. }
  107. return true;
  108. }
  109. static bool adding_first_cpu(void)
  110. {
  111. bool res;
  112. cpu_list_lock();
  113. res = adding_first_cpu1();
  114. cpu_list_unlock();
  115. return res;
  116. }
  117. void trace_init_vcpu(CPUState *vcpu)
  118. {
  119. TraceEventIter iter;
  120. TraceEvent *ev;
  121. trace_event_iter_init(&iter, NULL);
  122. while ((ev = trace_event_iter_next(&iter)) != NULL) {
  123. if (trace_event_is_vcpu(ev) &&
  124. trace_event_get_state_static(ev) &&
  125. trace_event_get_state_dynamic(ev)) {
  126. if (adding_first_cpu()) {
  127. /* check preconditions */
  128. assert(*ev->dstate == 1);
  129. /* disable early-init state ... */
  130. *ev->dstate = 0;
  131. trace_events_enabled_count--;
  132. /* ... and properly re-enable */
  133. trace_event_set_vcpu_state_dynamic(vcpu, ev, true);
  134. } else {
  135. trace_event_set_vcpu_state_dynamic(vcpu, ev, true);
  136. }
  137. }
  138. }
  139. trace_guest_cpu_enter(vcpu);
  140. }