From patchwork Thu Aug 11 17:08:12 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Catalin Marinas X-Patchwork-Id: 9275683 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 600ED600CB for ; Thu, 11 Aug 2016 17:08:32 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4BBBE28758 for ; Thu, 11 Aug 2016 17:08:32 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 409BF2875B; Thu, 11 Aug 2016 17:08:32 +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=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B747D28758 for ; Thu, 11 Aug 2016 17:08:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932362AbcHKRIR (ORCPT ); Thu, 11 Aug 2016 13:08:17 -0400 Received: from foss.arm.com ([217.140.101.70]:55624 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751059AbcHKRIR (ORCPT ); Thu, 11 Aug 2016 13:08:17 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 361E42F; Thu, 11 Aug 2016 10:09:45 -0700 (PDT) Received: from e104818-lin.cambridge.arm.com (e104818-lin.cambridge.arm.com [10.1.206.48]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 59A8B3F213; Thu, 11 Aug 2016 10:08:15 -0700 (PDT) Date: Thu, 11 Aug 2016 18:08:12 +0100 From: Catalin Marinas To: Grygorii Strashko Cc: Vignesh R , linux-mm@kvack.org, "linux-kernel@vger.kernel.org" , "linux-omap@vger.kernel.org" Subject: Re: kmemleak: Cannot insert 0xff7f1000 into the object search tree (overlaps existing) Message-ID: <20160811170812.GF18366@e104818-lin.cambridge.arm.com> References: <7f50c137-5c6a-0882-3704-ae9bb7552c30@ti.com> <20160811155423.GC18366@e104818-lin.cambridge.arm.com> <920709c7-2d5b-ea67-5f1c-4197ef30e3b2@ti.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <920709c7-2d5b-ea67-5f1c-4197ef30e3b2@ti.com> User-Agent: Mutt/1.5.23 (2014-03-12) Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP On Thu, Aug 11, 2016 at 07:48:12PM +0300, Grygorii Strashko wrote: > On 08/11/2016 06:54 PM, Catalin Marinas wrote: > > On Thu, Aug 11, 2016 at 05:20:51PM +0530, Vignesh R wrote: > >> I see the below message from kmemleak when booting linux-next on AM335x > >> GP EVM and DRA7 EVM > > > > Can you also reproduce it with 4.8-rc1? > > > >> [ 0.803934] kmemleak: Cannot insert 0xff7f1000 into the object search tree (overlaps existing) > >> [ 0.803950] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.8.0-rc1-next-20160809 #497 > >> [ 0.803958] Hardware name: Generic DRA72X (Flattened Device Tree) > >> [ 0.803979] [] (unwind_backtrace) from [] (show_stack+0x10/0x14) > >> [ 0.803994] [] (show_stack) from [] (dump_stack+0xac/0xe0) > >> [ 0.804010] [] (dump_stack) from [] (create_object+0x214/0x278) > >> [ 0.804025] [] (create_object) from [] (kmemleak_alloc_percpu+0x54/0xc0) > >> [ 0.804038] [] (kmemleak_alloc_percpu) from [] (pcpu_alloc+0x368/0x5fc) > >> [ 0.804052] [] (pcpu_alloc) from [] (crash_notes_memory_init+0x10/0x40) > >> [ 0.804064] [] (crash_notes_memory_init) from [] (do_one_initcall+0x3c/0x178) > >> [ 0.804075] [] (do_one_initcall) from [] (kernel_init_freeable+0x1fc/0x2c8) > >> [ 0.804086] [] (kernel_init_freeable) from [] (kernel_init+0x8/0x114) > >> [ 0.804098] [] (kernel_init) from [] (ret_from_fork+0x14/0x24) > > > > This is the allocation stack trace, going via pcpu_alloc(). > > > >> [ 0.804106] kmemleak: Kernel memory leak detector disabled > >> [ 0.804113] kmemleak: Object 0xfe800000 (size 16777216): > >> [ 0.804121] kmemleak: comm "swapper/0", pid 0, jiffies 4294937296 > >> [ 0.804127] kmemleak: min_count = -1 > >> [ 0.804132] kmemleak: count = 0 > >> [ 0.804138] kmemleak: flags = 0x5 > >> [ 0.804143] kmemleak: checksum = 0 > >> [ 0.804149] kmemleak: backtrace: > >> [ 0.804155] [] cma_declare_contiguous+0x16c/0x214 > >> [ 0.804170] [] dma_contiguous_reserve_area+0x30/0x64 > >> [ 0.804183] [] dma_contiguous_reserve+0x80/0x94 > >> [ 0.804195] [] arm_memblock_init+0x130/0x184 > >> [ 0.804207] [] setup_arch+0x590/0xc08 > >> [ 0.804217] [] start_kernel+0x58/0x3b4 > >> [ 0.804227] [<8000807c>] 0x8000807c > >> [ 0.804237] [] 0xffffffff > > > > This seems to be the original object that was allocated via > > cma_declare_contiguous(): 16MB range from 0xfe800000 to 0xff800000. > > Since the pointer returned by pcpu_alloc is 0xff7f1000 falls in the 16MB > > CMA range, kmemleak gets confused (it doesn't allow overlapping > > objects). > > > > So what I think goes wrong is that the kmemleak_alloc(__va(found)) call > > in memblock_alloc_range_nid() doesn't get the right value for the VA of > > the CMA block. The memblock_alloc_range() call in > > cma_declare_contiguous() asks for memory above high_memory, hence on a > > 32-bit architecture with highmem enabled, __va() use is not really > > valid, returning the wrong address. The existing kmemleak object is > > bogus, it shouldn't have been created in the first place. > > > > Now I'm trying to figure out how to differentiate between lowmem > > memblocks and highmem ones. Ignoring the kmemleak_alloc() calls > > altogether in mm/memblock.c is probably not an option as it would lead > > to lots of false positives. > > But cma_declare_contiguous() calls - > /* > * kmemleak scans/reads tracked objects for pointers to other > * objects but this address isn't mapped and accessible > */ > kmemleak_ignore(phys_to_virt(addr)); > > Does it means above code is incorrect also? Yes, as long as the phys_to_virt() use is invalid. You may get away with this, depending on the SoC. Also, kmemleak_ignore() here is meant to tell kmemleak not to bother with scanning or reporting such memory since it is not meant for pointers but it still keeps track of it. The only way to remove it from kmemleak is replace this with kmemleak_free(). But That's more of a hack since phys_to_virt(addr) is still invalid. > It's a little bit strange that this can be seen only now, because > commit 95b0e655f9 ("ARM: mm: don't limit default CMA region only to low memor") > is pretty old. You might want to double check my scenario above but I guess we've been lucky. So either some configuration changed and arm_dma_limit > arm_lowmem_limit or the random VA for the CMA memory didn't overlap with any other block. An untested attempt to avoid the kmemleak notification for highmem objects: diff --git a/mm/memblock.c b/mm/memblock.c index 483197ef613f..7d3361d53ac2 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -723,7 +723,8 @@ int __init_memblock memblock_free(phys_addr_t base, phys_addr_t size) (unsigned long long)base + size - 1, (void *)_RET_IP_); - kmemleak_free_part(__va(base), size); + if (base < __pa(high_memory)) + kmemleak_free_part(__va(base), size); return memblock_remove_range(&memblock.reserved, base, size); } @@ -1152,7 +1153,8 @@ static phys_addr_t __init memblock_alloc_range_nid(phys_addr_t size, * The min_count is set to 0 so that memblock allocations are * never reported as leaks. */ - kmemleak_alloc(__va(found), size, 0, 0); + if (found < __pa(high_memory)) + kmemleak_alloc(__va(found), size, 0, 0); return found; } return 0; @@ -1399,7 +1401,8 @@ void __init __memblock_free_early(phys_addr_t base, phys_addr_t size) memblock_dbg("%s: [%#016llx-%#016llx] %pF\n", __func__, (u64)base, (u64)base + size - 1, (void *)_RET_IP_); - kmemleak_free_part(__va(base), size); + if (base < __pa(high_memory)) + kmemleak_free_part(__va(base), size); memblock_remove_range(&memblock.reserved, base, size); } @@ -1419,7 +1422,8 @@ void __init __memblock_free_late(phys_addr_t base, phys_addr_t size) memblock_dbg("%s: [%#016llx-%#016llx] %pF\n", __func__, (u64)base, (u64)base + size - 1, (void *)_RET_IP_); - kmemleak_free_part(__va(base), size); + if (base < __pa(high_memory)) + kmemleak_free_part(__va(base), size); cursor = PFN_UP(base); end = PFN_DOWN(base + size);