On Thu, May 29, 2014 at 05:20:02PM +0800, Wang Nan wrote: > 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 at huawei.com> Thanks, applied. > --- > kexec/arch/arm/crashdump-arm.c | 49 +++++++++++++++++++++++++++++++++++++++++- > kexec/arch/arm/crashdump-arm.h | 4 +++- > 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; > -- > 1.8.4 >