blob: ccc36ad0bdc871336e4a3ffafc0bbaa14e19588a [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' Turner6af67652013-12-14 23:49:32 +010026#include "monitor/monitor.h"
David 'Digit' Turner34c48ff2013-12-15 00:25:03 +010027#include "sysemu/sysemu.h"
David 'Digit' Turner852088c2013-12-14 23:04:12 +010028#include "exec/gdbstub.h"
David 'Digit' Turner34c48ff2013-12-15 00:25:03 +010029#include "sysemu/dma.h"
30#include "sysemu/kvm.h"
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +010031#include "exec/exec-all.h"
David 'Digit' Turnere1e03df2013-12-15 00:42:21 +010032#include "exec/hax.h"
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020033
David 'Digit' Turner11822842013-12-17 09:16:47 +010034#include "sysemu/cpus.h"
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020035
David 'Digit' Turnere2678e12014-01-16 15:56:43 +010036static CPUOldState *cur_cpu;
37static CPUOldState *next_cpu;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020038
39/***********************************************************/
40void hw_error(const char *fmt, ...)
41{
42 va_list ap;
David 'Digit' Turnere2678e12014-01-16 15:56:43 +010043 CPUOldState *env;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020044
45 va_start(ap, fmt);
46 fprintf(stderr, "qemu: hardware error: ");
47 vfprintf(stderr, fmt, ap);
48 fprintf(stderr, "\n");
49 for(env = first_cpu; env != NULL; env = env->next_cpu) {
50 fprintf(stderr, "CPU #%d:\n", env->cpu_index);
51#ifdef TARGET_I386
52 cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU);
53#else
54 cpu_dump_state(env, stderr, fprintf, 0);
55#endif
56 }
57 va_end(ap);
58 abort();
59}
60
61static void do_vm_stop(int reason)
62{
63 if (vm_running) {
64 cpu_disable_ticks();
65 vm_running = 0;
66 pause_all_vcpus();
67 vm_state_notify(0, reason);
68 }
69}
70
David 'Digit' Turnere2678e12014-01-16 15:56:43 +010071static int cpu_can_run(CPUOldState *env)
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020072{
73 if (env->stop)
74 return 0;
75 if (env->stopped)
76 return 0;
77 return 1;
78}
79
David 'Digit' Turnere2678e12014-01-16 15:56:43 +010080static int cpu_has_work(CPUOldState *env)
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020081{
82 if (env->stop)
83 return 1;
84 if (env->stopped)
85 return 0;
86 if (!env->halted)
87 return 1;
88 if (qemu_cpu_has_work(env))
89 return 1;
90 return 0;
91}
92
93int tcg_has_work(void)
94{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +010095 CPUOldState *env;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +020096
97 for (env = first_cpu; env != NULL; env = env->next_cpu)
98 if (cpu_has_work(env))
99 return 1;
100 return 0;
101}
102
103#ifndef _WIN32
104static int io_thread_fd = -1;
105
106#if 0
107static void qemu_event_increment(void)
108{
109 static const char byte = 0;
110
111 if (io_thread_fd == -1)
112 return;
113
114 write(io_thread_fd, &byte, sizeof(byte));
115}
116#endif
117
118static void qemu_event_read(void *opaque)
119{
120 int fd = (unsigned long)opaque;
121 ssize_t len;
122
123 /* Drain the notify pipe */
124 do {
125 char buffer[512];
126 len = read(fd, buffer, sizeof(buffer));
127 } while ((len == -1 && errno == EINTR) || len > 0);
128}
129
130static int qemu_event_init(void)
131{
132 int err;
133 int fds[2];
134
135 err = pipe(fds);
136 if (err == -1)
137 return -errno;
138
139 err = fcntl_setfl(fds[0], O_NONBLOCK);
140 if (err < 0)
141 goto fail;
142
143 err = fcntl_setfl(fds[1], O_NONBLOCK);
144 if (err < 0)
145 goto fail;
146
147 qemu_set_fd_handler2(fds[0], NULL, qemu_event_read, NULL,
148 (void *)(unsigned long)fds[0]);
149
150 io_thread_fd = fds[1];
151 return 0;
152
153fail:
154 close(fds[0]);
155 close(fds[1]);
156 return err;
157}
158#else
159HANDLE qemu_event_handle;
160
161static void dummy_event_handler(void *opaque)
162{
163}
164
165static int qemu_event_init(void)
166{
167 qemu_event_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
168 if (!qemu_event_handle) {
169 perror("Failed CreateEvent");
170 return -1;
171 }
172 qemu_add_wait_object(qemu_event_handle, dummy_event_handler, NULL);
173 return 0;
174}
175
176#if 0
177static void qemu_event_increment(void)
178{
179 SetEvent(qemu_event_handle);
180}
181#endif
182#endif
183
184#ifndef CONFIG_IOTHREAD
185int qemu_init_main_loop(void)
186{
187 return qemu_event_init();
188}
189
190void qemu_init_vcpu(void *_env)
191{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100192 CPUOldState *env = _env;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200193
194 if (kvm_enabled())
195 kvm_init_vcpu(env);
Jun Nakajimaa381ef02011-12-17 19:13:25 -0800196#ifdef CONFIG_HAX
197 if (hax_enabled())
198 hax_init_vcpu(env);
199#endif
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200200 return;
201}
202
203int qemu_cpu_self(void *env)
204{
205 return 1;
206}
207
208void resume_all_vcpus(void)
209{
210}
211
212void pause_all_vcpus(void)
213{
214}
215
216void qemu_cpu_kick(void *env)
217{
218 return;
219}
220
221void qemu_notify_event(void)
222{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100223 CPUOldState *env = cpu_single_env;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200224
225 if (env) {
226 cpu_exit(env);
227#ifdef USE_KQEMU
228 if (env->kqemu_enabled)
229 kqemu_cpu_interrupt(env);
230#endif
Jun Nakajimaa381ef02011-12-17 19:13:25 -0800231 /*
232 * This is mainly for the Windows host, where the timer may be in
233 * a different thread with vcpu. Thus the timer function needs to
234 * notify the vcpu thread of more than simply cpu_exit. If env is
235 * not NULL, it means that the vcpu is in execute state, we need
236 * only to set the flags. If the guest is in execute state, the
237 * HAX kernel module will exit to qemu. If env is NULL, vcpu is
238 * in main_loop_wait, and we need a event to notify it.
239 */
240#ifdef CONFIG_HAX
241 if (hax_enabled())
242 hax_raise_event(env);
243 } else {
244#ifdef _WIN32
245 if(hax_enabled())
246 SetEvent(qemu_event_handle);
247#endif
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200248 }
Jun Nakajimaa381ef02011-12-17 19:13:25 -0800249#else
250 }
251#endif
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200252}
253
254void qemu_mutex_lock_iothread(void)
255{
256}
257
258void qemu_mutex_unlock_iothread(void)
259{
260}
261
262void vm_stop(int reason)
263{
264 do_vm_stop(reason);
265}
266
267#else /* CONFIG_IOTHREAD */
268
David 'Digit' Turner057b0f62013-12-15 00:58:30 +0100269#include "qemu/thread.h"
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200270
271QemuMutex qemu_global_mutex;
272static QemuMutex qemu_fair_mutex;
273
274static QemuThread io_thread;
275
276static QemuThread *tcg_cpu_thread;
277static QemuCond *tcg_halt_cond;
278
279static int qemu_system_ready;
280/* cpu creation */
281static QemuCond qemu_cpu_cond;
282/* system init */
283static QemuCond qemu_system_cond;
284static QemuCond qemu_pause_cond;
285
286static void block_io_signals(void);
287static void unblock_io_signals(void);
288static int tcg_has_work(void);
289
290int qemu_init_main_loop(void)
291{
292 int ret;
293
294 ret = qemu_event_init();
295 if (ret)
296 return ret;
297
298 qemu_cond_init(&qemu_pause_cond);
299 qemu_mutex_init(&qemu_fair_mutex);
300 qemu_mutex_init(&qemu_global_mutex);
301 qemu_mutex_lock(&qemu_global_mutex);
302
303 unblock_io_signals();
304 qemu_thread_self(&io_thread);
305
306 return 0;
307}
308
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100309static void qemu_wait_io_event(CPUOldState *env)
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200310{
311 while (!tcg_has_work())
312 qemu_cond_timedwait(env->halt_cond, &qemu_global_mutex, 1000);
313
314 qemu_mutex_unlock(&qemu_global_mutex);
315
316 /*
317 * Users of qemu_global_mutex can be starved, having no chance
318 * to acquire it since this path will get to it first.
319 * So use another lock to provide fairness.
320 */
321 qemu_mutex_lock(&qemu_fair_mutex);
322 qemu_mutex_unlock(&qemu_fair_mutex);
323
324 qemu_mutex_lock(&qemu_global_mutex);
325 if (env->stop) {
326 env->stop = 0;
327 env->stopped = 1;
328 qemu_cond_signal(&qemu_pause_cond);
329 }
330}
331
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100332static int qemu_cpu_exec(CPUOldState *env);
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200333
334static void *kvm_cpu_thread_fn(void *arg)
335{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100336 CPUOldState *env = arg;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200337
338 block_io_signals();
339 qemu_thread_self(env->thread);
340
341 /* signal CPU creation */
342 qemu_mutex_lock(&qemu_global_mutex);
343 env->created = 1;
344 qemu_cond_signal(&qemu_cpu_cond);
345
346 /* and wait for machine initialization */
347 while (!qemu_system_ready)
348 qemu_cond_timedwait(&qemu_system_cond, &qemu_global_mutex, 100);
349
350 while (1) {
351 if (cpu_can_run(env))
352 qemu_cpu_exec(env);
353 qemu_wait_io_event(env);
354 }
355
356 return NULL;
357}
358
359static void tcg_cpu_exec(void);
360
361static void *tcg_cpu_thread_fn(void *arg)
362{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100363 CPUOldState *env = arg;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200364
365 block_io_signals();
366 qemu_thread_self(env->thread);
367
368 /* signal CPU creation */
369 qemu_mutex_lock(&qemu_global_mutex);
370 for (env = first_cpu; env != NULL; env = env->next_cpu)
371 env->created = 1;
372 qemu_cond_signal(&qemu_cpu_cond);
373
374 /* and wait for machine initialization */
375 while (!qemu_system_ready)
376 qemu_cond_timedwait(&qemu_system_cond, &qemu_global_mutex, 100);
377
378 while (1) {
379 tcg_cpu_exec();
380 qemu_wait_io_event(cur_cpu);
381 }
382
383 return NULL;
384}
385
386void qemu_cpu_kick(void *_env)
387{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100388 CPUOldState *env = _env;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200389 qemu_cond_broadcast(env->halt_cond);
Jun Nakajimaa381ef02011-12-17 19:13:25 -0800390 if (kvm_enabled() || hax_enabled())
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200391 qemu_thread_signal(env->thread, SIGUSR1);
392}
393
394int qemu_cpu_self(void *env)
395{
396 return (cpu_single_env != NULL);
397}
398
399static void cpu_signal(int sig)
400{
401 if (cpu_single_env)
402 cpu_exit(cpu_single_env);
403}
404
405static void block_io_signals(void)
406{
407 sigset_t set;
408 struct sigaction sigact;
409
410 sigemptyset(&set);
411 sigaddset(&set, SIGUSR2);
412 sigaddset(&set, SIGIO);
413 sigaddset(&set, SIGALRM);
414 pthread_sigmask(SIG_BLOCK, &set, NULL);
415
416 sigemptyset(&set);
417 sigaddset(&set, SIGUSR1);
418 pthread_sigmask(SIG_UNBLOCK, &set, NULL);
419
420 memset(&sigact, 0, sizeof(sigact));
421 sigact.sa_handler = cpu_signal;
422 sigaction(SIGUSR1, &sigact, NULL);
423}
424
425static void unblock_io_signals(void)
426{
427 sigset_t set;
428
429 sigemptyset(&set);
430 sigaddset(&set, SIGUSR2);
431 sigaddset(&set, SIGIO);
432 sigaddset(&set, SIGALRM);
433 pthread_sigmask(SIG_UNBLOCK, &set, NULL);
434
435 sigemptyset(&set);
436 sigaddset(&set, SIGUSR1);
437 pthread_sigmask(SIG_BLOCK, &set, NULL);
438}
439
440static void qemu_signal_lock(unsigned int msecs)
441{
442 qemu_mutex_lock(&qemu_fair_mutex);
443
444 while (qemu_mutex_trylock(&qemu_global_mutex)) {
445 qemu_thread_signal(tcg_cpu_thread, SIGUSR1);
446 if (!qemu_mutex_timedlock(&qemu_global_mutex, msecs))
447 break;
448 }
449 qemu_mutex_unlock(&qemu_fair_mutex);
450}
451
452void qemu_mutex_lock_iothread(void)
453{
Jun Nakajimaa381ef02011-12-17 19:13:25 -0800454 if (kvm_enabled() || hax_enabled()) {
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200455 qemu_mutex_lock(&qemu_fair_mutex);
456 qemu_mutex_lock(&qemu_global_mutex);
457 qemu_mutex_unlock(&qemu_fair_mutex);
458 } else
459 qemu_signal_lock(100);
460}
461
462void qemu_mutex_unlock_iothread(void)
463{
464 qemu_mutex_unlock(&qemu_global_mutex);
465}
466
467static int all_vcpus_paused(void)
468{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100469 CPUOldState *penv = first_cpu;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200470
471 while (penv) {
472 if (!penv->stopped)
473 return 0;
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100474 penv = (CPUOldState *)penv->next_cpu;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200475 }
476
477 return 1;
478}
479
480void pause_all_vcpus(void)
481{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100482 CPUOldState *penv = first_cpu;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200483
484 while (penv) {
485 penv->stop = 1;
486 qemu_thread_signal(penv->thread, SIGUSR1);
487 qemu_cpu_kick(penv);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100488 penv = (CPUOldState *)penv->next_cpu;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200489 }
490
491 while (!all_vcpus_paused()) {
492 qemu_cond_timedwait(&qemu_pause_cond, &qemu_global_mutex, 100);
493 penv = first_cpu;
494 while (penv) {
495 qemu_thread_signal(penv->thread, SIGUSR1);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100496 penv = (CPUOldState *)penv->next_cpu;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200497 }
498 }
499}
500
501void resume_all_vcpus(void)
502{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100503 CPUOldState *penv = first_cpu;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200504
505 while (penv) {
506 penv->stop = 0;
507 penv->stopped = 0;
508 qemu_thread_signal(penv->thread, SIGUSR1);
509 qemu_cpu_kick(penv);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100510 penv = (CPUOldState *)penv->next_cpu;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200511 }
512}
513
514static void tcg_init_vcpu(void *_env)
515{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100516 CPUOldState *env = _env;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200517 /* share a single thread for all cpus with TCG */
518 if (!tcg_cpu_thread) {
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100519 env->thread = g_malloc0(sizeof(QemuThread));
520 env->halt_cond = g_malloc0(sizeof(QemuCond));
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200521 qemu_cond_init(env->halt_cond);
522 qemu_thread_create(env->thread, tcg_cpu_thread_fn, env);
523 while (env->created == 0)
524 qemu_cond_timedwait(&qemu_cpu_cond, &qemu_global_mutex, 100);
525 tcg_cpu_thread = env->thread;
526 tcg_halt_cond = env->halt_cond;
527 } else {
528 env->thread = tcg_cpu_thread;
529 env->halt_cond = tcg_halt_cond;
530 }
531}
532
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100533static void kvm_start_vcpu(CPUOldState *env)
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200534{
535#if 0
536 kvm_init_vcpu(env);
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100537 env->thread = g_malloc0(sizeof(QemuThread));
538 env->halt_cond = g_malloc0(sizeof(QemuCond));
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200539 qemu_cond_init(env->halt_cond);
540 qemu_thread_create(env->thread, kvm_cpu_thread_fn, env);
541 while (env->created == 0)
542 qemu_cond_timedwait(&qemu_cpu_cond, &qemu_global_mutex, 100);
543#endif
544}
545
546void qemu_init_vcpu(void *_env)
547{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100548 CPUOldState *env = _env;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200549
550 if (kvm_enabled())
551 kvm_start_vcpu(env);
552 else
553 tcg_init_vcpu(env);
554}
555
556void qemu_notify_event(void)
557{
558 qemu_event_increment();
559}
560
561void vm_stop(int reason)
562{
563 QemuThread me;
564 qemu_thread_self(&me);
565
566 if (!qemu_thread_equal(&me, &io_thread)) {
567 qemu_system_vmstop_request(reason);
568 /*
569 * FIXME: should not return to device code in case
570 * vm_stop() has been requested.
571 */
572 if (cpu_single_env) {
573 cpu_exit(cpu_single_env);
574 cpu_single_env->stop = 1;
575 }
576 return;
577 }
578 do_vm_stop(reason);
579}
580
581#endif
582
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100583static int qemu_cpu_exec(CPUOldState *env)
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200584{
585 int ret;
586#ifdef CONFIG_PROFILER
587 int64_t ti;
588#endif
589
590#ifdef CONFIG_PROFILER
591 ti = profile_getclock();
592#endif
593 if (use_icount) {
594 int64_t count;
595 int decr;
596 qemu_icount -= (env->icount_decr.u16.low + env->icount_extra);
597 env->icount_decr.u16.low = 0;
598 env->icount_extra = 0;
599 count = qemu_next_icount_deadline();
600 count = (count + (1 << icount_time_shift) - 1)
601 >> icount_time_shift;
602 qemu_icount += count;
603 decr = (count > 0xffff) ? 0xffff : count;
604 count -= decr;
605 env->icount_decr.u16.low = decr;
606 env->icount_extra = count;
607 }
608#ifdef CONFIG_TRACE
609 if (tbflush_requested) {
610 tbflush_requested = 0;
611 tb_flush(env);
612 return EXCP_INTERRUPT;
613 }
614#endif
615
616
617 ret = cpu_exec(env);
618#ifdef CONFIG_PROFILER
619 qemu_time += profile_getclock() - ti;
620#endif
621 if (use_icount) {
622 /* Fold pending instructions back into the
623 instruction counter, and clear the interrupt flag. */
624 qemu_icount -= (env->icount_decr.u16.low
625 + env->icount_extra);
626 env->icount_decr.u32 = 0;
627 env->icount_extra = 0;
628 }
629 return ret;
630}
631
632void tcg_cpu_exec(void)
633{
634 int ret = 0;
635
636 if (next_cpu == NULL)
637 next_cpu = first_cpu;
638 for (; next_cpu != NULL; next_cpu = next_cpu->next_cpu) {
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100639 CPUOldState *env = cur_cpu = next_cpu;
David 'Digit' Turner23ca2ae2011-06-01 16:14:53 +0200640
641 if (!vm_running)
642 break;
643 if (qemu_timer_alarm_pending()) {
644 break;
645 }
646 if (cpu_can_run(env))
647 ret = qemu_cpu_exec(env);
648 if (ret == EXCP_DEBUG) {
649 gdb_set_stop_cpu(env);
650 debug_requested = 1;
651 break;
652 }
653 }
654}
655