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#include "config-host.h" 25 26#include "cpu.h" 27#include "monitor/monitor.h" 28#include "sysemu/sysemu.h" 29#include "cpu.h" 30#include "exec/exec-all.h" 31#include "exec/gdbstub.h" 32#include "sysemu/dma.h" 33#include "sysemu/kvm.h" 34#include "exec/exec-all.h" 35#include "exec/hax.h" 36 37#include "sysemu/cpus.h" 38 39static CPUState *cur_cpu; 40static CPUState *next_cpu; 41 42/***********************************************************/ 43void hw_error(const char *fmt, ...) 44{ 45 va_list ap; 46 CPUState *cpu; 47 48 va_start(ap, fmt); 49 fprintf(stderr, "qemu: hardware error: "); 50 vfprintf(stderr, fmt, ap); 51 fprintf(stderr, "\n"); 52 CPU_FOREACH(cpu) { 53 fprintf(stderr, "CPU #%d:\n", cpu->cpu_index); 54#ifdef TARGET_I386 55 cpu_dump_state(cpu->env_ptr, stderr, fprintf, X86_DUMP_FPU); 56#else 57 cpu_dump_state(cpu->env_ptr, stderr, fprintf, 0); 58#endif 59 } 60 va_end(ap); 61 abort(); 62} 63 64static void do_vm_stop(int reason) 65{ 66 if (vm_running) { 67 cpu_disable_ticks(); 68 vm_running = 0; 69 pause_all_vcpus(); 70 vm_state_notify(0, reason); 71 } 72} 73 74static int cpu_can_run(CPUArchState *env) 75{ 76 CPUState *cpu = ENV_GET_CPU(env); 77 if (cpu->stop) 78 return 0; 79 if (cpu->stopped) 80 return 0; 81 return 1; 82} 83 84int tcg_has_work(void) 85{ 86 CPUState *cpu; 87 88 CPU_FOREACH(cpu) { 89 if (cpu->stop) 90 return 1; 91 if (cpu->stopped) 92 return 0; 93 if (!cpu->halted) 94 return 1; 95 if (cpu_has_work(cpu)) 96 return 1; 97 return 0; 98 } 99 return 0; 100} 101 102void qemu_init_vcpu(CPUState *cpu) 103{ 104 if (kvm_enabled()) 105 kvm_init_vcpu(cpu); 106#ifdef CONFIG_HAX 107 if (hax_enabled()) 108 hax_init_vcpu(cpu); 109#endif 110 return; 111} 112 113bool qemu_cpu_is_self(CPUState *cpu) 114{ 115 return true; 116} 117 118void resume_all_vcpus(void) 119{ 120} 121 122void pause_all_vcpus(void) 123{ 124} 125 126void qemu_cpu_kick(CPUState *cpu) 127{ 128 return; 129} 130 131// In main-loop.c 132#ifdef _WIN32 133extern HANDLE qemu_event_handle; 134#endif 135 136void qemu_notify_event(void) 137{ 138 CPUState *cpu = current_cpu; 139 140 if (cpu) { 141 cpu_exit(cpu); 142 /* 143 * This is mainly for the Windows host, where the timer may be in 144 * a different thread with vcpu. Thus the timer function needs to 145 * notify the vcpu thread of more than simply cpu_exit. If env is 146 * not NULL, it means that the vcpu is in execute state, we need 147 * only to set the flags. If the guest is in execute state, the 148 * HAX kernel module will exit to qemu. If env is NULL, vcpu is 149 * in main_loop_wait, and we need a event to notify it. 150 */ 151#ifdef CONFIG_HAX 152 if (hax_enabled()) 153 hax_raise_event(cpu); 154 } else { 155#ifdef _WIN32 156 if(hax_enabled()) 157 SetEvent(qemu_event_handle); 158#endif 159 } 160#else 161 } 162#endif 163} 164 165void qemu_mutex_lock_iothread(void) 166{ 167} 168 169void qemu_mutex_unlock_iothread(void) 170{ 171} 172 173void vm_stop(int reason) 174{ 175 do_vm_stop(reason); 176} 177 178static int qemu_cpu_exec(CPUOldState *env) 179{ 180 int ret; 181 182#ifdef CONFIG_PROFILER 183 int64_t ti = profile_getclock(); 184#endif 185#ifndef CONFIG_ANDROID 186 if (use_icount) { 187 int64_t count; 188 int decr; 189 qemu_icount -= (env->icount_decr.u16.low + env->icount_extra); 190 env->icount_decr.u16.low = 0; 191 env->icount_extra = 0; 192 count = qemu_next_icount_deadline(); 193 count = (count + (1 << icount_time_shift) - 1) 194 >> icount_time_shift; 195 qemu_icount += count; 196 decr = (count > 0xffff) ? 0xffff : count; 197 count -= decr; 198 env->icount_decr.u16.low = decr; 199 env->icount_extra = count; 200 } 201#endif 202 ret = cpu_exec(env); 203#ifdef CONFIG_PROFILER 204 qemu_time += profile_getclock() - ti; 205#endif 206#ifndef CONFIG_ANDROID 207 if (use_icount) { 208 /* Fold pending instructions back into the 209 instruction counter, and clear the interrupt flag. */ 210 qemu_icount -= (env->icount_decr.u16.low 211 + env->icount_extra); 212 env->icount_decr.u32 = 0; 213 env->icount_extra = 0; 214 } 215#endif 216 return ret; 217} 218 219void tcg_cpu_exec(void) 220{ 221 int ret = 0; 222 223 if (next_cpu == NULL) 224 next_cpu = QTAILQ_FIRST(&cpus); 225 for (; next_cpu != NULL; next_cpu = QTAILQ_NEXT(next_cpu, node)) {\ 226 cur_cpu = next_cpu; 227 CPUOldState *env = cur_cpu->env_ptr; 228 229 if (!vm_running) 230 break; 231 if (qemu_timer_alarm_pending()) { 232 break; 233 } 234 if (cpu_can_run(env)) 235 ret = qemu_cpu_exec(env); 236 if (ret == EXCP_DEBUG) { 237 gdb_set_stop_cpu(cur_cpu); 238 debug_requested = 1; 239 break; 240 } 241 } 242} 243 244/***********************************************************/ 245/* guest cycle counter */ 246 247typedef struct TimersState { 248 int64_t cpu_ticks_prev; 249 int64_t cpu_ticks_offset; 250 int64_t cpu_clock_offset; 251 int32_t cpu_ticks_enabled; 252 int64_t dummy; 253} TimersState; 254 255static void timer_save(QEMUFile *f, void *opaque) 256{ 257 TimersState *s = opaque; 258 259 if (s->cpu_ticks_enabled) { 260 hw_error("cannot save state if virtual timers are running"); 261 } 262 qemu_put_be64(f, s->cpu_ticks_prev); 263 qemu_put_be64(f, s->cpu_ticks_offset); 264 qemu_put_be64(f, s->cpu_clock_offset); 265 } 266 267static int timer_load(QEMUFile *f, void *opaque, int version_id) 268{ 269 TimersState *s = opaque; 270 271 if (version_id != 1 && version_id != 2) 272 return -EINVAL; 273 if (s->cpu_ticks_enabled) { 274 return -EINVAL; 275 } 276 s->cpu_ticks_prev = qemu_get_sbe64(f); 277 s->cpu_ticks_offset = qemu_get_sbe64(f); 278 if (version_id == 2) { 279 s->cpu_clock_offset = qemu_get_sbe64(f); 280 } 281 return 0; 282} 283 284 285TimersState timers_state; 286 287void qemu_timer_register_savevm(void) { 288 register_savevm(NULL, 289 "timer", 290 0, 291 2, 292 timer_save, 293 timer_load, 294 &timers_state); 295} 296 297/* Return the virtual CPU time, based on the instruction counter. */ 298int64_t cpu_get_icount(void) 299{ 300 int64_t icount; 301 CPUOldState *env = cpu_single_env;; 302 303 icount = qemu_icount; 304 if (env) { 305 if (!can_do_io(env)) { 306 fprintf(stderr, "Bad clock read\n"); 307 } 308 icount -= (env->icount_decr.u16.low + env->icount_extra); 309 } 310 return qemu_icount_bias + (icount << icount_time_shift); 311} 312 313/* return the host CPU cycle counter and handle stop/restart */ 314int64_t cpu_get_ticks(void) 315{ 316 if (use_icount) { 317 return cpu_get_icount(); 318 } 319 if (!timers_state.cpu_ticks_enabled) { 320 return timers_state.cpu_ticks_offset; 321 } else { 322 int64_t ticks; 323 ticks = cpu_get_real_ticks(); 324 if (timers_state.cpu_ticks_prev > ticks) { 325 /* Note: non increasing ticks may happen if the host uses 326 software suspend */ 327 timers_state.cpu_ticks_offset += timers_state.cpu_ticks_prev - ticks; 328 } 329 timers_state.cpu_ticks_prev = ticks; 330 return ticks + timers_state.cpu_ticks_offset; 331 } 332} 333 334/* return the host CPU monotonic timer and handle stop/restart */ 335int64_t cpu_get_clock(void) 336{ 337 int64_t ti; 338 if (!timers_state.cpu_ticks_enabled) { 339 return timers_state.cpu_clock_offset; 340 } else { 341 ti = get_clock(); 342 return ti + timers_state.cpu_clock_offset; 343 } 344} 345 346/* enable cpu_get_ticks() */ 347void cpu_enable_ticks(void) 348{ 349 if (!timers_state.cpu_ticks_enabled) { 350 timers_state.cpu_ticks_offset -= cpu_get_real_ticks(); 351 timers_state.cpu_clock_offset -= get_clock(); 352 timers_state.cpu_ticks_enabled = 1; 353 } 354} 355 356/* disable cpu_get_ticks() : the clock is stopped. You must not call 357 cpu_get_ticks() after that. */ 358void cpu_disable_ticks(void) 359{ 360 if (timers_state.cpu_ticks_enabled) { 361 timers_state.cpu_ticks_offset = cpu_get_ticks(); 362 timers_state.cpu_clock_offset = cpu_get_clock(); 363 timers_state.cpu_ticks_enabled = 0; 364 } 365} 366 367void qemu_clock_warp(QEMUClockType clock) { 368} 369