• Michal Nazarewicz's avatar
    mm: page_alloc: fix CMA area initialisation when pageblock > MAX_ORDER · dc78327c
    Michal Nazarewicz authored
    With a kernel configured with ARM64_64K_PAGES && !TRANSPARENT_HUGEPAGE,
    the following is triggered at early boot:
    
      SMP: Total of 8 processors activated.
      devtmpfs: initialized
      Unable to handle kernel NULL pointer dereference at virtual address 00000008
      pgd = fffffe0000050000
      [00000008] *pgd=00000043fba00003, *pmd=00000043fba00003, *pte=00e0000078010407
      Internal error: Oops: 96000006 [#1] SMP
      Modules linked in:
      CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.15.0-rc864k+ #44
      task: fffffe03bc040000 ti: fffffe03bc080000 task.ti: fffffe03bc080000
      PC is at __list_add+0x10/0xd4
      LR is at free_one_page+0x270/0x638
      ...
      Call trace:
        __list_add+0x10/0xd4
        free_one_page+0x26c/0x638
        __free_pages_ok.part.52+0x84/0xbc
        __free_pages+0x74/0xbc
        init_cma_reserved_pageblock+0xe8/0x104
        cma_init_reserved_areas+0x190/0x1e4
        do_one_initcall+0xc4/0x154
        kernel_init_freeable+0x204/0x2a8
        kernel_init+0xc/0xd4
    
    This happens because init_cma_reserved_pageblock() calls
    __free_one_page() with pageblock_order as page order but it is bigger
    than MAX_ORDER.  This in turn causes accesses past zone->free_list[].
    
    Fix the problem by changing init_cma_reserved_pageblock() such that it
    splits pageblock into individual MAX_ORDER pages if pageblock is bigger
    than a MAX_ORDER page.
    
    In cases where !CONFIG_HUGETLB_PAGE_SIZE_VARIABLE, which is all
    architectures expect for ia64, powerpc and tile at the moment, the
    “pageblock_order > MAX_ORDER” condition will be optimised out since both
    sides of the operator are constants.  In cases where pageblock size is
    variable, the performance degradation should not be significant anyway
    since init_cma_reserved_pageblock() is called only at boot time at most
    MAX_CMA_AREAS times which by default is eight.
    Signed-off-by: default avatarMichal Nazarewicz <mina86@mina86.com>
    Reported-by: default avatarMark Salter <msalter@redhat.com>
    Tested-by: default avatarMark Salter <msalter@redhat.com>
    Tested-by: default avatarChristopher Covington <cov@codeaurora.org>
    Cc: Mel Gorman <mgorman@suse.de>
    Cc: David Rientjes <rientjes@google.com>
    Cc: Marek Szyprowski <m.szyprowski@samsung.com>
    Cc: Catalin Marinas <catalin.marinas@arm.com>
    Cc: <stable@vger.kernel.org>	[3.5+]
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    dc78327c
page_alloc.c 184 KB