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