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