mirror of
https://git.proxmox.com/git/qemu
synced 2025-08-07 18:57:14 +00:00
qapi: Convert memsave
Please, note that the QMP command has a new 'cpu-index' parameter. Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
This commit is contained in:
parent
5889887366
commit
0cfd6a9ab4
47
cpus.c
47
cpus.c
@ -1136,3 +1136,50 @@ CpuInfoList *qmp_query_cpus(Error **errp)
|
|||||||
|
|
||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void qmp_memsave(int64_t addr, int64_t size, const char *filename,
|
||||||
|
bool has_cpu, int64_t cpu_index, Error **errp)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
uint32_t l;
|
||||||
|
CPUState *env;
|
||||||
|
uint8_t buf[1024];
|
||||||
|
|
||||||
|
if (!has_cpu) {
|
||||||
|
cpu_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (env = first_cpu; env; env = env->next_cpu) {
|
||||||
|
if (cpu_index == env->cpu_index) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (env == NULL) {
|
||||||
|
error_set(errp, QERR_INVALID_PARAMETER_VALUE, "cpu-index",
|
||||||
|
"a CPU number");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
f = fopen(filename, "wb");
|
||||||
|
if (!f) {
|
||||||
|
error_set(errp, QERR_OPEN_FILE_FAILED, filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (size != 0) {
|
||||||
|
l = sizeof(buf);
|
||||||
|
if (l > size)
|
||||||
|
l = size;
|
||||||
|
cpu_memory_rw_debug(env, addr, buf, l, 0);
|
||||||
|
if (fwrite(buf, 1, l, f) != l) {
|
||||||
|
error_set(errp, QERR_IO_ERROR);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
addr += l;
|
||||||
|
size -= l;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
@ -689,8 +689,7 @@ ETEXI
|
|||||||
.args_type = "val:l,size:i,filename:s",
|
.args_type = "val:l,size:i,filename:s",
|
||||||
.params = "addr size file",
|
.params = "addr size file",
|
||||||
.help = "save to disk virtual memory dump starting at 'addr' of size 'size'",
|
.help = "save to disk virtual memory dump starting at 'addr' of size 'size'",
|
||||||
.user_print = monitor_user_noop,
|
.mhandler.cmd = hmp_memsave,
|
||||||
.mhandler.cmd_new = do_memory_save,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
STEXI
|
STEXI
|
||||||
|
19
hmp.c
19
hmp.c
@ -14,6 +14,14 @@
|
|||||||
#include "hmp.h"
|
#include "hmp.h"
|
||||||
#include "qmp-commands.h"
|
#include "qmp-commands.h"
|
||||||
|
|
||||||
|
static void hmp_handle_error(Monitor *mon, Error **errp)
|
||||||
|
{
|
||||||
|
if (error_is_set(errp)) {
|
||||||
|
monitor_printf(mon, "%s\n", error_get_pretty(*errp));
|
||||||
|
error_free(*errp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void hmp_info_name(Monitor *mon)
|
void hmp_info_name(Monitor *mon)
|
||||||
{
|
{
|
||||||
NameInfo *info;
|
NameInfo *info;
|
||||||
@ -531,3 +539,14 @@ void hmp_cpu(Monitor *mon, const QDict *qdict)
|
|||||||
monitor_printf(mon, "invalid CPU index\n");
|
monitor_printf(mon, "invalid CPU index\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void hmp_memsave(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_memsave(addr, size, filename, true, monitor_get_cpu_index(), &errp);
|
||||||
|
hmp_handle_error(mon, &errp);
|
||||||
|
}
|
||||||
|
1
hmp.h
1
hmp.h
@ -37,5 +37,6 @@ void hmp_stop(Monitor *mon, const QDict *qdict);
|
|||||||
void hmp_system_reset(Monitor *mon, const QDict *qdict);
|
void hmp_system_reset(Monitor *mon, const QDict *qdict);
|
||||||
void hmp_system_powerdown(Monitor *mon, const QDict *qdict);
|
void hmp_system_powerdown(Monitor *mon, const QDict *qdict);
|
||||||
void hmp_cpu(Monitor *mon, const QDict *qdict);
|
void hmp_cpu(Monitor *mon, const QDict *qdict);
|
||||||
|
void hmp_memsave(Monitor *mon, const QDict *qdict);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
38
monitor.c
38
monitor.c
@ -1370,44 +1370,6 @@ static void do_print(Monitor *mon, const QDict *qdict)
|
|||||||
monitor_printf(mon, "\n");
|
monitor_printf(mon, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_memory_save(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
|
||||||
{
|
|
||||||
FILE *f;
|
|
||||||
uint32_t size = qdict_get_int(qdict, "size");
|
|
||||||
const char *filename = qdict_get_str(qdict, "filename");
|
|
||||||
target_long addr = qdict_get_int(qdict, "val");
|
|
||||||
uint32_t l;
|
|
||||||
CPUState *env;
|
|
||||||
uint8_t buf[1024];
|
|
||||||
int ret = -1;
|
|
||||||
|
|
||||||
env = mon_get_cpu();
|
|
||||||
|
|
||||||
f = fopen(filename, "wb");
|
|
||||||
if (!f) {
|
|
||||||
qerror_report(QERR_OPEN_FILE_FAILED, filename);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
while (size != 0) {
|
|
||||||
l = sizeof(buf);
|
|
||||||
if (l > size)
|
|
||||||
l = size;
|
|
||||||
cpu_memory_rw_debug(env, addr, buf, l, 0);
|
|
||||||
if (fwrite(buf, 1, l, f) != l) {
|
|
||||||
monitor_printf(mon, "fwrite() error in do_memory_save\n");
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
addr += l;
|
|
||||||
size -= l;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
exit:
|
|
||||||
fclose(f);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int do_physical_memory_save(Monitor *mon, const QDict *qdict,
|
static int do_physical_memory_save(Monitor *mon, const QDict *qdict,
|
||||||
QObject **ret_data)
|
QObject **ret_data)
|
||||||
{
|
{
|
||||||
|
@ -901,3 +901,29 @@
|
|||||||
# Notes: Do not use this command.
|
# Notes: Do not use this command.
|
||||||
##
|
##
|
||||||
{ 'command': 'cpu', 'data': {'index': 'int'} }
|
{ 'command': 'cpu', 'data': {'index': 'int'} }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @memsave:
|
||||||
|
#
|
||||||
|
# Save a portion of guest memory to a file.
|
||||||
|
#
|
||||||
|
# @val: the virtual address of the guest to start from
|
||||||
|
#
|
||||||
|
# @size: the size of memory region to save
|
||||||
|
#
|
||||||
|
# @filename: the file to save the memory to as binary data
|
||||||
|
#
|
||||||
|
# @cpu-index: #optional the index of the virtual CPU to use for translating the
|
||||||
|
# virtual address (defaults to CPU 0)
|
||||||
|
#
|
||||||
|
# Returns: Nothing on success
|
||||||
|
# If @cpu is not a valid VCPU, InvalidParameterValue
|
||||||
|
# If @filename cannot be opened, OpenFileFailed
|
||||||
|
# If an I/O error occurs while writing the file, IOError
|
||||||
|
#
|
||||||
|
# Since: 0.14.0
|
||||||
|
#
|
||||||
|
# Notes: Errors were not reliably returned until 1.1
|
||||||
|
##
|
||||||
|
{ 'command': 'memsave',
|
||||||
|
'data': {'val': 'int', 'size': 'int', 'filename': 'str', '*cpu-index': 'int'} }
|
||||||
|
@ -352,11 +352,8 @@ EQMP
|
|||||||
|
|
||||||
{
|
{
|
||||||
.name = "memsave",
|
.name = "memsave",
|
||||||
.args_type = "val:l,size:i,filename:s",
|
.args_type = "val:l,size:i,filename:s,cpu:i?",
|
||||||
.params = "addr size file",
|
.mhandler.cmd_new = qmp_marshal_input_memsave,
|
||||||
.help = "save to disk virtual memory dump starting at 'addr' of size 'size'",
|
|
||||||
.user_print = monitor_user_noop,
|
|
||||||
.mhandler.cmd_new = do_memory_save,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
SQMP
|
SQMP
|
||||||
@ -370,6 +367,7 @@ Arguments:
|
|||||||
- "val": the starting address (json-int)
|
- "val": the starting address (json-int)
|
||||||
- "size": the memory size, in bytes (json-int)
|
- "size": the memory size, in bytes (json-int)
|
||||||
- "filename": file path (json-string)
|
- "filename": file path (json-string)
|
||||||
|
- "cpu": virtual CPU index (json-int, optional)
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@ -379,8 +377,6 @@ Example:
|
|||||||
"filename": "/tmp/virtual-mem-dump" } }
|
"filename": "/tmp/virtual-mem-dump" } }
|
||||||
<- { "return": {} }
|
<- { "return": {} }
|
||||||
|
|
||||||
Note: Depends on the current CPU.
|
|
||||||
|
|
||||||
EQMP
|
EQMP
|
||||||
|
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user