All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v2] arm64: booti: allow to place kernel image anywhere in physical memory
@ 2017-03-08  2:35 Masahiro Yamada
  2017-03-08 16:05 ` Mark Rutland
  0 siblings, 1 reply; 3+ messages in thread
From: Masahiro Yamada @ 2017-03-08  2:35 UTC (permalink / raw)
  To: u-boot

At first, the ARM64 Linux booting requirement recommended that the
kernel image be placed text_offset bytes from 2MB aligned base near
the start of usable system RAM because memory below that base address
was unusable at that time.

This requirement was relaxed by Linux commit a7f8de168ace ("arm64:
allow kernel Image to be loaded anywhere in physical memory").
Since then, the bit 3 of the flags field indicates the tolerance
of the kernel physical placement.  If this bit is set, the 2MB
aligned base may be anywhere in physical memory.  For details, see
Documentation/arm64/booting.txt of Linux.

The booti command should be also relaxed.  If the bit 3 is set,
images->ep is respected, and the image is placed at the nearest
bootable location.  Otherwise, it is relocated to the start of the
system RAM to keep the original behavior.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---

Changes in v2:
  - Use le64_to_cpu() for correct endian-ness
  - Check the bit 3

 cmd/booti.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/cmd/booti.c b/cmd/booti.c
index bff87a8..8f3507d 100644
--- a/cmd/booti.c
+++ b/cmd/booti.c
@@ -11,6 +11,8 @@
 #include <image.h>
 #include <lmb.h>
 #include <mapmem.h>
+#include <linux/kernel.h>
+#include <linux/sizes.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -20,7 +22,7 @@ struct Image_header {
 	uint32_t	code1;		/* Executable code */
 	uint64_t	text_offset;	/* Image load offset, LE */
 	uint64_t	image_size;	/* Effective Image size, LE */
-	uint64_t	res1;		/* reserved */
+	uint64_t	flags;		/* Kernel flags, LE */
 	uint64_t	res2;		/* reserved */
 	uint64_t	res3;		/* reserved */
 	uint64_t	res4;		/* reserved */
@@ -51,10 +53,18 @@ static int booti_setup(bootm_headers_t *images)
 	}
 
 	/*
-	 * If we are not at the correct run-time location, set the new
-	 * correct location and then move the image there.
+	 * If bit 3 of the flags field is set, the 2MB aligned base of the
+	 * kernel image can be anywhere in physical memory, so respect
+	 * images->ep.  Otherwise, relocate the image to the base of RAM
+	 * since memory below it is not accessible via the linear mapping.
 	 */
-	dst = gd->bd->bi_dram[0].start + le64_to_cpu(ih->text_offset);
+	if (le64_to_cpu(ih->flags) & BIT(3))
+		dst = images->ep - le64_to_cpu(ih->text_offset);
+	else
+		dst = gd->bd->bi_dram[0].start;
+
+	dst = ALIGN(dst, SZ_2M);
+	dst += le64_to_cpu(ih->text_offset);
 
 	unmap_sysmem(ih);
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [U-Boot] [PATCH v2] arm64: booti: allow to place kernel image anywhere in physical memory
  2017-03-08  2:35 [U-Boot] [PATCH v2] arm64: booti: allow to place kernel image anywhere in physical memory Masahiro Yamada
@ 2017-03-08 16:05 ` Mark Rutland
  2017-03-09  2:10   ` Masahiro Yamada
  0 siblings, 1 reply; 3+ messages in thread
From: Mark Rutland @ 2017-03-08 16:05 UTC (permalink / raw)
  To: u-boot

On Wed, Mar 08, 2017 at 11:35:12AM +0900, Masahiro Yamada wrote:
> At first, the ARM64 Linux booting requirement recommended that the
> kernel image be placed text_offset bytes from 2MB aligned base near
> the start of usable system RAM because memory below that base address
> was unusable at that time.
> 
> This requirement was relaxed by Linux commit a7f8de168ace ("arm64:
> allow kernel Image to be loaded anywhere in physical memory").
> Since then, the bit 3 of the flags field indicates the tolerance
> of the kernel physical placement.  If this bit is set, the 2MB
> aligned base may be anywhere in physical memory.  For details, see
> Documentation/arm64/booting.txt of Linux.
> 
> The booti command should be also relaxed.  If the bit 3 is set,
> images->ep is respected, and the image is placed at the nearest
> bootable location.  Otherwise, it is relocated to the start of the
> system RAM to keep the original behavior.
> 
> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
> ---
> 
> Changes in v2:
>   - Use le64_to_cpu() for correct endian-ness
>   - Check the bit 3
> 
>  cmd/booti.c | 18 ++++++++++++++----
>  1 file changed, 14 insertions(+), 4 deletions(-)
> 
> diff --git a/cmd/booti.c b/cmd/booti.c
> index bff87a8..8f3507d 100644
> --- a/cmd/booti.c
> +++ b/cmd/booti.c
> @@ -11,6 +11,8 @@
>  #include <image.h>
>  #include <lmb.h>
>  #include <mapmem.h>
> +#include <linux/kernel.h>
> +#include <linux/sizes.h>
>  
>  DECLARE_GLOBAL_DATA_PTR;
>  
> @@ -20,7 +22,7 @@ struct Image_header {
>  	uint32_t	code1;		/* Executable code */
>  	uint64_t	text_offset;	/* Image load offset, LE */
>  	uint64_t	image_size;	/* Effective Image size, LE */
> -	uint64_t	res1;		/* reserved */
> +	uint64_t	flags;		/* Kernel flags, LE */
>  	uint64_t	res2;		/* reserved */
>  	uint64_t	res3;		/* reserved */
>  	uint64_t	res4;		/* reserved */
> @@ -51,10 +53,18 @@ static int booti_setup(bootm_headers_t *images)
>  	}
>  
>  	/*
> -	 * If we are not at the correct run-time location, set the new
> -	 * correct location and then move the image there.
> +	 * If bit 3 of the flags field is set, the 2MB aligned base of the
> +	 * kernel image can be anywhere in physical memory, so respect
> +	 * images->ep.  Otherwise, relocate the image to the base of RAM
> +	 * since memory below it is not accessible via the linear mapping.
>  	 */
> -	dst = gd->bd->bi_dram[0].start + le64_to_cpu(ih->text_offset);
> +	if (le64_to_cpu(ih->flags) & BIT(3))
> +		dst = images->ep - le64_to_cpu(ih->text_offset);

I take it this is a pre-correction for the ALIGN() below?

> +	else
> +		dst = gd->bd->bi_dram[0].start;
> +
> +	dst = ALIGN(dst, SZ_2M);
> +	dst += le64_to_cpu(ih->text_offset);

There's one last wrinkle to take care of here, if we want to boot a
kernel older than commit a2c1d73b94ed49f5 (i.e. v3.16). Until then, the
text_offset was of unknown endianness.

As mentiond in the Linux documentation, you can detect this based on the
image_size field, e.g.

	uint64_t text_offset;

	/*
	 * Prior to Linux commit a2c1d73b94ed49f5, the text_offset field
	 * is of unknown endianness. In these cases, the image_size
	 * field is zero, and we can assume a fixed value of 0x80000.
	 */
	if (le64_to_cpu(ih->image_size) == 0)
		text_offset = 0x80000;
	else
		text_offset = (le64_to_cpu(ih->text_offset));
		
... then you can reuse that text_offset value for both cases above.

Otherwise, this looks fine to me.

Thanks,
Mark.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [U-Boot] [PATCH v2] arm64: booti: allow to place kernel image anywhere in physical memory
  2017-03-08 16:05 ` Mark Rutland
@ 2017-03-09  2:10   ` Masahiro Yamada
  0 siblings, 0 replies; 3+ messages in thread
From: Masahiro Yamada @ 2017-03-09  2:10 UTC (permalink / raw)
  To: u-boot

Hi Mark,


2017-03-09 1:05 GMT+09:00 Mark Rutland <mark.rutland@arm.com>:
>>
>>       /*
>> -      * If we are not at the correct run-time location, set the new
>> -      * correct location and then move the image there.
>> +      * If bit 3 of the flags field is set, the 2MB aligned base of the
>> +      * kernel image can be anywhere in physical memory, so respect
>> +      * images->ep.  Otherwise, relocate the image to the base of RAM
>> +      * since memory below it is not accessible via the linear mapping.
>>        */
>> -     dst = gd->bd->bi_dram[0].start + le64_to_cpu(ih->text_offset);
>> +     if (le64_to_cpu(ih->flags) & BIT(3))
>> +             dst = images->ep - le64_to_cpu(ih->text_offset);
>
> I take it this is a pre-correction for the ALIGN() below?

Without this, the image would be always relocated
even if images->ep is already bootable location.

Unnecessary relocation should be avoided.





> There's one last wrinkle to take care of here, if we want to boot a
> kernel older than commit a2c1d73b94ed49f5 (i.e. v3.16). Until then, the
> text_offset was of unknown endianness.
>
> As mentiond in the Linux documentation, you can detect this based on the
> image_size field, e.g.
>
>         uint64_t text_offset;
>
>         /*
>          * Prior to Linux commit a2c1d73b94ed49f5, the text_offset field
>          * is of unknown endianness. In these cases, the image_size
>          * field is zero, and we can assume a fixed value of 0x80000.
>          */
>         if (le64_to_cpu(ih->image_size) == 0)
>                 text_offset = 0x80000;
>         else
>                 text_offset = (le64_to_cpu(ih->text_offset));
>
> ... then you can reuse that text_offset value for both cases above.
>

Thanks.  I will fix this too.



-- 
Best Regards
Masahiro Yamada

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2017-03-09  2:10 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-08  2:35 [U-Boot] [PATCH v2] arm64: booti: allow to place kernel image anywhere in physical memory Masahiro Yamada
2017-03-08 16:05 ` Mark Rutland
2017-03-09  2:10   ` Masahiro Yamada

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.