Blame view

arch/arm/mm/flush.c 10.7 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
  /*
   *  linux/arch/arm/mm/flush.c
   *
   *  Copyright (C) 1995-2002 Russell King
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   */
  #include <linux/module.h>
  #include <linux/mm.h>
  #include <linux/pagemap.h>
39af22a79   Nicolas Pitre   ARM: get rid of k...
13
  #include <linux/highmem.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
15
  
  #include <asm/cacheflush.h>
46097c7dd   Russell King   [ARM] cachetype: ...
16
  #include <asm/cachetype.h>
7e5a69e83   Nicolas Pitre   ARM: 6007/1: fix ...
17
  #include <asm/highmem.h>
2ef7f3dbd   Russell King   ARM: Fix ptrace a...
18
  #include <asm/smp_plat.h>
8d802d28c   Russell King   [PATCH] ARM: Add ...
19
  #include <asm/tlbflush.h>
0b19f9335   Steve Capper   ARM: mm: Add supp...
20
  #include <linux/hugetlb.h>
8d802d28c   Russell King   [PATCH] ARM: Add ...
21

1b2e2b73b   Russell King   [ARM] Cleanup arc...
22
  #include "mm.h"
8d802d28c   Russell King   [PATCH] ARM: Add ...
23
  #ifdef CONFIG_CPU_CACHE_VIPT
d7b6b3589   Russell King   [ARM] Fix ARMv6 V...
24

481467d6f   Catalin Marinas   [ARM] 2939/1: Fix...
25
26
  static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr)
  {
de27c3082   Russell King   ARM: pgtable: mov...
27
  	unsigned long to = FLUSH_ALIAS_START + (CACHE_COLOUR(vaddr) << PAGE_SHIFT);
141fa40cf   Catalin Marinas   [ARM] 3356/1: Wor...
28
  	const int zero = 0;
481467d6f   Catalin Marinas   [ARM] 2939/1: Fix...
29

67ece1443   Russell King   ARM: pgtable: con...
30
  	set_top_pte(to, pfn_pte(pfn, PAGE_KERNEL));
481467d6f   Catalin Marinas   [ARM] 2939/1: Fix...
31
32
33
  
  	asm(	"mcrr	p15, 0, %1, %0, c14
  "
df71dfd4c   Russell King   ARM: Fix errata 4...
34
  	"	mcr	p15, 0, %2, c7, c10, 4"
481467d6f   Catalin Marinas   [ARM] 2939/1: Fix...
35
  	    :
141fa40cf   Catalin Marinas   [ARM] 3356/1: Wor...
36
  	    : "r" (to), "r" (to + PAGE_SIZE - L1_CACHE_BYTES), "r" (zero)
481467d6f   Catalin Marinas   [ARM] 2939/1: Fix...
37
38
  	    : "cc");
  }
c4e259c85   Will Deacon   ARM: 6386/1: flus...
39
40
  static void flush_icache_alias(unsigned long pfn, unsigned long vaddr, unsigned long len)
  {
67ece1443   Russell King   ARM: pgtable: con...
41
  	unsigned long va = FLUSH_ALIAS_START + (CACHE_COLOUR(vaddr) << PAGE_SHIFT);
c4e259c85   Will Deacon   ARM: 6386/1: flus...
42
43
  	unsigned long offset = vaddr & (PAGE_SIZE - 1);
  	unsigned long to;
67ece1443   Russell King   ARM: pgtable: con...
44
45
  	set_top_pte(va, pfn_pte(pfn, PAGE_KERNEL));
  	to = va + offset;
c4e259c85   Will Deacon   ARM: 6386/1: flus...
46
47
  	flush_icache_range(to, to + len);
  }
d7b6b3589   Russell King   [ARM] Fix ARMv6 V...
48
49
50
  void flush_cache_mm(struct mm_struct *mm)
  {
  	if (cache_is_vivt()) {
2f0b19263   Russell King   ARM: Avoid duplic...
51
  		vivt_flush_cache_mm(mm);
d7b6b3589   Russell King   [ARM] Fix ARMv6 V...
52
53
54
55
56
57
  		return;
  	}
  
  	if (cache_is_vipt_aliasing()) {
  		asm(	"mcr	p15, 0, %0, c7, c14, 0
  "
df71dfd4c   Russell King   ARM: Fix errata 4...
58
  		"	mcr	p15, 0, %0, c7, c10, 4"
d7b6b3589   Russell King   [ARM] Fix ARMv6 V...
59
60
61
62
63
64
65
66
67
  		    :
  		    : "r" (0)
  		    : "cc");
  	}
  }
  
  void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
  {
  	if (cache_is_vivt()) {
2f0b19263   Russell King   ARM: Avoid duplic...
68
  		vivt_flush_cache_range(vma, start, end);
d7b6b3589   Russell King   [ARM] Fix ARMv6 V...
69
70
71
72
73
74
  		return;
  	}
  
  	if (cache_is_vipt_aliasing()) {
  		asm(	"mcr	p15, 0, %0, c7, c14, 0
  "
df71dfd4c   Russell King   ARM: Fix errata 4...
75
  		"	mcr	p15, 0, %0, c7, c10, 4"
d7b6b3589   Russell King   [ARM] Fix ARMv6 V...
76
77
78
79
  		    :
  		    : "r" (0)
  		    : "cc");
  	}
9e95922b1   Russell King   ARM: I-cache: Add...
80

6060e8df5   Russell King   ARM: I-cache: flu...
81
  	if (vma->vm_flags & VM_EXEC)
9e95922b1   Russell King   ARM: I-cache: Add...
82
  		__flush_icache_all();
d7b6b3589   Russell King   [ARM] Fix ARMv6 V...
83
84
85
86
87
  }
  
  void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned long pfn)
  {
  	if (cache_is_vivt()) {
2f0b19263   Russell King   ARM: Avoid duplic...
88
  		vivt_flush_cache_page(vma, user_addr, pfn);
d7b6b3589   Russell King   [ARM] Fix ARMv6 V...
89
90
  		return;
  	}
2df341edf   Russell King   ARM: Move __flush...
91
  	if (cache_is_vipt_aliasing()) {
d7b6b3589   Russell King   [ARM] Fix ARMv6 V...
92
  		flush_pfn_alias(pfn, user_addr);
2df341edf   Russell King   ARM: Move __flush...
93
94
  		__flush_icache_all();
  	}
9e95922b1   Russell King   ARM: I-cache: Add...
95
96
97
  
  	if (vma->vm_flags & VM_EXEC && icache_is_vivt_asid_tagged())
  		__flush_icache_all();
d7b6b3589   Russell King   [ARM] Fix ARMv6 V...
98
  }
c4e259c85   Will Deacon   ARM: 6386/1: flus...
99

2ef7f3dbd   Russell King   ARM: Fix ptrace a...
100
  #else
c4e259c85   Will Deacon   ARM: 6386/1: flus...
101
102
  #define flush_pfn_alias(pfn,vaddr)		do { } while (0)
  #define flush_icache_alias(pfn,vaddr,len)	do { } while (0)
2ef7f3dbd   Russell King   ARM: Fix ptrace a...
103
  #endif
a188ad2bc   George G. Davis   [ARM] 3762/1: Fix...
104

72e6ae285   Victor Kamensky   ARM: 8043/1: upro...
105
106
  #define FLAG_PA_IS_EXEC 1
  #define FLAG_PA_CORE_IN_MM 2
2ef7f3dbd   Russell King   ARM: Fix ptrace a...
107
108
109
110
  static void flush_ptrace_access_other(void *args)
  {
  	__flush_icache_all();
  }
2ef7f3dbd   Russell King   ARM: Fix ptrace a...
111

72e6ae285   Victor Kamensky   ARM: 8043/1: upro...
112
113
114
  static inline
  void __flush_ptrace_access(struct page *page, unsigned long uaddr, void *kaddr,
  			   unsigned long len, unsigned int flags)
a188ad2bc   George G. Davis   [ARM] 3762/1: Fix...
115
116
  {
  	if (cache_is_vivt()) {
72e6ae285   Victor Kamensky   ARM: 8043/1: upro...
117
  		if (flags & FLAG_PA_CORE_IN_MM) {
2ef7f3dbd   Russell King   ARM: Fix ptrace a...
118
119
120
  			unsigned long addr = (unsigned long)kaddr;
  			__cpuc_coherent_kern_range(addr, addr + len);
  		}
a188ad2bc   George G. Davis   [ARM] 3762/1: Fix...
121
122
123
124
125
  		return;
  	}
  
  	if (cache_is_vipt_aliasing()) {
  		flush_pfn_alias(page_to_pfn(page), uaddr);
2df341edf   Russell King   ARM: Move __flush...
126
  		__flush_icache_all();
a188ad2bc   George G. Davis   [ARM] 3762/1: Fix...
127
128
  		return;
  	}
c4e259c85   Will Deacon   ARM: 6386/1: flus...
129
  	/* VIPT non-aliasing D-cache */
72e6ae285   Victor Kamensky   ARM: 8043/1: upro...
130
  	if (flags & FLAG_PA_IS_EXEC) {
a188ad2bc   George G. Davis   [ARM] 3762/1: Fix...
131
  		unsigned long addr = (unsigned long)kaddr;
c4e259c85   Will Deacon   ARM: 6386/1: flus...
132
133
134
135
  		if (icache_is_vipt_aliasing())
  			flush_icache_alias(page_to_pfn(page), uaddr, len);
  		else
  			__cpuc_coherent_kern_range(addr, addr + len);
2ef7f3dbd   Russell King   ARM: Fix ptrace a...
136
137
138
  		if (cache_ops_need_broadcast())
  			smp_call_function(flush_ptrace_access_other,
  					  NULL, 1);
a188ad2bc   George G. Davis   [ARM] 3762/1: Fix...
139
140
  	}
  }
2ef7f3dbd   Russell King   ARM: Fix ptrace a...
141

72e6ae285   Victor Kamensky   ARM: 8043/1: upro...
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
  static
  void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
  			 unsigned long uaddr, void *kaddr, unsigned long len)
  {
  	unsigned int flags = 0;
  	if (cpumask_test_cpu(smp_processor_id(), mm_cpumask(vma->vm_mm)))
  		flags |= FLAG_PA_CORE_IN_MM;
  	if (vma->vm_flags & VM_EXEC)
  		flags |= FLAG_PA_IS_EXEC;
  	__flush_ptrace_access(page, uaddr, kaddr, len, flags);
  }
  
  void flush_uprobe_xol_access(struct page *page, unsigned long uaddr,
  			     void *kaddr, unsigned long len)
  {
  	unsigned int flags = FLAG_PA_CORE_IN_MM|FLAG_PA_IS_EXEC;
  
  	__flush_ptrace_access(page, uaddr, kaddr, len, flags);
  }
2ef7f3dbd   Russell King   ARM: Fix ptrace a...
161
162
163
164
165
166
167
168
169
170
171
172
173
  /*
   * Copy user data from/to a page which is mapped into a different
   * processes address space.  Really, we want to allow our "user
   * space" model to handle this.
   *
   * Note that this code needs to run on the current CPU.
   */
  void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
  		       unsigned long uaddr, void *dst, const void *src,
  		       unsigned long len)
  {
  #ifdef CONFIG_SMP
  	preempt_disable();
8d802d28c   Russell King   [PATCH] ARM: Add ...
174
  #endif
2ef7f3dbd   Russell King   ARM: Fix ptrace a...
175
176
177
178
179
180
  	memcpy(dst, src, len);
  	flush_ptrace_access(vma, page, uaddr, dst, len);
  #ifdef CONFIG_SMP
  	preempt_enable();
  #endif
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181

8830f04a0   Russell King   [PATCH] ARM: Fix ...
182
  void __flush_dcache_page(struct address_space *mapping, struct page *page)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184
185
186
187
188
  	/*
  	 * Writeback any data associated with the kernel mapping of this
  	 * page.  This ensures that data in the physical page is mutually
  	 * coherent with the kernels mapping.
  	 */
7e5a69e83   Nicolas Pitre   ARM: 6007/1: fix ...
189
  	if (!PageHighMem(page)) {
0b19f9335   Steve Capper   ARM: mm: Add supp...
190
191
  		size_t page_size = PAGE_SIZE << compound_order(page);
  		__cpuc_flush_dcache_area(page_address(page), page_size);
7e5a69e83   Nicolas Pitre   ARM: 6007/1: fix ...
192
  	} else {
0b19f9335   Steve Capper   ARM: mm: Add supp...
193
  		unsigned long i;
dd0f67f47   Joonsoo Kim   ARM: 7693/1: mm: ...
194
  		if (cache_is_vipt_nonaliasing()) {
0b19f9335   Steve Capper   ARM: mm: Add supp...
195
  			for (i = 0; i < (1 << compound_order(page)); i++) {
2a7cfcbc0   Steven Capper   ARM: 7923/1: mm: ...
196
  				void *addr = kmap_atomic(page + i);
dd0f67f47   Joonsoo Kim   ARM: 7693/1: mm: ...
197
  				__cpuc_flush_dcache_area(addr, PAGE_SIZE);
0b19f9335   Steve Capper   ARM: mm: Add supp...
198
199
200
201
  				kunmap_atomic(addr);
  			}
  		} else {
  			for (i = 0; i < (1 << compound_order(page)); i++) {
2a7cfcbc0   Steven Capper   ARM: 7923/1: mm: ...
202
  				void *addr = kmap_high_get(page + i);
0b19f9335   Steve Capper   ARM: mm: Add supp...
203
204
  				if (addr) {
  					__cpuc_flush_dcache_area(addr, PAGE_SIZE);
2a7cfcbc0   Steven Capper   ARM: 7923/1: mm: ...
205
  					kunmap_high(page + i);
0b19f9335   Steve Capper   ARM: mm: Add supp...
206
  				}
dd0f67f47   Joonsoo Kim   ARM: 7693/1: mm: ...
207
  			}
7e5a69e83   Nicolas Pitre   ARM: 6007/1: fix ...
208
209
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
210
211
  
  	/*
8830f04a0   Russell King   [PATCH] ARM: Fix ...
212
213
  	 * If this is a page cache page, and we have an aliasing VIPT cache,
  	 * we only need to do one flush - which would be at the relevant
8d802d28c   Russell King   [PATCH] ARM: Add ...
214
215
  	 * userspace colour, which is congruent with page->index.
  	 */
f91fb05d8   Russell King   ARM: Remove __flu...
216
  	if (mapping && cache_is_vipt_aliasing())
8830f04a0   Russell King   [PATCH] ARM: Fix ...
217
218
219
220
221
222
223
224
  		flush_pfn_alias(page_to_pfn(page),
  				page->index << PAGE_CACHE_SHIFT);
  }
  
  static void __flush_dcache_aliases(struct address_space *mapping, struct page *page)
  {
  	struct mm_struct *mm = current->active_mm;
  	struct vm_area_struct *mpnt;
8830f04a0   Russell King   [PATCH] ARM: Fix ...
225
  	pgoff_t pgoff;
8d802d28c   Russell King   [PATCH] ARM: Add ...
226
227
  
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228
229
230
231
232
233
234
235
  	 * There are possible user space mappings of this page:
  	 * - VIVT cache: we need to also write back and invalidate all user
  	 *   data in the current VM view associated with this page.
  	 * - aliasing VIPT: we only need to find one mapping of this page.
  	 */
  	pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
  
  	flush_dcache_mmap_lock(mapping);
6b2dbba8b   Michel Lespinasse   mm: replace vma p...
236
  	vma_interval_tree_foreach(mpnt, &mapping->i_mmap, pgoff, pgoff) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
238
239
240
241
242
243
244
245
246
247
  		unsigned long offset;
  
  		/*
  		 * If this VMA is not in our MM, we can ignore it.
  		 */
  		if (mpnt->vm_mm != mm)
  			continue;
  		if (!(mpnt->vm_flags & VM_MAYSHARE))
  			continue;
  		offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
  		flush_cache_page(mpnt, mpnt->vm_start + offset, page_to_pfn(page));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
248
249
250
  	}
  	flush_dcache_mmap_unlock(mapping);
  }
6012191aa   Catalin Marinas   ARM: 6380/1: Intr...
251
252
253
254
255
256
  #if __LINUX_ARM_ARCH__ >= 6
  void __sync_icache_dcache(pte_t pteval)
  {
  	unsigned long pfn;
  	struct page *page;
  	struct address_space *mapping;
6012191aa   Catalin Marinas   ARM: 6380/1: Intr...
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
  	if (cache_is_vipt_nonaliasing() && !pte_exec(pteval))
  		/* only flush non-aliasing VIPT caches for exec mappings */
  		return;
  	pfn = pte_pfn(pteval);
  	if (!pfn_valid(pfn))
  		return;
  
  	page = pfn_to_page(pfn);
  	if (cache_is_vipt_aliasing())
  		mapping = page_mapping(page);
  	else
  		mapping = NULL;
  
  	if (!test_and_set_bit(PG_dcache_clean, &page->flags))
  		__flush_dcache_page(mapping, page);
8373dc38c   saeed bishara   ARM: 6901/1: remo...
272
273
  
  	if (pte_exec(pteval))
6012191aa   Catalin Marinas   ARM: 6380/1: Intr...
274
275
276
  		__flush_icache_all();
  }
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
  /*
   * Ensure cache coherency between kernel mapping and userspace mapping
   * of this page.
   *
   * We have three cases to consider:
   *  - VIPT non-aliasing cache: fully coherent so nothing required.
   *  - VIVT: fully aliasing, so we need to handle every alias in our
   *          current VM view.
   *  - VIPT aliasing: need to handle one alias in our current VM view.
   *
   * If we need to handle aliasing:
   *  If the page only exists in the page cache and there are no user
   *  space mappings, we can be lazy and remember that we may have dirty
   *  kernel cache lines for later.  Otherwise, we assume we have
   *  aliasing mappings.
df2f5e721   Russell King   [ARM SMP] Disable...
292
   *
31bee4cf0   saeed bishara   ARM: 6899/1: fix ...
293
294
   * Note that we disable the lazy flush for SMP configurations where
   * the cache maintenance operations are not automatically broadcasted.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295
296
297
   */
  void flush_dcache_page(struct page *page)
  {
421fe93cc   Russell King   ARM: ZERO_PAGE: A...
298
299
300
301
302
303
304
305
306
307
  	struct address_space *mapping;
  
  	/*
  	 * The zero page is never written to, so never has any dirty
  	 * cache lines, and therefore never needs to be flushed.
  	 */
  	if (page == ZERO_PAGE(0))
  		return;
  
  	mapping = page_mapping(page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
308

85848dd7a   Catalin Marinas   ARM: 6381/1: Use ...
309
  	if (!cache_ops_need_broadcast() &&
81f28946a   Ming Lei   ARM: 7746/1: mm: ...
310
  	    mapping && !page_mapped(page))
c01778001   Catalin Marinas   ARM: 6379/1: Assu...
311
  		clear_bit(PG_dcache_clean, &page->flags);
85848dd7a   Catalin Marinas   ARM: 6381/1: Use ...
312
  	else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
313
  		__flush_dcache_page(mapping, page);
8830f04a0   Russell King   [PATCH] ARM: Fix ...
314
315
  		if (mapping && cache_is_vivt())
  			__flush_dcache_aliases(mapping, page);
826cbdaff   Catalin Marinas   [ARM] 5092/1: Fix...
316
317
  		else if (mapping)
  			__flush_icache_all();
c01778001   Catalin Marinas   ARM: 6379/1: Assu...
318
  		set_bit(PG_dcache_clean, &page->flags);
8830f04a0   Russell King   [PATCH] ARM: Fix ...
319
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320
321
  }
  EXPORT_SYMBOL(flush_dcache_page);
1bc39742a   Simon Baatz   ARM: 7755/1: hand...
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
  
  /*
   * Ensure cache coherency for the kernel mapping of this page. We can
   * assume that the page is pinned via kmap.
   *
   * If the page only exists in the page cache and there are no user
   * space mappings, this is a no-op since the page was already marked
   * dirty at creation.  Otherwise, we need to flush the dirty kernel
   * cache lines directly.
   */
  void flush_kernel_dcache_page(struct page *page)
  {
  	if (cache_is_vivt() || cache_is_vipt_aliasing()) {
  		struct address_space *mapping;
  
  		mapping = page_mapping(page);
  
  		if (!mapping || mapping_mapped(mapping)) {
  			void *addr;
  
  			addr = page_address(page);
  			/*
  			 * kmap_atomic() doesn't set the page virtual
  			 * address for highmem pages, and
  			 * kunmap_atomic() takes care of cache
  			 * flushing already.
  			 */
  			if (!IS_ENABLED(CONFIG_HIGHMEM) || addr)
  				__cpuc_flush_dcache_area(addr, PAGE_SIZE);
  		}
  	}
  }
  EXPORT_SYMBOL(flush_kernel_dcache_page);
6020dff09   Russell King   [ARM] Resolve fus...
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
  
  /*
   * Flush an anonymous page so that users of get_user_pages()
   * can safely access the data.  The expected sequence is:
   *
   *  get_user_pages()
   *    -> flush_anon_page
   *  memcpy() to/from page
   *  if written to page, flush_dcache_page()
   */
  void __flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vmaddr)
  {
  	unsigned long pfn;
  
  	/* VIPT non-aliasing caches need do nothing */
  	if (cache_is_vipt_nonaliasing())
  		return;
  
  	/*
  	 * Write back and invalidate userspace mapping.
  	 */
  	pfn = page_to_pfn(page);
  	if (cache_is_vivt()) {
  		flush_cache_page(vma, vmaddr, pfn);
  	} else {
  		/*
  		 * For aliasing VIPT, we can flush an alias of the
  		 * userspace address only.
  		 */
  		flush_pfn_alias(pfn, vmaddr);
2df341edf   Russell King   ARM: Move __flush...
385
  		__flush_icache_all();
6020dff09   Russell King   [ARM] Resolve fus...
386
387
388
389
390
391
392
  	}
  
  	/*
  	 * Invalidate kernel mapping.  No data should be contained
  	 * in this mapping of the page.  FIXME: this is overkill
  	 * since we actually ask for a write-back and invalidate.
  	 */
2c9b9c849   Russell King   ARM: add size arg...
393
  	__cpuc_flush_dcache_area(page_address(page), PAGE_SIZE);
6020dff09   Russell King   [ARM] Resolve fus...
394
  }
b8cd51afe   Steve Capper   arm: mm: enable R...
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
  
  #ifdef CONFIG_TRANSPARENT_HUGEPAGE
  #ifdef CONFIG_HAVE_RCU_TABLE_FREE
  void pmdp_splitting_flush(struct vm_area_struct *vma, unsigned long address,
  			  pmd_t *pmdp)
  {
  	pmd_t pmd = pmd_mksplitting(*pmdp);
  	VM_BUG_ON(address & ~PMD_MASK);
  	set_pmd_at(vma->vm_mm, address, pmdp, pmd);
  
  	/* dummy IPI to serialise against fast_gup */
  	kick_all_cpus_sync();
  }
  #endif /* CONFIG_HAVE_RCU_TABLE_FREE */
  #endif /* CONFIG_TRANSPARENT_HUGEPAGE */