Skip to content

Commit f4cac27

Browse files
author
Alexander Gordeev
committed
s390/crash: Use old os_info to create PT_LOAD headers
This is a preparatory rework to allow uncoupling virtual and physical addresses spaces. The vmcore ELF program headers describe virtual memory regions of a crashed kernel. User level tools use that information for the kernel text and data analysis (e.g vmcore-dmesg extracts the kernel log). Currently the kernel image is covered by program headers describing the identity mapping regions. But in the future the kernel image will be mapped into separate region outside of the identity mapping. Create the additional ELF program header that covers kernel image only, so that vmcore tools could locate kernel text and data. Further, the identity mapping in crashed and capture kernels will have different base address. Due to that __va() macro can not be used in the capture kernel. Instead, read crashed kernel identity mapping base address from os_info and use it for PT_LOAD type program headers creation. Acked-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
1 parent 378e32a commit f4cac27

File tree

3 files changed

+42
-5
lines changed

3 files changed

+42
-5
lines changed

arch/s390/include/asm/os_info.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
#define OS_INFO_VMEMMAP 7
2525
#define OS_INFO_AMODE31_START 8
2626
#define OS_INFO_AMODE31_END 9
27+
#define OS_INFO_IMAGE_START 10
28+
#define OS_INFO_IMAGE_END 11
29+
#define OS_INFO_IMAGE_PHYS 12
2730

2831
#define OS_INFO_FLAG_REIPL_CLEAR (1UL << 0)
2932

arch/s390/kernel/crash_dump.c

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,11 @@ static void *ehdr_init(Elf64_Ehdr *ehdr, int mem_chunk_cnt)
465465
ehdr->e_phoff = sizeof(Elf64_Ehdr);
466466
ehdr->e_ehsize = sizeof(Elf64_Ehdr);
467467
ehdr->e_phentsize = sizeof(Elf64_Phdr);
468-
ehdr->e_phnum = mem_chunk_cnt + 1;
468+
/*
469+
* Number of memory chunk PT_LOAD program headers plus one kernel
470+
* image PT_LOAD program header plus one PT_NOTE program header.
471+
*/
472+
ehdr->e_phnum = mem_chunk_cnt + 1 + 1;
469473
return ehdr + 1;
470474
}
471475

@@ -501,22 +505,42 @@ static int get_mem_chunk_cnt(void)
501505
*/
502506
static void loads_init(Elf64_Phdr *phdr)
503507
{
508+
unsigned long old_identity_base = os_info_old_value(OS_INFO_IDENTITY_BASE);
504509
phys_addr_t start, end;
505510
u64 idx;
506511

507512
for_each_physmem_range(idx, &oldmem_type, &start, &end) {
508-
phdr->p_filesz = end - start;
509513
phdr->p_type = PT_LOAD;
514+
phdr->p_vaddr = old_identity_base + start;
510515
phdr->p_offset = start;
511-
phdr->p_vaddr = (unsigned long)__va(start);
512516
phdr->p_paddr = start;
517+
phdr->p_filesz = end - start;
513518
phdr->p_memsz = end - start;
514519
phdr->p_flags = PF_R | PF_W | PF_X;
515520
phdr->p_align = PAGE_SIZE;
516521
phdr++;
517522
}
518523
}
519524

525+
/*
526+
* Prepare PT_LOAD type program header for kernel image region
527+
*/
528+
static void text_init(Elf64_Phdr *phdr)
529+
{
530+
unsigned long start_phys = os_info_old_value(OS_INFO_IMAGE_PHYS);
531+
unsigned long start = os_info_old_value(OS_INFO_IMAGE_START);
532+
unsigned long end = os_info_old_value(OS_INFO_IMAGE_END);
533+
534+
phdr->p_type = PT_LOAD;
535+
phdr->p_vaddr = start;
536+
phdr->p_filesz = end - start;
537+
phdr->p_memsz = end - start;
538+
phdr->p_offset = start_phys;
539+
phdr->p_paddr = start_phys;
540+
phdr->p_flags = PF_R | PF_W | PF_X;
541+
phdr->p_align = PAGE_SIZE;
542+
}
543+
520544
/*
521545
* Initialize notes (new kernel)
522546
*/
@@ -557,6 +581,8 @@ static size_t get_elfcorehdr_size(int mem_chunk_cnt)
557581
size += nt_vmcoreinfo_size();
558582
/* nt_final */
559583
size += sizeof(Elf64_Nhdr);
584+
/* PT_LOAD type program header for kernel text region */
585+
size += sizeof(Elf64_Phdr);
560586
/* PT_LOADS */
561587
size += mem_chunk_cnt * sizeof(Elf64_Phdr);
562588

@@ -568,7 +594,7 @@ static size_t get_elfcorehdr_size(int mem_chunk_cnt)
568594
*/
569595
int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size)
570596
{
571-
Elf64_Phdr *phdr_notes, *phdr_loads;
597+
Elf64_Phdr *phdr_notes, *phdr_loads, *phdr_text;
572598
size_t alloc_size;
573599
int mem_chunk_cnt;
574600
void *ptr, *hdr;
@@ -606,14 +632,19 @@ int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size)
606632
/* Init program headers */
607633
phdr_notes = ptr;
608634
ptr = PTR_ADD(ptr, sizeof(Elf64_Phdr));
635+
phdr_text = ptr;
636+
ptr = PTR_ADD(ptr, sizeof(Elf64_Phdr));
609637
phdr_loads = ptr;
610638
ptr = PTR_ADD(ptr, sizeof(Elf64_Phdr) * mem_chunk_cnt);
611639
/* Init notes */
612640
hdr_off = PTR_DIFF(ptr, hdr);
613641
ptr = notes_init(phdr_notes, ptr, ((unsigned long) hdr) + hdr_off);
642+
/* Init kernel text program header */
643+
text_init(phdr_text);
614644
/* Init loads */
615-
hdr_off = PTR_DIFF(ptr, hdr);
616645
loads_init(phdr_loads);
646+
/* Finalize program headers */
647+
hdr_off = PTR_DIFF(ptr, hdr);
617648
*addr = (unsigned long long) hdr;
618649
*size = (unsigned long long) hdr_off;
619650
BUG_ON(elfcorehdr_size > alloc_size);

arch/s390/kernel/os_info.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ void __init os_info_init(void)
8181
os_info_entry_add_val(OS_INFO_VMEMMAP, (unsigned long)vmemmap);
8282
os_info_entry_add_val(OS_INFO_AMODE31_START, AMODE31_START);
8383
os_info_entry_add_val(OS_INFO_AMODE31_END, AMODE31_END);
84+
os_info_entry_add_val(OS_INFO_IMAGE_START, (unsigned long)_stext);
85+
os_info_entry_add_val(OS_INFO_IMAGE_END, (unsigned long)_end);
86+
os_info_entry_add_val(OS_INFO_IMAGE_PHYS, __pa_symbol(_stext));
8487
os_info.csum = os_info_csum(&os_info);
8588
abs_lc = get_abs_lowcore();
8689
abs_lc->os_info = __pa(&os_info);

0 commit comments

Comments
 (0)