xref: /openbmc/qemu/trace/qmp.c (revision 54aa3de7)
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"
11e688df6bSMarkus Armbruster #include "qapi/error.h"
129af23989SMarkus Armbruster #include "qapi/qapi-commands-trace.h"
1313d4ff07SMarkus Armbruster #include "control-vcpu.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) {
95*54aa3de7SEric Blake         TraceEventInfo *value;
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 
101*54aa3de7SEric Blake         value = g_new(TraceEventInfo, 1);
102*54aa3de7SEric Blake         value->vcpu = is_vcpu;
103*54aa3de7SEric Blake         value->name = g_strdup(trace_event_get_name(ev));
10477e2b172SLluís Vilanova 
1051dde0f48SLluís Vilanova         if (!trace_event_get_state_static(ev)) {
106*54aa3de7SEric Blake             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)) {
111*54aa3de7SEric Blake                         value->state = TRACE_EVENT_STATE_ENABLED;
11277e2b172SLluís Vilanova                     } else {
113*54aa3de7SEric Blake                         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)) {
119*54aa3de7SEric Blake                     value->state = TRACE_EVENT_STATE_ENABLED;
12077e2b172SLluís Vilanova                 } else {
121*54aa3de7SEric Blake                     value->state = TRACE_EVENT_STATE_DISABLED;
12277e2b172SLluís Vilanova                 }
12377e2b172SLluís Vilanova             }
1241dde0f48SLluís Vilanova         }
125*54aa3de7SEric Blake         QAPI_LIST_PREPEND(events, value);
1261dde0f48SLluís Vilanova     }
1271dde0f48SLluís Vilanova 
1281dde0f48SLluís Vilanova     return events;
1291dde0f48SLluís Vilanova }
1301dde0f48SLluís Vilanova 
1311dde0f48SLluís Vilanova void qmp_trace_event_set_state(const char *name, bool enable,
13277e2b172SLluís Vilanova                                bool has_ignore_unavailable, bool ignore_unavailable,
13377e2b172SLluís Vilanova                                bool has_vcpu, int64_t vcpu,
13477e2b172SLluís Vilanova                                Error **errp)
1351dde0f48SLluís Vilanova {
13677e2b172SLluís Vilanova     Error *err = NULL;
1370d4e995cSDaniel P. Berrange     TraceEventIter iter;
1381dde0f48SLluís Vilanova     TraceEvent *ev;
13977e2b172SLluís Vilanova     bool is_pattern = trace_event_is_pattern(name);
14077e2b172SLluís Vilanova     CPUState *cpu;
1411dde0f48SLluís Vilanova 
14277e2b172SLluís Vilanova     /* Check provided vcpu */
14377e2b172SLluís Vilanova     cpu = get_cpu(has_vcpu, vcpu, &err);
14477e2b172SLluís Vilanova     if (err) {
14577e2b172SLluís Vilanova         error_propagate(errp, err);
1461dde0f48SLluís Vilanova         return;
1471dde0f48SLluís Vilanova     }
1481dde0f48SLluís Vilanova 
14977e2b172SLluís Vilanova     /* Check events */
15077e2b172SLluís Vilanova     if (!check_events(has_vcpu, has_ignore_unavailable && ignore_unavailable,
15177e2b172SLluís Vilanova                       is_pattern, name, errp)) {
15277e2b172SLluís Vilanova         return;
15377e2b172SLluís Vilanova     }
15477e2b172SLluís Vilanova 
15577e2b172SLluís Vilanova     /* Apply changes (all errors checked above) */
1560d4e995cSDaniel P. Berrange     trace_event_iter_init(&iter, name);
1570d4e995cSDaniel P. Berrange     while ((ev = trace_event_iter_next(&iter)) != NULL) {
15877e2b172SLluís Vilanova         if (!trace_event_get_state_static(ev) ||
15977e2b172SLluís Vilanova             (has_vcpu && !trace_event_is_vcpu(ev))) {
16077e2b172SLluís Vilanova             continue;
16177e2b172SLluís Vilanova         }
16277e2b172SLluís Vilanova         if (has_vcpu) {
16377e2b172SLluís Vilanova             trace_event_set_vcpu_state_dynamic(cpu, ev, enable);
16477e2b172SLluís Vilanova         } else {
1651dde0f48SLluís Vilanova             trace_event_set_state_dynamic(ev, enable);
1661dde0f48SLluís Vilanova         }
1671dde0f48SLluís Vilanova     }
1681dde0f48SLluís Vilanova }
169