Commit 084d1283 authored by Yinghai Lu's avatar Yinghai Lu Committed by H. Peter Anvin

x86, kexec: Set ident mapping for kernel that is above max_pfn

When first kernel is booted with memmap= or mem=  to limit max_pfn.
kexec can load second kernel above that max_pfn.

We need to set ident mapping for whole image in this case instead of just
for first 2M.
Signed-off-by: default avatarYinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1359058816-7615-23-git-send-email-yinghai@kernel.orgSigned-off-by: default avatarH. Peter Anvin <hpa@linux.intel.com>
parent 577af55d
...@@ -56,6 +56,25 @@ static int init_one_level2_page(struct kimage *image, pgd_t *pgd, ...@@ -56,6 +56,25 @@ static int init_one_level2_page(struct kimage *image, pgd_t *pgd,
return result; 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) static void init_level2_page(pmd_t *level2p, unsigned long addr)
{ {
unsigned long end_addr; unsigned long end_addr;
...@@ -184,22 +203,34 @@ static int init_transition_pgtable(struct kimage *image, pgd_t *pgd) ...@@ -184,22 +203,34 @@ static int init_transition_pgtable(struct kimage *image, pgd_t *pgd)
return result; return result;
} }
static int init_pgtable(struct kimage *image, unsigned long start_pgtable) static int init_pgtable(struct kimage *image, unsigned long start_pgtable)
{ {
unsigned long mstart, mend;
pgd_t *level4p; pgd_t *level4p;
int result; int result;
int i;
level4p = (pgd_t *)__va(start_pgtable); level4p = (pgd_t *)__va(start_pgtable);
result = init_level4_page(image, level4p, 0, max_pfn << PAGE_SHIFT); result = init_level4_page(image, level4p, 0, max_pfn << PAGE_SHIFT);
if (result) if (result)
return result; return result;
/* /*
* image->start may be outside 0 ~ max_pfn, for example when * segments's mem ranges could be outside 0 ~ max_pfn,
* jump back to original kernel from kexeced kernel * 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); 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) if (result)
return result; return result;
}
return init_transition_pgtable(image, level4p); return init_transition_pgtable(image, level4p);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment