From patchwork Wed Mar 18 17:05:05 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 45977 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-la0-f72.google.com (mail-la0-f72.google.com [209.85.215.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 4A5882153C for ; Wed, 18 Mar 2015 17:09:02 +0000 (UTC) Received: by lams18 with SMTP id s18sf8521944lam.2 for ; Wed, 18 Mar 2015 10:09:01 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:subject:date:message-id :in-reply-to:references:cc:precedence:list-id:list-unsubscribe :list-archive:list-post:list-help:list-subscribe:mime-version :content-type:content-transfer-encoding:sender:errors-to :x-original-sender:x-original-authentication-results:mailing-list; bh=b64AZEmJ12FjJJYaAPx3o7A8Z0NCKeEjIdkhw6+8LWY=; b=lLPPvdzUpFFAU4f569E3eM//SfIdui9u8p+i43pISeCSa+YpwizSDH0T62OnYw1rsS drG2OQn7rt49Ir/wj5CArNAdR1FqqrKCYJ6hm6rAyuMzc6yPxBMOq/i/5zIew//i+gtK LnMYjGujII0ZN1gdBlkYIHKBnqjZHJDfWC9ZW3QuIO0KInc/qwJjJj+v3ROc1qizdlkG WNgXfX43SBW5G8XZNdtdYsBqj8E09CZ71FZ7jrlQjyViI9IKpuQBjxlxUkObswCk4iPz hh6gW9Jzfuw73Q0pEYmN1/WQHM52Qic3WWTdzpozI0+re9JPw17pR/P8LPanG0O31mNR HDiw== X-Gm-Message-State: ALoCoQnh32Ypw5AyuX9+tv1gFDDzlJxwgwo7fXaA3dyBTglUD8GNyDlnsk2UJIryeQn3JhXFL9cC X-Received: by 10.152.6.41 with SMTP id x9mr11267474lax.10.1426698541164; Wed, 18 Mar 2015 10:09:01 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.170.164 with SMTP id an4ls193749lac.19.gmail; Wed, 18 Mar 2015 10:09:00 -0700 (PDT) X-Received: by 10.152.170.164 with SMTP id an4mr50934662lac.9.1426698540849; Wed, 18 Mar 2015 10:09:00 -0700 (PDT) Received: from mail-lb0-f170.google.com (mail-lb0-f170.google.com. [209.85.217.170]) by mx.google.com with ESMTPS id ai6si13340706lbc.147.2015.03.18.10.09.00 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 18 Mar 2015 10:09:00 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.170 as permitted sender) client-ip=209.85.217.170; Received: by lbbsy1 with SMTP id sy1so34614567lbb.1 for ; Wed, 18 Mar 2015 10:09:00 -0700 (PDT) X-Received: by 10.112.212.106 with SMTP id nj10mr46376201lbc.36.1426698540278; Wed, 18 Mar 2015 10:09:00 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.35.133 with SMTP id h5csp1287031lbj; Wed, 18 Mar 2015 10:08:58 -0700 (PDT) X-Received: by 10.66.66.108 with SMTP id e12mr166384692pat.31.1426698537674; Wed, 18 Mar 2015 10:08:57 -0700 (PDT) Received: from bombadil.infradead.org (bombadil.infradead.org. [2001:1868:205::9]) by mx.google.com with ESMTPS id sw9si37157108pab.235.2015.03.18.10.08.56 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 18 Mar 2015 10:08:57 -0700 (PDT) Received-SPF: none (google.com: linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org does not designate permitted sender hosts) client-ip=2001:1868:205::9; 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 1YYHQt-0000OS-CH; Wed, 18 Mar 2015 17:07:03 +0000 Received: from mail-we0-f177.google.com ([74.125.82.177]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1YYHPk-0008EV-2j for linux-arm-kernel@lists.infradead.org; Wed, 18 Mar 2015 17:05:54 +0000 Received: by weop45 with SMTP id p45so37459972weo.0 for ; Wed, 18 Mar 2015 10:05:30 -0700 (PDT) X-Received: by 10.180.105.40 with SMTP id gj8mr8700679wib.67.1426698329984; Wed, 18 Mar 2015 10:05:29 -0700 (PDT) Received: from ards-macbook-pro.local ([84.78.25.113]) by mx.google.com with ESMTPSA id dc9sm3972217wib.9.2015.03.18.10.05.27 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 18 Mar 2015 10:05:29 -0700 (PDT) From: Ard Biesheuvel To: linux-arm-kernel@lists.infradead.org, linux@arm.linux.org.uk, will.deacon@arm.com, mark.rutland@arm.com, catalin.marinas@arm.com, robh@kernel.org Subject: [PATCH v3 2/5] arm64: use fixmap region for permanent FDT mapping Date: Wed, 18 Mar 2015 18:05:05 +0100 Message-Id: <1426698308-726-3-git-send-email-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1426698308-726-1-git-send-email-ard.biesheuvel@linaro.org> References: <1426698308-726-1-git-send-email-ard.biesheuvel@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150318_100552_472079_EF06A0AE X-CRM114-Status: GOOD ( 24.37 ) X-Spam-Score: -0.7 (/) X-Spam-Report: SpamAssassin version 3.4.0 on bombadil.infradead.org summary: Content analysis details: (-0.7 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [74.125.82.177 listed in list.dnswl.org] -0.0 RCVD_IN_MSPIKE_H3 RBL: Good reputation (+3) [74.125.82.177 listed in wl.mailspike.net] -0.0 SPF_PASS SPF: sender matches SPF record -0.0 RCVD_IN_MSPIKE_WL Mailspike good senders Cc: Ard Biesheuvel X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 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+patch=linaro.org@lists.infradead.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: ard.biesheuvel@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.170 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 Currently, the FDT blob needs to be in the same naturally aligned 512 MB region as the kernel, so that it can be mapped into the kernel virtual memory space very early on using a minimal set of statically allocated translation tables. Now that we have early fixmap support, we can relax this restriction, by moving the permanent FDT mapping to the fixmap region instead. This way, the FDT blob may be anywhere in memory. This also moves the vetting of the FDT to setup.c, since the early init code in head.S does not handle mapping of the FDT anymore. At the same time, fix up some comments in head.S that have gone stale. Signed-off-by: Ard Biesheuvel --- Documentation/arm64/booting.txt | 10 +++--- arch/arm64/include/asm/fixmap.h | 9 ++++++ arch/arm64/kernel/Makefile | 1 + arch/arm64/kernel/head.S | 38 +--------------------- arch/arm64/kernel/setup.c | 72 +++++++++++++++++++++++++++++------------ arch/arm64/mm/init.c | 1 - 6 files changed, 69 insertions(+), 62 deletions(-) diff --git a/Documentation/arm64/booting.txt b/Documentation/arm64/booting.txt index f3c05b5f9f08..ab5a90adece3 100644 --- a/Documentation/arm64/booting.txt +++ b/Documentation/arm64/booting.txt @@ -45,11 +45,13 @@ sees fit.) Requirement: MANDATORY -The device tree blob (dtb) must be placed on an 8-byte boundary within -the first 512 megabytes from the start of the kernel image and must not -cross a 2-megabyte boundary. This is to allow the kernel to map the -blob using a single section mapping in the initial page tables. +The device tree blob (dtb) must be placed on an 8-byte boundary and must +not cross a 2-megabyte boundary. This is to allow the kernel to map the +blob using a single section mapping in the fixmap region. +NOTE: versions prior to v4.1 require, in addition to the requirements +listed above, that the dtb be placed above the kernel Image inside the +same naturally aligned 512 MB region. 3. Decompress the kernel image ------------------------------ diff --git a/arch/arm64/include/asm/fixmap.h b/arch/arm64/include/asm/fixmap.h index 926495686554..6e34347e80e3 100644 --- a/arch/arm64/include/asm/fixmap.h +++ b/arch/arm64/include/asm/fixmap.h @@ -32,6 +32,15 @@ */ enum fixed_addresses { FIX_HOLE, + + /* + * Reserve 2 MB of virtual space for the FDT at the top of the fixmap + * region. Keep this at the top so it remains 2 MB aligned. + */ +#define FIX_FDT_SIZE SZ_2M + FIX_FDT_END, + FIX_FDT = FIX_FDT_END + FIX_FDT_SIZE / PAGE_SIZE - 1, + FIX_EARLYCON_MEM_BASE, FIX_TEXT_POKE0, __end_of_permanent_fixed_addresses, diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 5ee07eee80c2..e60885766936 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -6,6 +6,7 @@ CPPFLAGS_vmlinux.lds := -DTEXT_OFFSET=$(TEXT_OFFSET) AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET) CFLAGS_efi-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) CFLAGS_armv8_deprecated.o := -I$(src) +CFLAGS_setup.o := -I$(srctree)/scripts/dtc/libfdt/ CFLAGS_REMOVE_ftrace.o = -pg CFLAGS_REMOVE_insn.o = -pg diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index d17649d39392..c849cfb157b3 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -255,7 +255,6 @@ ENTRY(stext) cbnz x23, 1f // invalid processor (x23=0)? b __error_p 1: - bl __vet_fdt bl __create_page_tables // x25=TTBR0, x26=TTBR1 /* * The following calls CPU specific code in a position independent @@ -274,24 +273,6 @@ ENTRY(stext) ENDPROC(stext) /* - * Determine validity of the x21 FDT pointer. - * The dtb must be 8-byte aligned and live in the first 512M of memory. - */ -__vet_fdt: - tst x21, #0x7 - b.ne 1f - cmp x21, x24 - b.lt 1f - mov x0, #(1 << 29) - add x0, x0, x24 - cmp x21, x0 - b.ge 1f - ret -1: - mov x21, #0 - ret -ENDPROC(__vet_fdt) -/* * Macro to create a table entry to the next page. * * tbl: page table address @@ -352,8 +333,7 @@ ENDPROC(__vet_fdt) * required to get the kernel running. The following sections are required: * - identity mapping to enable the MMU (low address, TTBR0) * - first few MB of the kernel linear mapping to jump to once the MMU has - * been enabled, including the FDT blob (TTBR1) - * - pgd entry for fixed mappings (TTBR1) + * been enabled */ __create_page_tables: pgtbl x25, x26, x28 // idmap_pg_dir and swapper_pg_dir addresses @@ -404,22 +384,6 @@ __create_page_tables: create_block_map x0, x7, x3, x5, x6 /* - * Map the FDT blob (maximum 2MB; must be within 512MB of - * PHYS_OFFSET). - */ - mov x3, x21 // FDT phys address - and x3, x3, #~((1 << 21) - 1) // 2MB aligned - mov x6, #PAGE_OFFSET - sub x5, x3, x24 // subtract PHYS_OFFSET - tst x5, #~((1 << 29) - 1) // within 512MB? - csel x21, xzr, x21, ne // zero the FDT pointer - b.ne 1f - add x5, x5, x6 // __va(FDT blob) - add x6, x5, #1 << 21 // 2MB for the FDT blob - sub x6, x6, #1 // inclusive range - create_block_map x0, x7, x3, x5, x6 -1: - /* * Since the page tables have been populated with non-cacheable * accesses (MMU disabled), invalidate the idmap and swapper page * tables again to remove any speculatively loaded cache lines. diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 14808947bf46..ef21f6e172f8 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -108,18 +109,6 @@ static struct resource mem_res[] = { #define kernel_code mem_res[0] #define kernel_data mem_res[1] -void __init early_print(const char *str, ...) -{ - char buf[256]; - va_list ap; - - va_start(ap, str); - vsnprintf(buf, sizeof(buf), str, ap); - va_end(ap); - - printk("%s", buf); -} - void __init smp_setup_processor_id(void) { u64 mpidr = read_cpuid_mpidr() & MPIDR_HWID_BITMASK; @@ -332,19 +321,62 @@ static void __init setup_processor(void) #endif } +static void *__init fixmap_remap_fdt(phys_addr_t dt_phys) +{ + const u64 dt_virt_base = __fix_to_virt(FIX_FDT); + phys_addr_t dt_phys_base = dt_phys & ~(FIX_FDT_SIZE - 1); + + /* + * Make sure that the FDT region can be mapped without the need to + * allocate additional translation table pages, so that it is safe + * to call create_pgd_mapping() this early. + * On 4k pages, we'll use section mappings for the region so we + * only have to be in the same PUD as the rest of the fixmap. + * On 64k pages, we need to be in the same PMD as well, as the region + * will be mapped using PTEs. + */ + BUILD_BUG_ON(dt_virt_base & (SZ_2M - 1)); + + if (IS_ENABLED(CONFIG_ARM64_64K_PAGES)) + BUILD_BUG_ON(__fix_to_virt(FIX_FDT_END) >> PMD_SHIFT != + __fix_to_virt(FIX_BTMAP_BEGIN) >> PMD_SHIFT); + else + BUILD_BUG_ON(__fix_to_virt(FIX_FDT_END) >> PUD_SHIFT != + __fix_to_virt(FIX_BTMAP_BEGIN) >> PUD_SHIFT); + + create_pgd_mapping(&init_mm, dt_phys_base, dt_virt_base, FIX_FDT_SIZE, + PAGE_KERNEL | PTE_RDONLY); + + return (void *)(dt_virt_base + dt_phys - dt_phys_base); +} + static void __init setup_machine_fdt(phys_addr_t dt_phys) { - if (!dt_phys || !early_init_dt_scan(phys_to_virt(dt_phys))) { - early_print("\n" - "Error: invalid device tree blob at physical address 0x%p (virtual address 0x%p)\n" - "The dtb must be 8-byte aligned and passed in the first 512MB of memory\n" + void *dt_virt = NULL; + + if (dt_phys && (dt_phys & 7) == 0) + dt_virt = fixmap_remap_fdt(dt_phys); + + /* + * Before passing the dt_virt pointer to early_init_dt_scan(), we have + * to ensure that the FDT size as reported in the FDT itself does not + * exceed the 2 MB window we just mapped for it. + */ + if (!dt_virt || + fdt_check_header(dt_virt) != 0 || + (dt_phys & (SZ_2M - 1)) + fdt_totalsize(dt_virt) > SZ_2M || + !early_init_dt_scan(dt_virt)) { + pr_crit("\n" + "Error: invalid device tree blob at physical address %pa (virtual address 0x%p)\n" + "The dtb must be 8-byte aligned and must not cross a 2 MB alignment boundary\n" "\nPlease check your bootloader.\n", - dt_phys, phys_to_virt(dt_phys)); + &dt_phys, dt_virt); while (true) cpu_relax(); } + memblock_reserve(dt_phys, fdt_totalsize(dt_virt)); dump_stack_set_arch_desc("%s (DT)", of_flat_dt_get_machine_name()); } @@ -382,6 +414,9 @@ void __init setup_arch(char **cmdline_p) { setup_processor(); + early_fixmap_init(); + early_ioremap_init(); + setup_machine_fdt(__fdt_pointer); init_mm.start_code = (unsigned long) _text; @@ -391,9 +426,6 @@ void __init setup_arch(char **cmdline_p) *cmdline_p = boot_command_line; - early_fixmap_init(); - early_ioremap_init(); - parse_early_param(); /* diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index fa2389b0f7f0..ae85da6307bb 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -170,7 +170,6 @@ void __init arm64_memblock_init(void) memblock_reserve(__virt_to_phys(initrd_start), initrd_end - initrd_start); #endif - early_init_fdt_reserve_self(); early_init_fdt_scan_reserved_mem(); /* 4GB maximum for 32-bit only capable devices */