summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWang Nan <wangnan0@huawei.com>2014-05-29 17:20:02 +0800
committerSimon Horman <horms@verge.net.au>2014-05-30 14:24:28 +0900
commit199bc59ca34ef1a0ce78aa9aa054dac53c5751bb (patch)
treeee63102a29ba09b13c002ad832838bd344f39a0f
parent8b1bac3073907193f226f45cf24ddab989281743 (diff)
downloadkexec-tools-199bc59ca34ef1a0ce78aa9aa054dac53c5751bb.tar.gz
kexec-tools: detect page_offset dynamically
ARM kernel can be compiled with CONFIG_VMSPLIT_1G, CONFIG_VMSPLIT_2G or CONFIG_VMSPLIT_3G. This patch dynamically detects PAGE_OFFSET according to _stext symbol from /proc/kallsyms. Signed-off-by: Wang Nan <wangnan0@huawei.com> Signed-off-by: Simon Horman <horms@verge.net.au>
-rw-r--r--kexec/arch/arm/crashdump-arm.c49
-rw-r--r--kexec/arch/arm/crashdump-arm.h4
2 files changed, 51 insertions, 2 deletions
diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
index 0cd6935..e6ff3e0 100644
--- a/kexec/arch/arm/crashdump-arm.c
+++ b/kexec/arch/arm/crashdump-arm.c
@@ -56,11 +56,55 @@ static struct crash_elf_info elf_info = {
.class = ELFCLASS32,
.data = ELFDATANATIVE,
.machine = EM_ARM,
- .page_offset = PAGE_OFFSET,
+ .page_offset = DEFAULT_PAGE_OFFSET,
};
unsigned long phys_offset;
+/* Retrieve kernel _stext symbol virtual address from /proc/kallsyms */
+static unsigned long long get_kernel_stext_sym(void)
+{
+ const char *kallsyms = "/proc/kallsyms";
+ const char *stext = "_stext";
+ char sym[128];
+ char line[128];
+ FILE *fp;
+ unsigned long long vaddr;
+ char type;
+
+ fp = fopen(kallsyms, "r"); if (!fp) {
+ fprintf(stderr, "Cannot open %s\n", kallsyms);
+ return 0;
+ }
+
+ while(fgets(line, sizeof(line), fp) != NULL) {
+ if (sscanf(line, "%Lx %c %s", &vaddr, &type, sym) != 3)
+ continue;
+ if (strcmp(sym, stext) == 0) {
+ dbgprintf("kernel symbol %s vaddr = %16llx\n", stext, vaddr);
+ return vaddr;
+ }
+ }
+
+ fprintf(stderr, "Cannot get kernel %s symbol address\n", stext);
+ return 0;
+}
+
+static int get_kernel_page_offset(struct kexec_info *info,
+ struct crash_elf_info *elf_info)
+{
+ unsigned long long stext_sym_addr = get_kernel_stext_sym();
+ if (stext_sym_addr == 0) {
+ elf_info->page_offset = (unsigned long long)DEFAULT_PAGE_OFFSET;
+ dbgprintf("Unable to get _stext symbol from /proc/kallsyms, use default: %llx\n",
+ elf_info->page_offset);
+ return 0;
+ }
+ elf_info->page_offset = stext_sym_addr & (~KVBASE_MASK);
+ dbgprintf("page_offset is set to %llx\n", elf_info->page_offset);
+ return 0;
+}
+
/**
* crash_range_callback() - callback called for each iomem region
* @data: not used
@@ -292,6 +336,9 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline)
phys_offset = usablemem_rgns.ranges->start;
dbgprintf("phys_offset: %#lx\n", phys_offset);
+ if (get_kernel_page_offset(info, &elf_info))
+ return -1;
+
err = crash_create_elf32_headers(info, &elf_info,
usablemem_rgns.ranges,
usablemem_rgns.size, &buf, &bufsz,
diff --git a/kexec/arch/arm/crashdump-arm.h b/kexec/arch/arm/crashdump-arm.h
index a342922..2dbde04 100644
--- a/kexec/arch/arm/crashdump-arm.h
+++ b/kexec/arch/arm/crashdump-arm.h
@@ -6,9 +6,11 @@ extern "C" {
#endif
#define COMMAND_LINE_SIZE 1024
-#define PAGE_OFFSET 0xc0000000
+#define DEFAULT_PAGE_OFFSET (0xc0000000)
+#define KVBASE_MASK (0x1ffffff)
#define CRASH_MAX_MEMORY_RANGES 32
+
extern struct memory_ranges usablemem_rgns;
struct kexec_info;