1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun #ifndef _LINUX_MMU_NOTIFIER_H
3*4882a593Smuzhiyun #define _LINUX_MMU_NOTIFIER_H
4*4882a593Smuzhiyun
5*4882a593Smuzhiyun #include <linux/list.h>
6*4882a593Smuzhiyun #include <linux/spinlock.h>
7*4882a593Smuzhiyun #include <linux/mm_types.h>
8*4882a593Smuzhiyun #include <linux/mmap_lock.h>
9*4882a593Smuzhiyun #include <linux/percpu-rwsem.h>
10*4882a593Smuzhiyun #include <linux/slab.h>
11*4882a593Smuzhiyun #include <linux/srcu.h>
12*4882a593Smuzhiyun #include <linux/interval_tree.h>
13*4882a593Smuzhiyun #include <linux/android_kabi.h>
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun struct mmu_notifier_subscriptions;
16*4882a593Smuzhiyun struct mmu_notifier;
17*4882a593Smuzhiyun struct mmu_notifier_range;
18*4882a593Smuzhiyun struct mmu_interval_notifier;
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun struct mmu_notifier_subscriptions_hdr {
21*4882a593Smuzhiyun bool valid;
22*4882a593Smuzhiyun #ifdef CONFIG_SPECULATIVE_PAGE_FAULT
23*4882a593Smuzhiyun struct percpu_rw_semaphore_atomic *mmu_notifier_lock;
24*4882a593Smuzhiyun #endif
25*4882a593Smuzhiyun };
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun /**
28*4882a593Smuzhiyun * enum mmu_notifier_event - reason for the mmu notifier callback
29*4882a593Smuzhiyun * @MMU_NOTIFY_UNMAP: either munmap() that unmap the range or a mremap() that
30*4882a593Smuzhiyun * move the range
31*4882a593Smuzhiyun *
32*4882a593Smuzhiyun * @MMU_NOTIFY_CLEAR: clear page table entry (many reasons for this like
33*4882a593Smuzhiyun * madvise() or replacing a page by another one, ...).
34*4882a593Smuzhiyun *
35*4882a593Smuzhiyun * @MMU_NOTIFY_PROTECTION_VMA: update is due to protection change for the range
36*4882a593Smuzhiyun * ie using the vma access permission (vm_page_prot) to update the whole range
37*4882a593Smuzhiyun * is enough no need to inspect changes to the CPU page table (mprotect()
38*4882a593Smuzhiyun * syscall)
39*4882a593Smuzhiyun *
40*4882a593Smuzhiyun * @MMU_NOTIFY_PROTECTION_PAGE: update is due to change in read/write flag for
41*4882a593Smuzhiyun * pages in the range so to mirror those changes the user must inspect the CPU
42*4882a593Smuzhiyun * page table (from the end callback).
43*4882a593Smuzhiyun *
44*4882a593Smuzhiyun * @MMU_NOTIFY_SOFT_DIRTY: soft dirty accounting (still same page and same
45*4882a593Smuzhiyun * access flags). User should soft dirty the page in the end callback to make
46*4882a593Smuzhiyun * sure that anyone relying on soft dirtyness catch pages that might be written
47*4882a593Smuzhiyun * through non CPU mappings.
48*4882a593Smuzhiyun *
49*4882a593Smuzhiyun * @MMU_NOTIFY_RELEASE: used during mmu_interval_notifier invalidate to signal
50*4882a593Smuzhiyun * that the mm refcount is zero and the range is no longer accessible.
51*4882a593Smuzhiyun *
52*4882a593Smuzhiyun * @MMU_NOTIFY_MIGRATE: used during migrate_vma_collect() invalidate to signal
53*4882a593Smuzhiyun * a device driver to possibly ignore the invalidation if the
54*4882a593Smuzhiyun * migrate_pgmap_owner field matches the driver's device private pgmap owner.
55*4882a593Smuzhiyun */
56*4882a593Smuzhiyun enum mmu_notifier_event {
57*4882a593Smuzhiyun MMU_NOTIFY_UNMAP = 0,
58*4882a593Smuzhiyun MMU_NOTIFY_CLEAR,
59*4882a593Smuzhiyun MMU_NOTIFY_PROTECTION_VMA,
60*4882a593Smuzhiyun MMU_NOTIFY_PROTECTION_PAGE,
61*4882a593Smuzhiyun MMU_NOTIFY_SOFT_DIRTY,
62*4882a593Smuzhiyun MMU_NOTIFY_RELEASE,
63*4882a593Smuzhiyun MMU_NOTIFY_MIGRATE,
64*4882a593Smuzhiyun };
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun #define MMU_NOTIFIER_RANGE_BLOCKABLE (1 << 0)
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun struct mmu_notifier_ops {
69*4882a593Smuzhiyun /*
70*4882a593Smuzhiyun * Called either by mmu_notifier_unregister or when the mm is
71*4882a593Smuzhiyun * being destroyed by exit_mmap, always before all pages are
72*4882a593Smuzhiyun * freed. This can run concurrently with other mmu notifier
73*4882a593Smuzhiyun * methods (the ones invoked outside the mm context) and it
74*4882a593Smuzhiyun * should tear down all secondary mmu mappings and freeze the
75*4882a593Smuzhiyun * secondary mmu. If this method isn't implemented you've to
76*4882a593Smuzhiyun * be sure that nothing could possibly write to the pages
77*4882a593Smuzhiyun * through the secondary mmu by the time the last thread with
78*4882a593Smuzhiyun * tsk->mm == mm exits.
79*4882a593Smuzhiyun *
80*4882a593Smuzhiyun * As side note: the pages freed after ->release returns could
81*4882a593Smuzhiyun * be immediately reallocated by the gart at an alias physical
82*4882a593Smuzhiyun * address with a different cache model, so if ->release isn't
83*4882a593Smuzhiyun * implemented because all _software_ driven memory accesses
84*4882a593Smuzhiyun * through the secondary mmu are terminated by the time the
85*4882a593Smuzhiyun * last thread of this mm quits, you've also to be sure that
86*4882a593Smuzhiyun * speculative _hardware_ operations can't allocate dirty
87*4882a593Smuzhiyun * cachelines in the cpu that could not be snooped and made
88*4882a593Smuzhiyun * coherent with the other read and write operations happening
89*4882a593Smuzhiyun * through the gart alias address, so leading to memory
90*4882a593Smuzhiyun * corruption.
91*4882a593Smuzhiyun */
92*4882a593Smuzhiyun void (*release)(struct mmu_notifier *subscription,
93*4882a593Smuzhiyun struct mm_struct *mm);
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun /*
96*4882a593Smuzhiyun * clear_flush_young is called after the VM is
97*4882a593Smuzhiyun * test-and-clearing the young/accessed bitflag in the
98*4882a593Smuzhiyun * pte. This way the VM will provide proper aging to the
99*4882a593Smuzhiyun * accesses to the page through the secondary MMUs and not
100*4882a593Smuzhiyun * only to the ones through the Linux pte.
101*4882a593Smuzhiyun * Start-end is necessary in case the secondary MMU is mapping the page
102*4882a593Smuzhiyun * at a smaller granularity than the primary MMU.
103*4882a593Smuzhiyun */
104*4882a593Smuzhiyun int (*clear_flush_young)(struct mmu_notifier *subscription,
105*4882a593Smuzhiyun struct mm_struct *mm,
106*4882a593Smuzhiyun unsigned long start,
107*4882a593Smuzhiyun unsigned long end);
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun /*
110*4882a593Smuzhiyun * clear_young is a lightweight version of clear_flush_young. Like the
111*4882a593Smuzhiyun * latter, it is supposed to test-and-clear the young/accessed bitflag
112*4882a593Smuzhiyun * in the secondary pte, but it may omit flushing the secondary tlb.
113*4882a593Smuzhiyun */
114*4882a593Smuzhiyun int (*clear_young)(struct mmu_notifier *subscription,
115*4882a593Smuzhiyun struct mm_struct *mm,
116*4882a593Smuzhiyun unsigned long start,
117*4882a593Smuzhiyun unsigned long end);
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun /*
120*4882a593Smuzhiyun * test_young is called to check the young/accessed bitflag in
121*4882a593Smuzhiyun * the secondary pte. This is used to know if the page is
122*4882a593Smuzhiyun * frequently used without actually clearing the flag or tearing
123*4882a593Smuzhiyun * down the secondary mapping on the page.
124*4882a593Smuzhiyun */
125*4882a593Smuzhiyun int (*test_young)(struct mmu_notifier *subscription,
126*4882a593Smuzhiyun struct mm_struct *mm,
127*4882a593Smuzhiyun unsigned long address);
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun /*
130*4882a593Smuzhiyun * change_pte is called in cases that pte mapping to page is changed:
131*4882a593Smuzhiyun * for example, when ksm remaps pte to point to a new shared page.
132*4882a593Smuzhiyun */
133*4882a593Smuzhiyun void (*change_pte)(struct mmu_notifier *subscription,
134*4882a593Smuzhiyun struct mm_struct *mm,
135*4882a593Smuzhiyun unsigned long address,
136*4882a593Smuzhiyun pte_t pte);
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun /*
139*4882a593Smuzhiyun * invalidate_range_start() and invalidate_range_end() must be
140*4882a593Smuzhiyun * paired and are called only when the mmap_lock and/or the
141*4882a593Smuzhiyun * locks protecting the reverse maps are held. If the subsystem
142*4882a593Smuzhiyun * can't guarantee that no additional references are taken to
143*4882a593Smuzhiyun * the pages in the range, it has to implement the
144*4882a593Smuzhiyun * invalidate_range() notifier to remove any references taken
145*4882a593Smuzhiyun * after invalidate_range_start().
146*4882a593Smuzhiyun *
147*4882a593Smuzhiyun * Invalidation of multiple concurrent ranges may be
148*4882a593Smuzhiyun * optionally permitted by the driver. Either way the
149*4882a593Smuzhiyun * establishment of sptes is forbidden in the range passed to
150*4882a593Smuzhiyun * invalidate_range_begin/end for the whole duration of the
151*4882a593Smuzhiyun * invalidate_range_begin/end critical section.
152*4882a593Smuzhiyun *
153*4882a593Smuzhiyun * invalidate_range_start() is called when all pages in the
154*4882a593Smuzhiyun * range are still mapped and have at least a refcount of one.
155*4882a593Smuzhiyun *
156*4882a593Smuzhiyun * invalidate_range_end() is called when all pages in the
157*4882a593Smuzhiyun * range have been unmapped and the pages have been freed by
158*4882a593Smuzhiyun * the VM.
159*4882a593Smuzhiyun *
160*4882a593Smuzhiyun * The VM will remove the page table entries and potentially
161*4882a593Smuzhiyun * the page between invalidate_range_start() and
162*4882a593Smuzhiyun * invalidate_range_end(). If the page must not be freed
163*4882a593Smuzhiyun * because of pending I/O or other circumstances then the
164*4882a593Smuzhiyun * invalidate_range_start() callback (or the initial mapping
165*4882a593Smuzhiyun * by the driver) must make sure that the refcount is kept
166*4882a593Smuzhiyun * elevated.
167*4882a593Smuzhiyun *
168*4882a593Smuzhiyun * If the driver increases the refcount when the pages are
169*4882a593Smuzhiyun * initially mapped into an address space then either
170*4882a593Smuzhiyun * invalidate_range_start() or invalidate_range_end() may
171*4882a593Smuzhiyun * decrease the refcount. If the refcount is decreased on
172*4882a593Smuzhiyun * invalidate_range_start() then the VM can free pages as page
173*4882a593Smuzhiyun * table entries are removed. If the refcount is only
174*4882a593Smuzhiyun * droppped on invalidate_range_end() then the driver itself
175*4882a593Smuzhiyun * will drop the last refcount but it must take care to flush
176*4882a593Smuzhiyun * any secondary tlb before doing the final free on the
177*4882a593Smuzhiyun * page. Pages will no longer be referenced by the linux
178*4882a593Smuzhiyun * address space but may still be referenced by sptes until
179*4882a593Smuzhiyun * the last refcount is dropped.
180*4882a593Smuzhiyun *
181*4882a593Smuzhiyun * If blockable argument is set to false then the callback cannot
182*4882a593Smuzhiyun * sleep and has to return with -EAGAIN if sleeping would be required.
183*4882a593Smuzhiyun * 0 should be returned otherwise. Please note that notifiers that can
184*4882a593Smuzhiyun * fail invalidate_range_start are not allowed to implement
185*4882a593Smuzhiyun * invalidate_range_end, as there is no mechanism for informing the
186*4882a593Smuzhiyun * notifier that its start failed.
187*4882a593Smuzhiyun */
188*4882a593Smuzhiyun int (*invalidate_range_start)(struct mmu_notifier *subscription,
189*4882a593Smuzhiyun const struct mmu_notifier_range *range);
190*4882a593Smuzhiyun void (*invalidate_range_end)(struct mmu_notifier *subscription,
191*4882a593Smuzhiyun const struct mmu_notifier_range *range);
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun /*
194*4882a593Smuzhiyun * invalidate_range() is either called between
195*4882a593Smuzhiyun * invalidate_range_start() and invalidate_range_end() when the
196*4882a593Smuzhiyun * VM has to free pages that where unmapped, but before the
197*4882a593Smuzhiyun * pages are actually freed, or outside of _start()/_end() when
198*4882a593Smuzhiyun * a (remote) TLB is necessary.
199*4882a593Smuzhiyun *
200*4882a593Smuzhiyun * If invalidate_range() is used to manage a non-CPU TLB with
201*4882a593Smuzhiyun * shared page-tables, it not necessary to implement the
202*4882a593Smuzhiyun * invalidate_range_start()/end() notifiers, as
203*4882a593Smuzhiyun * invalidate_range() alread catches the points in time when an
204*4882a593Smuzhiyun * external TLB range needs to be flushed. For more in depth
205*4882a593Smuzhiyun * discussion on this see Documentation/vm/mmu_notifier.rst
206*4882a593Smuzhiyun *
207*4882a593Smuzhiyun * Note that this function might be called with just a sub-range
208*4882a593Smuzhiyun * of what was passed to invalidate_range_start()/end(), if
209*4882a593Smuzhiyun * called between those functions.
210*4882a593Smuzhiyun */
211*4882a593Smuzhiyun void (*invalidate_range)(struct mmu_notifier *subscription,
212*4882a593Smuzhiyun struct mm_struct *mm,
213*4882a593Smuzhiyun unsigned long start,
214*4882a593Smuzhiyun unsigned long end);
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun /*
217*4882a593Smuzhiyun * These callbacks are used with the get/put interface to manage the
218*4882a593Smuzhiyun * lifetime of the mmu_notifier memory. alloc_notifier() returns a new
219*4882a593Smuzhiyun * notifier for use with the mm.
220*4882a593Smuzhiyun *
221*4882a593Smuzhiyun * free_notifier() is only called after the mmu_notifier has been
222*4882a593Smuzhiyun * fully put, calls to any ops callback are prevented and no ops
223*4882a593Smuzhiyun * callbacks are currently running. It is called from a SRCU callback
224*4882a593Smuzhiyun * and cannot sleep.
225*4882a593Smuzhiyun */
226*4882a593Smuzhiyun struct mmu_notifier *(*alloc_notifier)(struct mm_struct *mm);
227*4882a593Smuzhiyun void (*free_notifier)(struct mmu_notifier *subscription);
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun ANDROID_KABI_RESERVE(1);
230*4882a593Smuzhiyun ANDROID_KABI_RESERVE(2);
231*4882a593Smuzhiyun ANDROID_KABI_RESERVE(3);
232*4882a593Smuzhiyun ANDROID_KABI_RESERVE(4);
233*4882a593Smuzhiyun };
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun /*
236*4882a593Smuzhiyun * The notifier chains are protected by mmap_lock and/or the reverse map
237*4882a593Smuzhiyun * semaphores. Notifier chains are only changed when all reverse maps and
238*4882a593Smuzhiyun * the mmap_lock locks are taken.
239*4882a593Smuzhiyun *
240*4882a593Smuzhiyun * Therefore notifier chains can only be traversed when either
241*4882a593Smuzhiyun *
242*4882a593Smuzhiyun * 1. mmap_lock is held.
243*4882a593Smuzhiyun * 2. One of the reverse map locks is held (i_mmap_rwsem or anon_vma->rwsem).
244*4882a593Smuzhiyun * 3. No other concurrent thread can access the list (release)
245*4882a593Smuzhiyun */
246*4882a593Smuzhiyun struct mmu_notifier {
247*4882a593Smuzhiyun struct hlist_node hlist;
248*4882a593Smuzhiyun const struct mmu_notifier_ops *ops;
249*4882a593Smuzhiyun struct mm_struct *mm;
250*4882a593Smuzhiyun struct rcu_head rcu;
251*4882a593Smuzhiyun unsigned int users;
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun ANDROID_KABI_RESERVE(1);
254*4882a593Smuzhiyun ANDROID_KABI_RESERVE(2);
255*4882a593Smuzhiyun };
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun /**
258*4882a593Smuzhiyun * struct mmu_interval_notifier_ops
259*4882a593Smuzhiyun * @invalidate: Upon return the caller must stop using any SPTEs within this
260*4882a593Smuzhiyun * range. This function can sleep. Return false only if sleeping
261*4882a593Smuzhiyun * was required but mmu_notifier_range_blockable(range) is false.
262*4882a593Smuzhiyun */
263*4882a593Smuzhiyun struct mmu_interval_notifier_ops {
264*4882a593Smuzhiyun bool (*invalidate)(struct mmu_interval_notifier *interval_sub,
265*4882a593Smuzhiyun const struct mmu_notifier_range *range,
266*4882a593Smuzhiyun unsigned long cur_seq);
267*4882a593Smuzhiyun };
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun struct mmu_interval_notifier {
270*4882a593Smuzhiyun struct interval_tree_node interval_tree;
271*4882a593Smuzhiyun const struct mmu_interval_notifier_ops *ops;
272*4882a593Smuzhiyun struct mm_struct *mm;
273*4882a593Smuzhiyun struct hlist_node deferred_item;
274*4882a593Smuzhiyun unsigned long invalidate_seq;
275*4882a593Smuzhiyun };
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun #ifdef CONFIG_MMU_NOTIFIER
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun #ifdef CONFIG_LOCKDEP
280*4882a593Smuzhiyun extern struct lockdep_map __mmu_notifier_invalidate_range_start_map;
281*4882a593Smuzhiyun #endif
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun struct mmu_notifier_range {
284*4882a593Smuzhiyun struct vm_area_struct *vma;
285*4882a593Smuzhiyun struct mm_struct *mm;
286*4882a593Smuzhiyun unsigned long start;
287*4882a593Smuzhiyun unsigned long end;
288*4882a593Smuzhiyun unsigned flags;
289*4882a593Smuzhiyun enum mmu_notifier_event event;
290*4882a593Smuzhiyun void *migrate_pgmap_owner;
291*4882a593Smuzhiyun };
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun static inline
get_notifier_subscriptions_hdr(struct mm_struct * mm)294*4882a593Smuzhiyun struct mmu_notifier_subscriptions_hdr *get_notifier_subscriptions_hdr(
295*4882a593Smuzhiyun struct mm_struct *mm)
296*4882a593Smuzhiyun {
297*4882a593Smuzhiyun /*
298*4882a593Smuzhiyun * container_of() can't be used here because mmu_notifier_subscriptions
299*4882a593Smuzhiyun * struct should be kept invisible to mm_struct, otherwise it
300*4882a593Smuzhiyun * introduces KMI CRC breakage. Therefore the callers don't know what
301*4882a593Smuzhiyun * members struct mmu_notifier_subscriptions contains and can't call
302*4882a593Smuzhiyun * container_of(), which requires a member name.
303*4882a593Smuzhiyun *
304*4882a593Smuzhiyun * WARNING: For this typecasting to work, mmu_notifier_subscriptions_hdr
305*4882a593Smuzhiyun * should be the first member of struct mmu_notifier_subscriptions.
306*4882a593Smuzhiyun */
307*4882a593Smuzhiyun return (struct mmu_notifier_subscriptions_hdr *)mm->notifier_subscriptions;
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun
mm_has_notifiers(struct mm_struct * mm)310*4882a593Smuzhiyun static inline int mm_has_notifiers(struct mm_struct *mm)
311*4882a593Smuzhiyun {
312*4882a593Smuzhiyun #ifdef CONFIG_SPECULATIVE_PAGE_FAULT
313*4882a593Smuzhiyun return unlikely(get_notifier_subscriptions_hdr(mm)->valid);
314*4882a593Smuzhiyun #else
315*4882a593Smuzhiyun return unlikely(mm->notifier_subscriptions);
316*4882a593Smuzhiyun #endif
317*4882a593Smuzhiyun }
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun struct mmu_notifier *mmu_notifier_get_locked(const struct mmu_notifier_ops *ops,
320*4882a593Smuzhiyun struct mm_struct *mm);
321*4882a593Smuzhiyun static inline struct mmu_notifier *
mmu_notifier_get(const struct mmu_notifier_ops * ops,struct mm_struct * mm)322*4882a593Smuzhiyun mmu_notifier_get(const struct mmu_notifier_ops *ops, struct mm_struct *mm)
323*4882a593Smuzhiyun {
324*4882a593Smuzhiyun struct mmu_notifier *ret;
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun mmap_write_lock(mm);
327*4882a593Smuzhiyun ret = mmu_notifier_get_locked(ops, mm);
328*4882a593Smuzhiyun mmap_write_unlock(mm);
329*4882a593Smuzhiyun return ret;
330*4882a593Smuzhiyun }
331*4882a593Smuzhiyun void mmu_notifier_put(struct mmu_notifier *subscription);
332*4882a593Smuzhiyun void mmu_notifier_synchronize(void);
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun extern int mmu_notifier_register(struct mmu_notifier *subscription,
335*4882a593Smuzhiyun struct mm_struct *mm);
336*4882a593Smuzhiyun extern int __mmu_notifier_register(struct mmu_notifier *subscription,
337*4882a593Smuzhiyun struct mm_struct *mm);
338*4882a593Smuzhiyun extern void mmu_notifier_unregister(struct mmu_notifier *subscription,
339*4882a593Smuzhiyun struct mm_struct *mm);
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun unsigned long
342*4882a593Smuzhiyun mmu_interval_read_begin(struct mmu_interval_notifier *interval_sub);
343*4882a593Smuzhiyun int mmu_interval_notifier_insert(struct mmu_interval_notifier *interval_sub,
344*4882a593Smuzhiyun struct mm_struct *mm, unsigned long start,
345*4882a593Smuzhiyun unsigned long length,
346*4882a593Smuzhiyun const struct mmu_interval_notifier_ops *ops);
347*4882a593Smuzhiyun int mmu_interval_notifier_insert_locked(
348*4882a593Smuzhiyun struct mmu_interval_notifier *interval_sub, struct mm_struct *mm,
349*4882a593Smuzhiyun unsigned long start, unsigned long length,
350*4882a593Smuzhiyun const struct mmu_interval_notifier_ops *ops);
351*4882a593Smuzhiyun void mmu_interval_notifier_remove(struct mmu_interval_notifier *interval_sub);
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun /**
354*4882a593Smuzhiyun * mmu_interval_set_seq - Save the invalidation sequence
355*4882a593Smuzhiyun * @interval_sub - The subscription passed to invalidate
356*4882a593Smuzhiyun * @cur_seq - The cur_seq passed to the invalidate() callback
357*4882a593Smuzhiyun *
358*4882a593Smuzhiyun * This must be called unconditionally from the invalidate callback of a
359*4882a593Smuzhiyun * struct mmu_interval_notifier_ops under the same lock that is used to call
360*4882a593Smuzhiyun * mmu_interval_read_retry(). It updates the sequence number for later use by
361*4882a593Smuzhiyun * mmu_interval_read_retry(). The provided cur_seq will always be odd.
362*4882a593Smuzhiyun *
363*4882a593Smuzhiyun * If the caller does not call mmu_interval_read_begin() or
364*4882a593Smuzhiyun * mmu_interval_read_retry() then this call is not required.
365*4882a593Smuzhiyun */
366*4882a593Smuzhiyun static inline void
mmu_interval_set_seq(struct mmu_interval_notifier * interval_sub,unsigned long cur_seq)367*4882a593Smuzhiyun mmu_interval_set_seq(struct mmu_interval_notifier *interval_sub,
368*4882a593Smuzhiyun unsigned long cur_seq)
369*4882a593Smuzhiyun {
370*4882a593Smuzhiyun WRITE_ONCE(interval_sub->invalidate_seq, cur_seq);
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun /**
374*4882a593Smuzhiyun * mmu_interval_read_retry - End a read side critical section against a VA range
375*4882a593Smuzhiyun * interval_sub: The subscription
376*4882a593Smuzhiyun * seq: The return of the paired mmu_interval_read_begin()
377*4882a593Smuzhiyun *
378*4882a593Smuzhiyun * This MUST be called under a user provided lock that is also held
379*4882a593Smuzhiyun * unconditionally by op->invalidate() when it calls mmu_interval_set_seq().
380*4882a593Smuzhiyun *
381*4882a593Smuzhiyun * Each call should be paired with a single mmu_interval_read_begin() and
382*4882a593Smuzhiyun * should be used to conclude the read side.
383*4882a593Smuzhiyun *
384*4882a593Smuzhiyun * Returns true if an invalidation collided with this critical section, and
385*4882a593Smuzhiyun * the caller should retry.
386*4882a593Smuzhiyun */
387*4882a593Smuzhiyun static inline bool
mmu_interval_read_retry(struct mmu_interval_notifier * interval_sub,unsigned long seq)388*4882a593Smuzhiyun mmu_interval_read_retry(struct mmu_interval_notifier *interval_sub,
389*4882a593Smuzhiyun unsigned long seq)
390*4882a593Smuzhiyun {
391*4882a593Smuzhiyun return interval_sub->invalidate_seq != seq;
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun /**
395*4882a593Smuzhiyun * mmu_interval_check_retry - Test if a collision has occurred
396*4882a593Smuzhiyun * interval_sub: The subscription
397*4882a593Smuzhiyun * seq: The return of the matching mmu_interval_read_begin()
398*4882a593Smuzhiyun *
399*4882a593Smuzhiyun * This can be used in the critical section between mmu_interval_read_begin()
400*4882a593Smuzhiyun * and mmu_interval_read_retry(). A return of true indicates an invalidation
401*4882a593Smuzhiyun * has collided with this critical region and a future
402*4882a593Smuzhiyun * mmu_interval_read_retry() will return true.
403*4882a593Smuzhiyun *
404*4882a593Smuzhiyun * False is not reliable and only suggests a collision may not have
405*4882a593Smuzhiyun * occured. It can be called many times and does not have to hold the user
406*4882a593Smuzhiyun * provided lock.
407*4882a593Smuzhiyun *
408*4882a593Smuzhiyun * This call can be used as part of loops and other expensive operations to
409*4882a593Smuzhiyun * expedite a retry.
410*4882a593Smuzhiyun */
411*4882a593Smuzhiyun static inline bool
mmu_interval_check_retry(struct mmu_interval_notifier * interval_sub,unsigned long seq)412*4882a593Smuzhiyun mmu_interval_check_retry(struct mmu_interval_notifier *interval_sub,
413*4882a593Smuzhiyun unsigned long seq)
414*4882a593Smuzhiyun {
415*4882a593Smuzhiyun /* Pairs with the WRITE_ONCE in mmu_interval_set_seq() */
416*4882a593Smuzhiyun return READ_ONCE(interval_sub->invalidate_seq) != seq;
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun extern void __mmu_notifier_subscriptions_destroy(struct mm_struct *mm);
420*4882a593Smuzhiyun extern void __mmu_notifier_release(struct mm_struct *mm);
421*4882a593Smuzhiyun extern int __mmu_notifier_clear_flush_young(struct mm_struct *mm,
422*4882a593Smuzhiyun unsigned long start,
423*4882a593Smuzhiyun unsigned long end);
424*4882a593Smuzhiyun extern int __mmu_notifier_clear_young(struct mm_struct *mm,
425*4882a593Smuzhiyun unsigned long start,
426*4882a593Smuzhiyun unsigned long end);
427*4882a593Smuzhiyun extern int __mmu_notifier_test_young(struct mm_struct *mm,
428*4882a593Smuzhiyun unsigned long address);
429*4882a593Smuzhiyun extern void __mmu_notifier_change_pte(struct mm_struct *mm,
430*4882a593Smuzhiyun unsigned long address, pte_t pte);
431*4882a593Smuzhiyun extern int __mmu_notifier_invalidate_range_start(struct mmu_notifier_range *r);
432*4882a593Smuzhiyun extern void __mmu_notifier_invalidate_range_end(struct mmu_notifier_range *r,
433*4882a593Smuzhiyun bool only_end);
434*4882a593Smuzhiyun extern void __mmu_notifier_invalidate_range(struct mm_struct *mm,
435*4882a593Smuzhiyun unsigned long start, unsigned long end);
436*4882a593Smuzhiyun extern bool
437*4882a593Smuzhiyun mmu_notifier_range_update_to_read_only(const struct mmu_notifier_range *range);
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun static inline bool
mmu_notifier_range_blockable(const struct mmu_notifier_range * range)440*4882a593Smuzhiyun mmu_notifier_range_blockable(const struct mmu_notifier_range *range)
441*4882a593Smuzhiyun {
442*4882a593Smuzhiyun return (range->flags & MMU_NOTIFIER_RANGE_BLOCKABLE);
443*4882a593Smuzhiyun }
444*4882a593Smuzhiyun
mmu_notifier_release(struct mm_struct * mm)445*4882a593Smuzhiyun static inline void mmu_notifier_release(struct mm_struct *mm)
446*4882a593Smuzhiyun {
447*4882a593Smuzhiyun if (mm_has_notifiers(mm))
448*4882a593Smuzhiyun __mmu_notifier_release(mm);
449*4882a593Smuzhiyun }
450*4882a593Smuzhiyun
mmu_notifier_clear_flush_young(struct mm_struct * mm,unsigned long start,unsigned long end)451*4882a593Smuzhiyun static inline int mmu_notifier_clear_flush_young(struct mm_struct *mm,
452*4882a593Smuzhiyun unsigned long start,
453*4882a593Smuzhiyun unsigned long end)
454*4882a593Smuzhiyun {
455*4882a593Smuzhiyun if (mm_has_notifiers(mm))
456*4882a593Smuzhiyun return __mmu_notifier_clear_flush_young(mm, start, end);
457*4882a593Smuzhiyun return 0;
458*4882a593Smuzhiyun }
459*4882a593Smuzhiyun
mmu_notifier_clear_young(struct mm_struct * mm,unsigned long start,unsigned long end)460*4882a593Smuzhiyun static inline int mmu_notifier_clear_young(struct mm_struct *mm,
461*4882a593Smuzhiyun unsigned long start,
462*4882a593Smuzhiyun unsigned long end)
463*4882a593Smuzhiyun {
464*4882a593Smuzhiyun if (mm_has_notifiers(mm))
465*4882a593Smuzhiyun return __mmu_notifier_clear_young(mm, start, end);
466*4882a593Smuzhiyun return 0;
467*4882a593Smuzhiyun }
468*4882a593Smuzhiyun
mmu_notifier_test_young(struct mm_struct * mm,unsigned long address)469*4882a593Smuzhiyun static inline int mmu_notifier_test_young(struct mm_struct *mm,
470*4882a593Smuzhiyun unsigned long address)
471*4882a593Smuzhiyun {
472*4882a593Smuzhiyun if (mm_has_notifiers(mm))
473*4882a593Smuzhiyun return __mmu_notifier_test_young(mm, address);
474*4882a593Smuzhiyun return 0;
475*4882a593Smuzhiyun }
476*4882a593Smuzhiyun
mmu_notifier_change_pte(struct mm_struct * mm,unsigned long address,pte_t pte)477*4882a593Smuzhiyun static inline void mmu_notifier_change_pte(struct mm_struct *mm,
478*4882a593Smuzhiyun unsigned long address, pte_t pte)
479*4882a593Smuzhiyun {
480*4882a593Smuzhiyun if (mm_has_notifiers(mm))
481*4882a593Smuzhiyun __mmu_notifier_change_pte(mm, address, pte);
482*4882a593Smuzhiyun }
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun static inline void
mmu_notifier_invalidate_range_start(struct mmu_notifier_range * range)485*4882a593Smuzhiyun mmu_notifier_invalidate_range_start(struct mmu_notifier_range *range)
486*4882a593Smuzhiyun {
487*4882a593Smuzhiyun might_sleep();
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun lock_map_acquire(&__mmu_notifier_invalidate_range_start_map);
490*4882a593Smuzhiyun if (mm_has_notifiers(range->mm)) {
491*4882a593Smuzhiyun range->flags |= MMU_NOTIFIER_RANGE_BLOCKABLE;
492*4882a593Smuzhiyun __mmu_notifier_invalidate_range_start(range);
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun lock_map_release(&__mmu_notifier_invalidate_range_start_map);
495*4882a593Smuzhiyun }
496*4882a593Smuzhiyun
497*4882a593Smuzhiyun static inline int
mmu_notifier_invalidate_range_start_nonblock(struct mmu_notifier_range * range)498*4882a593Smuzhiyun mmu_notifier_invalidate_range_start_nonblock(struct mmu_notifier_range *range)
499*4882a593Smuzhiyun {
500*4882a593Smuzhiyun int ret = 0;
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun lock_map_acquire(&__mmu_notifier_invalidate_range_start_map);
503*4882a593Smuzhiyun if (mm_has_notifiers(range->mm)) {
504*4882a593Smuzhiyun range->flags &= ~MMU_NOTIFIER_RANGE_BLOCKABLE;
505*4882a593Smuzhiyun ret = __mmu_notifier_invalidate_range_start(range);
506*4882a593Smuzhiyun }
507*4882a593Smuzhiyun lock_map_release(&__mmu_notifier_invalidate_range_start_map);
508*4882a593Smuzhiyun return ret;
509*4882a593Smuzhiyun }
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun static inline void
mmu_notifier_invalidate_range_end(struct mmu_notifier_range * range)512*4882a593Smuzhiyun mmu_notifier_invalidate_range_end(struct mmu_notifier_range *range)
513*4882a593Smuzhiyun {
514*4882a593Smuzhiyun if (mmu_notifier_range_blockable(range))
515*4882a593Smuzhiyun might_sleep();
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun if (mm_has_notifiers(range->mm))
518*4882a593Smuzhiyun __mmu_notifier_invalidate_range_end(range, false);
519*4882a593Smuzhiyun }
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun static inline void
mmu_notifier_invalidate_range_only_end(struct mmu_notifier_range * range)522*4882a593Smuzhiyun mmu_notifier_invalidate_range_only_end(struct mmu_notifier_range *range)
523*4882a593Smuzhiyun {
524*4882a593Smuzhiyun if (mm_has_notifiers(range->mm))
525*4882a593Smuzhiyun __mmu_notifier_invalidate_range_end(range, true);
526*4882a593Smuzhiyun }
527*4882a593Smuzhiyun
mmu_notifier_invalidate_range(struct mm_struct * mm,unsigned long start,unsigned long end)528*4882a593Smuzhiyun static inline void mmu_notifier_invalidate_range(struct mm_struct *mm,
529*4882a593Smuzhiyun unsigned long start, unsigned long end)
530*4882a593Smuzhiyun {
531*4882a593Smuzhiyun if (mm_has_notifiers(mm))
532*4882a593Smuzhiyun __mmu_notifier_invalidate_range(mm, start, end);
533*4882a593Smuzhiyun }
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun #ifdef CONFIG_SPECULATIVE_PAGE_FAULT
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun extern bool mmu_notifier_subscriptions_init(struct mm_struct *mm);
538*4882a593Smuzhiyun extern void mmu_notifier_subscriptions_destroy(struct mm_struct *mm);
539*4882a593Smuzhiyun
mmu_notifier_trylock(struct mm_struct * mm)540*4882a593Smuzhiyun static inline bool mmu_notifier_trylock(struct mm_struct *mm)
541*4882a593Smuzhiyun {
542*4882a593Smuzhiyun return percpu_down_read_trylock(
543*4882a593Smuzhiyun &get_notifier_subscriptions_hdr(mm)->mmu_notifier_lock->rw_sem);
544*4882a593Smuzhiyun }
545*4882a593Smuzhiyun
mmu_notifier_unlock(struct mm_struct * mm)546*4882a593Smuzhiyun static inline void mmu_notifier_unlock(struct mm_struct *mm)
547*4882a593Smuzhiyun {
548*4882a593Smuzhiyun percpu_up_read(
549*4882a593Smuzhiyun &get_notifier_subscriptions_hdr(mm)->mmu_notifier_lock->rw_sem);
550*4882a593Smuzhiyun }
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun #else /* CONFIG_SPECULATIVE_PAGE_FAULT */
553*4882a593Smuzhiyun
mmu_notifier_subscriptions_init(struct mm_struct * mm)554*4882a593Smuzhiyun static inline bool mmu_notifier_subscriptions_init(struct mm_struct *mm)
555*4882a593Smuzhiyun {
556*4882a593Smuzhiyun mm->notifier_subscriptions = NULL;
557*4882a593Smuzhiyun return true;
558*4882a593Smuzhiyun }
559*4882a593Smuzhiyun
mmu_notifier_subscriptions_destroy(struct mm_struct * mm)560*4882a593Smuzhiyun static inline void mmu_notifier_subscriptions_destroy(struct mm_struct *mm)
561*4882a593Smuzhiyun {
562*4882a593Smuzhiyun if (mm_has_notifiers(mm))
563*4882a593Smuzhiyun __mmu_notifier_subscriptions_destroy(mm);
564*4882a593Smuzhiyun }
565*4882a593Smuzhiyun
mmu_notifier_trylock(struct mm_struct * mm)566*4882a593Smuzhiyun static inline bool mmu_notifier_trylock(struct mm_struct *mm)
567*4882a593Smuzhiyun {
568*4882a593Smuzhiyun return true;
569*4882a593Smuzhiyun }
570*4882a593Smuzhiyun
mmu_notifier_unlock(struct mm_struct * mm)571*4882a593Smuzhiyun static inline void mmu_notifier_unlock(struct mm_struct *mm)
572*4882a593Smuzhiyun {
573*4882a593Smuzhiyun }
574*4882a593Smuzhiyun
575*4882a593Smuzhiyun #endif /* CONFIG_SPECULATIVE_PAGE_FAULT */
576*4882a593Smuzhiyun
mmu_notifier_range_init(struct mmu_notifier_range * range,enum mmu_notifier_event event,unsigned flags,struct vm_area_struct * vma,struct mm_struct * mm,unsigned long start,unsigned long end)577*4882a593Smuzhiyun static inline void mmu_notifier_range_init(struct mmu_notifier_range *range,
578*4882a593Smuzhiyun enum mmu_notifier_event event,
579*4882a593Smuzhiyun unsigned flags,
580*4882a593Smuzhiyun struct vm_area_struct *vma,
581*4882a593Smuzhiyun struct mm_struct *mm,
582*4882a593Smuzhiyun unsigned long start,
583*4882a593Smuzhiyun unsigned long end)
584*4882a593Smuzhiyun {
585*4882a593Smuzhiyun range->vma = vma;
586*4882a593Smuzhiyun range->event = event;
587*4882a593Smuzhiyun range->mm = mm;
588*4882a593Smuzhiyun range->start = start;
589*4882a593Smuzhiyun range->end = end;
590*4882a593Smuzhiyun range->flags = flags;
591*4882a593Smuzhiyun }
592*4882a593Smuzhiyun
mmu_notifier_range_init_migrate(struct mmu_notifier_range * range,unsigned int flags,struct vm_area_struct * vma,struct mm_struct * mm,unsigned long start,unsigned long end,void * pgmap)593*4882a593Smuzhiyun static inline void mmu_notifier_range_init_migrate(
594*4882a593Smuzhiyun struct mmu_notifier_range *range, unsigned int flags,
595*4882a593Smuzhiyun struct vm_area_struct *vma, struct mm_struct *mm,
596*4882a593Smuzhiyun unsigned long start, unsigned long end, void *pgmap)
597*4882a593Smuzhiyun {
598*4882a593Smuzhiyun mmu_notifier_range_init(range, MMU_NOTIFY_MIGRATE, flags, vma, mm,
599*4882a593Smuzhiyun start, end);
600*4882a593Smuzhiyun range->migrate_pgmap_owner = pgmap;
601*4882a593Smuzhiyun }
602*4882a593Smuzhiyun
603*4882a593Smuzhiyun #define ptep_clear_flush_young_notify(__vma, __address, __ptep) \
604*4882a593Smuzhiyun ({ \
605*4882a593Smuzhiyun int __young; \
606*4882a593Smuzhiyun struct vm_area_struct *___vma = __vma; \
607*4882a593Smuzhiyun unsigned long ___address = __address; \
608*4882a593Smuzhiyun __young = ptep_clear_flush_young(___vma, ___address, __ptep); \
609*4882a593Smuzhiyun __young |= mmu_notifier_clear_flush_young(___vma->vm_mm, \
610*4882a593Smuzhiyun ___address, \
611*4882a593Smuzhiyun ___address + \
612*4882a593Smuzhiyun PAGE_SIZE); \
613*4882a593Smuzhiyun __young; \
614*4882a593Smuzhiyun })
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun #define pmdp_clear_flush_young_notify(__vma, __address, __pmdp) \
617*4882a593Smuzhiyun ({ \
618*4882a593Smuzhiyun int __young; \
619*4882a593Smuzhiyun struct vm_area_struct *___vma = __vma; \
620*4882a593Smuzhiyun unsigned long ___address = __address; \
621*4882a593Smuzhiyun __young = pmdp_clear_flush_young(___vma, ___address, __pmdp); \
622*4882a593Smuzhiyun __young |= mmu_notifier_clear_flush_young(___vma->vm_mm, \
623*4882a593Smuzhiyun ___address, \
624*4882a593Smuzhiyun ___address + \
625*4882a593Smuzhiyun PMD_SIZE); \
626*4882a593Smuzhiyun __young; \
627*4882a593Smuzhiyun })
628*4882a593Smuzhiyun
629*4882a593Smuzhiyun #define ptep_clear_young_notify(__vma, __address, __ptep) \
630*4882a593Smuzhiyun ({ \
631*4882a593Smuzhiyun int __young; \
632*4882a593Smuzhiyun struct vm_area_struct *___vma = __vma; \
633*4882a593Smuzhiyun unsigned long ___address = __address; \
634*4882a593Smuzhiyun __young = ptep_test_and_clear_young(___vma, ___address, __ptep);\
635*4882a593Smuzhiyun __young |= mmu_notifier_clear_young(___vma->vm_mm, ___address, \
636*4882a593Smuzhiyun ___address + PAGE_SIZE); \
637*4882a593Smuzhiyun __young; \
638*4882a593Smuzhiyun })
639*4882a593Smuzhiyun
640*4882a593Smuzhiyun #define pmdp_clear_young_notify(__vma, __address, __pmdp) \
641*4882a593Smuzhiyun ({ \
642*4882a593Smuzhiyun int __young; \
643*4882a593Smuzhiyun struct vm_area_struct *___vma = __vma; \
644*4882a593Smuzhiyun unsigned long ___address = __address; \
645*4882a593Smuzhiyun __young = pmdp_test_and_clear_young(___vma, ___address, __pmdp);\
646*4882a593Smuzhiyun __young |= mmu_notifier_clear_young(___vma->vm_mm, ___address, \
647*4882a593Smuzhiyun ___address + PMD_SIZE); \
648*4882a593Smuzhiyun __young; \
649*4882a593Smuzhiyun })
650*4882a593Smuzhiyun
651*4882a593Smuzhiyun #define ptep_clear_flush_notify(__vma, __address, __ptep) \
652*4882a593Smuzhiyun ({ \
653*4882a593Smuzhiyun unsigned long ___addr = __address & PAGE_MASK; \
654*4882a593Smuzhiyun struct mm_struct *___mm = (__vma)->vm_mm; \
655*4882a593Smuzhiyun pte_t ___pte; \
656*4882a593Smuzhiyun \
657*4882a593Smuzhiyun ___pte = ptep_clear_flush(__vma, __address, __ptep); \
658*4882a593Smuzhiyun mmu_notifier_invalidate_range(___mm, ___addr, \
659*4882a593Smuzhiyun ___addr + PAGE_SIZE); \
660*4882a593Smuzhiyun \
661*4882a593Smuzhiyun ___pte; \
662*4882a593Smuzhiyun })
663*4882a593Smuzhiyun
664*4882a593Smuzhiyun #define pmdp_huge_clear_flush_notify(__vma, __haddr, __pmd) \
665*4882a593Smuzhiyun ({ \
666*4882a593Smuzhiyun unsigned long ___haddr = __haddr & HPAGE_PMD_MASK; \
667*4882a593Smuzhiyun struct mm_struct *___mm = (__vma)->vm_mm; \
668*4882a593Smuzhiyun pmd_t ___pmd; \
669*4882a593Smuzhiyun \
670*4882a593Smuzhiyun ___pmd = pmdp_huge_clear_flush(__vma, __haddr, __pmd); \
671*4882a593Smuzhiyun mmu_notifier_invalidate_range(___mm, ___haddr, \
672*4882a593Smuzhiyun ___haddr + HPAGE_PMD_SIZE); \
673*4882a593Smuzhiyun \
674*4882a593Smuzhiyun ___pmd; \
675*4882a593Smuzhiyun })
676*4882a593Smuzhiyun
677*4882a593Smuzhiyun #define pudp_huge_clear_flush_notify(__vma, __haddr, __pud) \
678*4882a593Smuzhiyun ({ \
679*4882a593Smuzhiyun unsigned long ___haddr = __haddr & HPAGE_PUD_MASK; \
680*4882a593Smuzhiyun struct mm_struct *___mm = (__vma)->vm_mm; \
681*4882a593Smuzhiyun pud_t ___pud; \
682*4882a593Smuzhiyun \
683*4882a593Smuzhiyun ___pud = pudp_huge_clear_flush(__vma, __haddr, __pud); \
684*4882a593Smuzhiyun mmu_notifier_invalidate_range(___mm, ___haddr, \
685*4882a593Smuzhiyun ___haddr + HPAGE_PUD_SIZE); \
686*4882a593Smuzhiyun \
687*4882a593Smuzhiyun ___pud; \
688*4882a593Smuzhiyun })
689*4882a593Smuzhiyun
690*4882a593Smuzhiyun /*
691*4882a593Smuzhiyun * set_pte_at_notify() sets the pte _after_ running the notifier.
692*4882a593Smuzhiyun * This is safe to start by updating the secondary MMUs, because the primary MMU
693*4882a593Smuzhiyun * pte invalidate must have already happened with a ptep_clear_flush() before
694*4882a593Smuzhiyun * set_pte_at_notify() has been invoked. Updating the secondary MMUs first is
695*4882a593Smuzhiyun * required when we change both the protection of the mapping from read-only to
696*4882a593Smuzhiyun * read-write and the pfn (like during copy on write page faults). Otherwise the
697*4882a593Smuzhiyun * old page would remain mapped readonly in the secondary MMUs after the new
698*4882a593Smuzhiyun * page is already writable by some CPU through the primary MMU.
699*4882a593Smuzhiyun */
700*4882a593Smuzhiyun #define set_pte_at_notify(__mm, __address, __ptep, __pte) \
701*4882a593Smuzhiyun ({ \
702*4882a593Smuzhiyun struct mm_struct *___mm = __mm; \
703*4882a593Smuzhiyun unsigned long ___address = __address; \
704*4882a593Smuzhiyun pte_t ___pte = __pte; \
705*4882a593Smuzhiyun \
706*4882a593Smuzhiyun mmu_notifier_change_pte(___mm, ___address, ___pte); \
707*4882a593Smuzhiyun set_pte_at(___mm, ___address, __ptep, ___pte); \
708*4882a593Smuzhiyun })
709*4882a593Smuzhiyun
710*4882a593Smuzhiyun #else /* CONFIG_MMU_NOTIFIER */
711*4882a593Smuzhiyun
712*4882a593Smuzhiyun struct mmu_notifier_range {
713*4882a593Smuzhiyun unsigned long start;
714*4882a593Smuzhiyun unsigned long end;
715*4882a593Smuzhiyun };
716*4882a593Smuzhiyun
_mmu_notifier_range_init(struct mmu_notifier_range * range,unsigned long start,unsigned long end)717*4882a593Smuzhiyun static inline void _mmu_notifier_range_init(struct mmu_notifier_range *range,
718*4882a593Smuzhiyun unsigned long start,
719*4882a593Smuzhiyun unsigned long end)
720*4882a593Smuzhiyun {
721*4882a593Smuzhiyun range->start = start;
722*4882a593Smuzhiyun range->end = end;
723*4882a593Smuzhiyun }
724*4882a593Smuzhiyun
725*4882a593Smuzhiyun #define mmu_notifier_range_init(range,event,flags,vma,mm,start,end) \
726*4882a593Smuzhiyun _mmu_notifier_range_init(range, start, end)
727*4882a593Smuzhiyun #define mmu_notifier_range_init_migrate(range, flags, vma, mm, start, end, \
728*4882a593Smuzhiyun pgmap) \
729*4882a593Smuzhiyun _mmu_notifier_range_init(range, start, end)
730*4882a593Smuzhiyun
731*4882a593Smuzhiyun static inline bool
mmu_notifier_range_blockable(const struct mmu_notifier_range * range)732*4882a593Smuzhiyun mmu_notifier_range_blockable(const struct mmu_notifier_range *range)
733*4882a593Smuzhiyun {
734*4882a593Smuzhiyun return true;
735*4882a593Smuzhiyun }
736*4882a593Smuzhiyun
mm_has_notifiers(struct mm_struct * mm)737*4882a593Smuzhiyun static inline int mm_has_notifiers(struct mm_struct *mm)
738*4882a593Smuzhiyun {
739*4882a593Smuzhiyun return 0;
740*4882a593Smuzhiyun }
741*4882a593Smuzhiyun
mmu_notifier_release(struct mm_struct * mm)742*4882a593Smuzhiyun static inline void mmu_notifier_release(struct mm_struct *mm)
743*4882a593Smuzhiyun {
744*4882a593Smuzhiyun }
745*4882a593Smuzhiyun
mmu_notifier_clear_flush_young(struct mm_struct * mm,unsigned long start,unsigned long end)746*4882a593Smuzhiyun static inline int mmu_notifier_clear_flush_young(struct mm_struct *mm,
747*4882a593Smuzhiyun unsigned long start,
748*4882a593Smuzhiyun unsigned long end)
749*4882a593Smuzhiyun {
750*4882a593Smuzhiyun return 0;
751*4882a593Smuzhiyun }
752*4882a593Smuzhiyun
mmu_notifier_test_young(struct mm_struct * mm,unsigned long address)753*4882a593Smuzhiyun static inline int mmu_notifier_test_young(struct mm_struct *mm,
754*4882a593Smuzhiyun unsigned long address)
755*4882a593Smuzhiyun {
756*4882a593Smuzhiyun return 0;
757*4882a593Smuzhiyun }
758*4882a593Smuzhiyun
mmu_notifier_change_pte(struct mm_struct * mm,unsigned long address,pte_t pte)759*4882a593Smuzhiyun static inline void mmu_notifier_change_pte(struct mm_struct *mm,
760*4882a593Smuzhiyun unsigned long address, pte_t pte)
761*4882a593Smuzhiyun {
762*4882a593Smuzhiyun }
763*4882a593Smuzhiyun
764*4882a593Smuzhiyun static inline void
mmu_notifier_invalidate_range_start(struct mmu_notifier_range * range)765*4882a593Smuzhiyun mmu_notifier_invalidate_range_start(struct mmu_notifier_range *range)
766*4882a593Smuzhiyun {
767*4882a593Smuzhiyun }
768*4882a593Smuzhiyun
769*4882a593Smuzhiyun static inline int
mmu_notifier_invalidate_range_start_nonblock(struct mmu_notifier_range * range)770*4882a593Smuzhiyun mmu_notifier_invalidate_range_start_nonblock(struct mmu_notifier_range *range)
771*4882a593Smuzhiyun {
772*4882a593Smuzhiyun return 0;
773*4882a593Smuzhiyun }
774*4882a593Smuzhiyun
775*4882a593Smuzhiyun static inline
mmu_notifier_invalidate_range_end(struct mmu_notifier_range * range)776*4882a593Smuzhiyun void mmu_notifier_invalidate_range_end(struct mmu_notifier_range *range)
777*4882a593Smuzhiyun {
778*4882a593Smuzhiyun }
779*4882a593Smuzhiyun
780*4882a593Smuzhiyun static inline void
mmu_notifier_invalidate_range_only_end(struct mmu_notifier_range * range)781*4882a593Smuzhiyun mmu_notifier_invalidate_range_only_end(struct mmu_notifier_range *range)
782*4882a593Smuzhiyun {
783*4882a593Smuzhiyun }
784*4882a593Smuzhiyun
mmu_notifier_invalidate_range(struct mm_struct * mm,unsigned long start,unsigned long end)785*4882a593Smuzhiyun static inline void mmu_notifier_invalidate_range(struct mm_struct *mm,
786*4882a593Smuzhiyun unsigned long start, unsigned long end)
787*4882a593Smuzhiyun {
788*4882a593Smuzhiyun }
789*4882a593Smuzhiyun
mmu_notifier_subscriptions_init(struct mm_struct * mm)790*4882a593Smuzhiyun static inline bool mmu_notifier_subscriptions_init(struct mm_struct *mm)
791*4882a593Smuzhiyun {
792*4882a593Smuzhiyun return true;
793*4882a593Smuzhiyun }
794*4882a593Smuzhiyun
mmu_notifier_subscriptions_destroy(struct mm_struct * mm)795*4882a593Smuzhiyun static inline void mmu_notifier_subscriptions_destroy(struct mm_struct *mm)
796*4882a593Smuzhiyun {
797*4882a593Smuzhiyun }
798*4882a593Smuzhiyun
mmu_notifier_trylock(struct mm_struct * mm)799*4882a593Smuzhiyun static inline bool mmu_notifier_trylock(struct mm_struct *mm)
800*4882a593Smuzhiyun {
801*4882a593Smuzhiyun return true;
802*4882a593Smuzhiyun }
803*4882a593Smuzhiyun
mmu_notifier_unlock(struct mm_struct * mm)804*4882a593Smuzhiyun static inline void mmu_notifier_unlock(struct mm_struct *mm)
805*4882a593Smuzhiyun {
806*4882a593Smuzhiyun }
807*4882a593Smuzhiyun
808*4882a593Smuzhiyun #define mmu_notifier_range_update_to_read_only(r) false
809*4882a593Smuzhiyun
810*4882a593Smuzhiyun #define ptep_clear_flush_young_notify ptep_clear_flush_young
811*4882a593Smuzhiyun #define pmdp_clear_flush_young_notify pmdp_clear_flush_young
812*4882a593Smuzhiyun #define ptep_clear_young_notify ptep_test_and_clear_young
813*4882a593Smuzhiyun #define pmdp_clear_young_notify pmdp_test_and_clear_young
814*4882a593Smuzhiyun #define ptep_clear_flush_notify ptep_clear_flush
815*4882a593Smuzhiyun #define pmdp_huge_clear_flush_notify pmdp_huge_clear_flush
816*4882a593Smuzhiyun #define pudp_huge_clear_flush_notify pudp_huge_clear_flush
817*4882a593Smuzhiyun #define set_pte_at_notify set_pte_at
818*4882a593Smuzhiyun
mmu_notifier_synchronize(void)819*4882a593Smuzhiyun static inline void mmu_notifier_synchronize(void)
820*4882a593Smuzhiyun {
821*4882a593Smuzhiyun }
822*4882a593Smuzhiyun
823*4882a593Smuzhiyun #endif /* CONFIG_MMU_NOTIFIER */
824*4882a593Smuzhiyun
825*4882a593Smuzhiyun #endif /* _LINUX_MMU_NOTIFIER_H */
826