Skip to content

Commit 2b4c5c1

Browse files
wildea01gregkh
authored andcommitted
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: Mark Rutland <mark.rutland@arm.com> Tested-by: Laura Abbott <labbott@redhat.com> Tested-by: Shanker Donthineni <shankerd@codeaurora.org> Signed-off-by: Will 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: Greg Hackmann <ghackmann@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
1 parent f47c91d commit 2b4c5c1

File tree

4 files changed

+50
-6
lines changed

4 files changed

+50
-6
lines changed

arch/arm64/include/asm/cpufeature.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@
2929
#define ARM64_HAS_PAN 4
3030
#define ARM64_HAS_UAO 5
3131
#define ARM64_ALT_PAN_NOT_UAO 6
32+
#define ARM64_UNMAP_KERNEL_AT_EL0 23
3233

33-
#define ARM64_NCAPS 7
34+
#define ARM64_NCAPS 24
3435

3536
#ifndef __ASSEMBLY__
3637

arch/arm64/include/asm/mmu.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
#ifndef __ASSEMBLY__
2222

23+
#include <asm/cpufeature.h>
24+
2325
typedef struct {
2426
atomic64_t id;
2527
void *vdso;
@@ -34,7 +36,8 @@ typedef struct {
3436

3537
static inline bool arm64_kernel_unmapped_at_el0(void)
3638
{
37-
return IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0);
39+
return IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0) &&
40+
cpus_have_cap(ARM64_UNMAP_KERNEL_AT_EL0);
3841
}
3942

4043
extern void paging_init(void);

arch/arm64/kernel/cpufeature.c

+39
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,39 @@ has_cpuid_feature(const struct arm64_cpu_capabilities *entry)
617617
return feature_matches(val, entry);
618618
}
619619

620+
#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
621+
static int __kpti_forced; /* 0: not forced, >0: forced on, <0: forced off */
622+
623+
static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry)
624+
{
625+
/* Forced on command line? */
626+
if (__kpti_forced) {
627+
pr_info_once("kernel page table isolation forced %s by command line option\n",
628+
__kpti_forced > 0 ? "ON" : "OFF");
629+
return __kpti_forced > 0;
630+
}
631+
632+
/* Useful for KASLR robustness */
633+
if (IS_ENABLED(CONFIG_RANDOMIZE_BASE))
634+
return true;
635+
636+
return false;
637+
}
638+
639+
static int __init parse_kpti(char *str)
640+
{
641+
bool enabled;
642+
int ret = strtobool(str, &enabled);
643+
644+
if (ret)
645+
return ret;
646+
647+
__kpti_forced = enabled ? 1 : -1;
648+
return 0;
649+
}
650+
__setup("kpti=", parse_kpti);
651+
#endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
652+
620653
static const struct arm64_cpu_capabilities arm64_features[] = {
621654
{
622655
.desc = "GIC system register CPU interface",
@@ -654,6 +687,12 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
654687
.matches = cpufeature_pan_not_uao,
655688
},
656689
#endif /* CONFIG_ARM64_PAN */
690+
#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
691+
{
692+
.capability = ARM64_UNMAP_KERNEL_AT_EL0,
693+
.matches = unmap_kernel_at_el0,
694+
},
695+
#endif
657696
{},
658697
};
659698

arch/arm64/kernel/entry.S

+5-4
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
.macro kernel_ventry, el, label, regsize = 64
7474
.align 7
7575
#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
76+
alternative_if ARM64_UNMAP_KERNEL_AT_EL0
7677
.if \el == 0
7778
.if \regsize == 64
7879
mrs x30, tpidrro_el0
@@ -81,6 +82,7 @@
8182
mov x30, xzr
8283
.endif
8384
.endif
85+
alternative_else_nop_endif
8486
#endif
8587

8688
sub sp, sp, #S_FRAME_SIZE
@@ -257,21 +259,20 @@ alternative_else_nop_endif
257259
ldr lr, [sp, #S_LR]
258260
add sp, sp, #S_FRAME_SIZE // restore sp
259261

260-
#ifndef CONFIG_UNMAP_KERNEL_AT_EL0
261-
eret
262-
#else
263262
.if \el == 0
263+
alternative_insn eret, nop, ARM64_UNMAP_KERNEL_AT_EL0
264+
#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
264265
bne 4f
265266
msr far_el1, x30
266267
tramp_alias x30, tramp_exit_native
267268
br x30
268269
4:
269270
tramp_alias x30, tramp_exit_compat
270271
br x30
272+
#endif
271273
.else
272274
eret
273275
.endif
274-
#endif
275276
.endm
276277

277278
/*

0 commit comments

Comments
 (0)