diff --git a/input.c b/input.c index 6b5c2c3371..6968b31781 100644 --- a/input.c +++ b/input.c @@ -130,7 +130,7 @@ void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry) void kbd_put_keycode(int keycode) { - if (!runstate_is_running()) { + if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) { return; } if (qemu_put_kbd_event) { @@ -154,7 +154,7 @@ void kbd_mouse_event(int dx, int dy, int dz, int buttons_state) void *mouse_event_opaque; int width, height; - if (!runstate_is_running()) { + if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) { return; } if (QTAILQ_EMPTY(&mouse_handlers)) { diff --git a/migration.c b/migration.c index 94f7839e8b..f9e968ee2a 100644 --- a/migration.c +++ b/migration.c @@ -252,6 +252,7 @@ static void migrate_fd_put_ready(void *opaque) int old_vm_running = runstate_is_running(); DPRINTF("done iterating\n"); + qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); vm_stop_force_state(RUN_STATE_FINISH_MIGRATE); if (qemu_savevm_state_complete(s->file) < 0) { diff --git a/monitor.c b/monitor.c index 8946a100c0..12a6fe25ad 100644 --- a/monitor.c +++ b/monitor.c @@ -89,8 +89,8 @@ * TODO lift the restriction * 'i' 32 bit integer * 'l' target long (32 or 64 bit) - * 'M' just like 'l', except in user mode the value is - * multiplied by 2^20 (think Mebibyte) + * 'M' Non-negative target long (32 or 64 bit), in user mode the + * value is multiplied by 2^20 (think Mebibyte) * 'o' octets (aka bytes) * user mode accepts an optional T, t, G, g, M, m, K, k * suffix, which multiplies the value by 2^40 for @@ -3120,11 +3120,15 @@ static int64_t expr_unary(Monitor *mon) n = 0; break; default: + errno = 0; #if TARGET_PHYS_ADDR_BITS > 32 n = strtoull(pch, &p, 0); #else n = strtoul(pch, &p, 0); #endif + if (errno == ERANGE) { + expr_error(mon, "number too large"); + } if (pch == p) { expr_error(mon, "invalid char in expression"); } @@ -3618,6 +3622,10 @@ static const mon_cmd_t *monitor_parse_command(Monitor *mon, monitor_printf(mon, "integer is for 32-bit values\n"); goto fail; } else if (c == 'M') { + if (val < 0) { + monitor_printf(mon, "enter a positive value\n"); + goto fail; + } val <<= 20; } qdict_put(qdict, key, qint_from_int(val)); diff --git a/qapi-schema.json b/qapi-schema.json index 4279259bc1..2ca7195d25 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -92,6 +92,8 @@ # # @debug: QEMU is running on a debugger # +# @finish-migrate: guest is paused to finish the migration process +# # @inmigrate: guest is paused waiting for an incoming migration # # @internal-error: An internal error that prevents further guest execution @@ -106,8 +108,6 @@ # # @prelaunch: QEMU was started with -S and guest has not started # -# @finish-migrate: guest is paused to finish the migration process -# # @restore-vm: guest is paused to restore VM state # # @running: guest is actively running @@ -116,12 +116,14 @@ # # @shutdown: guest is shut down (and -no-shutdown is in use) # +# @suspended: guest is suspended (ACPI S3) +# # @watchdog: the watchdog action is configured to pause and has been triggered ## { 'enum': 'RunState', 'data': [ 'debug', 'inmigrate', 'internal-error', 'io-error', 'paused', 'postmigrate', 'prelaunch', 'finish-migrate', 'restore-vm', - 'running', 'save-vm', 'shutdown', 'watchdog' ] } + 'running', 'save-vm', 'shutdown', 'suspended', 'watchdog' ] } ## # @StatusInfo: diff --git a/qmp.c b/qmp.c index a182b5197e..fee9fb2a9d 100644 --- a/qmp.c +++ b/qmp.c @@ -151,6 +151,8 @@ void qmp_cont(Error **errp) runstate_check(RUN_STATE_SHUTDOWN)) { error_set(errp, QERR_RESET_REQUIRED); return; + } else if (runstate_check(RUN_STATE_SUSPENDED)) { + return; } bdrv_iterate(iostatus_bdrv_it, NULL); diff --git a/vl.c b/vl.c index ae91a8ab01..5e0080b98f 100644 --- a/vl.c +++ b/vl.c @@ -366,6 +366,11 @@ static const RunStateTransition runstate_transitions_def[] = { { RUN_STATE_SHUTDOWN, RUN_STATE_PAUSED }, { RUN_STATE_SHUTDOWN, RUN_STATE_FINISH_MIGRATE }, + { 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_WATCHDOG, RUN_STATE_RUNNING }, { RUN_STATE_WATCHDOG, RUN_STATE_FINISH_MIGRATE }, @@ -1288,7 +1293,6 @@ static pid_t shutdown_pid; static int powerdown_requested; static int debug_requested; static int suspend_requested; -static bool is_suspended; static NotifierList suspend_notifiers = NOTIFIER_LIST_INITIALIZER(suspend_notifiers); static NotifierList wakeup_notifiers = @@ -1420,13 +1424,13 @@ static void qemu_system_suspend(void) { pause_all_vcpus(); notifier_list_notify(&suspend_notifiers, NULL); + runstate_set(RUN_STATE_SUSPENDED); monitor_protocol_event(QEVENT_SUSPEND, NULL); - is_suspended = true; } void qemu_system_suspend_request(void) { - if (is_suspended) { + if (runstate_check(RUN_STATE_SUSPENDED)) { return; } suspend_requested = 1; @@ -1441,17 +1445,17 @@ void qemu_register_suspend_notifier(Notifier *notifier) void qemu_system_wakeup_request(WakeupReason reason) { - if (!is_suspended) { + if (!runstate_check(RUN_STATE_SUSPENDED)) { return; } if (!(wakeup_reason_mask & (1 << reason))) { return; } + runstate_set(RUN_STATE_RUNNING); monitor_protocol_event(QEVENT_WAKEUP, NULL); notifier_list_notify(&wakeup_notifiers, &reason); reset_requested = 1; qemu_notify_event(); - is_suspended = false; } void qemu_system_wakeup_enable(WakeupReason reason, bool enabled)