[PATCH 1/2] kexec-tools: detect page_offset dynamically
Simon Horman
horms at verge.net.au
Thu May 29 22:27:04 PDT 2014
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
>
More information about the kexec
mailing list