arm64: cover the .head.text section in the .text segment mapping
authorArd Biesheuvel <ard.biesheuvel@linaro.org>
Wed, 30 Mar 2016 15:43:08 +0000 (17:43 +0200)
committerArd Biesheuvel <ard.biesheuvel@linaro.org>
Fri, 29 Jul 2016 16:59:49 +0000 (18:59 +0200)
Keeping .head.text out of the .text mapping buys us very little: its actual
payload is only 4 KB, most of which is padding, but the page alignment may
add up to 2 MB (in case of CONFIG_DEBUG_ALIGN_RODATA=y) of additional
padding to the uncompressed kernel Image.

Also, on 4 KB granule kernels, the 4 KB misalignment of .text forces us to
map the adjacent 56 KB of code without the PTE_CONT attribute, and since
this region contains things like the vector table and the GIC interrupt
handling entry point, this region is likely to benefit from the reduced TLB
pressure that results from PTE_CONT mappings.

So remove the alignment between the .head.text and .text sections, and use
the [_text, _etext) rather than the [_stext, _etext) interval for mapping
the .text segment.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>
(cherry picked from commit 7eb90f2ff7e3ee814ff12f3cd909b965cdd4a869)
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
arch/arm64/kernel/vmlinux.lds.S
arch/arm64/mm/mmu.c

index 4c56e7a0621bcea078fb616487d60f9290f85214..7a141c098bbb625ba375494ca1b3bffb2bb2b271 100644 (file)
@@ -96,7 +96,6 @@ SECTIONS
                _text = .;
                HEAD_TEXT
        }
-       ALIGN_DEBUG_RO_MIN(PAGE_SIZE)
        .text : {                       /* Real text segment            */
                _stext = .;             /* Text and read-only data      */
                        __exception_text_start = .;
index cecd9d0057c8b710414539b81e0e7baa789ea4d5..cd4177a1781d8e86c99269091995a7f3090f37bc 100644 (file)
@@ -385,7 +385,7 @@ static void create_mapping_late(phys_addr_t phys, unsigned long virt,
 
 static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end)
 {
-       unsigned long kernel_start = __pa(_stext);
+       unsigned long kernel_start = __pa(_text);
        unsigned long kernel_end = __pa(_etext);
 
        /*
@@ -417,7 +417,7 @@ static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end
                                     early_pgtable_alloc);
 
        /*
-        * Map the linear alias of the [_stext, _etext) interval as
+        * Map the linear alias of the [_text, _etext) interval as
         * read-only/non-executable. This makes the contents of the
         * region accessible to subsystems such as hibernate, but
         * protects it from inadvertent modification or execution.
@@ -447,8 +447,8 @@ void mark_rodata_ro(void)
 {
        unsigned long section_size;
 
-       section_size = (unsigned long)__start_rodata - (unsigned long)_stext;
-       create_mapping_late(__pa(_stext), (unsigned long)_stext,
+       section_size = (unsigned long)__start_rodata - (unsigned long)_text;
+       create_mapping_late(__pa(_text), (unsigned long)_text,
                            section_size, PAGE_KERNEL_ROX);
        /*
         * mark .rodata as read only. Use _etext rather than __end_rodata to
@@ -497,7 +497,7 @@ static void __init map_kernel(pgd_t *pgd)
 {
        static struct vm_struct vmlinux_text, vmlinux_rodata, vmlinux_init, vmlinux_data;
 
-       map_kernel_segment(pgd, _stext, __start_rodata, PAGE_KERNEL_EXEC, &vmlinux_text);
+       map_kernel_segment(pgd, _text, __start_rodata, PAGE_KERNEL_EXEC, &vmlinux_text);
        map_kernel_segment(pgd, __start_rodata, _etext, PAGE_KERNEL, &vmlinux_rodata);
        map_kernel_segment(pgd, __init_begin, __init_end, PAGE_KERNEL_EXEC,
                           &vmlinux_init);