From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0A8E4C4727E for ; Thu, 1 Oct 2020 15:24:31 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A958D20719 for ; Thu, 1 Oct 2020 15:24:30 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="EfM8rOas"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="L3Z8I+Cr" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org A958D20719 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version: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=sqCe/nvZiQaEKf0gy8Huj7zpDQdgL2i3YI9xv9YWzDs=; b=EfM8rOasldkZfJvFcxyjG3los 0FFHUXdrxfntWhZ4bTU7Q5yzYVUunpcri79PFlhE/fg/mvMvRZW0OW61NyOQ+HLYmoYFqdNSwFxgz wLUU3y3DYwdUVFT2hzDlN80IWVZOFCuZ7bjHdCZJu83ttdW6+UQKXmc9DNK+inRSZCwpCFY6J10Ex N21j2USY18KwQVRCuvNNscUwB3LXuzYs55ET5Eg8fkUPtAFBscA75j7Iu/uCPKK9EUeXunJAtohIw zn1P3YePi6xH8ASS0Blr7rklfSYD4r7K8QUZ2sk1yo2U89vEo8K2FI1PhfOCOSTspgpCAKu58WQIc cjeIE1hSA==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kO0Q0-0000Kq-8j; Thu, 01 Oct 2020 15:22:52 +0000 Received: from mail-lj1-x244.google.com ([2a00:1450:4864:20::244]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kO0Pv-0000HI-VH for linux-arm-kernel@lists.infradead.org; Thu, 01 Oct 2020 15:22:49 +0000 Received: by mail-lj1-x244.google.com with SMTP id n25so5003220ljj.4 for ; Thu, 01 Oct 2020 08:22:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=RUW5N4EAoawnOCRHtwk3Ms/W06B4wy9TvxzPb8TQZbA=; b=L3Z8I+CrntxY4sKJ5EUu4FCbX8dpHQW/+Oqu2qoKnxGatoMRnQFdx/HkmNYG72aiyR 4hQ3G3yofBCUGGPkRhFenEkbK07Owh2OU7WCuowzDQ05Vb2irY8HMMcsqHxrqx+jNN8l NV1husVMFz1H99tZmXOmHtOLgLm3vljQzY6BIEb5WDhcUg5Phq18zyWrEwjEUwpaHzj+ d1ZH0tuVWp7tuGLi652GNnlcDcr20mKFxs2HogdcaMwHLIU+N+wX33Wg96T/PI+36rJB k7ourDA6SL5wchfnpVBE1WGQPDH5HEgwGeDbf/kW/QOobSCDhopPYb5K0BQkkCDqz4L5 k15A== 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:mime-version:content-transfer-encoding; bh=RUW5N4EAoawnOCRHtwk3Ms/W06B4wy9TvxzPb8TQZbA=; b=dw10Rl0Sukd5+plZ9WCcIdZiA3I3/Rhywu9x+WtyaOUhzhuJ2/WU9ztRFTwq1VwSvE q1JSdIOEe4ro2HpmPSNfmsSub0ZNJiiW/8hp17AFko1w4jb6eiaKXH0BP+8p7JZv4nDs kmpYMW4jipnCDQ7Q/8s9KUv9uNNpNf0v74iAtPT5VVwWtSDahdMtzYwvKR+SC2hkmnnW rXFnS10VXBcQj44q1OHL2UP6ZwJptx6/MUgxm/ljUV33M4CPRPO/hWqTv1MbMcKyap07 pw97EW5SIPw+uLzR7/McthGR+d+rYKonSPTB5MxgCEFGbqZmJl1OTjHbIzK1zF/4Qu21 WAcw== X-Gm-Message-State: AOAM532j+yUfQOgmLqFkr/Jea2+0y3s7N4C0v37RP1KUycglp6xNqddj l9+0CTVxLGqqJuH+8j5OGyVMig== X-Google-Smtp-Source: ABdhPJySdtjLNjyHI6jrKeQcUvzggxZTybSnNIFRfZvxVUWhCoVuwkRLnpwtTfHe1tdcgdJhf5kkgg== X-Received: by 2002:a2e:b531:: with SMTP id z17mr2761876ljm.30.1601565766389; Thu, 01 Oct 2020 08:22:46 -0700 (PDT) Received: from genomnajs.ideon.se ([85.235.10.227]) by smtp.gmail.com with ESMTPSA id v18sm587578lfa.238.2020.10.01.08.22.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Oct 2020 08:22:45 -0700 (PDT) From: Linus Walleij To: Florian Fainelli , Abbott Liu , Russell King , Ard Biesheuvel , Andrey Ryabinin , Mike Rapoport Subject: [PATCH 1/6 v14] ARM: Handle a device tree in lowmem Date: Thu, 1 Oct 2020 17:22:27 +0200 Message-Id: <20201001152232.274367-2-linus.walleij@linaro.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201001152232.274367-1-linus.walleij@linaro.org> References: <20201001152232.274367-1-linus.walleij@linaro.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201001_112248_058250_D5ABF994 X-CRM114-Status: GOOD ( 29.29 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Linus Walleij , Arnd Bergmann , linux-arm-kernel@lists.infradead.org Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org If the kernel grows big, it can happen that the kernel does not fit in the first memory block. This is normally out-of-spec but it turns out that the boot usually survives this. What it does not survive is that the prepare_page_table() code wipes all PMDs (page table pointers for the virtual memory) over lowmem, including the PMD where the attached DTB is stored. (The variable is named atags but this only really happens for DTBs.) Let's deal with this. First, this makes the code jump over two PMDs where the DTB is stored if it ends up in lowmem: it could happen that the DTB crosses a PMD_SIZE boundary so to be on the safe side we need to skip over the one we know it starts in and also the next. Next we make ARM use unflatten_and_copy_device_tree() instead of just unflattening it where it is. Currently we just assume that the device tree will be in some kind of "safe" memory and as proven by KASan it will sometimes end up in the kernel lowmem which will create crashes as the kernel will clear all lowmem PMDs while initializing the memory manager. Finally, we add a new call to the MMU code to go in and clear out the PMDs in lowmem if the device tree was there. Example boot log on an affected system: ATAGs/DTB found in lowmem, skip clearing PMD @0xc3000000 ATAGs/DTB found in lowmem, skip clearing PMD @0xc3200000 (...) DTB @430af0e0 (physical) copied to @cc394d80 (virtual) Clear ATAGs/DTB PMD @0xc3000000 Clear ATAGs/DTB PMD @0xc3200000 This fixes the problem where the Qualcomm APQ8060 would not boot while using KASan. Signed-off-by: Linus Walleij --- ChangeLog v13->v14: - New patch fixing the regression when using KASan on at least one of the affected platforms. --- arch/arm/include/asm/prom.h | 5 +++++ arch/arm/kernel/devtree.c | 14 +++++++++++++- arch/arm/kernel/setup.c | 8 ++++++-- arch/arm/mm/mmu.c | 37 +++++++++++++++++++++++++++++++++++-- 4 files changed, 59 insertions(+), 5 deletions(-) diff --git a/arch/arm/include/asm/prom.h b/arch/arm/include/asm/prom.h index 1e36c40533c1..41e189a2631c 100644 --- a/arch/arm/include/asm/prom.h +++ b/arch/arm/include/asm/prom.h @@ -11,6 +11,7 @@ extern const struct machine_desc *setup_machine_fdt(unsigned int dt_phys); extern void __init arm_dt_init_cpu_maps(void); +void __init setup_machine_copy_fdt(unsigned int dt_phys); #else /* CONFIG_OF */ @@ -21,5 +22,9 @@ static inline const struct machine_desc *setup_machine_fdt(unsigned int dt_phys) static inline void arm_dt_init_cpu_maps(void) { } +static inline void setup_machine_copy_fdt(unsigned int dt_phys) +{ +} + #endif /* CONFIG_OF */ #endif /* ASMARM_PROM_H */ diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c index 39c978698406..267011e133a7 100644 --- a/arch/arm/kernel/devtree.c +++ b/arch/arm/kernel/devtree.c @@ -23,7 +23,7 @@ #include #include #include - +#include #ifdef CONFIG_SMP extern struct of_cpu_method __cpu_method_of_table[]; @@ -257,3 +257,15 @@ const struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys) return mdesc; } + +extern void arm_mm_clear_atag_pages(void); + +void __init setup_machine_copy_fdt(unsigned int dt_phys) +{ + /* This will point the DT parser to the new location */ + unflatten_and_copy_device_tree(); + pr_info("DTB @%08x (physical) copied to @%px (virtual)\n", + dt_phys, initial_boot_params); + /* Clear out any mappings over the device tree */ + arm_mm_clear_atag_pages(); +} diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index d8e18cdd96d3..d0562cdc919e 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -1076,11 +1076,14 @@ void __init hyp_mode_check(void) void __init setup_arch(char **cmdline_p) { const struct machine_desc *mdesc; + bool using_dt = false; setup_processor(); mdesc = setup_machine_fdt(__atags_pointer); if (!mdesc) mdesc = setup_machine_tags(__atags_pointer, __machine_arch_type); + else + using_dt = true; if (!mdesc) { early_print("\nError: invalid dtb and unrecognized/unsupported machine ID\n"); early_print(" r1=0x%08x, r2=0x%08x\n", __machine_arch_type, @@ -1109,7 +1112,6 @@ void __init setup_arch(char **cmdline_p) early_fixmap_init(); early_ioremap_init(); - parse_early_param(); #ifdef CONFIG_MMU @@ -1135,7 +1137,9 @@ void __init setup_arch(char **cmdline_p) if (mdesc->restart) arm_pm_restart = mdesc->restart; - unflatten_device_tree(); + /* Remap and copy the device tree */ + if (using_dt) + setup_machine_copy_fdt(__atags_pointer); arm_dt_init_cpu_maps(); psci_dt_init(); diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index c36f977b2ccb..732c856c357d 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -68,6 +68,8 @@ pgprot_t pgprot_kernel; EXPORT_SYMBOL(pgprot_user); EXPORT_SYMBOL(pgprot_kernel); +extern unsigned long __atags_pointer; + struct cachepolicy { const char policy[16]; unsigned int cr_mask; @@ -1258,6 +1260,7 @@ void __init adjust_lowmem_bounds(void) static inline void prepare_page_table(void) { unsigned long addr; + unsigned long atags; phys_addr_t end; /* @@ -1284,9 +1287,40 @@ static inline void prepare_page_table(void) * Clear out all the kernel space mappings, except for the first * memory bank, up to the vmalloc region. */ + atags = __phys_to_virt(__atags_pointer); + atags &= PMD_MASK; for (addr = __phys_to_virt(end); - addr < VMALLOC_START; addr += PMD_SIZE) + addr < VMALLOC_START; addr += PMD_SIZE) { + if (addr >= atags && addr < (atags + 2 * PMD_SIZE)) { + pr_info("ATAGs/DTB found in lowmem, skip clearing PMD @0x%08lx\n", addr); + continue; + } pmd_clear(pmd_off_k(addr)); + } +} + +void __init arm_mm_clear_atag_pages(void) +{ + unsigned long addr; + unsigned long atags; + phys_addr_t end; + + /* + * Clear out the kernel space mappings used by the attached DTB if + * it happens to end up in lowmem. + */ + end = memblock.memory.regions[0].base + memblock.memory.regions[0].size; + if (end >= arm_lowmem_limit) + end = arm_lowmem_limit; + atags = __phys_to_virt(__atags_pointer); + atags &= PMD_MASK; + for (addr = __phys_to_virt(end); + addr < VMALLOC_START; addr += PMD_SIZE) { + if (addr >= atags && addr < (atags + 2 * PMD_SIZE)) { + pr_info("Clear ATAGs/DTB PMD @0x%08lx\n", addr); + pmd_clear(pmd_off_k(addr)); + } + } } #ifdef CONFIG_ARM_LPAE @@ -1503,7 +1537,6 @@ static void __init map_lowmem(void) } #ifdef CONFIG_ARM_PV_FIXUP -extern unsigned long __atags_pointer; typedef void pgtables_remap(long long offset, unsigned long pgd, void *bdata); pgtables_remap lpae_pgtables_remap_asm; -- 2.26.2 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel