diff --git a/console.c b/console.c
index 1e97c4a..301ac3d 100644
--- a/console.c
+++ b/console.c
@@ -176,8 +176,38 @@ void vga_hw_invalidate(void)
         active_console->hw_invalidate(active_console->hw);
 }
 
-void vga_hw_screen_dump(const char *filename)
+typedef struct VGAHwScreenDumpAsyncCbData {
+    char *filename;
+} VGAHwScreenDumpAsyncCbData;
+
+static VGAHwScreenDumpAsyncCbData *
+vga_hw_screen_dump_async_data_new(const char *filename)
+{
+    VGAHwScreenDumpAsyncCbData *data = g_malloc0(
+            sizeof(VGAHwScreenDumpAsyncCbData));
+
+    data->filename = g_strdup(filename);
+    return data;
+}
+
+static void vga_hw_screen_dump_async_data_free(
+        VGAHwScreenDumpAsyncCbData *data)
 {
+    g_free(data->filename);
+    g_free(data);
+}
+
+static void vga_hw_screen_dump_async_cb(void *opaque)
+{
+    VGAHwScreenDumpAsyncCbData *data = opaque;
+
+    monitor_protocol_screen_dump_complete_event(data->filename);
+    vga_hw_screen_dump_async_data_free(data);
+}
+
+static void vga_hw_screen_dump_helper(const char *filename, bool async)
+{
+    VGAHwScreenDumpAsyncCbData *data;
     TextConsole *previous_active_console;
     bool cswitch;
 
@@ -189,8 +219,15 @@ void vga_hw_screen_dump(const char *filename)
     if (cswitch) {
         console_select(0);
     }
-    if (consoles[0] && consoles[0]->hw_screen_dump) {
+    if (async && consoles[0] && consoles[0]->hw_screen_dump_async) {
+        data = vga_hw_screen_dump_async_data_new(filename);
+        consoles[0]->hw_screen_dump_async(consoles[0]->hw, filename, cswitch,
+                                          vga_hw_screen_dump_async_cb, data);
+    } else if (consoles[0] && consoles[0]->hw_screen_dump) {
         consoles[0]->hw_screen_dump(consoles[0]->hw, filename, cswitch);
+        if (async) {
+            monitor_protocol_screen_dump_complete_event(filename);
+        }
     } else {
         error_report("screen dump not implemented");
     }
@@ -200,6 +237,16 @@ void vga_hw_screen_dump(const char *filename)
     }
 }
 
+void vga_hw_screen_dump(const char *filename)
+{
+    vga_hw_screen_dump_helper(filename, false);
+}
+
+void vga_hw_screen_dump_async(const char *filename)
+{
+    vga_hw_screen_dump_helper(filename, true);
+}
+
 void vga_hw_text_update(console_ch_t *chardata)
 {
     if (active_console && active_console->hw_text_update)
diff --git a/monitor.c b/monitor.c
index a8c84c0..1c3bd2a 100644
--- a/monitor.c
+++ b/monitor.c
@@ -901,6 +901,11 @@ static int do_screen_dump(Monitor *mon, const QDict *qdict, QObject **ret_data)
     return 0;
 }
 
+void qmp_screendump_async(const char *filename, Error **errp)
+{
+    vga_hw_screen_dump_async(filename);
+}
+
 static void do_logfile(Monitor *mon, const QDict *qdict)
 {
     cpu_set_log_filename(qdict_get_str(qdict, "filename"));
diff --git a/qapi-schema.json b/qapi-schema.json
index dd9e0e5..60dae67 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1633,3 +1633,23 @@
 { 'command': 'qom-list-types',
   'data': { '*implements': 'str', '*abstract': 'bool' },
   'returns': [ 'ObjectTypeInfo' ] }
+
+##
+## @screendump-async:
+#
+# This command will perform a screen dump of the first console to the givem
+# filename. The additional parameters are unused at this time.
+#
+# @filename  name of output file to write screen dump to
+#
+# Since: 1.1
+#
+# Notes: This command is experimental and may change syntax in future releases.
+#
+# This command is the same as the qmp/hmp screendump command, except that on
+# successful completion of the scren dump the SCREEN_DUMP_COMPLETE event is
+# emitted.
+#
+##
+{ 'command': 'screendump-async',
+  'data': { 'filename': 'str' } }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 0c9bfac..94ee1ae 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -170,6 +170,32 @@ Example:
 EQMP
 
     {
+        .name       = "screendump-async",
+        .args_type  = "filename:F",
+        .params     = "filename",
+        .help       = "save screen into PPM image 'filename'",
+        .user_print = monitor_user_noop,
+        .mhandler.cmd_new = qmp_marshal_input_screendump_async,
+    },
+
+SQMP
+screendump-async
+----------------
+
+Save screen into PPM image. Fires a SCREEN_DUMP_COMPLETE event on completion.
+
+Arguments:
+
+- "filename": file path (json-string)
+
+Example:
+
+-> { "execute": "screendump-async", "arguments": { "filename": "/tmp/image" } }
+<- { "return": {} }
+
+EQMP
+
+    {
         .name       = "stop",
         .args_type  = "",
         .mhandler.cmd_new = qmp_marshal_input_stop,
