xref: /openbmc/qemu/trace/qmp.c (revision e688df6b)
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"
11*e688df6bSMarkus Armbruster #include "qapi/error.h"
121dde0f48SLluís Vilanova #include "qmp-commands.h"
131dde0f48SLluís Vilanova #include "trace/control.h"
141dde0f48SLluís Vilanova 
151dde0f48SLluís Vilanova 
1677e2b172SLluís Vilanova static CPUState *get_cpu(bool has_vcpu, int vcpu, Error **errp)
171dde0f48SLluís Vilanova {
1877e2b172SLluís Vilanova     if (has_vcpu) {
1977e2b172SLluís Vilanova         CPUState *cpu = qemu_get_cpu(vcpu);
2077e2b172SLluís Vilanova         if (cpu == NULL) {
2177e2b172SLluís Vilanova             error_setg(errp, "invalid vCPU index %u", vcpu);
2277e2b172SLluís Vilanova         }
2377e2b172SLluís Vilanova         return cpu;
2477e2b172SLluís Vilanova     } else {
2577e2b172SLluís Vilanova         return NULL;
2677e2b172SLluís Vilanova     }
2777e2b172SLluís Vilanova }
281dde0f48SLluís Vilanova 
2977e2b172SLluís Vilanova static bool check_events(bool has_vcpu, bool ignore_unavailable, bool is_pattern,
3077e2b172SLluís Vilanova                          const char *name, Error **errp)
3177e2b172SLluís Vilanova {
3277e2b172SLluís Vilanova     if (!is_pattern) {
3377e2b172SLluís Vilanova         TraceEvent *ev = trace_event_name(name);
3477e2b172SLluís Vilanova 
3577e2b172SLluís Vilanova         /* error for non-existing event */
3677e2b172SLluís Vilanova         if (ev == NULL) {
3777e2b172SLluís Vilanova             error_setg(errp, "unknown event \"%s\"", name);
3877e2b172SLluís Vilanova             return false;
3977e2b172SLluís Vilanova         }
4077e2b172SLluís Vilanova 
4177e2b172SLluís Vilanova         /* error for non-vcpu event */
4277e2b172SLluís Vilanova         if (has_vcpu && !trace_event_is_vcpu(ev)) {
4377e2b172SLluís Vilanova             error_setg(errp, "event \"%s\" is not vCPU-specific", name);
4477e2b172SLluís Vilanova             return false;
4577e2b172SLluís Vilanova         }
4677e2b172SLluís Vilanova 
4777e2b172SLluís Vilanova         /* error for unavailable event */
4877e2b172SLluís Vilanova         if (!ignore_unavailable && !trace_event_get_state_static(ev)) {
4977e2b172SLluís Vilanova             error_setg(errp, "event \"%s\" is disabled", name);
5077e2b172SLluís Vilanova             return false;
5177e2b172SLluís Vilanova         }
5277e2b172SLluís Vilanova 
5377e2b172SLluís Vilanova         return true;
5477e2b172SLluís Vilanova     } else {
5577e2b172SLluís Vilanova         /* error for unavailable events */
560d4e995cSDaniel P. Berrange         TraceEventIter iter;
570d4e995cSDaniel P. Berrange         TraceEvent *ev;
580d4e995cSDaniel P. Berrange         trace_event_iter_init(&iter, name);
590d4e995cSDaniel P. Berrange         while ((ev = trace_event_iter_next(&iter)) != NULL) {
6077e2b172SLluís Vilanova             if (!ignore_unavailable && !trace_event_get_state_static(ev)) {
6177e2b172SLluís Vilanova                 error_setg(errp, "event \"%s\" is disabled", trace_event_get_name(ev));
6277e2b172SLluís Vilanova                 return false;
6377e2b172SLluís Vilanova             }
6477e2b172SLluís Vilanova         }
6577e2b172SLluís Vilanova         return true;
6677e2b172SLluís Vilanova     }
6777e2b172SLluís Vilanova }
6877e2b172SLluís Vilanova 
6977e2b172SLluís Vilanova TraceEventInfoList *qmp_trace_event_get_state(const char *name,
7077e2b172SLluís Vilanova                                               bool has_vcpu, int64_t vcpu,
7177e2b172SLluís Vilanova                                               Error **errp)
7277e2b172SLluís Vilanova {
7377e2b172SLluís Vilanova     Error *err = NULL;
7477e2b172SLluís Vilanova     TraceEventInfoList *events = NULL;
750d4e995cSDaniel P. Berrange     TraceEventIter iter;
7677e2b172SLluís Vilanova     TraceEvent *ev;
7777e2b172SLluís Vilanova     bool is_pattern = trace_event_is_pattern(name);
7877e2b172SLluís Vilanova     CPUState *cpu;
7977e2b172SLluís Vilanova 
8077e2b172SLluís Vilanova     /* Check provided vcpu */
8177e2b172SLluís Vilanova     cpu = get_cpu(has_vcpu, vcpu, &err);
8277e2b172SLluís Vilanova     if (err) {
8377e2b172SLluís Vilanova         error_propagate(errp, err);
8477e2b172SLluís Vilanova         return NULL;
8577e2b172SLluís Vilanova     }
8677e2b172SLluís Vilanova 
8777e2b172SLluís Vilanova     /* Check events */
8877e2b172SLluís Vilanova     if (!check_events(has_vcpu, true, is_pattern, name, errp)) {
8977e2b172SLluís Vilanova         return NULL;
9077e2b172SLluís Vilanova     }
9177e2b172SLluís Vilanova 
9277e2b172SLluís Vilanova     /* Get states (all errors checked above) */
930d4e995cSDaniel P. Berrange     trace_event_iter_init(&iter, name);
940d4e995cSDaniel P. Berrange     while ((ev = trace_event_iter_next(&iter)) != NULL) {
9577e2b172SLluís Vilanova         TraceEventInfoList *elem;
9677e2b172SLluís Vilanova         bool is_vcpu = trace_event_is_vcpu(ev);
9777e2b172SLluís Vilanova         if (has_vcpu && !is_vcpu) {
9877e2b172SLluís Vilanova             continue;
9977e2b172SLluís Vilanova         }
10077e2b172SLluís Vilanova 
10177e2b172SLluís Vilanova         elem = g_new(TraceEventInfoList, 1);
1021dde0f48SLluís Vilanova         elem->value = g_new(TraceEventInfo, 1);
10377e2b172SLluís Vilanova         elem->value->vcpu = is_vcpu;
1041dde0f48SLluís Vilanova         elem->value->name = g_strdup(trace_event_get_name(ev));
10577e2b172SLluís Vilanova 
1061dde0f48SLluís Vilanova         if (!trace_event_get_state_static(ev)) {
1071dde0f48SLluís Vilanova             elem->value->state = TRACE_EVENT_STATE_UNAVAILABLE;
1081dde0f48SLluís Vilanova         } else {
10977e2b172SLluís Vilanova             if (has_vcpu) {
11077e2b172SLluís Vilanova                 if (is_vcpu) {
11177e2b172SLluís Vilanova                     if (trace_event_get_vcpu_state_dynamic(cpu, ev)) {
1121dde0f48SLluís Vilanova                         elem->value->state = TRACE_EVENT_STATE_ENABLED;
11377e2b172SLluís Vilanova                     } else {
11477e2b172SLluís Vilanova                         elem->value->state = TRACE_EVENT_STATE_DISABLED;
11577e2b172SLluís Vilanova                     }
11677e2b172SLluís Vilanova                 }
11777e2b172SLluís Vilanova                 /* else: already skipped above */
11877e2b172SLluís Vilanova             } else {
11977e2b172SLluís Vilanova                 if (trace_event_get_state_dynamic(ev)) {
12077e2b172SLluís Vilanova                     elem->value->state = TRACE_EVENT_STATE_ENABLED;
12177e2b172SLluís Vilanova                 } else {
12277e2b172SLluís Vilanova                     elem->value->state = TRACE_EVENT_STATE_DISABLED;
12377e2b172SLluís Vilanova                 }
12477e2b172SLluís Vilanova             }
1251dde0f48SLluís Vilanova         }
1261dde0f48SLluís Vilanova         elem->next = events;
1271dde0f48SLluís Vilanova         events = elem;
1281dde0f48SLluís Vilanova     }
1291dde0f48SLluís Vilanova 
1301dde0f48SLluís Vilanova     return events;
1311dde0f48SLluís Vilanova }
1321dde0f48SLluís Vilanova 
1331dde0f48SLluís Vilanova void qmp_trace_event_set_state(const char *name, bool enable,
13477e2b172SLluís Vilanova                                bool has_ignore_unavailable, bool ignore_unavailable,
13577e2b172SLluís Vilanova                                bool has_vcpu, int64_t vcpu,
13677e2b172SLluís Vilanova                                Error **errp)
1371dde0f48SLluís Vilanova {
13877e2b172SLluís Vilanova     Error *err = NULL;
1390d4e995cSDaniel P. Berrange     TraceEventIter iter;
1401dde0f48SLluís Vilanova     TraceEvent *ev;
14177e2b172SLluís Vilanova     bool is_pattern = trace_event_is_pattern(name);
14277e2b172SLluís Vilanova     CPUState *cpu;
1431dde0f48SLluís Vilanova 
14477e2b172SLluís Vilanova     /* Check provided vcpu */
14577e2b172SLluís Vilanova     cpu = get_cpu(has_vcpu, vcpu, &err);
14677e2b172SLluís Vilanova     if (err) {
14777e2b172SLluís Vilanova         error_propagate(errp, err);
1481dde0f48SLluís Vilanova         return;
1491dde0f48SLluís Vilanova     }
1501dde0f48SLluís Vilanova 
15177e2b172SLluís Vilanova     /* Check events */
15277e2b172SLluís Vilanova     if (!check_events(has_vcpu, has_ignore_unavailable && ignore_unavailable,
15377e2b172SLluís Vilanova                       is_pattern, name, errp)) {
15477e2b172SLluís Vilanova         return;
15577e2b172SLluís Vilanova     }
15677e2b172SLluís Vilanova 
15777e2b172SLluís Vilanova     /* Apply changes (all errors checked above) */
1580d4e995cSDaniel P. Berrange     trace_event_iter_init(&iter, name);
1590d4e995cSDaniel P. Berrange     while ((ev = trace_event_iter_next(&iter)) != NULL) {
16077e2b172SLluís Vilanova         if (!trace_event_get_state_static(ev) ||
16177e2b172SLluís Vilanova             (has_vcpu && !trace_event_is_vcpu(ev))) {
16277e2b172SLluís Vilanova             continue;
16377e2b172SLluís Vilanova         }
16477e2b172SLluís Vilanova         if (has_vcpu) {
16577e2b172SLluís Vilanova             trace_event_set_vcpu_state_dynamic(cpu, ev, enable);
16677e2b172SLluís Vilanova         } else {
1671dde0f48SLluís Vilanova             trace_event_set_state_dynamic(ev, enable);
1681dde0f48SLluís Vilanova         }
1691dde0f48SLluís Vilanova     }
1701dde0f48SLluís Vilanova }
171