diff --git a/zdump/dfi.c b/zdump/dfi.c index f0373e2b..e87faf1d 100644 --- a/zdump/dfi.c +++ b/zdump/dfi.c @@ -695,6 +695,8 @@ static void kdump_select_prod_init(void) unsigned long prefix, ptr, count, tv_sec, i; struct timeval timeval; + util_log_print(UTIL_LOG_TRACE, "DFI kdump production system dump initialization\n"); + if (g.opts.select_specified && !l.kdump_base) ERR_EXIT("The \"--select\" option is not possible with this " "dump"); @@ -712,9 +714,10 @@ static void kdump_select_prod_init(void) } dfi_cpu_info_init(DFI_CPU_CONTENT_ALL); for (i = 0; i < count; i++) { - if (dfi_mem_virt_read(ptr + i * sizeof(long), &prefix, + if (dfi_mem_virt_read(dfi_vm_vtop(ptr) + i * sizeof(long), &prefix, sizeof(prefix))) continue; + prefix = dfi_vm_vtop(prefix); if (prefix == 0) continue; if (prefix % 0x1000) @@ -736,7 +739,7 @@ static void utsname_init(void) if (dfi_vmcoreinfo_symbol(&ptr, "init_uts_ns")) return; - if (dfi_mem_virt_read(ptr, buf, sizeof(buf))) + if (dfi_mem_virt_read(dfi_vm_vtop(ptr), buf, sizeof(buf))) return; utsname = memchr(buf, 'L', sizeof(buf) - sizeof(*utsname)); if (!utsname) diff --git a/zdump/dfi_mem_chunk.c b/zdump/dfi_mem_chunk.c index b5a9cd16..cf6d5102 100644 --- a/zdump/dfi_mem_chunk.c +++ b/zdump/dfi_mem_chunk.c @@ -439,6 +439,10 @@ void dfi_mem_unmap(u64 start, u64 size) struct dfi_mem_chunk *mem_chunk, *tmp; u64 end = start + size - 1; + util_log_print(UTIL_LOG_TRACE, + "DFI mem unmap start 0x%016lx, size 0x%016lx\n", + start, size); + util_list_iterate_safe(&l.mem_virt.chunk_list, mem_chunk, tmp) { /* * Chunk not hit? @@ -504,6 +508,10 @@ void dfi_mem_unmap(u64 start, u64 size) */ void dfi_mem_map(u64 start, u64 size, u64 start_phys) { + util_log_print(UTIL_LOG_TRACE, + "DFI mem map start 0x%016lx, size 0x%016lx, base 0x%016lx\n", + start, size, start_phys); + if (mem_range_mapped(start, size)) { dfi_mem_map_print(false); ABORT("Map request for already mapped region (%llx/%llx/%llx)", diff --git a/zdump/dfi_vmcoreinfo.c b/zdump/dfi_vmcoreinfo.c index 51d0f270..ea3e43f3 100644 --- a/zdump/dfi_vmcoreinfo.c +++ b/zdump/dfi_vmcoreinfo.c @@ -30,12 +30,21 @@ #define LC_OS_INFO 0xe18 +struct vm_info { + u64 identity_base; + u64 kaslr_offset; + u64 kaslr_offset_phys; + u64 amode31_start; + u64 amode31_end; +}; + /* * File local static data */ static struct { char *vmcoreinfo; struct os_info *os_info; + struct vm_info *vm_info; } l; static u32 os_info_csum(struct os_info *os_info) @@ -53,6 +62,7 @@ static struct os_info *os_info_get(void) if (dfi_mem_virt_read(LC_OS_INFO, &addr, sizeof(addr))) return NULL; + util_log_print(UTIL_LOG_DEBUG, "DFI osinfo addr: 0x%016lx\n", addr); if (addr % 0x1000) return NULL; if (dfi_mem_virt_read(addr, &os_info, sizeof(os_info))) @@ -61,9 +71,46 @@ static struct os_info *os_info_get(void) return NULL; if (os_info.csum != os_info_csum(&os_info)) return NULL; + + util_log_print(UTIL_LOG_DEBUG, "DFI found valid osinfo!\n"); return &os_info; } +static struct vm_info *vm_info_get(void) +{ + static struct vm_info vm_info = { 0 }; + + util_log_print(UTIL_LOG_TRACE, "DFI read vm_info\n"); + + vm_info.identity_base = l.os_info->entry[OS_INFO_IDENTITY_BASE].val; + if (vm_info.identity_base == 0) + return NULL; + vm_info.kaslr_offset = l.os_info->entry[OS_INFO_KASLR_OFFSET].val; + vm_info.kaslr_offset_phys = l.os_info->entry[OS_INFO_KASLR_OFF_PHYS].val; + vm_info.amode31_start = l.os_info->entry[OS_INFO_AMODE31_START].val; + vm_info.amode31_end = l.os_info->entry[OS_INFO_AMODE31_END].val; + + return &vm_info; +} + +/* + * Convert virual address in the dump to the physical address using + * vm_info data derived from os_info + */ +u64 dfi_vm_vtop(u64 vaddr) +{ + if (!l.vm_info) + return vaddr; + if (vaddr < LOWCORE_SIZE) + return vaddr; + if ((vaddr < l.vm_info->amode31_end) && + (vaddr >= l.vm_info->amode31_start)) + return vaddr; + if (vaddr < l.vm_info->kaslr_offset) + return vaddr - l.vm_info->identity_base; + return vaddr - l.vm_info->kaslr_offset + l.vm_info->kaslr_offset_phys; +} + /* * Initialize vmcoreinfo */ @@ -76,6 +123,8 @@ void dfi_vmcoreinfo_init(void) util_log_print(UTIL_LOG_TRACE, "DFI vmcoreinfo initialization\n"); l.os_info = os_info_get(); + if (l.os_info) + l.vm_info = vm_info_get(); if (l.os_info && l.os_info->entry[OS_INFO_VMCOREINFO].size) { util_log_print(UTIL_LOG_DEBUG, "DFI found valid osinfo\n"); @@ -157,6 +206,7 @@ static int vmcoreinfo_item_ulong(unsigned long *val, const char *fmt, int rc; rc = vmcoreinfo_item(str, sizeof(str), fmt, sym); + util_log_print(UTIL_LOG_DEBUG, "DFI vmcoreinfo symbol %s : %s\n", sym, str); if (rc) return rc; *val = strtoul(str, NULL, base); diff --git a/zdump/dfi_vmcoreinfo.h b/zdump/dfi_vmcoreinfo.h index 3cffcd13..0cb5a171 100644 --- a/zdump/dfi_vmcoreinfo.h +++ b/zdump/dfi_vmcoreinfo.h @@ -16,5 +16,6 @@ int dfi_vmcoreinfo_offset(unsigned long *offs, const char *sym); int dfi_vmcoreinfo_size(unsigned long *size, const char *sym); int dfi_vmcoreinfo_length(unsigned long *len, const char *sym); int dfi_vmcoreinfo_val(unsigned long *val, const char *sym); +u64 dfi_vm_vtop(u64 vaddr); #endif /* DFI_VMCOREINFO_H */