1 /* 2 * QEMU System Emulator 3 * 4 * Copyright (c) 2003-2008 Fabrice Bellard 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 25 #include "qemu/osdep.h" 26 #include "qemu/cutils.h" 27 #include "migration/vmstate.h" 28 #include "qapi/error.h" 29 #include "qemu/error-report.h" 30 #include "sysemu/cpus.h" 31 #include "qemu/main-loop.h" 32 #include "qemu/option.h" 33 #include "qemu/seqlock.h" 34 #include "sysemu/replay.h" 35 #include "sysemu/runstate.h" 36 #include "hw/core/cpu.h" 37 #include "sysemu/cpu-timers.h" 38 #include "sysemu/cpu-throttle.h" 39 #include "sysemu/cpu-timers-internal.h" 40 41 /* clock and ticks */ 42 43 static int64_t cpu_get_ticks_locked(void) 44 { 45 int64_t ticks = timers_state.cpu_ticks_offset; 46 if (timers_state.cpu_ticks_enabled) { 47 ticks += cpu_get_host_ticks(); 48 } 49 50 if (timers_state.cpu_ticks_prev > ticks) { 51 /* Non increasing ticks may happen if the host uses software suspend. */ 52 timers_state.cpu_ticks_offset += timers_state.cpu_ticks_prev - ticks; 53 ticks = timers_state.cpu_ticks_prev; 54 } 55 56 timers_state.cpu_ticks_prev = ticks; 57 return ticks; 58 } 59 60 /* 61 * return the time elapsed in VM between vm_start and vm_stop. 62 * cpu_get_ticks() uses units of the host CPU cycle counter. 63 */ 64 int64_t cpu_get_ticks(void) 65 { 66 int64_t ticks; 67 68 qemu_spin_lock(&timers_state.vm_clock_lock); 69 ticks = cpu_get_ticks_locked(); 70 qemu_spin_unlock(&timers_state.vm_clock_lock); 71 return ticks; 72 } 73 74 int64_t cpu_get_clock_locked(void) 75 { 76 int64_t time; 77 78 time = timers_state.cpu_clock_offset; 79 if (timers_state.cpu_ticks_enabled) { 80 time += get_clock(); 81 } 82 83 return time; 84 } 85 86 /* 87 * Return the monotonic time elapsed in VM, i.e., 88 * the time between vm_start and vm_stop 89 */ 90 int64_t cpu_get_clock(void) 91 { 92 int64_t ti; 93 unsigned start; 94 95 do { 96 start = seqlock_read_begin(&timers_state.vm_clock_seqlock); 97 ti = cpu_get_clock_locked(); 98 } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, start)); 99 100 return ti; 101 } 102 103 /* 104 * enable cpu_get_ticks() 105 * Caller must hold BQL which serves as mutex for vm_clock_seqlock. 106 */ 107 void cpu_enable_ticks(void) 108 { 109 seqlock_write_lock(&timers_state.vm_clock_seqlock, 110 &timers_state.vm_clock_lock); 111 if (!timers_state.cpu_ticks_enabled) { 112 timers_state.cpu_ticks_offset -= cpu_get_host_ticks(); 113 timers_state.cpu_clock_offset -= get_clock(); 114 timers_state.cpu_ticks_enabled = 1; 115 } 116 seqlock_write_unlock(&timers_state.vm_clock_seqlock, 117 &timers_state.vm_clock_lock); 118 } 119 120 /* 121 * disable cpu_get_ticks() : the clock is stopped. You must not call 122 * cpu_get_ticks() after that. 123 * Caller must hold BQL which serves as mutex for vm_clock_seqlock. 124 */ 125 void cpu_disable_ticks(void) 126 { 127 seqlock_write_lock(&timers_state.vm_clock_seqlock, 128 &timers_state.vm_clock_lock); 129 if (timers_state.cpu_ticks_enabled) { 130 timers_state.cpu_ticks_offset += cpu_get_host_ticks(); 131 timers_state.cpu_clock_offset = cpu_get_clock_locked(); 132 timers_state.cpu_ticks_enabled = 0; 133 } 134 seqlock_write_unlock(&timers_state.vm_clock_seqlock, 135 &timers_state.vm_clock_lock); 136 } 137 138 static bool icount_state_needed(void *opaque) 139 { 140 return icount_enabled(); 141 } 142 143 static bool warp_timer_state_needed(void *opaque) 144 { 145 TimersState *s = opaque; 146 return s->icount_warp_timer != NULL; 147 } 148 149 static bool adjust_timers_state_needed(void *opaque) 150 { 151 TimersState *s = opaque; 152 return s->icount_rt_timer != NULL; 153 } 154 155 static bool icount_shift_state_needed(void *opaque) 156 { 157 return icount_enabled() == 2; 158 } 159 160 /* 161 * Subsection for warp timer migration is optional, because may not be created 162 */ 163 static const VMStateDescription icount_vmstate_warp_timer = { 164 .name = "timer/icount/warp_timer", 165 .version_id = 1, 166 .minimum_version_id = 1, 167 .needed = warp_timer_state_needed, 168 .fields = (const VMStateField[]) { 169 VMSTATE_INT64(vm_clock_warp_start, TimersState), 170 VMSTATE_TIMER_PTR(icount_warp_timer, TimersState), 171 VMSTATE_END_OF_LIST() 172 } 173 }; 174 175 static const VMStateDescription icount_vmstate_adjust_timers = { 176 .name = "timer/icount/timers", 177 .version_id = 1, 178 .minimum_version_id = 1, 179 .needed = adjust_timers_state_needed, 180 .fields = (const VMStateField[]) { 181 VMSTATE_TIMER_PTR(icount_rt_timer, TimersState), 182 VMSTATE_TIMER_PTR(icount_vm_timer, TimersState), 183 VMSTATE_END_OF_LIST() 184 } 185 }; 186 187 static const VMStateDescription icount_vmstate_shift = { 188 .name = "timer/icount/shift", 189 .version_id = 2, 190 .minimum_version_id = 2, 191 .needed = icount_shift_state_needed, 192 .fields = (const VMStateField[]) { 193 VMSTATE_INT16(icount_time_shift, TimersState), 194 VMSTATE_INT64(last_delta, TimersState), 195 VMSTATE_END_OF_LIST() 196 } 197 }; 198 199 /* 200 * This is a subsection for icount migration. 201 */ 202 static const VMStateDescription icount_vmstate_timers = { 203 .name = "timer/icount", 204 .version_id = 1, 205 .minimum_version_id = 1, 206 .needed = icount_state_needed, 207 .fields = (const VMStateField[]) { 208 VMSTATE_INT64(qemu_icount_bias, TimersState), 209 VMSTATE_INT64(qemu_icount, TimersState), 210 VMSTATE_END_OF_LIST() 211 }, 212 .subsections = (const VMStateDescription * const []) { 213 &icount_vmstate_warp_timer, 214 &icount_vmstate_adjust_timers, 215 &icount_vmstate_shift, 216 NULL 217 } 218 }; 219 220 static const VMStateDescription vmstate_timers = { 221 .name = "timer", 222 .version_id = 2, 223 .minimum_version_id = 1, 224 .fields = (const VMStateField[]) { 225 VMSTATE_INT64(cpu_ticks_offset, TimersState), 226 VMSTATE_UNUSED(8), 227 VMSTATE_INT64_V(cpu_clock_offset, TimersState, 2), 228 VMSTATE_END_OF_LIST() 229 }, 230 .subsections = (const VMStateDescription * const []) { 231 &icount_vmstate_timers, 232 NULL 233 } 234 }; 235 236 static void do_nothing(CPUState *cpu, run_on_cpu_data unused) 237 { 238 } 239 240 void qemu_timer_notify_cb(void *opaque, QEMUClockType type) 241 { 242 if (!icount_enabled() || type != QEMU_CLOCK_VIRTUAL) { 243 qemu_notify_event(); 244 return; 245 } 246 247 if (qemu_in_vcpu_thread()) { 248 /* 249 * A CPU is currently running; kick it back out to the 250 * tcg_cpu_exec() loop so it will recalculate its 251 * icount deadline immediately. 252 */ 253 qemu_cpu_kick(current_cpu); 254 } else if (first_cpu) { 255 /* 256 * qemu_cpu_kick is not enough to kick a halted CPU out of 257 * qemu_tcg_wait_io_event. async_run_on_cpu, instead, 258 * causes cpu_thread_is_idle to return false. This way, 259 * handle_icount_deadline can run. 260 * If we have no CPUs at all for some reason, we don't 261 * need to do anything. 262 */ 263 async_run_on_cpu(first_cpu, do_nothing, RUN_ON_CPU_NULL); 264 } 265 } 266 267 TimersState timers_state; 268 269 /* initialize timers state and the cpu throttle for convenience */ 270 void cpu_timers_init(void) 271 { 272 seqlock_init(&timers_state.vm_clock_seqlock); 273 qemu_spin_init(&timers_state.vm_clock_lock); 274 vmstate_register(NULL, 0, &vmstate_timers, &timers_state); 275 276 cpu_throttle_init(); 277 } 278