xref: /linux/include/linux/page_table_check.h (revision 5bd2c0650a9030007af5c2cf2a01dccdc67a6991)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 
3 /*
4  * Copyright (c) 2021, Google LLC.
5  * Pasha Tatashin <pasha.tatashin@soleen.com>
6  */
7 #ifndef __LINUX_PAGE_TABLE_CHECK_H
8 #define __LINUX_PAGE_TABLE_CHECK_H
9 
10 #ifdef CONFIG_PAGE_TABLE_CHECK
11 #include <linux/jump_label.h>
12 
13 extern struct static_key_true page_table_check_disabled;
14 extern struct page_ext_operations page_table_check_ops;
15 
16 void __page_table_check_zero(struct page *page, unsigned int order);
17 void __page_table_check_pte_clear(struct mm_struct *mm, unsigned long addr,
18 				  pte_t pte);
19 void __page_table_check_pmd_clear(struct mm_struct *mm, unsigned long addr,
20 				  pmd_t pmd);
21 void __page_table_check_pud_clear(struct mm_struct *mm, unsigned long addr,
22 				  pud_t pud);
23 void __page_table_check_ptes_set(struct mm_struct *mm, unsigned long addr,
24 		pte_t *ptep, pte_t pte, unsigned int nr);
25 void __page_table_check_pmds_set(struct mm_struct *mm, unsigned long addr,
26 		pmd_t *pmdp, pmd_t pmd, unsigned int nr);
27 void __page_table_check_puds_set(struct mm_struct *mm, unsigned long addr,
28 		pud_t *pudp, pud_t pud, unsigned int nr);
29 void __page_table_check_pte_clear_range(struct mm_struct *mm,
30 					unsigned long addr,
31 					pmd_t pmd);
32 
33 static inline void page_table_check_alloc(struct page *page, unsigned int order)
34 {
35 	if (static_branch_likely(&page_table_check_disabled))
36 		return;
37 
38 	__page_table_check_zero(page, order);
39 }
40 
41 static inline void page_table_check_free(struct page *page, unsigned int order)
42 {
43 	if (static_branch_likely(&page_table_check_disabled))
44 		return;
45 
46 	__page_table_check_zero(page, order);
47 }
48 
49 static inline void page_table_check_pte_clear(struct mm_struct *mm,
50 					      unsigned long addr, pte_t pte)
51 {
52 	if (static_branch_likely(&page_table_check_disabled))
53 		return;
54 
55 	__page_table_check_pte_clear(mm, addr, pte);
56 }
57 
58 static inline void page_table_check_pmd_clear(struct mm_struct *mm,
59 					      unsigned long addr, pmd_t pmd)
60 {
61 	if (static_branch_likely(&page_table_check_disabled))
62 		return;
63 
64 	__page_table_check_pmd_clear(mm, addr, pmd);
65 }
66 
67 static inline void page_table_check_pud_clear(struct mm_struct *mm,
68 					      unsigned long addr, pud_t pud)
69 {
70 	if (static_branch_likely(&page_table_check_disabled))
71 		return;
72 
73 	__page_table_check_pud_clear(mm, addr, pud);
74 }
75 
76 static inline void page_table_check_ptes_set(struct mm_struct *mm,
77 					     unsigned long addr, pte_t *ptep,
78 					     pte_t pte, unsigned int nr)
79 {
80 	if (static_branch_likely(&page_table_check_disabled))
81 		return;
82 
83 	__page_table_check_ptes_set(mm, addr, ptep, pte, nr);
84 }
85 
86 static inline void page_table_check_pmds_set(struct mm_struct *mm,
87 		unsigned long addr, pmd_t *pmdp, pmd_t pmd, unsigned int nr)
88 {
89 	if (static_branch_likely(&page_table_check_disabled))
90 		return;
91 
92 	__page_table_check_pmds_set(mm, addr, pmdp, pmd, nr);
93 }
94 
95 static inline void page_table_check_puds_set(struct mm_struct *mm,
96 		unsigned long addr, pud_t *pudp, pud_t pud, unsigned int nr)
97 {
98 	if (static_branch_likely(&page_table_check_disabled))
99 		return;
100 
101 	__page_table_check_puds_set(mm, addr, pudp, pud, nr);
102 }
103 
104 static inline void page_table_check_pte_clear_range(struct mm_struct *mm,
105 						    unsigned long addr,
106 						    pmd_t pmd)
107 {
108 	if (static_branch_likely(&page_table_check_disabled))
109 		return;
110 
111 	__page_table_check_pte_clear_range(mm, addr, pmd);
112 }
113 
114 #else
115 
116 static inline void page_table_check_alloc(struct page *page, unsigned int order)
117 {
118 }
119 
120 static inline void page_table_check_free(struct page *page, unsigned int order)
121 {
122 }
123 
124 static inline void page_table_check_pte_clear(struct mm_struct *mm,
125 					      unsigned long addr, pte_t pte)
126 {
127 }
128 
129 static inline void page_table_check_pmd_clear(struct mm_struct *mm,
130 					      unsigned long addr, pmd_t pmd)
131 {
132 }
133 
134 static inline void page_table_check_pud_clear(struct mm_struct *mm,
135 					      unsigned long addr, pud_t pud)
136 {
137 }
138 
139 static inline void page_table_check_ptes_set(struct mm_struct *mm,
140 					     unsigned long addr, pte_t *ptep,
141 					     pte_t pte, unsigned int nr)
142 {
143 }
144 
145 static inline void page_table_check_pmds_set(struct mm_struct *mm,
146 		unsigned long addr, pmd_t *pmdp, pmd_t pmd, unsigned int nr)
147 {
148 }
149 
150 static inline void page_table_check_puds_set(struct mm_struct *mm,
151 		unsigned long addr, pud_t *pudp, pud_t pud, unsigned int nr)
152 {
153 }
154 
155 static inline void page_table_check_pte_clear_range(struct mm_struct *mm,
156 						    unsigned long addr,
157 						    pmd_t pmd)
158 {
159 }
160 
161 #endif /* CONFIG_PAGE_TABLE_CHECK */
162 
163 #define page_table_check_pmd_set(mm, addr, pmdp, pmd)	page_table_check_pmds_set(mm, addr, pmdp, pmd, 1)
164 #define page_table_check_pud_set(mm, addr, pudp, pud)	page_table_check_puds_set(mm, addr, pudp, pud, 1)
165 
166 #endif /* __LINUX_PAGE_TABLE_CHECK_H */
167