diff options
Diffstat (limited to 'vl.c')
-rw-r--r-- | vl.c | 230 |
1 files changed, 66 insertions, 164 deletions
@@ -148,6 +148,7 @@ int main(int argc, char **argv) #include "qemu-objects.h" #include "qemu-options.h" #include "qmp-commands.h" +#include "main-loop.h" #ifdef CONFIG_VIRTFS #include "fsdev/qemu-fsdev.h" #endif @@ -337,16 +338,20 @@ static const RunStateTransition runstate_transitions_def[] = { { RUN_STATE_INMIGRATE, RUN_STATE_PRELAUNCH }, { RUN_STATE_INTERNAL_ERROR, RUN_STATE_PAUSED }, + { RUN_STATE_INTERNAL_ERROR, RUN_STATE_FINISH_MIGRATE }, { RUN_STATE_IO_ERROR, RUN_STATE_RUNNING }, + { RUN_STATE_IO_ERROR, RUN_STATE_FINISH_MIGRATE }, { RUN_STATE_PAUSED, RUN_STATE_RUNNING }, + { RUN_STATE_PAUSED, RUN_STATE_FINISH_MIGRATE }, { RUN_STATE_POSTMIGRATE, RUN_STATE_RUNNING }, + { RUN_STATE_POSTMIGRATE, RUN_STATE_FINISH_MIGRATE }, { RUN_STATE_PRELAUNCH, RUN_STATE_RUNNING }, + { RUN_STATE_PRELAUNCH, RUN_STATE_FINISH_MIGRATE }, { RUN_STATE_PRELAUNCH, RUN_STATE_INMIGRATE }, - { RUN_STATE_PRELAUNCH, RUN_STATE_POSTMIGRATE }, { RUN_STATE_FINISH_MIGRATE, RUN_STATE_RUNNING }, { RUN_STATE_FINISH_MIGRATE, RUN_STATE_POSTMIGRATE }, @@ -366,8 +371,10 @@ static const RunStateTransition runstate_transitions_def[] = { { RUN_STATE_SAVE_VM, RUN_STATE_RUNNING }, { RUN_STATE_SHUTDOWN, RUN_STATE_PAUSED }, + { RUN_STATE_SHUTDOWN, RUN_STATE_FINISH_MIGRATE }, { RUN_STATE_WATCHDOG, RUN_STATE_RUNNING }, + { RUN_STATE_WATCHDOG, RUN_STATE_FINISH_MIGRATE }, { RUN_STATE_MAX, RUN_STATE_MAX }, }; @@ -393,9 +400,12 @@ void runstate_init(void) /* This function will abort() on invalid state transitions */ void runstate_set(RunState new_state) { - if (new_state >= RUN_STATE_MAX || - !runstate_valid_transitions[current_run_state][new_state]) { - fprintf(stderr, "invalid runstate transition\n"); + assert(new_state < RUN_STATE_MAX); + + if (!runstate_valid_transitions[current_run_state][new_state]) { + fprintf(stderr, "ERROR: invalid runstate transition: '%s' -> '%s'\n", + RunState_lookup[current_run_state], + RunState_lookup[new_state]); abort(); } @@ -1416,142 +1426,51 @@ void qemu_system_vmstop_request(RunState state) qemu_notify_event(); } -static GPollFD poll_fds[1024 * 2]; /* this is probably overkill */ -static int n_poll_fds; -static int max_priority; +qemu_irq qemu_system_powerdown; -static void glib_select_fill(int *max_fd, fd_set *rfds, fd_set *wfds, - fd_set *xfds, struct timeval *tv) +static bool main_loop_should_exit(void) { - GMainContext *context = g_main_context_default(); - int i; - int timeout = 0, cur_timeout; - - g_main_context_prepare(context, &max_priority); - - n_poll_fds = g_main_context_query(context, max_priority, &timeout, - poll_fds, ARRAY_SIZE(poll_fds)); - g_assert(n_poll_fds <= ARRAY_SIZE(poll_fds)); - - for (i = 0; i < n_poll_fds; i++) { - GPollFD *p = &poll_fds[i]; - - if ((p->events & G_IO_IN)) { - FD_SET(p->fd, rfds); - *max_fd = MAX(*max_fd, p->fd); - } - if ((p->events & G_IO_OUT)) { - FD_SET(p->fd, wfds); - *max_fd = MAX(*max_fd, p->fd); - } - if ((p->events & G_IO_ERR)) { - FD_SET(p->fd, xfds); - *max_fd = MAX(*max_fd, p->fd); + RunState r; + if (qemu_debug_requested()) { + vm_stop(RUN_STATE_DEBUG); + } + if (qemu_shutdown_requested()) { + qemu_kill_report(); + monitor_protocol_event(QEVENT_SHUTDOWN, NULL); + if (no_shutdown) { + vm_stop(RUN_STATE_SHUTDOWN); + } else { + return true; } } - - cur_timeout = (tv->tv_sec * 1000) + ((tv->tv_usec + 500) / 1000); - if (timeout >= 0 && timeout < cur_timeout) { - tv->tv_sec = timeout / 1000; - tv->tv_usec = (timeout % 1000) * 1000; - } -} - -static void glib_select_poll(fd_set *rfds, fd_set *wfds, fd_set *xfds, - bool err) -{ - GMainContext *context = g_main_context_default(); - - if (!err) { - int i; - - for (i = 0; i < n_poll_fds; i++) { - GPollFD *p = &poll_fds[i]; - - if ((p->events & G_IO_IN) && FD_ISSET(p->fd, rfds)) { - p->revents |= G_IO_IN; - } - if ((p->events & G_IO_OUT) && FD_ISSET(p->fd, wfds)) { - p->revents |= G_IO_OUT; - } - if ((p->events & G_IO_ERR) && FD_ISSET(p->fd, xfds)) { - p->revents |= G_IO_ERR; - } + if (qemu_reset_requested()) { + pause_all_vcpus(); + cpu_synchronize_all_states(); + qemu_system_reset(VMRESET_REPORT); + resume_all_vcpus(); + if (runstate_check(RUN_STATE_INTERNAL_ERROR) || + runstate_check(RUN_STATE_SHUTDOWN)) { + runstate_set(RUN_STATE_PAUSED); } } - - if (g_main_context_check(context, max_priority, poll_fds, n_poll_fds)) { - g_main_context_dispatch(context); + if (qemu_powerdown_requested()) { + monitor_protocol_event(QEVENT_POWERDOWN, NULL); + qemu_irq_raise(qemu_system_powerdown); } -} - -int main_loop_wait(int nonblocking) -{ - fd_set rfds, wfds, xfds; - int ret, nfds; - struct timeval tv; - int timeout; - - if (nonblocking) - timeout = 0; - else { - timeout = qemu_calculate_timeout(); - qemu_bh_update_timeout(&timeout); - } - - os_host_main_loop_wait(&timeout); - - tv.tv_sec = timeout / 1000; - tv.tv_usec = (timeout % 1000) * 1000; - - /* poll any events */ - /* XXX: separate device handlers from system ones */ - nfds = -1; - FD_ZERO(&rfds); - FD_ZERO(&wfds); - FD_ZERO(&xfds); - - qemu_iohandler_fill(&nfds, &rfds, &wfds, &xfds); - slirp_select_fill(&nfds, &rfds, &wfds, &xfds); - glib_select_fill(&nfds, &rfds, &wfds, &xfds, &tv); - - if (timeout > 0) { - qemu_mutex_unlock_iothread(); + if (qemu_vmstop_requested(&r)) { + vm_stop(r); } - - ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv); - - if (timeout > 0) { - qemu_mutex_lock_iothread(); - } - - qemu_iohandler_poll(&rfds, &wfds, &xfds, ret); - slirp_select_poll(&rfds, &wfds, &xfds, (ret < 0)); - glib_select_poll(&rfds, &wfds, &xfds, (ret < 0)); - - qemu_run_all_timers(); - - /* Check bottom-halves last in case any of the earlier events triggered - them. */ - qemu_bh_poll(); - - return ret; + return false; } -qemu_irq qemu_system_powerdown; - static void main_loop(void) { bool nonblocking; - int last_io __attribute__ ((unused)) = 0; + int last_io = 0; #ifdef CONFIG_PROFILER int64_t ti; #endif - RunState r; - - qemu_main_loop_start(); - - for (;;) { + do { nonblocking = !kvm_enabled() && last_io > 0; #ifdef CONFIG_PROFILER ti = profile_getclock(); @@ -1560,38 +1479,7 @@ static void main_loop(void) #ifdef CONFIG_PROFILER dev_time += profile_getclock() - ti; #endif - - if (qemu_debug_requested()) { - vm_stop(RUN_STATE_DEBUG); - } - if (qemu_shutdown_requested()) { - qemu_kill_report(); - monitor_protocol_event(QEVENT_SHUTDOWN, NULL); - if (no_shutdown) { - vm_stop(RUN_STATE_SHUTDOWN); - } else - break; - } - if (qemu_reset_requested()) { - pause_all_vcpus(); - cpu_synchronize_all_states(); - qemu_system_reset(VMRESET_REPORT); - resume_all_vcpus(); - if (runstate_check(RUN_STATE_INTERNAL_ERROR) || - runstate_check(RUN_STATE_SHUTDOWN)) { - runstate_set(RUN_STATE_PAUSED); - } - } - if (qemu_powerdown_requested()) { - monitor_protocol_event(QEVENT_POWERDOWN, NULL); - qemu_irq_raise(qemu_system_powerdown); - } - if (qemu_vmstop_requested(&r)) { - vm_stop(r); - } - } - bdrv_close_all(); - pause_all_vcpus(); + } while (!main_loop_should_exit()); } static void version(void) @@ -2302,6 +2190,7 @@ int main(int argc, char **argv, char **envp) runstate_init(); init_clocks(); + rtc_clock = host_clock; qemu_cache_utils_init(envp); @@ -2774,6 +2663,7 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_virtfs: { QemuOpts *fsdev; QemuOpts *device; + const char *writeout; olist = qemu_find_opts("virtfs"); if (!olist) { @@ -2786,16 +2676,14 @@ int main(int argc, char **argv, char **envp) exit(1); } - if (qemu_opt_get(opts, "fstype") == NULL || + if (qemu_opt_get(opts, "fsdriver") == NULL || qemu_opt_get(opts, "mount_tag") == NULL || - qemu_opt_get(opts, "path") == NULL || - qemu_opt_get(opts, "security_model") == NULL) { - fprintf(stderr, "Usage: -virtfs fstype,path=/share_path/," - "security_model=[mapped|passthrough|none]," + qemu_opt_get(opts, "path") == NULL) { + fprintf(stderr, "Usage: -virtfs fsdriver,path=/share_path/," + "[security_model={mapped|passthrough|none}]," "mount_tag=tag.\n"); exit(1); } - fsdev = qemu_opts_create(qemu_find_opts("fsdev"), qemu_opt_get(opts, "mount_tag"), 1); if (!fsdev) { @@ -2803,7 +2691,18 @@ int main(int argc, char **argv, char **envp) qemu_opt_get(opts, "mount_tag")); exit(1); } - qemu_opt_set(fsdev, "fstype", qemu_opt_get(opts, "fstype")); + + writeout = qemu_opt_get(opts, "writeout"); + if (writeout) { +#ifdef CONFIG_SYNC_FILE_RANGE + qemu_opt_set(fsdev, "writeout", writeout); +#else + fprintf(stderr, "writeout=immediate not supported on " + "this platform\n"); + exit(1); +#endif + } + qemu_opt_set(fsdev, "fsdriver", qemu_opt_get(opts, "fsdriver")); qemu_opt_set(fsdev, "path", qemu_opt_get(opts, "path")); qemu_opt_set(fsdev, "security_model", qemu_opt_get(opts, "security_model")); @@ -3279,6 +3178,7 @@ int main(int argc, char **argv, char **envp) configure_accelerator(); + qemu_init_cpu_loop(); if (qemu_init_main_loop()) { fprintf(stderr, "qemu_init_main_loop failed\n"); exit(1); @@ -3545,8 +3445,10 @@ int main(int argc, char **argv, char **envp) os_setup_post(); + resume_all_vcpus(); main_loop(); - quit_timers(); + bdrv_close_all(); + pause_all_vcpus(); net_cleanup(); res_free(); |