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

x86, mm: use pfn_range_is_mapped() with reserve_initrd

We are going to map ram only, so under max_low_pfn_mapped,
between 4g and max_pfn_mapped does not mean mapped at all.

Use pfn_range_is_mapped() to find out if range is mapped for initrd.

That could happen bootloader put initrd in range but user could
use memmap to carve some of range out.

Also during copying need to use early_memmap to map original initrd
for accessing.
Signed-off-by: default avatarYinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1353123563-3103-15-git-send-email-yinghai@kernel.orgSigned-off-by: default avatarH. Peter Anvin <hpa@linux.intel.com>
parent 5101730c
...@@ -317,20 +317,19 @@ static void __init relocate_initrd(void) ...@@ -317,20 +317,19 @@ static void __init relocate_initrd(void)
u64 ramdisk_image = boot_params.hdr.ramdisk_image; u64 ramdisk_image = boot_params.hdr.ramdisk_image;
u64 ramdisk_size = boot_params.hdr.ramdisk_size; u64 ramdisk_size = boot_params.hdr.ramdisk_size;
u64 area_size = PAGE_ALIGN(ramdisk_size); u64 area_size = PAGE_ALIGN(ramdisk_size);
u64 end_of_lowmem = max_low_pfn_mapped << PAGE_SHIFT;
u64 ramdisk_here; u64 ramdisk_here;
unsigned long slop, clen, mapaddr; unsigned long slop, clen, mapaddr;
char *p, *q; char *p, *q;
/* We need to move the initrd down into lowmem */ /* We need to move the initrd down into directly mapped mem */
ramdisk_here = memblock_find_in_range(0, end_of_lowmem, area_size, ramdisk_here = memblock_find_in_range(0, PFN_PHYS(max_low_pfn_mapped),
PAGE_SIZE); area_size, PAGE_SIZE);
if (!ramdisk_here) if (!ramdisk_here)
panic("Cannot find place for new RAMDISK of size %lld\n", panic("Cannot find place for new RAMDISK of size %lld\n",
ramdisk_size); ramdisk_size);
/* Note: this includes all the lowmem currently occupied by /* Note: this includes all the mem currently occupied by
the initrd, we rely on that fact to keep the data intact. */ the initrd, we rely on that fact to keep the data intact. */
memblock_reserve(ramdisk_here, area_size); memblock_reserve(ramdisk_here, area_size);
initrd_start = ramdisk_here + PAGE_OFFSET; initrd_start = ramdisk_here + PAGE_OFFSET;
...@@ -340,17 +339,7 @@ static void __init relocate_initrd(void) ...@@ -340,17 +339,7 @@ static void __init relocate_initrd(void)
q = (char *)initrd_start; q = (char *)initrd_start;
/* Copy any lowmem portion of the initrd */ /* Copy the initrd */
if (ramdisk_image < end_of_lowmem) {
clen = end_of_lowmem - ramdisk_image;
p = (char *)__va(ramdisk_image);
memcpy(q, p, clen);
q += clen;
ramdisk_image += clen;
ramdisk_size -= clen;
}
/* Copy the highmem portion of the initrd */
while (ramdisk_size) { while (ramdisk_size) {
slop = ramdisk_image & ~PAGE_MASK; slop = ramdisk_image & ~PAGE_MASK;
clen = ramdisk_size; clen = ramdisk_size;
...@@ -364,7 +353,7 @@ static void __init relocate_initrd(void) ...@@ -364,7 +353,7 @@ static void __init relocate_initrd(void)
ramdisk_image += clen; ramdisk_image += clen;
ramdisk_size -= clen; ramdisk_size -= clen;
} }
/* high pages is not converted by early_res_to_bootmem */
ramdisk_image = boot_params.hdr.ramdisk_image; ramdisk_image = boot_params.hdr.ramdisk_image;
ramdisk_size = boot_params.hdr.ramdisk_size; ramdisk_size = boot_params.hdr.ramdisk_size;
printk(KERN_INFO "Move RAMDISK from [mem %#010llx-%#010llx] to" printk(KERN_INFO "Move RAMDISK from [mem %#010llx-%#010llx] to"
...@@ -373,13 +362,27 @@ static void __init relocate_initrd(void) ...@@ -373,13 +362,27 @@ static void __init relocate_initrd(void)
ramdisk_here, ramdisk_here + ramdisk_size - 1); ramdisk_here, ramdisk_here + ramdisk_size - 1);
} }
static u64 __init get_mem_size(unsigned long limit_pfn)
{
int i;
u64 mapped_pages = 0;
unsigned long start_pfn, end_pfn;
for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, NULL) {
start_pfn = min_t(unsigned long, start_pfn, limit_pfn);
end_pfn = min_t(unsigned long, end_pfn, limit_pfn);
mapped_pages += end_pfn - start_pfn;
}
return mapped_pages << PAGE_SHIFT;
}
static void __init reserve_initrd(void) static void __init reserve_initrd(void)
{ {
/* Assume only end is not page aligned */ /* Assume only end is not page aligned */
u64 ramdisk_image = boot_params.hdr.ramdisk_image; u64 ramdisk_image = boot_params.hdr.ramdisk_image;
u64 ramdisk_size = boot_params.hdr.ramdisk_size; u64 ramdisk_size = boot_params.hdr.ramdisk_size;
u64 ramdisk_end = PAGE_ALIGN(ramdisk_image + ramdisk_size); u64 ramdisk_end = PAGE_ALIGN(ramdisk_image + ramdisk_size);
u64 end_of_lowmem = max_low_pfn_mapped << PAGE_SHIFT; u64 mapped_size;
if (!boot_params.hdr.type_of_loader || if (!boot_params.hdr.type_of_loader ||
!ramdisk_image || !ramdisk_size) !ramdisk_image || !ramdisk_size)
...@@ -387,18 +390,19 @@ static void __init reserve_initrd(void) ...@@ -387,18 +390,19 @@ static void __init reserve_initrd(void)
initrd_start = 0; initrd_start = 0;
if (ramdisk_size >= (end_of_lowmem>>1)) { mapped_size = get_mem_size(max_low_pfn_mapped);
if (ramdisk_size >= (mapped_size>>1))
panic("initrd too large to handle, " panic("initrd too large to handle, "
"disabling initrd (%lld needed, %lld available)\n", "disabling initrd (%lld needed, %lld available)\n",
ramdisk_size, end_of_lowmem>>1); ramdisk_size, mapped_size>>1);
}
printk(KERN_INFO "RAMDISK: [mem %#010llx-%#010llx]\n", ramdisk_image, printk(KERN_INFO "RAMDISK: [mem %#010llx-%#010llx]\n", ramdisk_image,
ramdisk_end - 1); ramdisk_end - 1);
if (ramdisk_end <= (max_low_pfn_mapped<<PAGE_SHIFT) &&
if (ramdisk_end <= end_of_lowmem) { pfn_range_is_mapped(PFN_DOWN(ramdisk_image),
/* All in lowmem, easy case */ PFN_DOWN(ramdisk_end))) {
/* All are mapped, easy case */
/* /*
* don't need to reserve again, already reserved early * don't need to reserve again, already reserved early
* in i386_start_kernel * in i386_start_kernel
......
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