zdump: Use os_info data to convert dump vaddr to paddr

For vr-kernel dumps use the offsets stored in os_info entries for
virt to phys address conversion when dump virtual address is to be
read, (e.g. vmcoreinfo symbols) using similar method as implemented
in crash-utility.
It is mainly required for reading "init_uts_ns" symbol and, in case
of crashed kdump, "lowcore_ptr" symbol along with a pointers to the
lowcore of every CPU.

Acked-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
This commit is contained in:
Mikhail Zaslonko
2024-04-17 14:43:43 +02:00
committed by Steffen Eiden
parent 858da9af57
commit 6d15850480
4 changed files with 64 additions and 2 deletions

View File

@@ -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)

View File

@@ -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)",

View File

@@ -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);

View File

@@ -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 */