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