Message ID | 20210409101902.2800-1-vincenzo.frascino@arm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v2] arm64: mte: Move MTE TCF0 check in entry-common | expand |
Hi Vincenzo, I love your patch! Yet something to improve: [auto build test ERROR on arm/for-next] [also build test ERROR on soc/for-next kvmarm/next linus/master v5.12-rc6 next-20210408] [cannot apply to arm64/for-next/core xlnx/master] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Vincenzo-Frascino/arm64-mte-Move-MTE-TCF0-check-in-entry-common/20210409-182215 base: git://git.armlinux.org.uk/~rmk/linux-arm.git for-next config: arm64-allnoconfig (attached as .config) compiler: aarch64-linux-gcc (GCC) 9.3.0 reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/0day-ci/linux/commit/59174442d4b85039bfec7ede4825ff2b5c0b4331 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Vincenzo-Frascino/arm64-mte-Move-MTE-TCF0-check-in-entry-common/20210409-182215 git checkout 59174442d4b85039bfec7ede4825ff2b5c0b4331 # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=arm64 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All error/warnings (new ones prefixed by >>): In file included from arch/arm64/include/asm/pgtable.h:12, from include/linux/pgtable.h:6, from include/linux/mm.h:33, from arch/arm64/kernel/asm-offsets.c:12: >> arch/arm64/include/asm/mte.h:89:1: warning: ignoring attribute 'gnu_inline' because it conflicts with attribute 'noinline' [-Wattributes] 89 | { | ^ arch/arm64/include/asm/mte.h:34:14: note: previous declaration here 34 | void noinstr check_mte_async_tcf0(void); | ^~~~~~~~~~~~~~~~~~~~ >> arch/arm64/include/asm/mte.h:88:20: error: static declaration of 'check_mte_async_tcf0' follows non-static declaration 88 | static inline void check_mte_async_tcf0(void) | ^~~~~~~~~~~~~~~~~~~~ arch/arm64/include/asm/mte.h:34:14: note: previous declaration of 'check_mte_async_tcf0' was here 34 | void noinstr check_mte_async_tcf0(void); | ^~~~~~~~~~~~~~~~~~~~ arch/arm64/include/asm/mte.h:92:1: warning: ignoring attribute 'gnu_inline' because it conflicts with attribute 'noinline' [-Wattributes] 92 | { | ^ arch/arm64/include/asm/mte.h:35:14: note: previous declaration here 35 | void noinstr clear_mte_async_tcf0(void); | ^~~~~~~~~~~~~~~~~~~~ >> arch/arm64/include/asm/mte.h:91:20: error: static declaration of 'clear_mte_async_tcf0' follows non-static declaration 91 | static inline void clear_mte_async_tcf0(void) | ^~~~~~~~~~~~~~~~~~~~ arch/arm64/include/asm/mte.h:35:14: note: previous declaration of 'clear_mte_async_tcf0' was here 35 | void noinstr clear_mte_async_tcf0(void); | ^~~~~~~~~~~~~~~~~~~~ -- In file included from arch/arm64/include/asm/pgtable.h:12, from include/linux/pgtable.h:6, from include/linux/mm.h:33, from arch/arm64/kernel/asm-offsets.c:12: >> arch/arm64/include/asm/mte.h:89:1: warning: ignoring attribute 'gnu_inline' because it conflicts with attribute 'noinline' [-Wattributes] 89 | { | ^ arch/arm64/include/asm/mte.h:34:14: note: previous declaration here 34 | void noinstr check_mte_async_tcf0(void); | ^~~~~~~~~~~~~~~~~~~~ >> arch/arm64/include/asm/mte.h:88:20: error: static declaration of 'check_mte_async_tcf0' follows non-static declaration 88 | static inline void check_mte_async_tcf0(void) | ^~~~~~~~~~~~~~~~~~~~ arch/arm64/include/asm/mte.h:34:14: note: previous declaration of 'check_mte_async_tcf0' was here 34 | void noinstr check_mte_async_tcf0(void); | ^~~~~~~~~~~~~~~~~~~~ arch/arm64/include/asm/mte.h:92:1: warning: ignoring attribute 'gnu_inline' because it conflicts with attribute 'noinline' [-Wattributes] 92 | { | ^ arch/arm64/include/asm/mte.h:35:14: note: previous declaration here 35 | void noinstr clear_mte_async_tcf0(void); | ^~~~~~~~~~~~~~~~~~~~ >> arch/arm64/include/asm/mte.h:91:20: error: static declaration of 'clear_mte_async_tcf0' follows non-static declaration 91 | static inline void clear_mte_async_tcf0(void) | ^~~~~~~~~~~~~~~~~~~~ arch/arm64/include/asm/mte.h:35:14: note: previous declaration of 'clear_mte_async_tcf0' was here 35 | void noinstr clear_mte_async_tcf0(void); | ^~~~~~~~~~~~~~~~~~~~ make[2]: *** [scripts/Makefile.build:116: arch/arm64/kernel/asm-offsets.s] Error 1 make[2]: Target '__build' not remade because of errors. make[1]: *** [Makefile:1233: prepare0] Error 2 make[1]: Target 'prepare' not remade because of errors. make: *** [Makefile:215: __sub-make] Error 2 make: Target 'prepare' not remade because of errors. vim +/check_mte_async_tcf0 +88 arch/arm64/include/asm/mte.h 20 21 void mte_clear_page_tags(void *addr); 22 unsigned long mte_copy_tags_from_user(void *to, const void __user *from, 23 unsigned long n); 24 unsigned long mte_copy_tags_to_user(void __user *to, void *from, 25 unsigned long n); 26 int mte_save_tags(struct page *page); 27 void mte_save_page_tags(const void *page_addr, void *tag_storage); 28 bool mte_restore_tags(swp_entry_t entry, struct page *page); 29 void mte_restore_page_tags(void *page_addr, const void *tag_storage); 30 void mte_invalidate_tags(int type, pgoff_t offset); 31 void mte_invalidate_tags_area(int type); 32 void *mte_allocate_tag_storage(void); 33 void mte_free_tag_storage(char *storage); > 34 void noinstr check_mte_async_tcf0(void); 35 void noinstr clear_mte_async_tcf0(void); 36 37 #ifdef CONFIG_ARM64_MTE 38 39 /* track which pages have valid allocation tags */ 40 #define PG_mte_tagged PG_arch_2 41 42 void mte_sync_tags(pte_t *ptep, pte_t pte); 43 void mte_copy_page_tags(void *kto, const void *kfrom); 44 void flush_mte_state(void); 45 void mte_thread_switch(struct task_struct *next); 46 void mte_suspend_exit(void); 47 long set_mte_ctrl(struct task_struct *task, unsigned long arg); 48 long get_mte_ctrl(struct task_struct *task); 49 int mte_ptrace_copy_tags(struct task_struct *child, long request, 50 unsigned long addr, unsigned long data); 51 52 void mte_assign_mem_tag_range(void *addr, size_t size); 53 54 #else /* CONFIG_ARM64_MTE */ 55 56 /* unused if !CONFIG_ARM64_MTE, silence the compiler */ 57 #define PG_mte_tagged 0 58 59 static inline void mte_sync_tags(pte_t *ptep, pte_t pte) 60 { 61 } 62 static inline void mte_copy_page_tags(void *kto, const void *kfrom) 63 { 64 } 65 static inline void flush_mte_state(void) 66 { 67 } 68 static inline void mte_thread_switch(struct task_struct *next) 69 { 70 } 71 static inline void mte_suspend_exit(void) 72 { 73 } 74 static inline long set_mte_ctrl(struct task_struct *task, unsigned long arg) 75 { 76 return 0; 77 } 78 static inline long get_mte_ctrl(struct task_struct *task) 79 { 80 return 0; 81 } 82 static inline int mte_ptrace_copy_tags(struct task_struct *child, 83 long request, unsigned long addr, 84 unsigned long data) 85 { 86 return -EIO; 87 } > 88 static inline void check_mte_async_tcf0(void) > 89 { 90 } > 91 static inline void clear_mte_async_tcf0(void) 92 { 93 } 94 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff --git a/arch/arm64/include/asm/mte.h b/arch/arm64/include/asm/mte.h index 9b557a457f24..2ecb2156dac1 100644 --- a/arch/arm64/include/asm/mte.h +++ b/arch/arm64/include/asm/mte.h @@ -31,6 +31,8 @@ void mte_invalidate_tags(int type, pgoff_t offset); void mte_invalidate_tags_area(int type); void *mte_allocate_tag_storage(void); void mte_free_tag_storage(char *storage); +void noinstr check_mte_async_tcf0(void); +void noinstr clear_mte_async_tcf0(void); #ifdef CONFIG_ARM64_MTE @@ -83,6 +85,12 @@ static inline int mte_ptrace_copy_tags(struct task_struct *child, { return -EIO; } +static inline void check_mte_async_tcf0(void) +{ +} +static inline void clear_mte_async_tcf0(void) +{ +} static inline void mte_assign_mem_tag_range(void *addr, size_t size) { diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c index 9d3588450473..837d3624a1d5 100644 --- a/arch/arm64/kernel/entry-common.c +++ b/arch/arm64/kernel/entry-common.c @@ -289,10 +289,16 @@ asmlinkage void noinstr enter_from_user_mode(void) CT_WARN_ON(ct_state() != CONTEXT_USER); user_exit_irqoff(); trace_hardirqs_off_finish(); + + /* Check for asynchronous tag check faults in user space */ + check_mte_async_tcf0(); } asmlinkage void noinstr exit_to_user_mode(void) { + /* Ignore asynchronous tag check faults in the uaccess routines */ + clear_mte_async_tcf0(); + trace_hardirqs_on_prepare(); lockdep_hardirqs_on_prepare(CALLER_ADDR0); user_enter_irqoff(); diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index a31a0a713c85..fb57df0d453f 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -34,15 +34,11 @@ * user and kernel mode. */ .macro user_exit_irqoff -#if defined(CONFIG_CONTEXT_TRACKING) || defined(CONFIG_TRACE_IRQFLAGS) bl enter_from_user_mode -#endif .endm .macro user_enter_irqoff -#if defined(CONFIG_CONTEXT_TRACKING) || defined(CONFIG_TRACE_IRQFLAGS) bl exit_to_user_mode -#endif .endm .macro clear_gp_regs @@ -147,32 +143,6 @@ alternative_cb_end .L__asm_ssbd_skip\@: .endm - /* Check for MTE asynchronous tag check faults */ - .macro check_mte_async_tcf, flgs, tmp -#ifdef CONFIG_ARM64_MTE -alternative_if_not ARM64_MTE - b 1f -alternative_else_nop_endif - mrs_s \tmp, SYS_TFSRE0_EL1 - tbz \tmp, #SYS_TFSR_EL1_TF0_SHIFT, 1f - /* Asynchronous TCF occurred for TTBR0 access, set the TI flag */ - orr \flgs, \flgs, #_TIF_MTE_ASYNC_FAULT - str \flgs, [tsk, #TSK_TI_FLAGS] - msr_s SYS_TFSRE0_EL1, xzr -1: -#endif - .endm - - /* Clear the MTE asynchronous tag check faults */ - .macro clear_mte_async_tcf -#ifdef CONFIG_ARM64_MTE -alternative_if ARM64_MTE - dsb ish - msr_s SYS_TFSRE0_EL1, xzr -alternative_else_nop_endif -#endif - .endm - .macro mte_set_gcr, tmp, tmp2 #ifdef CONFIG_ARM64_MTE /* @@ -243,8 +213,6 @@ alternative_else_nop_endif ldr x19, [tsk, #TSK_TI_FLAGS] disable_step_tsk x19, x20 - /* Check for asynchronous tag check faults in user space */ - check_mte_async_tcf x19, x22 apply_ssbd 1, x22, x23 ptrauth_keys_install_kernel tsk, x20, x22, x23 @@ -775,8 +743,6 @@ SYM_CODE_START_LOCAL(ret_to_user) cbnz x2, work_pending finish_ret_to_user: user_enter_irqoff - /* Ignore asynchronous tag check faults in the uaccess routines */ - clear_mte_async_tcf enable_step_tsk x19, x2 #ifdef CONFIG_GCC_PLUGIN_STACKLEAK bl stackleak_erase diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c index b3c70a612c7a..84a942c25870 100644 --- a/arch/arm64/kernel/mte.c +++ b/arch/arm64/kernel/mte.c @@ -166,14 +166,43 @@ static void set_gcr_el1_excl(u64 excl) */ } -void flush_mte_state(void) +void noinstr check_mte_async_tcf0(void) +{ + u64 tcf0; + + if (!system_supports_mte()) + return; + + /* + * dsb(ish) is not required before the register read + * because the TFSRE0_EL1 is automatically synchronized + * by the hardware on exception entry as SCTLR_EL1.ITFSB + * is set. + */ + tcf0 = read_sysreg_s(SYS_TFSRE0_EL1); + + if (tcf0 & SYS_TFSR_EL1_TF0) + set_thread_flag(TIF_MTE_ASYNC_FAULT); + + write_sysreg_s(0, SYS_TFSRE0_EL1); +} + +void noinstr clear_mte_async_tcf0(void) { if (!system_supports_mte()) return; - /* clear any pending asynchronous tag fault */ dsb(ish); write_sysreg_s(0, SYS_TFSRE0_EL1); +} + +void flush_mte_state(void) +{ + if (!system_supports_mte()) + return; + + /* clear any pending asynchronous tag fault */ + clear_mte_async_tcf0(); clear_thread_flag(TIF_MTE_ASYNC_FAULT); /* disable tag checking */ set_sctlr_el1_tcf0(SCTLR_EL1_TCF0_NONE);
The check_mte_async_tcf macro sets the TIF flag non-atomically. This can race with another CPU doing a set_tsk_thread_flag() and all the other flags can be lost in the process. Move the tcf0 check to enter_from_user_mode() and clear tcf0 in exit_to_user_mode() to address the problem. Note: Moving the check in entry-common allows to use set_thread_flag() which is safe. Fixes: 637ec831ea4f ("arm64: mte: Handle synchronous and asynchronous tag check faults") Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Will Deacon <will@kernel.org> Cc: stable@vger.kernel.org Reported-by: Will Deacon <will@kernel.org> Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com> --- arch/arm64/include/asm/mte.h | 8 ++++++++ arch/arm64/kernel/entry-common.c | 6 ++++++ arch/arm64/kernel/entry.S | 34 -------------------------------- arch/arm64/kernel/mte.c | 33 +++++++++++++++++++++++++++++-- 4 files changed, 45 insertions(+), 36 deletions(-)