/* * 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); }