arm64: consistently use reserved_pg_dir
authorMark Rutland <mark.rutland@arm.com>
Tue, 3 Nov 2020 10:22:29 +0000 (10:22 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 14 Jul 2021 14:56:06 +0000 (16:56 +0200)
[ Upstream commit 833be850f1cabd0e3b5337c0fcab20a6e936dd48 ]

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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
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 4e2ba947784503d92fafe3175a28d4b39d75801a..68028de06d18ef6dc8742aa4f5b83c59327fa8da 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();
@@ -192,7 +192,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 717f13d52ecc511f53a65b91b3697d19bf623a8f..10ffbc96ac31f419f1e181e2c0334ee894fadc59 100644 (file)
@@ -530,6 +530,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 60d39912336004fd10fa87ca55aa1135de32ef49..fe83d6d67ec3dc72ae9e3a3d07d4eb8e5149b7c7 100644 (file)
@@ -770,9 +770,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
@@ -789,9 +790,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 a14927360be267d676cb000f3147bc7bf3f1a052..aacc7eab9b2ffa676dfb16fc23f09438b0d4ea2a 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