@@ -62,13 +62,30 @@
(__HEAD_FLAG_PHYS_BASE << 3))
/*
+ * The relocatable kernel does not care about TEXT_OFFSET, as long as the
+ * image is loaded at the correct segment alignment. So let's tweak the
+ * effective TEXT_OFFSET header field so that __init_begin coincides with
+ * a swapper block boundary: this way, we will not need to create any RWX
+ * mappings for the kernel, even in the earliest stages. (Note that this is
+ * already guaranteed if SWAPPER_BLOCK_SIZE <= SEGMENT_ALIGN.)
+ * If it turns out that the boot loader ignores the TEXT_OFFSET field, we can
+ * happily boot as before, with the only difference being that we had to use
+ * an early RWX mapping for .init.text.
+ */
+#if defined(CONFIG_RELOCATABLE) && SWAPPER_BLOCK_SIZE > PAGE_SIZE
+__eff_text_offset = SWAPPER_BLOCK_SIZE - ((__init_begin - TEXT_OFFSET) & (SWAPPER_BLOCK_SIZE - 1));
+#else
+__eff_text_offset = TEXT_OFFSET;
+#endif
+
+/*
* These will output as part of the Image header, which should be little-endian
* regardless of the endianness of the kernel. While constant values could be
* endian swapped in head.S, all are done here for consistency.
*/
-#define HEAD_SYMBOLS \
- DEFINE_IMAGE_LE64(_kernel_size_le, _end - _text); \
- DEFINE_IMAGE_LE64(_kernel_offset_le, TEXT_OFFSET); \
+#define HEAD_SYMBOLS \
+ DEFINE_IMAGE_LE64(_kernel_size_le, _end - _text); \
+ DEFINE_IMAGE_LE64(_kernel_offset_le, __eff_text_offset); \
DEFINE_IMAGE_LE64(_kernel_flags_le, __HEAD_FLAGS);
#ifdef CONFIG_EFI
The relocatable kernel needs to do a relocation pass regardless of whether it was loaded at the virtual offset it was linked at. This means we could completely ignore TEXT_OFFSET if we wanted to (and this is actually what the KASLR aware image loader in the stub does already), as long as we adhere to the segment alignment, which is at least 64 KB. Whether the .init.text region requires a RWX mapping depends on whether it shares a swapper block with other sections that require a writable mapping. Since the TEXT_OFFSET field gives us control over the placement of the Image with respect to a swapper block boundary, we can override its value with a value that puts __inittext_begin right on a swapper block boundary as well. This removes the need to use RWX mappings entirely, given that relocatable kernels have at least a couple of MBs of .rela data, which sits between the executable and the writable bits of the __init segment. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> --- arch/arm64/kernel/image.h | 23 +++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-)