diff options
Diffstat (limited to 'vl.c')
-rw-r--r-- | vl.c | 749 |
1 files changed, 3 insertions, 746 deletions
@@ -160,6 +160,7 @@ int main(int argc, char **argv) #include "slirp/libslirp.h" #include "qemu-queue.h" +#include "cpus.h" //#define DEBUG_NET //#define DEBUG_SLIRP @@ -249,8 +250,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]; @@ -314,28 +313,6 @@ static int default_driver_check(QemuOpts *opts, void *opaque) target_phys_addr_t isa_mem_base = 0; PicState2 *isa_pic; -/***********************************************************/ -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 set_proc_name(const char *s) { #if defined(__linux__) && defined(PR_SET_NAME) @@ -1962,33 +1939,6 @@ static void nographic_update(void *opaque) qemu_mod_timer(nographic_timer, interval + qemu_get_clock(rt_clock)); } -void cpu_synchronize_all_states(void) -{ - CPUState *cpu; - - for (cpu = first_cpu; cpu; cpu = cpu->next_cpu) { - cpu_synchronize_state(cpu); - } -} - -void cpu_synchronize_all_post_reset(void) -{ - CPUState *cpu; - - for (cpu = first_cpu; cpu; cpu = cpu->next_cpu) { - cpu_synchronize_post_reset(cpu); - } -} - -void cpu_synchronize_all_post_init(void) -{ - CPUState *cpu; - - for (cpu = first_cpu; cpu; cpu = cpu->next_cpu) { - cpu_synchronize_post_init(cpu); - } -} - struct vm_change_state_entry { VMChangeStateHandler *cb; void *opaque; @@ -2016,7 +1966,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; @@ -2025,9 +1975,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) { @@ -2051,7 +1998,7 @@ static QTAILQ_HEAD(reset_handlers, QEMUResetEntry) reset_handlers = static int reset_requested; static int shutdown_requested; static int powerdown_requested; -static int debug_requested; +int debug_requested; static int vmstop_requested; int qemu_shutdown_requested(void) @@ -2089,17 +2036,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); - monitor_protocol_event(QEVENT_STOP, NULL); - } -} - void qemu_register_reset(QEMUResetHandler *func, void *opaque) { QEMUResetEntry *re = qemu_mallocz(sizeof(QEMUResetEntry)); @@ -2156,589 +2092,6 @@ void qemu_system_powerdown_request(void) qemu_notify_event(); } -static int cpu_can_run(CPUState *env) -{ - if (env->stop) - return 0; - if (env->stopped) - return 0; - if (!vm_running) - 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; -} - -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; -} - -#ifndef _WIN32 -static int io_thread_fd = -1; - -static void qemu_event_increment(void) -{ - /* Write 8 bytes to be compatible with eventfd. */ - static uint64_t val = 1; - ssize_t ret; - - if (io_thread_fd == -1) - return; - - do { - ret = write(io_thread_fd, &val, sizeof(val)); - } while (ret < 0 && errno == EINTR); - - /* EAGAIN is fine, a read must be pending. */ - if (ret < 0 && errno != EAGAIN) { - fprintf(stderr, "qemu_event_increment: write() filed: %s\n", - strerror(errno)); - exit (1); - } -} - -static void qemu_event_read(void *opaque) -{ - int fd = (unsigned long)opaque; - ssize_t len; - char buffer[512]; - - /* Drain the notify pipe. For eventfd, only 8 bytes will be read. */ - do { - len = read(fd, buffer, sizeof(buffer)); - } while ((len == -1 && errno == EINTR) || len == sizeof(buffer)); -} - -static int qemu_event_init(void) -{ - int err; - int fds[2]; - - err = qemu_eventfd(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) { - fprintf(stderr, "Failed CreateEvent: %ld\n", GetLastError()); - return -1; - } - qemu_add_wait_object(qemu_event_handle, dummy_event_handler, NULL); - return 0; -} - -static void qemu_event_increment(void) -{ - if (!SetEvent(qemu_event_handle)) { - fprintf(stderr, "qemu_event_increment: SetEvent failed: %ld\n", - GetLastError()); - exit (1); - } -} -#endif - -#ifndef CONFIG_IOTHREAD -static int qemu_init_main_loop(void) -{ - return qemu_event_init(); -} - -void qemu_init_vcpu(void *_env) -{ - CPUState *env = _env; - - env->nr_cores = smp_cores; - env->nr_threads = smp_threads; - 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; - - qemu_event_increment (); - if (env) { - cpu_exit(env); - } - if (next_cpu && env != next_cpu) { - cpu_exit(next_cpu); - } -} - -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 tcg_block_io_signals(void); -static void kvm_block_io_signals(CPUState *env); -static void unblock_io_signals(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_common(CPUState *env) -{ - if (env->stop) { - env->stop = 0; - env->stopped = 1; - qemu_cond_signal(&qemu_pause_cond); - } -} - -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); - qemu_wait_io_event_common(env); -} - -static void qemu_kvm_eat_signal(CPUState *env, int timeout) -{ - struct timespec ts; - int r, e; - siginfo_t siginfo; - sigset_t waitset; - - ts.tv_sec = timeout / 1000; - ts.tv_nsec = (timeout % 1000) * 1000000; - - sigemptyset(&waitset); - sigaddset(&waitset, SIG_IPI); - - qemu_mutex_unlock(&qemu_global_mutex); - r = sigtimedwait(&waitset, &siginfo, &ts); - e = errno; - qemu_mutex_lock(&qemu_global_mutex); - - if (r == -1 && !(e == EAGAIN || e == EINTR)) { - fprintf(stderr, "sigtimedwait: %s\n", strerror(e)); - exit(1); - } -} - -static void qemu_kvm_wait_io_event(CPUState *env) -{ - while (!cpu_has_work(env)) - qemu_cond_timedwait(env->halt_cond, &qemu_global_mutex, 1000); - - qemu_kvm_eat_signal(env, 0); - qemu_wait_io_event_common(env); -} - -static int qemu_cpu_exec(CPUState *env); - -static void *kvm_cpu_thread_fn(void *arg) -{ - CPUState *env = arg; - - qemu_thread_self(env->thread); - if (kvm_enabled()) - kvm_init_vcpu(env); - - kvm_block_io_signals(env); - - /* 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_kvm_wait_io_event(env); - } - - return NULL; -} - -static bool tcg_cpu_exec(void); - -static void *tcg_cpu_thread_fn(void *arg) -{ - CPUState *env = arg; - - tcg_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, SIG_IPI); -} - -int qemu_cpu_self(void *_env) -{ - CPUState *env = _env; - QemuThread this; - - qemu_thread_self(&this); - - return qemu_thread_equal(&this, env->thread); -} - -static void cpu_signal(int sig) -{ - if (cpu_single_env) - cpu_exit(cpu_single_env); -} - -static void tcg_block_io_signals(void) -{ - sigset_t set; - struct sigaction sigact; - - sigemptyset(&set); - sigaddset(&set, SIGUSR2); - sigaddset(&set, SIGIO); - sigaddset(&set, SIGALRM); - sigaddset(&set, SIGCHLD); - pthread_sigmask(SIG_BLOCK, &set, NULL); - - sigemptyset(&set); - sigaddset(&set, SIG_IPI); - pthread_sigmask(SIG_UNBLOCK, &set, NULL); - - memset(&sigact, 0, sizeof(sigact)); - sigact.sa_handler = cpu_signal; - sigaction(SIG_IPI, &sigact, NULL); -} - -static void dummy_signal(int sig) -{ -} - -static void kvm_block_io_signals(CPUState *env) -{ - int r; - sigset_t set; - struct sigaction sigact; - - sigemptyset(&set); - sigaddset(&set, SIGUSR2); - sigaddset(&set, SIGIO); - sigaddset(&set, SIGALRM); - sigaddset(&set, SIGCHLD); - sigaddset(&set, SIG_IPI); - pthread_sigmask(SIG_BLOCK, &set, NULL); - - pthread_sigmask(SIG_BLOCK, NULL, &set); - sigdelset(&set, SIG_IPI); - - memset(&sigact, 0, sizeof(sigact)); - sigact.sa_handler = dummy_signal; - sigaction(SIG_IPI, &sigact, NULL); - - r = kvm_set_signal_mask(env, &set); - if (r) { - fprintf(stderr, "kvm_set_signal_mask: %s\n", strerror(r)); - exit(1); - } -} - -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, SIG_IPI); - 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, SIG_IPI); - 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, SIG_IPI); - 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, SIG_IPI); - 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, SIG_IPI); - 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) -{ - 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; - - env->nr_cores = smp_cores; - env->nr_threads = smp_threads; - if (kvm_enabled()) - kvm_start_vcpu(env); - else - tcg_init_vcpu(env); -} - -void qemu_notify_event(void) -{ - qemu_event_increment(); -} - -static void qemu_system_vmstop_request(int reason) -{ - vmstop_requested = reason; - qemu_notify_event(); -} - -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) { @@ -2865,102 +2218,6 @@ void main_loop_wait(int nonblocking) } -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_icount_round (qemu_next_deadline()); - 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 bool 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; - - qemu_clock_enable(vm_clock, - (cur_cpu->singlestep_enabled & SSTEP_NOTIMER) == 0); - - if (qemu_alarm_pending()) - 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 = EXCP_DEBUG; - break; - } - } - return tcg_has_work(); -} - -static void set_numa_modes(void) -{ - CPUState *env; - int i; - - for (env = first_cpu; env != NULL; env = env->next_cpu) { - for (i = 0; i < nb_numa_nodes; i++) { - if (node_cpumask[i] & (1 << env->cpu_index)) { - env->numa_node = i; - } - } - } -} - -static void set_cpu_log(const char *optarg) -{ - int mask; - const CPULogItem *item; - - mask = cpu_str_to_log_mask(optarg); - if (!mask) { - printf("Log items (comma separated):\n"); - for (item = cpu_log_items; item->mask != 0; item++) { - printf("%-10s %s\n", item->name, item->help); - } - exit(1); - } - cpu_set_log(mask); -} - static int vm_can_run(void) { if (powerdown_requested) |