@@ -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;
@@ -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;
@@ -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 */
__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@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(-)