arm64: EFI minimal FDT and Image placement fixes
Subsystems (5)
cover arm64: EFI minimal FDT and Image placement fixes
The EFI stub may place the Image or FDT in a memory location that is not allowed by the arm64/Linux boot protocol. Instead of fixing the stub, these patches relax the placement rules for Image and FDT so that the placement logic employed by the EFI stub is guaranteed to produce correct values.
These 4 patches have been split off from these series
http://thread.gmane.org/gmane.linux.kernel.efi/5736 (8 patches)
http://thread.gmane.org/gmane.linux.ports.arm.kernel/411718 (10 patches)
so that they may still be considered for inclusion in v4.2.
Changes since previous versions:
- added acks/R-b/T-b from Catalin and Mark Rutland
- improved Documentation text in patch #2
Ard Biesheuvel (4):
of/fdt: split off FDT self reservation from memreserve processing
arm64: use fixmap region for permanent FDT mapping
arm64: reduce ID map to a single page
arm64: drop sleep_idmap_phys and clean up cpu_resume()
Documentation/arm64/booting.txt | 10 ++++--- arch/arm/mm/init.c | 1 + arch/arm64/include/asm/boot.h | 14 +++++++++ arch/arm64/include/asm/fixmap.h | 15 ++++++++++ arch/arm64/include/asm/mmu.h | 1 + arch/arm64/kernel/head.S | 52 +++++--------------------------- arch/arm64/kernel/setup.c | 30 +++++++------------ arch/arm64/kernel/sleep.S | 9 +++--- arch/arm64/kernel/suspend.c | 3 -- arch/arm64/kernel/vmlinux.lds.S | 11 ++++++- arch/arm64/mm/Makefile | 2 ++ arch/arm64/mm/mmu.c | 66 +++++++++++++++++++++++++++++++++++++++++ arch/arm64/mm/proc.S | 3 +- arch/powerpc/kernel/prom.c | 1 + drivers/of/fdt.c | 19 ++++++++---- include/linux/of_fdt.h | 2 ++ 16 files changed, 156 insertions(+), 83 deletions(-) create mode 100644 arch/arm64/include/asm/boot.h
Signature · 1 line
1.9.1
PATCH 1/4 of/fdt: split off FDT self reservation from memreserve processing
This splits off the reservation of the memory occupied by the FDT binary itself from the processing of the memory reservations it contains. This is necessary because the physical address of the FDT, which is needed to perform the reservation, may not be known to the FDT driver core, i.e., it may be mapped outside the linear direct mapping, in which case __pa() returns a bogus value.
--- arch/arm/mm/init.c | 1 + arch/arm64/mm/init.c | 1 + arch/powerpc/kernel/prom.c | 1 + drivers/of/fdt.c | 19 ++++++++++++++----- include/linux/of_fdt.h | 2 ++ 5 files changed, 19 insertions(+), 5 deletions(-)
arch/arm/mm/init.c +1 -0
@@ -268,6 +268,7 @@ void __init arm_memblock_init(const struct machine_desc *mdesc)if (mdesc->reserve) mdesc->reserve (); +early_init_fdt_reserve_self ();early_init_fdt_scan_reserved_mem ();/* reserve memory for DMA contiguous allocations */
arch/arm64/mm/init.c +1 -0
@@ -170,6 +170,7 @@ void __init arm64_memblock_init(void)memblock_reserve (__virt_to_phys (initrd_start), initrd_end - initrd_start);#endif +early_init_fdt_reserve_self ();early_init_fdt_scan_reserved_mem ();/* 4GB maximum for 32-bit only capable devices */
arch/powerpc/kernel/prom.c +1 -0
@@ -573,6 +573,7 @@ static void __init early_reserve_mem_dt(void)int len;const __be32 *prop; +early_init_fdt_reserve_self ();early_init_fdt_scan_reserved_mem (); dt_root =of_get_flat_dt_root ();
drivers/of/fdt.c +14 -5
@@ -580,11 +580,6 @@ void __init early_init_fdt_scan_reserved_mem(void)if (!initial_boot_params)return ; -/* Reserve the dtb region */ -early_init_dt_reserve_memory_arch (__pa (initial_boot_params), -fdt_totalsize (initial_boot_params), -0 ); -/* Process header /memreserve/ fields */ for (n =0 ; ; n++) {fdt_get_mem_rsv (initial_boot_params, n, &base, &size);
@@ -598,6 +593,20 @@ void __init early_init_fdt_scan_reserved_mem(void) }/** +* early_init_fdt_reserve_self() - reserve the memory used by the FDT blob +*/ +void __init early_init_fdt_reserve_self (void ) +{ +if (!initial_boot_params) +return ; + +/* Reserve the dtb region */ +early_init_dt_reserve_memory_arch (__pa (initial_boot_params), +fdt_totalsize (initial_boot_params), +0 ); +} + +/** * of_scan_flat_dt - scan flattened tree blob and call callback on each. * @it: callback function * @data: context data pointer
include/linux/of_fdt.h +2 -0
@@ -64,6 +64,7 @@ extern int early_init_dt_scan_chosen(unsigned long node, const char *uname,extern int early_init_dt_scan_memory (unsigned long node,const char *uname,int depth,void *data);extern void early_init_fdt_scan_reserved_mem (void ); +extern void early_init_fdt_reserve_self (void );extern void early_init_dt_add_memory_arch (u64 base,u64 size);extern int early_init_dt_reserve_memory_arch (phys_addr_t base,phys_addr_t size,bool no_map);
@@ -91,6 +92,7 @@ extern u64 fdt_translate_address(const void *blob, int node_offset);extern void of_fdt_limit_memory (int limit);#else /* CONFIG_OF_FLATTREE */ static inline void early_init_fdt_scan_reserved_mem (void ) {} +static inline void early_init_fdt_reserve_self (void ) {}static inline const char *of_flat_dt_get_machine_name (void ) {return NULL ; }static inline void unflatten_device_tree (void ) {}static inline void unflatten_and_copy_device_tree (void ) {}
Signature · 1 line
1.9.1
Catalin Marinas
maintainerPATCH 1/4 of/fdt: split off FDT self reservation from memreserve processing
Quoted 14 lines · Ard Biesheuvel
This splits off the reservation of the memory occupied by the FDT binary itself from the processing of the memory reservations it contains. This is necessary because the physical address of the FDT, which is needed to perform the reservation, may not be known to the FDT driver core, i.e., it may be mapped outside the linear direct mapping, in which case
__pa()returns a bogus value.Cc Russell King <[email protected]>Cc Benjamin Herrenschmidt <[email protected]>Cc Paul Mackerras <[email protected]>Acked-by Rob Herring <[email protected]>Acked-by Mark Rutland <[email protected]>Acked-by Catalin Marinas <[email protected]>Signed-off-by Ard Biesheuvel <[email protected]>
Quoted 7 lines
--- arch/arm/mm/init.c | 1 + arch/arm64/mm/init.c | 1 + arch/powerpc/kernel/prom.c | 1 + drivers/of/fdt.c | 19 ++++++++++++++----- include/linux/of_fdt.h | 2 ++ 5 files changed, 19 insertions(+), 5 deletions(-)
I'm happy to take this patch (already acked by the DT maintainers) through the arm64 tree but it would be good to have an ack from the arch maintainers as well (i.e. Russell, Ben, Paul).
Thanks.
Signature · 1 line
Catalin
PATCH 1/4 of/fdt: split off FDT self reservation from memreserve processing
Quoted 23 lines · Catalin Marinas
Quoted 14 lines · Ard Biesheuvel
This splits off the reservation of the memory occupied by the FDT binary itself from the processing of the memory reservations it contains. This is necessary because the physical address of the FDT, which is needed to perform the reservation, may not be known to the FDT driver core, i.e., it may be mapped outside the linear direct mapping, in which case
__pa()returns a bogus value.Cc Russell King <[email protected]>Cc Benjamin Herrenschmidt <[email protected]>Cc Paul Mackerras <[email protected]>Acked-by Rob Herring <[email protected]>Acked-by Mark Rutland <[email protected]>Acked-by Catalin Marinas <[email protected]>Signed-off-by Ard Biesheuvel <[email protected]>Quoted 7 lines
--- arch/arm/mm/init.c | 1 + arch/arm64/mm/init.c | 1 + arch/powerpc/kernel/prom.c | 1 + drivers/of/fdt.c | 19 ++++++++++++++----- include/linux/of_fdt.h | 2 ++ 5 files changed, 19 insertions(+), 5 deletions(-)
Quoted 4 lines
I'm happy to take this patch (already acked by the DT maintainers) through the arm64 tree but it would be good to have an ack from the arch maintainers as well (i.e. Russell, Ben, Paul).
OK, fair enough,
@Ben, Paul
@Russell
Could you please indicate whether or not you have any objections to this patch?
Kind regards,
Ard.
Catalin Marinas
maintainerPATCH 1/4 of/fdt: split off FDT self reservation from memreserve processing
Quoted 28 lines · Ard Biesheuvel
Quoted 23 lines · Catalin Marinas
Quoted 14 lines · Ard Biesheuvel
This splits off the reservation of the memory occupied by the FDT binary itself from the processing of the memory reservations it contains. This is necessary because the physical address of the FDT, which is needed to perform the reservation, may not be known to the FDT driver core, i.e., it may be mapped outside the linear direct mapping, in which case
__pa()returns a bogus value.Cc Russell King <[email protected]>Cc Benjamin Herrenschmidt <[email protected]>Cc Paul Mackerras <[email protected]>Acked-by Rob Herring <[email protected]>Acked-by Mark Rutland <[email protected]>Acked-by Catalin Marinas <[email protected]>Signed-off-by Ard Biesheuvel <[email protected]>Quoted 7 lines
--- arch/arm/mm/init.c | 1 + arch/arm64/mm/init.c | 1 + arch/powerpc/kernel/prom.c | 1 + drivers/of/fdt.c | 19 ++++++++++++++----- include/linux/of_fdt.h | 2 ++ 5 files changed, 19 insertions(+), 5 deletions(-)Quoted 3 lines
I'm happy to take this patch (already acked by the DT maintainers) through the arm64 tree but it would be good to have an ack from the arch maintainers as well (i.e. Russell, Ben, Paul).
Quoted 6 lines
OK, fair enough,
@Ben, Paul
@RussellCould you please indicate whether or not you have any objections to this patch?
I'm going to push this patch into -next via the arm64 tree. If there are objections before the merging window, please let me know (looking at the previous commits adding early_init_fdt_scan_reserved_mem(), they were only acked by the DT maintainers).
I merged this series of 4 patches.
Thanks.
Signature · 1 line
Catalin
PATCH 1/4 of/fdt: split off FDT self reservation from memreserve processing
In reply to Ard BiesheuvelQuoted 8 lines · Ard Biesheuvel
This splits off the reservation of the memory occupied by the FDT binary itself from the processing of the memory reservations it contains. This is necessary because the physical address of the FDT, which is needed to perform the reservation, may not be known to the FDT driver core, i.e., it may be mapped outside the linear direct mapping, in which case
__pa()returns a bogus value.Cc Russell King <[email protected]>
Quoted 106 lines
Cc Paul Mackerras <[email protected]>Acked-by Rob Herring <[email protected]>Acked-by Mark Rutland <[email protected]>Acked-by Catalin Marinas <[email protected]>Signed-off-by Ard Biesheuvel <[email protected]>--- arch/arm/mm/init.c | 1 + arch/arm64/mm/init.c | 1 + arch/powerpc/kernel/prom.c | 1 + drivers/of/fdt.c | 19 ++++++++++++++----- include/linux/of_fdt.h | 2 ++ 5 files changed, 19 insertions(+), 5 deletions(-)arch/arm/mm/init.c +1
-0@@ -268,6 +268,7 @@ void __init arm_memblock_init(const struct machine_desc *mdesc)if (mdesc->reserve) mdesc->reserve (); +early_init_fdt_reserve_self ();early_init_fdt_scan_reserved_mem ();/* reserve memory for DMA contiguous allocations */ arch/arm64/mm/init.c +1
-0@@ -170,6 +170,7 @@ void __init arm64_memblock_init(void)memblock_reserve (__virt_to_phys (initrd_start), initrd_end - initrd_start);#endif +early_init_fdt_reserve_self ();early_init_fdt_scan_reserved_mem ();/* 4GB maximum for 32-bit only capable devices */ arch/powerpc/kernel/prom.c +1
-0@@ -573,6 +573,7 @@ static void __init early_reserve_mem_dt(void)int len;const __be32 *prop; +early_init_fdt_reserve_self ();early_init_fdt_scan_reserved_mem (); dt_root =of_get_flat_dt_root ();drivers/of/fdt.c +14
-5@@ -580,11 +580,6 @@ void __init early_init_fdt_scan_reserved_mem(void)if (!initial_boot_params)return ; -/* Reserve the dtb region */ -early_init_dt_reserve_memory_arch (__pa (initial_boot_params), -fdt_totalsize (initial_boot_params), -0 ); -/* Process header /memreserve/ fields */ for (n =0 ; ; n++) {fdt_get_mem_rsv (initial_boot_params, n, &base, &size);@@ -598,6 +593,20 @@ void __init early_init_fdt_scan_reserved_mem(void) }/** +* early_init_fdt_reserve_self() - reserve the memory used by the FDT blob +*/ +void __init early_init_fdt_reserve_self (void ) +{ +if (!initial_boot_params) +return ; + +/* Reserve the dtb region */ +early_init_dt_reserve_memory_arch (__pa (initial_boot_params), +fdt_totalsize (initial_boot_params), +0 ); +} + +/** * of_scan_flat_dt - scan flattened tree blob and call callback on each. * @it: callback function * @data: context data pointer include/linux/of_fdt.h +2
-0@@ -64,6 +64,7 @@ extern int early_init_dt_scan_chosen(unsigned long node, const char *uname,extern int early_init_dt_scan_memory (unsigned long node,const char *uname,int depth,void *data);extern void early_init_fdt_scan_reserved_mem (void ); +extern void early_init_fdt_reserve_self (void );extern void early_init_dt_add_memory_arch (u64 base,u64 size);extern int early_init_dt_reserve_memory_arch (phys_addr_t base,phys_addr_t size,bool no_map);@@ -91,6 +92,7 @@ extern u64 fdt_translate_address(const void *blob, int node_offset);extern void of_fdt_limit_memory (int limit);#else /* CONFIG_OF_FLATTREE */ static inline void early_init_fdt_scan_reserved_mem (void ) {} +static inline void early_init_fdt_reserve_self (void ) {}static inline const char *of_flat_dt_get_machine_name (void ) {return NULL ; }static inline void unflatten_device_tree (void ) {}static inline void unflatten_and_copy_device_tree (void ) {}
PATCH 2/4 arm64: use fixmap region for permanent FDT mapping
In reply to Ard BiesheuvelCurrently, the FDT blob needs to be in the same 512 MB region as the kernel, so that it can be mapped into the kernel virtual memory space very early on using a minimal set of statically allocated translation tables.
Now that we have early fixmap support, we can relax this restriction, by moving the permanent FDT mapping to the fixmap region instead. This way, the FDT blob may be anywhere in memory.
This also moves the vetting of the FDT to mmu.c, since the early init code in head.S does not handle mapping of the FDT anymore. At the same time, fix up some comments in head.S that have gone stale.
--- Documentation/arm64/booting.txt | 10 ++++--- arch/arm64/include/asm/boot.h | 14 +++++++++ arch/arm64/include/asm/fixmap.h | 15 ++++++++++ arch/arm64/include/asm/mmu.h | 1 + arch/arm64/kernel/head.S | 39 +----------------------- arch/arm64/kernel/setup.c | 30 +++++++------------ arch/arm64/mm/Makefile | 2 ++ arch/arm64/mm/init.c | 1 - arch/arm64/mm/mmu.c | 66 +++++++++++++++++++++++++++++++++++++++++ 9 files changed, 115 insertions(+), 63 deletions(-) create mode 100644 arch/arm64/include/asm/boot.h
Documentation/arm64/booting.txt +6 -4
@@ -45,11 +45,13 @@ sees fit.) Requirement: MANDATORY -The device tree blob (dtb) must be placed on an 8-byte boundary within -the first 512 megabytes from the start of the kernel image and must not -cross a 2-megabyte boundary. This is to allow the kernel to map the -blob using a single section mapping in the initial page tables. +The device tree blob (dtb) must be placed on an 8-byte boundary and must +not exceed 2 megabytes in size. Since the dtb will be mapped cacheable +using blocks of up to 2 megabytes in size, it must not be placed within +any 2M region which must be mapped with any specific attributes. +NOTE: versions prior to v4.2 also require that the DTB be placed within +the 512 MB region starting at text_offset bytes below the kernel Image. 3. Decompress the kernel image ------------------------------
arch/arm64/include/asm/boot.h new file +14 -0
@@ -0,0 +1,14 @@ + +#ifndef __ASM_BOOT_H +#define __ASM_BOOT_H + +#include <asm/sizes.h> + +/* +* arm64 requires the DTB to be 8 byte aligned and +* not exceed 2MB in size. +*/ +#define MIN_FDT_ALIGN 8 +#define MAX_FDT_SIZE SZ_2M + +#endif
arch/arm64/include/asm/fixmap.h +15 -0
@@ -17,6 +17,7 @@#ifndef __ASSEMBLY__#include <linux/kernel.h> +#include <asm/boot.h> #include <asm/page.h> /*
@@ -32,6 +33,20 @@*/ enum fixed_addresses {FIX_HOLE , + +/* +* Reserve a virtual window for the FDT that is 2 MB larger than the +* maximum supported size, and put it at the top of the fixmap region. +* The additional space ensures that any FDT that does not exceed +* MAX_FDT_SIZE can be mapped regardless of whether it crosses any +* 2 MB alignment boundaries. +* +* Keep this at the top so it remains 2 MB aligned. +*/ +#define FIX_FDT_SIZE (MAX_FDT_SIZE + SZ_2M) + FIX_FDT_END, +FIX_FDT =FIX_FDT_END +FIX_FDT_SIZE /PAGE_SIZE -1 , +FIX_EARLYCON_MEM_BASE ,FIX_TEXT_POKE0 , __end_of_permanent_fixed_addresses,
arch/arm64/include/asm/mmu.h +1 -0
@@ -34,5 +34,6 @@ extern void init_mem_pgprot(void);extern void create_pgd_mapping (struct mm_struct *mm,phys_addr_t phys,unsigned long virt,phys_addr_t size,pgprot_t prot); +extern void *fixmap_remap_fdt (phys_addr_t dt_phys);#endif
arch/arm64/kernel/head.S +1 -38
@@ -237,8 +237,6 @@ ENTRY(stext) bl el2_setup // Drop to EL1, w20=cpu_boot_mode adrp x24, __PHYS_OFFSET bl set_cpu_boot_mode_flag - - bl __vet_fdt bl __create_page_tables // x25=TTBR0, x26=TTBR1 /* * The following calls CPU setup code, see arch/arm64/mm/proc.S for
@@ -270,24 +268,6 @@ preserve_boot_args: ENDPROC(preserve_boot_args) /* - * Determine validity of the x21 FDT pointer. - * The dtb must be 8-byte aligned and live in the first 512M of memory. - */ -__vet_fdt: - tst x21, #0x7 - b.ne 1f - cmp x21, x24 - b.lt 1f - mov x0, #(1 << 29) - add x0, x0, x24 - cmp x21, x0 - b.ge 1f - ret -1: - mov x21, #0 - ret -ENDPROC(__vet_fdt) -/* * Macro to create a table entry to the next page. * * tbl: page table address
@@ -348,8 +328,7 @@ ENDPROC(__vet_fdt) * required to get the kernel running. The following sections are required: * - identity mapping to enable the MMU (low address, TTBR0) * - first few MB of the kernel linear mapping to jump to once the MMU has - * been enabled, including the FDT blob (TTBR1) - * - pgd entry for fixed mappings (TTBR1) + * been enabled */ __create_page_tables: adrp x25, idmap_pg_dir
@@ -439,22 +418,6 @@ __create_page_tables: create_block_map x0, x7, x3, x5, x6 /* - * Map the FDT blob (maximum 2MB; must be within 512MB of - * PHYS_OFFSET). - */ - mov x3, x21 // FDT phys address - and x3, x3, #~((1 << 21) - 1) // 2MB aligned - mov x6, #PAGE_OFFSET - sub x5, x3, x24 // subtract PHYS_OFFSET - tst x5, #~((1 << 29) - 1) // within 512MB? - csel x21, xzr, x21, ne // zero the FDT pointer - b.ne 1f - add x5, x5, x6 // __va(FDT blob) - add x6, x5, #1 << 21 // 2MB for the FDT blob - sub x6, x6, #1 // inclusive range - create_block_map x0, x7, x3, x5, x6 -1: - /* * Since the page tables have been populated with non-cacheable * accesses (MMU disabled), invalidate the idmap and swapper page * tables again to remove any speculatively loaded cache lines.
arch/arm64/kernel/setup.c +10 -20
@@ -105,18 +105,6 @@ static struct resource mem_res[] = {#define kernel_code mem_res[0]#define kernel_data mem_res[1] -void __init early_print (const char *str, ...) -{ -char buf[256 ]; -va_list ap; - -va_start (ap, str); -vsnprintf (buf,sizeof (buf), str, ap); -va_end (ap); - -printk ("%s" , buf); -} -/* * The recorded values of x0 .. x3 upon kernel entry. */
@@ -326,12 +314,14 @@ static void __init setup_processor(void)static void __init setup_machine_fdt (phys_addr_t dt_phys) { -if (!dt_phys || !early_init_dt_scan (phys_to_virt (dt_phys))) { -early_print ("\n" -"Error: invalid device tree blob at physical address 0x%p (virtual address 0x%p)\n" -"The dtb must be 8-byte aligned and passed in the first 512MB of memory\n" -"\nPlease check your bootloader.\n" , - dt_phys,phys_to_virt (dt_phys)); +void *dt_virt =fixmap_remap_fdt (dt_phys); + +if (!dt_virt || !early_init_dt_scan (dt_virt)) { +pr_crit ("\n" +"Error: invalid device tree blob@physical address %pa (virtual address 0x%p)\n" +"The dtb must be 8-byte aligned and must not exceed 2 MB in size\n" +"\nPlease check your bootloader." , + &dt_phys, dt_virt);while (true)cpu_relax ();
@@ -374,8 +364,6 @@ void __init setup_arch(char **cmdline_p) {setup_processor (); -setup_machine_fdt (__fdt_pointer); - init_mm.start_code = (unsigned long ) _text; init_mm.end_code = (unsigned long ) _etext; init_mm.end_data = (unsigned long ) _edata;
@@ -386,6 +374,8 @@ void __init setup_arch(char **cmdline_p)early_fixmap_init ();early_ioremap_init (); +setup_machine_fdt (__fdt_pointer); +parse_early_param ();/*
arch/arm64/mm/Makefile +2 -0
@@ -4,3 +4,5 @@ obj-y := dma-mapping.o extable.o fault.o init.o \ context.o proc.o pageattr.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o obj-$(CONFIG_ARM64_PTDUMP) += dump.o + +CFLAGS_mmu.o := -I$(srctree)/scripts/dtc/libfdt/
arch/arm64/mm/init.c +0 -1
@@ -170,7 +170,6 @@ void __init arm64_memblock_init(void)memblock_reserve (__virt_to_phys (initrd_start), initrd_end - initrd_start);#endif -early_init_fdt_reserve_self ();early_init_fdt_scan_reserved_mem ();/* 4GB maximum for 32-bit only capable devices */
arch/arm64/mm/mmu.c +66 -0
75 lines not on this page · raw message
Signature · 1 line
1.9.1
PATCH 3/4 arm64: reduce ID map to a single page
In reply to Ard BiesheuvelCommit ea8c2e112445 ("arm64: Extend the idmap to the whole kernel image") changed the early page table code so that the entire kernel Image is covered by the identity map. This allows functions that need to enable or disable the MMU to reside anywhere in the kernel Image.
However, this change has the unfortunate side effect that the Image cannot cross a physical 512 MB alignment boundary anymore, since the early page table code cannot deal with the Image crossing a /virtual/ 512 MB alignment boundary.
So instead, reduce the ID map to a single page, that is populated by the contents of the .idmap.text section. Only three functions reside there at the moment: __enable_mmu(), cpu_resume_mmu() and cpu_reset(). If new code is introduced that needs to manipulate the MMU state, it should be added to this section as well.
--- arch/arm64/kernel/head.S | 13 +++++++------ arch/arm64/kernel/sleep.S | 2 ++ arch/arm64/kernel/vmlinux.lds.S | 11 ++++++++++- arch/arm64/mm/proc.S | 3 ++- 4 files changed, 21 insertions(+), 8 deletions(-)
arch/arm64/kernel/head.S +7 -6
@@ -361,7 +361,7 @@ __create_page_tables: * Create the identity mapping. */ mov x0, x25 // idmap_pg_dir - adrp x3, KERNEL_START // __pa(KERNEL_START) + adrp x3, __idmap_text_start // __pa(__idmap_text_start) #ifndef CONFIG_ARM64_VA_BITS_48 #define EXTRA_SHIFT (PGDIR_SHIFT + PAGE_SHIFT - 3)
@@ -384,11 +384,11 @@ __create_page_tables: /* * Calculate the maximum allowed value for TCR_EL1.T0SZ so that the - * entire kernel image can be ID mapped. As T0SZ == (64 - #bits used), + * entire ID map region can be mapped. As T0SZ == (64 - #bits used), * this number conveniently equals the number of leading zeroes in - * the physical address of KERNEL_END. + * the physical address of __idmap_text_end. */ - adrp x5, KERNEL_END + adrp x5, __idmap_text_end clz x5, x5 cmp x5, TCR_T0SZ(VA_BITS) // default T0SZ small enough? b.ge 1f // .. then skip additional level
@@ -403,8 +403,8 @@ __create_page_tables: #endif create_pgd_entry x0, x3, x5, x6 - mov x5, x3 // __pa(KERNEL_START) - adr_l x6, KERNEL_END // __pa(KERNEL_END) + mov x5, x3 // __pa(__idmap_text_start) + adr_l x6, __idmap_text_end // __pa(__idmap_text_end) create_block_map x0, x7, x3, x5, x6 /*
@@ -632,6 +632,7 @@ ENDPROC(__secondary_switched) * * other registers depend on the function called upon completion */ + .section ".idmap.text", "ax" __enable_mmu: ldr x5, =vectors msr vbar_el1, x5
arch/arm64/kernel/sleep.S +2 -0
@@ -130,12 +130,14 @@ ENDPROC(__cpu_suspend_enter) /* * x0 must contain the sctlr value retrieved from restored context */ + .pushsection ".idmap.text", "ax" ENTRY(cpu_resume_mmu) ldr x3, =cpu_resume_after_mmu msr sctlr_el1, x0 // restore sctlr_el1 isb br x3 // global jump to virtual address ENDPROC(cpu_resume_mmu) + .popsection cpu_resume_after_mmu: mov x0, #0 // return zero on success ldp x19, x20, [sp, #16]
arch/arm64/kernel/vmlinux.lds.S +10 -1
@@ -38,6 +38,12 @@ jiffies = jiffies_64; *(.hyp.text) \ VMLINUX_SYMBOL(__hyp_text_end) = .; +#define IDMAP_TEXT \ + . = ALIGN(SZ_4K); \ + VMLINUX_SYMBOL(__idmap_text_start) = .; \ + *(.idmap.text) \ + VMLINUX_SYMBOL(__idmap_text_end) = .; + /* * The size of the PE/COFF section that covers the kernel image, which * runs from stext to _edata, must be a round multiple of the PE/COFF
@@ -95,6 +101,7 @@ SECTIONS SCHED_TEXT LOCK_TEXT HYPERVISOR_TEXT + IDMAP_TEXT *(.fixup) *(.gnu.warning) . = ALIGN(16);
@@ -167,11 +174,13 @@ SECTIONS } /* - * The HYP init code can't be more than a page long, + * The HYP init code and ID map text can't be longer than a page each, * and should not cross a page boundary. */ ASSERT(__hyp_idmap_text_end - (__hyp_idmap_text_start & ~(SZ_4K - 1)) <= SZ_4K, "HYP init code too big or misaligned") +ASSERT(__idmap_text_end - (__idmap_text_start & ~(SZ_4K - 1)) <= SZ_4K, + "ID map text too big or misaligned") /* * If padding is applied before .head.text, virt<->phys conversions will fail.
arch/arm64/mm/proc.S +2 -1
@@ -67,7 +67,7 @@ ENDPROC(cpu_cache_off) * * - loc - location to jump to for soft reset */ - .align 5 + .pushsection ".idmap.text", "ax" ENTRY(cpu_reset) mrs x1, sctlr_el1 bic x1, x1, #1
@@ -75,6 +75,7 @@ ENTRY(cpu_reset) isb ret x0 ENDPROC(cpu_reset) + .popsection ENTRY(cpu_soft_restart) /* Save address of cpu_reset() and reset address */
Signature · 1 line
1.9.1
PATCH 4/4 arm64: drop sleep_idmap_phys and clean up cpu_resume()
In reply to Ard BiesheuvelTwo cleanups of the asm function cpu_resume():
- The global variable sleep_idmap_phys always points to idmap_pg_dir, so we can just use that value directly in the CPU resume path.
- Unclutter the load of sleep_save_sp::save_ptr_stash_phys.
--- arch/arm64/kernel/sleep.S | 7 ++----- arch/arm64/kernel/suspend.c | 3 --- 2 files changed, 2 insertions(+), 8 deletions(-)
arch/arm64/kernel/sleep.S +2 -5
@@ -164,15 +164,12 @@ ENTRY(cpu_resume) #else mov x7, xzr #endif - adrp x0, sleep_save_sp - add x0, x0, #:lo12:sleep_save_sp - ldr x0, [x0, #SLEEP_SAVE_SP_PHYS] + ldr_l x0, sleep_save_sp + SLEEP_SAVE_SP_PHYS ldr x0, [x0, x7, lsl #3] /* load sp from context */ ldr x2, [x0, #CPU_CTX_SP] - adrp x1, sleep_idmap_phys /* load physical address of identity map page table in x1 */ - ldr x1, [x1, #:lo12:sleep_idmap_phys] + adrp x1, idmap_pg_dir mov sp, x2 /* * cpu_do_resume expects x0 to contain context physical address
arch/arm64/kernel/suspend.c +0 -3
@@ -118,7 +118,6 @@ int __cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) }struct sleep_save_sp sleep_save_sp; -phys_addr_t sleep_idmap_phys;static int __init cpu_suspend_init (void ) {
@@ -132,9 +131,7 @@ static int __init cpu_suspend_init(void) sleep_save_sp.save_ptr_stash = ctx_ptr; sleep_save_sp.save_ptr_stash_phys =virt_to_phys (ctx_ptr); - sleep_idmap_phys =virt_to_phys (idmap_pg_dir);__flush_dcache_area (&sleep_save_sp,sizeof (struct sleep_save_sp )); -__flush_dcache_area (&sleep_idmap_phys,sizeof (sleep_idmap_phys));return 0 ; }
Signature · 1 line
1.9.1