xref: /openbmc/qemu/trace/control-target.c (revision 6e99f5741ff1b408ea76e6caf2bd4f76df4060e9)
1  /*
2   * Interface for configuring and controlling the state of 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  
10  #include "qemu/osdep.h"
11  #include "cpu.h"
12  #include "trace.h"
13  #include "trace/control.h"
14  #include "translate-all.h"
15  
16  
17  void trace_event_set_state_dynamic_init(TraceEvent *ev, bool state)
18  {
19      bool state_pre;
20      assert(trace_event_get_state_static(ev));
21      /*
22       * We ignore the "vcpu" property here, since no vCPUs have been created
23       * yet. Then dstate can only be 1 or 0.
24       */
25      state_pre = *ev->dstate;
26      if (state_pre != state) {
27          if (state) {
28              trace_events_enabled_count++;
29              *ev->dstate = 1;
30          } else {
31              trace_events_enabled_count--;
32              *ev->dstate = 0;
33          }
34      }
35  }
36  
37  void trace_event_set_state_dynamic(TraceEvent *ev, bool state)
38  {
39      CPUState *vcpu;
40      assert(trace_event_get_state_static(ev));
41      if (trace_event_is_vcpu(ev)) {
42          CPU_FOREACH(vcpu) {
43              trace_event_set_vcpu_state_dynamic(vcpu, ev, state);
44          }
45      } else {
46          /* Without the "vcpu" property, dstate can only be 1 or 0 */
47          bool state_pre = *ev->dstate;
48          if (state_pre != state) {
49              if (state) {
50                  trace_events_enabled_count++;
51                  *ev->dstate = 1;
52              } else {
53                  trace_events_enabled_count--;
54                  *ev->dstate = 0;
55              }
56          }
57      }
58  }
59  
60  void trace_event_set_vcpu_state_dynamic(CPUState *vcpu,
61                                          TraceEvent *ev, bool state)
62  {
63      uint32_t vcpu_id;
64      bool state_pre;
65      assert(trace_event_get_state_static(ev));
66      assert(trace_event_is_vcpu(ev));
67      vcpu_id = trace_event_get_vcpu_id(ev);
68      state_pre = test_bit(vcpu_id, vcpu->trace_dstate);
69      if (state_pre != state) {
70          if (state) {
71              trace_events_enabled_count++;
72              set_bit(vcpu_id, vcpu->trace_dstate);
73              (*ev->dstate)++;
74          } else {
75              trace_events_enabled_count--;
76              clear_bit(vcpu_id, vcpu->trace_dstate);
77              (*ev->dstate)--;
78          }
79      }
80  }
81  
82  static bool adding_first_cpu(void)
83  {
84      CPUState *cpu;
85      size_t count = 0;
86      CPU_FOREACH(cpu) {
87          count++;
88          if (count > 1) {
89              return false;
90          }
91      }
92      return true;
93  }
94  
95  void trace_init_vcpu(CPUState *vcpu)
96  {
97      TraceEventIter iter;
98      TraceEvent *ev;
99      trace_event_iter_init(&iter, NULL);
100      while ((ev = trace_event_iter_next(&iter)) != NULL) {
101          if (trace_event_is_vcpu(ev) &&
102              trace_event_get_state_static(ev) &&
103              trace_event_get_state_dynamic(ev)) {
104              if (adding_first_cpu()) {
105                  /* check preconditions */
106                  assert(*ev->dstate == 1);
107                  /* disable early-init state ... */
108                  *ev->dstate = 0;
109                  trace_events_enabled_count--;
110                  /* ... and properly re-enable */
111                  trace_event_set_vcpu_state_dynamic(vcpu, ev, true);
112              } else {
113                  trace_event_set_vcpu_state_dynamic(vcpu, ev, true);
114              }
115          }
116      }
117      trace_guest_cpu_enter(vcpu);
118  }
119