[PATCH] of: Expose __early_init_dt_declare_initrd as a weak function

Andrew Jones ajones at ventanamicro.com
Mon Jan 30 00:40:14 PST 2023


__early_init_dt_declare_initrd is provided by OF as a convenience
for early setup of initrd_start and initrd_end. This is nice for the
large majority of architectures, but arm64 cannot use it, as its early
linear map is too limited to be used to translate the addresses.
Rather than guarding the translations with !CONFIG_ARM64 in OF code,
expose __early_init_dt_declare_initrd as a weak function which
architectures may override. Architectures may prepare a mapping in
their version of the function or, if they know it's safe to defer the
setup until later, they can just provide a stub.

Apply this to arm64 immediately in order to remove the !CONFIG_ARM64
check. riscv64 will also use this after modifying its linear map to
use larger pages.

Note, while this somewhat reverts what commit cdbc848b0341 ("of/fdt:
Remove custom __early_init_dt_declare_initrd() implementation") is
doing, the weak function approach shouldn't have the rebuild noise
that changing CONFIG_BLK_DEV_INITRD was causing before. It is,
however, necessary to duplicate the !CONFIG_BLK_DEV_INITRD check
which early_init_dt_check_for_initrd() has into the newly exposed
function, as the compiler will now treat it independently.

Signed-off-by: Andrew Jones <ajones at ventanamicro.com>
---
 arch/arm64/kernel/setup.c | 11 +++++++++++
 drivers/of/fdt.c          | 26 +++++++++++++-------------
 include/linux/of_fdt.h    |  2 ++
 3 files changed, 26 insertions(+), 13 deletions(-)

diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 12cfe9d0d3fa..ffdbe6900d8d 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -180,6 +180,17 @@ asmlinkage void __init early_fdt_map(u64 dt_phys)
 	early_fdt_ptr = fixmap_remap_fdt(dt_phys, &fdt_size, PAGE_KERNEL);
 }
 
+void __init early_init_dt_declare_initrd_arch(unsigned long start,
+					      unsigned long end)
+{
+	/*
+	 * Using OF's version of this function would cause ARM64 to BUG when
+	 * CONFIG_DEBUG_VM is enabled, since __va() would be called too early.
+	 * initrd_start and initrd_end will be initialized later in
+	 * arm64_memblock_init()
+	 */
+}
+
 static void __init setup_machine_fdt(phys_addr_t dt_phys)
 {
 	int size;
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index f08b25195ae7..6c555739cf20 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -888,19 +888,19 @@ const void * __init of_flat_dt_match_machine(const void *default_match,
 	return best_data;
 }
 
-static void __early_init_dt_declare_initrd(unsigned long start,
-					   unsigned long end)
+/*
+ * This may be overridden by architectures which do not have a linear map
+ * sufficiently setup this early to simply use __va().
+ */
+void __init __weak early_init_dt_declare_initrd_arch(unsigned long start,
+						     unsigned long end)
 {
-	/* ARM64 would cause a BUG to occur here when CONFIG_DEBUG_VM is
-	 * enabled since __va() is called too early. ARM64 does make use
-	 * of phys_initrd_start/phys_initrd_size so we can skip this
-	 * conversion.
-	 */
-	if (!IS_ENABLED(CONFIG_ARM64)) {
-		initrd_start = (unsigned long)__va(start);
-		initrd_end = (unsigned long)__va(end);
-		initrd_below_start_ok = 1;
-	}
+	if (!IS_ENABLED(CONFIG_BLK_DEV_INITRD))
+		return;
+
+	initrd_start = (unsigned long)__va(start);
+	initrd_end = (unsigned long)__va(end);
+	initrd_below_start_ok = 1;
 }
 
 /**
@@ -930,7 +930,7 @@ static void __init early_init_dt_check_for_initrd(unsigned long node)
 	if (start > end)
 		return;
 
-	__early_init_dt_declare_initrd(start, end);
+	early_init_dt_declare_initrd_arch(start, end);
 	phys_initrd_start = start;
 	phys_initrd_size = end - start;
 
diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
index d69ad5bb1eb1..040ab7e402e0 100644
--- a/include/linux/of_fdt.h
+++ b/include/linux/of_fdt.h
@@ -65,6 +65,8 @@ extern int early_init_dt_scan_chosen_stdout(void);
 extern void early_init_fdt_scan_reserved_mem(void);
 extern void early_init_fdt_reserve_self(void);
 extern void early_init_dt_add_memory_arch(u64 base, u64 size);
+extern void early_init_dt_declare_initrd_arch(unsigned long start,
+					      unsigned long end);
 extern u64 dt_mem_next_cell(int s, const __be32 **cellp);
 
 /* Early flat tree scan hooks */
-- 
2.39.1




More information about the linux-arm-kernel mailing list