From mboxrd@z Thu Jan 1 00:00:00 1970 From: Mark Rutland Date: Wed, 8 Mar 2017 16:05:12 +0000 Subject: [U-Boot] [PATCH v2] arm64: booti: allow to place kernel image anywhere in physical memory In-Reply-To: <1488940512-18181-1-git-send-email-yamada.masahiro@socionext.com> References: <1488940512-18181-1-git-send-email-yamada.masahiro@socionext.com> Message-ID: <20170308160512.GD13133@leverpostej> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de 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 > --- > > 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 > #include > #include > +#include > +#include > > 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.