#include "qapi/qapi-commands-block-core.h"
#include "qapi/qapi-commands-misc.h"
#include "qapi/qapi-commands-run-state.h"
+#include "qapi/qapi-commands-ui.h"
#include "qapi/qmp/qerror.h"
#include "sysemu/iothread.h"
int nb_nics;
NICInfo nd_table[MAX_NICS];
int autostart;
-static int rtc_utc = 1;
-static int rtc_date_offset = -1; /* -1 means no change */
+static enum {
+ RTC_BASE_UTC,
+ RTC_BASE_LOCALTIME,
+ RTC_BASE_DATETIME,
+} rtc_base_type = RTC_BASE_UTC;
+static time_t rtc_ref_start_datetime;
+static int rtc_realtime_clock_offset; /* used only with QEMU_CLOCK_REALTIME */
+static int rtc_host_datetime_offset = -1; /* valid & used only with
+ RTC_BASE_DATETIME */
QEMUClockType rtc_clock;
int vga_interface_type = VGA_NONE;
static DisplayOptions dpy;
static QemuOptsList qemu_rtc_opts = {
.name = "rtc",
.head = QTAILQ_HEAD_INITIALIZER(qemu_rtc_opts.head),
+ .merge_lists = true,
.desc = {
{
.name = "base",
}, {
.name = "file",
.type = QEMU_OPT_STRING,
- .help = "Sets the name of the file from which\n"
+ .help = "Sets the name of the file from which "
"the fw_cfg blob will be loaded",
}, {
.name = "string",
}
/***********************************************************/
-/* real time host monotonic timer */
-
-static time_t qemu_time(void)
+/* RTC reference time/date access */
+static time_t qemu_ref_timedate(QEMUClockType clock)
{
- return qemu_clock_get_ms(QEMU_CLOCK_HOST) / 1000;
+ time_t value = qemu_clock_get_ms(clock) / 1000;
+ switch (clock) {
+ case QEMU_CLOCK_REALTIME:
+ value -= rtc_realtime_clock_offset;
+ /* no break */
+ case QEMU_CLOCK_VIRTUAL:
+ value += rtc_ref_start_datetime;
+ break;
+ case QEMU_CLOCK_HOST:
+ if (rtc_base_type == RTC_BASE_DATETIME) {
+ value -= rtc_host_datetime_offset;
+ }
+ break;
+ default:
+ assert(0);
+ }
+ return value;
}
-/***********************************************************/
-/* host time/date access */
void qemu_get_timedate(struct tm *tm, int offset)
{
- time_t ti = qemu_time();
+ time_t ti = qemu_ref_timedate(rtc_clock);
ti += offset;
- if (rtc_date_offset == -1) {
- if (rtc_utc)
- gmtime_r(&ti, tm);
- else
- localtime_r(&ti, tm);
- } else {
- ti -= rtc_date_offset;
+
+ switch (rtc_base_type) {
+ case RTC_BASE_DATETIME:
+ case RTC_BASE_UTC:
gmtime_r(&ti, tm);
+ break;
+ case RTC_BASE_LOCALTIME:
+ localtime_r(&ti, tm);
+ break;
}
}
{
time_t seconds;
- if (rtc_date_offset == -1)
- if (rtc_utc)
- seconds = mktimegm(tm);
- else {
- struct tm tmp = *tm;
- tmp.tm_isdst = -1; /* use timezone to figure it out */
- seconds = mktime(&tmp);
- }
- else
- seconds = mktimegm(tm) + rtc_date_offset;
-
- return seconds - qemu_time();
+ switch (rtc_base_type) {
+ case RTC_BASE_DATETIME:
+ case RTC_BASE_UTC:
+ seconds = mktimegm(tm);
+ break;
+ case RTC_BASE_LOCALTIME:
+ {
+ struct tm tmp = *tm;
+ tmp.tm_isdst = -1; /* use timezone to figure it out */
+ seconds = mktime(&tmp);
+ break;
+ }
+ default:
+ abort();
+ }
+
+ return seconds - qemu_ref_timedate(QEMU_CLOCK_HOST);
}
-static void configure_rtc_date_offset(const char *startdate)
+static void configure_rtc_base_datetime(const char *startdate)
{
- time_t rtc_start_date;
+ time_t rtc_start_datetime;
struct tm tm;
if (sscanf(startdate, "%d-%d-%dT%d:%d:%d", &tm.tm_year, &tm.tm_mon,
}
tm.tm_year -= 1900;
tm.tm_mon--;
- rtc_start_date = mktimegm(&tm);
- if (rtc_start_date == -1) {
+ rtc_start_datetime = mktimegm(&tm);
+ if (rtc_start_datetime == -1) {
date_fail:
- error_report("invalid date format");
+ error_report("invalid datetime format");
error_printf("valid formats: "
"'2006-06-17T16:01:21' or '2006-06-17'\n");
exit(1);
}
- rtc_date_offset = qemu_time() - rtc_start_date;
+ rtc_host_datetime_offset = rtc_ref_start_datetime - rtc_start_datetime;
+ rtc_ref_start_datetime = rtc_start_datetime;
}
static void configure_rtc(QemuOpts *opts)
{
const char *value;
+ /* Set defaults */
+ rtc_clock = QEMU_CLOCK_HOST;
+ rtc_ref_start_datetime = qemu_clock_get_ms(QEMU_CLOCK_HOST) / 1000;
+ rtc_realtime_clock_offset = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) / 1000;
+
value = qemu_opt_get(opts, "base");
if (value) {
if (!strcmp(value, "utc")) {
- rtc_utc = 1;
+ rtc_base_type = RTC_BASE_UTC;
} else if (!strcmp(value, "localtime")) {
Error *blocker = NULL;
- rtc_utc = 0;
+ rtc_base_type = RTC_BASE_LOCALTIME;
error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED,
"-rtc base=localtime");
replay_add_blocker(blocker);
} else {
- configure_rtc_date_offset(value);
+ rtc_base_type = RTC_BASE_DATETIME;
+ configure_rtc_base_datetime(value);
}
}
value = qemu_opt_get(opts, "clock");
fd_opaque = qemu_opt_get(opts, "opaque");
if (fd < 0) {
- error_report("fd option is required and must be non-negative");
+ error_setg(errp, "fd option is required and must be non-negative");
return -1;
}
if (fd <= STDERR_FILENO) {
- error_report("fd cannot be a standard I/O stream");
+ error_setg(errp, "fd cannot be a standard I/O stream");
return -1;
}
*/
flags = fcntl(fd, F_GETFD);
if (flags == -1 || (flags & FD_CLOEXEC)) {
- error_report("fd is not valid or already in use");
+ error_setg(errp, "fd is not valid or already in use");
return -1;
}
if (fdset_id < 0) {
- error_report("set option is required and must be non-negative");
+ error_setg(errp, "set option is required and must be non-negative");
return -1;
}
}
#endif
if (dupfd == -1) {
- error_report("error duplicating fd: %s", strerror(errno));
+ error_setg(errp, "error duplicating fd: %s", strerror(errno));
return -1;
}
{
BlockInterfaceType *block_default_type = opaque;
- return drive_new(opts, *block_default_type) == NULL;
+ return drive_new(opts, *block_default_type, errp) == NULL;
}
static int drive_enable_snapshot(void *opaque, QemuOpts *opts, Error **errp)
drive_enable_snapshot(NULL, opts, NULL);
}
- dinfo = drive_new(opts, type);
- if (!dinfo) {
- exit(1);
- }
+ dinfo = drive_new(opts, type, &error_abort);
dinfo->is_default = true;
}
/* compute missing values, prefer sockets over cores over threads */
if (cpus == 0 || sockets == 0) {
- sockets = sockets > 0 ? sockets : 1;
cores = cores > 0 ? cores : 1;
threads = threads > 0 ? threads : 1;
if (cpus == 0) {
+ sockets = sockets > 0 ? sockets : 1;
cpus = cores * threads * sockets;
+ } else {
+ max_cpus = qemu_opt_get_number(opts, "maxcpus", cpus);
+ sockets = max_cpus / (cores * threads);
}
} else if (cores == 0) {
threads = threads > 0 ? threads : 1;
exit(1);
}
+ if (sockets * cores * threads != max_cpus) {
+ warn_report("Invalid CPU topology deprecated: "
+ "sockets (%u) * cores (%u) * threads (%u) "
+ "!= maxcpus (%u)",
+ sockets, cores, threads, max_cpus);
+ }
+
smp_cpus = cpus;
smp_cores = cores;
smp_threads = threads;
return 1;
}
-/***********************************************************/
-/* main execution loop */
-
struct vm_change_state_entry {
VMChangeStateHandler *cb;
void *opaque;
static void parse_display_qapi(const char *optarg)
{
- Error *err = NULL;
DisplayOptions *opts;
Visitor *v;
- v = qobject_input_visitor_new_str(optarg, "type", &err);
- if (!v) {
- error_report_err(err);
- exit(1);
- }
+ v = qobject_input_visitor_new_str(optarg, "type", &error_fatal);
visit_type_DisplayOptions(v, NULL, &opts, &error_fatal);
QAPI_CLONE_MEMBERS(DisplayOptions, &dpy, opts);
visit_free(v);
}
+DisplayOptions *qmp_query_display_options(Error **errp)
+{
+ return QAPI_CLONE(DisplayOptions, &dpy);
+}
+
static void parse_display(const char *p)
{
const char *opts;
FWCfgState *fw_cfg = (FWCfgState *) opaque;
if (fw_cfg == NULL) {
- error_report("fw_cfg device not available");
+ error_setg(errp, "fw_cfg device not available");
return -1;
}
name = qemu_opt_get(opts, "name");
/* we need name and either a file or the content string */
if (!(nonempty_str(name) && (nonempty_str(file) || nonempty_str(str)))) {
- error_report("invalid argument(s)");
+ error_setg(errp, "invalid argument(s)");
return -1;
}
if (nonempty_str(file) && nonempty_str(str)) {
- error_report("file and string are mutually exclusive");
+ error_setg(errp, "file and string are mutually exclusive");
return -1;
}
if (strlen(name) > FW_CFG_MAX_FILE_PATH - 1) {
- error_report("name too long (max. %d char)", FW_CFG_MAX_FILE_PATH - 1);
+ error_setg(errp, "name too long (max. %d char)",
+ FW_CFG_MAX_FILE_PATH - 1);
return -1;
}
if (strncmp(name, "opt/", 4) != 0) {
size = strlen(str); /* NUL terminator NOT included in fw_cfg blob */
buf = g_memdup(str, size);
} else {
- if (!g_file_get_contents(file, &buf, &size, NULL)) {
- error_report("can't load %s", file);
+ GError *err = NULL;
+ if (!g_file_get_contents(file, &buf, &size, &err)) {
+ error_setg(errp, "can't load %s: %s", file, err->message);
+ g_error_free(err);
return -1;
}
}
static int device_init_func(void *opaque, QemuOpts *opts, Error **errp)
{
- Error *err = NULL;
DeviceState *dev;
- dev = qdev_device_add(opts, &err);
+ dev = qdev_device_add(opts, errp);
if (!dev) {
- error_report_err(err);
return -1;
}
object_unref(OBJECT(dev));
if (!qemu_chr_new_from_opts(opts, &local_err)) {
if (local_err) {
- error_report_err(local_err);
+ error_propagate(errp, local_err);
return -1;
}
exit(0);
#ifdef CONFIG_VIRTFS
static int fsdev_init_func(void *opaque, QemuOpts *opts, Error **errp)
{
- return qemu_fsdev_add(opts);
+ return qemu_fsdev_add(opts, errp);
}
#endif
} else if (strcmp(mode, "control") == 0) {
flags = MONITOR_USE_CONTROL;
} else {
- error_report("unknown monitor mode \"%s\"", mode);
- exit(1);
+ error_setg(errp, "unknown monitor mode \"%s\"", mode);
+ return -1;
}
if (qemu_opt_get_bool(opts, "pretty", 0))
}
chardev = qemu_opt_get(opts, "chardev");
+ if (!chardev) {
+ error_report("chardev is required");
+ exit(1);
+ }
chr = qemu_chr_find(chardev);
if (chr == NULL) {
- error_report("chardev \"%s\" not found", chardev);
- exit(1);
+ error_setg(errp, "chardev \"%s\" not found", chardev);
+ return -1;
}
monitor_init(chr, flags);
} else {
snprintf(label, sizeof(label), "compat_monitor%d",
monitor_device_index);
- opts = qemu_chr_parse_compat(label, optarg);
+ opts = qemu_chr_parse_compat(label, optarg, true);
if (!opts) {
error_report("parse error: %s", optarg);
exit(1);
snprintf(label, sizeof(label), "serial%d", index);
serial_hds = g_renew(Chardev *, serial_hds, index + 1);
- serial_hds[index] = qemu_chr_new(label, devname);
+ serial_hds[index] = qemu_chr_new_mux_mon(label, devname);
if (!serial_hds[index]) {
error_report("could not connect serial device"
" to character backend '%s'", devname);
exit(1);
}
snprintf(label, sizeof(label), "parallel%d", index);
- parallel_hds[index] = qemu_chr_new(label, devname);
+ parallel_hds[index] = qemu_chr_new_mux_mon(label, devname);
if (!parallel_hds[index]) {
error_report("could not connect parallel device"
" to character backend '%s'", devname);
qemu_opt_set(dev_opts, "driver", "virtconsole", &error_abort);
snprintf(label, sizeof(label), "virtcon%d", index);
- virtcon_hds[index] = qemu_chr_new(label, devname);
+ virtcon_hds[index] = qemu_chr_new_mux_mon(label, devname);
if (!virtcon_hds[index]) {
error_report("could not connect virtio console"
" to character backend '%s'", devname);
{
QemuOpts *opts;
- if (!qemu_chr_new("debugcon", devname)) {
+ if (!qemu_chr_new_mux_mon("debugcon", devname)) {
+ error_report("invalid character backend '%s'", devname);
exit(1);
}
opts = qemu_opts_create(qemu_find_opts("device"), "debugcon", 1, NULL);
notifier_list_notify(&exit_notifiers, NULL);
}
+static const char *pid_file;
+static Notifier qemu_unlink_pidfile_notifier;
+
+static void qemu_unlink_pidfile(Notifier *n, void *data)
+{
+ if (pid_file) {
+ unlink(pid_file);
+ }
+}
+
bool machine_init_done;
void qemu_add_machine_init_done_notifier(Notifier *notify)
g_free(qom_name);
if (local_err) {
- error_report_err(local_err);
+ error_propagate(errp, local_err);
return -1;
}
* cannot be created here, as it depends on the chardev
* already existing.
*/
-static bool object_create_initial(const char *type)
+static bool object_create_initial(const char *type, QemuOpts *opts)
{
+ ObjectClass *klass;
+
+ if (is_help_option(type)) {
+ GSList *l, *list;
+
+ printf("List of user creatable objects:\n");
+ list = object_class_get_list_sorted(TYPE_USER_CREATABLE, false);
+ for (l = list; l != NULL; l = l->next) {
+ ObjectClass *oc = OBJECT_CLASS(l->data);
+ printf(" %s\n", object_class_get_name(oc));
+ }
+ g_slist_free(list);
+ exit(0);
+ }
+
+ klass = object_class_by_name(type);
+ if (klass && qemu_opt_has_help_opt(opts)) {
+ ObjectPropertyIterator iter;
+ ObjectProperty *prop;
+ GPtrArray *array = g_ptr_array_new();
+ int i;
+
+ object_class_property_iter_init(&iter, klass);
+ while ((prop = object_property_iter_next(&iter))) {
+ GString *str;
+
+ if (!prop->set) {
+ continue;
+ }
+
+ str = g_string_new(NULL);
+ g_string_append_printf(str, " %s=<%s>", prop->name, prop->type);
+ if (prop->description) {
+ if (str->len < 24) {
+ g_string_append_printf(str, "%*s", 24 - (int)str->len, "");
+ }
+ g_string_append_printf(str, " - %s", prop->description);
+ }
+ g_ptr_array_add(array, g_string_free(str, false));
+ }
+ g_ptr_array_sort(array, (GCompareFunc)qemu_pstrcmp0);
+ if (array->len > 0) {
+ printf("%s options:\n", type);
+ } else {
+ printf("There are no options for %s.\n", type);
+ }
+ for (i = 0; i < array->len; i++) {
+ printf("%s\n", (char *)array->pdata[i]);
+ }
+ g_ptr_array_set_free_func(array, g_free);
+ g_ptr_array_free(array, true);
+ exit(0);
+ }
+
if (g_str_equal(type, "rng-egd") ||
g_str_has_prefix(type, "pr-manager-")) {
return false;
* The remainder of object creation happens after the
* creation of chardev, fsdev, net clients and device data types.
*/
-static bool object_create_delayed(const char *type)
+static bool object_create_delayed(const char *type, QemuOpts *opts)
{
- return !object_create_initial(type);
+ return !object_create_initial(type, opts);
}
const char *vga_model = NULL;
const char *qtest_chrdev = NULL;
const char *qtest_log = NULL;
- const char *pid_file = NULL;
const char *incoming = NULL;
bool userconfig = true;
bool nographic = false;
error_reportf_err(err, "cannot initialize crypto: ");
exit(1);
}
- rtc_clock = QEMU_CLOCK_HOST;
QLIST_INIT (&vm_change_state_head);
os_setup_early_signal_handling();
break;
#endif
case QEMU_OPTION_bt:
+ warn_report("The bluetooth subsystem is deprecated and will "
+ "be removed soon. If the bluetooth subsystem is "
+ "still useful for you, please send a mail to "
add_device_config(DEV_BT, optarg);
break;
case QEMU_OPTION_audio_help:
if (!opts) {
exit(1);
}
- configure_rtc(opts);
break;
case QEMU_OPTION_tb_size:
#ifndef CONFIG_TCG
exit(EXIT_FAILURE);
}
+ configure_rtc(qemu_find_opts_singleton("rtc"));
+
machine_class = select_machine();
set_memory_options(&ram_slots, &maxram_size, machine_class);
os_daemonize();
rcu_disable_atfork();
- if (pid_file && qemu_create_pidfile(pid_file) != 0) {
- error_report("could not acquire pid file: %s", strerror(errno));
+ if (pid_file && !qemu_write_pidfile(pid_file, &err)) {
+ error_reportf_err(err, "cannot create PID file: ");
exit(1);
}
+ qemu_unlink_pidfile_notifier.notify = qemu_unlink_pidfile;
+ qemu_add_exit_notifier(&qemu_unlink_pidfile_notifier);
+
if (qemu_init_main_loop(&main_loop_err)) {
error_report_err(main_loop_err);
exit(1);
#ifdef CONFIG_SECCOMP
olist = qemu_find_opts_err("sandbox", NULL);
- if (olist && qemu_opts_foreach(olist, parse_sandbox, NULL, NULL)) {
- exit(1);
+ if (olist) {
+ qemu_opts_foreach(olist, parse_sandbox, NULL, &error_fatal);
}
#endif
- if (qemu_opts_foreach(qemu_find_opts("name"),
- parse_name, NULL, NULL)) {
- exit(1);
- }
+ qemu_opts_foreach(qemu_find_opts("name"),
+ parse_name, NULL, &error_fatal);
#ifndef _WIN32
- if (qemu_opts_foreach(qemu_find_opts("add-fd"),
- parse_add_fd, NULL, NULL)) {
- exit(1);
- }
+ qemu_opts_foreach(qemu_find_opts("add-fd"),
+ parse_add_fd, NULL, &error_fatal);
- if (qemu_opts_foreach(qemu_find_opts("add-fd"),
- cleanup_add_fd, NULL, NULL)) {
- exit(1);
- }
+ qemu_opts_foreach(qemu_find_opts("add-fd"),
+ cleanup_add_fd, NULL, &error_fatal);
#endif
current_machine = MACHINE(object_new(object_class_get_name(
page_size_init();
socket_init();
- if (qemu_opts_foreach(qemu_find_opts("object"),
- user_creatable_add_opts_foreach,
- object_create_initial, NULL)) {
- exit(1);
- }
+ qemu_opts_foreach(qemu_find_opts("object"),
+ user_creatable_add_opts_foreach,
+ object_create_initial, &error_fatal);
- if (qemu_opts_foreach(qemu_find_opts("chardev"),
- chardev_init_func, NULL, NULL)) {
- exit(1);
- }
+ qemu_opts_foreach(qemu_find_opts("chardev"),
+ chardev_init_func, NULL, &error_fatal);
#ifdef CONFIG_VIRTFS
- if (qemu_opts_foreach(qemu_find_opts("fsdev"),
- fsdev_init_func, NULL, NULL)) {
- exit(1);
- }
+ qemu_opts_foreach(qemu_find_opts("fsdev"),
+ fsdev_init_func, NULL, &error_fatal);
#endif
if (qemu_opts_foreach(qemu_find_opts("device"),
}
machine_opts = qemu_get_machine_opts();
- if (qemu_opt_foreach(machine_opts, machine_set_property, current_machine,
- NULL)) {
- object_unref(OBJECT(current_machine));
- exit(1);
- }
+ qemu_opt_foreach(machine_opts, machine_set_property, current_machine,
+ &error_fatal);
configure_accelerator(current_machine);
#endif
}
- colo_info_init();
-
if (net_init_clients(&err) < 0) {
error_report_err(err);
exit(1);
}
- if (qemu_opts_foreach(qemu_find_opts("object"),
- user_creatable_add_opts_foreach,
- object_create_delayed, NULL)) {
- exit(1);
- }
+ qemu_opts_foreach(qemu_find_opts("object"),
+ user_creatable_add_opts_foreach,
+ object_create_delayed, &error_fatal);
- if (tpm_init() < 0) {
- exit(1);
- }
+ tpm_init();
/* init the bluetooth world */
if (foreach_device_config(DEV_BT, bt_parse))
NULL, NULL);
}
if (qemu_opts_foreach(qemu_find_opts("drive"), drive_init_func,
- &machine_class->block_default_type, NULL)) {
- exit(1);
+ &machine_class->block_default_type, &error_fatal)) {
+ /* We printed help */
+ exit(0);
}
default_drive(default_cdrom, snapshot, machine_class->block_default_type, 2,
default_drive(default_floppy, snapshot, IF_FLOPPY, 0, FD_OPTS);
default_drive(default_sdcard, snapshot, IF_SD, 0, SD_OPTS);
- if (qemu_opts_foreach(qemu_find_opts("mon"),
- mon_init_func, NULL, NULL)) {
- exit(1);
- }
+ qemu_opts_foreach(qemu_find_opts("mon"),
+ mon_init_func, NULL, &error_fatal);
if (foreach_device_config(DEV_SERIAL, serial_parse) < 0)
exit(1);
hax_sync_vcpus();
}
- if (qemu_opts_foreach(qemu_find_opts("fw_cfg"),
- parse_fw_cfg, fw_cfg_find(), NULL) != 0) {
- exit(1);
- }
+ qemu_opts_foreach(qemu_find_opts("fw_cfg"),
+ parse_fw_cfg, fw_cfg_find(), &error_fatal);
/* init USB devices */
if (machine_usb(current_machine)) {
/* init generic devices */
rom_set_order_override(FW_CFG_ORDER_OVERRIDE_DEVICE);
- if (qemu_opts_foreach(qemu_find_opts("device"),
- device_init_func, NULL, NULL)) {
- exit(1);
- }
+ qemu_opts_foreach(qemu_find_opts("device"),
+ device_init_func, NULL, &error_fatal);
cpu_synchronize_all_post_init();
/* init remote displays */
#ifdef CONFIG_VNC
qemu_opts_foreach(qemu_find_opts("vnc"),
- vnc_init_func, NULL, NULL);
+ vnc_init_func, NULL, &error_fatal);
#endif
if (using_spice) {
replay_checkpoint(CHECKPOINT_RESET);
qemu_system_reset(SHUTDOWN_CAUSE_NONE);
register_global_state();
- if (replay_mode != REPLAY_MODE_NONE) {
- replay_vmstate_init();
- } else if (loadvm) {
+ if (loadvm) {
Error *local_err = NULL;
if (load_snapshot(loadvm, &local_err) < 0) {
error_report_err(local_err);
autostart = 0;
+ exit(1);
}
}
+ if (replay_mode != REPLAY_MODE_NONE) {
+ replay_vmstate_init();
+ }
qdev_prop_check_globals();
if (vmstate_dump_file) {