dump patches
Hi Includes: - the first patches from "[PATCH v5 00/18] dump: Add arch section and s390x PV dump" - "[PATCH v2 0/2] Fix dumping in kdump format with non-aligned memory" -----BEGIN PGP SIGNATURE----- iQJQBAABCAA6FiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmM+9UocHG1hcmNhbmRy ZS5sdXJlYXVAcmVkaGF0LmNvbQAKCRDa6OEJdZac5aoMD/0eya5IqxX0ke9jjUcB wWhRbsVdiO9yt2oN3gsQVkUtuK98p7/JpWSKHWXsQQjd7vIYPCj8RBHXZ4Cp71+S n+Db/K22fmWvuP0LtCNzYujq1ZxKdQI8KdKmYwHQdGkgy85QwYO+0SgpVgLjRd/2 1IWzHuzIcEmraxkSLvR8N0lmz/Z2CBc7ME5izO1mHSZrs8Ria2tDpXnz5rFxPy+q TDqo+LP0GIapoHbbE+6JWGL2u9mLiP0sg9SclZOPZG3CsPQ5XYEStyZcLw1YYIO1 rruom463SbP4NJHIRspC8pADFI+d4uBamj/eUu8/9CUVqetk0UpKyXWiqgEDvmkO /2/yFYS60gEghvd3XVnuZnTNeRSDSE1aUXUmKdGqDjYL4DYcsehIQ9z8ut/tuYIO D+4RuiuCmEyznV/DDecnwHhrv9jWftNwdwjW5GAniEjDBp/DtoouAeMArQw9rE1Z mXqTa5NaeW69VTtzxzN25GzSAjiEzFT7UFRt3bT8fb0NX+UOkluD/agBqRIM5lzh KbUJjqWhqA6TnHtDekbNLlmocDCn+NeBeXxDUIa19C4LICCuuxbFU+MG7cvdjSEg sXRB6/qAdWgv4O3zGw1SHff+qmvtHjKVj0ihrNkrrYrL+31O2splqTMeaCqGdq9C elE/TAS46CcMUSYuWzxy6mAMmA== =O9tr -----END PGP SIGNATURE----- Merge tag 'dump-pull-request' of https://gitlab.com/marcandre.lureau/qemu into staging dump patches Hi Includes: - the first patches from "[PATCH v5 00/18] dump: Add arch section and s390x PV dump" - "[PATCH v2 0/2] Fix dumping in kdump format with non-aligned memory" # -----BEGIN PGP SIGNATURE----- # # iQJQBAABCAA6FiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmM+9UocHG1hcmNhbmRy # ZS5sdXJlYXVAcmVkaGF0LmNvbQAKCRDa6OEJdZac5aoMD/0eya5IqxX0ke9jjUcB # wWhRbsVdiO9yt2oN3gsQVkUtuK98p7/JpWSKHWXsQQjd7vIYPCj8RBHXZ4Cp71+S # n+Db/K22fmWvuP0LtCNzYujq1ZxKdQI8KdKmYwHQdGkgy85QwYO+0SgpVgLjRd/2 # 1IWzHuzIcEmraxkSLvR8N0lmz/Z2CBc7ME5izO1mHSZrs8Ria2tDpXnz5rFxPy+q # TDqo+LP0GIapoHbbE+6JWGL2u9mLiP0sg9SclZOPZG3CsPQ5XYEStyZcLw1YYIO1 # rruom463SbP4NJHIRspC8pADFI+d4uBamj/eUu8/9CUVqetk0UpKyXWiqgEDvmkO # /2/yFYS60gEghvd3XVnuZnTNeRSDSE1aUXUmKdGqDjYL4DYcsehIQ9z8ut/tuYIO # D+4RuiuCmEyznV/DDecnwHhrv9jWftNwdwjW5GAniEjDBp/DtoouAeMArQw9rE1Z # mXqTa5NaeW69VTtzxzN25GzSAjiEzFT7UFRt3bT8fb0NX+UOkluD/agBqRIM5lzh # KbUJjqWhqA6TnHtDekbNLlmocDCn+NeBeXxDUIa19C4LICCuuxbFU+MG7cvdjSEg # sXRB6/qAdWgv4O3zGw1SHff+qmvtHjKVj0ihrNkrrYrL+31O2splqTMeaCqGdq9C # elE/TAS46CcMUSYuWzxy6mAMmA== # =O9tr # -----END PGP SIGNATURE----- # gpg: Signature made Thu 06 Oct 2022 11:33:30 EDT # gpg: using RSA key 87A9BD933F87C606D276F62DDAE8E10975969CE5 # gpg: issuer "marcandre.lureau@redhat.com" # gpg: Good signature from "Marc-André Lureau <marcandre.lureau@redhat.com>" [full] # gpg: aka "Marc-André Lureau <marcandre.lureau@gmail.com>" [full] # Primary key fingerprint: 87A9 BD93 3F87 C606 D276 F62D DAE8 E109 7596 9CE5 * tag 'dump-pull-request' of https://gitlab.com/marcandre.lureau/qemu: dump: fix kdump to work over non-aligned blocks dump: simplify a bit kdump get_next_page() dump: Rename write_elf*_phdr_note to prepare_elf*_phdr_note dump: Split elf header functions into prepare and write dump: Rework dump_calculate_size function dump: Rework filter area variables dump: Rework get_start_block dump: Refactor dump_iterate and introduce dump_filter_memblock_*() dump: Rename write_elf_loads to write_elf_phdr_loads dump: Replace opaque DumpState pointer with a typed one Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
commit
42e1e350bf
343
dump/dump.c
343
dump/dump.c
@ -59,6 +59,11 @@ static inline bool dump_is_64bit(DumpState *s)
|
|||||||
return s->dump_info.d_class == ELFCLASS64;
|
return s->dump_info.d_class == ELFCLASS64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool dump_has_filter(DumpState *s)
|
||||||
|
{
|
||||||
|
return s->filter_area_length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t cpu_to_dump16(DumpState *s, uint16_t val)
|
uint16_t cpu_to_dump16(DumpState *s, uint16_t val)
|
||||||
{
|
{
|
||||||
if (s->dump_info.d_endian == ELFDATA2LSB) {
|
if (s->dump_info.d_endian == ELFDATA2LSB) {
|
||||||
@ -126,7 +131,7 @@ static int fd_write_vmcore(const void *buf, size_t size, void *opaque)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_elf64_header(DumpState *s, Error **errp)
|
static void prepare_elf64_header(DumpState *s, Elf64_Ehdr *elf_header)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* phnum in the elf header is 16 bit, if we have more segments we
|
* phnum in the elf header is 16 bit, if we have more segments we
|
||||||
@ -134,34 +139,27 @@ static void write_elf64_header(DumpState *s, Error **errp)
|
|||||||
* special section.
|
* special section.
|
||||||
*/
|
*/
|
||||||
uint16_t phnum = MIN(s->phdr_num, PN_XNUM);
|
uint16_t phnum = MIN(s->phdr_num, PN_XNUM);
|
||||||
Elf64_Ehdr elf_header;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
memset(&elf_header, 0, sizeof(Elf64_Ehdr));
|
memset(elf_header, 0, sizeof(Elf64_Ehdr));
|
||||||
memcpy(&elf_header, ELFMAG, SELFMAG);
|
memcpy(elf_header, ELFMAG, SELFMAG);
|
||||||
elf_header.e_ident[EI_CLASS] = ELFCLASS64;
|
elf_header->e_ident[EI_CLASS] = ELFCLASS64;
|
||||||
elf_header.e_ident[EI_DATA] = s->dump_info.d_endian;
|
elf_header->e_ident[EI_DATA] = s->dump_info.d_endian;
|
||||||
elf_header.e_ident[EI_VERSION] = EV_CURRENT;
|
elf_header->e_ident[EI_VERSION] = EV_CURRENT;
|
||||||
elf_header.e_type = cpu_to_dump16(s, ET_CORE);
|
elf_header->e_type = cpu_to_dump16(s, ET_CORE);
|
||||||
elf_header.e_machine = cpu_to_dump16(s, s->dump_info.d_machine);
|
elf_header->e_machine = cpu_to_dump16(s, s->dump_info.d_machine);
|
||||||
elf_header.e_version = cpu_to_dump32(s, EV_CURRENT);
|
elf_header->e_version = cpu_to_dump32(s, EV_CURRENT);
|
||||||
elf_header.e_ehsize = cpu_to_dump16(s, sizeof(elf_header));
|
elf_header->e_ehsize = cpu_to_dump16(s, sizeof(elf_header));
|
||||||
elf_header.e_phoff = cpu_to_dump64(s, s->phdr_offset);
|
elf_header->e_phoff = cpu_to_dump64(s, s->phdr_offset);
|
||||||
elf_header.e_phentsize = cpu_to_dump16(s, sizeof(Elf64_Phdr));
|
elf_header->e_phentsize = cpu_to_dump16(s, sizeof(Elf64_Phdr));
|
||||||
elf_header.e_phnum = cpu_to_dump16(s, phnum);
|
elf_header->e_phnum = cpu_to_dump16(s, phnum);
|
||||||
if (s->shdr_num) {
|
if (s->shdr_num) {
|
||||||
elf_header.e_shoff = cpu_to_dump64(s, s->shdr_offset);
|
elf_header->e_shoff = cpu_to_dump64(s, s->shdr_offset);
|
||||||
elf_header.e_shentsize = cpu_to_dump16(s, sizeof(Elf64_Shdr));
|
elf_header->e_shentsize = cpu_to_dump16(s, sizeof(Elf64_Shdr));
|
||||||
elf_header.e_shnum = cpu_to_dump16(s, s->shdr_num);
|
elf_header->e_shnum = cpu_to_dump16(s, s->shdr_num);
|
||||||
}
|
|
||||||
|
|
||||||
ret = fd_write_vmcore(&elf_header, sizeof(elf_header), s);
|
|
||||||
if (ret < 0) {
|
|
||||||
error_setg_errno(errp, -ret, "dump: failed to write elf header");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_elf32_header(DumpState *s, Error **errp)
|
static void prepare_elf32_header(DumpState *s, Elf32_Ehdr *elf_header)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* phnum in the elf header is 16 bit, if we have more segments we
|
* phnum in the elf header is 16 bit, if we have more segments we
|
||||||
@ -169,28 +167,45 @@ static void write_elf32_header(DumpState *s, Error **errp)
|
|||||||
* special section.
|
* special section.
|
||||||
*/
|
*/
|
||||||
uint16_t phnum = MIN(s->phdr_num, PN_XNUM);
|
uint16_t phnum = MIN(s->phdr_num, PN_XNUM);
|
||||||
Elf32_Ehdr elf_header;
|
|
||||||
|
memset(elf_header, 0, sizeof(Elf32_Ehdr));
|
||||||
|
memcpy(elf_header, ELFMAG, SELFMAG);
|
||||||
|
elf_header->e_ident[EI_CLASS] = ELFCLASS32;
|
||||||
|
elf_header->e_ident[EI_DATA] = s->dump_info.d_endian;
|
||||||
|
elf_header->e_ident[EI_VERSION] = EV_CURRENT;
|
||||||
|
elf_header->e_type = cpu_to_dump16(s, ET_CORE);
|
||||||
|
elf_header->e_machine = cpu_to_dump16(s, s->dump_info.d_machine);
|
||||||
|
elf_header->e_version = cpu_to_dump32(s, EV_CURRENT);
|
||||||
|
elf_header->e_ehsize = cpu_to_dump16(s, sizeof(elf_header));
|
||||||
|
elf_header->e_phoff = cpu_to_dump32(s, s->phdr_offset);
|
||||||
|
elf_header->e_phentsize = cpu_to_dump16(s, sizeof(Elf32_Phdr));
|
||||||
|
elf_header->e_phnum = cpu_to_dump16(s, phnum);
|
||||||
|
if (s->shdr_num) {
|
||||||
|
elf_header->e_shoff = cpu_to_dump32(s, s->shdr_offset);
|
||||||
|
elf_header->e_shentsize = cpu_to_dump16(s, sizeof(Elf32_Shdr));
|
||||||
|
elf_header->e_shnum = cpu_to_dump16(s, s->shdr_num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_elf_header(DumpState *s, Error **errp)
|
||||||
|
{
|
||||||
|
Elf32_Ehdr elf32_header;
|
||||||
|
Elf64_Ehdr elf64_header;
|
||||||
|
size_t header_size;
|
||||||
|
void *header_ptr;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
memset(&elf_header, 0, sizeof(Elf32_Ehdr));
|
if (dump_is_64bit(s)) {
|
||||||
memcpy(&elf_header, ELFMAG, SELFMAG);
|
prepare_elf64_header(s, &elf64_header);
|
||||||
elf_header.e_ident[EI_CLASS] = ELFCLASS32;
|
header_size = sizeof(elf64_header);
|
||||||
elf_header.e_ident[EI_DATA] = s->dump_info.d_endian;
|
header_ptr = &elf64_header;
|
||||||
elf_header.e_ident[EI_VERSION] = EV_CURRENT;
|
} else {
|
||||||
elf_header.e_type = cpu_to_dump16(s, ET_CORE);
|
prepare_elf32_header(s, &elf32_header);
|
||||||
elf_header.e_machine = cpu_to_dump16(s, s->dump_info.d_machine);
|
header_size = sizeof(elf32_header);
|
||||||
elf_header.e_version = cpu_to_dump32(s, EV_CURRENT);
|
header_ptr = &elf32_header;
|
||||||
elf_header.e_ehsize = cpu_to_dump16(s, sizeof(elf_header));
|
|
||||||
elf_header.e_phoff = cpu_to_dump32(s, s->phdr_offset);
|
|
||||||
elf_header.e_phentsize = cpu_to_dump16(s, sizeof(Elf32_Phdr));
|
|
||||||
elf_header.e_phnum = cpu_to_dump16(s, phnum);
|
|
||||||
if (s->shdr_num) {
|
|
||||||
elf_header.e_shoff = cpu_to_dump32(s, s->shdr_offset);
|
|
||||||
elf_header.e_shentsize = cpu_to_dump16(s, sizeof(Elf32_Shdr));
|
|
||||||
elf_header.e_shnum = cpu_to_dump16(s, s->shdr_num);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = fd_write_vmcore(&elf_header, sizeof(elf_header), s);
|
ret = fd_write_vmcore(header_ptr, header_size, s);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_setg_errno(errp, -ret, "dump: failed to write elf header");
|
error_setg_errno(errp, -ret, "dump: failed to write elf header");
|
||||||
}
|
}
|
||||||
@ -245,7 +260,7 @@ static void write_elf32_load(DumpState *s, MemoryMapping *memory_mapping,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_elf64_phdr_note(DumpState *s, Elf64_Phdr *phdr)
|
static void prepare_elf64_phdr_note(DumpState *s, Elf64_Phdr *phdr)
|
||||||
{
|
{
|
||||||
memset(phdr, 0, sizeof(*phdr));
|
memset(phdr, 0, sizeof(*phdr));
|
||||||
phdr->p_type = cpu_to_dump32(s, PT_NOTE);
|
phdr->p_type = cpu_to_dump32(s, PT_NOTE);
|
||||||
@ -301,7 +316,7 @@ static void write_elf64_notes(WriteCoreDumpFunction f, DumpState *s,
|
|||||||
write_guest_note(f, s, errp);
|
write_guest_note(f, s, errp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_elf32_phdr_note(DumpState *s, Elf32_Phdr *phdr)
|
static void prepare_elf32_phdr_note(DumpState *s, Elf32_Phdr *phdr)
|
||||||
{
|
{
|
||||||
memset(phdr, 0, sizeof(*phdr));
|
memset(phdr, 0, sizeof(*phdr));
|
||||||
phdr->p_type = cpu_to_dump32(s, PT_NOTE);
|
phdr->p_type = cpu_to_dump32(s, PT_NOTE);
|
||||||
@ -349,11 +364,11 @@ static void write_elf_phdr_note(DumpState *s, Error **errp)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (dump_is_64bit(s)) {
|
if (dump_is_64bit(s)) {
|
||||||
write_elf64_phdr_note(s, &phdr64);
|
prepare_elf64_phdr_note(s, &phdr64);
|
||||||
size = sizeof(phdr64);
|
size = sizeof(phdr64);
|
||||||
phdr = &phdr64;
|
phdr = &phdr64;
|
||||||
} else {
|
} else {
|
||||||
write_elf32_phdr_note(s, &phdr32);
|
prepare_elf32_phdr_note(s, &phdr32);
|
||||||
size = sizeof(phdr32);
|
size = sizeof(phdr32);
|
||||||
phdr = &phdr32;
|
phdr = &phdr32;
|
||||||
}
|
}
|
||||||
@ -443,29 +458,30 @@ static void get_offset_range(hwaddr phys_addr,
|
|||||||
*p_offset = -1;
|
*p_offset = -1;
|
||||||
*p_filesz = 0;
|
*p_filesz = 0;
|
||||||
|
|
||||||
if (s->has_filter) {
|
if (dump_has_filter(s)) {
|
||||||
if (phys_addr < s->begin || phys_addr >= s->begin + s->length) {
|
if (phys_addr < s->filter_area_begin ||
|
||||||
|
phys_addr >= s->filter_area_begin + s->filter_area_length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) {
|
QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) {
|
||||||
if (s->has_filter) {
|
if (dump_has_filter(s)) {
|
||||||
if (block->target_start >= s->begin + s->length ||
|
if (block->target_start >= s->filter_area_begin + s->filter_area_length ||
|
||||||
block->target_end <= s->begin) {
|
block->target_end <= s->filter_area_begin) {
|
||||||
/* This block is out of the range */
|
/* This block is out of the range */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->begin <= block->target_start) {
|
if (s->filter_area_begin <= block->target_start) {
|
||||||
start = block->target_start;
|
start = block->target_start;
|
||||||
} else {
|
} else {
|
||||||
start = s->begin;
|
start = s->filter_area_begin;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_in_block = block->target_end - start;
|
size_in_block = block->target_end - start;
|
||||||
if (s->begin + s->length < block->target_end) {
|
if (s->filter_area_begin + s->filter_area_length < block->target_end) {
|
||||||
size_in_block -= block->target_end - (s->begin + s->length);
|
size_in_block -= block->target_end - (s->filter_area_begin + s->filter_area_length);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
start = block->target_start;
|
start = block->target_start;
|
||||||
@ -490,7 +506,7 @@ static void get_offset_range(hwaddr phys_addr,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_elf_loads(DumpState *s, Error **errp)
|
static void write_elf_phdr_loads(DumpState *s, Error **errp)
|
||||||
{
|
{
|
||||||
ERRP_GUARD();
|
ERRP_GUARD();
|
||||||
hwaddr offset, filesz;
|
hwaddr offset, filesz;
|
||||||
@ -558,11 +574,7 @@ static void dump_begin(DumpState *s, Error **errp)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* write elf header to vmcore */
|
/* write elf header to vmcore */
|
||||||
if (dump_is_64bit(s)) {
|
write_elf_header(s, errp);
|
||||||
write_elf64_header(s, errp);
|
|
||||||
} else {
|
|
||||||
write_elf32_header(s, errp);
|
|
||||||
}
|
|
||||||
if (*errp) {
|
if (*errp) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -573,8 +585,8 @@ static void dump_begin(DumpState *s, Error **errp)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write all PT_LOAD to vmcore */
|
/* write all PT_LOADs to vmcore */
|
||||||
write_elf_loads(s, errp);
|
write_elf_phdr_loads(s, errp);
|
||||||
if (*errp) {
|
if (*errp) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -591,31 +603,43 @@ static void dump_begin(DumpState *s, Error **errp)
|
|||||||
write_elf_notes(s, errp);
|
write_elf_notes(s, errp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_next_block(DumpState *s, GuestPhysBlock *block)
|
static int64_t dump_filtered_memblock_size(GuestPhysBlock *block,
|
||||||
|
int64_t filter_area_start,
|
||||||
|
int64_t filter_area_length)
|
||||||
{
|
{
|
||||||
while (1) {
|
int64_t size, left, right;
|
||||||
block = QTAILQ_NEXT(block, next);
|
|
||||||
if (!block) {
|
/* No filter, return full size */
|
||||||
/* no more block */
|
if (!filter_area_length) {
|
||||||
return 1;
|
return block->target_end - block->target_start;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->start = 0;
|
/* calculate the overlapped region. */
|
||||||
s->next_block = block;
|
left = MAX(filter_area_start, block->target_start);
|
||||||
if (s->has_filter) {
|
right = MIN(filter_area_start + filter_area_length, block->target_end);
|
||||||
if (block->target_start >= s->begin + s->length ||
|
size = right - left;
|
||||||
block->target_end <= s->begin) {
|
size = size > 0 ? size : 0;
|
||||||
/* This block is out of the range */
|
|
||||||
continue;
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int64_t dump_filtered_memblock_start(GuestPhysBlock *block,
|
||||||
|
int64_t filter_area_start,
|
||||||
|
int64_t filter_area_length)
|
||||||
|
{
|
||||||
|
if (filter_area_length) {
|
||||||
|
/* return -1 if the block is not within filter area */
|
||||||
|
if (block->target_start >= filter_area_start + filter_area_length ||
|
||||||
|
block->target_end <= filter_area_start) {
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->begin > block->target_start) {
|
if (filter_area_start > block->target_start) {
|
||||||
s->start = s->begin - block->target_start;
|
return filter_area_start - block->target_start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write all memory to vmcore */
|
/* write all memory to vmcore */
|
||||||
@ -623,24 +647,22 @@ static void dump_iterate(DumpState *s, Error **errp)
|
|||||||
{
|
{
|
||||||
ERRP_GUARD();
|
ERRP_GUARD();
|
||||||
GuestPhysBlock *block;
|
GuestPhysBlock *block;
|
||||||
int64_t size;
|
int64_t memblock_size, memblock_start;
|
||||||
|
|
||||||
do {
|
QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) {
|
||||||
block = s->next_block;
|
memblock_start = dump_filtered_memblock_start(block, s->filter_area_begin, s->filter_area_length);
|
||||||
|
if (memblock_start == -1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
size = block->target_end - block->target_start;
|
memblock_size = dump_filtered_memblock_size(block, s->filter_area_begin, s->filter_area_length);
|
||||||
if (s->has_filter) {
|
|
||||||
size -= s->start;
|
/* Write the memory to file */
|
||||||
if (s->begin + s->length < block->target_end) {
|
write_memory(s, block, memblock_start, memblock_size, errp);
|
||||||
size -= block->target_end - (s->begin + s->length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
write_memory(s, block, s->start, size, errp);
|
|
||||||
if (*errp) {
|
if (*errp) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} while (!get_next_block(s, block));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void create_vmcore(DumpState *s, Error **errp)
|
static void create_vmcore(DumpState *s, Error **errp)
|
||||||
@ -1094,55 +1116,81 @@ static uint64_t dump_pfn_to_paddr(DumpState *s, uint64_t pfn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* exam every page and return the page frame number and the address of the page.
|
* Return the page frame number and the page content in *bufptr. bufptr can be
|
||||||
* bufptr can be NULL. note: the blocks here is supposed to reflect guest-phys
|
* NULL. If not NULL, *bufptr must contains a target page size of pre-allocated
|
||||||
* blocks, so block->target_start and block->target_end should be interal
|
* memory. This is not necessarily the memory returned.
|
||||||
* multiples of the target page size.
|
|
||||||
*/
|
*/
|
||||||
static bool get_next_page(GuestPhysBlock **blockptr, uint64_t *pfnptr,
|
static bool get_next_page(GuestPhysBlock **blockptr, uint64_t *pfnptr,
|
||||||
uint8_t **bufptr, DumpState *s)
|
uint8_t **bufptr, DumpState *s)
|
||||||
{
|
{
|
||||||
GuestPhysBlock *block = *blockptr;
|
GuestPhysBlock *block = *blockptr;
|
||||||
hwaddr addr, target_page_mask = ~((hwaddr)s->dump_info.page_size - 1);
|
uint32_t page_size = s->dump_info.page_size;
|
||||||
uint8_t *buf;
|
uint8_t *buf = NULL, *hbuf;
|
||||||
|
hwaddr addr;
|
||||||
|
|
||||||
/* block == NULL means the start of the iteration */
|
/* block == NULL means the start of the iteration */
|
||||||
if (!block) {
|
if (!block) {
|
||||||
block = QTAILQ_FIRST(&s->guest_phys_blocks.head);
|
block = QTAILQ_FIRST(&s->guest_phys_blocks.head);
|
||||||
*blockptr = block;
|
*blockptr = block;
|
||||||
assert((block->target_start & ~target_page_mask) == 0);
|
addr = block->target_start;
|
||||||
assert((block->target_end & ~target_page_mask) == 0);
|
*pfnptr = dump_paddr_to_pfn(s, addr);
|
||||||
*pfnptr = dump_paddr_to_pfn(s, block->target_start);
|
} else {
|
||||||
if (bufptr) {
|
*pfnptr += 1;
|
||||||
*bufptr = block->host_addr;
|
addr = dump_pfn_to_paddr(s, *pfnptr);
|
||||||
}
|
}
|
||||||
|
assert(block != NULL);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (addr >= block->target_start && addr < block->target_end) {
|
||||||
|
size_t n = MIN(block->target_end - addr, page_size - addr % page_size);
|
||||||
|
hbuf = block->host_addr + (addr - block->target_start);
|
||||||
|
if (!buf) {
|
||||||
|
if (n == page_size) {
|
||||||
|
/* this is a whole target page, go for it */
|
||||||
|
assert(addr % page_size == 0);
|
||||||
|
buf = hbuf;
|
||||||
|
break;
|
||||||
|
} else if (bufptr) {
|
||||||
|
assert(*bufptr);
|
||||||
|
buf = *bufptr;
|
||||||
|
memset(buf, 0, page_size);
|
||||||
|
} else {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
*pfnptr = *pfnptr + 1;
|
memcpy(buf + addr % page_size, hbuf, n);
|
||||||
addr = dump_pfn_to_paddr(s, *pfnptr);
|
addr += n;
|
||||||
|
if (addr % page_size == 0) {
|
||||||
if ((addr >= block->target_start) &&
|
/* we filled up the page */
|
||||||
(addr + s->dump_info.page_size <= block->target_end)) {
|
break;
|
||||||
buf = block->host_addr + (addr - block->target_start);
|
}
|
||||||
} else {
|
} else {
|
||||||
/* the next page is in the next block */
|
/* the next page is in the next block */
|
||||||
block = QTAILQ_NEXT(block, next);
|
*blockptr = block = QTAILQ_NEXT(block, next);
|
||||||
*blockptr = block;
|
|
||||||
if (!block) {
|
if (!block) {
|
||||||
return false;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = block->target_start;
|
||||||
|
/* are we still in the same page? */
|
||||||
|
if (dump_paddr_to_pfn(s, addr) != *pfnptr) {
|
||||||
|
if (buf) {
|
||||||
|
/* no, but we already filled something earlier, return it */
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
/* else continue from there */
|
||||||
|
*pfnptr = dump_paddr_to_pfn(s, addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
assert((block->target_start & ~target_page_mask) == 0);
|
|
||||||
assert((block->target_end & ~target_page_mask) == 0);
|
|
||||||
*pfnptr = dump_paddr_to_pfn(s, block->target_start);
|
|
||||||
buf = block->host_addr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bufptr) {
|
if (bufptr) {
|
||||||
*bufptr = buf;
|
*bufptr = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return buf != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_dump_bitmap(DumpState *s, Error **errp)
|
static void write_dump_bitmap(DumpState *s, Error **errp)
|
||||||
@ -1280,6 +1328,7 @@ static void write_dump_pages(DumpState *s, Error **errp)
|
|||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
GuestPhysBlock *block_iter = NULL;
|
GuestPhysBlock *block_iter = NULL;
|
||||||
uint64_t pfn_iter;
|
uint64_t pfn_iter;
|
||||||
|
g_autofree uint8_t *page = NULL;
|
||||||
|
|
||||||
/* get offset of page_desc and page_data in dump file */
|
/* get offset of page_desc and page_data in dump file */
|
||||||
offset_desc = s->offset_page;
|
offset_desc = s->offset_page;
|
||||||
@ -1315,12 +1364,13 @@ static void write_dump_pages(DumpState *s, Error **errp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
offset_data += s->dump_info.page_size;
|
offset_data += s->dump_info.page_size;
|
||||||
|
page = g_malloc(s->dump_info.page_size);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* dump memory to vmcore page by page. zero page will all be resided in the
|
* dump memory to vmcore page by page. zero page will all be resided in the
|
||||||
* first page of page section
|
* first page of page section
|
||||||
*/
|
*/
|
||||||
while (get_next_page(&block_iter, &pfn_iter, &buf, s)) {
|
for (buf = page; get_next_page(&block_iter, &pfn_iter, &buf, s); buf = page) {
|
||||||
/* check zero page */
|
/* check zero page */
|
||||||
if (buffer_is_zero(buf, s->dump_info.page_size)) {
|
if (buffer_is_zero(buf, s->dump_info.page_size)) {
|
||||||
ret = write_cache(&page_desc, &pd_zero, sizeof(PageDescriptor),
|
ret = write_cache(&page_desc, &pd_zero, sizeof(PageDescriptor),
|
||||||
@ -1490,29 +1540,21 @@ static void create_kdump_vmcore(DumpState *s, Error **errp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static ram_addr_t get_start_block(DumpState *s)
|
static int validate_start_block(DumpState *s)
|
||||||
{
|
{
|
||||||
GuestPhysBlock *block;
|
GuestPhysBlock *block;
|
||||||
|
|
||||||
if (!s->has_filter) {
|
if (!dump_has_filter(s)) {
|
||||||
s->next_block = QTAILQ_FIRST(&s->guest_phys_blocks.head);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) {
|
QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) {
|
||||||
if (block->target_start >= s->begin + s->length ||
|
|
||||||
block->target_end <= s->begin) {
|
|
||||||
/* This block is out of the range */
|
/* This block is out of the range */
|
||||||
|
if (block->target_start >= s->filter_area_begin + s->filter_area_length ||
|
||||||
|
block->target_end <= s->filter_area_begin) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
s->next_block = block;
|
|
||||||
if (s->begin > block->target_start) {
|
|
||||||
s->start = s->begin - block->target_start;
|
|
||||||
} else {
|
|
||||||
s->start = 0;
|
|
||||||
}
|
|
||||||
return s->start;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
@ -1540,25 +1582,19 @@ bool qemu_system_dump_in_progress(void)
|
|||||||
return (qatomic_read(&state->status) == DUMP_STATUS_ACTIVE);
|
return (qatomic_read(&state->status) == DUMP_STATUS_ACTIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* calculate total size of memory to be dumped (taking filter into
|
/*
|
||||||
* acoount.) */
|
* calculate total size of memory to be dumped (taking filter into
|
||||||
|
* account.)
|
||||||
|
*/
|
||||||
static int64_t dump_calculate_size(DumpState *s)
|
static int64_t dump_calculate_size(DumpState *s)
|
||||||
{
|
{
|
||||||
GuestPhysBlock *block;
|
GuestPhysBlock *block;
|
||||||
int64_t size = 0, total = 0, left = 0, right = 0;
|
int64_t total = 0;
|
||||||
|
|
||||||
QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) {
|
QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) {
|
||||||
if (s->has_filter) {
|
total += dump_filtered_memblock_size(block,
|
||||||
/* calculate the overlapped region. */
|
s->filter_area_begin,
|
||||||
left = MAX(s->begin, block->target_start);
|
s->filter_area_length);
|
||||||
right = MIN(s->begin + s->length, block->target_end);
|
|
||||||
size = right - left;
|
|
||||||
size = size > 0 ? size : 0;
|
|
||||||
} else {
|
|
||||||
/* count the whole region in */
|
|
||||||
size = (block->target_end - block->target_start);
|
|
||||||
}
|
|
||||||
total += size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return total;
|
return total;
|
||||||
@ -1641,9 +1677,12 @@ static void dump_init(DumpState *s, int fd, bool has_format,
|
|||||||
}
|
}
|
||||||
|
|
||||||
s->fd = fd;
|
s->fd = fd;
|
||||||
s->has_filter = has_filter;
|
if (has_filter && !length) {
|
||||||
s->begin = begin;
|
error_setg(errp, QERR_INVALID_PARAMETER, "length");
|
||||||
s->length = length;
|
goto cleanup;
|
||||||
|
}
|
||||||
|
s->filter_area_begin = begin;
|
||||||
|
s->filter_area_length = length;
|
||||||
|
|
||||||
memory_mapping_list_init(&s->list);
|
memory_mapping_list_init(&s->list);
|
||||||
|
|
||||||
@ -1660,8 +1699,8 @@ static void dump_init(DumpState *s, int fd, bool has_format,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->start = get_start_block(s);
|
/* Is the filter filtering everything? */
|
||||||
if (s->start == -1) {
|
if (validate_start_block(s) == -1) {
|
||||||
error_setg(errp, QERR_INVALID_PARAMETER, "begin");
|
error_setg(errp, QERR_INVALID_PARAMETER, "begin");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -1776,8 +1815,8 @@ static void dump_init(DumpState *s, int fd, bool has_format,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->has_filter) {
|
if (dump_has_filter(s)) {
|
||||||
memory_mapping_filter(&s->list, s->begin, s->length);
|
memory_mapping_filter(&s->list, s->filter_area_begin, s->filter_area_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -53,25 +53,25 @@ typedef struct SysemuCPUOps {
|
|||||||
* 32-bit VM coredump.
|
* 32-bit VM coredump.
|
||||||
*/
|
*/
|
||||||
int (*write_elf32_note)(WriteCoreDumpFunction f, CPUState *cpu,
|
int (*write_elf32_note)(WriteCoreDumpFunction f, CPUState *cpu,
|
||||||
int cpuid, void *opaque);
|
int cpuid, DumpState *s);
|
||||||
/**
|
/**
|
||||||
* @write_elf64_note: Callback for writing a CPU-specific ELF note to a
|
* @write_elf64_note: Callback for writing a CPU-specific ELF note to a
|
||||||
* 64-bit VM coredump.
|
* 64-bit VM coredump.
|
||||||
*/
|
*/
|
||||||
int (*write_elf64_note)(WriteCoreDumpFunction f, CPUState *cpu,
|
int (*write_elf64_note)(WriteCoreDumpFunction f, CPUState *cpu,
|
||||||
int cpuid, void *opaque);
|
int cpuid, DumpState *s);
|
||||||
/**
|
/**
|
||||||
* @write_elf32_qemunote: Callback for writing a CPU- and QEMU-specific ELF
|
* @write_elf32_qemunote: Callback for writing a CPU- and QEMU-specific ELF
|
||||||
* note to a 32-bit VM coredump.
|
* note to a 32-bit VM coredump.
|
||||||
*/
|
*/
|
||||||
int (*write_elf32_qemunote)(WriteCoreDumpFunction f, CPUState *cpu,
|
int (*write_elf32_qemunote)(WriteCoreDumpFunction f, CPUState *cpu,
|
||||||
void *opaque);
|
DumpState *s);
|
||||||
/**
|
/**
|
||||||
* @write_elf64_qemunote: Callback for writing a CPU- and QEMU-specific ELF
|
* @write_elf64_qemunote: Callback for writing a CPU- and QEMU-specific ELF
|
||||||
* note to a 64-bit VM coredump.
|
* note to a 64-bit VM coredump.
|
||||||
*/
|
*/
|
||||||
int (*write_elf64_qemunote)(WriteCoreDumpFunction f, CPUState *cpu,
|
int (*write_elf64_qemunote)(WriteCoreDumpFunction f, CPUState *cpu,
|
||||||
void *opaque);
|
DumpState *s);
|
||||||
/**
|
/**
|
||||||
* @virtio_is_big_endian: Callback to return %true if a CPU which supports
|
* @virtio_is_big_endian: Callback to return %true if a CPU which supports
|
||||||
* runtime configurable endianness is currently big-endian.
|
* runtime configurable endianness is currently big-endian.
|
||||||
|
@ -131,6 +131,7 @@ typedef struct VirtIODevice VirtIODevice;
|
|||||||
typedef struct Visitor Visitor;
|
typedef struct Visitor Visitor;
|
||||||
typedef struct VMChangeStateEntry VMChangeStateEntry;
|
typedef struct VMChangeStateEntry VMChangeStateEntry;
|
||||||
typedef struct VMStateDescription VMStateDescription;
|
typedef struct VMStateDescription VMStateDescription;
|
||||||
|
typedef struct DumpState DumpState;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pointer types
|
* Pointer types
|
||||||
|
@ -166,11 +166,16 @@ typedef struct DumpState {
|
|||||||
hwaddr memory_offset;
|
hwaddr memory_offset;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
GuestPhysBlock *next_block;
|
/*
|
||||||
ram_addr_t start;
|
* Dump filter area variables
|
||||||
bool has_filter;
|
*
|
||||||
int64_t begin;
|
* A filtered dump only contains the guest memory designated by
|
||||||
int64_t length;
|
* the start address and length variables defined below.
|
||||||
|
*
|
||||||
|
* If length is 0, no filtering is applied.
|
||||||
|
*/
|
||||||
|
int64_t filter_area_begin; /* Start address of partial guest memory area */
|
||||||
|
int64_t filter_area_length; /* Length of partial guest memory area */
|
||||||
|
|
||||||
uint8_t *note_buf; /* buffer for notes */
|
uint8_t *note_buf; /* buffer for notes */
|
||||||
size_t note_buf_offset; /* the writing place in note_buf */
|
size_t note_buf_offset; /* the writing place in note_buf */
|
||||||
|
@ -232,12 +232,11 @@ static int aarch64_write_elf64_sve(WriteCoreDumpFunction f,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
int arm_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
|
int arm_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
|
||||||
int cpuid, void *opaque)
|
int cpuid, DumpState *s)
|
||||||
{
|
{
|
||||||
struct aarch64_note note;
|
struct aarch64_note note;
|
||||||
ARMCPU *cpu = ARM_CPU(cs);
|
ARMCPU *cpu = ARM_CPU(cs);
|
||||||
CPUARMState *env = &cpu->env;
|
CPUARMState *env = &cpu->env;
|
||||||
DumpState *s = opaque;
|
|
||||||
uint64_t pstate, sp;
|
uint64_t pstate, sp;
|
||||||
int ret, i;
|
int ret, i;
|
||||||
|
|
||||||
@ -360,12 +359,11 @@ static int arm_write_elf32_vfp(WriteCoreDumpFunction f, CPUARMState *env,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int arm_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
|
int arm_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
|
||||||
int cpuid, void *opaque)
|
int cpuid, DumpState *s)
|
||||||
{
|
{
|
||||||
struct arm_note note;
|
struct arm_note note;
|
||||||
ARMCPU *cpu = ARM_CPU(cs);
|
ARMCPU *cpu = ARM_CPU(cs);
|
||||||
CPUARMState *env = &cpu->env;
|
CPUARMState *env = &cpu->env;
|
||||||
DumpState *s = opaque;
|
|
||||||
int ret, i;
|
int ret, i;
|
||||||
bool fpvalid = cpu_isar_feature(aa32_vfp_simd, cpu);
|
bool fpvalid = cpu_isar_feature(aa32_vfp_simd, cpu);
|
||||||
|
|
||||||
|
@ -1102,9 +1102,9 @@ int arm_gen_dynamic_svereg_xml(CPUState *cpu, int base_reg);
|
|||||||
const char *arm_gdb_get_dynamic_xml(CPUState *cpu, const char *xmlname);
|
const char *arm_gdb_get_dynamic_xml(CPUState *cpu, const char *xmlname);
|
||||||
|
|
||||||
int arm_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
|
int arm_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
|
||||||
int cpuid, void *opaque);
|
int cpuid, DumpState *s);
|
||||||
int arm_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
|
int arm_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
|
||||||
int cpuid, void *opaque);
|
int cpuid, DumpState *s);
|
||||||
|
|
||||||
#ifdef TARGET_AARCH64
|
#ifdef TARGET_AARCH64
|
||||||
int aarch64_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
|
int aarch64_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
|
||||||
|
@ -42,7 +42,7 @@ typedef struct {
|
|||||||
|
|
||||||
static int x86_64_write_elf64_note(WriteCoreDumpFunction f,
|
static int x86_64_write_elf64_note(WriteCoreDumpFunction f,
|
||||||
CPUX86State *env, int id,
|
CPUX86State *env, int id,
|
||||||
void *opaque)
|
DumpState *s)
|
||||||
{
|
{
|
||||||
x86_64_user_regs_struct regs;
|
x86_64_user_regs_struct regs;
|
||||||
Elf64_Nhdr *note;
|
Elf64_Nhdr *note;
|
||||||
@ -94,7 +94,7 @@ static int x86_64_write_elf64_note(WriteCoreDumpFunction f,
|
|||||||
buf += descsz - sizeof(x86_64_user_regs_struct)-sizeof(target_ulong);
|
buf += descsz - sizeof(x86_64_user_regs_struct)-sizeof(target_ulong);
|
||||||
memcpy(buf, ®s, sizeof(x86_64_user_regs_struct));
|
memcpy(buf, ®s, sizeof(x86_64_user_regs_struct));
|
||||||
|
|
||||||
ret = f(note, note_size, opaque);
|
ret = f(note, note_size, s);
|
||||||
g_free(note);
|
g_free(note);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -148,7 +148,7 @@ static void x86_fill_elf_prstatus(x86_elf_prstatus *prstatus, CPUX86State *env,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int x86_write_elf64_note(WriteCoreDumpFunction f, CPUX86State *env,
|
static int x86_write_elf64_note(WriteCoreDumpFunction f, CPUX86State *env,
|
||||||
int id, void *opaque)
|
int id, DumpState *s)
|
||||||
{
|
{
|
||||||
x86_elf_prstatus prstatus;
|
x86_elf_prstatus prstatus;
|
||||||
Elf64_Nhdr *note;
|
Elf64_Nhdr *note;
|
||||||
@ -170,7 +170,7 @@ static int x86_write_elf64_note(WriteCoreDumpFunction f, CPUX86State *env,
|
|||||||
buf += ROUND_UP(name_size, 4);
|
buf += ROUND_UP(name_size, 4);
|
||||||
memcpy(buf, &prstatus, sizeof(prstatus));
|
memcpy(buf, &prstatus, sizeof(prstatus));
|
||||||
|
|
||||||
ret = f(note, note_size, opaque);
|
ret = f(note, note_size, s);
|
||||||
g_free(note);
|
g_free(note);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -180,7 +180,7 @@ static int x86_write_elf64_note(WriteCoreDumpFunction f, CPUX86State *env,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int x86_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
|
int x86_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
|
||||||
int cpuid, void *opaque)
|
int cpuid, DumpState *s)
|
||||||
{
|
{
|
||||||
X86CPU *cpu = X86_CPU(cs);
|
X86CPU *cpu = X86_CPU(cs);
|
||||||
int ret;
|
int ret;
|
||||||
@ -189,10 +189,10 @@ int x86_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
|
|||||||
bool lma = !!(first_x86_cpu->env.hflags & HF_LMA_MASK);
|
bool lma = !!(first_x86_cpu->env.hflags & HF_LMA_MASK);
|
||||||
|
|
||||||
if (lma) {
|
if (lma) {
|
||||||
ret = x86_64_write_elf64_note(f, &cpu->env, cpuid, opaque);
|
ret = x86_64_write_elf64_note(f, &cpu->env, cpuid, s);
|
||||||
} else {
|
} else {
|
||||||
#endif
|
#endif
|
||||||
ret = x86_write_elf64_note(f, &cpu->env, cpuid, opaque);
|
ret = x86_write_elf64_note(f, &cpu->env, cpuid, s);
|
||||||
#ifdef TARGET_X86_64
|
#ifdef TARGET_X86_64
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -201,7 +201,7 @@ int x86_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int x86_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
|
int x86_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
|
||||||
int cpuid, void *opaque)
|
int cpuid, DumpState *s)
|
||||||
{
|
{
|
||||||
X86CPU *cpu = X86_CPU(cs);
|
X86CPU *cpu = X86_CPU(cs);
|
||||||
x86_elf_prstatus prstatus;
|
x86_elf_prstatus prstatus;
|
||||||
@ -224,7 +224,7 @@ int x86_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
|
|||||||
buf += ROUND_UP(name_size, 4);
|
buf += ROUND_UP(name_size, 4);
|
||||||
memcpy(buf, &prstatus, sizeof(prstatus));
|
memcpy(buf, &prstatus, sizeof(prstatus));
|
||||||
|
|
||||||
ret = f(note, note_size, opaque);
|
ret = f(note, note_size, s);
|
||||||
g_free(note);
|
g_free(note);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -329,7 +329,7 @@ static void qemu_get_cpustate(QEMUCPUState *s, CPUX86State *env)
|
|||||||
|
|
||||||
static inline int cpu_write_qemu_note(WriteCoreDumpFunction f,
|
static inline int cpu_write_qemu_note(WriteCoreDumpFunction f,
|
||||||
CPUX86State *env,
|
CPUX86State *env,
|
||||||
void *opaque,
|
DumpState *s,
|
||||||
int type)
|
int type)
|
||||||
{
|
{
|
||||||
QEMUCPUState state;
|
QEMUCPUState state;
|
||||||
@ -369,7 +369,7 @@ static inline int cpu_write_qemu_note(WriteCoreDumpFunction f,
|
|||||||
buf += ROUND_UP(name_size, 4);
|
buf += ROUND_UP(name_size, 4);
|
||||||
memcpy(buf, &state, sizeof(state));
|
memcpy(buf, &state, sizeof(state));
|
||||||
|
|
||||||
ret = f(note, note_size, opaque);
|
ret = f(note, note_size, s);
|
||||||
g_free(note);
|
g_free(note);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -379,19 +379,19 @@ static inline int cpu_write_qemu_note(WriteCoreDumpFunction f,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int x86_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cs,
|
int x86_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cs,
|
||||||
void *opaque)
|
DumpState *s)
|
||||||
{
|
{
|
||||||
X86CPU *cpu = X86_CPU(cs);
|
X86CPU *cpu = X86_CPU(cs);
|
||||||
|
|
||||||
return cpu_write_qemu_note(f, &cpu->env, opaque, 1);
|
return cpu_write_qemu_note(f, &cpu->env, s, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int x86_cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cs,
|
int x86_cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cs,
|
||||||
void *opaque)
|
DumpState *s)
|
||||||
{
|
{
|
||||||
X86CPU *cpu = X86_CPU(cs);
|
X86CPU *cpu = X86_CPU(cs);
|
||||||
|
|
||||||
return cpu_write_qemu_note(f, &cpu->env, opaque, 0);
|
return cpu_write_qemu_note(f, &cpu->env, s, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cpu_get_dump_info(ArchDumpInfo *info,
|
int cpu_get_dump_info(ArchDumpInfo *info,
|
||||||
|
@ -1938,13 +1938,13 @@ extern const VMStateDescription vmstate_x86_cpu;
|
|||||||
int x86_cpu_pending_interrupt(CPUState *cs, int interrupt_request);
|
int x86_cpu_pending_interrupt(CPUState *cs, int interrupt_request);
|
||||||
|
|
||||||
int x86_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cpu,
|
int x86_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cpu,
|
||||||
int cpuid, void *opaque);
|
int cpuid, DumpState *s);
|
||||||
int x86_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cpu,
|
int x86_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cpu,
|
||||||
int cpuid, void *opaque);
|
int cpuid, DumpState *s);
|
||||||
int x86_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
|
int x86_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
|
||||||
void *opaque);
|
DumpState *s);
|
||||||
int x86_cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
|
int x86_cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
|
||||||
void *opaque);
|
DumpState *s);
|
||||||
|
|
||||||
void x86_cpu_get_memory_mapping(CPUState *cpu, MemoryMappingList *list,
|
void x86_cpu_get_memory_mapping(CPUState *cpu, MemoryMappingList *list,
|
||||||
Error **errp);
|
Error **errp);
|
||||||
|
@ -270,23 +270,23 @@ ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
|
|||||||
static int ppc_write_all_elf_notes(const char *note_name,
|
static int ppc_write_all_elf_notes(const char *note_name,
|
||||||
WriteCoreDumpFunction f,
|
WriteCoreDumpFunction f,
|
||||||
PowerPCCPU *cpu, int id,
|
PowerPCCPU *cpu, int id,
|
||||||
void *opaque)
|
DumpState *s)
|
||||||
{
|
{
|
||||||
NoteFuncArg arg = { .state = opaque };
|
NoteFuncArg arg = { .state = s };
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
int note_size;
|
int note_size;
|
||||||
const NoteFuncDesc *nf;
|
const NoteFuncDesc *nf;
|
||||||
|
|
||||||
for (nf = note_func; nf->note_contents_func; nf++) {
|
for (nf = note_func; nf->note_contents_func; nf++) {
|
||||||
arg.note.hdr.n_namesz = cpu_to_dump32(opaque, sizeof(arg.note.name));
|
arg.note.hdr.n_namesz = cpu_to_dump32(s, sizeof(arg.note.name));
|
||||||
arg.note.hdr.n_descsz = cpu_to_dump32(opaque, nf->contents_size);
|
arg.note.hdr.n_descsz = cpu_to_dump32(s, nf->contents_size);
|
||||||
strncpy(arg.note.name, note_name, sizeof(arg.note.name));
|
strncpy(arg.note.name, note_name, sizeof(arg.note.name));
|
||||||
|
|
||||||
(*nf->note_contents_func)(&arg, cpu);
|
(*nf->note_contents_func)(&arg, cpu);
|
||||||
|
|
||||||
note_size =
|
note_size =
|
||||||
sizeof(arg.note) - sizeof(arg.note.contents) + nf->contents_size;
|
sizeof(arg.note) - sizeof(arg.note.contents) + nf->contents_size;
|
||||||
ret = f(&arg.note, note_size, opaque);
|
ret = f(&arg.note, note_size, s);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -295,15 +295,15 @@ static int ppc_write_all_elf_notes(const char *note_name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
|
int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
|
||||||
int cpuid, void *opaque)
|
int cpuid, DumpState *s)
|
||||||
{
|
{
|
||||||
PowerPCCPU *cpu = POWERPC_CPU(cs);
|
PowerPCCPU *cpu = POWERPC_CPU(cs);
|
||||||
return ppc_write_all_elf_notes("CORE", f, cpu, cpuid, opaque);
|
return ppc_write_all_elf_notes("CORE", f, cpu, cpuid, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ppc32_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
|
int ppc32_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
|
||||||
int cpuid, void *opaque)
|
int cpuid, DumpState *s)
|
||||||
{
|
{
|
||||||
PowerPCCPU *cpu = POWERPC_CPU(cs);
|
PowerPCCPU *cpu = POWERPC_CPU(cs);
|
||||||
return ppc_write_all_elf_notes("CORE", f, cpu, cpuid, opaque);
|
return ppc_write_all_elf_notes("CORE", f, cpu, cpuid, s);
|
||||||
}
|
}
|
||||||
|
@ -1354,9 +1354,9 @@ void ppc_gdb_gen_spr_xml(PowerPCCPU *cpu);
|
|||||||
const char *ppc_gdb_get_dynamic_xml(CPUState *cs, const char *xml_name);
|
const char *ppc_gdb_get_dynamic_xml(CPUState *cs, const char *xml_name);
|
||||||
#endif
|
#endif
|
||||||
int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
|
int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
|
||||||
int cpuid, void *opaque);
|
int cpuid, DumpState *s);
|
||||||
int ppc32_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
|
int ppc32_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
|
||||||
int cpuid, void *opaque);
|
int cpuid, DumpState *s);
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
void ppc_cpu_do_interrupt(CPUState *cpu);
|
void ppc_cpu_do_interrupt(CPUState *cpu);
|
||||||
bool ppc_cpu_exec_interrupt(CPUState *cpu, int int_req);
|
bool ppc_cpu_exec_interrupt(CPUState *cpu, int int_req);
|
||||||
|
@ -64,12 +64,11 @@ static void riscv64_note_init(struct riscv64_note *note, DumpState *s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int riscv_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
|
int riscv_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
|
||||||
int cpuid, void *opaque)
|
int cpuid, DumpState *s)
|
||||||
{
|
{
|
||||||
struct riscv64_note note;
|
struct riscv64_note note;
|
||||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||||
CPURISCVState *env = &cpu->env;
|
CPURISCVState *env = &cpu->env;
|
||||||
DumpState *s = opaque;
|
|
||||||
int ret, i = 0;
|
int ret, i = 0;
|
||||||
const char name[] = "CORE";
|
const char name[] = "CORE";
|
||||||
|
|
||||||
@ -134,12 +133,11 @@ static void riscv32_note_init(struct riscv32_note *note, DumpState *s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int riscv_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
|
int riscv_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
|
||||||
int cpuid, void *opaque)
|
int cpuid, DumpState *s)
|
||||||
{
|
{
|
||||||
struct riscv32_note note;
|
struct riscv32_note note;
|
||||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||||
CPURISCVState *env = &cpu->env;
|
CPURISCVState *env = &cpu->env;
|
||||||
DumpState *s = opaque;
|
|
||||||
int ret, i;
|
int ret, i;
|
||||||
const char name[] = "CORE";
|
const char name[] = "CORE";
|
||||||
|
|
||||||
|
@ -534,9 +534,9 @@ extern const char * const riscv_fpr_regnames[];
|
|||||||
const char *riscv_cpu_get_trap_name(target_ulong cause, bool async);
|
const char *riscv_cpu_get_trap_name(target_ulong cause, bool async);
|
||||||
void riscv_cpu_do_interrupt(CPUState *cpu);
|
void riscv_cpu_do_interrupt(CPUState *cpu);
|
||||||
int riscv_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
|
int riscv_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
|
||||||
int cpuid, void *opaque);
|
int cpuid, DumpState *s);
|
||||||
int riscv_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
|
int riscv_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
|
||||||
int cpuid, void *opaque);
|
int cpuid, DumpState *s);
|
||||||
int riscv_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
|
int riscv_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
|
||||||
int riscv_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
|
int riscv_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||||
int riscv_cpu_hviprio_index2irq(int index, int *out_irq, int *out_rdzero);
|
int riscv_cpu_hviprio_index2irq(int index, int *out_irq, int *out_rdzero);
|
||||||
|
@ -204,7 +204,7 @@ static const NoteFuncDesc note_linux[] = {
|
|||||||
static int s390x_write_elf64_notes(const char *note_name,
|
static int s390x_write_elf64_notes(const char *note_name,
|
||||||
WriteCoreDumpFunction f,
|
WriteCoreDumpFunction f,
|
||||||
S390CPU *cpu, int id,
|
S390CPU *cpu, int id,
|
||||||
void *opaque,
|
DumpState *s,
|
||||||
const NoteFuncDesc *funcs)
|
const NoteFuncDesc *funcs)
|
||||||
{
|
{
|
||||||
Note note;
|
Note note;
|
||||||
@ -222,7 +222,7 @@ static int s390x_write_elf64_notes(const char *note_name,
|
|||||||
(*nf->note_contents_func)(¬e, cpu, id);
|
(*nf->note_contents_func)(¬e, cpu, id);
|
||||||
|
|
||||||
note_size = sizeof(note) - sizeof(note.contents) + nf->contents_size;
|
note_size = sizeof(note) - sizeof(note.contents) + nf->contents_size;
|
||||||
ret = f(¬e, note_size, opaque);
|
ret = f(¬e, note_size, s);
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -235,16 +235,16 @@ static int s390x_write_elf64_notes(const char *note_name,
|
|||||||
|
|
||||||
|
|
||||||
int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
|
int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
|
||||||
int cpuid, void *opaque)
|
int cpuid, DumpState *s)
|
||||||
{
|
{
|
||||||
S390CPU *cpu = S390_CPU(cs);
|
S390CPU *cpu = S390_CPU(cs);
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = s390x_write_elf64_notes("CORE", f, cpu, cpuid, opaque, note_core);
|
r = s390x_write_elf64_notes("CORE", f, cpu, cpuid, s, note_core);
|
||||||
if (r) {
|
if (r) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
return s390x_write_elf64_notes("LINUX", f, cpu, cpuid, opaque, note_linux);
|
return s390x_write_elf64_notes("LINUX", f, cpu, cpuid, s, note_linux);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cpu_get_dump_info(ArchDumpInfo *info,
|
int cpu_get_dump_info(ArchDumpInfo *info,
|
||||||
|
@ -227,7 +227,7 @@ static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb,
|
|||||||
|
|
||||||
/* arch_dump.c */
|
/* arch_dump.c */
|
||||||
int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
|
int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
|
||||||
int cpuid, void *opaque);
|
int cpuid, DumpState *s);
|
||||||
|
|
||||||
|
|
||||||
/* cc_helper.c */
|
/* cc_helper.c */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user