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