From: Luo Haiyang <[email protected]>
The kexec shows the following crashdump log:
Elf header: p_type = 1, p_offset = 0x80100000 p_paddr = 0x80100000 p_vaddr = 0xcff000 ...
Elf header: p_type = 1, p_offset = 0x100000000 p_paddr = 0x100000000 p_vaddr = 0x80bff000 ...
Elf header: p_type = 1, p_offset = 0x87ffff000 p_paddr = 0x87ffff000 p_vaddr = 0x800bfe000 ...
Obviously, phys_to_virt returns an incorrect virtual address (vaddr). On the RISC-V architecture,
the linear address mapping is defined as:
va = pa + kernel_map.va_pa_offset (kernel_map.va_pa_offset = PAGE_OFFSET - phys_ram_base)
Both PAGE_OFFSET and phys_ram_base can be read from /proc/kcore.
Signed-off-by: Luo Haiyang <[email protected]>
---
kexec/arch/riscv/Makefile | 2 ++
kexec/arch/riscv/crashdump-riscv.c | 55 ++++++++++++++++++++++++------
util_lib/elf_info.c | 41 +++++++++++++++++-----
util_lib/include/elf_info.h | 1 +
4 files changed, 80 insertions(+), 19 deletions(-)
diff --git a/kexec/arch/riscv/Makefile b/kexec/arch/riscv/Makefile
index 18a997b..e886770 100644
--- a/kexec/arch/riscv/Makefile
+++ b/kexec/arch/riscv/Makefile
@@ -14,6 +14,8 @@ riscv_ARCH_REUSE_INITRD =
riscv_CPPFLAGS += -I $(srcdir)/kexec/
+riscv_PHYS_TO_VIRT =
+
dist += $(riscv_KEXEC_SRCS) \
kexec/arch/riscv/image-header.h \
kexec/arch/riscv/include/arch/options.h \
diff --git a/kexec/arch/riscv/crashdump-riscv.c b/kexec/arch/riscv/crashdump-riscv.c
index e923a71..6875249 100644
--- a/kexec/arch/riscv/crashdump-riscv.c
+++ b/kexec/arch/riscv/crashdump-riscv.c
@@ -1,5 +1,6 @@
#include <errno.h>
#include <elf.h>
+#include <elf_info.h>
#include <unistd.h>
#include "kexec.h"
@@ -22,18 +23,45 @@ static struct memory_ranges crash_mem_ranges = {0};
static struct memory_ranges system_mem_ranges = {0};
struct memory_range elfcorehdr_mem = {0};
-static unsigned long long get_page_offset(struct kexec_info *info)
+static unsigned long long phys_offset;
+
+static int get_page_offset(unsigned long long *page_offset)
{
- unsigned long long vaddr_off = 0;
- unsigned long long page_size = sysconf(_SC_PAGESIZE);
- unsigned long long init_start = get_kernel_sym("_sinittext");
+ int fd, ret = 0;
- /*
- * Begining of init section is aligned to page size
- */
- vaddr_off = init_start - page_size;
+ if ((fd = open("/proc/kcore", O_RDONLY)) < 0) {
+ fprintf(stderr, "Can't open (%s).\n", "/proc/kcore");
+ return EFAILED;
+ }
+
+ ret = read_page_offset_elf_kcore(fd, (long *)page_offset);
+ if (ret)
+ fprintf(stderr, "Can't get page_offset from /proc/kcore\n");
+
+ close(fd);
+ return ret;
+}
+
+static int get_phys_offset(unsigned long long *phys_offset)
+{
+ int fd, ret = 0;
+
+ if ((fd = open("/proc/kcore", O_RDONLY)) < 0) {
+ fprintf(stderr, "Can't open (%s).\n", "/proc/kcore");
+ return EFAILED;
+ }
+
+ ret = read_phys_offset_elf_kcore(fd, (long *)phys_offset);
+ if (ret)
+ fprintf(stderr, "Can't get phys_offset from /proc/kcore\n");
- return vaddr_off;
+ close(fd);
+ return ret;
+}
+
+unsigned long phys_to_virt(struct crash_elf_info *elf_info, unsigned long long p)
+{
+ return elf_info->page_offset - phys_offset + p;
}
/*
@@ -124,7 +152,14 @@ int load_elfcorehdr(struct kexec_info *info)
if (crash_get_memory_ranges())
return EFAILED;
- elf_info.page_offset = get_page_offset(info);
+ if (get_phys_offset(&phys_offset))
+ return EFAILED;
+
+ dbgprintf("phys_offset: %016llx\n", phys_offset);
+
+ if (get_page_offset(&elf_info.page_offset))
+ return EFAILED;
+
dbgprintf("page_offset: %016llx\n", elf_info.page_offset);
#if __riscv_xlen == 64
diff --git a/util_lib/elf_info.c b/util_lib/elf_info.c
index 589bc1a..36eb895 100644
--- a/util_lib/elf_info.c
+++ b/util_lib/elf_info.c
@@ -1308,16 +1308,39 @@ int read_phys_offset_elf_kcore(int fd, long *phys_off)
*phys_off = ULONG_MAX;
+ if (phys_offset != UINT64_MAX) {
+ *phys_off = phys_offset;
+ return 0;
+ }
+
+ /* If we have a valid 'PHYS_OFFSET' by now,
+ * return it to the caller now.
+ */
ret = read_elf(fd);
- if (!ret) {
- /* If we have a valid 'PHYS_OFFSET' by now,
- * return it to the caller now.
- */
- if (phys_offset != UINT64_MAX) {
- *phys_off = phys_offset;
- return ret;
- }
+ if (!ret && phys_offset != UINT64_MAX) {
+ *phys_off = phys_offset;
+ return 0;
+ }
+
+ return -EFAULT;
+}
+
+int read_page_offset_elf_kcore(int fd, long *page_off)
+{
+ int ret;
+
+ *page_off = ULONG_MAX;
+
+ if (page_offset != UINT64_MAX) {
+ *page_off = page_offset;
+ return 0;
+ }
+
+ ret = read_elf(fd);
+ if (!ret && page_offset != UINT64_MAX) {
+ *page_off = page_offset;
+ return 0;
}
- return 2;
+ return -EFAULT;
}
diff --git a/util_lib/include/elf_info.h b/util_lib/include/elf_info.h
index fdf4c3d..3ccc950 100644
--- a/util_lib/include/elf_info.h
+++ b/util_lib/include/elf_info.h
@@ -29,6 +29,7 @@ int get_pt_load(int idx,
unsigned long long *virt_start,
unsigned long long *virt_end);
int read_phys_offset_elf_kcore(int fd, long *phys_off);
+int read_page_offset_elf_kcore(int fd, long *page_off);
int read_elf(int fd);
void dump_dmesg(int fd, void (*handler)(char*, unsigned int));
extern void (*arch_scan_vmcoreinfo)(char *pos);
--
2.27.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.