From patchwork Fri Oct 9 15:55:09 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: yalin wang X-Patchwork-Id: 7362481 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 4414EBEEA4 for ; Fri, 9 Oct 2015 15:57:19 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 5D40920610 for ; Fri, 9 Oct 2015 15:57:18 +0000 (UTC) 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.kernel.org (Postfix) with ESMTPS id 6DFEA20673 for ; Fri, 9 Oct 2015 15:57:17 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1Zka1O-0002HA-4E; Fri, 09 Oct 2015 15:55:50 +0000 Received: from mail-pa0-x244.google.com ([2607:f8b0:400e:c03::244]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1Zka1K-0001re-Pd for linux-arm-kernel@lists.infradead.org; Fri, 09 Oct 2015 15:55:47 +0000 Received: by palb17 with SMTP id b17so10828579pal.2 for ; Fri, 09 Oct 2015 08:55:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:subject:date:message-id; bh=ulukDN5GbM6i1LXXtIDMU2lG4ZUjiUyWEijy1kZrxrg=; b=FjAulHHT2I5qOZjGX+QlWzpVnwIHsTUUC0D2GegWwQEzhOshQ9Nj2RzIzwE9v1Po1o gJvxu2CuGmQrcYXUbZ4/yOMv4fR0XcsVTK9xm7ED8S/jmcWR8ybRa56eItKn1KwQq2nD rFigaczsuNnZccrLoUeV8x6yZuyHUo8ERAT1lugTnwe+PV7MA7ZhDt/BiBUYrToiWRl8 Cvd/HIzPDMDj7x6PAUYSxsUnvKHd5pOk8Qr2U5P1V4IfNLR++F1QqR6tDz/JvarxNu+b uXOOUwG8eEorayTS++f5iXJbXVP05HyzTQ5D+rrSVFoNXuvT+RqIhHmeWRzpzc4CQ3N4 GxrQ== X-Received: by 10.66.228.97 with SMTP id sh1mr15889571pac.91.1444406125239; Fri, 09 Oct 2015 08:55:25 -0700 (PDT) Received: from ubuntu.localdomain ([17.87.20.100]) by smtp.googlemail.com with ESMTPSA id x6sm3255697pbt.3.2015.10.09.08.55.18 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 09 Oct 2015 08:55:24 -0700 (PDT) From: yalin wang To: linux@arm.linux.org.uk, nico@linaro.org, keescook@chromium.org, robh@kernel.org, stefan@agner.ch, yalin.wang2010@gmail.com, rabin@rab.in, msalter@redhat.com, ard.biesheuvel@linaro.org, will.deacon@arm.com, ssantosh@kernel.org, yamada.m@jp.panasonic.com, sboyd@codeaurora.org, contact@paulk.fr, pavel@ucw.cz, slash.tmp@free.fr, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [RFC] arm: add relocate initrd support Date: Fri, 9 Oct 2015 23:55:09 +0800 Message-Id: <1444406109-28354-1-git-send-email-yalin.wang2010@gmail.com> X-Mailer: git-send-email 1.9.1 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20151009_085546_881520_8D5FDE6E X-CRM114-Status: GOOD ( 16.62 ) X-Spam-Score: -2.5 (--) 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: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.1 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, T_DKIM_INVALID, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add support for initrd on ARM arch, in case mem= boot option change the memory size or the initrd are not placed in low memory region, we need copy the initrd to low memory region. Signed-off-by: yalin wang --- arch/arm/include/asm/fixmap.h | 1 + arch/arm/kernel/setup.c | 72 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/arch/arm/include/asm/fixmap.h b/arch/arm/include/asm/fixmap.h index 58cfe9f..18ad90f 100644 --- a/arch/arm/include/asm/fixmap.h +++ b/arch/arm/include/asm/fixmap.h @@ -10,6 +10,7 @@ enum fixed_addresses { FIX_EARLYCON_MEM_BASE, + FIX_RELOCATE_INITRD, __end_of_permanent_fixed_addresses, FIX_KMAP_BEGIN = __end_of_permanent_fixed_addresses, diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 20edd34..4260d59 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -811,6 +811,77 @@ static void __init request_standard_resources(const struct machine_desc *mdesc) request_resource(&ioport_resource, &lp2); } +#if defined(CONFIG_BLK_DEV_INITRD) && defined(CONFIG_MMU) +/* + * Relocate initrd if it is not completely within the linear mapping. + * This would be the case if mem= cuts out all or part of it + * or the initrd are not in low mem region place. + */ +static void __init relocate_initrd(void) +{ + phys_addr_t orig_start = __virt_to_phys(initrd_start); + phys_addr_t orig_end = __virt_to_phys(initrd_end); + phys_addr_t ram_end = memblock_end_of_DRAM(); + phys_addr_t new_start; + phys_addr_t src; + unsigned long size, to_free = 0; + unsigned long slop, clen, p; + void *dest; + + if (orig_end <= memblock_get_current_limit()) + return; + + /* + * Any of the original initrd which overlaps the linear map should + * be freed after relocating. + */ + if (orig_start < ram_end) + to_free = min(ram_end, orig_end) - orig_start; + + size = orig_end - orig_start; + + /* initrd needs to be relocated completely inside linear mapping */ + new_start = memblock_find_in_range(0, 0, size, PAGE_SIZE); + if (!new_start) + panic("Cannot relocate initrd of size %ld\n", size); + memblock_reserve(new_start, size); + + initrd_start = __phys_to_virt(new_start); + initrd_end = initrd_start + size; + + pr_info("Moving initrd from [%llx-%llx] to [%llx-%llx]\n", + (unsigned long long)orig_start, + (unsigned long long)(orig_start + size - 1), + (unsigned long long)new_start, + (unsigned long long)(new_start + size - 1)); + + dest = (void *)initrd_start; + + src = orig_start; + while (size) { + slop = src & ~PAGE_MASK; + clen = min(PAGE_SIZE - slop, size); + p = set_fixmap_offset(FIX_RELOCATE_INITRD, src); + memcpy(dest, (void *)p, clen); + clear_fixmap(FIX_RELOCATE_INITRD); + dest += clen; + src += clen; + size -= clen; + } + + if (to_free) { + pr_info("Freeing original RAMDISK from [%llx-%llx]\n", + (unsigned long long)orig_start, + (unsigned long long)(orig_start + to_free - 1)); + memblock_free(orig_start, to_free); + } +} +#else +static inline void __init relocate_initrd(void) +{ +} +#endif + #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) struct screen_info screen_info = { .orig_video_lines = 30, @@ -969,6 +1040,7 @@ void __init setup_arch(char **cmdline_p) arm_memblock_init(mdesc); paging_init(mdesc); + relocate_initrd(); request_standard_resources(mdesc); if (mdesc->restart)