diff mbox

[V5,1/1] qmp: add pmemload command

Message ID 1397065744-9561-1-git-send-email-wangbj@gmail.com
State New
Headers show

Commit Message

Baojun Wang April 9, 2014, 5:49 p.m. UTC
I found this could be useful to have qemu-softmmu as a cross debugger (launch
with -s -S command line option), then if we can have a command to load guest
physical memory, we can use cross gdb to do some target debug which gdb cannot
do directly.

Many thanks to Eric Blake for review the patch and suggestions.

Signed-off-by: Baojun Wang <wangbj@gmail.com>
---
 cpus.c           | 29 +++++++++++++++++++++++++++++
 hmp-commands.hx  | 13 +++++++++++++
 hmp.c            | 11 +++++++++++
 hmp.h            |  1 +
 qapi-schema.json | 18 ++++++++++++++++++
 qmp-commands.hx  | 27 +++++++++++++++++++++++++++
 6 files changed, 99 insertions(+)

Comments

Michael Tokarev April 27, 2014, 9:18 a.m. UTC | #1
09.04.2014 21:49, Baojun Wang wrote:
> I found this could be useful to have qemu-softmmu as a cross debugger (launch
> with -s -S command line option), then if we can have a command to load guest
> physical memory, we can use cross gdb to do some target debug which gdb cannot
> do directly.
> 
> Many thanks to Eric Blake for review the patch and suggestions.

Okay, that looks sane, but can you explain please, why did you address
qemu-trivial@?  The change definitely is not "trivial", as it introduces
a new qmp command which becomes a part of public interface.  Even if
the implementation may look trivial, the interface change should not be
done using -trivial tree.

Thanks,

/mjt
Markus Armbruster April 28, 2014, 6:30 a.m. UTC | #2
Michael Tokarev <mjt@tls.msk.ru> writes:

> 09.04.2014 21:49, Baojun Wang wrote:
>> I found this could be useful to have qemu-softmmu as a cross debugger (launch
>> with -s -S command line option), then if we can have a command to load guest
>> physical memory, we can use cross gdb to do some target debug which gdb cannot
>> do directly.
>> 
>> Many thanks to Eric Blake for review the patch and suggestions.
>
> Okay, that looks sane, but can you explain please, why did you address
> qemu-trivial@?  The change definitely is not "trivial", as it introduces
> a new qmp command which becomes a part of public interface.  Even if
> the implementation may look trivial, the interface change should not be
> done using -trivial tree.

Yes.  Copying Luiz.
Baojun Wang April 30, 2014, 6 p.m. UTC | #3
Sorry for reply late Michael (my gmail priority inbox didn't sort this
email into my inbox), I thought the change is trivial compare to the huge
patch set in the mailing list :)
I'm OK with the change not one in the -trivial tree.

Best Regards
Baojun


On Sun, Apr 27, 2014 at 2:18 AM, Michael Tokarev <mjt@tls.msk.ru> wrote:

> 09.04.2014 21:49, Baojun Wang wrote:
> > I found this could be useful to have qemu-softmmu as a cross debugger
> (launch
> > with -s -S command line option), then if we can have a command to load
> guest
> > physical memory, we can use cross gdb to do some target debug which gdb
> cannot
> > do directly.
> >
> > Many thanks to Eric Blake for review the patch and suggestions.
>
> Okay, that looks sane, but can you explain please, why did you address
> qemu-trivial@?  The change definitely is not "trivial", as it introduces
> a new qmp command which becomes a part of public interface.  Even if
> the implementation may look trivial, the interface change should not be
> done using -trivial tree.
>
> Thanks,
>
> /mjt
>
diff mbox

Patch

diff --git a/cpus.c b/cpus.c
index 1104d61..230664f 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1467,6 +1467,35 @@  exit:
     fclose(f);
 }
 
+void qmp_pmemload(const char* filename, int64_t addr, int64_t size,
+                  Error **errp)
+{
+    int fd;
+    ssize_t l;
+    uint8_t buf[4096];
+
+    fd = qemu_open(filename, O_RDONLY | O_BINARY);
+    if (fd < 0) {
+        error_setg_file_open(errp, errno, filename);
+        return;
+    }
+
+    while (size != 0) {
+        l = read(fd, buf, sizeof(buf));
+        if (l != sizeof(buf)) {
+            error_set(errp, QERR_IO_ERROR);
+            goto exit;
+        }
+        if (l > size)
+            l = size;
+        cpu_physical_memory_rw(addr, buf, l, 1);
+        addr += l;
+        size -= l;
+    }
+
+exit:
+    qemu_close(fd);
+}
 void qmp_inject_nmi(Error **errp)
 {
 #if defined(TARGET_I386)
diff --git a/hmp-commands.hx b/hmp-commands.hx
index f3fc514..1eae6e3 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -809,6 +809,19 @@  save to disk physical memory dump starting at @var{addr} of size @var{size}.
 ETEXI
 
     {
+        .name       = "pmemload",
+        .args_type  = "filename:s,val:l,size:i",
+        .params     = "file addr size",
+        .help       = "load from disk physical memory dump starting at 'addr' of size 'size'",
+        .mhandler.cmd = hmp_pmemload,
+    },
+
+STEXI
+@item pmemload @var{file} @var{addr} @var{size}
+@findex pmemload
+load from disk physical memory dump starting at @var{addr} of size @var{size}.
+ETEXI
+    {
         .name       = "boot_set",
         .args_type  = "bootdevice:s",
         .params     = "bootdevice",
diff --git a/hmp.c b/hmp.c
index 2f279c4..745c087 100644
--- a/hmp.c
+++ b/hmp.c
@@ -767,6 +767,17 @@  void hmp_pmemsave(Monitor *mon, const QDict *qdict)
     hmp_handle_error(mon, &errp);
 }
 
+void hmp_pmemload(Monitor *mon, const QDict *qdict)
+{
+    uint32_t size = qdict_get_int(qdict, "size");
+    const char *filename = qdict_get_str(qdict, "filename");
+    uint64_t addr = qdict_get_int(qdict, "val");
+    Error *errp = NULL;
+
+    qmp_pmemload(filename, addr, size, &errp);
+    hmp_handle_error(mon, &errp);
+}
+
 void hmp_ringbuf_write(Monitor *mon, const QDict *qdict)
 {
     const char *chardev = qdict_get_str(qdict, "device");
diff --git a/hmp.h b/hmp.h
index ed58f0e..f5f2a16 100644
--- a/hmp.h
+++ b/hmp.h
@@ -44,6 +44,7 @@  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_pmemload(Monitor *mon, const QDict *qdict);
 void hmp_ringbuf_write(Monitor *mon, const QDict *qdict);
 void hmp_ringbuf_read(Monitor *mon, const QDict *qdict);
 void hmp_cont(Monitor *mon, const QDict *qdict);
diff --git a/qapi-schema.json b/qapi-schema.json
index 391356f..7198242 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1708,6 +1708,24 @@ 
   'data': {'val': 'int', 'size': 'int', 'filename': 'str'} }
 
 ##
+# @pmemload:
+#
+# Load a portion of guest physical memory from a file.
+#
+# @filename: the file to load the memory from as binary data
+#
+# @val: the physical address of the guest to start from
+#
+# @size: the size of memory region to load
+#
+# Returns: Nothing on success
+#
+# Since: 2.1
+##
+{ 'command': 'pmemload',
+  'data': {'filename': 'str', 'val': 'int', 'size': 'int'} }
+
+##
 # @cont:
 #
 # Resume guest VCPU execution.
diff --git a/qmp-commands.hx b/qmp-commands.hx
index ed3ab92..2831038 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -468,6 +468,33 @@  Example:
 EQMP
 
     {
+        .name       = "pmemload",
+        .args_type  = "filename:s,val:l,size:i",
+        .mhandler.cmd_new = qmp_marshal_input_pmemload,
+    },
+
+SQMP
+pmemload
+--------
+
+load from disk physical memory dump starting at 'val' of size 'size'.
+
+Arguments:
+
+- "filename": file path (json-string)
+- "val": the starting address (json-int)
+- "size": the memory size, in bytes (json-int)
+
+Example:
+
+-> { "execute": "pmemload",
+             "arguments": { "filename": "/tmp/physical-mem-dump",
+                            "val": 10,
+                            "size": 100 } }
+<- { "return": {} }
+
+EQMP
+    {
         .name       = "inject-nmi",
         .args_type  = "",
         .mhandler.cmd_new = qmp_marshal_input_inject_nmi,