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

Commit 2b4c5c1f authored by Will Deacon's avatar Will Deacon Committed by Greg Kroah-Hartman
Browse files

FROMLIST: arm64: entry: Add fake CPU feature for unmapping the kernel at EL0



Allow explicit disabling of the entry trampoline on the kernel command
line (kpti=off) by adding a fake CPU feature (ARM64_UNMAP_KERNEL_AT_EL0)
that can be used to toggle the alternative sequences in our entry code and
avoid use of the trampoline altogether if desired. This also allows us to
make use of a static key in arm64_kernel_unmapped_at_el0().

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 ea1e3de85e94d711f63437c04624aa0e8de5c8b3)

Change-Id: I11cb874d12a7d0921f452c62b0752e0028a8e0a7
[ghackmann@google.com:
 - adjust context
 - apply cpucaps.h changes to cpufeature.h
 - replace cpus_have_const_cap() with cpus_have_cap(), and include the
   header that declares it
 - tweak unmap_kernel_at_el0() declaration to match 3.18 APIs]
Signed-off-by: default avatarGreg Hackmann <ghackmann@google.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent f47c91dc
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -29,8 +29,9 @@
#define ARM64_HAS_PAN				4
#define ARM64_HAS_UAO				5
#define ARM64_ALT_PAN_NOT_UAO			6
#define ARM64_UNMAP_KERNEL_AT_EL0		23

#define ARM64_NCAPS				7
#define ARM64_NCAPS				24

#ifndef __ASSEMBLY__

+4 −1
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@

#ifndef __ASSEMBLY__

#include <asm/cpufeature.h>

typedef struct {
	atomic64_t	id;
	void		*vdso;
@@ -34,7 +36,8 @@ typedef struct {

static inline bool arm64_kernel_unmapped_at_el0(void)
{
	return IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0);
	return IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0) &&
	       cpus_have_cap(ARM64_UNMAP_KERNEL_AT_EL0);
}

extern void paging_init(void);
+39 −0
Original line number Diff line number Diff line
@@ -617,6 +617,39 @@ has_cpuid_feature(const struct arm64_cpu_capabilities *entry)
	return feature_matches(val, entry);
}

#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
static int __kpti_forced; /* 0: not forced, >0: forced on, <0: forced off */

static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry)
{
	/* Forced on command line? */
	if (__kpti_forced) {
		pr_info_once("kernel page table isolation forced %s by command line option\n",
			     __kpti_forced > 0 ? "ON" : "OFF");
		return __kpti_forced > 0;
	}

	/* Useful for KASLR robustness */
	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE))
		return true;

	return false;
}

static int __init parse_kpti(char *str)
{
	bool enabled;
	int ret = strtobool(str, &enabled);

	if (ret)
		return ret;

	__kpti_forced = enabled ? 1 : -1;
	return 0;
}
__setup("kpti=", parse_kpti);
#endif	/* CONFIG_UNMAP_KERNEL_AT_EL0 */

static const struct arm64_cpu_capabilities arm64_features[] = {
	{
		.desc = "GIC system register CPU interface",
@@ -654,6 +687,12 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
		.matches = cpufeature_pan_not_uao,
	},
#endif /* CONFIG_ARM64_PAN */
#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
	{
		.capability = ARM64_UNMAP_KERNEL_AT_EL0,
		.matches = unmap_kernel_at_el0,
	},
#endif
	{},
};

+5 −4
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@
	.macro kernel_ventry, el, label, regsize = 64
	.align 7
#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
alternative_if ARM64_UNMAP_KERNEL_AT_EL0
	.if	\el == 0
	.if	\regsize == 64
	mrs	x30, tpidrro_el0
@@ -81,6 +82,7 @@
	mov	x30, xzr
	.endif
	.endif
alternative_else_nop_endif
#endif

	sub	sp, sp, #S_FRAME_SIZE
@@ -257,10 +259,9 @@ alternative_else_nop_endif
	ldr	lr, [sp, #S_LR]
	add	sp, sp, #S_FRAME_SIZE		// restore sp

#ifndef CONFIG_UNMAP_KERNEL_AT_EL0
	eret
#else
	.if	\el == 0
alternative_insn eret, nop, ARM64_UNMAP_KERNEL_AT_EL0
#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
	bne	4f
	msr	far_el1, x30
	tramp_alias	x30, tramp_exit_native
@@ -268,10 +269,10 @@ alternative_else_nop_endif
4:
	tramp_alias	x30, tramp_exit_compat
	br	x30
#endif
	.else
	eret
	.endif
#endif
	.endm

/*