* THE SOFTWARE.
*/
#include "qemu/osdep.h"
+#include "qemu-version.h"
#include "qemu/cutils.h"
#include "qemu/help_option.h"
int win2k_install_hack = 0;
int singlestep = 0;
int smp_cpus = 1;
-int max_cpus = 0;
+int max_cpus = 1;
int smp_cores = 1;
int smp_threads = 1;
int acpi_enabled = 1;
},
};
-static QemuOptsList qemu_trace_opts = {
- .name = "trace",
- .implied_opt_name = "enable",
- .head = QTAILQ_HEAD_INITIALIZER(qemu_trace_opts.head),
- .desc = {
- {
- .name = "enable",
- .type = QEMU_OPT_STRING,
- },
- {
- .name = "events",
- .type = QEMU_OPT_STRING,
- },{
- .name = "file",
- .type = QEMU_OPT_STRING,
- },
- { /* end of list */ }
- },
-};
-
static QemuOptsList qemu_option_rom_opts = {
.name = "option-rom",
.implied_opt_name = "romfile",
return has_defaults;
}
-bool usb_enabled(void)
-{
- return machine_usb(current_machine);
-}
-
#ifndef _WIN32
static int parse_add_fd(void *opaque, QemuOpts *opts, Error **errp)
{
static void smp_parse(QemuOpts *opts)
{
if (opts) {
-
unsigned cpus = qemu_opt_get_number(opts, "cpus", 0);
unsigned sockets = qemu_opt_get_number(opts, "sockets", 0);
unsigned cores = qemu_opt_get_number(opts, "cores", 0);
} else if (cores == 0) {
threads = threads > 0 ? threads : 1;
cores = cpus / (sockets * threads);
+ cores = cores > 0 ? cores : 1;
} else if (threads == 0) {
threads = cpus / (cores * sockets);
+ threads = threads > 0 ? threads : 1;
} else if (sockets * cores * threads < cpus) {
error_report("cpu topology: "
"sockets (%u) * cores (%u) * threads (%u) < "
}
max_cpus = qemu_opt_get_number(opts, "maxcpus", cpus);
+
+ if (max_cpus > MAX_CPUMASK_BITS) {
+ error_report("unsupported number of maxcpus");
+ exit(1);
+ }
+
+ if (max_cpus < cpus) {
+ error_report("maxcpus must be equal to or greater than smp");
+ exit(1);
+ }
+
if (sockets * cores * threads > max_cpus) {
error_report("cpu topology: "
"sockets (%u) * cores (%u) * threads (%u) > "
}
smp_cpus = cpus;
- smp_cores = cores > 0 ? cores : 1;
- smp_threads = threads > 0 ? threads : 1;
-
- }
-
- if (max_cpus == 0) {
- max_cpus = smp_cpus;
+ smp_cores = cores;
+ smp_threads = threads;
}
- if (max_cpus > MAX_CPUMASK_BITS) {
- error_report("unsupported number of maxcpus");
- exit(1);
- }
- if (max_cpus < smp_cpus) {
- error_report("maxcpus must be equal to or greater than smp");
- exit(1);
- }
-
- if (smp_cpus > 1 || smp_cores > 1 || smp_threads > 1) {
+ if (smp_cpus > 1) {
Error *blocker = NULL;
error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED, "smp");
replay_add_blocker(blocker);
const char *p;
#endif
- if (!usb_enabled()) {
+ if (!machine_usb(current_machine)) {
return -1;
}
return -1;
}
- if (!usb_enabled()) {
+ if (!machine_usb(current_machine)) {
return -1;
}
info->name = g_strdup(mc->name);
info->cpu_max = !mc->max_cpus ? 1 : mc->max_cpus;
+ info->hotpluggable_cpus = !!mc->query_hotpluggable_cpus;
entry = g_malloc0(sizeof(*entry));
entry->value = info;
#ifdef CONFIG_VIRTFS
static int fsdev_init_func(void *opaque, QemuOpts *opts, Error **errp)
{
- int ret;
- ret = qemu_fsdev_add(opts);
-
- return ret;
+ return qemu_fsdev_add(opts);
}
#endif
}
}
+void qemu_remove_machine_init_done_notifier(Notifier *notify)
+{
+ notifier_remove(notify);
+}
+
static void qemu_run_machine_init_done_notifiers(void)
{
notifier_list_notify(&machine_init_done_notifiers, NULL);
loc_pop(&loc);
}
+static int global_init_func(void *opaque, QemuOpts *opts, Error **errp)
+{
+ GlobalProperty *g;
+
+ g = g_malloc0(sizeof(*g));
+ g->driver = qemu_opt_get(opts, "driver");
+ g->property = qemu_opt_get(opts, "property");
+ g->value = qemu_opt_get(opts, "value");
+ g->user_provided = true;
+ g->errp = &error_fatal;
+ qdev_prop_register_global(g);
+ return 0;
+}
+
int main(int argc, char **argv, char **envp)
{
int i;
const char *qtest_log = NULL;
const char *pid_file = NULL;
const char *incoming = NULL;
- int show_vnc_port = 0;
bool defconfig = true;
bool userconfig = true;
bool nographic = false;
FILE *vmstate_dump_file = NULL;
Error *main_loop_err = NULL;
Error *err = NULL;
+ bool list_data_dirs = false;
qemu_init_cpu_loop();
qemu_mutex_lock_iothread();
popt = lookup_opt(argc, argv, &optarg, &optind);
if (!(popt->arch_mask & arch_type)) {
- printf("Option %s not supported for this target\n", popt->name);
+ error_report("Option not supported for this target");
exit(1);
}
switch(popt->index) {
log_file = optarg;
break;
case QEMU_OPTION_DFILTER:
- qemu_set_dfilter_ranges(optarg);
+ qemu_set_dfilter_ranges(optarg, &error_fatal);
break;
case QEMU_OPTION_s:
add_device_config(DEV_GDB, "tcp::" DEFAULT_GDBSTUB_PORT);
add_device_config(DEV_GDB, optarg);
break;
case QEMU_OPTION_L:
- if (data_dir_idx < ARRAY_SIZE(data_dir)) {
+ if (is_help_option(optarg)) {
+ list_data_dirs = true;
+ } else if (data_dir_idx < ARRAY_SIZE(data_dir)) {
data_dir[data_dir_idx++] = optarg;
}
break;
break;
case QEMU_OPTION_xen_domid:
if (!(xen_available())) {
- printf("Option %s not supported for this target\n", popt->name);
+ error_report("Option not supported for this target");
exit(1);
}
xen_domid = atoi(optarg);
break;
case QEMU_OPTION_xen_create:
if (!(xen_available())) {
- printf("Option %s not supported for this target\n", popt->name);
+ error_report("Option not supported for this target");
exit(1);
}
xen_mode = XEN_CREATE;
break;
case QEMU_OPTION_xen_attach:
if (!(xen_available())) {
- printf("Option %s not supported for this target\n", popt->name);
+ error_report("Option not supported for this target");
exit(1);
}
xen_mode = XEN_ATTACH;
break;
case QEMU_OPTION_trace:
- {
- opts = qemu_opts_parse_noisily(qemu_find_opts("trace"),
- optarg, true);
- if (!opts) {
- exit(1);
- }
- if (qemu_opt_get(opts, "enable")) {
- trace_enable_events(qemu_opt_get(opts, "enable"));
- }
- trace_init_events(qemu_opt_get(opts, "events"));
- if (trace_file) {
- g_free(trace_file);
- }
- trace_file = g_strdup(qemu_opt_get(opts, "file"));
- qemu_opts_del(opts);
+ g_free(trace_file);
+ trace_file = trace_opt_parse(optarg);
break;
- }
case QEMU_OPTION_readconfig:
{
int ret = qemu_read_config_file(optarg);
/* Open the logfile at this point and set the log mask if necessary.
*/
if (log_file) {
- qemu_set_log_filename(log_file);
+ qemu_set_log_filename(log_file, &error_fatal);
}
if (log_mask) {
data_dir[data_dir_idx++] = CONFIG_QEMU_DATADIR;
}
+ /* -L help lists the data directories and exits. */
+ if (list_data_dirs) {
+ for (i = 0; i < data_dir_idx; i++) {
+ printf("%s\n", data_dir[i]);
+ }
+ exit(0);
+ }
+
smp_parse(qemu_opts_find(qemu_find_opts("smp-opts"), NULL));
machine_class->max_cpus = machine_class->max_cpus ?: 1; /* Default to UP */
display_type = DT_COCOA;
#elif defined(CONFIG_VNC)
vnc_parse("localhost:0,to=99,id=default", &error_abort);
- show_vnc_port = 1;
#else
display_type = DT_NONE;
#endif
qemu_opts_del(icount_opts);
}
- /* clean up network at qemu process termination */
- atexit(&net_cleanup);
-
if (default_net) {
QemuOptsList *net = qemu_find_opts("net");
qemu_opts_set(net, NULL, "type", "nic", &error_abort);
exit (i == 1 ? 1 : 0);
}
- if (machine_class->compat_props) {
- GlobalProperty *p;
- for (i = 0; i < machine_class->compat_props->len; i++) {
- p = g_array_index(machine_class->compat_props, GlobalProperty *, i);
- qdev_prop_register_global(p);
- }
- }
- qemu_add_globals();
+ machine_register_compat_props(current_machine);
+
+ qemu_opts_foreach(qemu_find_opts("global"),
+ global_init_func, NULL, NULL);
/* This checkpoint is required by replay to separate prior clock
reading from the other reads, because timer polling functions query
}
/* init USB devices */
- if (usb_enabled()) {
+ if (machine_usb(current_machine)) {
if (foreach_device_config(DEV_USB, usb_parse) < 0)
exit(1);
}
os_setup_signal_handling();
/* init remote displays */
+#ifdef CONFIG_VNC
qemu_opts_foreach(qemu_find_opts("vnc"),
vnc_init_func, NULL, NULL);
- if (show_vnc_port) {
- char *ret = vnc_display_local_addr("default");
- printf("VNC server running on '%s'\n", ret);
- g_free(ret);
- }
+#endif
if (using_spice) {
qemu_spice_display_init();
os_setup_post();
+ trace_init_vcpu_events();
main_loop();
replay_disable_events();
tpm_cleanup();
#endif
+ /* vhost-user must be cleaned up before chardevs. */
+ net_cleanup();
+ qemu_chr_cleanup();
+
return 0;
}