| /* |
| * QMP commands to dump physical memory |
| * |
| * Copyright (c) 2003-2008 Fabrice Bellard |
| * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. |
| * |
| * SPDX-License-Identifier: GPL-2.0-or-later |
| */ |
| |
| #include "qemu/osdep.h" |
| #include "qapi/error.h" |
| #include "qapi/qapi-commands-machine.h" |
| #include "qapi/qmp/qerror.h" |
| #include "hw/core/cpu.h" |
| #include "system/physmem.h" |
| #include "migration/misc.h" |
| |
| void qmp_memsave(uint64_t addr, uint64_t size, const char *filename, |
| bool has_cpu, int64_t cpu_index, Error **errp) |
| { |
| FILE *f; |
| uint64_t l; |
| CPUState *cpu; |
| uint8_t buf[1024]; |
| uint64_t orig_addr = addr, orig_size = size; |
| |
| if (migration_guest_ram_loading()) { |
| error_setg(errp, "Guest memory access not allowed during migration"); |
| return; |
| } |
| |
| if (!has_cpu) { |
| cpu_index = 0; |
| } |
| |
| cpu = qemu_get_cpu(cpu_index); |
| if (cpu == NULL) { |
| error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "cpu-index", |
| "a CPU number"); |
| return; |
| } |
| |
| f = fopen(filename, "wb"); |
| if (!f) { |
| error_setg_file_open(errp, errno, filename); |
| return; |
| } |
| |
| while (size != 0) { |
| l = sizeof(buf); |
| if (l > size) { |
| l = size; |
| } |
| if (cpu_memory_rw_debug(cpu, addr, buf, l, 0) != 0) { |
| error_setg(errp, "Invalid addr 0x%016" PRIx64 "/size %" PRIu64 |
| " specified", orig_addr, orig_size); |
| goto exit; |
| } |
| if (fwrite(buf, 1, l, f) != l) { |
| error_setg(errp, "writing memory to '%s' failed", |
| filename); |
| goto exit; |
| } |
| addr += l; |
| size -= l; |
| } |
| |
| exit: |
| fclose(f); |
| } |
| |
| void qmp_pmemsave(uint64_t addr, uint64_t size, const char *filename, |
| Error **errp) |
| { |
| FILE *f; |
| uint64_t l; |
| uint8_t buf[1024]; |
| |
| if (migration_guest_ram_loading()) { |
| error_setg(errp, "Guest memory access not allowed during migration"); |
| return; |
| } |
| |
| f = fopen(filename, "wb"); |
| if (!f) { |
| error_setg_file_open(errp, errno, filename); |
| return; |
| } |
| |
| while (size != 0) { |
| l = sizeof(buf); |
| if (l > size) { |
| l = size; |
| } |
| physical_memory_read(addr, buf, l); |
| if (fwrite(buf, 1, l, f) != l) { |
| error_setg(errp, "writing memory to '%s' failed", |
| filename); |
| goto exit; |
| } |
| addr += l; |
| size -= l; |
| } |
| |
| exit: |
| fclose(f); |
| } |