Christophe Leroy <christophe.le...@c-s.fr> writes: > Le 08/03/2019 à 02:16, Michael Ellerman a écrit : ... >> diff --git a/arch/powerpc/include/asm/book3s/64/kup-radix.h >> b/arch/powerpc/include/asm/book3s/64/kup-radix.h >> new file mode 100644 >> index 000000000000..3d60b04fc3f6 >> --- /dev/null >> +++ b/arch/powerpc/include/asm/book3s/64/kup-radix.h >> @@ -0,0 +1,107 @@ >> +/* SPDX-License-Identifier: GPL-2.0 */ >> +#ifndef _ASM_POWERPC_BOOK3S_64_KUP_RADIX_H >> +#define _ASM_POWERPC_BOOK3S_64_KUP_RADIX_H >> + >> +#include <linux/const.h> >> + >> +#define AMR_KUAP_BLOCK_READ UL(0x4000000000000000) >> +#define AMR_KUAP_BLOCK_WRITE UL(0x8000000000000000) >> +#define AMR_KUAP_BLOCKED (AMR_KUAP_BLOCK_READ | AMR_KUAP_BLOCK_WRITE) >> +#define AMR_KUAP_SHIFT 62 >> + >> +#ifdef __ASSEMBLY__ >> + >> +.macro kuap_restore_amr gpr > > What about calling it just kuap_restore (kuap_check and > kuap_save_and_lock) , for the day we add an different implementation for > non RADIX ?
I don't think we have any plan to use anything other than AMR. We can always rename them if we do. >> +#ifdef CONFIG_PPC_KUAP >> + BEGIN_MMU_FTR_SECTION_NESTED(67) >> + ld \gpr, STACK_REGS_KUAP(r1) >> + mtspr SPRN_AMR, \gpr >> + END_MMU_FTR_SECTION_NESTED_IFSET(MMU_FTR_RADIX_KUAP, 67) >> +#endif >> +.endm >> + >> +.macro kuap_check_amr gpr1 gpr2 > > What about using .macro kuap_check_amr gpr1, gpr2 instead to have a > standard form with a ',' like kuap_save_amr_and_lock Yep, that was not intentional. >> +#ifdef CONFIG_PPC_KUAP_DEBUG >> + BEGIN_MMU_FTR_SECTION_NESTED(67) >> + mfspr \gpr1, SPRN_AMR >> + li \gpr2, (AMR_KUAP_BLOCKED >> AMR_KUAP_SHIFT) >> + sldi \gpr2, \gpr2, AMR_KUAP_SHIFT >> +999: tdne \gpr1, \gpr2 >> + EMIT_BUG_ENTRY 999b,__FILE__,__LINE__, \ >> + (BUGFLAG_WARNING|BUGFLAG_ONCE) > > This should fit on a single line. > Also add space after , and around | Yep, copy/pasted from elsewhere. >> +.macro kuap_save_amr_and_lock gpr1, gpr2, use_cr, msr_pr_cr >> +#ifdef CONFIG_PPC_KUAP >> + BEGIN_MMU_FTR_SECTION_NESTED(67) >> + .ifnb \msr_pr_cr >> + bne \msr_pr_cr, 99f >> + .endif >> + mfspr \gpr1, SPRN_AMR >> + std \gpr1, STACK_REGS_KUAP(r1) >> + li \gpr2, (AMR_KUAP_BLOCKED >> AMR_KUAP_SHIFT) >> + sldi \gpr2, \gpr2, AMR_KUAP_SHIFT >> + cmpd \use_cr, \gpr1, \gpr2 > > On ppc32, I would have used rlwinm. to do the test. Is there an > equivalent rldinm. (unless we need to preserve cr0) ? I prefer to have the CR field specified, so we don't accidentally clobber cr0 in some path where it is live. >> + beq \use_cr, 99f >> + // We don't isync here because we very recently entered via rfid > > Is this form of comment acceptable now ? It used to be /* */ only. Yeah it is, at least in powerpc code :) >> diff --git a/arch/powerpc/include/asm/exception-64s.h >> b/arch/powerpc/include/asm/exception-64s.h >> index 937bb630093f..bef4e05a6823 100644 >> --- a/arch/powerpc/include/asm/exception-64s.h >> +++ b/arch/powerpc/include/asm/exception-64s.h >> @@ -497,6 +497,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943) >> RESTORE_CTR(r1, area); \ >> b bad_stack; \ >> 3: EXCEPTION_PROLOG_COMMON_1(); \ >> + kuap_save_amr_and_lock r9, r10, cr1, cr0; \ > > What about moving this to 4f, to avoid the cr test and branch in > kuap_save_amr_and_lock ? Moving it there wouldn't help, because user & kernel entry both go through 4f. So we'd still need to check if we're coming from user. Or did I misunderstand? >> beq 4f; /* if from kernel mode */ \ >> ACCOUNT_CPU_USER_ENTRY(r13, r9, r10); \ >> SAVE_PPR(area, r9); \ >> diff --git a/arch/powerpc/mm/pgtable-radix.c >> b/arch/powerpc/mm/pgtable-radix.c >> index 224bcd4be5ae..0c87832ddd6c 100644 >> --- a/arch/powerpc/mm/pgtable-radix.c >> +++ b/arch/powerpc/mm/pgtable-radix.c >> @@ -553,6 +554,23 @@ void __init setup_kuep(bool disabled) >> } >> #endif >> >> +#ifdef CONFIG_PPC_KUAP >> +void __init setup_kuap(bool disabled) >> +{ >> + if (disabled || !early_radix_enabled()) >> + return; >> + >> + if (smp_processor_id() == boot_cpuid) { >> + pr_info("Activating Kernel Userspace Access Prevention\n"); >> + cur_cpu_spec->mmu_features |= MMU_FTR_RADIX_KUAP; >> + } >> + >> + /* Make sure userspace can't change the AMR */ >> + mtspr(SPRN_UAMOR, 0); >> + mtspr(SPRN_AMR, AMR_KUAP_BLOCKED); > > No isync() needed here ? Will add. >> diff --git a/arch/powerpc/platforms/Kconfig.cputype >> b/arch/powerpc/platforms/Kconfig.cputype >> index 60371784c9f1..5e53b9fd62aa 100644 >> --- a/arch/powerpc/platforms/Kconfig.cputype >> +++ b/arch/powerpc/platforms/Kconfig.cputype >> @@ -370,6 +371,13 @@ config PPC_KUAP >> >> If you're unsure, say Y. >> >> +config PPC_KUAP_DEBUG >> + bool "Extra debugging for Kernel Userspace Access Protection" >> + depends on PPC_HAVE_KUAP && PPC_RADIX_MMU > > Why only PPC_RADIX_MMU ? Because it doesn't do anything useful unless radix is enabled. We can remove it when another platform wants it. Thanks for the review. cheers