diff --git a/hmp-commands.hx b/hmp-commands.hx
index 0a721cc..9503751 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 96e3ce1..d623526 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 4882bea..b034704 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 a1b46b3..b0d1862 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 e76795f..052f1cb 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 7f9aa94..b6fd3f1 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 5093ac9..03b2617 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 511dd62..d71ceb4 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();
+}
