blob: ce13a5557fd583e1775e22e1fe6f187c17a29a38 [file] [log] [blame]
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +02001/*
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
David 'Digit' Turner9b3a4b02014-01-23 00:52:54 +010026#include "cpu.h"
27#include "exec/exec-all.h"
David 'Digit' Turner6af67652013-12-14 23:49:32 +010028#include "monitor/monitor.h"
David 'Digit' Turner34c48ff2013-12-15 00:25:03 +010029#include "sysemu/sysemu.h"
David 'Digit' Turner852088c2013-12-14 23:04:12 +010030#include "exec/gdbstub.h"
David 'Digit' Turner34c48ff2013-12-15 00:25:03 +010031#include "sysemu/dma.h"
32#include "sysemu/kvm.h"
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +010033#include "exec/exec-all.h"
David 'Digit' Turnere1e03df2013-12-15 00:42:21 +010034#include "exec/hax.h"
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020035
David 'Digit' Turner11822842013-12-17 09:16:47 +010036#include "sysemu/cpus.h"
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020037
David 'Digit' Turnere2678e12014-01-16 15:56:43 +010038static CPUOldState *cur_cpu;
39static CPUOldState *next_cpu;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020040
41/***********************************************************/
42void hw_error(const char *fmt, ...)
43{
44 va_list ap;
David 'Digit' Turnere2678e12014-01-16 15:56:43 +010045 CPUOldState *env;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020046
47 va_start(ap, fmt);
48 fprintf(stderr, "qemu: hardware error: ");
49 vfprintf(stderr, fmt, ap);
50 fprintf(stderr, "\n");
51 for(env = first_cpu; env != NULL; env = env->next_cpu) {
52 fprintf(stderr, "CPU #%d:\n", env->cpu_index);
53#ifdef TARGET_I386
54 cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU);
55#else
56 cpu_dump_state(env, stderr, fprintf, 0);
57#endif
58 }
59 va_end(ap);
60 abort();
61}
62
63static void do_vm_stop(int reason)
64{
65 if (vm_running) {
66 cpu_disable_ticks();
67 vm_running = 0;
68 pause_all_vcpus();
69 vm_state_notify(0, reason);
70 }
71}
72
David 'Digit' Turnere2678e12014-01-16 15:56:43 +010073static int cpu_can_run(CPUOldState *env)
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020074{
75 if (env->stop)
76 return 0;
77 if (env->stopped)
78 return 0;
79 return 1;
80}
81
David 'Digit' Turnere2678e12014-01-16 15:56:43 +010082static int cpu_has_work(CPUOldState *env)
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020083{
84 if (env->stop)
85 return 1;
86 if (env->stopped)
87 return 0;
88 if (!env->halted)
89 return 1;
90 if (qemu_cpu_has_work(env))
91 return 1;
92 return 0;
93}
94
95int tcg_has_work(void)
96{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +010097 CPUOldState *env;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020098
99 for (env = first_cpu; env != NULL; env = env->next_cpu)
100 if (cpu_has_work(env))
101 return 1;
102 return 0;
103}
104
105#ifndef _WIN32
106static int io_thread_fd = -1;
107
108#if 0
109static void qemu_event_increment(void)
110{
111 static const char byte = 0;
112
113 if (io_thread_fd == -1)
114 return;
115
116 write(io_thread_fd, &byte, sizeof(byte));
117}
118#endif
119
120static void qemu_event_read(void *opaque)
121{
122 int fd = (unsigned long)opaque;
123 ssize_t len;
124
125 /* Drain the notify pipe */
126 do {
127 char buffer[512];
128 len = read(fd, buffer, sizeof(buffer));
129 } while ((len == -1 && errno == EINTR) || len > 0);
130}
131
132static int qemu_event_init(void)
133{
134 int err;
135 int fds[2];
136
137 err = pipe(fds);
138 if (err == -1)
139 return -errno;
140
141 err = fcntl_setfl(fds[0], O_NONBLOCK);
142 if (err < 0)
143 goto fail;
144
145 err = fcntl_setfl(fds[1], O_NONBLOCK);
146 if (err < 0)
147 goto fail;
148
149 qemu_set_fd_handler2(fds[0], NULL, qemu_event_read, NULL,
150 (void *)(unsigned long)fds[0]);
151
152 io_thread_fd = fds[1];
153 return 0;
154
155fail:
156 close(fds[0]);
157 close(fds[1]);
158 return err;
159}
160#else
161HANDLE qemu_event_handle;
162
163static void dummy_event_handler(void *opaque)
164{
165}
166
167static int qemu_event_init(void)
168{
169 qemu_event_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
170 if (!qemu_event_handle) {
171 perror("Failed CreateEvent");
172 return -1;
173 }
174 qemu_add_wait_object(qemu_event_handle, dummy_event_handler, NULL);
175 return 0;
176}
177
178#if 0
179static void qemu_event_increment(void)
180{
181 SetEvent(qemu_event_handle);
182}
183#endif
184#endif
185
186#ifndef CONFIG_IOTHREAD
187int qemu_init_main_loop(void)
188{
189 return qemu_event_init();
190}
191
192void qemu_init_vcpu(void *_env)
193{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100194 CPUOldState *env = _env;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200195
196 if (kvm_enabled())
197 kvm_init_vcpu(env);
Jun Nakajimaa381ef02011-12-17 19:13:25 -0800198#ifdef CONFIG_HAX
199 if (hax_enabled())
200 hax_init_vcpu(env);
201#endif
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200202 return;
203}
204
205int qemu_cpu_self(void *env)
206{
207 return 1;
208}
209
210void resume_all_vcpus(void)
211{
212}
213
214void pause_all_vcpus(void)
215{
216}
217
218void qemu_cpu_kick(void *env)
219{
220 return;
221}
222
223void qemu_notify_event(void)
224{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100225 CPUOldState *env = cpu_single_env;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200226
227 if (env) {
228 cpu_exit(env);
229#ifdef USE_KQEMU
230 if (env->kqemu_enabled)
231 kqemu_cpu_interrupt(env);
232#endif
Jun Nakajimaa381ef02011-12-17 19:13:25 -0800233 /*
234 * This is mainly for the Windows host, where the timer may be in
235 * a different thread with vcpu. Thus the timer function needs to
236 * notify the vcpu thread of more than simply cpu_exit. If env is
237 * not NULL, it means that the vcpu is in execute state, we need
238 * only to set the flags. If the guest is in execute state, the
239 * HAX kernel module will exit to qemu. If env is NULL, vcpu is
240 * in main_loop_wait, and we need a event to notify it.
241 */
242#ifdef CONFIG_HAX
243 if (hax_enabled())
244 hax_raise_event(env);
245 } else {
246#ifdef _WIN32
247 if(hax_enabled())
248 SetEvent(qemu_event_handle);
249#endif
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200250 }
Jun Nakajimaa381ef02011-12-17 19:13:25 -0800251#else
252 }
253#endif
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200254}
255
256void qemu_mutex_lock_iothread(void)
257{
258}
259
260void qemu_mutex_unlock_iothread(void)
261{
262}
263
264void vm_stop(int reason)
265{
266 do_vm_stop(reason);
267}
268
269#else /* CONFIG_IOTHREAD */
270
David 'Digit' Turner057b0f62013-12-15 00:58:30 +0100271#include "qemu/thread.h"
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200272
273QemuMutex qemu_global_mutex;
274static QemuMutex qemu_fair_mutex;
275
276static QemuThread io_thread;
277
278static QemuThread *tcg_cpu_thread;
279static QemuCond *tcg_halt_cond;
280
281static int qemu_system_ready;
282/* cpu creation */
283static QemuCond qemu_cpu_cond;
284/* system init */
285static QemuCond qemu_system_cond;
286static QemuCond qemu_pause_cond;
287
288static void block_io_signals(void);
289static void unblock_io_signals(void);
290static int tcg_has_work(void);
291
292int qemu_init_main_loop(void)
293{
294 int ret;
295
296 ret = qemu_event_init();
297 if (ret)
298 return ret;
299
300 qemu_cond_init(&qemu_pause_cond);
301 qemu_mutex_init(&qemu_fair_mutex);
302 qemu_mutex_init(&qemu_global_mutex);
303 qemu_mutex_lock(&qemu_global_mutex);
304
305 unblock_io_signals();
306 qemu_thread_self(&io_thread);
307
308 return 0;
309}
310
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100311static void qemu_wait_io_event(CPUOldState *env)
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200312{
313 while (!tcg_has_work())
314 qemu_cond_timedwait(env->halt_cond, &qemu_global_mutex, 1000);
315
316 qemu_mutex_unlock(&qemu_global_mutex);
317
318 /*
319 * Users of qemu_global_mutex can be starved, having no chance
320 * to acquire it since this path will get to it first.
321 * So use another lock to provide fairness.
322 */
323 qemu_mutex_lock(&qemu_fair_mutex);
324 qemu_mutex_unlock(&qemu_fair_mutex);
325
326 qemu_mutex_lock(&qemu_global_mutex);
327 if (env->stop) {
328 env->stop = 0;
329 env->stopped = 1;
330 qemu_cond_signal(&qemu_pause_cond);
331 }
332}
333
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100334static int qemu_cpu_exec(CPUOldState *env);
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200335
336static void *kvm_cpu_thread_fn(void *arg)
337{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100338 CPUOldState *env = arg;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200339
340 block_io_signals();
341 qemu_thread_self(env->thread);
342
343 /* signal CPU creation */
344 qemu_mutex_lock(&qemu_global_mutex);
345 env->created = 1;
346 qemu_cond_signal(&qemu_cpu_cond);
347
348 /* and wait for machine initialization */
349 while (!qemu_system_ready)
350 qemu_cond_timedwait(&qemu_system_cond, &qemu_global_mutex, 100);
351
352 while (1) {
353 if (cpu_can_run(env))
354 qemu_cpu_exec(env);
355 qemu_wait_io_event(env);
356 }
357
358 return NULL;
359}
360
361static void tcg_cpu_exec(void);
362
363static void *tcg_cpu_thread_fn(void *arg)
364{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100365 CPUOldState *env = arg;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200366
367 block_io_signals();
368 qemu_thread_self(env->thread);
369
370 /* signal CPU creation */
371 qemu_mutex_lock(&qemu_global_mutex);
372 for (env = first_cpu; env != NULL; env = env->next_cpu)
373 env->created = 1;
374 qemu_cond_signal(&qemu_cpu_cond);
375
376 /* and wait for machine initialization */
377 while (!qemu_system_ready)
378 qemu_cond_timedwait(&qemu_system_cond, &qemu_global_mutex, 100);
379
380 while (1) {
381 tcg_cpu_exec();
382 qemu_wait_io_event(cur_cpu);
383 }
384
385 return NULL;
386}
387
388void qemu_cpu_kick(void *_env)
389{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100390 CPUOldState *env = _env;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200391 qemu_cond_broadcast(env->halt_cond);
Jun Nakajimaa381ef02011-12-17 19:13:25 -0800392 if (kvm_enabled() || hax_enabled())
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200393 qemu_thread_signal(env->thread, SIGUSR1);
394}
395
396int qemu_cpu_self(void *env)
397{
398 return (cpu_single_env != NULL);
399}
400
401static void cpu_signal(int sig)
402{
403 if (cpu_single_env)
404 cpu_exit(cpu_single_env);
405}
406
407static void block_io_signals(void)
408{
409 sigset_t set;
410 struct sigaction sigact;
411
412 sigemptyset(&set);
413 sigaddset(&set, SIGUSR2);
414 sigaddset(&set, SIGIO);
415 sigaddset(&set, SIGALRM);
416 pthread_sigmask(SIG_BLOCK, &set, NULL);
417
418 sigemptyset(&set);
419 sigaddset(&set, SIGUSR1);
420 pthread_sigmask(SIG_UNBLOCK, &set, NULL);
421
422 memset(&sigact, 0, sizeof(sigact));
423 sigact.sa_handler = cpu_signal;
424 sigaction(SIGUSR1, &sigact, NULL);
425}
426
427static void unblock_io_signals(void)
428{
429 sigset_t set;
430
431 sigemptyset(&set);
432 sigaddset(&set, SIGUSR2);
433 sigaddset(&set, SIGIO);
434 sigaddset(&set, SIGALRM);
435 pthread_sigmask(SIG_UNBLOCK, &set, NULL);
436
437 sigemptyset(&set);
438 sigaddset(&set, SIGUSR1);
439 pthread_sigmask(SIG_BLOCK, &set, NULL);
440}
441
442static void qemu_signal_lock(unsigned int msecs)
443{
444 qemu_mutex_lock(&qemu_fair_mutex);
445
446 while (qemu_mutex_trylock(&qemu_global_mutex)) {
447 qemu_thread_signal(tcg_cpu_thread, SIGUSR1);
448 if (!qemu_mutex_timedlock(&qemu_global_mutex, msecs))
449 break;
450 }
451 qemu_mutex_unlock(&qemu_fair_mutex);
452}
453
454void qemu_mutex_lock_iothread(void)
455{
Jun Nakajimaa381ef02011-12-17 19:13:25 -0800456 if (kvm_enabled() || hax_enabled()) {
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200457 qemu_mutex_lock(&qemu_fair_mutex);
458 qemu_mutex_lock(&qemu_global_mutex);
459 qemu_mutex_unlock(&qemu_fair_mutex);
460 } else
461 qemu_signal_lock(100);
462}
463
464void qemu_mutex_unlock_iothread(void)
465{
466 qemu_mutex_unlock(&qemu_global_mutex);
467}
468
469static int all_vcpus_paused(void)
470{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100471 CPUOldState *penv = first_cpu;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200472
473 while (penv) {
474 if (!penv->stopped)
475 return 0;
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100476 penv = (CPUOldState *)penv->next_cpu;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200477 }
478
479 return 1;
480}
481
482void pause_all_vcpus(void)
483{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100484 CPUOldState *penv = first_cpu;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200485
486 while (penv) {
487 penv->stop = 1;
488 qemu_thread_signal(penv->thread, SIGUSR1);
489 qemu_cpu_kick(penv);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100490 penv = (CPUOldState *)penv->next_cpu;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200491 }
492
493 while (!all_vcpus_paused()) {
494 qemu_cond_timedwait(&qemu_pause_cond, &qemu_global_mutex, 100);
495 penv = first_cpu;
496 while (penv) {
497 qemu_thread_signal(penv->thread, SIGUSR1);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100498 penv = (CPUOldState *)penv->next_cpu;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200499 }
500 }
501}
502
503void resume_all_vcpus(void)
504{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100505 CPUOldState *penv = first_cpu;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200506
507 while (penv) {
508 penv->stop = 0;
509 penv->stopped = 0;
510 qemu_thread_signal(penv->thread, SIGUSR1);
511 qemu_cpu_kick(penv);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100512 penv = (CPUOldState *)penv->next_cpu;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200513 }
514}
515
516static void tcg_init_vcpu(void *_env)
517{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100518 CPUOldState *env = _env;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200519 /* share a single thread for all cpus with TCG */
520 if (!tcg_cpu_thread) {
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100521 env->thread = g_malloc0(sizeof(QemuThread));
522 env->halt_cond = g_malloc0(sizeof(QemuCond));
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200523 qemu_cond_init(env->halt_cond);
524 qemu_thread_create(env->thread, tcg_cpu_thread_fn, env);
525 while (env->created == 0)
526 qemu_cond_timedwait(&qemu_cpu_cond, &qemu_global_mutex, 100);
527 tcg_cpu_thread = env->thread;
528 tcg_halt_cond = env->halt_cond;
529 } else {
530 env->thread = tcg_cpu_thread;
531 env->halt_cond = tcg_halt_cond;
532 }
533}
534
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100535static void kvm_start_vcpu(CPUOldState *env)
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200536{
537#if 0
538 kvm_init_vcpu(env);
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100539 env->thread = g_malloc0(sizeof(QemuThread));
540 env->halt_cond = g_malloc0(sizeof(QemuCond));
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200541 qemu_cond_init(env->halt_cond);
542 qemu_thread_create(env->thread, kvm_cpu_thread_fn, env);
543 while (env->created == 0)
544 qemu_cond_timedwait(&qemu_cpu_cond, &qemu_global_mutex, 100);
545#endif
546}
547
548void qemu_init_vcpu(void *_env)
549{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100550 CPUOldState *env = _env;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200551
552 if (kvm_enabled())
553 kvm_start_vcpu(env);
554 else
555 tcg_init_vcpu(env);
556}
557
558void qemu_notify_event(void)
559{
560 qemu_event_increment();
561}
562
563void vm_stop(int reason)
564{
565 QemuThread me;
566 qemu_thread_self(&me);
567
568 if (!qemu_thread_equal(&me, &io_thread)) {
569 qemu_system_vmstop_request(reason);
570 /*
571 * FIXME: should not return to device code in case
572 * vm_stop() has been requested.
573 */
574 if (cpu_single_env) {
575 cpu_exit(cpu_single_env);
576 cpu_single_env->stop = 1;
577 }
578 return;
579 }
580 do_vm_stop(reason);
581}
582
583#endif
584
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100585static int qemu_cpu_exec(CPUOldState *env)
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200586{
587 int ret;
588#ifdef CONFIG_PROFILER
589 int64_t ti;
590#endif
591
592#ifdef CONFIG_PROFILER
593 ti = profile_getclock();
594#endif
595 if (use_icount) {
596 int64_t count;
597 int decr;
598 qemu_icount -= (env->icount_decr.u16.low + env->icount_extra);
599 env->icount_decr.u16.low = 0;
600 env->icount_extra = 0;
601 count = qemu_next_icount_deadline();
602 count = (count + (1 << icount_time_shift) - 1)
603 >> icount_time_shift;
604 qemu_icount += count;
605 decr = (count > 0xffff) ? 0xffff : count;
606 count -= decr;
607 env->icount_decr.u16.low = decr;
608 env->icount_extra = count;
609 }
610#ifdef CONFIG_TRACE
611 if (tbflush_requested) {
612 tbflush_requested = 0;
613 tb_flush(env);
614 return EXCP_INTERRUPT;
615 }
616#endif
617
618
619 ret = cpu_exec(env);
620#ifdef CONFIG_PROFILER
621 qemu_time += profile_getclock() - ti;
622#endif
623 if (use_icount) {
624 /* Fold pending instructions back into the
625 instruction counter, and clear the interrupt flag. */
626 qemu_icount -= (env->icount_decr.u16.low
627 + env->icount_extra);
628 env->icount_decr.u32 = 0;
629 env->icount_extra = 0;
630 }
631 return ret;
632}
633
634void tcg_cpu_exec(void)
635{
636 int ret = 0;
637
638 if (next_cpu == NULL)
639 next_cpu = first_cpu;
640 for (; next_cpu != NULL; next_cpu = next_cpu->next_cpu) {
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100641 CPUOldState *env = cur_cpu = next_cpu;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200642
643 if (!vm_running)
644 break;
645 if (qemu_timer_alarm_pending()) {
646 break;
647 }
648 if (cpu_can_run(env))
649 ret = qemu_cpu_exec(env);
650 if (ret == EXCP_DEBUG) {
651 gdb_set_stop_cpu(env);
652 debug_requested = 1;
653 break;
654 }
655 }
656}
657
David 'Digit' Turner9b3a4b02014-01-23 00:52:54 +0100658/* Return the virtual CPU time, based on the instruction counter. */
659int64_t cpu_get_icount(void)
660{
661 int64_t icount;
662 CPUOldState *env = cpu_single_env;;
663
664 icount = qemu_icount;
665 if (env) {
666 if (!can_do_io(env)) {
667 fprintf(stderr, "Bad clock read\n");
668 }
669 icount -= (env->icount_decr.u16.low + env->icount_extra);
670 }
671 return qemu_icount_bias + (icount << icount_time_shift);
672}