arm64: consistently use reserved_pg_dir
authorMark Rutland <mark.rutland@arm.com>
Tue, 3 Nov 2020 10:22:29 +0000 (10:22 +0000)
committerCatalin Marinas <catalin.marinas@arm.com>
Tue, 10 Nov 2020 17:30:40 +0000 (17:30 +0000)
Depending on configuration options and specific code paths, we either
use the empty_zero_page or the configuration-dependent reserved_ttbr0
as a reserved value for TTBR{0,1}_EL1.

To simplify this code, let's always allocate and use the same
reserved_pg_dir, replacing reserved_ttbr0. Note that this is allocated
(and hence pre-zeroed), and is also marked as read-only in the kernel
Image mapping.

Keeping this separate from the empty_zero_page potentially helps with
robustness as the empty_zero_page is used in a number of cases where a
failure to map it read-only could allow it to become corrupted.

The (presently unused) swapper_pg_end symbol is also removed, and
comments are added wherever we rely on the offsets between the
pre-allocated pg_dirs to keep these cases easily identifiable.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Will Deacon <will@kernel.org>
Link: https://lore.kernel.org/r/20201103102229.8542-1-mark.rutland@arm.com
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
arch/arm64/include/asm/asm-uaccess.h
arch/arm64/include/asm/kernel-pgtable.h
arch/arm64/include/asm/mmu_context.h
arch/arm64/include/asm/pgtable.h
arch/arm64/include/asm/uaccess.h
arch/arm64/kernel/entry.S
arch/arm64/kernel/setup.c
arch/arm64/kernel/vmlinux.lds.S
arch/arm64/mm/proc.S

index f68a0e64482a1eb2acceb89a000b517175aba6d4..5ef624fef44a2f453803c2480ac56c0c1d8beaeb 100644 (file)
        .macro  __uaccess_ttbr0_disable, tmp1
        mrs     \tmp1, ttbr1_el1                        // swapper_pg_dir
        bic     \tmp1, \tmp1, #TTBR_ASID_MASK
-       sub     \tmp1, \tmp1, #RESERVED_TTBR0_SIZE      // reserved_ttbr0 just before swapper_pg_dir
+       sub     \tmp1, \tmp1, #PAGE_SIZE                // reserved_pg_dir just before swapper_pg_dir
        msr     ttbr0_el1, \tmp1                        // set reserved TTBR0_EL1
        isb
-       add     \tmp1, \tmp1, #RESERVED_TTBR0_SIZE
+       add     \tmp1, \tmp1, #PAGE_SIZE
        msr     ttbr1_el1, \tmp1                // set reserved ASID
        isb
        .endm
index 19ca76ea60d98ae6338b677988dc4ccc5cda6b15..587c504a4c8b2d5162a23c566283e6b019d60dff 100644 (file)
 #define INIT_DIR_SIZE (PAGE_SIZE * EARLY_PAGES(KIMAGE_VADDR, _end))
 #define IDMAP_DIR_SIZE         (IDMAP_PGTABLE_LEVELS * PAGE_SIZE)
 
-#ifdef CONFIG_ARM64_SW_TTBR0_PAN
-#define RESERVED_TTBR0_SIZE    (PAGE_SIZE)
-#else
-#define RESERVED_TTBR0_SIZE    (0)
-#endif
-
 /* Initial memory map size */
 #if ARM64_SWAPPER_USES_SECTION_MAPS
 #define SWAPPER_BLOCK_SHIFT    SECTION_SHIFT
index 0672236e1aeab1e1cc2ebce29672fb471bba842a..5c72c20bd300e1cc964f16a2e124a7f1e9b60d05 100644 (file)
@@ -36,11 +36,11 @@ static inline void contextidr_thread_switch(struct task_struct *next)
 }
 
 /*
- * Set TTBR0 to empty_zero_page. No translations will be possible via TTBR0.
+ * Set TTBR0 to reserved_pg_dir. No translations will be possible via TTBR0.
  */
 static inline void cpu_set_reserved_ttbr0(void)
 {
-       unsigned long ttbr = phys_to_ttbr(__pa_symbol(empty_zero_page));
+       unsigned long ttbr = phys_to_ttbr(__pa_symbol(reserved_pg_dir));
 
        write_sysreg(ttbr, ttbr0_el1);
        isb();
@@ -195,7 +195,7 @@ static inline void update_saved_ttbr0(struct task_struct *tsk,
                return;
 
        if (mm == &init_mm)
-               ttbr = __pa_symbol(empty_zero_page);
+               ttbr = __pa_symbol(reserved_pg_dir);
        else
                ttbr = virt_to_phys(mm->pgd) | ASID(mm) << 48;
 
index 4ff12a7adcfd112beed24807ef231008447678e3..74694e129f9a7b918ad5a26379b2d875b99f1c62 100644 (file)
@@ -519,6 +519,7 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 extern pgd_t idmap_pg_dir[PTRS_PER_PGD];
 extern pgd_t idmap_pg_end[];
 extern pgd_t tramp_pg_dir[PTRS_PER_PGD];
+extern pgd_t reserved_pg_dir[PTRS_PER_PGD];
 
 extern void set_swapper_pgd(pgd_t *pgdp, pgd_t pgd);
 
index 991dd5f031e4613cdfceab311d37aec32ee4d60a..385a189f7d39eada61a81079bc1697603381b858 100644 (file)
@@ -113,8 +113,8 @@ static inline void __uaccess_ttbr0_disable(void)
        local_irq_save(flags);
        ttbr = read_sysreg(ttbr1_el1);
        ttbr &= ~TTBR_ASID_MASK;
-       /* reserved_ttbr0 placed before swapper_pg_dir */
-       write_sysreg(ttbr - RESERVED_TTBR0_SIZE, ttbr0_el1);
+       /* reserved_pg_dir placed before swapper_pg_dir */
+       write_sysreg(ttbr - PAGE_SIZE, ttbr0_el1);
        isb();
        /* Set reserved ASID */
        write_sysreg(ttbr, ttbr1_el1);
index b295fb912b12b2993e1723a588874a2a6a092b19..6f31c2c0678855ee824a8b66f828c5dcd3826ec8 100644 (file)
@@ -807,9 +807,10 @@ SYM_CODE_END(ret_to_user)
  */
        .pushsection ".entry.tramp.text", "ax"
 
+       // Move from tramp_pg_dir to swapper_pg_dir
        .macro tramp_map_kernel, tmp
        mrs     \tmp, ttbr1_el1
-       add     \tmp, \tmp, #(PAGE_SIZE + RESERVED_TTBR0_SIZE)
+       add     \tmp, \tmp, #(2 * PAGE_SIZE)
        bic     \tmp, \tmp, #USER_ASID_FLAG
        msr     ttbr1_el1, \tmp
 #ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003
@@ -826,9 +827,10 @@ alternative_else_nop_endif
 #endif /* CONFIG_QCOM_FALKOR_ERRATUM_1003 */
        .endm
 
+       // Move from swapper_pg_dir to tramp_pg_dir
        .macro tramp_unmap_kernel, tmp
        mrs     \tmp, ttbr1_el1
-       sub     \tmp, \tmp, #(PAGE_SIZE + RESERVED_TTBR0_SIZE)
+       sub     \tmp, \tmp, #(2 * PAGE_SIZE)
        orr     \tmp, \tmp, #USER_ASID_FLAG
        msr     ttbr1_el1, \tmp
        /*
index 133257ffd8591d692f5f64abf8f41fb2d0e0910c..c28a9ec76b1175b869fa7ba1a639dcfd380a8288 100644 (file)
@@ -366,7 +366,7 @@ void __init __no_sanitize_address setup_arch(char **cmdline_p)
         * faults in case uaccess_enable() is inadvertently called by the init
         * thread.
         */
-       init_task.thread_info.ttbr0 = __pa_symbol(empty_zero_page);
+       init_task.thread_info.ttbr0 = __pa_symbol(reserved_pg_dir);
 #endif
 
        if (boot_args[1] || boot_args[2] || boot_args[3]) {
index 1bda604f4c704bd22f810c02fcacd60d720c43e4..30c102978942748b995d51729ca3a4e0b82dddba 100644 (file)
@@ -164,13 +164,11 @@ SECTIONS
        . += PAGE_SIZE;
 #endif
 
-#ifdef CONFIG_ARM64_SW_TTBR0_PAN
-       reserved_ttbr0 = .;
-       . += RESERVED_TTBR0_SIZE;
-#endif
+       reserved_pg_dir = .;
+       . += PAGE_SIZE;
+
        swapper_pg_dir = .;
        . += PAGE_SIZE;
-       swapper_pg_end = .;
 
        . = ALIGN(SEGMENT_ALIGN);
        __init_begin = .;
index 23c326a06b2d40cde5dbdc1cf491a1441766a82e..0eaf16b0442a0241c4ff7b0bedb7d44ef575a5b8 100644 (file)
@@ -168,7 +168,7 @@ SYM_FUNC_END(cpu_do_resume)
        .pushsection ".idmap.text", "awx"
 
 .macro __idmap_cpu_set_reserved_ttbr1, tmp1, tmp2
-       adrp    \tmp1, empty_zero_page
+       adrp    \tmp1, reserved_pg_dir
        phys_to_ttbr \tmp2, \tmp1
        offset_ttbr1 \tmp2, \tmp1
        msr     ttbr1_el1, \tmp2