xref: /openbmc/qemu/trace/qmp.c (revision 0d4e995c)
11dde0f48SLluís Vilanova /*
21dde0f48SLluís Vilanova  * QMP commands for tracing events.
31dde0f48SLluís Vilanova  *
477e2b172SLluí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 
1577e2b172SLluís Vilanova static CPUState *get_cpu(bool has_vcpu, int vcpu, Error **errp)
161dde0f48SLluís Vilanova {
1777e2b172SLluís Vilanova     if (has_vcpu) {
1877e2b172SLluís Vilanova         CPUState *cpu = qemu_get_cpu(vcpu);
1977e2b172SLluís Vilanova         if (cpu == NULL) {
2077e2b172SLluís Vilanova             error_setg(errp, "invalid vCPU index %u", vcpu);
2177e2b172SLluís Vilanova         }
2277e2b172SLluís Vilanova         return cpu;
2377e2b172SLluís Vilanova     } else {
2477e2b172SLluís Vilanova         return NULL;
2577e2b172SLluís Vilanova     }
2677e2b172SLluís Vilanova }
271dde0f48SLluís Vilanova 
2877e2b172SLluís Vilanova static bool check_events(bool has_vcpu, bool ignore_unavailable, bool is_pattern,
2977e2b172SLluís Vilanova                          const char *name, Error **errp)
3077e2b172SLluís Vilanova {
3177e2b172SLluís Vilanova     if (!is_pattern) {
3277e2b172SLluís Vilanova         TraceEvent *ev = trace_event_name(name);
3377e2b172SLluís Vilanova 
3477e2b172SLluís Vilanova         /* error for non-existing event */
3577e2b172SLluís Vilanova         if (ev == NULL) {
3677e2b172SLluís Vilanova             error_setg(errp, "unknown event \"%s\"", name);
3777e2b172SLluís Vilanova             return false;
3877e2b172SLluís Vilanova         }
3977e2b172SLluís Vilanova 
4077e2b172SLluís Vilanova         /* error for non-vcpu event */
4177e2b172SLluís Vilanova         if (has_vcpu && !trace_event_is_vcpu(ev)) {
4277e2b172SLluís Vilanova             error_setg(errp, "event \"%s\" is not vCPU-specific", name);
4377e2b172SLluís Vilanova             return false;
4477e2b172SLluís Vilanova         }
4577e2b172SLluís Vilanova 
4677e2b172SLluís Vilanova         /* error for unavailable event */
4777e2b172SLluís Vilanova         if (!ignore_unavailable && !trace_event_get_state_static(ev)) {
4877e2b172SLluís Vilanova             error_setg(errp, "event \"%s\" is disabled", name);
4977e2b172SLluís Vilanova             return false;
5077e2b172SLluís Vilanova         }
5177e2b172SLluís Vilanova 
5277e2b172SLluís Vilanova         return true;
5377e2b172SLluís Vilanova     } else {
5477e2b172SLluís Vilanova         /* error for unavailable events */
55*0d4e995cSDaniel P. Berrange         TraceEventIter iter;
56*0d4e995cSDaniel P. Berrange         TraceEvent *ev;
57*0d4e995cSDaniel P. Berrange         trace_event_iter_init(&iter, name);
58*0d4e995cSDaniel P. Berrange         while ((ev = trace_event_iter_next(&iter)) != NULL) {
5977e2b172SLluís Vilanova             if (!ignore_unavailable && !trace_event_get_state_static(ev)) {
6077e2b172SLluís Vilanova                 error_setg(errp, "event \"%s\" is disabled", trace_event_get_name(ev));
6177e2b172SLluís Vilanova                 return false;
6277e2b172SLluís Vilanova             }
6377e2b172SLluís Vilanova         }
6477e2b172SLluís Vilanova         return true;
6577e2b172SLluís Vilanova     }
6677e2b172SLluís Vilanova }
6777e2b172SLluís Vilanova 
6877e2b172SLluís Vilanova TraceEventInfoList *qmp_trace_event_get_state(const char *name,
6977e2b172SLluís Vilanova                                               bool has_vcpu, int64_t vcpu,
7077e2b172SLluís Vilanova                                               Error **errp)
7177e2b172SLluís Vilanova {
7277e2b172SLluís Vilanova     Error *err = NULL;
7377e2b172SLluís Vilanova     TraceEventInfoList *events = NULL;
74*0d4e995cSDaniel P. Berrange     TraceEventIter iter;
7577e2b172SLluís Vilanova     TraceEvent *ev;
7677e2b172SLluís Vilanova     bool is_pattern = trace_event_is_pattern(name);
7777e2b172SLluís Vilanova     CPUState *cpu;
7877e2b172SLluís Vilanova 
7977e2b172SLluís Vilanova     /* Check provided vcpu */
8077e2b172SLluís Vilanova     cpu = get_cpu(has_vcpu, vcpu, &err);
8177e2b172SLluís Vilanova     if (err) {
8277e2b172SLluís Vilanova         error_propagate(errp, err);
8377e2b172SLluís Vilanova         return NULL;
8477e2b172SLluís Vilanova     }
8577e2b172SLluís Vilanova 
8677e2b172SLluís Vilanova     /* Check events */
8777e2b172SLluís Vilanova     if (!check_events(has_vcpu, true, is_pattern, name, errp)) {
8877e2b172SLluís Vilanova         return NULL;
8977e2b172SLluís Vilanova     }
9077e2b172SLluís Vilanova 
9177e2b172SLluís Vilanova     /* Get states (all errors checked above) */
92*0d4e995cSDaniel P. Berrange     trace_event_iter_init(&iter, name);
93*0d4e995cSDaniel P. Berrange     while ((ev = trace_event_iter_next(&iter)) != NULL) {
9477e2b172SLluís Vilanova         TraceEventInfoList *elem;
9577e2b172SLluís Vilanova         bool is_vcpu = trace_event_is_vcpu(ev);
9677e2b172SLluís Vilanova         if (has_vcpu && !is_vcpu) {
9777e2b172SLluís Vilanova             continue;
9877e2b172SLluís Vilanova         }
9977e2b172SLluís Vilanova 
10077e2b172SLluís Vilanova         elem = g_new(TraceEventInfoList, 1);
1011dde0f48SLluís Vilanova         elem->value = g_new(TraceEventInfo, 1);
10277e2b172SLluís Vilanova         elem->value->vcpu = is_vcpu;
1031dde0f48SLluís Vilanova         elem->value->name = g_strdup(trace_event_get_name(ev));
10477e2b172SLluís Vilanova 
1051dde0f48SLluís Vilanova         if (!trace_event_get_state_static(ev)) {
1061dde0f48SLluís Vilanova             elem->value->state = TRACE_EVENT_STATE_UNAVAILABLE;
1071dde0f48SLluís Vilanova         } else {
10877e2b172SLluís Vilanova             if (has_vcpu) {
10977e2b172SLluís Vilanova                 if (is_vcpu) {
11077e2b172SLluís Vilanova                     if (trace_event_get_vcpu_state_dynamic(cpu, ev)) {
1111dde0f48SLluís Vilanova                         elem->value->state = TRACE_EVENT_STATE_ENABLED;
11277e2b172SLluís Vilanova                     } else {
11377e2b172SLluís Vilanova                         elem->value->state = TRACE_EVENT_STATE_DISABLED;
11477e2b172SLluís Vilanova                     }
11577e2b172SLluís Vilanova                 }
11677e2b172SLluís Vilanova                 /* else: already skipped above */
11777e2b172SLluís Vilanova             } else {
11877e2b172SLluís Vilanova                 if (trace_event_get_state_dynamic(ev)) {
11977e2b172SLluís Vilanova                     elem->value->state = TRACE_EVENT_STATE_ENABLED;
12077e2b172SLluís Vilanova                 } else {
12177e2b172SLluís Vilanova                     elem->value->state = TRACE_EVENT_STATE_DISABLED;
12277e2b172SLluís Vilanova                 }
12377e2b172SLluís Vilanova             }
1241dde0f48SLluís Vilanova         }
1251dde0f48SLluís Vilanova         elem->next = events;
1261dde0f48SLluís Vilanova         events = elem;
1271dde0f48SLluís Vilanova     }
1281dde0f48SLluís Vilanova 
1291dde0f48SLluís Vilanova     return events;
1301dde0f48SLluís Vilanova }
1311dde0f48SLluís Vilanova 
1321dde0f48SLluís Vilanova void qmp_trace_event_set_state(const char *name, bool enable,
13377e2b172SLluís Vilanova                                bool has_ignore_unavailable, bool ignore_unavailable,
13477e2b172SLluís Vilanova                                bool has_vcpu, int64_t vcpu,
13577e2b172SLluís Vilanova                                Error **errp)
1361dde0f48SLluís Vilanova {
13777e2b172SLluís Vilanova     Error *err = NULL;
138*0d4e995cSDaniel P. Berrange     TraceEventIter iter;
1391dde0f48SLluís Vilanova     TraceEvent *ev;
14077e2b172SLluís Vilanova     bool is_pattern = trace_event_is_pattern(name);
14177e2b172SLluís Vilanova     CPUState *cpu;
1421dde0f48SLluís Vilanova 
14377e2b172SLluís Vilanova     /* Check provided vcpu */
14477e2b172SLluís Vilanova     cpu = get_cpu(has_vcpu, vcpu, &err);
14577e2b172SLluís Vilanova     if (err) {
14677e2b172SLluís Vilanova         error_propagate(errp, err);
1471dde0f48SLluís Vilanova         return;
1481dde0f48SLluís Vilanova     }
1491dde0f48SLluís Vilanova 
15077e2b172SLluís Vilanova     /* Check events */
15177e2b172SLluís Vilanova     if (!check_events(has_vcpu, has_ignore_unavailable && ignore_unavailable,
15277e2b172SLluís Vilanova                       is_pattern, name, errp)) {
15377e2b172SLluís Vilanova         return;
15477e2b172SLluís Vilanova     }
15577e2b172SLluís Vilanova 
15677e2b172SLluís Vilanova     /* Apply changes (all errors checked above) */
157*0d4e995cSDaniel P. Berrange     trace_event_iter_init(&iter, name);
158*0d4e995cSDaniel P. Berrange     while ((ev = trace_event_iter_next(&iter)) != NULL) {
15977e2b172SLluís Vilanova         if (!trace_event_get_state_static(ev) ||
16077e2b172SLluís Vilanova             (has_vcpu && !trace_event_is_vcpu(ev))) {
16177e2b172SLluís Vilanova             continue;
16277e2b172SLluís Vilanova         }
16377e2b172SLluís Vilanova         if (has_vcpu) {
16477e2b172SLluís Vilanova             trace_event_set_vcpu_state_dynamic(cpu, ev, enable);
16577e2b172SLluís Vilanova         } else {
1661dde0f48SLluís Vilanova             trace_event_set_state_dynamic(ev, enable);
1671dde0f48SLluís Vilanova         }
1681dde0f48SLluís Vilanova     }
1691dde0f48SLluís Vilanova }
170