From patchwork Wed Jul 27 20:23:41 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolas Pitre X-Patchwork-Id: 9250379 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 1B08F60757 for ; Wed, 27 Jul 2016 20:25:46 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0D59A24B48 for ; Wed, 27 Jul 2016 20:25:46 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 020772522B; Wed, 27 Jul 2016 20:25:45 +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=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 29DFE24B48 for ; Wed, 27 Jul 2016 20:25:45 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1bSVND-0002rn-Cd; Wed, 27 Jul 2016 20:24:11 +0000 Received: from mail-qk0-x22b.google.com ([2607:f8b0:400d:c09::22b]) by bombadil.infradead.org with esmtps (Exim 4.85_2 #1 (Red Hat Linux)) id 1bSVN7-0002qP-0P for linux-arm-kernel@lists.infradead.org; Wed, 27 Jul 2016 20:24:09 +0000 Received: by mail-qk0-x22b.google.com with SMTP id o67so44980535qke.1 for ; Wed, 27 Jul 2016 13:23:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=date:from:to:cc:subject:message-id:user-agent:mime-version; bh=C4tmb/a5ZKKTkEdUAEe16QxyvI9Mo43aGPE+hM872zo=; b=Gw+3Ra55aOeqwAGa/l+naxR2sQKMcHSa3zPfpWR8GhkBsbOergwKhKiTNsn9pgV1io b8cKCU0f5Uj8mnoo/GIRMsedWYn9PspQjrvs9ECJnxVT4Qd1hHXs8LZ9cPqVbOJkqfNO EDLTTaHTq4cTH57qmbrvPjPlU20+bqYEo0e0w= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:date:from:to:cc:subject:message-id:user-agent :mime-version; bh=C4tmb/a5ZKKTkEdUAEe16QxyvI9Mo43aGPE+hM872zo=; b=F+RF/2i2yRCf/hqGMYNeGoQv5FzDO2vT/LnUWTsc1mkH39AbkMZU5WyjKM6i+cnL22 jyYRxS+2rOTSVfhHC1PXxsWD85ivfgTKOLqW+FZ4KpIc05Q600rkBkvL7i761njB1FNP U5rT4qE+askLgPhzas/y9+/S++S3NUrMNrfo98/Rm/0afqhw9ALaF2cshsNI1H7QGBk/ /aHHC5WfQKlzLtm4jpsFmsA/gFUq7Tlu5JPUpcuo3VTmesGz3yFuCJqnq5JzfbilIZIT aDDeKr+6G3jIREFjfM3ytUSIRlOXVA7paIds6HyNcjvy3MMLgHac4cgfFN9axG53Ttnj aSUA== X-Gm-Message-State: AEkoouunXOFoSWtppBpsJZ/hDIezxw6+Mq8Mih3JrGKuDY7a9CEfcTJo7Apy9etwcn72z+mq X-Received: by 10.55.6.148 with SMTP id 142mr37147501qkg.206.1469651022705; Wed, 27 Jul 2016 13:23:42 -0700 (PDT) Received: from xanadu.home ([2607:fa48:6e39:d410:feaa:14ff:fea7:ed77]) by smtp.gmail.com with ESMTPSA id 128sm5259122qke.10.2016.07.27.13.23.41 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 27 Jul 2016 13:23:42 -0700 (PDT) Date: Wed, 27 Jul 2016 16:23:41 -0400 (EDT) From: Nicolas Pitre To: linux-arm-kernel@lists.infradead.org Subject: [PATCH] sanity_check_meminfo(): avoid overflow on vmalloc_limit Message-ID: User-Agent: Alpine 2.20 (LFD 67 2015-01-07) MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160727_132405_269577_A1943C72 X-CRM114-Status: GOOD ( 15.07 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Emil Renner Berthing 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 To limit the amount of mapped low memory, we determine a physical address boundary based on the start of the vmalloc area using __pa(). Strictly speaking, the vmalloc area location is arbitrary and does not necessarily corresponds to a valid physical address. For example, if PAGE_OFFSET = 0x80000000 PHYS_OFFSET = 0x90000000 vmalloc_min = 0xf0000000 then __pa(vmalloc_min) overflows and returns a wrapped 0 when phys_addr_t is a 32-bit type. Then the code that follows determines that the entire physical memory is above that boundary and no low memory gets mapped at all: |[...] |Machine model: Freescale i.MX51 NA04 Board |Ignoring RAM at 0x90000000-0xb0000000 (!CONFIG_HIGHMEM) |Consider using a HIGHMEM enabled kernel. To avoid this problem let's make vmalloc_limit a 64-bit value all the time and determine that boundary explicitly without using __pa(). Reported-by: Emil Renner Berthing Signed-off-by: Nicolas Pitre Tested-by: Emil Renner Berthing diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 62f4d01941..12774c8e77 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -1155,10 +1155,19 @@ void __init sanity_check_meminfo(void) { phys_addr_t memblock_limit = 0; int highmem = 0; - phys_addr_t vmalloc_limit = __pa(vmalloc_min - 1) + 1; + u64 vmalloc_limit; struct memblock_region *reg; bool should_use_highmem = false; + /* + * Let's use our own (unoptimized) equivalent of __pa() that is + * not affected by wrap-arounds when sizeof(phys_addr_t) == 4. + * The result is used as the upper bound on physical memory address + * and may itself be outside the valid range for which phys_addr_t + * and therefore __pa() is defined. + */ + vmalloc_limit = (u64)(uintptr_t)vmalloc_min - PAGE_OFFSET + PHYS_OFFSET; + for_each_memblock(memory, reg) { phys_addr_t block_start = reg->base; phys_addr_t block_end = reg->base + reg->size; @@ -1183,10 +1192,11 @@ void __init sanity_check_meminfo(void) if (reg->size > size_limit) { phys_addr_t overlap_size = reg->size - size_limit; - pr_notice("Truncating RAM at %pa-%pa to -%pa", - &block_start, &block_end, &vmalloc_limit); - memblock_remove(vmalloc_limit, overlap_size); + pr_notice("Truncating RAM at %pa-%pa", + &block_start, &block_end); block_end = vmalloc_limit; + pr_cont(" to -%pa", &block_end); + memblock_remove(vmalloc_limit, overlap_size); should_use_highmem = true; } }