From patchwork Fri May 5 19:46:19 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 98654 Delivered-To: patch@linaro.org Received: by 10.140.96.100 with SMTP id j91csp292611qge; Fri, 5 May 2017 12:48:06 -0700 (PDT) X-Received: by 10.98.202.149 with SMTP id y21mr18827493pfk.225.1494013686303; Fri, 05 May 2017 12:48:06 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 144si6012850pfa.118.2017.05.05.12.48.06; Fri, 05 May 2017 12:48:06 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751271AbdEETsF (ORCPT + 6 others); Fri, 5 May 2017 15:48:05 -0400 Received: from mout.kundenserver.de ([212.227.126.130]:64512 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750751AbdEETsE (ORCPT ); Fri, 5 May 2017 15:48:04 -0400 Received: from wuerfel.lan ([78.42.17.5]) by mrelayeu.kundenserver.de (mreue002 [212.227.15.129]) with ESMTPA (Nemesis) id 0MTsu0-1dX5kC1HLE-00QSA1; Fri, 05 May 2017 21:47:56 +0200 From: Arnd Bergmann To: Ben Hutchings Cc: stable@vger.kernel.org, Oliver O'Halloran , Anton Blanchard , Benjamin Herrenschmidt , Paul Mackerras , Mel Gorman , Andrew Morton , Linus Torvalds , Arnd Bergmann , Greg Kroah-Hartman Subject: [PATCH 3.16-stable 01/87] mm/init: fix zone boundary creation Date: Fri, 5 May 2017 21:46:19 +0200 Message-Id: <20170505194745.3627137-2-arnd@arndb.de> X-Mailer: git-send-email 2.9.0 In-Reply-To: <20170505194745.3627137-1-arnd@arndb.de> References: <20170505194745.3627137-1-arnd@arndb.de> X-Provags-ID: V03:K0:EJ8tvVEiu+ASHIkxZD7ZSgmlQ4d3a7QLHgPf5WEhNZX/dw4tUUC lx2GYkQlgdEWZo20kH2Uz5YBkkmxjKDs1/kOEm8pRz2r6IMo9ahMLCdEPXny3eYtoalEm0v FjOik9/IarXbgPHtldi4KukIZsn0agV1qTaD96k75KweHur9d8sXVX8yn2S7tg7mUAXKRuU p6WrojzDaDNqfjzUffH4w== X-UI-Out-Filterresults: notjunk:1; V01:K0:VPR1U2sNWMA=:zaR541hG4ZdowyS1E3wcN5 duyHov9fMY1vtbRakaCZefAEtiJ8y5qlqrGO+BspDMkS+OIeHt/0kxLqj9Q/yQZzua5zK+w0x LKQUQAMfMSG0X7zVmyl71x3BaJykUCi63TtnLsiF6riv4mCpgSHfcn8idkysiyMFHAEjP+n3e FNoEC45KniFoo6kj6qmqLBnT5dS0kp9fn5n+nvtt1yyG/nKfbtUn1kFxZgBgnH/9S8z0nn/WQ ccSQH/8S+pwmz4RayDwLaA5QPiOI3nbIN3m0FxVC+E3ob1fBK9i9LPo1kJhBWrVKxcMB9C9sk yAdyMFNxQxWozidc02ZR/T58SJ7e40+brjZPp6+BzVxI7iJLSC+bak78z6mIoXLTdLyS2WbdU 6gorTf0g7d6XBYMo0loIN1cbbe8nmxaQvOSsHArJCQbFM4PTrfcPHHARsfEJmI4wF8a5WGpGN 3aSI+LJ+I6kczzSA78d06aylciXqNXgifk1A8z6ypNbuRmDYwY0kVj+/AWghPKpWxvsv5PedY DFeKO22EcTZWdl20xC2B+pe1sWGOcMvGps8F2i5OvCK9kAtAKbcdLjDJQmooB0zmzRvYgszbV ruV0tcvQQBECNejB2Q/0+T6qrTqWj17faJFYP3J52LkQlhOLjNGQTFqINgajYrCxgWmvhaBp7 dEvz3PiFuzlFfH/jSgjxoJHA5vA8FO3j9A/BJ3BWhvr6E/xFW+WVI9P077OPq/eL8Om8= Sender: stable-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Oliver O'Halloran commit 90cae1fe1c3540f791d5b8e025985fa5e699b2bb upstream. As a part of memory initialisation the architecture passes an array to free_area_init_nodes() which specifies the max PFN of each memory zone. This array is not necessarily monotonic (due to unused zones) so this array is parsed to build monotonic lists of the min and max PFN for each zone. ZONE_MOVABLE is special cased here as its limits are managed by the mm subsystem rather than the architecture. Unfortunately, this special casing is broken when ZONE_MOVABLE is the not the last zone in the zone list. The core of the issue is: if (i == ZONE_MOVABLE) continue; arch_zone_lowest_possible_pfn[i] = arch_zone_highest_possible_pfn[i-1]; As ZONE_MOVABLE is skipped the lowest_possible_pfn of the next zone will be set to zero. This patch fixes this bug by adding explicitly tracking where the next zone should start rather than relying on the contents arch_zone_highest_possible_pfn[]. Thie is low priority. To get bitten by this you need to enable a zone that appears after ZONE_MOVABLE in the zone_type enum. As far as I can tell this means running a kernel with ZONE_DEVICE or ZONE_CMA enabled, so I can't see this affecting too many people. I only noticed this because I've been fiddling with ZONE_DEVICE on powerpc and 4.6 broke my test kernel. This bug, in conjunction with the changes in Taku Izumi's kernelcore=mirror patch (d91749c1dda71) and powerpc being the odd architecture which initialises max_zone_pfn[] to ~0ul instead of 0 caused all of system memory to be placed into ZONE_DEVICE at boot, followed a panic since device memory cannot be used for kernel allocations. I've already submitted a patch to fix the powerpc specific bits, but I figured this should be fixed too. Link: http://lkml.kernel.org/r/1462435033-15601-1-git-send-email-oohall@gmail.com Signed-off-by: Oliver O'Halloran Cc: Anton Blanchard Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Cc: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman Signed-off-by: Arnd Bergmann --- mm/page_alloc.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) -- 2.9.0 diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 9ddea0200c94..7415fb62fa9d 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -5319,15 +5319,18 @@ void __init free_area_init_nodes(unsigned long *max_zone_pfn) sizeof(arch_zone_lowest_possible_pfn)); memset(arch_zone_highest_possible_pfn, 0, sizeof(arch_zone_highest_possible_pfn)); - arch_zone_lowest_possible_pfn[0] = find_min_pfn_with_active_regions(); - arch_zone_highest_possible_pfn[0] = max_zone_pfn[0]; - for (i = 1; i < MAX_NR_ZONES; i++) { + + start_pfn = find_min_pfn_with_active_regions(); + + for (i = 0; i < MAX_NR_ZONES; i++) { if (i == ZONE_MOVABLE) continue; - arch_zone_lowest_possible_pfn[i] = - arch_zone_highest_possible_pfn[i-1]; - arch_zone_highest_possible_pfn[i] = - max(max_zone_pfn[i], arch_zone_lowest_possible_pfn[i]); + + end_pfn = max(max_zone_pfn[i], start_pfn); + arch_zone_lowest_possible_pfn[i] = start_pfn; + arch_zone_highest_possible_pfn[i] = end_pfn; + + start_pfn = end_pfn; } arch_zone_lowest_possible_pfn[ZONE_MOVABLE] = 0; arch_zone_highest_possible_pfn[ZONE_MOVABLE] = 0;