* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-#include <unistd.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <time.h>
-#include <errno.h>
-#include <sys/time.h>
+#include "qemu/osdep.h"
-#include "config-host.h"
#ifdef CONFIG_SECCOMP
#include "sysemu/seccomp.h"
#include "qemu/queue.h"
#include "sysemu/cpus.h"
#include "sysemu/arch_init.h"
-#include "qemu/osdep.h"
#include "ui/qemu-spice.h"
#include "qapi/string-input-visitor.h"
#include "qapi-event.h"
#include "exec/semihost.h"
#include "crypto/init.h"
+#include "sysemu/replay.h"
+#include "qapi/qmp/qerror.h"
#define MAX_VIRTIO_CONSOLES 1
#define MAX_SCLP_CONSOLES 1
{ .driver = "ide-drive", .flag = &default_cdrom },
{ .driver = "scsi-cd", .flag = &default_cdrom },
{ .driver = "virtio-serial-pci", .flag = &default_virtcon },
- { .driver = "virtio-serial-s390", .flag = &default_virtcon },
{ .driver = "virtio-serial", .flag = &default_virtcon },
{ .driver = "VGA", .flag = &default_vga },
{ .driver = "isa-vga", .flag = &default_vga },
static QemuOptsList qemu_trace_opts = {
.name = "trace",
- .implied_opt_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 = "sleep",
.type = QEMU_OPT_BOOL,
+ }, {
+ .name = "rr",
+ .type = QEMU_OPT_STRING,
+ }, {
+ .name = "rrfile",
+ .type = QEMU_OPT_STRING,
},
{ /* end of list */ }
},
static RunState current_run_state = RUN_STATE_PRELAUNCH;
-/* We use RUN_STATE_MAX but any invalid value will do */
-static RunState vmstop_requested = RUN_STATE_MAX;
+/* We use RUN_STATE__MAX but any invalid value will do */
+static RunState vmstop_requested = RUN_STATE__MAX;
static QemuMutex vmstop_lock;
typedef struct {
/* from -> to */
{ RUN_STATE_DEBUG, RUN_STATE_RUNNING },
{ RUN_STATE_DEBUG, RUN_STATE_FINISH_MIGRATE },
+ { RUN_STATE_DEBUG, RUN_STATE_PRELAUNCH },
{ RUN_STATE_INMIGRATE, RUN_STATE_INTERNAL_ERROR },
{ RUN_STATE_INMIGRATE, RUN_STATE_IO_ERROR },
{ RUN_STATE_INMIGRATE, RUN_STATE_WATCHDOG },
{ RUN_STATE_INMIGRATE, RUN_STATE_GUEST_PANICKED },
{ RUN_STATE_INMIGRATE, RUN_STATE_FINISH_MIGRATE },
+ { RUN_STATE_INMIGRATE, RUN_STATE_PRELAUNCH },
+ { RUN_STATE_INMIGRATE, RUN_STATE_POSTMIGRATE },
{ RUN_STATE_INTERNAL_ERROR, RUN_STATE_PAUSED },
{ RUN_STATE_INTERNAL_ERROR, RUN_STATE_FINISH_MIGRATE },
+ { RUN_STATE_INTERNAL_ERROR, RUN_STATE_PRELAUNCH },
{ RUN_STATE_IO_ERROR, RUN_STATE_RUNNING },
{ RUN_STATE_IO_ERROR, RUN_STATE_FINISH_MIGRATE },
+ { RUN_STATE_IO_ERROR, RUN_STATE_PRELAUNCH },
{ RUN_STATE_PAUSED, RUN_STATE_RUNNING },
{ RUN_STATE_PAUSED, RUN_STATE_FINISH_MIGRATE },
+ { RUN_STATE_PAUSED, RUN_STATE_PRELAUNCH },
{ RUN_STATE_POSTMIGRATE, RUN_STATE_RUNNING },
{ RUN_STATE_POSTMIGRATE, RUN_STATE_FINISH_MIGRATE },
+ { RUN_STATE_POSTMIGRATE, RUN_STATE_PRELAUNCH },
{ RUN_STATE_PRELAUNCH, RUN_STATE_RUNNING },
{ RUN_STATE_PRELAUNCH, RUN_STATE_FINISH_MIGRATE },
{ RUN_STATE_FINISH_MIGRATE, RUN_STATE_RUNNING },
{ RUN_STATE_FINISH_MIGRATE, RUN_STATE_POSTMIGRATE },
+ { RUN_STATE_FINISH_MIGRATE, RUN_STATE_PRELAUNCH },
{ RUN_STATE_RESTORE_VM, RUN_STATE_RUNNING },
+ { RUN_STATE_RESTORE_VM, RUN_STATE_PRELAUNCH },
{ RUN_STATE_RUNNING, RUN_STATE_DEBUG },
{ RUN_STATE_RUNNING, RUN_STATE_INTERNAL_ERROR },
{ RUN_STATE_SHUTDOWN, RUN_STATE_PAUSED },
{ RUN_STATE_SHUTDOWN, RUN_STATE_FINISH_MIGRATE },
+ { RUN_STATE_SHUTDOWN, RUN_STATE_PRELAUNCH },
{ RUN_STATE_DEBUG, RUN_STATE_SUSPENDED },
{ RUN_STATE_RUNNING, RUN_STATE_SUSPENDED },
{ RUN_STATE_SUSPENDED, RUN_STATE_RUNNING },
{ RUN_STATE_SUSPENDED, RUN_STATE_FINISH_MIGRATE },
+ { RUN_STATE_SUSPENDED, RUN_STATE_PRELAUNCH },
{ RUN_STATE_WATCHDOG, RUN_STATE_RUNNING },
{ RUN_STATE_WATCHDOG, RUN_STATE_FINISH_MIGRATE },
+ { RUN_STATE_WATCHDOG, RUN_STATE_PRELAUNCH },
{ RUN_STATE_GUEST_PANICKED, RUN_STATE_RUNNING },
{ RUN_STATE_GUEST_PANICKED, RUN_STATE_FINISH_MIGRATE },
+ { RUN_STATE_GUEST_PANICKED, RUN_STATE_PRELAUNCH },
- { RUN_STATE_MAX, RUN_STATE_MAX },
+ { RUN_STATE__MAX, RUN_STATE__MAX },
};
-static bool runstate_valid_transitions[RUN_STATE_MAX][RUN_STATE_MAX];
+static bool runstate_valid_transitions[RUN_STATE__MAX][RUN_STATE__MAX];
bool runstate_check(RunState state)
{
const RunStateTransition *p;
memset(&runstate_valid_transitions, 0, sizeof(runstate_valid_transitions));
- for (p = &runstate_transitions_def[0]; p->from != RUN_STATE_MAX; p++) {
+ for (p = &runstate_transitions_def[0]; p->from != RUN_STATE__MAX; p++) {
runstate_valid_transitions[p->from][p->to] = true;
}
/* This function will abort() on invalid state transitions */
void runstate_set(RunState new_state)
{
- assert(new_state < RUN_STATE_MAX);
+ 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]);
+ error_report("invalid runstate transition: '%s' -> '%s'",
+ RunState_lookup[current_run_state],
+ RunState_lookup[new_state]);
abort();
}
trace_runstate_set(new_state);
{
qemu_mutex_lock(&vmstop_lock);
*r = vmstop_requested;
- vmstop_requested = RUN_STATE_MAX;
+ vmstop_requested = RUN_STATE__MAX;
qemu_mutex_unlock(&vmstop_lock);
- return *r < RUN_STATE_MAX;
+ return *r < RUN_STATE__MAX;
}
void qemu_system_vmstop_request_prepare(void)
RunState requested;
qemu_vmstop_requested(&requested);
- if (runstate_is_running() && requested == RUN_STATE_MAX) {
+ if (runstate_is_running() && requested == RUN_STATE__MAX) {
return;
}
rtc_start_date = mktimegm(&tm);
if (rtc_start_date == -1) {
date_fail:
- fprintf(stderr, "Invalid date format. Valid formats are:\n"
- "'2006-06-17T16:01:21' or '2006-06-17'\n");
+ error_report("invalid date 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;
if (!strcmp(value, "utc")) {
rtc_utc = 1;
} else if (!strcmp(value, "localtime")) {
+ Error *blocker = NULL;
rtc_utc = 0;
+ error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED,
+ "-rtc base=localtime");
+ replay_add_blocker(blocker);
} else {
configure_rtc_date_offset(value, 0);
}
} else if (!strcmp(value, "vm")) {
rtc_clock = QEMU_CLOCK_VIRTUAL;
} else {
- fprintf(stderr, "qemu: invalid option value '%s'\n", value);
+ error_report("invalid option value '%s'", value);
exit(1);
}
}
} else if (!strcmp(value, "none")) {
/* discard is default */
} else {
- fprintf(stderr, "qemu: invalid option value '%s'\n", value);
+ error_report("invalid option value '%s'", value);
exit(1);
}
}
bdaddr_t bdaddr;
if (nb_hcis >= MAX_NICS) {
- fprintf(stderr, "qemu: Too many bluetooth HCIs (max %i).\n", MAX_NICS);
+ error_report("too many bluetooth HCIs (max %i)", MAX_NICS);
return -1;
}
struct bt_scatternet_s *vlan = qemu_find_bt_vlan(vlan_id);
if (!vlan->slave)
- fprintf(stderr, "qemu: warning: adding a VHCI to "
- "an empty scatternet %i\n", vlan_id);
+ error_report("warning: adding a VHCI to an empty scatternet %i",
+ vlan_id);
bt_vhci_init(bt_new_hci(vlan));
}
if (endp) {
vlan_id = strtol(endp + 6, &endp, 0);
if (*endp) {
- fprintf(stderr, "qemu: unrecognised bluetooth vlan Id\n");
+ error_report("unrecognised bluetooth vlan Id");
return 0;
}
}
vlan = qemu_find_bt_vlan(vlan_id);
if (!vlan->slave)
- fprintf(stderr, "qemu: warning: adding a slave device to "
- "an empty scatternet %i\n", vlan_id);
+ error_report("warning: adding a slave device to an empty scatternet %i",
+ vlan_id);
if (!strcmp(devname, "keyboard"))
return bt_keyboard_init(vlan);
- fprintf(stderr, "qemu: unsupported bluetooth device `%s'\n", devname);
+ error_report("unsupported bluetooth device '%s'", devname);
return 0;
}
if (strstart(endp, ",vlan=", &p)) {
vlan = strtol(p, (char **) &endp, 0);
if (*endp) {
- fprintf(stderr, "qemu: bad scatternet '%s'\n", p);
+ error_report("bad scatternet '%s'", p);
return 1;
}
} else {
- fprintf(stderr, "qemu: bad parameter '%s'\n", endp + 1);
+ error_report("bad parameter '%s'", endp + 1);
return 1;
}
} else
} else if (strstart(opt, "device:", &endp))
return !bt_device_add(endp);
- fprintf(stderr, "qemu: bad bluetooth parameter '%s'\n", opt);
+ error_report("bad bluetooth parameter '%s'", opt);
return 1;
}
return -1;
}
#else
- error_report("sandboxing request but seccomp is not compiled "
- "into this build");
+ error_report("seccomp support is disabled");
return -1;
#endif
}
}
#endif
if (dupfd == -1) {
- error_report("Error duplicating fd: %s", strerror(errno));
+ error_report("error duplicating fd: %s", strerror(errno));
return -1;
}
} else if (threads == 0) {
threads = cpus / (cores * sockets);
} else if (sockets * cores * threads < cpus) {
- fprintf(stderr, "cpu topology: error: "
- "sockets (%u) * cores (%u) * threads (%u) < "
- "smp_cpus (%u)\n",
- sockets, cores, threads, cpus);
+ error_report("cpu topology: "
+ "sockets (%u) * cores (%u) * threads (%u) < "
+ "smp_cpus (%u)",
+ sockets, cores, threads, cpus);
exit(1);
}
max_cpus = qemu_opt_get_number(opts, "maxcpus", cpus);
if (sockets * cores * threads > max_cpus) {
- fprintf(stderr, "cpu topology: error: "
- "sockets (%u) * cores (%u) * threads (%u) > maxcpus (%u)\n",
- sockets, cores, threads, max_cpus);
+ error_report("cpu topology: "
+ "sockets (%u) * cores (%u) * threads (%u) > "
+ "maxcpus (%u)",
+ sockets, cores, threads, max_cpus);
exit(1);
}
}
if (max_cpus > MAX_CPUMASK_BITS) {
- fprintf(stderr, "Unsupported number of maxcpus\n");
+ error_report("unsupported number of maxcpus");
exit(1);
}
if (max_cpus < smp_cpus) {
- fprintf(stderr, "maxcpus must be equal to or greater than smp\n");
+ error_report("maxcpus must be equal to or greater than smp");
exit(1);
}
+ if (smp_cpus > 1 || smp_cores > 1 || smp_threads > 1) {
+ Error *blocker = NULL;
+ error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED, "smp");
+ replay_add_blocker(blocker);
+ }
}
static void realtime_init(void)
{
if (enable_mlock) {
if (os_mlock() < 0) {
- fprintf(stderr, "qemu: locking memory failed\n");
+ error_report("locking memory failed");
exit(1);
}
}
int r;
r = usb_device_add(cmdline);
if (r < 0) {
- fprintf(stderr, "qemu: could not add USB device '%s'\n", cmdline);
+ error_report("could not add USB device '%s'", cmdline);
}
return r;
}
static int machine_help_func(QemuOpts *opts, MachineState *machine)
{
ObjectProperty *prop;
+ ObjectPropertyIterator iter;
if (!qemu_opt_has_help_opt(opts)) {
return 0;
}
- QTAILQ_FOREACH(prop, &OBJECT(machine)->properties, node) {
+ object_property_iter_init(&iter, OBJECT(machine));
+ while ((prop = object_property_iter_next(&iter))) {
if (!prop->set) {
continue;
}
static void qemu_kill_report(void)
{
if (!qtest_driver() && shutdown_signal != -1) {
- fprintf(stderr, "qemu: terminating on signal %d", shutdown_signal);
if (shutdown_pid == 0) {
/* This happens for eg ^C at the terminal, so it's worth
* avoiding printing an odd message in that case.
*/
- fputc('\n', stderr);
+ error_report("terminating on signal %d", shutdown_signal);
} else {
- fprintf(stderr, " from pid " FMT_pid "\n", shutdown_pid);
+ error_report("terminating on signal %d from pid " FMT_pid,
+ shutdown_signal, shutdown_pid);
}
shutdown_signal = -1;
}
static int qemu_reset_requested(void)
{
int r = reset_requested;
- reset_requested = 0;
- return r;
+ if (r && replay_checkpoint(CHECKPOINT_RESET_REQUESTED)) {
+ reset_requested = 0;
+ return r;
+ }
+ return false;
}
static int qemu_suspend_requested(void)
{
int r = suspend_requested;
- suspend_requested = 0;
- return r;
+ if (r && replay_checkpoint(CHECKPOINT_SUSPEND_REQUESTED)) {
+ suspend_requested = 0;
+ return r;
+ }
+ return false;
}
static WakeupReason qemu_wakeup_requested(void)
shutdown_signal = signal;
shutdown_pid = pid;
no_shutdown = 0;
- qemu_system_shutdown_request();
+
+ /* Cannot call qemu_system_shutdown_request directly because
+ * we are in a signal handler.
+ */
+ shutdown_requested = 1;
+ qemu_notify_event();
}
void qemu_system_shutdown_request(void)
{
trace_qemu_system_shutdown_request();
+ replay_shutdown_request();
shutdown_requested = 1;
qemu_notify_event();
}
cpu_synchronize_all_states();
qemu_system_reset(VMRESET_REPORT);
resume_all_vcpus();
- if (runstate_needs_reset()) {
- runstate_set(RUN_STATE_PAUSED);
+ if (!runstate_check(RUN_STATE_RUNNING) &&
+ !runstate_check(RUN_STATE_INMIGRATE)) {
+ runstate_set(RUN_STATE_PRELAUNCH);
}
}
if (qemu_wakeup_requested()) {
if (vga_available()) {
vga_interface_type = VGA_STD;
} else {
- fprintf(stderr, "Error: standard VGA not available\n");
+ error_report("standard VGA not available");
exit(0);
}
} else if (strstart(p, "cirrus", &opts)) {
if (cirrus_vga_available()) {
vga_interface_type = VGA_CIRRUS;
} else {
- fprintf(stderr, "Error: Cirrus VGA not available\n");
+ error_report("Cirrus VGA not available");
exit(0);
}
} else if (strstart(p, "vmware", &opts)) {
if (vmware_vga_available()) {
vga_interface_type = VGA_VMWARE;
} else {
- fprintf(stderr, "Error: VMWare SVGA not available\n");
+ error_report("VMWare SVGA not available");
exit(0);
}
} else if (strstart(p, "virtio", &opts)) {
if (virtio_vga_available()) {
vga_interface_type = VGA_VIRTIO;
} else {
- fprintf(stderr, "Error: Virtio VGA not available\n");
+ error_report("Virtio VGA not available");
exit(0);
}
} else if (strstart(p, "xenfb", &opts)) {
if (qxl_vga_available()) {
vga_interface_type = VGA_QXL;
} else {
- fprintf(stderr, "Error: QXL VGA not available\n");
+ error_report("QXL VGA not available");
exit(0);
}
} else if (strstart(p, "tcx", &opts)) {
if (tcx_vga_available()) {
vga_interface_type = VGA_TCX;
} else {
- fprintf(stderr, "Error: TCX framebuffer not available\n");
+ error_report("TCX framebuffer not available");
exit(0);
}
} else if (strstart(p, "cg3", &opts)) {
if (cg3_vga_available()) {
vga_interface_type = VGA_CG3;
} else {
- fprintf(stderr, "Error: CG3 framebuffer not available\n");
+ error_report("CG3 framebuffer not available");
exit(0);
}
} else if (!strstart(p, "none", &opts)) {
invalid_vga:
- fprintf(stderr, "Unknown vga type: %s\n", p);
+ error_report("unknown vga type: %s", p);
exit(1);
}
while (*opts) {
}
} else {
invalid_sdl_args:
- error_report("Invalid SDL option string");
+ error_report("invalid SDL option string");
exit(1);
}
opts = nextopt;
#ifdef CONFIG_CURSES
display = DT_CURSES;
#else
- error_report("Curses support is disabled");
+ error_report("curses support is disabled");
exit(1);
#endif
} else if (strstart(p, "gtk", &opts)) {
}
} else {
invalid_gtk_args:
- error_report("Invalid GTK option string");
+ error_report("invalid GTK option string");
exit(1);
}
opts = nextopt;
} else if (strstart(p, "none", &opts)) {
display = DT_NONE;
} else {
- error_report("Unknown display type");
+ error_report("unknown display type");
exit(1);
}
return -1;
}
if (strncmp(name, "opt/", 4) != 0) {
- error_report("WARNING: externally provided fw_cfg item names "
- "should be prefixed with \"opt/\"!");
+ error_report("warning: externally provided fw_cfg item names "
+ "should be prefixed with \"opt/\"");
}
if (nonempty_str(str)) {
size = strlen(str); /* NUL terminator NOT included in fw_cfg blob */
} else if (strcmp(mode, "control") == 0) {
flags = MONITOR_USE_CONTROL;
} else {
- fprintf(stderr, "unknown monitor mode \"%s\"\n", mode);
+ error_report("unknown monitor mode \"%s\"", mode);
exit(1);
}
chardev = qemu_opt_get(opts, "chardev");
chr = qemu_chr_find(chardev);
if (chr == NULL) {
- fprintf(stderr, "chardev \"%s\" not found\n", chardev);
+ error_report("chardev \"%s\" not found", chardev);
exit(1);
}
}
opts = qemu_chr_parse_compat(label, optarg);
if (!opts) {
- fprintf(stderr, "parse error: %s\n", optarg);
+ error_report("parse error: %s", optarg);
exit(1);
}
}
if (strcmp(devname, "none") == 0)
return 0;
if (index == MAX_SERIAL_PORTS) {
- fprintf(stderr, "qemu: too many serial ports\n");
+ error_report("too many serial ports");
exit(1);
}
snprintf(label, sizeof(label), "serial%d", index);
serial_hds[index] = qemu_chr_new(label, devname, NULL);
if (!serial_hds[index]) {
- fprintf(stderr, "qemu: could not connect serial device"
- " to character backend '%s'\n", devname);
+ error_report("could not connect serial device"
+ " to character backend '%s'", devname);
return -1;
}
index++;
if (strcmp(devname, "none") == 0)
return 0;
if (index == MAX_PARALLEL_PORTS) {
- fprintf(stderr, "qemu: too many parallel ports\n");
+ error_report("too many parallel ports");
exit(1);
}
snprintf(label, sizeof(label), "parallel%d", index);
parallel_hds[index] = qemu_chr_new(label, devname, NULL);
if (!parallel_hds[index]) {
- fprintf(stderr, "qemu: could not connect parallel device"
- " to character backend '%s'\n", devname);
+ error_report("could not connect parallel device"
+ " to character backend '%s'", devname);
return -1;
}
index++;
if (strcmp(devname, "none") == 0)
return 0;
if (index == MAX_VIRTIO_CONSOLES) {
- fprintf(stderr, "qemu: too many virtio consoles\n");
+ error_report("too many virtio consoles");
exit(1);
}
bus_opts = qemu_opts_create(device, NULL, 0, &error_abort);
- if (arch_type == QEMU_ARCH_S390X) {
- qemu_opt_set(bus_opts, "driver", "virtio-serial-s390", &error_abort);
- } else {
- qemu_opt_set(bus_opts, "driver", "virtio-serial-pci", &error_abort);
- }
+ qemu_opt_set(bus_opts, "driver", "virtio-serial", &error_abort);
dev_opts = qemu_opts_create(device, NULL, 0, &error_abort);
qemu_opt_set(dev_opts, "driver", "virtconsole", &error_abort);
snprintf(label, sizeof(label), "virtcon%d", index);
virtcon_hds[index] = qemu_chr_new(label, devname, NULL);
if (!virtcon_hds[index]) {
- fprintf(stderr, "qemu: could not connect virtio console"
- " to character backend '%s'\n", devname);
+ error_report("could not connect virtio console"
+ " to character backend '%s'", devname);
return -1;
}
qemu_opt_set(dev_opts, "chardev", label, &error_abort);
return 0;
}
if (index == MAX_SCLP_CONSOLES) {
- fprintf(stderr, "qemu: too many sclp consoles\n");
+ error_report("too many sclp consoles");
exit(1);
}
snprintf(label, sizeof(label), "sclpcon%d", index);
sclp_hds[index] = qemu_chr_new(label, devname, NULL);
if (!sclp_hds[index]) {
- fprintf(stderr, "qemu: could not connect sclp console"
- " to character backend '%s'\n", devname);
+ error_report("could not connect sclp console"
+ " to character backend '%s'", devname);
return -1;
}
qemu_opt_set(dev_opts, "chardev", label, &error_abort);
}
opts = qemu_opts_create(qemu_find_opts("device"), "debugcon", 1, NULL);
if (!opts) {
- fprintf(stderr, "qemu: already have a debugcon device\n");
+ error_report("already have a debugcon device");
exit(1);
}
qemu_opt_set(opts, "driver", "isa-debugcon", &error_abort);
return mc;
}
if (name && !is_help_option(name)) {
- error_report("Unsupported machine type");
- error_printf("Use -machine help to list supported machines!\n");
+ error_report("unsupported machine type");
+ error_printf("Use -machine help to list supported machines\n");
} else {
printf("Supported machines are:\n");
machines = g_slist_sort(machines, machine_class_cmp);
return popt;
}
+static MachineClass *select_machine(void)
+{
+ MachineClass *machine_class = find_default_machine();
+ const char *optarg;
+ QemuOpts *opts;
+ Location loc;
+
+ loc_push_none(&loc);
+
+ opts = qemu_get_machine_opts();
+ qemu_opts_loc_restore(opts);
+
+ optarg = qemu_opt_get(opts, "type");
+ if (optarg) {
+ machine_class = machine_parse(optarg);
+ }
+
+ if (!machine_class) {
+ error_report("No machine specified, and there is no default");
+ error_printf("Use -machine help to list supported machines\n");
+ exit(1);
+ }
+
+ loc_pop(&loc);
+ return machine_class;
+}
+
static int machine_set_property(void *opaque,
const char *name, const char *value,
Error **errp)
return false;
}
- if (g_str_equal(type, "filter-buffer")) {
+ /*
+ * return false for concrete netfilters since
+ * they depend on netdevs already existing
+ */
+ if (g_str_equal(type, "filter-buffer") ||
+ g_str_equal(type, "filter-dump")) {
return false;
}
}
-static int object_create(void *opaque, QemuOpts *opts, Error **errp)
-{
- Error *err = NULL;
- char *type = NULL;
- char *id = NULL;
- void *dummy = NULL;
- OptsVisitor *ov;
- QDict *pdict;
- bool (*type_predicate)(const char *) = opaque;
-
- ov = opts_visitor_new(opts);
- pdict = qemu_opts_to_qdict(opts, NULL);
-
- visit_start_struct(opts_get_visitor(ov), &dummy, NULL, NULL, 0, &err);
- if (err) {
- goto out;
- }
-
- qdict_del(pdict, "qom-type");
- visit_type_str(opts_get_visitor(ov), &type, "qom-type", &err);
- if (err) {
- goto out;
- }
- if (!type_predicate(type)) {
- goto out;
- }
-
- qdict_del(pdict, "id");
- visit_type_str(opts_get_visitor(ov), &id, "id", &err);
- if (err) {
- goto out;
- }
-
- object_add(type, id, pdict, opts_get_visitor(ov), &err);
- if (err) {
- goto out;
- }
- visit_end_struct(opts_get_visitor(ov), &err);
- if (err) {
- qmp_object_del(id, NULL);
- }
-
-out:
- opts_visitor_cleanup(ov);
-
- QDECREF(pdict);
- g_free(id);
- g_free(type);
- g_free(dummy);
- if (err) {
- error_report_err(err);
- return -1;
- }
- return 0;
-}
-
static void set_memory_options(uint64_t *ram_slots, ram_addr_t *maxram_size,
MachineClass *mc)
{
const char *maxmem_str, *slots_str;
const ram_addr_t default_ram_size = mc->default_ram_size;
QemuOpts *opts = qemu_find_opts_singleton("memory");
+ Location loc;
+
+ loc_push_none(&loc);
+ qemu_opts_loc_restore(opts);
sz = 0;
mem_str = qemu_opt_get(opts, "size");
"'%s' option", slots_str ? "maxmem" : "slots");
exit(EXIT_FAILURE);
}
+
+ loc_pop(&loc);
}
int main(int argc, char **argv, char **envp)
bool userconfig = true;
const char *log_mask = NULL;
const char *log_file = NULL;
- const char *trace_events = NULL;
- const char *trace_file = NULL;
+ char *trace_file = NULL;
ram_addr_t maxram_size;
uint64_t ram_slots = 0;
FILE *vmstate_dump_file = NULL;
runstate_init();
if (qcrypto_init(&err) < 0) {
- fprintf(stderr, "Cannot initialize crypto: %s\n",
- error_get_pretty(err));
+ error_reportf_err(err, "cannot initialize crypto: ");
exit(1);
}
rtc_clock = QEMU_CLOCK_HOST;
os_setup_early_signal_handling();
module_call_init(MODULE_INIT_MACHINE);
- machine_class = find_default_machine();
cpu_model = NULL;
snapshot = 0;
cyls = heads = secs = 0;
}
} else if (*p != '\0') {
chs_fail:
- fprintf(stderr, "qemu: invalid physical CHS format\n");
+ error_report("invalid physical CHS format");
exit(1);
}
if (hda_opts != NULL) {
#ifdef CONFIG_CURSES
display_type = DT_CURSES;
#else
- fprintf(stderr, "Curses support is disabled\n");
+ error_report("curses support is disabled");
exit(1);
#endif
break;
graphic_rotate = strtol(optarg, (char **) &optarg, 10);
if (graphic_rotate != 0 && graphic_rotate != 90 &&
graphic_rotate != 180 && graphic_rotate != 270) {
- fprintf(stderr,
- "qemu: only 90, 180, 270 deg rotation is available\n");
+ error_report("only 90, 180, 270 deg rotation is available");
exit(1);
}
break;
#endif
#ifdef CONFIG_SLIRP
case QEMU_OPTION_tftp:
+ error_report("The -tftp option is deprecated. "
+ "Please use '-netdev user,tftp=...' instead.");
legacy_tftp_prefix = optarg;
break;
case QEMU_OPTION_bootp:
+ error_report("The -bootp option is deprecated. "
+ "Please use '-netdev user,bootfile=...' instead.");
legacy_bootp_filename = optarg;
break;
case QEMU_OPTION_redir:
+ error_report("The -redir option is deprecated. "
+ "Please use '-netdev user,hostfwd=...' instead.");
if (net_slirp_redir(optarg) < 0)
exit(1);
break;
w = strtol(p, (char **)&p, 10);
if (w <= 0) {
graphic_error:
- fprintf(stderr, "qemu: invalid resolution or depth\n");
+ error_report("invalid resolution or depth");
exit(1);
}
if (*p != 'x')
case QEMU_OPTION_fsdev:
olist = qemu_find_opts("fsdev");
if (!olist) {
- fprintf(stderr, "fsdev is not supported by this qemu build.\n");
+ error_report("fsdev support is disabled");
exit(1);
}
opts = qemu_opts_parse_noisily(olist, optarg, true);
olist = qemu_find_opts("virtfs");
if (!olist) {
- fprintf(stderr, "virtfs is not supported by this qemu build.\n");
+ error_report("virtfs support is disabled");
exit(1);
}
opts = qemu_opts_parse_noisily(olist, optarg, true);
if (qemu_opt_get(opts, "fsdriver") == NULL ||
qemu_opt_get(opts, "mount_tag") == NULL) {
- fprintf(stderr, "Usage: -virtfs fsdriver,mount_tag=tag.\n");
+ error_report("Usage: -virtfs fsdriver,mount_tag=tag");
exit(1);
}
fsdev = qemu_opts_create(qemu_find_opts("fsdev"),
qemu_opt_get(opts, "mount_tag"),
1, NULL);
if (!fsdev) {
- fprintf(stderr, "duplicate fsdev id: %s\n",
- qemu_opt_get(opts, "mount_tag"));
+ error_report("duplicate fsdev id: %s",
+ qemu_opt_get(opts, "mount_tag"));
exit(1);
}
#ifdef CONFIG_SYNC_FILE_RANGE
qemu_opt_set(fsdev, "writeout", writeout, &error_abort);
#else
- fprintf(stderr, "writeout=immediate not supported on "
- "this platform\n");
+ error_report("writeout=immediate not supported "
+ "on this platform");
exit(1);
#endif
}
fsdev = qemu_opts_create(qemu_find_opts("fsdev"), "v_synth",
1, NULL);
if (!fsdev) {
- fprintf(stderr, "duplicate option: %s\n", "virtfs_synth");
+ error_report("duplicate option: %s", "virtfs_synth");
exit(1);
}
qemu_opt_set(fsdev, "fsdriver", "synth", &error_abort);
break;
case QEMU_OPTION_watchdog:
if (watchdog) {
- fprintf(stderr,
- "qemu: only one watchdog option may be given\n");
+ error_report("only one watchdog option may be given");
return 1;
}
watchdog = optarg;
break;
case QEMU_OPTION_watchdog_action:
if (select_watchdog_action(optarg) == -1) {
- fprintf(stderr, "Unknown -watchdog-action parameter\n");
+ error_report("unknown -watchdog-action parameter");
exit(1);
}
break;
display_type = DT_SDL;
break;
#else
- fprintf(stderr, "SDL support is disabled\n");
+ error_report("SDL support is disabled");
exit(1);
#endif
case QEMU_OPTION_pidfile:
qemu_opts_parse_noisily(olist, "accel=tcg", false);
break;
case QEMU_OPTION_no_kvm_pit: {
- fprintf(stderr, "Warning: KVM PIT can no longer be disabled "
- "separately.\n");
+ error_report("warning: ignoring deprecated option");
break;
}
case QEMU_OPTION_no_kvm_pit_reinjection: {
{ /* end of list */ }
};
- fprintf(stderr, "Warning: option deprecated, use "
- "lost_tick_policy property of kvm-pit instead.\n");
+ error_report("warning: deprecated, replaced by "
+ "-global kvm-pit.lost_tick_policy=discard");
qdev_prop_register_global_list(kvm_pit_lost_tick_policy);
break;
}
exit(1);
}
#else
- fprintf(stderr, "VNC support is disabled\n");
+ error_report("VNC support is disabled");
exit(1);
#endif
break;
break;
case QEMU_OPTION_balloon:
if (balloon_parse(optarg) < 0) {
- fprintf(stderr, "Unknown -balloon argument %s\n", optarg);
+ error_report("unknown -balloon argument %s", optarg);
exit(1);
}
break;
break;
case QEMU_OPTION_uuid:
if(qemu_uuid_parse(optarg, qemu_uuid) < 0) {
- fprintf(stderr, "Fail to parse UUID string."
- " Wrong format.\n");
+ error_report("failed to parse UUID string: wrong format");
exit(1);
}
qemu_uuid_set = true;
break;
case QEMU_OPTION_option_rom:
if (nb_option_roms >= MAX_OPTION_ROMS) {
- fprintf(stderr, "Too many option ROMs\n");
+ error_report("too many option ROMs");
exit(1);
}
opts = qemu_opts_parse_noisily(qemu_find_opts("option-rom"),
option_rom[nb_option_roms].bootindex =
qemu_opt_get_number(opts, "bootindex", -1);
if (!option_rom[nb_option_roms].name) {
- fprintf(stderr, "Option ROM file is not specified\n");
+ error_report("Option ROM file is not specified");
exit(1);
}
nb_option_roms++;
} else if (strcmp("auto", target) == 0) {
semihosting.target = SEMIHOSTING_TARGET_AUTO;
} else {
- fprintf(stderr, "Unsupported semihosting-config"
- " %s\n",
- optarg);
+ error_report("unsupported semihosting-config %s",
+ optarg);
exit(1);
}
} else {
qemu_opt_foreach(opts, add_semihosting_arg,
&semihosting, NULL);
} else {
- fprintf(stderr, "Unsupported semihosting-config %s\n",
- optarg);
+ error_report("unsupported semihosting-config %s", optarg);
exit(1);
}
break;
case QEMU_OPTION_tdf:
- fprintf(stderr, "Warning: user space PIT time drift fix "
- "is no longer supported.\n");
+ error_report("warning: ignoring deprecated option");
break;
case QEMU_OPTION_name:
opts = qemu_opts_parse_noisily(qemu_find_opts("name"),
break;
case QEMU_OPTION_prom_env:
if (nb_prom_envs >= MAX_PROM_ENVS) {
- fprintf(stderr, "Too many prom variables\n");
+ error_report("too many prom variables");
exit(1);
}
prom_envs[nb_prom_envs] = optarg;
case QEMU_OPTION_trace:
{
opts = qemu_opts_parse_noisily(qemu_find_opts("trace"),
- optarg, false);
+ optarg, true);
if (!opts) {
exit(1);
}
- trace_events = qemu_opt_get(opts, "events");
- trace_file = qemu_opt_get(opts, "file");
+ 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);
break;
}
case QEMU_OPTION_readconfig:
{
int ret = qemu_read_config_file(optarg);
if (ret < 0) {
- fprintf(stderr, "read config %s: %s\n", optarg,
- strerror(-ret));
+ error_report("read config %s: %s", optarg,
+ strerror(-ret));
exit(1);
}
break;
case QEMU_OPTION_spice:
olist = qemu_find_opts("spice");
if (!olist) {
- fprintf(stderr, "spice is not supported by this qemu build.\n");
+ error_report("spice support is disabled");
exit(1);
}
opts = qemu_opts_parse_noisily(olist, optarg, false);
} else {
fp = fopen(optarg, "w");
if (fp == NULL) {
- fprintf(stderr, "open %s: %s\n", optarg, strerror(errno));
+ error_report("open %s: %s", optarg,
+ strerror(errno));
exit(1);
}
}
break;
case QEMU_OPTION_dump_vmstate:
if (vmstate_dump_file) {
- fprintf(stderr, "qemu: only one '-dump-vmstate' "
- "option may be given\n");
+ error_report("only one '-dump-vmstate' "
+ "option may be given");
exit(1);
}
vmstate_dump_file = fopen(optarg, "w");
if (vmstate_dump_file == NULL) {
- fprintf(stderr, "open %s: %s\n", optarg, strerror(errno));
+ error_report("open %s: %s", optarg, strerror(errno));
exit(1);
}
break;
}
}
}
+ /*
+ * Clear error location left behind by the loop.
+ * Best done right after the loop. Do not insert code here!
+ */
+ loc_set_none();
- opts = qemu_get_machine_opts();
- optarg = qemu_opt_get(opts, "type");
- if (optarg) {
- machine_class = machine_parse(optarg);
- }
+ replay_configure(icount_opts);
- if (machine_class == NULL) {
- fprintf(stderr, "No machine specified, and there is no default.\n"
- "Use -machine help to list supported machines!\n");
- exit(1);
- }
+ machine_class = select_machine();
set_memory_options(&ram_slots, &maxram_size, machine_class);
- loc_set_none();
-
os_daemonize();
if (qemu_init_main_loop(&main_loop_err)) {
cpu_exec_init_all();
if (machine_class->hw_version) {
- qemu_set_version(machine_class->hw_version);
+ qemu_set_hw_version(machine_class->hw_version);
}
/* Init CPU def lists, based on config
exit(0);
}
+ if (!trace_init_backends()) {
+ exit(1);
+ }
+ trace_init_file(trace_file);
+
/* Open the logfile at this point and set the log mask if necessary.
*/
if (log_file) {
exit(1);
}
qemu_set_log(mask);
- }
-
- if (!is_daemonized()) {
- if (!trace_init_backends(trace_events, trace_file)) {
- exit(1);
- }
+ } else {
+ qemu_set_log(0);
}
/* If no data_dir is specified then try to find it relative to the
machine_class->max_cpus = machine_class->max_cpus ?: 1; /* Default to UP */
if (max_cpus > machine_class->max_cpus) {
- fprintf(stderr, "Number of SMP cpus requested (%d), exceeds max cpus "
- "supported by machine `%s' (%d)\n", max_cpus,
- machine_class->name, machine_class->max_cpus);
+ error_report("Number of SMP CPUs requested (%d) exceeds max CPUs "
+ "supported by machine '%s' (%d)", max_cpus,
+ machine_class->name, machine_class->max_cpus);
exit(1);
}
if (display_type == DT_NOGRAPHIC
&& (default_parallel || default_serial
|| default_monitor || default_virtcon)) {
- fprintf(stderr, "-nographic can not be used with -daemonize\n");
+ error_report("-nographic cannot be used with -daemonize");
exit(1);
}
#ifdef CONFIG_CURSES
if (display_type == DT_CURSES) {
- fprintf(stderr, "curses display can not be used with -daemonize\n");
+ error_report("curses display cannot be used with -daemonize");
exit(1);
}
#endif
}
if ((no_frame || alt_grab || ctrl_grab) && display_type != DT_SDL) {
- fprintf(stderr, "-no-frame, -alt-grab and -ctrl-grab are only valid "
- "for SDL, ignoring option\n");
+ error_report("-no-frame, -alt-grab and -ctrl-grab are only valid "
+ "for SDL, ignoring option");
}
if (no_quit && (display_type != DT_GTK && display_type != DT_SDL)) {
- fprintf(stderr, "-no-quit is only valid for GTK and SDL, "
- "ignoring option\n");
+ error_report("-no-quit is only valid for GTK and SDL, "
+ "ignoring option");
}
#if defined(CONFIG_GTK)
#endif
if (request_opengl == 1 && display_opengl == 0) {
#if defined(CONFIG_OPENGL)
- fprintf(stderr, "OpenGL is not supported by the display.\n");
+ error_report("OpenGL is not supported by the display");
#else
- fprintf(stderr, "QEMU was built without opengl support.\n");
+ error_report("OpenGL support is disabled");
#endif
exit(1);
}
+ page_size_init();
socket_init();
if (qemu_opts_foreach(qemu_find_opts("object"),
- object_create,
- object_create_initial, NULL)) {
+ user_creatable_add_opts_foreach,
+ object_create_initial, &err)) {
+ error_report_err(err);
exit(1);
}
#endif
if (pid_file && qemu_create_pidfile(pid_file) != 0) {
- fprintf(stderr, "Could not acquire pid file: %s\n", strerror(errno));
+ error_report("could not acquire pid file: %s", strerror(errno));
exit(1);
}
configure_accelerator(current_machine);
if (qtest_chrdev) {
- Error *local_err = NULL;
- qtest_init(qtest_chrdev, qtest_log, &local_err);
- if (local_err) {
- error_report_err(local_err);
- exit(1);
- }
+ qtest_init(qtest_chrdev, qtest_log, &error_fatal);
}
machine_opts = qemu_get_machine_opts();
opts = qemu_opts_find(qemu_find_opts("boot-opts"), NULL);
if (opts) {
- Error *local_err = NULL;
-
boot_order = qemu_opt_get(opts, "order");
if (boot_order) {
- validate_bootdevices(boot_order, &local_err);
- if (local_err) {
- error_report_err(local_err);
- exit(1);
- }
+ validate_bootdevices(boot_order, &error_fatal);
}
boot_once = qemu_opt_get(opts, "once");
if (boot_once) {
- validate_bootdevices(boot_once, &local_err);
- if (local_err) {
- error_report_err(local_err);
- exit(1);
- }
+ validate_bootdevices(boot_once, &error_fatal);
}
boot_menu = qemu_opt_get_bool(opts, "menu", boot_menu);
linux_boot = (kernel_filename != NULL);
if (!linux_boot && *kernel_cmdline != '\0') {
- fprintf(stderr, "-append only allowed with -kernel option\n");
+ error_report("-append only allowed with -kernel option");
exit(1);
}
if (!linux_boot && initrd_filename != NULL) {
- fprintf(stderr, "-initrd only allowed with -kernel option\n");
+ error_report("-initrd only allowed with -kernel option");
exit(1);
}
if (!linux_boot && qemu_opt_get(machine_opts, "dtb")) {
- fprintf(stderr, "-dtb only allowed with -kernel option\n");
+ error_report("-dtb only allowed with -kernel option");
exit(1);
}
cpu_ticks_init();
if (icount_opts) {
if (kvm_enabled() || xen_enabled()) {
- fprintf(stderr, "-icount is not allowed with kvm or xen\n");
+ error_report("-icount is not allowed with kvm or xen");
exit(1);
}
configure_icount(icount_opts, &error_abort);
}
if (qemu_opts_foreach(qemu_find_opts("object"),
- object_create,
- object_create_delayed, NULL)) {
+ user_creatable_add_opts_foreach,
+ object_create_delayed, &err)) {
+ error_report_err(err);
exit(1);
}
if (!xen_enabled()) {
/* On 32-bit hosts, QEMU is limited by virtual address space */
if (ram_size > (2047 << 20) && HOST_LONG_BITS == 32) {
- fprintf(stderr, "qemu: at most 2047 MB RAM can be simulated\n");
+ error_report("at most 2047 MB RAM can be simulated");
exit(1);
}
}
}
/* open the virtual block devices */
- if (snapshot)
- qemu_opts_foreach(qemu_find_opts("drive"),
- drive_enable_snapshot, NULL, NULL);
+ if (snapshot || replay_mode != REPLAY_MODE_NONE) {
+ qemu_opts_foreach(qemu_find_opts("drive"), drive_enable_snapshot,
+ NULL, NULL);
+ }
if (qemu_opts_foreach(qemu_find_opts("drive"), drive_init_func,
&machine_class->block_default_type, NULL)) {
exit(1);
}
qemu_add_globals();
+ /* This checkpoint is required by replay to separate prior clock
+ reading from the other reads, because timer polling functions query
+ clock values from the log. */
+ replay_checkpoint(CHECKPOINT_INIT);
qdev_machine_init();
current_machine->ram_size = ram_size;
net_check_clients();
if (boot_once) {
- Error *local_err = NULL;
- qemu_boot_set(boot_once, &local_err);
- if (local_err) {
- error_report("%s", error_get_pretty(local_err));
- exit(1);
- }
+ qemu_boot_set(boot_once, &error_fatal);
qemu_register_reset(restore_boot_order, g_strdup(boot_order));
}
vnc_init_func, NULL, NULL);
if (show_vnc_port) {
char *ret = vnc_display_local_addr("default");
- printf("VNC server running on `%s'\n", ret);
+ printf("VNC server running on '%s'\n", ret);
g_free(ret);
}
#endif
qemu_run_machine_init_done_notifiers();
if (rom_check_and_register_reset() != 0) {
- fprintf(stderr, "rom check and register reset failed\n");
+ error_report("rom check and register reset failed");
exit(1);
}
+ replay_start();
+
+ /* This checkpoint is required by replay to separate prior clock
+ reading from the other reads, because timer polling functions query
+ clock values from the log. */
+ replay_checkpoint(CHECKPOINT_RESET);
qemu_system_reset(VMRESET_SILENT);
register_global_state();
if (loadvm) {
Error *local_err = NULL;
qemu_start_incoming_migration(incoming, &local_err);
if (local_err) {
- error_report("-incoming %s: %s", incoming,
- error_get_pretty(local_err));
- error_free(local_err);
+ error_reportf_err(local_err, "-incoming %s: ", incoming);
exit(1);
}
} else if (autostart) {
os_setup_post();
- if (is_daemonized()) {
- if (!trace_init_backends(trace_events, trace_file)) {
- exit(1);
- }
- }
-
main_loop();
+ replay_disable_events();
+
bdrv_close_all();
pause_all_vcpus();
res_free();