From patchwork Mon Apr 2 02:30:32 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jia He X-Patchwork-Id: 10319415 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 3050460388 for ; Mon, 2 Apr 2018 02:32:59 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 21511279E0 for ; Mon, 2 Apr 2018 02:32:59 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1603828161; Mon, 2 Apr 2018 02:32:59 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, DKIM_VALID, FREEMAIL_FROM autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 72B2E279E0 for ; Mon, 2 Apr 2018 02:32:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=DuBepwT0+RxLo5Vx56ZOc0hmt6gw2nSDAsN9ULHOoao=; b=rHDXYO6Vj6yHJ5lk3j1Hu7Ps7k 9schxruYzCYrOYQndOKIF99Y1fSdWi5E4c4syjI66RIT2j9isna9AbAOi3tI33nFNoMVmjQHZdaY2 8yjtgilwapuXnNtfgeqUnoiEeqSj8zkFPkPJXVUvbUi1jWYGNXEhu8AUP57E+aQM1HNu/SEWVnhBD 7xpUEgEkH63gtQo1CcTiODd+obVEntr79BepYw4QLDA39Oqh8mJkOLAy4iSGAbEwxOGWB+qtrdUGU zvLuMu6e6Ol6bbBNrgx+OtPbIw7+3WSx2oA5Jj5/eDZCXKwzJS+3IvLFJ5zNZjTsTc+bH0V2efGUE ie+CAgHQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1f2pH6-0005zd-Aj; Mon, 02 Apr 2018 02:32:48 +0000 Received: from mail-pl0-x242.google.com ([2607:f8b0:400e:c01::242]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1f2pGt-0005hO-1Y for linux-arm-kernel@lists.infradead.org; Mon, 02 Apr 2018 02:32:40 +0000 Received: by mail-pl0-x242.google.com with SMTP id 59-v6so595936plc.13 for ; Sun, 01 Apr 2018 19:32:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=nfnmpH36ya8Gy6VB0XveTx1x0oDqOdqdNrB069YfGZk=; b=pBfEmbl7mZJw0fmEunrmC8x2Zxqlhh9eAtzAn9uh4SHqYwQ5dxchSJH02cyesRZYzA saJMKJLvU16W5Kv1qkVERpe4gKAtmlb2JLPZqPkmj6lOTr860DarfnbEdWx2ygbsAQWe ah0un21jehGVtaTyfk1OxYZGm9YCYXBiaTKp2vl0ZLIQYCCH4KUADXiPM6Gv7qOXGwhj nf6RcraiuEgFl1IUVsdRcZQJCs/p+jPRSiXd+HdXvFmamzIzaX7mK/yCnPlkrIiEpaKo UTj77t8H0jub2JSww5r6GjfMT7oSmamlNm4a+FB5cPsmlYbG3qFmyD6yYJ7RsHOGmaYn AaCA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=nfnmpH36ya8Gy6VB0XveTx1x0oDqOdqdNrB069YfGZk=; b=IDViFoux8FP9XNZAjkti2FfRvUHDhl+LH2088LXeDMlBHZIoI+TChmiUCNetNVNPmj Pi9o43wHCXoh3/zyi5+rHyCSBar/gBakfnMncB++izkMTSSWghyfsIA18rPMNdjAy62r cS8dgxYqJkap25JkvDwhAwLOv3cIYMrA8EjwjOVocetU90D55863X8F/sxsu7I+WZtxJ NPP8s4HQmZy9AWXefXTwCZWWVbnzm9yl39jAoPsYV53qWdLJIXHAoMfLZW7UbpPccGtL Am5XALZ4bzhLSI520hvaQEs8GGKDT3Kbv+IN38TnyEVvXRK5oll4VHT6qMtLXMsci/3K NIpg== X-Gm-Message-State: AElRT7EKdk0MIV0MCpqnW7un5Adz3N5Se025eUyZIPfUCd96T96nayED XYPzZTr/JjU6sSjA9fXKXDKHOEhF X-Google-Smtp-Source: AIpwx4+AMuIl96EDcwYRz5OyailPacf+bTFCRDWxU/z0OaqH7sI2tFs5KxuEz2s9y2ajhZWrr7y1ow== X-Received: by 2002:a17:902:102a:: with SMTP id b39-v6mr8161699pla.112.1522636343980; Sun, 01 Apr 2018 19:32:23 -0700 (PDT) Received: from localhost.localdomain ([38.106.11.25]) by smtp.gmail.com with ESMTPSA id t20sm25934371pfh.182.2018.04.01.19.32.11 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 01 Apr 2018 19:32:23 -0700 (PDT) From: Jia He To: Russell King , Catalin Marinas , Will Deacon , Mark Rutland , Ard Biesheuvel , Andrew Morton , Michal Hocko Subject: [PATCH v5 1/5] mm: page_alloc: remain memblock_next_valid_pfn() on arm and arm64 Date: Sun, 1 Apr 2018 19:30:32 -0700 Message-Id: <1522636236-12625-2-git-send-email-hejianet@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1522636236-12625-1-git-send-email-hejianet@gmail.com> References: <1522636236-12625-1-git-send-email-hejianet@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20180401_193235_115298_1FAF3BBA X-CRM114-Status: GOOD ( 22.12 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Grygorii Strashko , Wei Yang , linux-mm@kvack.org, Eugeniu Rosca , Petr Tesarik , Nikolay Borisov , Jia He , Pavel Tatashin , Daniel Jordan , AKASHI Takahiro , Gioh Kim , Andrey Ryabinin , Laura Abbott , Daniel Vacek , Mel Gorman , Vladimir Murzin , Kees Cook , Philip Derrin , YASUAKI ISHIMATSU , Jia He , Kemi Wang , Vlastimil Babka , linux-arm-kernel@lists.infradead.org, Steve Capper , linux-kernel@vger.kernel.org, James Morse , Johannes Weiner MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Commit b92df1de5d28 ("mm: page_alloc: skip over regions of invalid pfns where possible") optimized the loop in memmap_init_zone(). But it causes possible panic bug. So Daniel Vacek reverted it later. But as suggested by Daniel Vacek, it is fine to using memblock to skip gaps and finding next valid frame with CONFIG_HAVE_ARCH_PFN_VALID. On arm and arm64, memblock is used by default. But generic version of pfn_valid() is based on mem sections and memblock_next_valid_pfn() does not always return the next valid one but skips more resulting in some valid frames to be skipped (as if they were invalid). And that's why kernel was eventually crashing on some !arm machines. And as verified by Eugeniu Rosca, arm can benifit from commit b92df1de5d28. So remain the memblock_next_valid_pfn on arm{,64} and move the related codes to arm64 arch directory. Suggested-by: Daniel Vacek Signed-off-by: Jia He --- arch/arm/include/asm/page.h | 2 ++ arch/arm/mm/init.c | 31 ++++++++++++++++++++++++++++++- arch/arm64/include/asm/page.h | 2 ++ arch/arm64/mm/init.c | 31 ++++++++++++++++++++++++++++++- include/linux/mmzone.h | 1 + mm/page_alloc.c | 4 +++- 6 files changed, 68 insertions(+), 3 deletions(-) diff --git a/arch/arm/include/asm/page.h b/arch/arm/include/asm/page.h index 4355f0e..489875c 100644 --- a/arch/arm/include/asm/page.h +++ b/arch/arm/include/asm/page.h @@ -158,6 +158,8 @@ typedef struct page *pgtable_t; #ifdef CONFIG_HAVE_ARCH_PFN_VALID extern int pfn_valid(unsigned long); +extern unsigned long memblock_next_valid_pfn(unsigned long pfn); +#define skip_to_last_invalid_pfn(pfn) (memblock_next_valid_pfn(pfn) - 1) #endif #include diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index a1f11a7..0fb85ca 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -198,7 +198,36 @@ int pfn_valid(unsigned long pfn) return memblock_is_map_memory(__pfn_to_phys(pfn)); } EXPORT_SYMBOL(pfn_valid); -#endif + +/* HAVE_MEMBLOCK is always enabled on arm */ +unsigned long __init_memblock memblock_next_valid_pfn(unsigned long pfn) +{ + struct memblock_type *type = &memblock.memory; + unsigned int right = type->cnt; + unsigned int mid, left = 0; + phys_addr_t addr = PFN_PHYS(++pfn); + + do { + mid = (right + left) / 2; + + if (addr < type->regions[mid].base) + right = mid; + else if (addr >= (type->regions[mid].base + + type->regions[mid].size)) + left = mid + 1; + else { + /* addr is within the region, so pfn is valid */ + return pfn; + } + } while (left < right); + + if (right == type->cnt) + return -1UL; + else + return PHYS_PFN(type->regions[right].base); +} +EXPORT_SYMBOL(memblock_next_valid_pfn); +#endif /*CONFIG_HAVE_ARCH_PFN_VALID*/ #ifndef CONFIG_SPARSEMEM static void __init arm_memory_present(void) diff --git a/arch/arm64/include/asm/page.h b/arch/arm64/include/asm/page.h index 60d02c8..e57d3f2 100644 --- a/arch/arm64/include/asm/page.h +++ b/arch/arm64/include/asm/page.h @@ -39,6 +39,8 @@ typedef struct page *pgtable_t; #ifdef CONFIG_HAVE_ARCH_PFN_VALID extern int pfn_valid(unsigned long); +extern unsigned long memblock_next_valid_pfn(unsigned long pfn); +#define skip_to_last_invalid_pfn(pfn) (memblock_next_valid_pfn(pfn) - 1) #endif #include diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index 00e7b90..13e43ff 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -290,7 +290,36 @@ int pfn_valid(unsigned long pfn) return memblock_is_map_memory(pfn << PAGE_SHIFT); } EXPORT_SYMBOL(pfn_valid); -#endif + +/* HAVE_MEMBLOCK is always enabled on arm64 */ +unsigned long __init_memblock memblock_next_valid_pfn(unsigned long pfn) +{ + struct memblock_type *type = &memblock.memory; + unsigned int right = type->cnt; + unsigned int mid, left = 0; + phys_addr_t addr = PFN_PHYS(++pfn); + + do { + mid = (right + left) / 2; + + if (addr < type->regions[mid].base) + right = mid; + else if (addr >= (type->regions[mid].base + + type->regions[mid].size)) + left = mid + 1; + else { + /* addr is within the region, so pfn is valid */ + return pfn; + } + } while (left < right); + + if (right == type->cnt) + return -1UL; + else + return PHYS_PFN(type->regions[right].base); +} +EXPORT_SYMBOL(memblock_next_valid_pfn); +#endif /*CONFIG_HAVE_ARCH_PFN_VALID*/ #ifndef CONFIG_SPARSEMEM static void __init arm64_memory_present(void) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index d797716..f9c0c46 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -1245,6 +1245,7 @@ static inline int pfn_valid(unsigned long pfn) return 0; return valid_section(__nr_to_section(pfn_to_section_nr(pfn))); } +#define skip_to_last_invalid_pfn(pfn) (pfn) #endif static inline int pfn_present(unsigned long pfn) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index c19f5ac..30f7d76 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -5483,8 +5483,10 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone, if (context != MEMMAP_EARLY) goto not_early; - if (!early_pfn_valid(pfn)) + if (!early_pfn_valid(pfn)) { + pfn = skip_to_last_invalid_pfn(pfn); continue; + } if (!early_pfn_in_nid(pfn, nid)) continue; if (!update_defer_init(pgdat, pfn, end_pfn, &nr_initialised))