diff mbox series

[v2,qemu,3/3] dump: Add qmp argument "reassembled"

Message ID 20230914010315.945705-4-stephen.s.brennan@oracle.com
State New
Headers show
Series Allow dump-guest-memory to output standard kdump format | expand

Commit Message

Stephen Brennan Sept. 14, 2023, 1:03 a.m. UTC
This can be used from QMP command line as "-R" to mirror the
corresponding flag for makedumpfile. This enables the kdump_reassembled
flag introduced in the previous patch.

Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com>
---
 dump/dump-hmp-cmds.c |  8 +++++++-
 dump/dump.c          | 12 +++++++++++-
 hmp-commands.hx      |  7 +++++--
 qapi/dump.json       | 14 +++++++++++++-
 4 files changed, 36 insertions(+), 5 deletions(-)

Comments

Marc-André Lureau Sept. 18, 2023, 11:15 a.m. UTC | #1
Hi

On Thu, Sep 14, 2023 at 5:03 AM Stephen Brennan
<stephen.s.brennan@oracle.com> wrote:
>
> This can be used from QMP command line as "-R" to mirror the
> corresponding flag for makedumpfile. This enables the kdump_reassembled
> flag introduced in the previous patch.
>
> Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com>
> ---
>  dump/dump-hmp-cmds.c |  8 +++++++-
>  dump/dump.c          | 12 +++++++++++-
>  hmp-commands.hx      |  7 +++++--
>  qapi/dump.json       | 14 +++++++++++++-
>  4 files changed, 36 insertions(+), 5 deletions(-)
>
> diff --git a/dump/dump-hmp-cmds.c b/dump/dump-hmp-cmds.c
> index b038785fee..1d882e4bd8 100644
> --- a/dump/dump-hmp-cmds.c
> +++ b/dump/dump-hmp-cmds.c
> @@ -24,9 +24,11 @@ void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
>      bool has_begin = qdict_haskey(qdict, "begin");
>      bool has_length = qdict_haskey(qdict, "length");
>      bool has_detach = qdict_haskey(qdict, "detach");
> +    bool has_reassembled = qdict_haskey(qdict, "reassembled");
>      int64_t begin = 0;
>      int64_t length = 0;
>      bool detach = false;
> +    bool reassembled = false;
>      enum DumpGuestMemoryFormat dump_format = DUMP_GUEST_MEMORY_FORMAT_ELF;
>      char *prot;
>
> @@ -61,11 +63,15 @@ void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
>      if (has_detach) {
>          detach = qdict_get_bool(qdict, "detach");
>      }
> +    if (has_reassembled) {
> +        reassembled = qdict_get_bool(qdict, "reassembled");
> +    }
>
>      prot = g_strconcat("file:", file, NULL);
>
>      qmp_dump_guest_memory(paging, prot, true, detach, has_begin, begin,
> -                          has_length, length, true, dump_format, &err);
> +                          has_length, length, true, has_reassembled,
> +                          reassembled, dump_format, &err);
>      hmp_handle_error(mon, err);
>      g_free(prot);
>  }
> diff --git a/dump/dump.c b/dump/dump.c
> index fb9040cfbc..42d4015fb3 100644
> --- a/dump/dump.c
> +++ b/dump/dump.c
> @@ -2089,6 +2089,7 @@ void qmp_dump_guest_memory(bool paging, const char *file,
>                             bool has_detach, bool detach,
>                             bool has_begin, int64_t begin, bool has_length,
>                             int64_t length, bool has_format,
> +                           bool has_reassembled, bool reassembled,
>                             DumpGuestMemoryFormat format, Error **errp)
>  {
>      ERRP_GUARD();
> @@ -2119,6 +2120,12 @@ void qmp_dump_guest_memory(bool paging, const char *file,
>                           "filter");
>          return;
>      }
> +    if (has_reassembled && format != DUMP_GUEST_MEMORY_FORMAT_KDUMP_ZLIB
> +                        && format != DUMP_GUEST_MEMORY_FORMAT_KDUMP_LZO
> +                        && format != DUMP_GUEST_MEMORY_FORMAT_KDUMP_SNAPPY) {
> +        error_setg(errp, "'reassembled' only applies to kdump format");
> +        return;
> +    }
>      if (has_begin && !has_length) {
>          error_setg(errp, QERR_MISSING_PARAMETER, "length");
>          return;
> @@ -2130,6 +2137,9 @@ void qmp_dump_guest_memory(bool paging, const char *file,
>      if (has_detach) {
>          detach_p = detach;
>      }
> +    if (!has_reassembled) {
> +        reassembled = false;
> +    }
>
>      /* check whether lzo/snappy is supported */
>  #ifndef CONFIG_LZO
> @@ -2192,7 +2202,7 @@ void qmp_dump_guest_memory(bool paging, const char *file,
>      dump_state_prepare(s);
>
>      dump_init(s, fd, has_format, format, paging, has_begin,
> -              begin, length, false, errp);
> +              begin, length, reassembled, errp);
>      if (*errp) {
>          qatomic_set(&s->status, DUMP_STATUS_FAILED);
>          return;
> diff --git a/hmp-commands.hx b/hmp-commands.hx
> index 2cbd0f77a0..c3062da470 100644
> --- a/hmp-commands.hx
> +++ b/hmp-commands.hx
> @@ -1085,14 +1085,15 @@ ERST
>
>      {
>          .name       = "dump-guest-memory",
> -        .args_type  = "paging:-p,detach:-d,windmp:-w,zlib:-z,lzo:-l,snappy:-s,filename:F,begin:l?,length:l?",
> -        .params     = "[-p] [-d] [-z|-l|-s|-w] filename [begin length]",
> +        .args_type  = "paging:-p,detach:-d,windmp:-w,zlib:-z,lzo:-l,snappy:-s,reassembled:-R,filename:F,begin:l?,length:l?",
> +        .params     = "[-p] [-d] [-z|-l|-s|-w] [-R] filename [begin length]",
>          .help       = "dump guest memory into file 'filename'.\n\t\t\t"
>                        "-p: do paging to get guest's memory mapping.\n\t\t\t"
>                        "-d: return immediately (do not wait for completion).\n\t\t\t"
>                        "-z: dump in kdump-compressed format, with zlib compression.\n\t\t\t"
>                        "-l: dump in kdump-compressed format, with lzo compression.\n\t\t\t"
>                        "-s: dump in kdump-compressed format, with snappy compression.\n\t\t\t"
> +                      "-R: when using kdump (-z, -l, -s), try to avoid the flattened format.\n\t\t\t"
>                        "-w: dump in Windows crashdump format (can be used instead of ELF-dump converting),\n\t\t\t"
>                        "    for Windows x86 and x64 guests with vmcoreinfo driver only.\n\t\t\t"
>                        "begin: the starting physical address.\n\t\t\t"
> @@ -1115,6 +1116,8 @@ SRST
>      dump in kdump-compressed format, with lzo compression.
>    ``-s``
>      dump in kdump-compressed format, with snappy compression.
> +  ``-R``
> +    when using kdump (-z, -l, -s), try to avoid the flattened format.
>    ``-w``
>      dump in Windows crashdump format (can be used instead of ELF-dump converting),
>      for Windows x64 guests with vmcoreinfo driver only
> diff --git a/qapi/dump.json b/qapi/dump.json
> index 4ae1f722a9..9cc7c3ea93 100644
> --- a/qapi/dump.json
> +++ b/qapi/dump.json
> @@ -69,6 +69,18 @@
>  #     to dump all guest's memory, please specify the start @begin and
>  #     @length
>  #
> +# @reassembled: if false (the default), the kdump output formats will use the
> +#     "makedumpfile flattened" variant of the format, which is less broadly
> +#     compatible with analysis tools. The flattened dump can be reassembled
> +#     after the fact using the command "makedumpfile -R". If true, Qemu

QEMU

> +#     attempts to generate the standard kdump format. This requires a
> +#     seekable file as output -- if the output file is not seekable, then
> +#     the flattened format is still generated. The standard format is more

Will have to be adjusted to return an error if we drop the fallback behaviour.

> +#     broadly compatible with debugging tools, but generating it requires a
> +#     seekable output file descriptor, and could use more system memory due
> +#     to page cache utilization. This should be left unspecified for non-kdump
> +#     output formats.
> +#
>  # @format: if specified, the format of guest memory dump.  But non-elf
>  #     format is conflict with paging and filter, ie.  @paging, @begin
>  #     and @length is not allowed to be specified with non-elf @format
> @@ -89,7 +101,7 @@
>  { 'command': 'dump-guest-memory',
>    'data': { 'paging': 'bool', 'protocol': 'str', '*detach': 'bool',
>              '*begin': 'int', '*length': 'int',
> -            '*format': 'DumpGuestMemoryFormat'} }
> +            '*reassembled': 'bool', '*format': 'DumpGuestMemoryFormat'} }
>
>  ##
>  # @DumpStatus:
> --
> 2.39.3
>
Daniel P. Berrangé Sept. 18, 2023, 12:08 p.m. UTC | #2
On Wed, Sep 13, 2023 at 06:03:15PM -0700, Stephen Brennan wrote:
> This can be used from QMP command line as "-R" to mirror the
> corresponding flag for makedumpfile. This enables the kdump_reassembled
> flag introduced in the previous patch.
> 
> Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com>
> ---
>  dump/dump-hmp-cmds.c |  8 +++++++-
>  dump/dump.c          | 12 +++++++++++-
>  hmp-commands.hx      |  7 +++++--
>  qapi/dump.json       | 14 +++++++++++++-
>  4 files changed, 36 insertions(+), 5 deletions(-)

> diff --git a/qapi/dump.json b/qapi/dump.json
> index 4ae1f722a9..9cc7c3ea93 100644
> --- a/qapi/dump.json
> +++ b/qapi/dump.json
> @@ -69,6 +69,18 @@
>  #     to dump all guest's memory, please specify the start @begin and
>  #     @length
>  #
> +# @reassembled: if false (the default), the kdump output formats will use the
> +#     "makedumpfile flattened" variant of the format, which is less broadly
> +#     compatible with analysis tools. The flattened dump can be reassembled
> +#     after the fact using the command "makedumpfile -R". If true, Qemu
> +#     attempts to generate the standard kdump format. This requires a
> +#     seekable file as output -- if the output file is not seekable, then
> +#     the flattened format is still generated. The standard format is more
> +#     broadly compatible with debugging tools, but generating it requires a
> +#     seekable output file descriptor, and could use more system memory due
> +#     to page cache utilization. This should be left unspecified for non-kdump
> +#     output formats.
> +#
>  # @format: if specified, the format of guest memory dump.  But non-elf
>  #     format is conflict with paging and filter, ie.  @paging, @begin
>  #     and @length is not allowed to be specified with non-elf @format
> @@ -89,7 +101,7 @@
>  { 'command': 'dump-guest-memory',
>    'data': { 'paging': 'bool', 'protocol': 'str', '*detach': 'bool',
>              '*begin': 'int', '*length': 'int',
> -            '*format': 'DumpGuestMemoryFormat'} }
> +            '*reassembled': 'bool', '*format': 'DumpGuestMemoryFormat'} }

The 'reassembled' flag is changing the meaning of 3 out of the 5
'format' enum values. IMHO, we should just be adding new formats
instead of changing the meaning of existing formats. It is a shame
we have the current 'kdump' naming prefix, but we're stuck with
that for backwards compat, we need a new prefix. I'd suggest
'kdump-raw'. eg

#
# @DumpGuestMemoryFormat:
#
# An enumeration of guest-memory-dump's format.
#
# @elf: elf format
#
# @kdump-zlib: makedumpfile flattened, kdump-compressed format with zlib-compressed
#
# @kdump-lzo: makedumpfile flattened, kdump-compressed format with lzo-compressed
#
# @kdump-snappy: makedumpfile flattened, kdump-compressed format with snappy-compressed
#
# @kdump-raw-zlib: raw assembled kdump-compressed format with zlib-compressed (since 8.2)
#
# @kdump-raw-lzo: raw assembled kdump-compressed format with lzo-compressed (since 8.2)
#
# @kdump-raw-snappy: raw assembled kdump-compressed format with snappy-compressed (since 8.2)
#
# @win-dmp: Windows full crashdump format, can be used instead of ELF
#     converting (since 2.13)
#
# Since: 2.0
##
{ 'enum': 'DumpGuestMemoryFormat',
  'data': [ 'elf',
            'kdump-zlib', 'kdump-lzo', 'kdump-snappy',
            'kdump-raw-zlib', 'kdump-raw-lzo', 'kdump-raw-snappy',
            'win-dmp' ] }


With regards,
Daniel
Stephen Brennan Sept. 18, 2023, 5:34 p.m. UTC | #3
Daniel P. Berrangé <berrange@redhat.com> writes:
> On Wed, Sep 13, 2023 at 06:03:15PM -0700, Stephen Brennan wrote:
>> This can be used from QMP command line as "-R" to mirror the
>> corresponding flag for makedumpfile. This enables the kdump_reassembled
>> flag introduced in the previous patch.
>> 
>> Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com>
>> ---
>>  dump/dump-hmp-cmds.c |  8 +++++++-
>>  dump/dump.c          | 12 +++++++++++-
>>  hmp-commands.hx      |  7 +++++--
>>  qapi/dump.json       | 14 +++++++++++++-
>>  4 files changed, 36 insertions(+), 5 deletions(-)
>
>> diff --git a/qapi/dump.json b/qapi/dump.json
>> index 4ae1f722a9..9cc7c3ea93 100644
>> --- a/qapi/dump.json
>> +++ b/qapi/dump.json
>> @@ -69,6 +69,18 @@
>>  #     to dump all guest's memory, please specify the start @begin and
>>  #     @length
>>  #
>> +# @reassembled: if false (the default), the kdump output formats will use the
>> +#     "makedumpfile flattened" variant of the format, which is less broadly
>> +#     compatible with analysis tools. The flattened dump can be reassembled
>> +#     after the fact using the command "makedumpfile -R". If true, Qemu
>> +#     attempts to generate the standard kdump format. This requires a
>> +#     seekable file as output -- if the output file is not seekable, then
>> +#     the flattened format is still generated. The standard format is more
>> +#     broadly compatible with debugging tools, but generating it requires a
>> +#     seekable output file descriptor, and could use more system memory due
>> +#     to page cache utilization. This should be left unspecified for non-kdump
>> +#     output formats.
>> +#
>>  # @format: if specified, the format of guest memory dump.  But non-elf
>>  #     format is conflict with paging and filter, ie.  @paging, @begin
>>  #     and @length is not allowed to be specified with non-elf @format
>> @@ -89,7 +101,7 @@
>>  { 'command': 'dump-guest-memory',
>>    'data': { 'paging': 'bool', 'protocol': 'str', '*detach': 'bool',
>>              '*begin': 'int', '*length': 'int',
>> -            '*format': 'DumpGuestMemoryFormat'} }
>> +            '*reassembled': 'bool', '*format': 'DumpGuestMemoryFormat'} }
>
> The 'reassembled' flag is changing the meaning of 3 out of the 5
> 'format' enum values. IMHO, we should just be adding new formats
> instead of changing the meaning of existing formats. It is a shame
> we have the current 'kdump' naming prefix, but we're stuck with
> that for backwards compat, we need a new prefix. I'd suggest
> 'kdump-raw'. eg
>
> #
> # @DumpGuestMemoryFormat:
> #
> # An enumeration of guest-memory-dump's format.
> #
> # @elf: elf format
> #
> # @kdump-zlib: makedumpfile flattened, kdump-compressed format with zlib-compressed
> #
> # @kdump-lzo: makedumpfile flattened, kdump-compressed format with lzo-compressed
> #
> # @kdump-snappy: makedumpfile flattened, kdump-compressed format with snappy-compressed
> #
> # @kdump-raw-zlib: raw assembled kdump-compressed format with zlib-compressed (since 8.2)
> #
> # @kdump-raw-lzo: raw assembled kdump-compressed format with lzo-compressed (since 8.2)
> #
> # @kdump-raw-snappy: raw assembled kdump-compressed format with snappy-compressed (since 8.2)
> #
> # @win-dmp: Windows full crashdump format, can be used instead of ELF
> #     converting (since 2.13)
> #
> # Since: 2.0
> ##
> { 'enum': 'DumpGuestMemoryFormat',
>   'data': [ 'elf',
>             'kdump-zlib', 'kdump-lzo', 'kdump-snappy',
>             'kdump-raw-zlib', 'kdump-raw-lzo', 'kdump-raw-snappy',
>             'win-dmp' ] }

Hi Daniel,

Sure, I'll go ahead and use this approach instead. One question: I see
that this generates the enumeration DumpGuestMemoryFormat in
qapi-types-dump.h. I just wanted to double-check if there's any ABI
considerations for the numbering of this enum? Inserting kdump-raw-* at
this point would result in 'win-dmp' getting a different numbering, and
it seems possible that the API/ABI which libvirt uses might depend on
the enumeration values not changing. E.G. if libvirt is built against
one version of Qemu and then used with a different one.

Thanks,
Stephen

> With regards,
> Daniel
> -- 
> |: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
> |: https://libvirt.org         -o-            https://fstop138.berrange.com :|
> |: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|
Daniel P. Berrangé Sept. 18, 2023, 5:43 p.m. UTC | #4
On Mon, Sep 18, 2023 at 10:34:30AM -0700, Stephen Brennan wrote:
> Daniel P. Berrangé <berrange@redhat.com> writes:
> > #
> > # @DumpGuestMemoryFormat:
> > #
> > # An enumeration of guest-memory-dump's format.
> > #
> > # @elf: elf format
> > #
> > # @kdump-zlib: makedumpfile flattened, kdump-compressed format with zlib-compressed
> > #
> > # @kdump-lzo: makedumpfile flattened, kdump-compressed format with lzo-compressed
> > #
> > # @kdump-snappy: makedumpfile flattened, kdump-compressed format with snappy-compressed
> > #
> > # @kdump-raw-zlib: raw assembled kdump-compressed format with zlib-compressed (since 8.2)
> > #
> > # @kdump-raw-lzo: raw assembled kdump-compressed format with lzo-compressed (since 8.2)
> > #
> > # @kdump-raw-snappy: raw assembled kdump-compressed format with snappy-compressed (since 8.2)
> > #
> > # @win-dmp: Windows full crashdump format, can be used instead of ELF
> > #     converting (since 2.13)
> > #
> > # Since: 2.0
> > ##
> > { 'enum': 'DumpGuestMemoryFormat',
> >   'data': [ 'elf',
> >             'kdump-zlib', 'kdump-lzo', 'kdump-snappy',
> >             'kdump-raw-zlib', 'kdump-raw-lzo', 'kdump-raw-snappy',
> >             'win-dmp' ] }
> 
> Hi Daniel,
> 
> Sure, I'll go ahead and use this approach instead. One question: I see
> that this generates the enumeration DumpGuestMemoryFormat in
> qapi-types-dump.h. I just wanted to double-check if there's any ABI
> considerations for the numbering of this enum? Inserting kdump-raw-* at
> this point would result in 'win-dmp' getting a different numbering, and
> it seems possible that the API/ABI which libvirt uses might depend on
> the enumeration values not changing. E.G. if libvirt is built against
> one version of Qemu and then used with a different one.

The QAPI integer representation of enums is a private internal impl
detail known only to QEMU.

In terms of QMP, the on the wire representation is exclusively string
format, so safe wrt re-ordering for new/old QEMU and new/old libvirt.


In livirt's own public API, if we chose to expose these new formats,
then we have to strictly append after the existing enums constants
in libvirt's header file.

With regards,
Daniel
diff mbox series

Patch

diff --git a/dump/dump-hmp-cmds.c b/dump/dump-hmp-cmds.c
index b038785fee..1d882e4bd8 100644
--- a/dump/dump-hmp-cmds.c
+++ b/dump/dump-hmp-cmds.c
@@ -24,9 +24,11 @@  void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
     bool has_begin = qdict_haskey(qdict, "begin");
     bool has_length = qdict_haskey(qdict, "length");
     bool has_detach = qdict_haskey(qdict, "detach");
+    bool has_reassembled = qdict_haskey(qdict, "reassembled");
     int64_t begin = 0;
     int64_t length = 0;
     bool detach = false;
+    bool reassembled = false;
     enum DumpGuestMemoryFormat dump_format = DUMP_GUEST_MEMORY_FORMAT_ELF;
     char *prot;
 
@@ -61,11 +63,15 @@  void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
     if (has_detach) {
         detach = qdict_get_bool(qdict, "detach");
     }
+    if (has_reassembled) {
+        reassembled = qdict_get_bool(qdict, "reassembled");
+    }
 
     prot = g_strconcat("file:", file, NULL);
 
     qmp_dump_guest_memory(paging, prot, true, detach, has_begin, begin,
-                          has_length, length, true, dump_format, &err);
+                          has_length, length, true, has_reassembled,
+                          reassembled, dump_format, &err);
     hmp_handle_error(mon, err);
     g_free(prot);
 }
diff --git a/dump/dump.c b/dump/dump.c
index fb9040cfbc..42d4015fb3 100644
--- a/dump/dump.c
+++ b/dump/dump.c
@@ -2089,6 +2089,7 @@  void qmp_dump_guest_memory(bool paging, const char *file,
                            bool has_detach, bool detach,
                            bool has_begin, int64_t begin, bool has_length,
                            int64_t length, bool has_format,
+                           bool has_reassembled, bool reassembled,
                            DumpGuestMemoryFormat format, Error **errp)
 {
     ERRP_GUARD();
@@ -2119,6 +2120,12 @@  void qmp_dump_guest_memory(bool paging, const char *file,
                          "filter");
         return;
     }
+    if (has_reassembled && format != DUMP_GUEST_MEMORY_FORMAT_KDUMP_ZLIB
+                        && format != DUMP_GUEST_MEMORY_FORMAT_KDUMP_LZO
+                        && format != DUMP_GUEST_MEMORY_FORMAT_KDUMP_SNAPPY) {
+        error_setg(errp, "'reassembled' only applies to kdump format");
+        return;
+    }
     if (has_begin && !has_length) {
         error_setg(errp, QERR_MISSING_PARAMETER, "length");
         return;
@@ -2130,6 +2137,9 @@  void qmp_dump_guest_memory(bool paging, const char *file,
     if (has_detach) {
         detach_p = detach;
     }
+    if (!has_reassembled) {
+        reassembled = false;
+    }
 
     /* check whether lzo/snappy is supported */
 #ifndef CONFIG_LZO
@@ -2192,7 +2202,7 @@  void qmp_dump_guest_memory(bool paging, const char *file,
     dump_state_prepare(s);
 
     dump_init(s, fd, has_format, format, paging, has_begin,
-              begin, length, false, errp);
+              begin, length, reassembled, errp);
     if (*errp) {
         qatomic_set(&s->status, DUMP_STATUS_FAILED);
         return;
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 2cbd0f77a0..c3062da470 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1085,14 +1085,15 @@  ERST
 
     {
         .name       = "dump-guest-memory",
-        .args_type  = "paging:-p,detach:-d,windmp:-w,zlib:-z,lzo:-l,snappy:-s,filename:F,begin:l?,length:l?",
-        .params     = "[-p] [-d] [-z|-l|-s|-w] filename [begin length]",
+        .args_type  = "paging:-p,detach:-d,windmp:-w,zlib:-z,lzo:-l,snappy:-s,reassembled:-R,filename:F,begin:l?,length:l?",
+        .params     = "[-p] [-d] [-z|-l|-s|-w] [-R] filename [begin length]",
         .help       = "dump guest memory into file 'filename'.\n\t\t\t"
                       "-p: do paging to get guest's memory mapping.\n\t\t\t"
                       "-d: return immediately (do not wait for completion).\n\t\t\t"
                       "-z: dump in kdump-compressed format, with zlib compression.\n\t\t\t"
                       "-l: dump in kdump-compressed format, with lzo compression.\n\t\t\t"
                       "-s: dump in kdump-compressed format, with snappy compression.\n\t\t\t"
+                      "-R: when using kdump (-z, -l, -s), try to avoid the flattened format.\n\t\t\t"
                       "-w: dump in Windows crashdump format (can be used instead of ELF-dump converting),\n\t\t\t"
                       "    for Windows x86 and x64 guests with vmcoreinfo driver only.\n\t\t\t"
                       "begin: the starting physical address.\n\t\t\t"
@@ -1115,6 +1116,8 @@  SRST
     dump in kdump-compressed format, with lzo compression.
   ``-s``
     dump in kdump-compressed format, with snappy compression.
+  ``-R``
+    when using kdump (-z, -l, -s), try to avoid the flattened format.
   ``-w``
     dump in Windows crashdump format (can be used instead of ELF-dump converting),
     for Windows x64 guests with vmcoreinfo driver only
diff --git a/qapi/dump.json b/qapi/dump.json
index 4ae1f722a9..9cc7c3ea93 100644
--- a/qapi/dump.json
+++ b/qapi/dump.json
@@ -69,6 +69,18 @@ 
 #     to dump all guest's memory, please specify the start @begin and
 #     @length
 #
+# @reassembled: if false (the default), the kdump output formats will use the
+#     "makedumpfile flattened" variant of the format, which is less broadly
+#     compatible with analysis tools. The flattened dump can be reassembled
+#     after the fact using the command "makedumpfile -R". If true, Qemu
+#     attempts to generate the standard kdump format. This requires a
+#     seekable file as output -- if the output file is not seekable, then
+#     the flattened format is still generated. The standard format is more
+#     broadly compatible with debugging tools, but generating it requires a
+#     seekable output file descriptor, and could use more system memory due
+#     to page cache utilization. This should be left unspecified for non-kdump
+#     output formats.
+#
 # @format: if specified, the format of guest memory dump.  But non-elf
 #     format is conflict with paging and filter, ie.  @paging, @begin
 #     and @length is not allowed to be specified with non-elf @format
@@ -89,7 +101,7 @@ 
 { 'command': 'dump-guest-memory',
   'data': { 'paging': 'bool', 'protocol': 'str', '*detach': 'bool',
             '*begin': 'int', '*length': 'int',
-            '*format': 'DumpGuestMemoryFormat'} }
+            '*reassembled': 'bool', '*format': 'DumpGuestMemoryFormat'} }
 
 ##
 # @DumpStatus: