From 59752bf03526a5ab4e3d825f7bb3fc5b6f456cfe Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 24 Jan 2013 12:20:03 -0800 Subject: [PATCH] --- yaml --- r: 356247 b: refs/heads/master c: 084d1283986a530828b8898f206adf44d5d3146d h: refs/heads/master i: 356245: c0de433b86af1db093871f620d3b6061a307b6f5 356243: 9cb23bcc4c6f50694542b5ae21ca3810bdb2dd12 356239: 884fc4090d1f19bb2f7f90439fa7a38bd5e5d6f3 v: v3 --- [refs] | 2 +- trunk/arch/x86/kernel/machine_kexec_64.c | 43 ++++++++++++++++++++---- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/[refs] b/[refs] index 5e3d99de10da..580de38d2709 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 577af55d802d9fe114287e750504e09e7c677c9c +refs/heads/master: 084d1283986a530828b8898f206adf44d5d3146d diff --git a/trunk/arch/x86/kernel/machine_kexec_64.c b/trunk/arch/x86/kernel/machine_kexec_64.c index b3ea9db39db6..be14ee120c43 100644 --- a/trunk/arch/x86/kernel/machine_kexec_64.c +++ b/trunk/arch/x86/kernel/machine_kexec_64.c @@ -56,6 +56,25 @@ static int init_one_level2_page(struct kimage *image, pgd_t *pgd, return result; } +static int ident_mapping_init(struct kimage *image, pgd_t *level4p, + unsigned long mstart, unsigned long mend) +{ + int result; + + mstart = round_down(mstart, PMD_SIZE); + mend = round_up(mend - 1, PMD_SIZE); + + while (mstart < mend) { + result = init_one_level2_page(image, level4p, mstart); + if (result) + return result; + + mstart += PMD_SIZE; + } + + return 0; +} + static void init_level2_page(pmd_t *level2p, unsigned long addr) { unsigned long end_addr; @@ -184,22 +203,34 @@ static int init_transition_pgtable(struct kimage *image, pgd_t *pgd) return result; } - static int init_pgtable(struct kimage *image, unsigned long start_pgtable) { + unsigned long mstart, mend; pgd_t *level4p; int result; + int i; + level4p = (pgd_t *)__va(start_pgtable); result = init_level4_page(image, level4p, 0, max_pfn << PAGE_SHIFT); if (result) return result; + /* - * image->start may be outside 0 ~ max_pfn, for example when - * jump back to original kernel from kexeced kernel + * segments's mem ranges could be outside 0 ~ max_pfn, + * for example when jump back to original kernel from kexeced kernel. + * or first kernel is booted with user mem map, and second kernel + * could be loaded out of that range. */ - result = init_one_level2_page(image, level4p, image->start); - if (result) - return result; + for (i = 0; i < image->nr_segments; i++) { + mstart = image->segment[i].mem; + mend = mstart + image->segment[i].memsz; + + result = ident_mapping_init(image, level4p, mstart, mend); + + if (result) + return result; + } + return init_transition_pgtable(image, level4p); }