* [PATCH v2 1/3] of/fdt: factor out assignment of initrd_start/initrd_end
2016-02-11 16:47 [PATCH v2 0/3] arm64: avoid early __va translations Ard Biesheuvel
@ 2016-02-11 16:48 ` Ard Biesheuvel
2016-02-11 22:12 ` Arnd Bergmann
2016-02-11 16:48 ` [PATCH v2 2/3] arm64: defer __va translation of initrd_start and initrd_end Ard Biesheuvel
2016-02-11 16:48 ` [PATCH v2 3/3] arm64: prevent __va() translations before memstart_addr is assigned Ard Biesheuvel
2 siblings, 1 reply; 9+ messages in thread
From: Ard Biesheuvel @ 2016-02-11 16:48 UTC (permalink / raw)
To: linux-arm-kernel
Since architectures may not yet have their linear mapping up and running
when the initrd address is discovered from the DT, factor out the
assignment of initrd_start and initrd_end, so that an architecture can
override it and use the translation it needs.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
drivers/of/fdt.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 1f98156f8996..d1dd23127085 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -760,6 +760,14 @@ const void * __init of_flat_dt_match_machine(const void *default_match,
}
#ifdef CONFIG_BLK_DEV_INITRD
+void __weak __early_init_dt_declare_initrd(unsigned long start,
+ unsigned long end)
+{
+ initrd_start = (unsigned long)__va(start);
+ initrd_end = (unsigned long)__va(end);
+ initrd_below_start_ok = 1;
+}
+
/**
* early_init_dt_check_for_initrd - Decode initrd location from flat tree
* @node: reference to node containing initrd location ('chosen')
@@ -782,9 +790,7 @@ static void __init early_init_dt_check_for_initrd(unsigned long node)
return;
end = of_read_number(prop, len/4);
- initrd_start = (unsigned long)__va(start);
- initrd_end = (unsigned long)__va(end);
- initrd_below_start_ok = 1;
+ __early_init_dt_declare_initrd(start, end);
pr_debug("initrd_start=0x%llx initrd_end=0x%llx\n",
(unsigned long long)start, (unsigned long long)end);
--
2.5.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2 1/3] of/fdt: factor out assignment of initrd_start/initrd_end
2016-02-11 16:48 ` [PATCH v2 1/3] of/fdt: factor out assignment of initrd_start/initrd_end Ard Biesheuvel
@ 2016-02-11 22:12 ` Arnd Bergmann
2016-02-12 8:08 ` Ard Biesheuvel
0 siblings, 1 reply; 9+ messages in thread
From: Arnd Bergmann @ 2016-02-11 22:12 UTC (permalink / raw)
To: linux-arm-kernel
On Thursday 11 February 2016 17:48:00 Ard Biesheuvel wrote:
>
> #ifdef CONFIG_BLK_DEV_INITRD
> +void __weak __early_init_dt_declare_initrd(unsigned long start,
> + unsigned long end)
> +{
> + initrd_start = (unsigned long)__va(start);
> + initrd_end = (unsigned long)__va(end);
> + initrd_below_start_ok = 1;
> +}
> +
>
I find __weak functions particularly hard to follow, I think a Kconfig
symbols or a function you can override by defining a macro in asm/memory.h
would be nicer.
Arnd
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 1/3] of/fdt: factor out assignment of initrd_start/initrd_end
2016-02-11 22:12 ` Arnd Bergmann
@ 2016-02-12 8:08 ` Ard Biesheuvel
0 siblings, 0 replies; 9+ messages in thread
From: Ard Biesheuvel @ 2016-02-12 8:08 UTC (permalink / raw)
To: linux-arm-kernel
On 11 February 2016 at 23:12, Arnd Bergmann <arnd@arndb.de> wrote:
> On Thursday 11 February 2016 17:48:00 Ard Biesheuvel wrote:
>>
>> #ifdef CONFIG_BLK_DEV_INITRD
>> +void __weak __early_init_dt_declare_initrd(unsigned long start,
>> + unsigned long end)
>> +{
>> + initrd_start = (unsigned long)__va(start);
>> + initrd_end = (unsigned long)__va(end);
>> + initrd_below_start_ok = 1;
>> +}
>> +
>>
>
> I find __weak functions particularly hard to follow, I think a Kconfig
> symbols or a function you can override by defining a macro in asm/memory.h
> would be nicer.
>
OK, that makes sense.
I will give Catalin a chance to comment before respinning, though.
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 2/3] arm64: defer __va translation of initrd_start and initrd_end
2016-02-11 16:47 [PATCH v2 0/3] arm64: avoid early __va translations Ard Biesheuvel
2016-02-11 16:48 ` [PATCH v2 1/3] of/fdt: factor out assignment of initrd_start/initrd_end Ard Biesheuvel
@ 2016-02-11 16:48 ` Ard Biesheuvel
2016-02-11 16:48 ` [PATCH v2 3/3] arm64: prevent __va() translations before memstart_addr is assigned Ard Biesheuvel
2 siblings, 0 replies; 9+ messages in thread
From: Ard Biesheuvel @ 2016-02-11 16:48 UTC (permalink / raw)
To: linux-arm-kernel
Commit 66f51676a095 ("arm64: allow kernel Image to be loaded anywhere in
physical memory") defers the assignment of memstart_addr to the point where
all memory has been discovered and possibly clipped based on the size of
the linear region and the presence of a mem= command line parameter.
However, this results in __va() translations that have been performed up
to this point to have been carried out with a preliminary, incorrect value
of memstart_addr, and these values need to be fixed up. So wire up the
generic support to declare the initrd addresses, and implement it without
__va() translations, and perform the translation after memstart_addr has
been assigned.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm64/mm/init.c | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 3a9fc46cbf80..eff4751f8761 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -61,12 +61,18 @@ static int __init early_initrd(char *p)
if (*endp == ',') {
size = memparse(endp + 1, NULL);
- initrd_start = (unsigned long)__va(start);
- initrd_end = (unsigned long)__va(start + size);
+ initrd_start = start;
+ initrd_end = start + size;
}
return 0;
}
early_param("initrd", early_initrd);
+
+void __early_init_dt_declare_initrd(unsigned long start, unsigned long end)
+{
+ initrd_start = start;
+ initrd_end = end;
+}
#endif
/*
@@ -213,8 +219,13 @@ void __init arm64_memblock_init(void)
*/
memblock_reserve(__pa(_text), _end - _text);
#ifdef CONFIG_BLK_DEV_INITRD
- if (initrd_start)
- memblock_reserve(__virt_to_phys(initrd_start), initrd_end - initrd_start);
+ if (initrd_start) {
+ memblock_reserve(initrd_start, initrd_end - initrd_start);
+
+ /* the generic initrd code expects virtual addresses */
+ initrd_start = __phys_to_virt(initrd_start);
+ initrd_end = __phys_to_virt(initrd_end);
+ }
#endif
early_init_fdt_scan_reserved_mem();
--
2.5.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2 3/3] arm64: prevent __va() translations before memstart_addr is assigned
2016-02-11 16:47 [PATCH v2 0/3] arm64: avoid early __va translations Ard Biesheuvel
2016-02-11 16:48 ` [PATCH v2 1/3] of/fdt: factor out assignment of initrd_start/initrd_end Ard Biesheuvel
2016-02-11 16:48 ` [PATCH v2 2/3] arm64: defer __va translation of initrd_start and initrd_end Ard Biesheuvel
@ 2016-02-11 16:48 ` Ard Biesheuvel
2016-02-12 11:49 ` Will Deacon
2 siblings, 1 reply; 9+ messages in thread
From: Ard Biesheuvel @ 2016-02-11 16:48 UTC (permalink / raw)
To: linux-arm-kernel
Just a hack to check whether all early __va() calls are gone.
---
arch/arm64/include/asm/memory.h | 10 +++++++++-
arch/arm64/mm/init.c | 2 +-
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index 083361531a61..0d4d1b3b9695 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -90,7 +90,9 @@
__x >= PAGE_OFFSET ? (__x - PAGE_OFFSET + PHYS_OFFSET) : \
(__x - kimage_voffset); })
-#define __phys_to_virt(x) ((unsigned long)((x) - PHYS_OFFSET + PAGE_OFFSET))
+#define __phys_to_virt(x) ({ \
+ assert_memstart_addr_assigned(); \
+ (unsigned long)((x) - PHYS_OFFSET + PAGE_OFFSET); })
#define __phys_to_kimg(x) ((unsigned long)((x) + kimage_voffset))
/*
@@ -133,6 +135,12 @@ extern u64 kimage_vaddr;
/* the offset between the kernel virtual and physical mappings */
extern u64 kimage_voffset;
+static inline void assert_memstart_addr_assigned(void)
+{
+ if (unlikely(memstart_addr == (phys_addr_t)-1))
+ asm("brk #%0" :: "I"(0x800));
+}
+
/*
* Allow all memory at the discovery stage. We will clip it later.
*/
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index eff4751f8761..e88db8acd181 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -48,7 +48,7 @@
#include "mm.h"
-phys_addr_t memstart_addr __read_mostly = 0;
+phys_addr_t memstart_addr __read_mostly = (phys_addr_t)-1;
phys_addr_t arm64_dma_phys_limit __read_mostly;
#ifdef CONFIG_BLK_DEV_INITRD
--
2.5.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2 3/3] arm64: prevent __va() translations before memstart_addr is assigned
2016-02-11 16:48 ` [PATCH v2 3/3] arm64: prevent __va() translations before memstart_addr is assigned Ard Biesheuvel
@ 2016-02-12 11:49 ` Will Deacon
2016-02-12 11:51 ` Ard Biesheuvel
0 siblings, 1 reply; 9+ messages in thread
From: Will Deacon @ 2016-02-12 11:49 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, Feb 11, 2016 at 05:48:02PM +0100, Ard Biesheuvel wrote:
> Just a hack to check whether all early __va() calls are gone.
> ---
> arch/arm64/include/asm/memory.h | 10 +++++++++-
> arch/arm64/mm/init.c | 2 +-
> 2 files changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
> index 083361531a61..0d4d1b3b9695 100644
> --- a/arch/arm64/include/asm/memory.h
> +++ b/arch/arm64/include/asm/memory.h
> @@ -90,7 +90,9 @@
> __x >= PAGE_OFFSET ? (__x - PAGE_OFFSET + PHYS_OFFSET) : \
> (__x - kimage_voffset); })
>
> -#define __phys_to_virt(x) ((unsigned long)((x) - PHYS_OFFSET + PAGE_OFFSET))
> +#define __phys_to_virt(x) ({ \
> + assert_memstart_addr_assigned(); \
> + (unsigned long)((x) - PHYS_OFFSET + PAGE_OFFSET); })
> #define __phys_to_kimg(x) ((unsigned long)((x) + kimage_voffset))
>
> /*
> @@ -133,6 +135,12 @@ extern u64 kimage_vaddr;
> /* the offset between the kernel virtual and physical mappings */
> extern u64 kimage_voffset;
>
> +static inline void assert_memstart_addr_assigned(void)
> +{
> + if (unlikely(memstart_addr == (phys_addr_t)-1))
> + asm("brk #%0" :: "I"(0x800));
Ok, I'll bite! Why isn't this just a BUG_ON?
Will
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 3/3] arm64: prevent __va() translations before memstart_addr is assigned
2016-02-12 11:49 ` Will Deacon
@ 2016-02-12 11:51 ` Ard Biesheuvel
2016-02-12 12:09 ` Arnd Bergmann
0 siblings, 1 reply; 9+ messages in thread
From: Ard Biesheuvel @ 2016-02-12 11:51 UTC (permalink / raw)
To: linux-arm-kernel
On 12 February 2016 at 12:49, Will Deacon <will.deacon@arm.com> wrote:
> On Thu, Feb 11, 2016 at 05:48:02PM +0100, Ard Biesheuvel wrote:
>> Just a hack to check whether all early __va() calls are gone.
>> ---
>> arch/arm64/include/asm/memory.h | 10 +++++++++-
>> arch/arm64/mm/init.c | 2 +-
>> 2 files changed, 10 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
>> index 083361531a61..0d4d1b3b9695 100644
>> --- a/arch/arm64/include/asm/memory.h
>> +++ b/arch/arm64/include/asm/memory.h
>> @@ -90,7 +90,9 @@
>> __x >= PAGE_OFFSET ? (__x - PAGE_OFFSET + PHYS_OFFSET) : \
>> (__x - kimage_voffset); })
>>
>> -#define __phys_to_virt(x) ((unsigned long)((x) - PHYS_OFFSET + PAGE_OFFSET))
>> +#define __phys_to_virt(x) ({ \
>> + assert_memstart_addr_assigned(); \
>> + (unsigned long)((x) - PHYS_OFFSET + PAGE_OFFSET); })
>> #define __phys_to_kimg(x) ((unsigned long)((x) + kimage_voffset))
>>
>> /*
>> @@ -133,6 +135,12 @@ extern u64 kimage_vaddr;
>> /* the offset between the kernel virtual and physical mappings */
>> extern u64 kimage_voffset;
>>
>> +static inline void assert_memstart_addr_assigned(void)
>> +{
>> + if (unlikely(memstart_addr == (phys_addr_t)-1))
>> + asm("brk #%0" :: "I"(0x800));
>
> Ok, I'll bite! Why isn't this just a BUG_ON?
>
Because circular header dependencies prevent BUG_ON() from being used
here, and I was reluctant to move this function into a .c file.
Note that I am not necessarily suggesting that this patch be merged,
but I included it since it's the code I used to confirm that no other
early instance of __va() remain. I can try and clean it up if we want
to keep it.
--
Ard.
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 3/3] arm64: prevent __va() translations before memstart_addr is assigned
2016-02-12 11:51 ` Ard Biesheuvel
@ 2016-02-12 12:09 ` Arnd Bergmann
0 siblings, 0 replies; 9+ messages in thread
From: Arnd Bergmann @ 2016-02-12 12:09 UTC (permalink / raw)
To: linux-arm-kernel
On Friday 12 February 2016 12:51:40 Ard Biesheuvel wrote:
> >> @@ -133,6 +135,12 @@ extern u64 kimage_vaddr;
> >> /* the offset between the kernel virtual and physical mappings */
> >> extern u64 kimage_voffset;
> >>
> >> +static inline void assert_memstart_addr_assigned(void)
> >> +{
> >> + if (unlikely(memstart_addr == (phys_addr_t)-1))
> >> + asm("brk #%0" :: "I"(0x800));
> >
> > Ok, I'll bite! Why isn't this just a BUG_ON?
> >
>
> Because circular header dependencies prevent BUG_ON() from being used
> here, and I was reluctant to move this function into a .c file.
Maybe it works if you make assert_memstart_addr_assigned() a macro as well?
Arnd
^ permalink raw reply [flat|nested] 9+ messages in thread