Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6415b1f8 authored by Will Deacon's avatar Will Deacon Committed by Greg Kroah-Hartman
Browse files

FROMLIST: arm64: entry: Add exception trampoline page for exceptions from EL0



To allow unmapping of the kernel whilst running at EL0, we need to
point the exception vectors at an entry trampoline that can map/unmap
the kernel on entry/exit respectively.

This patch adds the trampoline page, although it is not yet plugged
into the vector table and is therefore unused.

Reviewed-by: default avatarMark Rutland <mark.rutland@arm.com>
Tested-by: default avatarLaura Abbott <labbott@redhat.com>
Tested-by: default avatarShanker Donthineni <shankerd@codeaurora.org>
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
(cherry picked from git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git


 commit c7b9adaf85f818d747eeff5145eb4095ccd587fb)

Change-Id: Idd27ab26f1ec1db2ff756fc33ebb782201806f7c
[ghackmann@google.com: adjust context]
Signed-off-by: default avatarGreg Hackmann <ghackmann@google.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent eed2e002
Loading
Loading
Loading
Loading
+85 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include <asm/errno.h>
#include <asm/esr.h>
#include <asm/memory.h>
#include <asm/mmu.h>
#include <asm/ptrace.h>
#include <asm/thread_info.h>
#include <asm/uaccess.h>
@@ -810,6 +811,90 @@ __ni_sys_trace:
	bl	do_ni_syscall
	b	__sys_trace_return

#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
/*
 * Exception vectors trampoline.
 */
	.pushsection ".entry.tramp.text", "ax"

	.macro tramp_map_kernel, tmp
	mrs	\tmp, ttbr1_el1
	sub	\tmp, \tmp, #(SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE)
	bic	\tmp, \tmp, #USER_ASID_FLAG
	msr	ttbr1_el1, \tmp
	.endm

	.macro tramp_unmap_kernel, tmp
	mrs	\tmp, ttbr1_el1
	add	\tmp, \tmp, #(SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE)
	orr	\tmp, \tmp, #USER_ASID_FLAG
	msr	ttbr1_el1, \tmp
	/*
	 * We avoid running the post_ttbr_update_workaround here because the
	 * user and kernel ASIDs don't have conflicting mappings, so any
	 * "blessing" as described in:
	 *
	 *   http://lkml.kernel.org/r/56BB848A.6060603@caviumnetworks.com
	 *
	 * will not hurt correctness. Whilst this may partially defeat the
	 * point of using split ASIDs in the first place, it avoids
	 * the hit of invalidating the entire I-cache on every return to
	 * userspace.
	 */
	.endm

	.macro tramp_ventry, regsize = 64
	.align	7
1:
	.if	\regsize == 64
	msr	tpidrro_el0, x30	// Restored in kernel_ventry
	.endif
	tramp_map_kernel	x30
	ldr	x30, =vectors
	prfm	plil1strm, [x30, #(1b - tramp_vectors)]
	msr	vbar_el1, x30
	add	x30, x30, #(1b - tramp_vectors)
	isb
	br	x30
	.endm

	.macro tramp_exit, regsize = 64
	adr	x30, tramp_vectors
	msr	vbar_el1, x30
	tramp_unmap_kernel	x30
	.if	\regsize == 64
	mrs	x30, far_el1
	.endif
	eret
	.endm

	.align	11
ENTRY(tramp_vectors)
	.space	0x400

	tramp_ventry
	tramp_ventry
	tramp_ventry
	tramp_ventry

	tramp_ventry	32
	tramp_ventry	32
	tramp_ventry	32
	tramp_ventry	32
END(tramp_vectors)

ENTRY(tramp_exit_native)
	tramp_exit
END(tramp_exit_native)

ENTRY(tramp_exit_compat)
	tramp_exit	32
END(tramp_exit_compat)

	.ltorg
	.popsection				// .entry.tramp.text
#endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */

/*
 * Special system call wrappers.
 */
+17 −0
Original line number Diff line number Diff line
@@ -34,6 +34,17 @@ jiffies = jiffies_64;
	*(.hyp.text)					\
	VMLINUX_SYMBOL(__hyp_text_end) = .;

#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
#define TRAMP_TEXT					\
	. = ALIGN(PAGE_SIZE);				\
	VMLINUX_SYMBOL(__entry_tramp_text_start) = .;	\
	*(.entry.tramp.text)				\
	. = ALIGN(PAGE_SIZE);				\
	VMLINUX_SYMBOL(__entry_tramp_text_end) = .;
#else
#define TRAMP_TEXT
#endif

/*
 * 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
@@ -91,6 +102,7 @@ SECTIONS
			SCHED_TEXT
			LOCK_TEXT
			HYPERVISOR_TEXT
			TRAMP_TEXT
			*(.fixup)
			*(.gnu.warning)
		. = ALIGN(16);
@@ -161,6 +173,11 @@ SECTIONS
	. += RESERVED_TTBR0_SIZE;
#endif

#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
	tramp_pg_dir = .;
	. += PAGE_SIZE;
#endif

	_end = .;

	STABS_DEBUG