#include <dirent.h>
#include <netdb.h>
#include <sys/select.h>
-#ifdef CONFIG_SIMPLE_TRACE
-#include "trace.h"
-#endif
#ifdef CONFIG_BSD
#include <sys/stat.h>
#include "slirp/libslirp.h"
#include "trace.h"
+#include "simpletrace.h"
#include "qemu-queue.h"
#include "cpus.h"
#include "arch_init.h"
int max_cpus = 0;
int smp_cores = 1;
int smp_threads = 1;
+#ifdef CONFIG_VNC
const char *vnc_display;
+#endif
int acpi_enabled = 1;
int no_hpet = 0;
int fd_bootchk = 1;
/***********************************************************/
/* QEMU Block devices */
-#define HD_ALIAS "index=%d,media=disk"
-#define CDROM_ALIAS "index=2,media=cdrom"
-#define FD_ALIAS "index=%d,if=floppy"
-#define PFLASH_ALIAS "if=pflash"
-#define MTD_ALIAS "if=mtd"
-#define SD_ALIAS "index=0,if=sd"
+#define HD_OPTS "media=disk"
+#define CDROM_OPTS "media=cdrom"
+#define FD_OPTS ""
+#define PFLASH_OPTS ""
+#define MTD_OPTS ""
+#define SD_OPTS ""
static int drive_init_func(QemuOpts *opts, void *opaque)
{
int *use_scsi = opaque;
- int fatal_error = 0;
- if (drive_init(opts, *use_scsi, &fatal_error) == NULL) {
- if (fatal_error)
- return 1;
- }
- return 0;
+ return drive_init(opts, *use_scsi) == NULL;
}
static int drive_enable_snapshot(QemuOpts *opts, void *opaque)
return 0;
}
+static void default_drive(int enable, int snapshot, int use_scsi,
+ BlockInterfaceType type, int index,
+ const char *optstr)
+{
+ QemuOpts *opts;
+
+ if (type == IF_DEFAULT) {
+ type = use_scsi ? IF_SCSI : IF_IDE;
+ }
+
+ if (!enable || drive_get_by_index(type, index)) {
+ return;
+ }
+
+ opts = drive_add(type, index, NULL, optstr);
+ if (snapshot) {
+ drive_enable_snapshot(opts, NULL);
+ }
+ if (!drive_init(opts, use_scsi)) {
+ exit(1);
+ }
+}
+
void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque)
{
boot_set_handler = func;
node = qemu_mallocz(sizeof(FWBootEntry));
node->bootindex = bootindex;
- node->suffix = strdup(suffix);
+ node->suffix = suffix ? qemu_strdup(suffix) : NULL;
node->dev = dev;
QTAILQ_FOREACH(i, &fw_boot_order, link) {
} else if (devpath) {
bootpath = devpath;
} else {
- bootpath = strdup(i->suffix);
+ bootpath = qemu_strdup(i->suffix);
assert(bootpath);
}
if (get_param_value(option, 128, "mem", optarg) == 0) {
node_mem[nodenr] = 0;
} else {
- ssize_t sval;
+ int64_t sval;
sval = strtosz(option, NULL);
if (sval < 0) {
fprintf(stderr, "qemu: invalid numa mem size: %s\n", optarg);
interval = dcl->gui_timer_interval;
dcl = dcl->next;
}
- qemu_mod_timer(ds->gui_timer, interval + qemu_get_clock(rt_clock));
+ qemu_mod_timer(ds->gui_timer, interval + qemu_get_clock_ms(rt_clock));
}
static void nographic_update(void *opaque)
uint64_t interval = GUI_REFRESH_INTERVAL;
qemu_flush_coalesced_mmio_buffer();
- qemu_mod_timer(nographic_timer, interval + qemu_get_clock(rt_clock));
+ qemu_mod_timer(nographic_timer, interval + qemu_get_clock_ms(rt_clock));
}
struct vm_change_state_entry {
static QTAILQ_HEAD(reset_handlers, QEMUResetEntry) reset_handlers =
QTAILQ_HEAD_INITIALIZER(reset_handlers);
static int reset_requested;
-static int shutdown_requested;
+static int shutdown_requested, shutdown_signal = -1;
+static pid_t shutdown_pid;
static int powerdown_requested;
-int debug_requested;
-int vmstop_requested;
+static int debug_requested;
+static int vmstop_requested;
int qemu_shutdown_requested(void)
{
return r;
}
+void qemu_kill_report(void)
+{
+ if (shutdown_signal != -1) {
+ fprintf(stderr, "Got signal %d from pid %d\n",
+ shutdown_signal, shutdown_pid);
+ shutdown_signal = -1;
+ }
+}
+
int qemu_reset_requested(void)
{
int r = reset_requested;
} else {
reset_requested = 1;
}
+ cpu_stop_current();
qemu_notify_event();
}
+void qemu_system_killed(int signal, pid_t pid)
+{
+ shutdown_signal = signal;
+ shutdown_pid = pid;
+ qemu_system_shutdown_request();
+}
+
void qemu_system_shutdown_request(void)
{
shutdown_requested = 1;
qemu_notify_event();
}
+void qemu_system_debug_request(void)
+{
+ debug_requested = 1;
+ qemu_notify_event();
+}
+
+void qemu_system_vmstop_request(int reason)
+{
+ vmstop_requested = reason;
+ qemu_notify_event();
+}
+
void main_loop_wait(int nonblocking)
{
IOHandlerRecord *ioh;
}
-static int vm_can_run(void)
+#ifndef CONFIG_IOTHREAD
+static int vm_request_pending(void)
{
- if (powerdown_requested)
- return 0;
- if (reset_requested)
- return 0;
- if (shutdown_requested)
- return 0;
- if (debug_requested)
- return 0;
- return 1;
+ return powerdown_requested ||
+ reset_requested ||
+ shutdown_requested ||
+ debug_requested ||
+ vmstop_requested;
}
+#endif
qemu_irq qemu_system_powerdown;
static void main_loop(void)
{
+ bool nonblocking = false;
+#ifdef CONFIG_PROFILER
+ int64_t ti;
+#endif
int r;
qemu_main_loop_start();
for (;;) {
- do {
- bool nonblocking = false;
-#ifdef CONFIG_PROFILER
- int64_t ti;
-#endif
#ifndef CONFIG_IOTHREAD
- nonblocking = cpu_exec_all();
+ nonblocking = cpu_exec_all();
+ if (vm_request_pending()) {
+ nonblocking = true;
+ }
#endif
#ifdef CONFIG_PROFILER
- ti = profile_getclock();
+ ti = profile_getclock();
#endif
- main_loop_wait(nonblocking);
+ main_loop_wait(nonblocking);
#ifdef CONFIG_PROFILER
- dev_time += profile_getclock() - ti;
+ dev_time += profile_getclock() - ti;
#endif
- } while (vm_can_run());
- if ((r = qemu_debug_requested())) {
- vm_stop(r);
+ if (qemu_debug_requested()) {
+ vm_stop(VMSTOP_DEBUG);
}
if (qemu_shutdown_requested()) {
+ qemu_kill_report();
monitor_protocol_event(QEVENT_SHUTDOWN, NULL);
if (no_shutdown) {
- vm_stop(0);
+ vm_stop(VMSTOP_SHUTDOWN);
no_shutdown = 0;
} else
break;
}
if (qemu_reset_requested()) {
pause_all_vcpus();
+ cpu_synchronize_all_states();
qemu_system_reset();
resume_all_vcpus();
}
}
}
+static DisplayType select_display(const char *p)
+{
+ const char *opts;
+ DisplayType display = DT_DEFAULT;
+
+ if (strstart(p, "sdl", &opts)) {
+#ifdef CONFIG_SDL
+ display = DT_SDL;
+ while (*opts) {
+ const char *nextopt;
+
+ if (strstart(opts, ",frame=", &nextopt)) {
+ opts = nextopt;
+ if (strstart(opts, "on", &nextopt)) {
+ no_frame = 0;
+ } else if (strstart(opts, "off", &nextopt)) {
+ no_frame = 1;
+ } else {
+ goto invalid_sdl_args;
+ }
+ } else if (strstart(opts, ",alt_grab=", &nextopt)) {
+ opts = nextopt;
+ if (strstart(opts, "on", &nextopt)) {
+ alt_grab = 1;
+ } else if (strstart(opts, "off", &nextopt)) {
+ alt_grab = 0;
+ } else {
+ goto invalid_sdl_args;
+ }
+ } else if (strstart(opts, ",ctrl_grab=", &nextopt)) {
+ opts = nextopt;
+ if (strstart(opts, "on", &nextopt)) {
+ ctrl_grab = 1;
+ } else if (strstart(opts, "off", &nextopt)) {
+ ctrl_grab = 0;
+ } else {
+ goto invalid_sdl_args;
+ }
+ } else if (strstart(opts, ",window_close=", &nextopt)) {
+ opts = nextopt;
+ if (strstart(opts, "on", &nextopt)) {
+ no_quit = 0;
+ } else if (strstart(opts, "off", &nextopt)) {
+ no_quit = 1;
+ } else {
+ goto invalid_sdl_args;
+ }
+ } else {
+ invalid_sdl_args:
+ fprintf(stderr, "Invalid SDL option string: %s\n", p);
+ exit(1);
+ }
+ opts = nextopt;
+ }
+#else
+ fprintf(stderr, "SDL support is disabled\n");
+ exit(1);
+#endif
+ } else if (strstart(p, "vnc", &opts)) {
+#ifdef CONFIG_VNC
+ display_remote++;
+
+ if (*opts) {
+ const char *nextopt;
+
+ if (strstart(opts, "=", &nextopt)) {
+ vnc_display = nextopt;
+ }
+ }
+ if (!vnc_display) {
+ fprintf(stderr, "VNC requires a display argument vnc=<display>\n");
+ exit(1);
+ }
+#else
+ fprintf(stderr, "VNC support is disabled\n");
+ exit(1);
+#endif
+ } else if (strstart(p, "curses", &opts)) {
+#ifdef CONFIG_CURSES
+ display = DT_CURSES;
+#else
+ fprintf(stderr, "Curses support is disabled\n");
+ exit(1);
+#endif
+ } else if (strstart(p, "none", &opts)) {
+ display = DT_NONE;
+ } else {
+ fprintf(stderr, "Unknown display type: %s\n", p);
+ exit(1);
+ }
+
+ return display;
+}
+
static int balloon_parse(const char *arg)
{
QemuOpts *opts;
int tb_size;
const char *pid_file = NULL;
const char *incoming = NULL;
+#ifdef CONFIG_VNC
int show_vnc_port = 0;
+#endif
int defconfig = 1;
-
-#ifdef CONFIG_SIMPLE_TRACE
const char *trace_file = NULL;
-#endif
+
atexit(qemu_run_exit_notifiers);
error_set_progname(argv[0]);
if (optind >= argc)
break;
if (argv[optind][0] != '-') {
- hda_opts = drive_add(argv[optind++], HD_ALIAS, 0);
+ hda_opts = drive_add(IF_DEFAULT, 0, argv[optind++], HD_OPTS);
} else {
const QEMUOption *popt;
initrd_filename = optarg;
break;
case QEMU_OPTION_hda:
- if (cyls == 0)
- hda_opts = drive_add(optarg, HD_ALIAS, 0);
- else
- hda_opts = drive_add(optarg, HD_ALIAS
- ",cyls=%d,heads=%d,secs=%d%s",
- 0, cyls, heads, secs,
- translation == BIOS_ATA_TRANSLATION_LBA ?
+ {
+ char buf[256];
+ if (cyls == 0)
+ snprintf(buf, sizeof(buf), "%s", HD_OPTS);
+ else
+ snprintf(buf, sizeof(buf),
+ "%s,cyls=%d,heads=%d,secs=%d%s",
+ HD_OPTS , cyls, heads, secs,
+ translation == BIOS_ATA_TRANSLATION_LBA ?
",trans=lba" :
- translation == BIOS_ATA_TRANSLATION_NONE ?
+ translation == BIOS_ATA_TRANSLATION_NONE ?
",trans=none" : "");
- break;
+ drive_add(IF_DEFAULT, 0, optarg, buf);
+ break;
+ }
case QEMU_OPTION_hdb:
case QEMU_OPTION_hdc:
case QEMU_OPTION_hdd:
- drive_add(optarg, HD_ALIAS, popt->index - QEMU_OPTION_hda);
+ drive_add(IF_DEFAULT, popt->index - QEMU_OPTION_hda, optarg,
+ HD_OPTS);
break;
case QEMU_OPTION_drive:
- drive_add(NULL, "%s", optarg);
+ drive_def(optarg);
break;
case QEMU_OPTION_set:
if (qemu_set_option(optarg) != 0)
exit(1);
break;
case QEMU_OPTION_mtdblock:
- drive_add(optarg, MTD_ALIAS);
+ drive_add(IF_MTD, -1, optarg, MTD_OPTS);
break;
case QEMU_OPTION_sd:
- drive_add(optarg, SD_ALIAS);
+ drive_add(IF_SD, 0, optarg, SD_OPTS);
break;
case QEMU_OPTION_pflash:
- drive_add(optarg, PFLASH_ALIAS);
+ drive_add(IF_PFLASH, -1, optarg, PFLASH_OPTS);
break;
case QEMU_OPTION_snapshot:
snapshot = 1;
}
numa_add(optarg);
break;
+ case QEMU_OPTION_display:
+ display_type = select_display(optarg);
+ break;
case QEMU_OPTION_nographic:
display_type = DT_NOGRAPHIC;
break;
-#ifdef CONFIG_CURSES
case QEMU_OPTION_curses:
+#ifdef CONFIG_CURSES
display_type = DT_CURSES;
- break;
+#else
+ fprintf(stderr, "Curses support is disabled\n");
+ exit(1);
#endif
+ break;
case QEMU_OPTION_portrait:
graphic_rotate = 1;
break;
kernel_cmdline = optarg;
break;
case QEMU_OPTION_cdrom:
- drive_add(optarg, CDROM_ALIAS);
+ drive_add(IF_DEFAULT, 2, optarg, CDROM_OPTS);
break;
case QEMU_OPTION_boot:
{
break;
case QEMU_OPTION_fda:
case QEMU_OPTION_fdb:
- drive_add(optarg, FD_ALIAS, popt->index - QEMU_OPTION_fda);
+ drive_add(IF_FLOPPY, popt->index - QEMU_OPTION_fda,
+ optarg, FD_OPTS);
break;
case QEMU_OPTION_no_fd_bootchk:
fd_bootchk = 0;
exit(0);
break;
case QEMU_OPTION_m: {
- ssize_t value;
+ int64_t value;
value = strtosz(optarg, NULL);
if (value < 0) {
case QEMU_OPTION_sdl:
display_type = DT_SDL;
break;
+#else
+ case QEMU_OPTION_no_frame:
+ case QEMU_OPTION_alt_grab:
+ case QEMU_OPTION_ctrl_grab:
+ case QEMU_OPTION_no_quit:
+ case QEMU_OPTION_sdl:
+ fprintf(stderr, "SDL support is disabled\n");
+ exit(1);
#endif
case QEMU_OPTION_pidfile:
pid_file = optarg;
}
break;
case QEMU_OPTION_vnc:
+#ifdef CONFIG_VNC
display_remote++;
- vnc_display = optarg;
- break;
+ vnc_display = optarg;
+#else
+ fprintf(stderr, "VNC support is disabled\n");
+ exit(1);
+#endif
+ break;
case QEMU_OPTION_no_acpi:
acpi_enabled = 0;
break;
}
loc_set_none();
+ if (!st_init(trace_file)) {
+ fprintf(stderr, "warning: unable to initialize simple trace backend\n");
+ }
+
/* If no data_dir is specified then try to find it relative to the
executable path. */
if (!data_dir) {
data_dir = CONFIG_QEMU_DATADIR;
}
-#ifdef CONFIG_SIMPLE_TRACE
- /*
- * Set the trace file name, if specified.
- */
- st_set_trace_file(trace_file);
-#endif
/*
* Default to max_cpus = smp_cpus, in case the user doesn't
* specify a max_cpus value.
blk_mig_init();
- if (default_cdrom) {
- /* we always create the cdrom drive, even if no disk is there */
- drive_add(NULL, CDROM_ALIAS);
- }
-
- if (default_floppy) {
- /* we always create at least one floppy */
- drive_add(NULL, FD_ALIAS, 0);
- }
-
- if (default_sdcard) {
- /* we always create one sd slot, even if no card is in it */
- drive_add(NULL, SD_ALIAS);
- }
-
/* open the virtual block devices */
if (snapshot)
qemu_opts_foreach(qemu_find_opts("drive"), drive_enable_snapshot, NULL, 0);
if (qemu_opts_foreach(qemu_find_opts("drive"), drive_init_func, &machine->use_scsi, 1) != 0)
exit(1);
+ default_drive(default_cdrom, snapshot, machine->use_scsi,
+ IF_DEFAULT, 2, CDROM_OPTS);
+ default_drive(default_floppy, snapshot, machine->use_scsi,
+ IF_FLOPPY, 0, FD_OPTS);
+ default_drive(default_sdcard, snapshot, machine->use_scsi,
+ IF_SD, 0, SD_OPTS);
+
register_savevm_live(NULL, "ram", 0, 4, NULL, ram_save_live, NULL,
ram_load, NULL);
if (display_type == DT_DEFAULT && !display_remote) {
#if defined(CONFIG_SDL) || defined(CONFIG_COCOA)
display_type = DT_SDL;
-#else
+#elif defined(CONFIG_VNC)
vnc_display = "localhost:0,to=99";
show_vnc_port = 1;
+#else
+ display_type = DT_NONE;
#endif
}
-
+
/* init local displays */
switch (display_type) {
break;
}
+#ifdef CONFIG_VNC
/* init remote displays */
if (vnc_display) {
vnc_display_init(ds);
printf("VNC server running on `%s'\n", vnc_display_local_addr(ds));
}
}
+#endif
#ifdef CONFIG_SPICE
if (using_spice && !qxl_enabled) {
qemu_spice_display_init(ds);
dcl = ds->listeners;
while (dcl != NULL) {
if (dcl->dpy_refresh != NULL) {
- ds->gui_timer = qemu_new_timer(rt_clock, gui_update, ds);
- qemu_mod_timer(ds->gui_timer, qemu_get_clock(rt_clock));
+ ds->gui_timer = qemu_new_timer_ms(rt_clock, gui_update, ds);
+ qemu_mod_timer(ds->gui_timer, qemu_get_clock_ms(rt_clock));
break;
}
dcl = dcl->next;
}
if (ds->gui_timer == NULL) {
- nographic_timer = qemu_new_timer(rt_clock, nographic_update, NULL);
- qemu_mod_timer(nographic_timer, qemu_get_clock(rt_clock));
+ nographic_timer = qemu_new_timer_ms(rt_clock, nographic_update, NULL);
+ qemu_mod_timer(nographic_timer, qemu_get_clock_ms(rt_clock));
}
text_consoles_set_display(ds);