#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
}, {
.name = "sleep",
.type = QEMU_OPT_BOOL,
+ }, {
+ .name = "rr",
+ .type = QEMU_OPT_STRING,
+ }, {
+ .name = "rrfile",
+ .type = QEMU_OPT_STRING,
},
{ /* end of list */ }
},
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);
}
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)
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();
}
}
}
+ replay_configure(icount_opts);
+
opts = qemu_get_machine_opts();
optarg = qemu_opt_get(opts, "type");
if (optarg) {
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(1);
}
+ page_size_init();
socket_init();
if (qemu_opts_foreach(qemu_find_opts("object"),
}
/* 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;
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) {
}
main_loop();
+ replay_disable_events();
+
bdrv_close_all();
pause_all_vcpus();
res_free();