aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hmp-commands.hx3
-rw-r--r--hmp.c32
-rw-r--r--hmp.h1
-rw-r--r--monitor.c74
-rw-r--r--monitor.h3
-rw-r--r--qapi-schema.json17
-rw-r--r--qmp-commands.hx5
-rw-r--r--qmp.c37
8 files changed, 107 insertions, 65 deletions
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 0a721ccd9..950375164 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -304,8 +304,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "resume emulation",
- .user_print = monitor_user_noop,
- .mhandler.cmd_new = do_cont,
+ .mhandler.cmd = hmp_cont,
},
STEXI
diff --git a/hmp.c b/hmp.c
index 96e3ce18c..d6235269b 100644
--- a/hmp.c
+++ b/hmp.c
@@ -561,3 +561,35 @@ void hmp_pmemsave(Monitor *mon, const QDict *qdict)
qmp_pmemsave(addr, size, filename, &errp);
hmp_handle_error(mon, &errp);
}
+
+static void hmp_cont_cb(void *opaque, int err)
+{
+ Monitor *mon = opaque;
+
+ if (!err) {
+ hmp_cont(mon, NULL);
+ }
+}
+
+void hmp_cont(Monitor *mon, const QDict *qdict)
+{
+ Error *errp = NULL;
+
+ qmp_cont(&errp);
+ if (error_is_set(&errp)) {
+ if (error_is_type(errp, QERR_DEVICE_ENCRYPTED)) {
+ const char *device;
+
+ /* The device is encrypted. Ask the user for the password
+ and retry */
+
+ device = error_get_field(errp, "device");
+ assert(device != NULL);
+
+ monitor_read_block_device_key(mon, device, hmp_cont_cb, mon);
+ error_free(errp);
+ return;
+ }
+ hmp_handle_error(mon, &errp);
+ }
+}
diff --git a/hmp.h b/hmp.h
index 4882bea1f..b0347047b 100644
--- a/hmp.h
+++ b/hmp.h
@@ -39,5 +39,6 @@ void hmp_system_powerdown(Monitor *mon, const QDict *qdict);
void hmp_cpu(Monitor *mon, const QDict *qdict);
void hmp_memsave(Monitor *mon, const QDict *qdict);
void hmp_pmemsave(Monitor *mon, const QDict *qdict);
+void hmp_cont(Monitor *mon, const QDict *qdict);
#endif
diff --git a/monitor.c b/monitor.c
index a1b46b3c6..b0d1862de 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1073,65 +1073,6 @@ static void do_singlestep(Monitor *mon, const QDict *qdict)
}
}
-static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs);
-
-struct bdrv_iterate_context {
- Monitor *mon;
- int err;
-};
-
-static void iostatus_bdrv_it(void *opaque, BlockDriverState *bs)
-{
- bdrv_iostatus_reset(bs);
-}
-
-/**
- * do_cont(): Resume emulation.
- */
-static int do_cont(Monitor *mon, const QDict *qdict, QObject **ret_data)
-{
- struct bdrv_iterate_context context = { mon, 0 };
-
- if (runstate_check(RUN_STATE_INMIGRATE)) {
- qerror_report(QERR_MIGRATION_EXPECTED);
- return -1;
- } else if (runstate_check(RUN_STATE_INTERNAL_ERROR) ||
- runstate_check(RUN_STATE_SHUTDOWN)) {
- qerror_report(QERR_RESET_REQUIRED);
- return -1;
- }
-
- bdrv_iterate(iostatus_bdrv_it, NULL);
- bdrv_iterate(encrypted_bdrv_it, &context);
- /* only resume the vm if all keys are set and valid */
- if (!context.err) {
- vm_start();
- return 0;
- } else {
- return -1;
- }
-}
-
-static void bdrv_key_cb(void *opaque, int err)
-{
- Monitor *mon = opaque;
-
- /* another key was set successfully, retry to continue */
- if (!err)
- do_cont(mon, NULL, NULL);
-}
-
-static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs)
-{
- struct bdrv_iterate_context *context = opaque;
-
- if (!context->err && bdrv_key_required(bs)) {
- context->err = -EBUSY;
- monitor_read_bdrv_key_start(context->mon, bs, bdrv_key_cb,
- context->mon);
- }
-}
-
static void do_gdbserver(Monitor *mon, const QDict *qdict)
{
const char *device = qdict_get_try_str(qdict, "device");
@@ -4858,3 +4799,18 @@ int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
return err;
}
+
+int monitor_read_block_device_key(Monitor *mon, const char *device,
+ BlockDriverCompletionFunc *completion_cb,
+ void *opaque)
+{
+ BlockDriverState *bs;
+
+ bs = bdrv_find(device);
+ if (!bs) {
+ monitor_printf(mon, "Device not found %s\n", device);
+ return -1;
+ }
+
+ return monitor_read_bdrv_key_start(mon, bs, completion_cb, opaque);
+}
diff --git a/monitor.h b/monitor.h
index e76795f1f..052f1cb24 100644
--- a/monitor.h
+++ b/monitor.h
@@ -49,6 +49,9 @@ void monitor_resume(Monitor *mon);
int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
BlockDriverCompletionFunc *completion_cb,
void *opaque);
+int monitor_read_block_device_key(Monitor *mon, const char *device,
+ BlockDriverCompletionFunc *completion_cb,
+ void *opaque);
int monitor_get_fd(Monitor *mon, const char *fdname);
diff --git a/qapi-schema.json b/qapi-schema.json
index 7f9aa94f1..b6fd3f1d3 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -949,3 +949,20 @@
##
{ 'command': 'pmemsave',
'data': {'val': 'int', 'size': 'int', 'filename': 'str'} }
+
+##
+# @cont:
+#
+# Resume guest VCPU execution.
+#
+# Since: 0.14.0
+#
+# Returns: If successful, nothing
+# If the QEMU is waiting for an incoming migration, MigrationExpected
+# If QEMU was started with an encrypted block device and a key has
+# not yet been set, DeviceEncrypted.
+#
+# Notes: This command will succeed if the guest is currently running.
+##
+{ 'command': 'cont' }
+
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 5093ac900..03b261710 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -199,10 +199,7 @@ EQMP
{
.name = "cont",
.args_type = "",
- .params = "",
- .help = "resume emulation",
- .user_print = monitor_user_noop,
- .mhandler.cmd_new = do_cont,
+ .mhandler.cmd_new = qmp_marshal_input_cont,
},
SQMP
diff --git a/qmp.c b/qmp.c
index 511dd624b..d71ceb4e4 100644
--- a/qmp.c
+++ b/qmp.c
@@ -117,3 +117,40 @@ SpiceInfo *qmp_query_spice(Error **errp)
return NULL;
};
#endif
+
+static void iostatus_bdrv_it(void *opaque, BlockDriverState *bs)
+{
+ bdrv_iostatus_reset(bs);
+}
+
+static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs)
+{
+ Error **err = opaque;
+
+ if (!error_is_set(err) && bdrv_key_required(bs)) {
+ error_set(err, QERR_DEVICE_ENCRYPTED, bdrv_get_device_name(bs));
+ }
+}
+
+void qmp_cont(Error **errp)
+{
+ Error *local_err = NULL;
+
+ if (runstate_check(RUN_STATE_INMIGRATE)) {
+ error_set(errp, QERR_MIGRATION_EXPECTED);
+ return;
+ } else if (runstate_check(RUN_STATE_INTERNAL_ERROR) ||
+ runstate_check(RUN_STATE_SHUTDOWN)) {
+ error_set(errp, QERR_RESET_REQUIRED);
+ return;
+ }
+
+ bdrv_iterate(iostatus_bdrv_it, NULL);
+ bdrv_iterate(encrypted_bdrv_it, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ vm_start();
+}