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:
Stefan Hajnoczi 2022-10-11 09:31:19 -04:00
commit 42e1e350bf
14 changed files with 264 additions and 223 deletions

View file

@ -59,6 +59,11 @@ static inline bool dump_is_64bit(DumpState *s)
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)
{
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;
}
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
@ -134,34 +139,27 @@ static void write_elf64_header(DumpState *s, Error **errp)
* special section.
*/
uint16_t phnum = MIN(s->phdr_num, PN_XNUM);
Elf64_Ehdr elf_header;
int ret;
memset(&elf_header, 0, sizeof(Elf64_Ehdr));
memcpy(&elf_header, ELFMAG, SELFMAG);
elf_header.e_ident[EI_CLASS] = ELFCLASS64;
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_dump64(s, s->phdr_offset);
elf_header.e_phentsize = cpu_to_dump16(s, sizeof(Elf64_Phdr));
elf_header.e_phnum = cpu_to_dump16(s, phnum);
memset(elf_header, 0, sizeof(Elf64_Ehdr));
memcpy(elf_header, ELFMAG, SELFMAG);
elf_header->e_ident[EI_CLASS] = ELFCLASS64;
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_dump64(s, s->phdr_offset);
elf_header->e_phentsize = cpu_to_dump16(s, sizeof(Elf64_Phdr));
elf_header->e_phnum = cpu_to_dump16(s, phnum);
if (s->shdr_num) {
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_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");
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_shnum = cpu_to_dump16(s, s->shdr_num);
}
}
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
@ -169,28 +167,45 @@ static void write_elf32_header(DumpState *s, Error **errp)
* special section.
*/
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;
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);
if (dump_is_64bit(s)) {
prepare_elf64_header(s, &elf64_header);
header_size = sizeof(elf64_header);
header_ptr = &elf64_header;
} else {
prepare_elf32_header(s, &elf32_header);
header_size = sizeof(elf32_header);
header_ptr = &elf32_header;
}
ret = fd_write_vmcore(&elf_header, sizeof(elf_header), s);
ret = fd_write_vmcore(header_ptr, header_size, s);
if (ret < 0) {
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));
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);
}
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));
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;
if (dump_is_64bit(s)) {
write_elf64_phdr_note(s, &phdr64);
prepare_elf64_phdr_note(s, &phdr64);
size = sizeof(phdr64);
phdr = &phdr64;
} else {
write_elf32_phdr_note(s, &phdr32);
prepare_elf32_phdr_note(s, &phdr32);
size = sizeof(phdr32);
phdr = &phdr32;
}
@ -443,29 +458,30 @@ static void get_offset_range(hwaddr phys_addr,
*p_offset = -1;
*p_filesz = 0;
if (s->has_filter) {
if (phys_addr < s->begin || phys_addr >= s->begin + s->length) {
if (dump_has_filter(s)) {
if (phys_addr < s->filter_area_begin ||
phys_addr >= s->filter_area_begin + s->filter_area_length) {
return;
}
}
QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) {
if (s->has_filter) {
if (block->target_start >= s->begin + s->length ||
block->target_end <= s->begin) {
if (dump_has_filter(s)) {
if (block->target_start >= s->filter_area_begin + s->filter_area_length ||
block->target_end <= s->filter_area_begin) {
/* This block is out of the range */
continue;
}
if (s->begin <= block->target_start) {
if (s->filter_area_begin <= block->target_start) {
start = block->target_start;
} else {
start = s->begin;
start = s->filter_area_begin;
}
size_in_block = block->target_end - start;
if (s->begin + s->length < block->target_end) {
size_in_block -= block->target_end - (s->begin + s->length);
if (s->filter_area_begin + s->filter_area_length < block->target_end) {
size_in_block -= block->target_end - (s->filter_area_begin + s->filter_area_length);
}
} else {
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();
hwaddr offset, filesz;
@ -558,11 +574,7 @@ static void dump_begin(DumpState *s, Error **errp)
*/
/* write elf header to vmcore */
if (dump_is_64bit(s)) {
write_elf64_header(s, errp);
} else {
write_elf32_header(s, errp);
}
write_elf_header(s, errp);
if (*errp) {
return;
}
@ -573,8 +585,8 @@ static void dump_begin(DumpState *s, Error **errp)
return;
}
/* write all PT_LOAD to vmcore */
write_elf_loads(s, errp);
/* write all PT_LOADs to vmcore */
write_elf_phdr_loads(s, errp);
if (*errp) {
return;
}
@ -591,31 +603,43 @@ static void dump_begin(DumpState *s, Error **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) {
block = QTAILQ_NEXT(block, next);
if (!block) {
/* no more block */
return 1;
}
int64_t size, left, right;
s->start = 0;
s->next_block = block;
if (s->has_filter) {
if (block->target_start >= s->begin + s->length ||
block->target_end <= s->begin) {
/* This block is out of the range */
continue;
}
if (s->begin > block->target_start) {
s->start = s->begin - block->target_start;
}
}
return 0;
/* No filter, return full size */
if (!filter_area_length) {
return block->target_end - block->target_start;
}
/* calculate the overlapped region. */
left = MAX(filter_area_start, block->target_start);
right = MIN(filter_area_start + filter_area_length, block->target_end);
size = right - left;
size = size > 0 ? size : 0;
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 (filter_area_start > block->target_start) {
return filter_area_start - block->target_start;
}
}
return 0;
}
/* write all memory to vmcore */
@ -623,24 +647,22 @@ static void dump_iterate(DumpState *s, Error **errp)
{
ERRP_GUARD();
GuestPhysBlock *block;
int64_t size;
int64_t memblock_size, memblock_start;
do {
block = s->next_block;
size = block->target_end - block->target_start;
if (s->has_filter) {
size -= s->start;
if (s->begin + s->length < block->target_end) {
size -= block->target_end - (s->begin + s->length);
}
QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) {
memblock_start = dump_filtered_memblock_start(block, s->filter_area_begin, s->filter_area_length);
if (memblock_start == -1) {
continue;
}
write_memory(s, block, s->start, size, errp);
memblock_size = dump_filtered_memblock_size(block, s->filter_area_begin, s->filter_area_length);
/* Write the memory to file */
write_memory(s, block, memblock_start, memblock_size, errp);
if (*errp) {
return;
}
} while (!get_next_block(s, block));
}
}
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.
* bufptr can be NULL. note: the blocks here is supposed to reflect guest-phys
* blocks, so block->target_start and block->target_end should be interal
* multiples of the target page size.
* Return the page frame number and the page content in *bufptr. bufptr can be
* NULL. If not NULL, *bufptr must contains a target page size of pre-allocated
* memory. This is not necessarily the memory returned.
*/
static bool get_next_page(GuestPhysBlock **blockptr, uint64_t *pfnptr,
uint8_t **bufptr, DumpState *s)
{
GuestPhysBlock *block = *blockptr;
hwaddr addr, target_page_mask = ~((hwaddr)s->dump_info.page_size - 1);
uint8_t *buf;
uint32_t page_size = s->dump_info.page_size;
uint8_t *buf = NULL, *hbuf;
hwaddr addr;
/* block == NULL means the start of the iteration */
if (!block) {
block = QTAILQ_FIRST(&s->guest_phys_blocks.head);
*blockptr = block;
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);
if (bufptr) {
*bufptr = block->host_addr;
}
return true;
}
*pfnptr = *pfnptr + 1;
addr = dump_pfn_to_paddr(s, *pfnptr);
if ((addr >= block->target_start) &&
(addr + s->dump_info.page_size <= block->target_end)) {
buf = block->host_addr + (addr - block->target_start);
addr = block->target_start;
*pfnptr = dump_paddr_to_pfn(s, addr);
} else {
/* the next page is in the next block */
block = QTAILQ_NEXT(block, next);
*blockptr = block;
if (!block) {
return false;
*pfnptr += 1;
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;
}
}
memcpy(buf + addr % page_size, hbuf, n);
addr += n;
if (addr % page_size == 0) {
/* we filled up the page */
break;
}
} else {
/* the next page is in the next block */
*blockptr = block = QTAILQ_NEXT(block, next);
if (!block) {
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) {
*bufptr = buf;
}
return true;
return buf != NULL;
}
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;
GuestPhysBlock *block_iter = NULL;
uint64_t pfn_iter;
g_autofree uint8_t *page = NULL;
/* get offset of page_desc and page_data in dump file */
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;
page = g_malloc(s->dump_info.page_size);
/*
* dump memory to vmcore page by page. zero page will all be resided in the
* 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 */
if (buffer_is_zero(buf, s->dump_info.page_size)) {
ret = write_cache(&page_desc, &pd_zero, sizeof(PageDescriptor),
@ -1490,30 +1540,22 @@ 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;
if (!s->has_filter) {
s->next_block = QTAILQ_FIRST(&s->guest_phys_blocks.head);
if (!dump_has_filter(s)) {
return 0;
}
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;
}
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 0;
}
return -1;
}
@ -1540,25 +1582,19 @@ bool qemu_system_dump_in_progress(void)
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)
{
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) {
if (s->has_filter) {
/* calculate the overlapped region. */
left = MAX(s->begin, block->target_start);
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;
total += dump_filtered_memblock_size(block,
s->filter_area_begin,
s->filter_area_length);
}
return total;
@ -1641,9 +1677,12 @@ static void dump_init(DumpState *s, int fd, bool has_format,
}
s->fd = fd;
s->has_filter = has_filter;
s->begin = begin;
s->length = length;
if (has_filter && !length) {
error_setg(errp, QERR_INVALID_PARAMETER, "length");
goto cleanup;
}
s->filter_area_begin = begin;
s->filter_area_length = length;
memory_mapping_list_init(&s->list);
@ -1660,8 +1699,8 @@ static void dump_init(DumpState *s, int fd, bool has_format,
goto cleanup;
}
s->start = get_start_block(s);
if (s->start == -1) {
/* Is the filter filtering everything? */
if (validate_start_block(s) == -1) {
error_setg(errp, QERR_INVALID_PARAMETER, "begin");
goto cleanup;
}
@ -1776,8 +1815,8 @@ static void dump_init(DumpState *s, int fd, bool has_format,
return;
}
if (s->has_filter) {
memory_mapping_filter(&s->list, s->begin, s->length);
if (dump_has_filter(s)) {
memory_mapping_filter(&s->list, s->filter_area_begin, s->filter_area_length);
}
/*

View file

@ -53,25 +53,25 @@ typedef struct SysemuCPUOps {
* 32-bit VM coredump.
*/
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
* 64-bit VM coredump.
*/
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
* note to a 32-bit VM coredump.
*/
int (*write_elf32_qemunote)(WriteCoreDumpFunction f, CPUState *cpu,
void *opaque);
DumpState *s);
/**
* @write_elf64_qemunote: Callback for writing a CPU- and QEMU-specific ELF
* note to a 64-bit VM coredump.
*/
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
* runtime configurable endianness is currently big-endian.

View file

@ -131,6 +131,7 @@ typedef struct VirtIODevice VirtIODevice;
typedef struct Visitor Visitor;
typedef struct VMChangeStateEntry VMChangeStateEntry;
typedef struct VMStateDescription VMStateDescription;
typedef struct DumpState DumpState;
/*
* Pointer types

View file

@ -166,11 +166,16 @@ typedef struct DumpState {
hwaddr memory_offset;
int fd;
GuestPhysBlock *next_block;
ram_addr_t start;
bool has_filter;
int64_t begin;
int64_t length;
/*
* Dump filter area variables
*
* A filtered dump only contains the guest memory designated by
* 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 */
size_t note_buf_offset; /* the writing place in note_buf */

View file

@ -232,12 +232,11 @@ static int aarch64_write_elf64_sve(WriteCoreDumpFunction f,
#endif
int arm_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
int cpuid, void *opaque)
int cpuid, DumpState *s)
{
struct aarch64_note note;
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
DumpState *s = opaque;
uint64_t pstate, sp;
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 cpuid, void *opaque)
int cpuid, DumpState *s)
{
struct arm_note note;
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
DumpState *s = opaque;
int ret, i;
bool fpvalid = cpu_isar_feature(aa32_vfp_simd, cpu);

View file

@ -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);
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 cpuid, void *opaque);
int cpuid, DumpState *s);
#ifdef TARGET_AARCH64
int aarch64_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);

View file

@ -42,7 +42,7 @@ typedef struct {
static int x86_64_write_elf64_note(WriteCoreDumpFunction f,
CPUX86State *env, int id,
void *opaque)
DumpState *s)
{
x86_64_user_regs_struct regs;
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);
memcpy(buf, &regs, sizeof(x86_64_user_regs_struct));
ret = f(note, note_size, opaque);
ret = f(note, note_size, s);
g_free(note);
if (ret < 0) {
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,
int id, void *opaque)
int id, DumpState *s)
{
x86_elf_prstatus prstatus;
Elf64_Nhdr *note;
@ -170,7 +170,7 @@ static int x86_write_elf64_note(WriteCoreDumpFunction f, CPUX86State *env,
buf += ROUND_UP(name_size, 4);
memcpy(buf, &prstatus, sizeof(prstatus));
ret = f(note, note_size, opaque);
ret = f(note, note_size, s);
g_free(note);
if (ret < 0) {
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 cpuid, void *opaque)
int cpuid, DumpState *s)
{
X86CPU *cpu = X86_CPU(cs);
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);
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 {
#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
}
#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 cpuid, void *opaque)
int cpuid, DumpState *s)
{
X86CPU *cpu = X86_CPU(cs);
x86_elf_prstatus prstatus;
@ -224,7 +224,7 @@ int x86_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
buf += ROUND_UP(name_size, 4);
memcpy(buf, &prstatus, sizeof(prstatus));
ret = f(note, note_size, opaque);
ret = f(note, note_size, s);
g_free(note);
if (ret < 0) {
return -1;
@ -329,7 +329,7 @@ static void qemu_get_cpustate(QEMUCPUState *s, CPUX86State *env)
static inline int cpu_write_qemu_note(WriteCoreDumpFunction f,
CPUX86State *env,
void *opaque,
DumpState *s,
int type)
{
QEMUCPUState state;
@ -369,7 +369,7 @@ static inline int cpu_write_qemu_note(WriteCoreDumpFunction f,
buf += ROUND_UP(name_size, 4);
memcpy(buf, &state, sizeof(state));
ret = f(note, note_size, opaque);
ret = f(note, note_size, s);
g_free(note);
if (ret < 0) {
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,
void *opaque)
DumpState *s)
{
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,
void *opaque)
DumpState *s)
{
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,

View file

@ -1938,13 +1938,13 @@ extern const VMStateDescription vmstate_x86_cpu;
int x86_cpu_pending_interrupt(CPUState *cs, int interrupt_request);
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 cpuid, void *opaque);
int cpuid, DumpState *s);
int x86_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
void *opaque);
DumpState *s);
int x86_cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
void *opaque);
DumpState *s);
void x86_cpu_get_memory_mapping(CPUState *cpu, MemoryMappingList *list,
Error **errp);

View file

@ -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,
WriteCoreDumpFunction f,
PowerPCCPU *cpu, int id,
void *opaque)
DumpState *s)
{
NoteFuncArg arg = { .state = opaque };
NoteFuncArg arg = { .state = s };
int ret = -1;
int note_size;
const NoteFuncDesc *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_descsz = cpu_to_dump32(opaque, nf->contents_size);
arg.note.hdr.n_namesz = cpu_to_dump32(s, sizeof(arg.note.name));
arg.note.hdr.n_descsz = cpu_to_dump32(s, nf->contents_size);
strncpy(arg.note.name, note_name, sizeof(arg.note.name));
(*nf->note_contents_func)(&arg, cpu);
note_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) {
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 cpuid, void *opaque)
int cpuid, DumpState *s)
{
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 cpuid, void *opaque)
int cpuid, DumpState *s)
{
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);
}

View file

@ -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);
#endif
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 cpuid, void *opaque);
int cpuid, DumpState *s);
#ifndef CONFIG_USER_ONLY
void ppc_cpu_do_interrupt(CPUState *cpu);
bool ppc_cpu_exec_interrupt(CPUState *cpu, int int_req);

View file

@ -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 cpuid, void *opaque)
int cpuid, DumpState *s)
{
struct riscv64_note note;
RISCVCPU *cpu = RISCV_CPU(cs);
CPURISCVState *env = &cpu->env;
DumpState *s = opaque;
int ret, i = 0;
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 cpuid, void *opaque)
int cpuid, DumpState *s)
{
struct riscv32_note note;
RISCVCPU *cpu = RISCV_CPU(cs);
CPURISCVState *env = &cpu->env;
DumpState *s = opaque;
int ret, i;
const char name[] = "CORE";

View file

@ -534,9 +534,9 @@ extern const char * const riscv_fpr_regnames[];
const char *riscv_cpu_get_trap_name(target_ulong cause, bool async);
void riscv_cpu_do_interrupt(CPUState *cpu);
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 cpuid, void *opaque);
int cpuid, DumpState *s);
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_hviprio_index2irq(int index, int *out_irq, int *out_rdzero);

View file

@ -204,7 +204,7 @@ static const NoteFuncDesc note_linux[] = {
static int s390x_write_elf64_notes(const char *note_name,
WriteCoreDumpFunction f,
S390CPU *cpu, int id,
void *opaque,
DumpState *s,
const NoteFuncDesc *funcs)
{
Note note;
@ -222,7 +222,7 @@ static int s390x_write_elf64_notes(const char *note_name,
(*nf->note_contents_func)(&note, cpu, id);
note_size = sizeof(note) - sizeof(note.contents) + nf->contents_size;
ret = f(&note, note_size, opaque);
ret = f(&note, note_size, s);
if (ret < 0) {
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 cpuid, void *opaque)
int cpuid, DumpState *s)
{
S390CPU *cpu = S390_CPU(cs);
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) {
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,

View file

@ -227,7 +227,7 @@ static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb,
/* arch_dump.c */
int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
int cpuid, void *opaque);
int cpuid, DumpState *s);
/* cc_helper.c */