Lluís Vilanova | 4815185 | 2016-07-11 12:53:41 +0200 | [diff] [blame] | 1 | /* |
| 2 | * Interface for configuring and controlling the state of tracing events. |
| 3 | * |
Lluís Vilanova | f5956d7 | 2017-06-25 14:08:38 +0300 | [diff] [blame] | 4 | * Copyright (C) 2014-2017 Lluís Vilanova <vilanova@ac.upc.edu> |
Lluís Vilanova | 4815185 | 2016-07-11 12:53:41 +0200 | [diff] [blame] | 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 "cpu.h" |
Daniel P. Berrange | 0ab8ed1 | 2017-01-25 16:14:15 +0000 | [diff] [blame] | 12 | #include "trace-root.h" |
Lluís Vilanova | 4815185 | 2016-07-11 12:53:41 +0200 | [diff] [blame] | 13 | #include "trace/control.h" |
Lluís Vilanova | 4815185 | 2016-07-11 12:53:41 +0200 | [diff] [blame] | 14 | |
| 15 | |
Lluís Vilanova | a4d50b1 | 2016-08-23 10:58:52 +0200 | [diff] [blame] | 16 | void trace_event_set_state_dynamic_init(TraceEvent *ev, bool state) |
| 17 | { |
Lluís Vilanova | 8eb1b9d | 2016-08-23 10:58:58 +0200 | [diff] [blame] | 18 | bool state_pre; |
Lluís Vilanova | a4d50b1 | 2016-08-23 10:58:52 +0200 | [diff] [blame] | 19 | assert(trace_event_get_state_static(ev)); |
Lluís Vilanova | 8eb1b9d | 2016-08-23 10:58:58 +0200 | [diff] [blame] | 20 | /* |
| 21 | * We ignore the "vcpu" property here, since no vCPUs have been created |
| 22 | * yet. Then dstate can only be 1 or 0. |
| 23 | */ |
Daniel P. Berrange | 9397740 | 2016-10-04 14:35:45 +0100 | [diff] [blame] | 24 | state_pre = *ev->dstate; |
Lluís Vilanova | 8eb1b9d | 2016-08-23 10:58:58 +0200 | [diff] [blame] | 25 | if (state_pre != state) { |
| 26 | if (state) { |
| 27 | trace_events_enabled_count++; |
Daniel P. Berrange | 9397740 | 2016-10-04 14:35:45 +0100 | [diff] [blame] | 28 | *ev->dstate = 1; |
Lluís Vilanova | 8eb1b9d | 2016-08-23 10:58:58 +0200 | [diff] [blame] | 29 | } else { |
| 30 | trace_events_enabled_count--; |
Daniel P. Berrange | 9397740 | 2016-10-04 14:35:45 +0100 | [diff] [blame] | 31 | *ev->dstate = 0; |
Lluís Vilanova | 8eb1b9d | 2016-08-23 10:58:58 +0200 | [diff] [blame] | 32 | } |
| 33 | } |
Lluís Vilanova | a4d50b1 | 2016-08-23 10:58:52 +0200 | [diff] [blame] | 34 | } |
| 35 | |
Lluís Vilanova | 4815185 | 2016-07-11 12:53:41 +0200 | [diff] [blame] | 36 | void trace_event_set_state_dynamic(TraceEvent *ev, bool state) |
| 37 | { |
| 38 | CPUState *vcpu; |
| 39 | assert(trace_event_get_state_static(ev)); |
Lluís Vilanova | f5956d7 | 2017-06-25 14:08:38 +0300 | [diff] [blame] | 40 | if (trace_event_is_vcpu(ev) && likely(first_cpu != NULL)) { |
Lluís Vilanova | 4815185 | 2016-07-11 12:53:41 +0200 | [diff] [blame] | 41 | CPU_FOREACH(vcpu) { |
| 42 | trace_event_set_vcpu_state_dynamic(vcpu, ev, state); |
| 43 | } |
| 44 | } else { |
Lluís Vilanova | f5956d7 | 2017-06-25 14:08:38 +0300 | [diff] [blame] | 45 | /* |
| 46 | * Without the "vcpu" property, dstate can only be 1 or 0. With it, we |
| 47 | * haven't instantiated any vCPU yet, so we will set a global state |
| 48 | * instead, and trace_init_vcpu will reconcile it afterwards. |
| 49 | */ |
Daniel P. Berrange | 9397740 | 2016-10-04 14:35:45 +0100 | [diff] [blame] | 50 | bool state_pre = *ev->dstate; |
Lluís Vilanova | 8eb1b9d | 2016-08-23 10:58:58 +0200 | [diff] [blame] | 51 | if (state_pre != state) { |
| 52 | if (state) { |
| 53 | trace_events_enabled_count++; |
Daniel P. Berrange | 9397740 | 2016-10-04 14:35:45 +0100 | [diff] [blame] | 54 | *ev->dstate = 1; |
Lluís Vilanova | 8eb1b9d | 2016-08-23 10:58:58 +0200 | [diff] [blame] | 55 | } else { |
| 56 | trace_events_enabled_count--; |
Daniel P. Berrange | 9397740 | 2016-10-04 14:35:45 +0100 | [diff] [blame] | 57 | *ev->dstate = 0; |
Lluís Vilanova | 8eb1b9d | 2016-08-23 10:58:58 +0200 | [diff] [blame] | 58 | } |
| 59 | } |
Lluís Vilanova | 4815185 | 2016-07-11 12:53:41 +0200 | [diff] [blame] | 60 | } |
| 61 | } |
| 62 | |
Lluís Vilanova | d438111 | 2017-07-04 10:38:26 +0200 | [diff] [blame] | 63 | static void trace_event_synchronize_vcpu_state_dynamic( |
| 64 | CPUState *vcpu, run_on_cpu_data ignored) |
| 65 | { |
| 66 | bitmap_copy(vcpu->trace_dstate, vcpu->trace_dstate_delayed, |
| 67 | CPU_TRACE_DSTATE_MAX_EVENTS); |
Lluís Vilanova | 61a67f7 | 2017-07-04 10:42:32 +0200 | [diff] [blame] | 68 | cpu_tb_jmp_cache_clear(vcpu); |
Lluís Vilanova | d438111 | 2017-07-04 10:38:26 +0200 | [diff] [blame] | 69 | } |
| 70 | |
Lluís Vilanova | 4815185 | 2016-07-11 12:53:41 +0200 | [diff] [blame] | 71 | void trace_event_set_vcpu_state_dynamic(CPUState *vcpu, |
| 72 | TraceEvent *ev, bool state) |
| 73 | { |
Daniel P. Berrange | ef4c9fc | 2016-10-04 14:35:49 +0100 | [diff] [blame] | 74 | uint32_t vcpu_id; |
Lluís Vilanova | 4815185 | 2016-07-11 12:53:41 +0200 | [diff] [blame] | 75 | bool state_pre; |
| 76 | assert(trace_event_get_state_static(ev)); |
| 77 | assert(trace_event_is_vcpu(ev)); |
Lluís Vilanova | 4815185 | 2016-07-11 12:53:41 +0200 | [diff] [blame] | 78 | vcpu_id = trace_event_get_vcpu_id(ev); |
| 79 | state_pre = test_bit(vcpu_id, vcpu->trace_dstate); |
| 80 | if (state_pre != state) { |
| 81 | if (state) { |
| 82 | trace_events_enabled_count++; |
Lluís Vilanova | d438111 | 2017-07-04 10:38:26 +0200 | [diff] [blame] | 83 | set_bit(vcpu_id, vcpu->trace_dstate_delayed); |
Daniel P. Berrange | 9397740 | 2016-10-04 14:35:45 +0100 | [diff] [blame] | 84 | (*ev->dstate)++; |
Lluís Vilanova | 4815185 | 2016-07-11 12:53:41 +0200 | [diff] [blame] | 85 | } else { |
| 86 | trace_events_enabled_count--; |
Lluís Vilanova | d438111 | 2017-07-04 10:38:26 +0200 | [diff] [blame] | 87 | clear_bit(vcpu_id, vcpu->trace_dstate_delayed); |
Daniel P. Berrange | 9397740 | 2016-10-04 14:35:45 +0100 | [diff] [blame] | 88 | (*ev->dstate)--; |
Lluís Vilanova | 4815185 | 2016-07-11 12:53:41 +0200 | [diff] [blame] | 89 | } |
Lluís Vilanova | f99b38f | 2017-09-13 01:50:25 +0300 | [diff] [blame] | 90 | if (vcpu->created) { |
| 91 | /* |
| 92 | * Delay changes until next TB; we want all TBs to be built from a |
| 93 | * single set of dstate values to ensure consistency of generated |
| 94 | * tracing code. |
| 95 | */ |
| 96 | async_run_on_cpu(vcpu, trace_event_synchronize_vcpu_state_dynamic, |
| 97 | RUN_ON_CPU_NULL); |
| 98 | } else { |
| 99 | trace_event_synchronize_vcpu_state_dynamic(vcpu, RUN_ON_CPU_NULL); |
| 100 | } |
Lluís Vilanova | 4815185 | 2016-07-11 12:53:41 +0200 | [diff] [blame] | 101 | } |
| 102 | } |
Lluís Vilanova | 2bfe11c | 2016-09-19 14:55:07 +0200 | [diff] [blame] | 103 | |
Lluís Vilanova | fff895d | 2016-12-26 22:24:35 +0100 | [diff] [blame] | 104 | static bool adding_first_cpu1(void) |
Lluís Vilanova | 2bfe11c | 2016-09-19 14:55:07 +0200 | [diff] [blame] | 105 | { |
| 106 | CPUState *cpu; |
| 107 | size_t count = 0; |
| 108 | CPU_FOREACH(cpu) { |
| 109 | count++; |
| 110 | if (count > 1) { |
| 111 | return false; |
| 112 | } |
| 113 | } |
| 114 | return true; |
| 115 | } |
| 116 | |
Lluís Vilanova | fff895d | 2016-12-26 22:24:35 +0100 | [diff] [blame] | 117 | static bool adding_first_cpu(void) |
| 118 | { |
| 119 | bool res; |
| 120 | cpu_list_lock(); |
| 121 | res = adding_first_cpu1(); |
| 122 | cpu_list_unlock(); |
| 123 | return res; |
| 124 | } |
| 125 | |
Lluís Vilanova | 2bfe11c | 2016-09-19 14:55:07 +0200 | [diff] [blame] | 126 | void trace_init_vcpu(CPUState *vcpu) |
| 127 | { |
Daniel P. Berrange | 0d4e995 | 2016-10-04 14:35:43 +0100 | [diff] [blame] | 128 | TraceEventIter iter; |
| 129 | TraceEvent *ev; |
| 130 | trace_event_iter_init(&iter, NULL); |
| 131 | while ((ev = trace_event_iter_next(&iter)) != NULL) { |
Lluís Vilanova | 2bfe11c | 2016-09-19 14:55:07 +0200 | [diff] [blame] | 132 | if (trace_event_is_vcpu(ev) && |
| 133 | trace_event_get_state_static(ev) && |
| 134 | trace_event_get_state_dynamic(ev)) { |
Lluís Vilanova | 2bfe11c | 2016-09-19 14:55:07 +0200 | [diff] [blame] | 135 | if (adding_first_cpu()) { |
| 136 | /* check preconditions */ |
Daniel P. Berrange | 9397740 | 2016-10-04 14:35:45 +0100 | [diff] [blame] | 137 | assert(*ev->dstate == 1); |
Lluís Vilanova | 2bfe11c | 2016-09-19 14:55:07 +0200 | [diff] [blame] | 138 | /* disable early-init state ... */ |
Daniel P. Berrange | 9397740 | 2016-10-04 14:35:45 +0100 | [diff] [blame] | 139 | *ev->dstate = 0; |
Lluís Vilanova | 2bfe11c | 2016-09-19 14:55:07 +0200 | [diff] [blame] | 140 | trace_events_enabled_count--; |
| 141 | /* ... and properly re-enable */ |
| 142 | trace_event_set_vcpu_state_dynamic(vcpu, ev, true); |
| 143 | } else { |
| 144 | trace_event_set_vcpu_state_dynamic(vcpu, ev, true); |
| 145 | } |
| 146 | } |
| 147 | } |
Lluís Vilanova | b9d7221 | 2016-09-19 14:55:13 +0200 | [diff] [blame] | 148 | trace_guest_cpu_enter(vcpu); |
Lluís Vilanova | 2bfe11c | 2016-09-19 14:55:07 +0200 | [diff] [blame] | 149 | } |