diff mbox series

[v2,13/18] arm64: entry: Hook up entry trampoline to exception vectors

Message ID 1512059986-21325-14-git-send-email-will.deacon@arm.com
State Superseded
Headers show
Series arm64: Unmap the kernel whilst running in userspace (KAISER) | expand

Commit Message

Will Deacon Nov. 30, 2017, 4:39 p.m. UTC
Hook up the entry trampoline to our exception vectors so that all
exceptions from and returns to EL0 go via the trampoline, which swizzles
the vector base register accordingly. Transitioning to and from the
kernel clobbers x30, so we use tpidrro_el0 and far_el1 as scratch
registers for native tasks.

Signed-off-by: Will Deacon <will.deacon@arm.com>

---
 arch/arm64/kernel/entry.S | 39 ++++++++++++++++++++++++++++++++++++---
 1 file changed, 36 insertions(+), 3 deletions(-)

-- 
2.1.4

Comments

Mark Rutland Dec. 1, 2017, 1:53 p.m. UTC | #1
On Thu, Nov 30, 2017 at 04:39:41PM +0000, Will Deacon wrote:
>  	.macro kernel_ventry, el, label, regsize = 64

>  	.align 7

> +#ifdef CONFIG_UNMAP_KERNEL_AT_EL0

> +	.if	\el == 0

> +	.if	\regsize == 64

> +	mrs	x30, tpidrro_el0

> +	msr	tpidrro_el0, xzr

> +	.else

> +	mov	x30, xzr


I guess that's just to prevent acccidental leaks if we dump registers
somewhere, since we used x30 as a scratch register?

> +	.macro tramp_alias, dst, sym

> +	mov_q	\dst, TRAMP_VALIAS

> +	add	\dst, \dst, #(\sym - .entry.tramp.text)

> +	.endm


I didn't realise you could refer to sections like this; neat!

Otherwise, looks fine to me.

Thanks,
Mark.
Will Deacon Dec. 1, 2017, 5:40 p.m. UTC | #2
On Fri, Dec 01, 2017 at 01:53:01PM +0000, Mark Rutland wrote:
> On Thu, Nov 30, 2017 at 04:39:41PM +0000, Will Deacon wrote:

> >  	.macro kernel_ventry, el, label, regsize = 64

> >  	.align 7

> > +#ifdef CONFIG_UNMAP_KERNEL_AT_EL0

> > +	.if	\el == 0

> > +	.if	\regsize == 64

> > +	mrs	x30, tpidrro_el0

> > +	msr	tpidrro_el0, xzr

> > +	.else

> > +	mov	x30, xzr

> 

> I guess that's just to prevent acccidental leaks if we dump registers

> somewhere, since we used x30 as a scratch register?


Indeed. I don't have a concrete example, but I was worried about things
like perf and ptrace, which might allow you to get at the AArch64 register
state for a compat task so it felt like a good idea to zero this.

Will
diff mbox series

Patch

diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 688e52f65a8d..99d105048663 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -73,6 +73,17 @@ 
 
 	.macro kernel_ventry, el, label, regsize = 64
 	.align 7
+#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
+	.if	\el == 0
+	.if	\regsize == 64
+	mrs	x30, tpidrro_el0
+	msr	tpidrro_el0, xzr
+	.else
+	mov	x30, xzr
+	.endif
+	.endif
+#endif
+
 	sub	sp, sp, #S_FRAME_SIZE
 #ifdef CONFIG_VMAP_STACK
 	/*
@@ -119,6 +130,11 @@ 
 	b	el\()\el\()_\label
 	.endm
 
+	.macro tramp_alias, dst, sym
+	mov_q	\dst, TRAMP_VALIAS
+	add	\dst, \dst, #(\sym - .entry.tramp.text)
+	.endm
+
 	.macro	kernel_entry, el, regsize = 64
 	.if	\regsize == 32
 	mov	w0, w0				// zero upper 32 bits of x0
@@ -271,18 +287,20 @@  alternative_else_nop_endif
 	.if	\el == 0
 	ldr	x23, [sp, #S_SP]		// load return stack pointer
 	msr	sp_el0, x23
+	tst	x22, #PSR_MODE32_BIT		// native task?
+	b.eq	3f
+
 #ifdef CONFIG_ARM64_ERRATUM_845719
 alternative_if ARM64_WORKAROUND_845719
-	tbz	x22, #4, 1f
 #ifdef CONFIG_PID_IN_CONTEXTIDR
 	mrs	x29, contextidr_el1
 	msr	contextidr_el1, x29
 #else
 	msr contextidr_el1, xzr
 #endif
-1:
 alternative_else_nop_endif
 #endif
+3:
 	.endif
 
 	msr	elr_el1, x21			// set up the return data
@@ -304,7 +322,22 @@  alternative_else_nop_endif
 	ldp	x28, x29, [sp, #16 * 14]
 	ldr	lr, [sp, #S_LR]
 	add	sp, sp, #S_FRAME_SIZE		// restore sp
-	eret					// return to kernel
+
+#ifndef CONFIG_UNMAP_KERNEL_AT_EL0
+	eret
+#else
+	.if	\el == 0
+	bne	4f
+	msr	far_el1, x30
+	tramp_alias	x30, tramp_exit_native
+	br	x30
+4:
+	tramp_alias	x30, tramp_exit_compat
+	br	x30
+	.else
+	eret
+	.endif
+#endif
 	.endm
 
 	.macro	irq_stack_entry