Loading arch/arm64/include/asm/cpucaps.h +3 −1 Original line number Diff line number Diff line Loading @@ -35,6 +35,8 @@ #define ARM64_HYP_OFFSET_LOW 14 #define ARM64_MISMATCHED_CACHE_LINE_SIZE 15 #define ARM64_NCAPS 16 #define ARM64_UNMAP_KERNEL_AT_EL0 16 #define ARM64_NCAPS 17 #endif /* __ASM_CPUCAPS_H */ arch/arm64/include/asm/mmu.h +2 −1 Original line number Diff line number Diff line Loading @@ -35,7 +35,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); Loading arch/arm64/kernel/cpufeature.c +41 −0 Original line number Diff line number Diff line Loading @@ -748,6 +748,40 @@ static bool hyp_offset_low(const struct arm64_cpu_capabilities *entry, return idmap_addr > GENMASK(VA_BITS - 2, 0) && !is_kernel_in_hyp_mode(); } #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, int __unused) { /* 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", Loading Loading @@ -831,6 +865,13 @@ static const struct arm64_cpu_capabilities arm64_features[] = { .def_scope = SCOPE_SYSTEM, .matches = hyp_offset_low, }, #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 { .capability = ARM64_UNMAP_KERNEL_AT_EL0, .def_scope = SCOPE_SYSTEM, .matches = unmap_kernel_at_el0, }, #endif {}, }; Loading arch/arm64/kernel/entry.S +5 −4 Original line number Diff line number Diff line Loading @@ -74,6 +74,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 Loading @@ -82,6 +83,7 @@ mov x30, xzr .endif .endif alternative_else_nop_endif #endif sub sp, sp, #S_FRAME_SIZE Loading Loading @@ -269,10 +271,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 Loading @@ -280,10 +281,10 @@ alternative_else_nop_endif 4: tramp_alias x30, tramp_exit_compat br x30 #endif .else eret .endif #endif .endm .macro irq_stack_entry Loading Loading
arch/arm64/include/asm/cpucaps.h +3 −1 Original line number Diff line number Diff line Loading @@ -35,6 +35,8 @@ #define ARM64_HYP_OFFSET_LOW 14 #define ARM64_MISMATCHED_CACHE_LINE_SIZE 15 #define ARM64_NCAPS 16 #define ARM64_UNMAP_KERNEL_AT_EL0 16 #define ARM64_NCAPS 17 #endif /* __ASM_CPUCAPS_H */
arch/arm64/include/asm/mmu.h +2 −1 Original line number Diff line number Diff line Loading @@ -35,7 +35,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); Loading
arch/arm64/kernel/cpufeature.c +41 −0 Original line number Diff line number Diff line Loading @@ -748,6 +748,40 @@ static bool hyp_offset_low(const struct arm64_cpu_capabilities *entry, return idmap_addr > GENMASK(VA_BITS - 2, 0) && !is_kernel_in_hyp_mode(); } #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, int __unused) { /* 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", Loading Loading @@ -831,6 +865,13 @@ static const struct arm64_cpu_capabilities arm64_features[] = { .def_scope = SCOPE_SYSTEM, .matches = hyp_offset_low, }, #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 { .capability = ARM64_UNMAP_KERNEL_AT_EL0, .def_scope = SCOPE_SYSTEM, .matches = unmap_kernel_at_el0, }, #endif {}, }; Loading
arch/arm64/kernel/entry.S +5 −4 Original line number Diff line number Diff line Loading @@ -74,6 +74,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 Loading @@ -82,6 +83,7 @@ mov x30, xzr .endif .endif alternative_else_nop_endif #endif sub sp, sp, #S_FRAME_SIZE Loading Loading @@ -269,10 +271,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 Loading @@ -280,10 +281,10 @@ alternative_else_nop_endif 4: tramp_alias x30, tramp_exit_compat br x30 #endif .else eret .endif #endif .endm .macro irq_stack_entry Loading