xref: /linux/include/linux/page_table_check.h (revision 47cf96fbe393839b125a9b694a8cfdd3f4216baa)
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, pte_t pte);
18 void __page_table_check_pmd_clear(struct mm_struct *mm, pmd_t pmd);
19 void __page_table_check_pud_clear(struct mm_struct *mm, pud_t pud);
20 void __page_table_check_ptes_set(struct mm_struct *mm, pte_t *ptep, pte_t pte,
21 		unsigned int nr);
22 void __page_table_check_pmds_set(struct mm_struct *mm, pmd_t *pmdp, pmd_t pmd,
23 		unsigned int nr);
24 void __page_table_check_puds_set(struct mm_struct *mm, pud_t *pudp, pud_t pud,
25 		unsigned int nr);
26 void __page_table_check_pte_clear_range(struct mm_struct *mm,
27 					unsigned long addr,
28 					pmd_t pmd);
29 
30 static inline void page_table_check_alloc(struct page *page, unsigned int order)
31 {
32 	if (static_branch_likely(&page_table_check_disabled))
33 		return;
34 
35 	__page_table_check_zero(page, order);
36 }
37 
38 static inline void page_table_check_free(struct page *page, unsigned int order)
39 {
40 	if (static_branch_likely(&page_table_check_disabled))
41 		return;
42 
43 	__page_table_check_zero(page, order);
44 }
45 
46 static inline void page_table_check_pte_clear(struct mm_struct *mm, pte_t pte)
47 {
48 	if (static_branch_likely(&page_table_check_disabled))
49 		return;
50 
51 	__page_table_check_pte_clear(mm, pte);
52 }
53 
54 static inline void page_table_check_pmd_clear(struct mm_struct *mm, pmd_t pmd)
55 {
56 	if (static_branch_likely(&page_table_check_disabled))
57 		return;
58 
59 	__page_table_check_pmd_clear(mm, pmd);
60 }
61 
62 static inline void page_table_check_pud_clear(struct mm_struct *mm, pud_t pud)
63 {
64 	if (static_branch_likely(&page_table_check_disabled))
65 		return;
66 
67 	__page_table_check_pud_clear(mm, pud);
68 }
69 
70 static inline void page_table_check_ptes_set(struct mm_struct *mm,
71 		pte_t *ptep, pte_t pte, unsigned int nr)
72 {
73 	if (static_branch_likely(&page_table_check_disabled))
74 		return;
75 
76 	__page_table_check_ptes_set(mm, ptep, pte, nr);
77 }
78 
79 static inline void page_table_check_pmds_set(struct mm_struct *mm,
80 		pmd_t *pmdp, pmd_t pmd, unsigned int nr)
81 {
82 	if (static_branch_likely(&page_table_check_disabled))
83 		return;
84 
85 	__page_table_check_pmds_set(mm, pmdp, pmd, nr);
86 }
87 
88 static inline void page_table_check_puds_set(struct mm_struct *mm,
89 		pud_t *pudp, pud_t pud, unsigned int nr)
90 {
91 	if (static_branch_likely(&page_table_check_disabled))
92 		return;
93 
94 	__page_table_check_puds_set(mm, pudp, pud, nr);
95 }
96 
97 static inline void page_table_check_pte_clear_range(struct mm_struct *mm,
98 						    unsigned long addr,
99 						    pmd_t pmd)
100 {
101 	if (static_branch_likely(&page_table_check_disabled))
102 		return;
103 
104 	__page_table_check_pte_clear_range(mm, addr, pmd);
105 }
106 
107 #else
108 
109 static inline void page_table_check_alloc(struct page *page, unsigned int order)
110 {
111 }
112 
113 static inline void page_table_check_free(struct page *page, unsigned int order)
114 {
115 }
116 
117 static inline void page_table_check_pte_clear(struct mm_struct *mm, pte_t pte)
118 {
119 }
120 
121 static inline void page_table_check_pmd_clear(struct mm_struct *mm, pmd_t pmd)
122 {
123 }
124 
125 static inline void page_table_check_pud_clear(struct mm_struct *mm, pud_t pud)
126 {
127 }
128 
129 static inline void page_table_check_ptes_set(struct mm_struct *mm,
130 		pte_t *ptep, pte_t pte, unsigned int nr)
131 {
132 }
133 
134 static inline void page_table_check_pmds_set(struct mm_struct *mm,
135 		pmd_t *pmdp, pmd_t pmd, unsigned int nr)
136 {
137 }
138 
139 static inline void page_table_check_puds_set(struct mm_struct *mm,
140 		pud_t *pudp, pud_t pud, unsigned int nr)
141 {
142 }
143 
144 static inline void page_table_check_pte_clear_range(struct mm_struct *mm,
145 						    unsigned long addr,
146 						    pmd_t pmd)
147 {
148 }
149 
150 #endif /* CONFIG_PAGE_TABLE_CHECK */
151 
152 #define page_table_check_pmd_set(mm, pmdp, pmd)	page_table_check_pmds_set(mm, pmdp, pmd, 1)
153 #define page_table_check_pud_set(mm, pudp, pud)	page_table_check_puds_set(mm, pudp, pud, 1)
154 
155 #endif /* __LINUX_PAGE_TABLE_CHECK_H */
156