xref: /OK3568_Linux_fs/kernel/arch/arm64/include/asm/mte.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) 2020 ARM Ltd.
4*4882a593Smuzhiyun  */
5*4882a593Smuzhiyun #ifndef __ASM_MTE_H
6*4882a593Smuzhiyun #define __ASM_MTE_H
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <asm/compiler.h>
9*4882a593Smuzhiyun #include <asm/mte-def.h>
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #ifndef __ASSEMBLY__
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #include <linux/bitfield.h>
14*4882a593Smuzhiyun #include <linux/page-flags.h>
15*4882a593Smuzhiyun #include <linux/types.h>
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #include <asm/pgtable-types.h>
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun void mte_clear_page_tags(void *addr);
20*4882a593Smuzhiyun unsigned long mte_copy_tags_from_user(void *to, const void __user *from,
21*4882a593Smuzhiyun 				      unsigned long n);
22*4882a593Smuzhiyun unsigned long mte_copy_tags_to_user(void __user *to, void *from,
23*4882a593Smuzhiyun 				    unsigned long n);
24*4882a593Smuzhiyun int mte_save_tags(struct page *page);
25*4882a593Smuzhiyun void mte_save_page_tags(const void *page_addr, void *tag_storage);
26*4882a593Smuzhiyun bool mte_restore_tags(swp_entry_t entry, struct page *page);
27*4882a593Smuzhiyun void mte_restore_page_tags(void *page_addr, const void *tag_storage);
28*4882a593Smuzhiyun void mte_invalidate_tags(int type, pgoff_t offset);
29*4882a593Smuzhiyun void mte_invalidate_tags_area(int type);
30*4882a593Smuzhiyun void *mte_allocate_tag_storage(void);
31*4882a593Smuzhiyun void mte_free_tag_storage(char *storage);
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun #ifdef CONFIG_ARM64_MTE
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun /* track which pages have valid allocation tags */
36*4882a593Smuzhiyun #define PG_mte_tagged	PG_arch_2
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun void mte_zero_clear_page_tags(void *addr);
39*4882a593Smuzhiyun void mte_sync_tags(pte_t *ptep, pte_t pte);
40*4882a593Smuzhiyun void mte_copy_page_tags(void *kto, const void *kfrom);
41*4882a593Smuzhiyun void mte_thread_init_user(void);
42*4882a593Smuzhiyun void mte_thread_switch(struct task_struct *next);
43*4882a593Smuzhiyun void mte_suspend_enter(void);
44*4882a593Smuzhiyun long set_mte_ctrl(struct task_struct *task, unsigned long arg);
45*4882a593Smuzhiyun long get_mte_ctrl(struct task_struct *task);
46*4882a593Smuzhiyun int mte_ptrace_copy_tags(struct task_struct *child, long request,
47*4882a593Smuzhiyun 			 unsigned long addr, unsigned long data);
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun #else /* CONFIG_ARM64_MTE */
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun /* unused if !CONFIG_ARM64_MTE, silence the compiler */
52*4882a593Smuzhiyun #define PG_mte_tagged	0
53*4882a593Smuzhiyun 
mte_zero_clear_page_tags(void * addr)54*4882a593Smuzhiyun static inline void mte_zero_clear_page_tags(void *addr)
55*4882a593Smuzhiyun {
56*4882a593Smuzhiyun }
mte_sync_tags(pte_t * ptep,pte_t pte)57*4882a593Smuzhiyun static inline void mte_sync_tags(pte_t *ptep, pte_t pte)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun }
mte_copy_page_tags(void * kto,const void * kfrom)60*4882a593Smuzhiyun static inline void mte_copy_page_tags(void *kto, const void *kfrom)
61*4882a593Smuzhiyun {
62*4882a593Smuzhiyun }
mte_thread_init_user(void)63*4882a593Smuzhiyun static inline void mte_thread_init_user(void)
64*4882a593Smuzhiyun {
65*4882a593Smuzhiyun }
mte_thread_switch(struct task_struct * next)66*4882a593Smuzhiyun static inline void mte_thread_switch(struct task_struct *next)
67*4882a593Smuzhiyun {
68*4882a593Smuzhiyun }
mte_suspend_enter(void)69*4882a593Smuzhiyun static inline void mte_suspend_enter(void)
70*4882a593Smuzhiyun {
71*4882a593Smuzhiyun }
set_mte_ctrl(struct task_struct * task,unsigned long arg)72*4882a593Smuzhiyun static inline long set_mte_ctrl(struct task_struct *task, unsigned long arg)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun 	return 0;
75*4882a593Smuzhiyun }
get_mte_ctrl(struct task_struct * task)76*4882a593Smuzhiyun static inline long get_mte_ctrl(struct task_struct *task)
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun 	return 0;
79*4882a593Smuzhiyun }
mte_ptrace_copy_tags(struct task_struct * child,long request,unsigned long addr,unsigned long data)80*4882a593Smuzhiyun static inline int mte_ptrace_copy_tags(struct task_struct *child,
81*4882a593Smuzhiyun 				       long request, unsigned long addr,
82*4882a593Smuzhiyun 				       unsigned long data)
83*4882a593Smuzhiyun {
84*4882a593Smuzhiyun 	return -EIO;
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun #endif /* CONFIG_ARM64_MTE */
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun #ifdef CONFIG_KASAN_HW_TAGS
90*4882a593Smuzhiyun /* Whether the MTE asynchronous mode is enabled. */
91*4882a593Smuzhiyun DECLARE_STATIC_KEY_FALSE(mte_async_mode);
92*4882a593Smuzhiyun 
system_uses_mte_async_mode(void)93*4882a593Smuzhiyun static inline bool system_uses_mte_async_mode(void)
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun 	return static_branch_unlikely(&mte_async_mode);
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun void mte_check_tfsr_el1(void);
99*4882a593Smuzhiyun 
mte_check_tfsr_entry(void)100*4882a593Smuzhiyun static inline void mte_check_tfsr_entry(void)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun 	if (!system_supports_mte())
103*4882a593Smuzhiyun 		return;
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	mte_check_tfsr_el1();
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun 
mte_check_tfsr_exit(void)108*4882a593Smuzhiyun static inline void mte_check_tfsr_exit(void)
109*4882a593Smuzhiyun {
110*4882a593Smuzhiyun 	if (!system_supports_mte())
111*4882a593Smuzhiyun 		return;
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 	/*
114*4882a593Smuzhiyun 	 * The asynchronous faults are sync'ed automatically with
115*4882a593Smuzhiyun 	 * TFSR_EL1 on kernel entry but for exit an explicit dsb()
116*4882a593Smuzhiyun 	 * is required.
117*4882a593Smuzhiyun 	 */
118*4882a593Smuzhiyun 	dsb(nsh);
119*4882a593Smuzhiyun 	isb();
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	mte_check_tfsr_el1();
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun #else
system_uses_mte_async_mode(void)124*4882a593Smuzhiyun static inline bool system_uses_mte_async_mode(void)
125*4882a593Smuzhiyun {
126*4882a593Smuzhiyun 	return false;
127*4882a593Smuzhiyun }
mte_check_tfsr_el1(void)128*4882a593Smuzhiyun static inline void mte_check_tfsr_el1(void)
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun }
mte_check_tfsr_entry(void)131*4882a593Smuzhiyun static inline void mte_check_tfsr_entry(void)
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun }
mte_check_tfsr_exit(void)134*4882a593Smuzhiyun static inline void mte_check_tfsr_exit(void)
135*4882a593Smuzhiyun {
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun #endif /* CONFIG_KASAN_HW_TAGS */
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun #endif /* __ASSEMBLY__ */
140*4882a593Smuzhiyun #endif /* __ASM_MTE_H  */
141