mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
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:
committed by
Steffen Eiden
parent
858da9af57
commit
6d15850480
@@ -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)
|
||||
|
||||
@@ -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)",
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user