• Y
    x86: Make sure free_init_pages() frees pages on page boundary · c967da6a
    Yinghai Lu 提交于
    When CONFIG_NO_BOOTMEM=y, it could use memory more effiently, or
    in a more compact fashion.
    
    Example:
    
     Allocated new RAMDISK: 00ec2000 - 0248ce57
     Move RAMDISK from 000000002ea04000 - 000000002ffcee56 to 00ec2000 - 0248ce56
    
    The new RAMDISK's end is not page aligned.
    Last page could be shared with other users.
    
    When free_init_pages are called for initrd or .init, the page
    could be freed and we could corrupt other data.
    
    code segment in free_init_pages():
    
     |        for (; addr < end; addr += PAGE_SIZE) {
     |                ClearPageReserved(virt_to_page(addr));
     |                init_page_count(virt_to_page(addr));
     |                memset((void *)(addr & ~(PAGE_SIZE-1)),
     |                        POISON_FREE_INITMEM, PAGE_SIZE);
     |                free_page(addr);
     |                totalram_pages++;
     |        }
    
    last half page could be used as one whole free page.
    
    So page align the boundaries.
    
    -v2: make the original initramdisk to be aligned, according to
         Johannes, otherwise we have the chance to lose one page.
         we still need to keep initrd_end not aligned, otherwise it could
         confuse decompressor.
    -v3: change to WARN_ON instead, suggested by Johannes.
    -v4: use PAGE_ALIGN, suggested by Johannes.
         We may fix that macro name later to PAGE_ALIGN_UP, and PAGE_ALIGN_DOWN
         Add comments about assuming ramdisk start is aligned
         in relocate_initrd(), change to re get ramdisk_image instead of save it
         to make diff smaller. Add warning for wrong range, suggested by Johannes.
    -v6: remove one WARN()
         We need to align beginning in free_init_pages()
         do not copy more than ramdisk_size, noticed by Johannes
    Reported-by: NStanislaw Gruszka <sgruszka@redhat.com>
    Tested-by: NStanislaw Gruszka <sgruszka@redhat.com>
    Signed-off-by: NYinghai Lu <yinghai@kernel.org>
    Acked-by: NJohannes Weiner <hannes@cmpxchg.org>
    Cc: David Miller <davem@davemloft.net>
    Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
    Cc: Linus Torvalds <torvalds@linux-foundation.org>
    LKML-Reference: <1269830604-26214-3-git-send-email-yinghai@kernel.org>
    Signed-off-by: NIngo Molnar <mingo@elte.hu>
    c967da6a
init.c 10.6 KB