xref: /openbmc/qemu/trace/qmp.c (revision 77e2b172)
11dde0f48SLluís Vilanova /*
21dde0f48SLluís Vilanova  * QMP commands for tracing events.
31dde0f48SLluís Vilanova  *
4*77e2b172SLluís Vilanova  * Copyright (C) 2014-2016 Lluís Vilanova <vilanova@ac.upc.edu>
51dde0f48SLluís Vilanova  *
61dde0f48SLluís Vilanova  * This work is licensed under the terms of the GNU GPL, version 2 or later.
71dde0f48SLluís Vilanova  * See the COPYING file in the top-level directory.
81dde0f48SLluís Vilanova  */
91dde0f48SLluís Vilanova 
10d38ea87aSPeter Maydell #include "qemu/osdep.h"
111dde0f48SLluís Vilanova #include "qmp-commands.h"
121dde0f48SLluís Vilanova #include "trace/control.h"
131dde0f48SLluís Vilanova 
141dde0f48SLluís Vilanova 
15*77e2b172SLluís Vilanova static CPUState *get_cpu(bool has_vcpu, int vcpu, Error **errp)
161dde0f48SLluís Vilanova {
17*77e2b172SLluís Vilanova     if (has_vcpu) {
18*77e2b172SLluís Vilanova         CPUState *cpu = qemu_get_cpu(vcpu);
19*77e2b172SLluís Vilanova         if (cpu == NULL) {
20*77e2b172SLluís Vilanova             error_setg(errp, "invalid vCPU index %u", vcpu);
21*77e2b172SLluís Vilanova         }
22*77e2b172SLluís Vilanova         return cpu;
23*77e2b172SLluís Vilanova     } else {
24*77e2b172SLluís Vilanova         return NULL;
25*77e2b172SLluís Vilanova     }
26*77e2b172SLluís Vilanova }
271dde0f48SLluís Vilanova 
28*77e2b172SLluís Vilanova static bool check_events(bool has_vcpu, bool ignore_unavailable, bool is_pattern,
29*77e2b172SLluís Vilanova                          const char *name, Error **errp)
30*77e2b172SLluís Vilanova {
31*77e2b172SLluís Vilanova     if (!is_pattern) {
32*77e2b172SLluís Vilanova         TraceEvent *ev = trace_event_name(name);
33*77e2b172SLluís Vilanova 
34*77e2b172SLluís Vilanova         /* error for non-existing event */
35*77e2b172SLluís Vilanova         if (ev == NULL) {
36*77e2b172SLluís Vilanova             error_setg(errp, "unknown event \"%s\"", name);
37*77e2b172SLluís Vilanova             return false;
38*77e2b172SLluís Vilanova         }
39*77e2b172SLluís Vilanova 
40*77e2b172SLluís Vilanova         /* error for non-vcpu event */
41*77e2b172SLluís Vilanova         if (has_vcpu && !trace_event_is_vcpu(ev)) {
42*77e2b172SLluís Vilanova             error_setg(errp, "event \"%s\" is not vCPU-specific", name);
43*77e2b172SLluís Vilanova             return false;
44*77e2b172SLluís Vilanova         }
45*77e2b172SLluís Vilanova 
46*77e2b172SLluís Vilanova         /* error for unavailable event */
47*77e2b172SLluís Vilanova         if (!ignore_unavailable && !trace_event_get_state_static(ev)) {
48*77e2b172SLluís Vilanova             error_setg(errp, "event \"%s\" is disabled", name);
49*77e2b172SLluís Vilanova             return false;
50*77e2b172SLluís Vilanova         }
51*77e2b172SLluís Vilanova 
52*77e2b172SLluís Vilanova         return true;
53*77e2b172SLluís Vilanova     } else {
54*77e2b172SLluís Vilanova         /* error for unavailable events */
55*77e2b172SLluís Vilanova         TraceEvent *ev = NULL;
56*77e2b172SLluís Vilanova         while ((ev = trace_event_pattern(name, ev)) != NULL) {
57*77e2b172SLluís Vilanova             if (!ignore_unavailable && !trace_event_get_state_static(ev)) {
58*77e2b172SLluís Vilanova                 error_setg(errp, "event \"%s\" is disabled", trace_event_get_name(ev));
59*77e2b172SLluís Vilanova                 return false;
60*77e2b172SLluís Vilanova             }
61*77e2b172SLluís Vilanova         }
62*77e2b172SLluís Vilanova         return true;
63*77e2b172SLluís Vilanova     }
64*77e2b172SLluís Vilanova }
65*77e2b172SLluís Vilanova 
66*77e2b172SLluís Vilanova TraceEventInfoList *qmp_trace_event_get_state(const char *name,
67*77e2b172SLluís Vilanova                                               bool has_vcpu, int64_t vcpu,
68*77e2b172SLluís Vilanova                                               Error **errp)
69*77e2b172SLluís Vilanova {
70*77e2b172SLluís Vilanova     Error *err = NULL;
71*77e2b172SLluís Vilanova     TraceEventInfoList *events = NULL;
72*77e2b172SLluís Vilanova     TraceEvent *ev;
73*77e2b172SLluís Vilanova     bool is_pattern = trace_event_is_pattern(name);
74*77e2b172SLluís Vilanova     CPUState *cpu;
75*77e2b172SLluís Vilanova 
76*77e2b172SLluís Vilanova     /* Check provided vcpu */
77*77e2b172SLluís Vilanova     cpu = get_cpu(has_vcpu, vcpu, &err);
78*77e2b172SLluís Vilanova     if (err) {
79*77e2b172SLluís Vilanova         error_propagate(errp, err);
80*77e2b172SLluís Vilanova         return NULL;
81*77e2b172SLluís Vilanova     }
82*77e2b172SLluís Vilanova 
83*77e2b172SLluís Vilanova     /* Check events */
84*77e2b172SLluís Vilanova     if (!check_events(has_vcpu, true, is_pattern, name, errp)) {
85*77e2b172SLluís Vilanova         return NULL;
86*77e2b172SLluís Vilanova     }
87*77e2b172SLluís Vilanova 
88*77e2b172SLluís Vilanova     /* Get states (all errors checked above) */
891dde0f48SLluís Vilanova     ev = NULL;
901dde0f48SLluís Vilanova     while ((ev = trace_event_pattern(name, ev)) != NULL) {
91*77e2b172SLluís Vilanova         TraceEventInfoList *elem;
92*77e2b172SLluís Vilanova         bool is_vcpu = trace_event_is_vcpu(ev);
93*77e2b172SLluís Vilanova         if (has_vcpu && !is_vcpu) {
94*77e2b172SLluís Vilanova             continue;
95*77e2b172SLluís Vilanova         }
96*77e2b172SLluís Vilanova 
97*77e2b172SLluís Vilanova         elem = g_new(TraceEventInfoList, 1);
981dde0f48SLluís Vilanova         elem->value = g_new(TraceEventInfo, 1);
99*77e2b172SLluís Vilanova         elem->value->vcpu = is_vcpu;
1001dde0f48SLluís Vilanova         elem->value->name = g_strdup(trace_event_get_name(ev));
101*77e2b172SLluís Vilanova 
1021dde0f48SLluís Vilanova         if (!trace_event_get_state_static(ev)) {
1031dde0f48SLluís Vilanova             elem->value->state = TRACE_EVENT_STATE_UNAVAILABLE;
1041dde0f48SLluís Vilanova         } else {
105*77e2b172SLluís Vilanova             if (has_vcpu) {
106*77e2b172SLluís Vilanova                 if (is_vcpu) {
107*77e2b172SLluís Vilanova                     if (trace_event_get_vcpu_state_dynamic(cpu, ev)) {
1081dde0f48SLluís Vilanova                         elem->value->state = TRACE_EVENT_STATE_ENABLED;
109*77e2b172SLluís Vilanova                     } else {
110*77e2b172SLluís Vilanova                         elem->value->state = TRACE_EVENT_STATE_DISABLED;
111*77e2b172SLluís Vilanova                     }
112*77e2b172SLluís Vilanova                 }
113*77e2b172SLluís Vilanova                 /* else: already skipped above */
114*77e2b172SLluís Vilanova             } else {
115*77e2b172SLluís Vilanova                 if (trace_event_get_state_dynamic(ev)) {
116*77e2b172SLluís Vilanova                     elem->value->state = TRACE_EVENT_STATE_ENABLED;
117*77e2b172SLluís Vilanova                 } else {
118*77e2b172SLluís Vilanova                     elem->value->state = TRACE_EVENT_STATE_DISABLED;
119*77e2b172SLluís Vilanova                 }
120*77e2b172SLluís Vilanova             }
1211dde0f48SLluís Vilanova         }
1221dde0f48SLluís Vilanova         elem->next = events;
1231dde0f48SLluís Vilanova         events = elem;
1241dde0f48SLluís Vilanova     }
1251dde0f48SLluís Vilanova 
1261dde0f48SLluís Vilanova     return events;
1271dde0f48SLluís Vilanova }
1281dde0f48SLluís Vilanova 
1291dde0f48SLluís Vilanova void qmp_trace_event_set_state(const char *name, bool enable,
130*77e2b172SLluís Vilanova                                bool has_ignore_unavailable, bool ignore_unavailable,
131*77e2b172SLluís Vilanova                                bool has_vcpu, int64_t vcpu,
132*77e2b172SLluís Vilanova                                Error **errp)
1331dde0f48SLluís Vilanova {
134*77e2b172SLluís Vilanova     Error *err = NULL;
1351dde0f48SLluís Vilanova     TraceEvent *ev;
136*77e2b172SLluís Vilanova     bool is_pattern = trace_event_is_pattern(name);
137*77e2b172SLluís Vilanova     CPUState *cpu;
1381dde0f48SLluís Vilanova 
139*77e2b172SLluís Vilanova     /* Check provided vcpu */
140*77e2b172SLluís Vilanova     cpu = get_cpu(has_vcpu, vcpu, &err);
141*77e2b172SLluís Vilanova     if (err) {
142*77e2b172SLluís Vilanova         error_propagate(errp, err);
1431dde0f48SLluís Vilanova         return;
1441dde0f48SLluís Vilanova     }
1451dde0f48SLluís Vilanova 
146*77e2b172SLluís Vilanova     /* Check events */
147*77e2b172SLluís Vilanova     if (!check_events(has_vcpu, has_ignore_unavailable && ignore_unavailable,
148*77e2b172SLluís Vilanova                       is_pattern, name, errp)) {
149*77e2b172SLluís Vilanova         return;
150*77e2b172SLluís Vilanova     }
151*77e2b172SLluís Vilanova 
152*77e2b172SLluís Vilanova     /* Apply changes (all errors checked above) */
1531dde0f48SLluís Vilanova     ev = NULL;
1541dde0f48SLluís Vilanova     while ((ev = trace_event_pattern(name, ev)) != NULL) {
155*77e2b172SLluís Vilanova         if (!trace_event_get_state_static(ev) ||
156*77e2b172SLluís Vilanova             (has_vcpu && !trace_event_is_vcpu(ev))) {
157*77e2b172SLluís Vilanova             continue;
158*77e2b172SLluís Vilanova         }
159*77e2b172SLluís Vilanova         if (has_vcpu) {
160*77e2b172SLluís Vilanova             trace_event_set_vcpu_state_dynamic(cpu, ev, enable);
161*77e2b172SLluís Vilanova         } else {
1621dde0f48SLluís Vilanova             trace_event_set_state_dynamic(ev, enable);
1631dde0f48SLluís Vilanova         }
1641dde0f48SLluís Vilanova     }
1651dde0f48SLluís Vilanova }
166