Commit 833be850 authored by Mark Rutland's avatar Mark Rutland Committed by Catalin Marinas
Browse files

arm64: consistently use reserved_pg_dir



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: default avatarMark 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: default avatarCatalin Marinas <catalin.marinas@arm.com>
parent ba090f9c
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -15,10 +15,10 @@
	.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
+0 −6
Original line number Diff line number Diff line
@@ -89,12 +89,6 @@
#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
+3 −3
Original line number Diff line number Diff line
@@ -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;

+1 −0
Original line number Diff line number Diff line
@@ -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);

+2 −2
Original line number Diff line number Diff line
@@ -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);
Loading