#include "qemu/sockets.h"
#include "hw/hw.h"
#include "hw/boards.h"
+#include "sysemu/accel.h"
#include "hw/usb.h"
#include "hw/pcmcia.h"
#include "hw/i386/pc.h"
#include "qemu/timer.h"
#include "sysemu/char.h"
#include "qemu/bitmap.h"
-#include "qemu/cache-utils.h"
#include "sysemu/blockdev.h"
#include "hw/block/block.h"
#include "migration/block.h"
#include "ui/qemu-spice.h"
#include "qapi/string-input-visitor.h"
#include "qapi/opts-visitor.h"
+#include "qom/object_interfaces.h"
+#include "qapi-event.h"
#define DEFAULT_RAM_SIZE 128
ram_addr_t ram_size;
const char *mem_path = NULL;
int mem_prealloc = 0; /* force preallocation of physical target memory */
+bool enable_mlock = false;
int nb_nics;
NICInfo nd_table[MAX_NICS];
int autostart;
unsigned int nb_prom_envs = 0;
const char *prom_envs[MAX_PROM_ENVS];
int boot_menu;
-static bool boot_strict;
+bool boot_strict;
uint8_t *boot_splash_filedata;
size_t boot_splash_filedata_size;
uint8_t qemu_extra_params_fw[2];
-typedef struct FWBootEntry FWBootEntry;
-
-struct FWBootEntry {
- QTAILQ_ENTRY(FWBootEntry) link;
- int32_t bootindex;
- DeviceState *dev;
- char *suffix;
-};
-
-static QTAILQ_HEAD(, FWBootEntry) fw_boot_order =
- QTAILQ_HEAD_INITIALIZER(fw_boot_order);
+int icount_align_option;
int nb_numa_nodes;
+int max_numa_nodeid;
NodeInfo numa_info[MAX_NODES];
uint8_t qemu_uuid[16];
static NotifierList machine_init_done_notifiers =
NOTIFIER_LIST_INITIALIZER(machine_init_done_notifiers);
-static bool tcg_allowed = true;
bool xen_allowed;
uint32_t xen_domid;
enum xen_mode xen_mode = XEN_EMULATE;
-static int tcg_tb_size;
static int has_defaults = 1;
static int default_serial = 1;
.name = PC_MACHINE_MAX_RAM_BELOW_4G,
.type = QEMU_OPT_SIZE,
.help = "maximum ram below the 4G boundary (32bit boundary)",
+ },{
+ .name = "iommu",
+ .type = QEMU_OPT_BOOL,
+ .help = "Set on/off to enable/disable Intel IOMMU (VT-d)",
},
{ /* End of list */ }
},
},
};
+static QemuOptsList qemu_icount_opts = {
+ .name = "icount",
+ .implied_opt_name = "shift",
+ .merge_lists = true,
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_icount_opts.head),
+ .desc = {
+ {
+ .name = "shift",
+ .type = QEMU_OPT_STRING,
+ }, {
+ .name = "align",
+ .type = QEMU_OPT_BOOL,
+ },
+ { /* end of list */ }
+ },
+};
+
/**
* Get machine options
*
* the STOP event.
*/
if (runstate_is_running()) {
- monitor_protocol_event(QEVENT_STOP, NULL);
+ qapi_event_send_stop(&error_abort);
} else {
cpu_enable_ticks();
runstate_set(RUN_STATE_RUNNING);
resume_all_vcpus();
}
- monitor_protocol_event(QEVENT_RESUME, NULL);
+ qapi_event_send_resume(&error_abort);
}
return seconds - time(NULL);
}
-void rtc_change_mon_event(struct tm *tm)
-{
- QObject *data;
-
- data = qobject_from_jsonf("{ 'offset': %d }", qemu_timedate_diff(tm));
- monitor_protocol_event(QEVENT_RTC_CHANGE, data);
- qobject_decref(data);
-}
-
static void configure_rtc_date_offset(const char *startdate, int legacy)
{
time_t rtc_start_date;
static int drive_enable_snapshot(QemuOpts *opts, void *opaque)
{
- if (NULL == qemu_opt_get(opts, "snapshot")) {
+ if (qemu_opt_get(opts, "snapshot") == NULL) {
qemu_opt_set(opts, "snapshot", "on");
}
return 0;
int index, const char *optstr)
{
QemuOpts *opts;
+ DriveInfo *dinfo;
if (!enable || drive_get_by_index(type, index)) {
return;
if (snapshot) {
drive_enable_snapshot(opts, NULL);
}
- if (!drive_new(opts, type)) {
+
+ dinfo = drive_new(opts, type);
+ if (!dinfo) {
exit(1);
}
+ dinfo->is_default = true;
+
}
void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque)
g_free(normal_boot_order);
}
-void add_boot_device_path(int32_t bootindex, DeviceState *dev,
- const char *suffix)
-{
- FWBootEntry *node, *i;
-
- if (bootindex < 0) {
- return;
- }
-
- assert(dev != NULL || suffix != NULL);
-
- node = g_malloc0(sizeof(FWBootEntry));
- node->bootindex = bootindex;
- node->suffix = g_strdup(suffix);
- node->dev = dev;
-
- QTAILQ_FOREACH(i, &fw_boot_order, link) {
- if (i->bootindex == bootindex) {
- fprintf(stderr, "Two devices with same boot index %d\n", bootindex);
- exit(1);
- } else if (i->bootindex < bootindex) {
- continue;
- }
- QTAILQ_INSERT_BEFORE(i, node, link);
- return;
- }
- QTAILQ_INSERT_TAIL(&fw_boot_order, node, link);
-}
-
-DeviceState *get_boot_device(uint32_t position)
-{
- uint32_t counter = 0;
- FWBootEntry *i = NULL;
- DeviceState *res = NULL;
-
- if (!QTAILQ_EMPTY(&fw_boot_order)) {
- QTAILQ_FOREACH(i, &fw_boot_order, link) {
- if (counter == position) {
- res = i->dev;
- break;
- }
- counter++;
- }
- }
- return res;
-}
-
-/*
- * This function returns null terminated string that consist of new line
- * separated device paths.
- *
- * memory pointed by "size" is assigned total length of the array in bytes
- *
- */
-char *get_boot_devices_list(size_t *size, bool ignore_suffixes)
-{
- FWBootEntry *i;
- size_t total = 0;
- char *list = NULL;
-
- QTAILQ_FOREACH(i, &fw_boot_order, link) {
- char *devpath = NULL, *bootpath;
- size_t len;
-
- if (i->dev) {
- devpath = qdev_get_fw_dev_path(i->dev);
- assert(devpath);
- }
-
- if (i->suffix && !ignore_suffixes && devpath) {
- size_t bootpathlen = strlen(devpath) + strlen(i->suffix) + 1;
-
- bootpath = g_malloc(bootpathlen);
- snprintf(bootpath, bootpathlen, "%s%s", devpath, i->suffix);
- g_free(devpath);
- } else if (devpath) {
- bootpath = devpath;
- } else if (!ignore_suffixes) {
- assert(i->suffix);
- bootpath = g_strdup(i->suffix);
- } else {
- bootpath = g_strdup("");
- }
-
- if (total) {
- list[total-1] = '\n';
- }
- len = strlen(bootpath) + 1;
- list = g_realloc(list, total + len);
- memcpy(&list[total], bootpath, len);
- total += len;
- g_free(bootpath);
- }
-
- *size = total;
-
- if (boot_strict && *size > 0) {
- list[total-1] = '\n';
- list = g_realloc(list, total + 5);
- memcpy(&list[total], "HALT", 5);
- *size = total + 5;
- }
- return list;
-}
-
static QemuOptsList qemu_smp_opts = {
.name = "smp-opts",
.implied_opt_name = "cpus",
}
-static void configure_realtime(QemuOpts *opts)
+static void realtime_init(void)
{
- bool enable_mlock;
-
- enable_mlock = qemu_opt_get_bool(opts, "mlock", true);
-
if (enable_mlock) {
if (os_mlock() < 0) {
fprintf(stderr, "qemu: locking memory failed\n");
mc->hot_add_cpu = qm->hot_add_cpu;
mc->kvm_type = qm->kvm_type;
mc->block_default_type = qm->block_default_type;
+ mc->units_per_default_bus = qm->units_per_default_bus;
mc->max_cpus = qm->max_cpus;
mc->no_serial = qm->no_serial;
mc->no_parallel = qm->no_parallel;
void vm_state_notify(int running, RunState state)
{
- VMChangeStateEntry *e;
+ VMChangeStateEntry *e, *next;
trace_vm_state_notify(running, state);
- for (e = vm_change_state_head.lh_first; e; e = e->entries.le_next) {
+ QLIST_FOREACH_SAFE(e, &vm_change_state_head, entries, next) {
e->cb(e->opaque, running, state);
}
}
qemu_devices_reset();
}
if (report) {
- monitor_protocol_event(QEVENT_RESET, NULL);
+ qapi_event_send_reset(&error_abort);
}
cpu_synchronize_all_post_reset();
}
pause_all_vcpus();
notifier_list_notify(&suspend_notifiers, NULL);
runstate_set(RUN_STATE_SUSPENDED);
- monitor_protocol_event(QEVENT_SUSPEND, NULL);
+ qapi_event_send_suspend(&error_abort);
}
void qemu_system_suspend_request(void)
void qemu_system_shutdown_request(void)
{
+ trace_qemu_system_shutdown_request();
shutdown_requested = 1;
qemu_notify_event();
}
static void qemu_system_powerdown(void)
{
- monitor_protocol_event(QEVENT_POWERDOWN, NULL);
+ qapi_event_send_powerdown(&error_abort);
notifier_list_notify(&powerdown_notifiers, NULL);
}
void qemu_system_powerdown_request(void)
{
+ trace_qemu_system_powerdown_request();
powerdown_requested = 1;
qemu_notify_event();
}
}
if (qemu_shutdown_requested()) {
qemu_kill_report();
- monitor_protocol_event(QEVENT_SHUTDOWN, NULL);
+ qapi_event_send_shutdown(&error_abort);
if (no_shutdown) {
vm_stop(RUN_STATE_SHUTDOWN);
} else {
notifier_list_notify(&wakeup_notifiers, &wakeup_reason);
wakeup_reason = QEMU_WAKEUP_REASON_NONE;
resume_all_vcpus();
- monitor_protocol_event(QEVENT_WAKEUP, NULL);
+ qapi_event_send_wakeup(&error_abort);
}
if (qemu_powerdown_requested()) {
qemu_system_powerdown();
loc_push_restore(&conf->loc);
rc = func(conf->cmdline);
loc_pop(&conf->loc);
- if (0 != rc)
+ if (rc) {
return rc;
+ }
}
return 0;
}
exit(!name || !is_help_option(name));
}
-static int tcg_init(MachineClass *mc)
-{
- tcg_exec_init(tcg_tb_size * 1024 * 1024);
- return 0;
-}
-
-static struct {
- const char *opt_name;
- const char *name;
- int (*available)(void);
- int (*init)(MachineClass *mc);
- bool *allowed;
-} accel_list[] = {
- { "tcg", "tcg", tcg_available, tcg_init, &tcg_allowed },
- { "xen", "Xen", xen_available, xen_init, &xen_allowed },
- { "kvm", "KVM", kvm_available, kvm_init, &kvm_allowed },
- { "qtest", "QTest", qtest_available, qtest_init_accel, &qtest_allowed },
-};
-
-static int configure_accelerator(MachineClass *mc)
-{
- const char *p;
- char buf[10];
- int i, ret;
- bool accel_initialised = false;
- bool init_failed = false;
-
- p = qemu_opt_get(qemu_get_machine_opts(), "accel");
- if (p == NULL) {
- /* Use the default "accelerator", tcg */
- p = "tcg";
- }
-
- while (!accel_initialised && *p != '\0') {
- if (*p == ':') {
- p++;
- }
- p = get_opt_name(buf, sizeof (buf), p, ':');
- for (i = 0; i < ARRAY_SIZE(accel_list); i++) {
- if (strcmp(accel_list[i].opt_name, buf) == 0) {
- if (!accel_list[i].available()) {
- printf("%s not supported for this target\n",
- accel_list[i].name);
- break;
- }
- *(accel_list[i].allowed) = true;
- ret = accel_list[i].init(mc);
- if (ret < 0) {
- init_failed = true;
- fprintf(stderr, "failed to initialize %s: %s\n",
- accel_list[i].name,
- strerror(-ret));
- *(accel_list[i].allowed) = false;
- } else {
- accel_initialised = true;
- }
- break;
- }
- }
- if (i == ARRAY_SIZE(accel_list)) {
- fprintf(stderr, "\"%s\" accelerator does not exist.\n", buf);
- }
- }
-
- if (!accel_initialised) {
- if (!init_failed) {
- fprintf(stderr, "No accelerator found!\n");
- }
- exit(1);
- }
-
- if (init_failed) {
- fprintf(stderr, "Back to %s accelerator.\n", accel_list[i].name);
- }
-
- return !accel_initialised;
-}
-
void qemu_add_exit_notifier(Notifier *notify)
{
notifier_list_add(&exit_notifiers, notify);
free(mem);
}
-static int object_set_property(const char *name, const char *value, void *opaque)
+static int machine_set_property(const char *name, const char *value,
+ void *opaque)
{
Object *obj = OBJECT(opaque);
StringInputVisitor *siv;
Error *local_err = NULL;
+ char *c, *qom_name;
- if (strcmp(name, "qom-type") == 0 || strcmp(name, "id") == 0 ||
- strcmp(name, "type") == 0) {
+ if (strcmp(name, "type") == 0) {
return 0;
}
+ qom_name = g_strdup(name);
+ c = qom_name;
+ while (*c++) {
+ if (*c == '_') {
+ *c = '-';
+ }
+ }
+
siv = string_input_visitor_new(value);
- object_property_set(obj, string_input_get_visitor(siv), name, &local_err);
+ object_property_set(obj, string_input_get_visitor(siv), qom_name, &local_err);
string_input_visitor_cleanup(siv);
+ g_free(qom_name);
if (local_err) {
qerror_report_err(local_err);
g_free(dummy);
if (err) {
qerror_report_err(err);
+ error_free(err);
return -1;
}
return 0;
{
int i;
int snapshot, linux_boot;
- const char *icount_option = NULL;
const char *initrd_filename;
const char *kernel_filename, *kernel_cmdline;
const char *boot_order;
DisplayState *ds;
int cyls, heads, secs, translation;
- QemuOpts *hda_opts = NULL, *opts, *machine_opts;
+ QemuOpts *hda_opts = NULL, *opts, *machine_opts, *icount_opts = NULL;
QemuOptsList *olist;
int optind;
const char *optarg;
1024 * 1024;
ram_addr_t maxram_size = default_ram_size;
uint64_t ram_slots = 0;
+ FILE *vmstate_dump_file = NULL;
+ Error *main_loop_err = NULL;
atexit(qemu_run_exit_notifiers);
error_set_progname(argv[0]);
qemu_add_opts(&qemu_msg_opts);
qemu_add_opts(&qemu_name_opts);
qemu_add_opts(&qemu_numa_opts);
+ qemu_add_opts(&qemu_icount_opts);
runstate_init();
rtc_clock = QEMU_CLOCK_HOST;
- qemu_init_auxval(envp);
- qemu_cache_utils_init();
-
QLIST_INIT (&vm_change_state_head);
os_setup_early_signal_handling();
for (i = 0; i < MAX_NODES; i++) {
numa_info[i].node_mem = 0;
+ numa_info[i].present = false;
bitmap_zero(numa_info[i].node_cpu, MAX_CPUMASK_BITS);
}
nb_numa_nodes = 0;
+ max_numa_nodeid = 0;
nb_nics = 0;
bdrv_init_with_whitelist();
error_report("ram size too large");
exit(EXIT_FAILURE);
}
+ maxram_size = ram_size;
maxmem_str = qemu_opt_get(opts, "maxmem");
slots_str = qemu_opt_get(opts, "slots");
sz = qemu_opt_get_size(opts, "maxmem", 0);
if (sz < ram_size) {
- fprintf(stderr, "qemu: invalid -m option value: maxmem "
- "(%" PRIu64 ") <= initial memory ("
- RAM_ADDR_FMT ")\n", sz, ram_size);
+ error_report("invalid -m option value: maxmem "
+ "(0x%" PRIx64 ") <= initial memory (0x"
+ RAM_ADDR_FMT ")", sz, ram_size);
exit(EXIT_FAILURE);
}
slots = qemu_opt_get_number(opts, "slots", 0);
if ((sz > ram_size) && !slots) {
- fprintf(stderr, "qemu: invalid -m option value: maxmem "
- "(%" PRIu64 ") more than initial memory ("
+ error_report("invalid -m option value: maxmem "
+ "(0x%" PRIx64 ") more than initial memory (0x"
RAM_ADDR_FMT ") but no hotplug slots where "
- "specified\n", sz, ram_size);
+ "specified", sz, ram_size);
exit(EXIT_FAILURE);
}
if ((sz <= ram_size) && slots) {
- fprintf(stderr, "qemu: invalid -m option value: %"
+ error_report("invalid -m option value: %"
PRIu64 " hotplug slots where specified but "
- "maxmem (%" PRIu64 ") <= initial memory ("
- RAM_ADDR_FMT ")\n", slots, sz, ram_size);
+ "maxmem (0x%" PRIx64 ") <= initial memory (0x"
+ RAM_ADDR_FMT ")", slots, sz, ram_size);
exit(EXIT_FAILURE);
}
maxram_size = sz;
ram_slots = slots;
} else if ((!maxmem_str && slots_str) ||
(maxmem_str && !slots_str)) {
- fprintf(stderr, "qemu: invalid -m option value: missing "
- "'%s' option\n", slots_str ? "maxmem" : "slots");
+ error_report("invalid -m option value: missing "
+ "'%s' option", slots_str ? "maxmem" : "slots");
exit(EXIT_FAILURE);
}
break;
}
break;
case QEMU_OPTION_icount:
- icount_option = optarg;
+ icount_opts = qemu_opts_parse(qemu_find_opts("icount"),
+ optarg, 1);
+ if (!icount_opts) {
+ exit(1);
+ }
break;
case QEMU_OPTION_incoming:
incoming = optarg;
if (!opts) {
exit(1);
}
- configure_realtime(opts);
+ enable_mlock = qemu_opt_get_bool(opts, "mlock", true);
break;
case QEMU_OPTION_msg:
opts = qemu_opts_parse(qemu_find_opts("msg"), optarg, 0);
}
configure_msg(opts);
break;
+ case QEMU_OPTION_dump_vmstate:
+ vmstate_dump_file = fopen(optarg, "w");
+ if (vmstate_dump_file == NULL) {
+ fprintf(stderr, "open %s: %s\n", optarg, strerror(errno));
+ exit(1);
+ }
+ break;
default:
os_parse_cmd_args(popt->index, optarg);
}
os_daemonize();
- if (qemu_init_main_loop()) {
- fprintf(stderr, "qemu_init_main_loop failed\n");
+ if (qemu_init_main_loop(&main_loop_err)) {
+ error_report("%s", error_get_pretty(main_loop_err));
exit(1);
}
exit(1);
}
- cpu_exec_init_all();
-
current_machine = MACHINE(object_new(object_class_get_name(
OBJECT_CLASS(machine_class))));
object_property_add_child(object_get_root(), "machine",
OBJECT(current_machine), &error_abort);
+ cpu_exec_init_all();
if (machine_class->hw_version) {
qemu_set_version(machine_class->hw_version);
}
- if (qemu_opts_foreach(qemu_find_opts("object"),
- object_create, NULL, 0) != 0) {
- exit(1);
- }
-
/* Init CPU def lists, based on config
* - Must be called after all the qemu_read_config_file() calls
* - Must be called before list_cpus()
exit(0);
}
+ if (qemu_opts_foreach(qemu_find_opts("object"),
+ object_create, NULL, 0) != 0) {
+ exit(1);
+ }
+
machine_opts = qemu_get_machine_opts();
- if (qemu_opt_foreach(machine_opts, object_set_property, current_machine,
+ if (qemu_opt_foreach(machine_opts, machine_set_property, current_machine,
1) < 0) {
object_unref(OBJECT(current_machine));
exit(1);
}
- configure_accelerator(machine_class);
+ configure_accelerator(current_machine);
if (qtest_chrdev) {
Error *local_err = NULL;
qemu_spice_init();
#endif
- if (icount_option && (kvm_enabled() || xen_enabled())) {
- fprintf(stderr, "-icount is not allowed with kvm or xen\n");
- exit(1);
+ cpu_ticks_init();
+ if (icount_opts) {
+ if (kvm_enabled() || xen_enabled()) {
+ fprintf(stderr, "-icount is not allowed with kvm or xen\n");
+ exit(1);
+ }
+ configure_icount(icount_opts, &error_abort);
+ qemu_opts_del(icount_opts);
}
- configure_icount(icount_option);
/* clean up network at qemu process termination */
atexit(&net_cleanup);
blk_mig_init();
ram_mig_init();
+ /* If the currently selected machine wishes to override the units-per-bus
+ * property of its default HBA interface type, do so now. */
+ if (machine_class->units_per_default_bus) {
+ override_max_devs(machine_class->block_default_type,
+ machine_class->units_per_default_bus);
+ }
+
/* open the virtual block devices */
if (snapshot)
qemu_opts_foreach(qemu_find_opts("drive"), drive_enable_snapshot, NULL, 0);
machine_class->init(current_machine);
+ realtime_init();
+
audio_init();
cpu_synchronize_all_post_init();
if (qemu_opts_foreach(qemu_find_opts("device"), device_init_func, NULL, 1) != 0)
exit(1);
+ /* Did we create any drives that we failed to create a device for? */
+ drive_check_orphaned();
+
net_check_clients();
ds = init_displaystate();
}
}
- qdev_prop_check_global();
+ qdev_prop_check_globals();
+ if (vmstate_dump_file) {
+ /* dump and exit */
+ dump_vmstate_json_to_file(vmstate_dump_file);
+ return 0;
+ }
if (incoming) {
Error *local_err = NULL;