From 23ca2ae2bf303236eb6b1e0beb126ec05c6c23bf Mon Sep 17 00:00:00 2001 From: David 'Digit' Turner Date: Wed, 1 Jun 2011 16:14:53 +0200 Subject: vl-android.c: move cpu functions to cpus.c Change-Id: Ib422f24224c2e75dd126689c67dbbb187d7c1670 --- Makefile.target | 2 + cpus.c | 629 ++++++++++++++++++++++++++++++++++++++++++++++++ cpus.h | 36 +++ vl-android.c | 733 +------------------------------------------------------- vl.c | 661 +------------------------------------------------- 5 files changed, 675 insertions(+), 1386 deletions(-) create mode 100644 cpus.c create mode 100644 cpus.h diff --git a/Makefile.target b/Makefile.target index aa3824b..190219f 100644 --- a/Makefile.target +++ b/Makefile.target @@ -248,6 +248,7 @@ LOCAL_LDLIBS += \ LOCAL_SRC_FILES := \ audio/audio.c \ + cpus.c \ disas.c \ dma-helpers.c \ gdbstub.c \ @@ -325,6 +326,7 @@ LOCAL_CFLAGS += \ LOCAL_SRC_FILES := \ audio/audio.c \ + cpus.c \ disas.c \ dma-helpers.c \ gdbstub.c \ diff --git a/cpus.c b/cpus.c new file mode 100644 index 0000000..470eb32 --- /dev/null +++ b/cpus.c @@ -0,0 +1,629 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "config-host.h" + +#include "monitor.h" +#include "sysemu.h" +#include "gdbstub.h" +#include "dma.h" +#include "kvm.h" + +#include "cpus.h" + +static CPUState *cur_cpu; +static CPUState *next_cpu; + +/***********************************************************/ +void hw_error(const char *fmt, ...) +{ + va_list ap; + CPUState *env; + + va_start(ap, fmt); + fprintf(stderr, "qemu: hardware error: "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + for(env = first_cpu; env != NULL; env = env->next_cpu) { + fprintf(stderr, "CPU #%d:\n", env->cpu_index); +#ifdef TARGET_I386 + cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU); +#else + cpu_dump_state(env, stderr, fprintf, 0); +#endif + } + va_end(ap); + abort(); +} + +static void do_vm_stop(int reason) +{ + if (vm_running) { + cpu_disable_ticks(); + vm_running = 0; + pause_all_vcpus(); + vm_state_notify(0, reason); + } +} + +static int cpu_can_run(CPUState *env) +{ + if (env->stop) + return 0; + if (env->stopped) + return 0; + return 1; +} + +static int cpu_has_work(CPUState *env) +{ + if (env->stop) + return 1; + if (env->stopped) + return 0; + if (!env->halted) + return 1; + if (qemu_cpu_has_work(env)) + return 1; + return 0; +} + +int tcg_has_work(void) +{ + CPUState *env; + + for (env = first_cpu; env != NULL; env = env->next_cpu) + if (cpu_has_work(env)) + return 1; + return 0; +} + +#ifndef _WIN32 +static int io_thread_fd = -1; + +#if 0 +static void qemu_event_increment(void) +{ + static const char byte = 0; + + if (io_thread_fd == -1) + return; + + write(io_thread_fd, &byte, sizeof(byte)); +} +#endif + +static void qemu_event_read(void *opaque) +{ + int fd = (unsigned long)opaque; + ssize_t len; + + /* Drain the notify pipe */ + do { + char buffer[512]; + len = read(fd, buffer, sizeof(buffer)); + } while ((len == -1 && errno == EINTR) || len > 0); +} + +static int qemu_event_init(void) +{ + int err; + int fds[2]; + + err = pipe(fds); + if (err == -1) + return -errno; + + err = fcntl_setfl(fds[0], O_NONBLOCK); + if (err < 0) + goto fail; + + err = fcntl_setfl(fds[1], O_NONBLOCK); + if (err < 0) + goto fail; + + qemu_set_fd_handler2(fds[0], NULL, qemu_event_read, NULL, + (void *)(unsigned long)fds[0]); + + io_thread_fd = fds[1]; + return 0; + +fail: + close(fds[0]); + close(fds[1]); + return err; +} +#else +HANDLE qemu_event_handle; + +static void dummy_event_handler(void *opaque) +{ +} + +static int qemu_event_init(void) +{ + qemu_event_handle = CreateEvent(NULL, FALSE, FALSE, NULL); + if (!qemu_event_handle) { + perror("Failed CreateEvent"); + return -1; + } + qemu_add_wait_object(qemu_event_handle, dummy_event_handler, NULL); + return 0; +} + +#if 0 +static void qemu_event_increment(void) +{ + SetEvent(qemu_event_handle); +} +#endif +#endif + +#ifndef CONFIG_IOTHREAD +int qemu_init_main_loop(void) +{ + return qemu_event_init(); +} + +void qemu_init_vcpu(void *_env) +{ + CPUState *env = _env; + + if (kvm_enabled()) + kvm_init_vcpu(env); + return; +} + +int qemu_cpu_self(void *env) +{ + return 1; +} + +void resume_all_vcpus(void) +{ +} + +void pause_all_vcpus(void) +{ +} + +void qemu_cpu_kick(void *env) +{ + return; +} + +void qemu_notify_event(void) +{ + CPUState *env = cpu_single_env; + + if (env) { + cpu_exit(env); +#ifdef USE_KQEMU + if (env->kqemu_enabled) + kqemu_cpu_interrupt(env); +#endif + } +} + +void qemu_mutex_lock_iothread(void) +{ +} + +void qemu_mutex_unlock_iothread(void) +{ +} + +void vm_stop(int reason) +{ + do_vm_stop(reason); +} + +#else /* CONFIG_IOTHREAD */ + +#include "qemu-thread.h" + +QemuMutex qemu_global_mutex; +static QemuMutex qemu_fair_mutex; + +static QemuThread io_thread; + +static QemuThread *tcg_cpu_thread; +static QemuCond *tcg_halt_cond; + +static int qemu_system_ready; +/* cpu creation */ +static QemuCond qemu_cpu_cond; +/* system init */ +static QemuCond qemu_system_cond; +static QemuCond qemu_pause_cond; + +static void block_io_signals(void); +static void unblock_io_signals(void); +static int tcg_has_work(void); + +int qemu_init_main_loop(void) +{ + int ret; + + ret = qemu_event_init(); + if (ret) + return ret; + + qemu_cond_init(&qemu_pause_cond); + qemu_mutex_init(&qemu_fair_mutex); + qemu_mutex_init(&qemu_global_mutex); + qemu_mutex_lock(&qemu_global_mutex); + + unblock_io_signals(); + qemu_thread_self(&io_thread); + + return 0; +} + +static void qemu_wait_io_event(CPUState *env) +{ + while (!tcg_has_work()) + qemu_cond_timedwait(env->halt_cond, &qemu_global_mutex, 1000); + + qemu_mutex_unlock(&qemu_global_mutex); + + /* + * Users of qemu_global_mutex can be starved, having no chance + * to acquire it since this path will get to it first. + * So use another lock to provide fairness. + */ + qemu_mutex_lock(&qemu_fair_mutex); + qemu_mutex_unlock(&qemu_fair_mutex); + + qemu_mutex_lock(&qemu_global_mutex); + if (env->stop) { + env->stop = 0; + env->stopped = 1; + qemu_cond_signal(&qemu_pause_cond); + } +} + +static int qemu_cpu_exec(CPUState *env); + +static void *kvm_cpu_thread_fn(void *arg) +{ + CPUState *env = arg; + + block_io_signals(); + qemu_thread_self(env->thread); + + /* signal CPU creation */ + qemu_mutex_lock(&qemu_global_mutex); + env->created = 1; + qemu_cond_signal(&qemu_cpu_cond); + + /* and wait for machine initialization */ + while (!qemu_system_ready) + qemu_cond_timedwait(&qemu_system_cond, &qemu_global_mutex, 100); + + while (1) { + if (cpu_can_run(env)) + qemu_cpu_exec(env); + qemu_wait_io_event(env); + } + + return NULL; +} + +static void tcg_cpu_exec(void); + +static void *tcg_cpu_thread_fn(void *arg) +{ + CPUState *env = arg; + + block_io_signals(); + qemu_thread_self(env->thread); + + /* signal CPU creation */ + qemu_mutex_lock(&qemu_global_mutex); + for (env = first_cpu; env != NULL; env = env->next_cpu) + env->created = 1; + qemu_cond_signal(&qemu_cpu_cond); + + /* and wait for machine initialization */ + while (!qemu_system_ready) + qemu_cond_timedwait(&qemu_system_cond, &qemu_global_mutex, 100); + + while (1) { + tcg_cpu_exec(); + qemu_wait_io_event(cur_cpu); + } + + return NULL; +} + +void qemu_cpu_kick(void *_env) +{ + CPUState *env = _env; + qemu_cond_broadcast(env->halt_cond); + if (kvm_enabled()) + qemu_thread_signal(env->thread, SIGUSR1); +} + +int qemu_cpu_self(void *env) +{ + return (cpu_single_env != NULL); +} + +static void cpu_signal(int sig) +{ + if (cpu_single_env) + cpu_exit(cpu_single_env); +} + +static void block_io_signals(void) +{ + sigset_t set; + struct sigaction sigact; + + sigemptyset(&set); + sigaddset(&set, SIGUSR2); + sigaddset(&set, SIGIO); + sigaddset(&set, SIGALRM); + pthread_sigmask(SIG_BLOCK, &set, NULL); + + sigemptyset(&set); + sigaddset(&set, SIGUSR1); + pthread_sigmask(SIG_UNBLOCK, &set, NULL); + + memset(&sigact, 0, sizeof(sigact)); + sigact.sa_handler = cpu_signal; + sigaction(SIGUSR1, &sigact, NULL); +} + +static void unblock_io_signals(void) +{ + sigset_t set; + + sigemptyset(&set); + sigaddset(&set, SIGUSR2); + sigaddset(&set, SIGIO); + sigaddset(&set, SIGALRM); + pthread_sigmask(SIG_UNBLOCK, &set, NULL); + + sigemptyset(&set); + sigaddset(&set, SIGUSR1); + pthread_sigmask(SIG_BLOCK, &set, NULL); +} + +static void qemu_signal_lock(unsigned int msecs) +{ + qemu_mutex_lock(&qemu_fair_mutex); + + while (qemu_mutex_trylock(&qemu_global_mutex)) { + qemu_thread_signal(tcg_cpu_thread, SIGUSR1); + if (!qemu_mutex_timedlock(&qemu_global_mutex, msecs)) + break; + } + qemu_mutex_unlock(&qemu_fair_mutex); +} + +void qemu_mutex_lock_iothread(void) +{ + if (kvm_enabled()) { + qemu_mutex_lock(&qemu_fair_mutex); + qemu_mutex_lock(&qemu_global_mutex); + qemu_mutex_unlock(&qemu_fair_mutex); + } else + qemu_signal_lock(100); +} + +void qemu_mutex_unlock_iothread(void) +{ + qemu_mutex_unlock(&qemu_global_mutex); +} + +static int all_vcpus_paused(void) +{ + CPUState *penv = first_cpu; + + while (penv) { + if (!penv->stopped) + return 0; + penv = (CPUState *)penv->next_cpu; + } + + return 1; +} + +void pause_all_vcpus(void) +{ + CPUState *penv = first_cpu; + + while (penv) { + penv->stop = 1; + qemu_thread_signal(penv->thread, SIGUSR1); + qemu_cpu_kick(penv); + penv = (CPUState *)penv->next_cpu; + } + + while (!all_vcpus_paused()) { + qemu_cond_timedwait(&qemu_pause_cond, &qemu_global_mutex, 100); + penv = first_cpu; + while (penv) { + qemu_thread_signal(penv->thread, SIGUSR1); + penv = (CPUState *)penv->next_cpu; + } + } +} + +void resume_all_vcpus(void) +{ + CPUState *penv = first_cpu; + + while (penv) { + penv->stop = 0; + penv->stopped = 0; + qemu_thread_signal(penv->thread, SIGUSR1); + qemu_cpu_kick(penv); + penv = (CPUState *)penv->next_cpu; + } +} + +static void tcg_init_vcpu(void *_env) +{ + CPUState *env = _env; + /* share a single thread for all cpus with TCG */ + if (!tcg_cpu_thread) { + env->thread = qemu_mallocz(sizeof(QemuThread)); + env->halt_cond = qemu_mallocz(sizeof(QemuCond)); + qemu_cond_init(env->halt_cond); + qemu_thread_create(env->thread, tcg_cpu_thread_fn, env); + while (env->created == 0) + qemu_cond_timedwait(&qemu_cpu_cond, &qemu_global_mutex, 100); + tcg_cpu_thread = env->thread; + tcg_halt_cond = env->halt_cond; + } else { + env->thread = tcg_cpu_thread; + env->halt_cond = tcg_halt_cond; + } +} + +static void kvm_start_vcpu(CPUState *env) +{ +#if 0 + kvm_init_vcpu(env); + env->thread = qemu_mallocz(sizeof(QemuThread)); + env->halt_cond = qemu_mallocz(sizeof(QemuCond)); + qemu_cond_init(env->halt_cond); + qemu_thread_create(env->thread, kvm_cpu_thread_fn, env); + while (env->created == 0) + qemu_cond_timedwait(&qemu_cpu_cond, &qemu_global_mutex, 100); +#endif +} + +void qemu_init_vcpu(void *_env) +{ + CPUState *env = _env; + + if (kvm_enabled()) + kvm_start_vcpu(env); + else + tcg_init_vcpu(env); +} + +void qemu_notify_event(void) +{ + qemu_event_increment(); +} + +void vm_stop(int reason) +{ + QemuThread me; + qemu_thread_self(&me); + + if (!qemu_thread_equal(&me, &io_thread)) { + qemu_system_vmstop_request(reason); + /* + * FIXME: should not return to device code in case + * vm_stop() has been requested. + */ + if (cpu_single_env) { + cpu_exit(cpu_single_env); + cpu_single_env->stop = 1; + } + return; + } + do_vm_stop(reason); +} + +#endif + +static int qemu_cpu_exec(CPUState *env) +{ + int ret; +#ifdef CONFIG_PROFILER + int64_t ti; +#endif + +#ifdef CONFIG_PROFILER + ti = profile_getclock(); +#endif + if (use_icount) { + int64_t count; + int decr; + qemu_icount -= (env->icount_decr.u16.low + env->icount_extra); + env->icount_decr.u16.low = 0; + env->icount_extra = 0; + count = qemu_next_icount_deadline(); + count = (count + (1 << icount_time_shift) - 1) + >> icount_time_shift; + qemu_icount += count; + decr = (count > 0xffff) ? 0xffff : count; + count -= decr; + env->icount_decr.u16.low = decr; + env->icount_extra = count; + } +#ifdef CONFIG_TRACE + if (tbflush_requested) { + tbflush_requested = 0; + tb_flush(env); + return EXCP_INTERRUPT; + } +#endif + + + ret = cpu_exec(env); +#ifdef CONFIG_PROFILER + qemu_time += profile_getclock() - ti; +#endif + if (use_icount) { + /* Fold pending instructions back into the + instruction counter, and clear the interrupt flag. */ + qemu_icount -= (env->icount_decr.u16.low + + env->icount_extra); + env->icount_decr.u32 = 0; + env->icount_extra = 0; + } + return ret; +} + +void tcg_cpu_exec(void) +{ + int ret = 0; + + if (next_cpu == NULL) + next_cpu = first_cpu; + for (; next_cpu != NULL; next_cpu = next_cpu->next_cpu) { + CPUState *env = cur_cpu = next_cpu; + + if (!vm_running) + break; + if (qemu_timer_alarm_pending()) { + break; + } + if (cpu_can_run(env)) + ret = qemu_cpu_exec(env); + if (ret == EXCP_DEBUG) { + gdb_set_stop_cpu(env); + debug_requested = 1; + break; + } + } +} + diff --git a/cpus.h b/cpus.h new file mode 100644 index 0000000..c25f35e --- /dev/null +++ b/cpus.h @@ -0,0 +1,36 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef QEMU_CPUS_H +#define QEMU_CPUS_H + +void tcg_cpu_exec(void); +void vm_state_notify(int running, int reason); +extern int tbflush_requested; +extern int debug_requested; + +void resume_all_vcpus(void); +void pause_all_vcpus(void); +int qemu_init_main_loop(void); + +#endif /* QEMU_CPUS_H */ diff --git a/vl-android.c b/vl-android.c index 18fdb40..c85aff5 100644 --- a/vl-android.c +++ b/vl-android.c @@ -162,6 +162,7 @@ #define memalign(align, size) malloc(size) #endif +#include "cpus.h" #ifdef CONFIG_COCOA #undef main @@ -329,8 +330,6 @@ int nb_numa_nodes; uint64_t node_mem[MAX_NODES]; uint64_t node_cpumask[MAX_NODES]; -static CPUState *cur_cpu; -static CPUState *next_cpu; static QEMUTimer *nographic_timer; uint8_t qemu_uuid[16]; @@ -562,28 +561,6 @@ FILE* rotate_qemu_log(FILE* old_log_fd, const char* filename) { return new_log_fd; } -/***********************************************************/ -void hw_error(const char *fmt, ...) -{ - va_list ap; - CPUState *env; - - va_start(ap, fmt); - fprintf(stderr, "qemu: hardware error: "); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); - for(env = first_cpu; env != NULL; env = env->next_cpu) { - fprintf(stderr, "CPU #%d:\n", env->cpu_index); -#ifdef TARGET_I386 - cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU); -#else - cpu_dump_state(env, stderr, fprintf, 0); -#endif - } - va_end(ap); - abort(); -} - /***************/ /* ballooning */ @@ -648,7 +625,7 @@ int qemu_timedate_diff(struct tm *tm) #ifdef CONFIG_TRACE -static int tbflush_requested; +int tbflush_requested; static int exit_requested; void start_tracing() @@ -1717,86 +1694,6 @@ void pcmcia_info(Monitor *mon) "Empty"); } -#ifdef _WIN32 -/***********************************************************/ -/* Polling handling */ - -typedef struct PollingEntry { - PollingFunc *func; - void *opaque; - struct PollingEntry *next; -} PollingEntry; - -static PollingEntry *first_polling_entry; - -int qemu_add_polling_cb(PollingFunc *func, void *opaque) -{ - PollingEntry **ppe, *pe; - pe = qemu_mallocz(sizeof(PollingEntry)); - pe->func = func; - pe->opaque = opaque; - for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next); - *ppe = pe; - return 0; -} - -void qemu_del_polling_cb(PollingFunc *func, void *opaque) -{ - PollingEntry **ppe, *pe; - for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next) { - pe = *ppe; - if (pe->func == func && pe->opaque == opaque) { - *ppe = pe->next; - qemu_free(pe); - break; - } - } -} - -/***********************************************************/ -/* Wait objects support */ -typedef struct WaitObjects { - int num; - HANDLE events[MAXIMUM_WAIT_OBJECTS + 1]; - WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS + 1]; - void *opaque[MAXIMUM_WAIT_OBJECTS + 1]; -} WaitObjects; - -static WaitObjects wait_objects = {0}; - -int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque) -{ - WaitObjects *w = &wait_objects; - - if (w->num >= MAXIMUM_WAIT_OBJECTS) - return -1; - w->events[w->num] = handle; - w->func[w->num] = func; - w->opaque[w->num] = opaque; - w->num++; - return 0; -} - -void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque) -{ - int i, found; - WaitObjects *w = &wait_objects; - - found = 0; - for (i = 0; i < w->num; i++) { - if (w->events[i] == handle) - found = 1; - if (found) { - w->events[i] = w->events[i + 1]; - w->func[i] = w->func[i + 1]; - w->opaque[i] = w->opaque[i + 1]; - } - } - if (found) - w->num--; -} -#endif - /***********************************************************/ /* ram save/restore */ @@ -2207,7 +2104,7 @@ void qemu_del_vm_change_state_handler(VMChangeStateEntry *e) qemu_free (e); } -static void vm_state_notify(int running, int reason) +void vm_state_notify(int running, int reason) { VMChangeStateEntry *e; @@ -2216,9 +2113,6 @@ static void vm_state_notify(int running, int reason) } } -static void resume_all_vcpus(void); -static void pause_all_vcpus(void); - void vm_start(void) { if (!vm_running) { @@ -2244,7 +2138,7 @@ static int reset_requested; static int shutdown_requested, shutdown_signal = -1; static pid_t shutdown_pid; static int powerdown_requested; -static int debug_requested; +int debug_requested; static int vmstop_requested; int qemu_shutdown_requested(void) @@ -2282,16 +2176,6 @@ static int qemu_vmstop_requested(void) return r; } -static void do_vm_stop(int reason) -{ - if (vm_running) { - cpu_disable_ticks(); - vm_running = 0; - pause_all_vcpus(); - vm_state_notify(0, reason); - } -} - void qemu_register_reset(QEMUResetHandler *func, int order, void *opaque) { QEMUResetEntry **pre, *re; @@ -2355,517 +2239,6 @@ static void qemu_system_vmstop_request(int reason) } #endif -#ifndef _WIN32 -static int io_thread_fd = -1; - -#if 0 -static void qemu_event_increment(void) -{ - static const char byte = 0; - - if (io_thread_fd == -1) - return; - - write(io_thread_fd, &byte, sizeof(byte)); -} -#endif - -static void qemu_event_read(void *opaque) -{ - int fd = (unsigned long)opaque; - ssize_t len; - - /* Drain the notify pipe */ - do { - char buffer[512]; - len = read(fd, buffer, sizeof(buffer)); - } while ((len == -1 && errno == EINTR) || len > 0); -} - -static int qemu_event_init(void) -{ - int err; - int fds[2]; - - err = pipe(fds); - if (err == -1) - return -errno; - - err = fcntl_setfl(fds[0], O_NONBLOCK); - if (err < 0) - goto fail; - - err = fcntl_setfl(fds[1], O_NONBLOCK); - if (err < 0) - goto fail; - - qemu_set_fd_handler2(fds[0], NULL, qemu_event_read, NULL, - (void *)(unsigned long)fds[0]); - - io_thread_fd = fds[1]; - return 0; - -fail: - close(fds[0]); - close(fds[1]); - return err; -} -#else -HANDLE qemu_event_handle; - -static void dummy_event_handler(void *opaque) -{ -} - -static int qemu_event_init(void) -{ - qemu_event_handle = CreateEvent(NULL, FALSE, FALSE, NULL); - if (!qemu_event_handle) { - perror("Failed CreateEvent"); - return -1; - } - qemu_add_wait_object(qemu_event_handle, dummy_event_handler, NULL); - return 0; -} - -#if 0 -static void qemu_event_increment(void) -{ - SetEvent(qemu_event_handle); -} -#endif -#endif - -static int cpu_can_run(CPUState *env) -{ - if (env->stop) - return 0; - if (env->stopped) - return 0; - return 1; -} - -#ifndef CONFIG_IOTHREAD -static int qemu_init_main_loop(void) -{ - return qemu_event_init(); -} - -void qemu_init_vcpu(void *_env) -{ - CPUState *env = _env; - - if (kvm_enabled()) - kvm_init_vcpu(env); - return; -} - -int qemu_cpu_self(void *env) -{ - return 1; -} - -static void resume_all_vcpus(void) -{ -} - -static void pause_all_vcpus(void) -{ -} - -void qemu_cpu_kick(void *env) -{ - return; -} - -void qemu_notify_event(void) -{ - CPUState *env = cpu_single_env; - - if (env) { - cpu_exit(env); -#ifdef USE_KQEMU - if (env->kqemu_enabled) - kqemu_cpu_interrupt(env); -#endif - } -} - -#define qemu_mutex_lock_iothread() do { } while (0) -#define qemu_mutex_unlock_iothread() do { } while (0) - -void vm_stop(int reason) -{ - do_vm_stop(reason); -} - -#else /* CONFIG_IOTHREAD */ - -#include "qemu-thread.h" - -QemuMutex qemu_global_mutex; -static QemuMutex qemu_fair_mutex; - -static QemuThread io_thread; - -static QemuThread *tcg_cpu_thread; -static QemuCond *tcg_halt_cond; - -static int qemu_system_ready; -/* cpu creation */ -static QemuCond qemu_cpu_cond; -/* system init */ -static QemuCond qemu_system_cond; -static QemuCond qemu_pause_cond; - -static void block_io_signals(void); -static void unblock_io_signals(void); -static int tcg_has_work(void); - -static int qemu_init_main_loop(void) -{ - int ret; - - ret = qemu_event_init(); - if (ret) - return ret; - - qemu_cond_init(&qemu_pause_cond); - qemu_mutex_init(&qemu_fair_mutex); - qemu_mutex_init(&qemu_global_mutex); - qemu_mutex_lock(&qemu_global_mutex); - - unblock_io_signals(); - qemu_thread_self(&io_thread); - - return 0; -} - -static void qemu_wait_io_event(CPUState *env) -{ - while (!tcg_has_work()) - qemu_cond_timedwait(env->halt_cond, &qemu_global_mutex, 1000); - - qemu_mutex_unlock(&qemu_global_mutex); - - /* - * Users of qemu_global_mutex can be starved, having no chance - * to acquire it since this path will get to it first. - * So use another lock to provide fairness. - */ - qemu_mutex_lock(&qemu_fair_mutex); - qemu_mutex_unlock(&qemu_fair_mutex); - - qemu_mutex_lock(&qemu_global_mutex); - if (env->stop) { - env->stop = 0; - env->stopped = 1; - qemu_cond_signal(&qemu_pause_cond); - } -} - -static int qemu_cpu_exec(CPUState *env); - -static void *kvm_cpu_thread_fn(void *arg) -{ - CPUState *env = arg; - - block_io_signals(); - qemu_thread_self(env->thread); - - /* signal CPU creation */ - qemu_mutex_lock(&qemu_global_mutex); - env->created = 1; - qemu_cond_signal(&qemu_cpu_cond); - - /* and wait for machine initialization */ - while (!qemu_system_ready) - qemu_cond_timedwait(&qemu_system_cond, &qemu_global_mutex, 100); - - while (1) { - if (cpu_can_run(env)) - qemu_cpu_exec(env); - qemu_wait_io_event(env); - } - - return NULL; -} - -static void tcg_cpu_exec(void); - -static void *tcg_cpu_thread_fn(void *arg) -{ - CPUState *env = arg; - - block_io_signals(); - qemu_thread_self(env->thread); - - /* signal CPU creation */ - qemu_mutex_lock(&qemu_global_mutex); - for (env = first_cpu; env != NULL; env = env->next_cpu) - env->created = 1; - qemu_cond_signal(&qemu_cpu_cond); - - /* and wait for machine initialization */ - while (!qemu_system_ready) - qemu_cond_timedwait(&qemu_system_cond, &qemu_global_mutex, 100); - - while (1) { - tcg_cpu_exec(); - qemu_wait_io_event(cur_cpu); - } - - return NULL; -} - -void qemu_cpu_kick(void *_env) -{ - CPUState *env = _env; - qemu_cond_broadcast(env->halt_cond); - if (kvm_enabled()) - qemu_thread_signal(env->thread, SIGUSR1); -} - -int qemu_cpu_self(void *env) -{ - return (cpu_single_env != NULL); -} - -static void cpu_signal(int sig) -{ - if (cpu_single_env) - cpu_exit(cpu_single_env); -} - -static void block_io_signals(void) -{ - sigset_t set; - struct sigaction sigact; - - sigemptyset(&set); - sigaddset(&set, SIGUSR2); - sigaddset(&set, SIGIO); - sigaddset(&set, SIGALRM); - pthread_sigmask(SIG_BLOCK, &set, NULL); - - sigemptyset(&set); - sigaddset(&set, SIGUSR1); - pthread_sigmask(SIG_UNBLOCK, &set, NULL); - - memset(&sigact, 0, sizeof(sigact)); - sigact.sa_handler = cpu_signal; - sigaction(SIGUSR1, &sigact, NULL); -} - -static void unblock_io_signals(void) -{ - sigset_t set; - - sigemptyset(&set); - sigaddset(&set, SIGUSR2); - sigaddset(&set, SIGIO); - sigaddset(&set, SIGALRM); - pthread_sigmask(SIG_UNBLOCK, &set, NULL); - - sigemptyset(&set); - sigaddset(&set, SIGUSR1); - pthread_sigmask(SIG_BLOCK, &set, NULL); -} - -static void qemu_signal_lock(unsigned int msecs) -{ - qemu_mutex_lock(&qemu_fair_mutex); - - while (qemu_mutex_trylock(&qemu_global_mutex)) { - qemu_thread_signal(tcg_cpu_thread, SIGUSR1); - if (!qemu_mutex_timedlock(&qemu_global_mutex, msecs)) - break; - } - qemu_mutex_unlock(&qemu_fair_mutex); -} - -void qemu_mutex_lock_iothread(void) -{ - if (kvm_enabled()) { - qemu_mutex_lock(&qemu_fair_mutex); - qemu_mutex_lock(&qemu_global_mutex); - qemu_mutex_unlock(&qemu_fair_mutex); - } else - qemu_signal_lock(100); -} - -void qemu_mutex_unlock_iothread(void) -{ - qemu_mutex_unlock(&qemu_global_mutex); -} - -static int all_vcpus_paused(void) -{ - CPUState *penv = first_cpu; - - while (penv) { - if (!penv->stopped) - return 0; - penv = (CPUState *)penv->next_cpu; - } - - return 1; -} - -static void pause_all_vcpus(void) -{ - CPUState *penv = first_cpu; - - while (penv) { - penv->stop = 1; - qemu_thread_signal(penv->thread, SIGUSR1); - qemu_cpu_kick(penv); - penv = (CPUState *)penv->next_cpu; - } - - while (!all_vcpus_paused()) { - qemu_cond_timedwait(&qemu_pause_cond, &qemu_global_mutex, 100); - penv = first_cpu; - while (penv) { - qemu_thread_signal(penv->thread, SIGUSR1); - penv = (CPUState *)penv->next_cpu; - } - } -} - -static void resume_all_vcpus(void) -{ - CPUState *penv = first_cpu; - - while (penv) { - penv->stop = 0; - penv->stopped = 0; - qemu_thread_signal(penv->thread, SIGUSR1); - qemu_cpu_kick(penv); - penv = (CPUState *)penv->next_cpu; - } -} - -static void tcg_init_vcpu(void *_env) -{ - CPUState *env = _env; - /* share a single thread for all cpus with TCG */ - if (!tcg_cpu_thread) { - env->thread = qemu_mallocz(sizeof(QemuThread)); - env->halt_cond = qemu_mallocz(sizeof(QemuCond)); - qemu_cond_init(env->halt_cond); - qemu_thread_create(env->thread, tcg_cpu_thread_fn, env); - while (env->created == 0) - qemu_cond_timedwait(&qemu_cpu_cond, &qemu_global_mutex, 100); - tcg_cpu_thread = env->thread; - tcg_halt_cond = env->halt_cond; - } else { - env->thread = tcg_cpu_thread; - env->halt_cond = tcg_halt_cond; - } -} - -static void kvm_start_vcpu(CPUState *env) -{ -#if 0 - kvm_init_vcpu(env); - env->thread = qemu_mallocz(sizeof(QemuThread)); - env->halt_cond = qemu_mallocz(sizeof(QemuCond)); - qemu_cond_init(env->halt_cond); - qemu_thread_create(env->thread, kvm_cpu_thread_fn, env); - while (env->created == 0) - qemu_cond_timedwait(&qemu_cpu_cond, &qemu_global_mutex, 100); -#endif -} - -void qemu_init_vcpu(void *_env) -{ - CPUState *env = _env; - - if (kvm_enabled()) - kvm_start_vcpu(env); - else - tcg_init_vcpu(env); -} - -void qemu_notify_event(void) -{ - qemu_event_increment(); -} - -void vm_stop(int reason) -{ - QemuThread me; - qemu_thread_self(&me); - - if (!qemu_thread_equal(&me, &io_thread)) { - qemu_system_vmstop_request(reason); - /* - * FIXME: should not return to device code in case - * vm_stop() has been requested. - */ - if (cpu_single_env) { - cpu_exit(cpu_single_env); - cpu_single_env->stop = 1; - } - return; - } - do_vm_stop(reason); -} - -#endif - - -#ifdef _WIN32 -static void host_main_loop_wait(int *timeout) -{ - int ret, ret2, i; - PollingEntry *pe; - - - /* XXX: need to suppress polling by better using win32 events */ - ret = 0; - for(pe = first_polling_entry; pe != NULL; pe = pe->next) { - ret |= pe->func(pe->opaque); - } - if (ret == 0) { - int err; - WaitObjects *w = &wait_objects; - - ret = WaitForMultipleObjects(w->num, w->events, FALSE, *timeout); - if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) { - if (w->func[ret - WAIT_OBJECT_0]) - w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]); - - /* Check for additional signaled events */ - for(i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) { - - /* Check if event is signaled */ - ret2 = WaitForSingleObject(w->events[i], 0); - if(ret2 == WAIT_OBJECT_0) { - if (w->func[i]) - w->func[i](w->opaque[i]); - } else if (ret2 == WAIT_TIMEOUT) { - } else { - err = GetLastError(); - fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err); - } - } - } else if (ret == WAIT_TIMEOUT) { - } else { - err = GetLastError(); - fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err); - } - } - - *timeout = 0; -} -#else -static void host_main_loop_wait(int *timeout) -{ -} -#endif - void main_loop_wait(int timeout) { fd_set rfds, wfds, xfds; @@ -2874,7 +2247,7 @@ void main_loop_wait(int timeout) qemu_bh_update_timeout(&timeout); - host_main_loop_wait(&timeout); + os_host_main_loop_wait(&timeout); tv.tv_sec = timeout / 1000; @@ -2914,102 +2287,6 @@ void main_loop_wait(int timeout) } -static int qemu_cpu_exec(CPUState *env) -{ - int ret; -#ifdef CONFIG_PROFILER - int64_t ti; -#endif - -#ifdef CONFIG_PROFILER - ti = profile_getclock(); -#endif - if (use_icount) { - int64_t count; - int decr; - qemu_icount -= (env->icount_decr.u16.low + env->icount_extra); - env->icount_decr.u16.low = 0; - env->icount_extra = 0; - count = qemu_next_icount_deadline(); - count = (count + (1 << icount_time_shift) - 1) - >> icount_time_shift; - qemu_icount += count; - decr = (count > 0xffff) ? 0xffff : count; - count -= decr; - env->icount_decr.u16.low = decr; - env->icount_extra = count; - } -#ifdef CONFIG_TRACE - if (tbflush_requested) { - tbflush_requested = 0; - tb_flush(env); - return EXCP_INTERRUPT; - } -#endif - - - ret = cpu_exec(env); -#ifdef CONFIG_PROFILER - qemu_time += profile_getclock() - ti; -#endif - if (use_icount) { - /* Fold pending instructions back into the - instruction counter, and clear the interrupt flag. */ - qemu_icount -= (env->icount_decr.u16.low - + env->icount_extra); - env->icount_decr.u32 = 0; - env->icount_extra = 0; - } - return ret; -} - -static void tcg_cpu_exec(void) -{ - int ret = 0; - - if (next_cpu == NULL) - next_cpu = first_cpu; - for (; next_cpu != NULL; next_cpu = next_cpu->next_cpu) { - CPUState *env = cur_cpu = next_cpu; - - if (!vm_running) - break; - if (qemu_timer_alarm_pending()) { - break; - } - if (cpu_can_run(env)) - ret = qemu_cpu_exec(env); - if (ret == EXCP_DEBUG) { - gdb_set_stop_cpu(env); - debug_requested = 1; - break; - } - } -} - -static int cpu_has_work(CPUState *env) -{ - if (env->stop) - return 1; - if (env->stopped) - return 0; - if (!env->halted) - return 1; - if (qemu_cpu_has_work(env)) - return 1; - return 0; -} - -int tcg_has_work(void) -{ - CPUState *env; - - for (env = first_cpu; env != NULL; env = env->next_cpu) - if (cpu_has_work(env)) - return 1; - return 0; -} - static int vm_can_run(void) { if (powerdown_requested) diff --git a/vl.c b/vl.c index feb8831..f1246f4 100644 --- a/vl.c +++ b/vl.c @@ -261,9 +261,6 @@ int nb_numa_nodes; uint64_t node_mem[MAX_NODES]; uint64_t node_cpumask[MAX_NODES]; -static CPUState *cur_cpu; -static CPUState *next_cpu; -static int timer_alarm_pending = 1; static QEMUTimer *nographic_timer; uint8_t qemu_uuid[16]; @@ -351,28 +348,6 @@ static void default_ioport_writel(void *opaque, uint32_t address, uint32_t data) } -/***********************************************************/ -void hw_error(const char *fmt, ...) -{ - va_list ap; - CPUState *env; - - va_start(ap, fmt); - fprintf(stderr, "qemu: hardware error: "); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); - for(env = first_cpu; env != NULL; env = env->next_cpu) { - fprintf(stderr, "CPU #%d:\n", env->cpu_index); -#ifdef TARGET_I386 - cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU); -#else - cpu_dump_state(env, stderr, fprintf, 0); -#endif - } - va_end(ap); - abort(); -} - /***************/ /* ballooning */ @@ -1932,7 +1907,7 @@ void qemu_del_vm_change_state_handler(VMChangeStateEntry *e) qemu_free (e); } -static void vm_state_notify(int running, int reason) +void vm_state_notify(int running, int reason) { VMChangeStateEntry *e; @@ -1941,9 +1916,6 @@ static void vm_state_notify(int running, int reason) } } -static void resume_all_vcpus(void); -static void pause_all_vcpus(void); - void vm_start(void) { if (!vm_running) { @@ -1969,7 +1941,7 @@ static int reset_requested; static int shutdown_requested, shutdown_signal = -1; static pid_t shutdown_pid; static int powerdown_requested; -static int debug_requested; +int debug_requested; static int vmstop_requested; int qemu_shutdown_requested(void) @@ -2007,38 +1979,6 @@ static int qemu_vmstop_requested(void) return r; } -void qemu_register_reset(QEMUResetHandler *func, void *opaque) -{ - QEMUResetEntry *re = qemu_mallocz(sizeof(QEMUResetEntry)); - - re->func = func; - re->opaque = opaque; - QTAILQ_INSERT_TAIL(&reset_handlers, re, entry); -} - -void qemu_unregister_reset(QEMUResetHandler *func, void *opaque) -{ - QEMUResetEntry *re; - - QTAILQ_FOREACH(re, &reset_handlers, entry) { - if (re->func == func && re->opaque == opaque) { - QTAILQ_REMOVE(&reset_handlers, re, entry); - qemu_free(re); - return; - } - } -} - -static void do_vm_stop(int reason) -{ - if (vm_running) { - cpu_disable_ticks(); - vm_running = 0; - pause_all_vcpus(); - vm_state_notify(0, reason); - } -} - void qemu_register_reset(QEMUResetHandler *func, int order, void *opaque) { QEMUResetEntry **pre, *re; @@ -2102,519 +2042,15 @@ static void qemu_system_vmstop_request(int reason) } #endif -#ifndef _WIN32 -static int io_thread_fd = -1; - -static void qemu_event_increment(void) -{ - static const char byte = 0; - - if (io_thread_fd == -1) - return; - - write(io_thread_fd, &byte, sizeof(byte)); -} - -static void qemu_event_read(void *opaque) -{ - int fd = (unsigned long)opaque; - ssize_t len; - - /* Drain the notify pipe */ - do { - char buffer[512]; - len = read(fd, buffer, sizeof(buffer)); - } while ((len == -1 && errno == EINTR) || len > 0); -} - -static int qemu_event_init(void) -{ - int err; - int fds[2]; - - err = pipe(fds); - if (err == -1) - return -errno; - - err = fcntl_setfl(fds[0], O_NONBLOCK); - if (err < 0) - goto fail; - - err = fcntl_setfl(fds[1], O_NONBLOCK); - if (err < 0) - goto fail; - - qemu_set_fd_handler2(fds[0], NULL, qemu_event_read, NULL, - (void *)(unsigned long)fds[0]); - - io_thread_fd = fds[1]; - return 0; - -fail: - close(fds[0]); - close(fds[1]); - return err; -} -#else -HANDLE qemu_event_handle; - -static void dummy_event_handler(void *opaque) -{ -} - -static int qemu_event_init(void) -{ - qemu_event_handle = CreateEvent(NULL, FALSE, FALSE, NULL); - if (!qemu_event_handle) { - perror("Failed CreateEvent"); - return -1; - } - qemu_add_wait_object(qemu_event_handle, dummy_event_handler, NULL); - return 0; -} - -static void qemu_event_increment(void) -{ - SetEvent(qemu_event_handle); -} -#endif - -static int cpu_can_run(CPUState *env) -{ - if (env->stop) - return 0; - if (env->stopped) - return 0; - if (!vm_running) - return 0; - return 1; -} - -#ifndef CONFIG_IOTHREAD -static int qemu_init_main_loop(void) -{ - return qemu_event_init(); -} - -void qemu_init_vcpu(void *_env) -{ - CPUState *env = _env; - - if (kvm_enabled()) - kvm_init_vcpu(env); - return; -} - -int qemu_cpu_self(void *env) -{ - return 1; -} - -static void resume_all_vcpus(void) -{ -} - -static void pause_all_vcpus(void) -{ -} - -void qemu_cpu_kick(void *env) -{ - return; -} - -void qemu_notify_event(void) -{ - CPUState *env = cpu_single_env; - - if (env) { - cpu_exit(env); - } -} - -#define qemu_mutex_lock_iothread() do { } while (0) -#define qemu_mutex_unlock_iothread() do { } while (0) - -void vm_stop(int reason) -{ - do_vm_stop(reason); -} - -#else /* CONFIG_IOTHREAD */ - -#include "qemu-thread.h" - -QemuMutex qemu_global_mutex; -static QemuMutex qemu_fair_mutex; - -static QemuThread io_thread; - -static QemuThread *tcg_cpu_thread; -static QemuCond *tcg_halt_cond; - -static int qemu_system_ready; -/* cpu creation */ -static QemuCond qemu_cpu_cond; -/* system init */ -static QemuCond qemu_system_cond; -static QemuCond qemu_pause_cond; - -static void block_io_signals(void); -static void unblock_io_signals(void); -static int tcg_has_work(void); - -static int qemu_init_main_loop(void) -{ - int ret; - - ret = qemu_event_init(); - if (ret) - return ret; - - qemu_cond_init(&qemu_pause_cond); - qemu_mutex_init(&qemu_fair_mutex); - qemu_mutex_init(&qemu_global_mutex); - qemu_mutex_lock(&qemu_global_mutex); - - unblock_io_signals(); - qemu_thread_self(&io_thread); - - return 0; -} - -static void qemu_wait_io_event(CPUState *env) -{ - while (!tcg_has_work()) - qemu_cond_timedwait(env->halt_cond, &qemu_global_mutex, 1000); - - qemu_mutex_unlock(&qemu_global_mutex); - - /* - * Users of qemu_global_mutex can be starved, having no chance - * to acquire it since this path will get to it first. - * So use another lock to provide fairness. - */ - qemu_mutex_lock(&qemu_fair_mutex); - qemu_mutex_unlock(&qemu_fair_mutex); - - qemu_mutex_lock(&qemu_global_mutex); - if (env->stop) { - env->stop = 0; - env->stopped = 1; - qemu_cond_signal(&qemu_pause_cond); - } -} - -static int qemu_cpu_exec(CPUState *env); - -static void *kvm_cpu_thread_fn(void *arg) -{ - CPUState *env = arg; - - block_io_signals(); - qemu_thread_self(env->thread); - - /* signal CPU creation */ - qemu_mutex_lock(&qemu_global_mutex); - env->created = 1; - qemu_cond_signal(&qemu_cpu_cond); - - /* and wait for machine initialization */ - while (!qemu_system_ready) - qemu_cond_timedwait(&qemu_system_cond, &qemu_global_mutex, 100); - - while (1) { - if (cpu_can_run(env)) - qemu_cpu_exec(env); - qemu_wait_io_event(env); - } - - return NULL; -} - -static void tcg_cpu_exec(void); - -static void *tcg_cpu_thread_fn(void *arg) -{ - CPUState *env = arg; - - block_io_signals(); - qemu_thread_self(env->thread); - - /* signal CPU creation */ - qemu_mutex_lock(&qemu_global_mutex); - for (env = first_cpu; env != NULL; env = env->next_cpu) - env->created = 1; - qemu_cond_signal(&qemu_cpu_cond); - - /* and wait for machine initialization */ - while (!qemu_system_ready) - qemu_cond_timedwait(&qemu_system_cond, &qemu_global_mutex, 100); - - while (1) { - tcg_cpu_exec(); - qemu_wait_io_event(cur_cpu); - } - - return NULL; -} - -void qemu_cpu_kick(void *_env) -{ - CPUState *env = _env; - qemu_cond_broadcast(env->halt_cond); - if (kvm_enabled()) - qemu_thread_signal(env->thread, SIGUSR1); -} - -int qemu_cpu_self(void *env) -{ - return (cpu_single_env != NULL); -} - -static void cpu_signal(int sig) -{ - if (cpu_single_env) - cpu_exit(cpu_single_env); -} - -static void block_io_signals(void) -{ - sigset_t set; - struct sigaction sigact; - - sigemptyset(&set); - sigaddset(&set, SIGUSR2); - sigaddset(&set, SIGIO); - sigaddset(&set, SIGALRM); - pthread_sigmask(SIG_BLOCK, &set, NULL); - - sigemptyset(&set); - sigaddset(&set, SIGUSR1); - pthread_sigmask(SIG_UNBLOCK, &set, NULL); - - memset(&sigact, 0, sizeof(sigact)); - sigact.sa_handler = cpu_signal; - sigaction(SIGUSR1, &sigact, NULL); -} - -static void unblock_io_signals(void) -{ - sigset_t set; - - sigemptyset(&set); - sigaddset(&set, SIGUSR2); - sigaddset(&set, SIGIO); - sigaddset(&set, SIGALRM); - pthread_sigmask(SIG_UNBLOCK, &set, NULL); - - sigemptyset(&set); - sigaddset(&set, SIGUSR1); - pthread_sigmask(SIG_BLOCK, &set, NULL); -} - -static void qemu_signal_lock(unsigned int msecs) -{ - qemu_mutex_lock(&qemu_fair_mutex); - - while (qemu_mutex_trylock(&qemu_global_mutex)) { - qemu_thread_signal(tcg_cpu_thread, SIGUSR1); - if (!qemu_mutex_timedlock(&qemu_global_mutex, msecs)) - break; - } - qemu_mutex_unlock(&qemu_fair_mutex); -} - -void qemu_mutex_lock_iothread(void) -{ - if (kvm_enabled()) { - qemu_mutex_lock(&qemu_fair_mutex); - qemu_mutex_lock(&qemu_global_mutex); - qemu_mutex_unlock(&qemu_fair_mutex); - } else - qemu_signal_lock(100); -} - -void qemu_mutex_unlock_iothread(void) -{ - qemu_mutex_unlock(&qemu_global_mutex); -} - -static int all_vcpus_paused(void) -{ - CPUState *penv = first_cpu; - - while (penv) { - if (!penv->stopped) - return 0; - penv = (CPUState *)penv->next_cpu; - } - - return 1; -} - -static void pause_all_vcpus(void) -{ - CPUState *penv = first_cpu; - - while (penv) { - penv->stop = 1; - qemu_thread_signal(penv->thread, SIGUSR1); - qemu_cpu_kick(penv); - penv = (CPUState *)penv->next_cpu; - } - - while (!all_vcpus_paused()) { - qemu_cond_timedwait(&qemu_pause_cond, &qemu_global_mutex, 100); - penv = first_cpu; - while (penv) { - qemu_thread_signal(penv->thread, SIGUSR1); - penv = (CPUState *)penv->next_cpu; - } - } -} - -static void resume_all_vcpus(void) -{ - CPUState *penv = first_cpu; - - while (penv) { - penv->stop = 0; - penv->stopped = 0; - qemu_thread_signal(penv->thread, SIGUSR1); - qemu_cpu_kick(penv); - penv = (CPUState *)penv->next_cpu; - } -} - -static void tcg_init_vcpu(void *_env) -{ - CPUState *env = _env; - /* share a single thread for all cpus with TCG */ - if (!tcg_cpu_thread) { - env->thread = qemu_mallocz(sizeof(QemuThread)); - env->halt_cond = qemu_mallocz(sizeof(QemuCond)); - qemu_cond_init(env->halt_cond); - qemu_thread_create(env->thread, tcg_cpu_thread_fn, env); - while (env->created == 0) - qemu_cond_timedwait(&qemu_cpu_cond, &qemu_global_mutex, 100); - tcg_cpu_thread = env->thread; - tcg_halt_cond = env->halt_cond; - } else { - env->thread = tcg_cpu_thread; - env->halt_cond = tcg_halt_cond; - } -} - -static void kvm_start_vcpu(CPUState *env) -{ - kvm_init_vcpu(env); - env->thread = qemu_mallocz(sizeof(QemuThread)); - env->halt_cond = qemu_mallocz(sizeof(QemuCond)); - qemu_cond_init(env->halt_cond); - qemu_thread_create(env->thread, kvm_cpu_thread_fn, env); - while (env->created == 0) - qemu_cond_timedwait(&qemu_cpu_cond, &qemu_global_mutex, 100); -} - -void qemu_init_vcpu(void *_env) -{ - CPUState *env = _env; - - if (kvm_enabled()) - kvm_start_vcpu(env); - else - tcg_init_vcpu(env); -} - -void qemu_notify_event(void) -{ - qemu_event_increment(); -} - -void vm_stop(int reason) -{ - QemuThread me; - qemu_thread_self(&me); - - if (!qemu_thread_equal(&me, &io_thread)) { - qemu_system_vmstop_request(reason); - /* - * FIXME: should not return to device code in case - * vm_stop() has been requested. - */ - if (cpu_single_env) { - cpu_exit(cpu_single_env); - cpu_single_env->stop = 1; - } - return; - } - do_vm_stop(reason); -} - -#endif - - -#ifdef _WIN32 -static void host_main_loop_wait(int *timeout) -{ - int ret, ret2, i; - PollingEntry *pe; - - - /* XXX: need to suppress polling by better using win32 events */ - ret = 0; - for(pe = first_polling_entry; pe != NULL; pe = pe->next) { - ret |= pe->func(pe->opaque); - } - if (ret == 0) { - int err; - WaitObjects *w = &wait_objects; - - ret = WaitForMultipleObjects(w->num, w->events, FALSE, *timeout); - if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) { - if (w->func[ret - WAIT_OBJECT_0]) - w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]); - - /* Check for additional signaled events */ - for(i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) { - - /* Check if event is signaled */ - ret2 = WaitForSingleObject(w->events[i], 0); - if(ret2 == WAIT_OBJECT_0) { - if (w->func[i]) - w->func[i](w->opaque[i]); - } else if (ret2 == WAIT_TIMEOUT) { - } else { - err = GetLastError(); - fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err); - } - } - } else if (ret == WAIT_TIMEOUT) { - } else { - err = GetLastError(); - fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err); - } - } - - *timeout = 0; -} -#else -static void host_main_loop_wait(int *timeout) -{ -} -#endif - void main_loop_wait(int timeout) { - IOHandlerRecord *ioh; fd_set rfds, wfds, xfds; int ret, nfds; struct timeval tv; qemu_bh_update_timeout(&timeout); - host_main_loop_wait(&timeout); + os_host_main_loop_wait(&timeout); tv.tv_sec = timeout / 1000; @@ -2653,97 +2089,6 @@ void main_loop_wait(int timeout) } -static int qemu_cpu_exec(CPUState *env) -{ - int ret; -#ifdef CONFIG_PROFILER - int64_t ti; -#endif - -#ifdef CONFIG_PROFILER - ti = profile_getclock(); -#endif - if (use_icount) { - int64_t count; - int decr; - qemu_icount -= (env->icount_decr.u16.low + env->icount_extra); - env->icount_decr.u16.low = 0; - env->icount_extra = 0; - count = qemu_next_deadline(); - count = (count + (1 << icount_time_shift) - 1) - >> icount_time_shift; - qemu_icount += count; - decr = (count > 0xffff) ? 0xffff : count; - count -= decr; - env->icount_decr.u16.low = decr; - env->icount_extra = count; - } - ret = cpu_exec(env); -#ifdef CONFIG_PROFILER - qemu_time += profile_getclock() - ti; -#endif - if (use_icount) { - /* Fold pending instructions back into the - instruction counter, and clear the interrupt flag. */ - qemu_icount -= (env->icount_decr.u16.low - + env->icount_extra); - env->icount_decr.u32 = 0; - env->icount_extra = 0; - } - return ret; -} - -static void tcg_cpu_exec(void) -{ - int ret = 0; - - if (next_cpu == NULL) - next_cpu = first_cpu; - for (; next_cpu != NULL; next_cpu = next_cpu->next_cpu) { - CPUState *env = cur_cpu = next_cpu; - - if (timer_alarm_pending) { - timer_alarm_pending = 0; - break; - } - if (cpu_can_run(env)) - ret = qemu_cpu_exec(env); - else if (env->stop) - break; - - if (ret == EXCP_DEBUG) { - gdb_set_stop_cpu(env); - debug_requested = 1; - break; - } - } -} - -#if 0 -static int cpu_has_work(CPUState *env) -{ - if (env->stop) - return 1; - if (env->stopped) - return 0; - if (!env->halted) - return 1; - if (qemu_cpu_has_work(env)) - return 1; - return 0; -} - -static int tcg_has_work(void) -{ - CPUState *env; - - for (env = first_cpu; env != NULL; env = env->next_cpu) - if (cpu_has_work(env)) - return 1; - return 0; -} -#endif - static int vm_can_run(void) { if (powerdown_requested) -- cgit v1.1