Blame view

mm/pgtable-generic.c 5.18 KB
e2cda3226   Andrea Arcangeli   thp: add pmd mang...
1
2
3
4
5
6
7
  /*
   *  mm/pgtable-generic.c
   *
   *  Generic pgtable methods declared in asm-generic/pgtable.h
   *
   *  Copyright (C) 2010  Linus Torvalds
   */
f95ba941d   Andrew Morton   mm/pgtable-generi...
8
  #include <linux/pagemap.h>
e2cda3226   Andrea Arcangeli   thp: add pmd mang...
9
10
  #include <asm/tlb.h>
  #include <asm-generic/pgtable.h>
bc4b4448d   Joonsoo Kim   mm: move pgtable ...
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
  /*
   * If a p?d_bad entry is found while walking page tables, report
   * the error, before resetting entry to p?d_none.  Usually (but
   * very seldom) called out from the p?d_none_or_clear_bad macros.
   */
  
  void pgd_clear_bad(pgd_t *pgd)
  {
  	pgd_ERROR(*pgd);
  	pgd_clear(pgd);
  }
  
  void pud_clear_bad(pud_t *pud)
  {
  	pud_ERROR(*pud);
  	pud_clear(pud);
  }
  
  void pmd_clear_bad(pmd_t *pmd)
  {
  	pmd_ERROR(*pmd);
  	pmd_clear(pmd);
  }
e2cda3226   Andrea Arcangeli   thp: add pmd mang...
34
35
  #ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
  /*
cef23d9db   Rik van Riel   mm,generic: only ...
36
37
   * Only sets the access flags (dirty, accessed), as well as write 
   * permission. Furthermore, we know it always gets set to a "more
e2cda3226   Andrea Arcangeli   thp: add pmd mang...
38
39
40
41
42
43
44
45
46
47
48
49
50
   * permissive" setting, which allows most architectures to optimize
   * this. We return whether the PTE actually changed, which in turn
   * instructs the caller to do things like update__mmu_cache.  This
   * used to be done in the caller, but sparc needs minor faults to
   * force that call on sun4c so we changed this macro slightly
   */
  int ptep_set_access_flags(struct vm_area_struct *vma,
  			  unsigned long address, pte_t *ptep,
  			  pte_t entry, int dirty)
  {
  	int changed = !pte_same(*ptep, entry);
  	if (changed) {
  		set_pte_at(vma->vm_mm, address, ptep, entry);
cef23d9db   Rik van Riel   mm,generic: only ...
51
  		flush_tlb_fix_spurious_fault(vma, address);
e2cda3226   Andrea Arcangeli   thp: add pmd mang...
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
  	}
  	return changed;
  }
  #endif
  
  #ifndef __HAVE_ARCH_PMDP_SET_ACCESS_FLAGS
  int pmdp_set_access_flags(struct vm_area_struct *vma,
  			  unsigned long address, pmd_t *pmdp,
  			  pmd_t entry, int dirty)
  {
  #ifdef CONFIG_TRANSPARENT_HUGEPAGE
  	int changed = !pmd_same(*pmdp, entry);
  	VM_BUG_ON(address & ~HPAGE_PMD_MASK);
  	if (changed) {
  		set_pmd_at(vma->vm_mm, address, pmdp, entry);
  		flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
  	}
  	return changed;
  #else /* CONFIG_TRANSPARENT_HUGEPAGE */
  	BUG();
  	return 0;
  #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
  }
  #endif
  
  #ifndef __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
  int ptep_clear_flush_young(struct vm_area_struct *vma,
  			   unsigned long address, pte_t *ptep)
  {
  	int young;
  	young = ptep_test_and_clear_young(vma, address, ptep);
  	if (young)
  		flush_tlb_page(vma, address);
  	return young;
  }
  #endif
  
  #ifndef __HAVE_ARCH_PMDP_CLEAR_YOUNG_FLUSH
  int pmdp_clear_flush_young(struct vm_area_struct *vma,
  			   unsigned long address, pmd_t *pmdp)
  {
  	int young;
d8c37c480   Naoya Horiguchi   thp: add HPAGE_PM...
94
95
96
  #ifdef CONFIG_TRANSPARENT_HUGEPAGE
  	VM_BUG_ON(address & ~HPAGE_PMD_MASK);
  #else
e2cda3226   Andrea Arcangeli   thp: add pmd mang...
97
98
  	BUG();
  #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
e2cda3226   Andrea Arcangeli   thp: add pmd mang...
99
100
101
102
103
104
105
106
107
108
109
  	young = pmdp_test_and_clear_young(vma, address, pmdp);
  	if (young)
  		flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
  	return young;
  }
  #endif
  
  #ifndef __HAVE_ARCH_PTEP_CLEAR_FLUSH
  pte_t ptep_clear_flush(struct vm_area_struct *vma, unsigned long address,
  		       pte_t *ptep)
  {
208414059   Rik van Riel   mm: fix TLB flush...
110
  	struct mm_struct *mm = (vma)->vm_mm;
e2cda3226   Andrea Arcangeli   thp: add pmd mang...
111
  	pte_t pte;
208414059   Rik van Riel   mm: fix TLB flush...
112
113
  	pte = ptep_get_and_clear(mm, address, ptep);
  	if (pte_accessible(mm, pte))
8d1acce45   Rik van Riel   mm: Only flush th...
114
  		flush_tlb_page(vma, address);
e2cda3226   Andrea Arcangeli   thp: add pmd mang...
115
116
117
118
119
  	return pte;
  }
  #endif
  
  #ifndef __HAVE_ARCH_PMDP_CLEAR_FLUSH
b3697c025   Andrea Arcangeli   fix non-x86 build...
120
  #ifdef CONFIG_TRANSPARENT_HUGEPAGE
e2cda3226   Andrea Arcangeli   thp: add pmd mang...
121
122
123
124
  pmd_t pmdp_clear_flush(struct vm_area_struct *vma, unsigned long address,
  		       pmd_t *pmdp)
  {
  	pmd_t pmd;
e2cda3226   Andrea Arcangeli   thp: add pmd mang...
125
126
127
128
129
  	VM_BUG_ON(address & ~HPAGE_PMD_MASK);
  	pmd = pmdp_get_and_clear(vma->vm_mm, address, pmdp);
  	flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
  	return pmd;
  }
b3697c025   Andrea Arcangeli   fix non-x86 build...
130
  #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
e2cda3226   Andrea Arcangeli   thp: add pmd mang...
131
132
133
  #endif
  
  #ifndef __HAVE_ARCH_PMDP_SPLITTING_FLUSH
b3697c025   Andrea Arcangeli   fix non-x86 build...
134
  #ifdef CONFIG_TRANSPARENT_HUGEPAGE
73636b1aa   Chris Metcalf   arch/tile: allow ...
135
136
  void pmdp_splitting_flush(struct vm_area_struct *vma, unsigned long address,
  			  pmd_t *pmdp)
e2cda3226   Andrea Arcangeli   thp: add pmd mang...
137
  {
e2cda3226   Andrea Arcangeli   thp: add pmd mang...
138
139
140
141
142
  	pmd_t pmd = pmd_mksplitting(*pmdp);
  	VM_BUG_ON(address & ~HPAGE_PMD_MASK);
  	set_pmd_at(vma->vm_mm, address, pmdp, pmd);
  	/* tlb flush only to serialize against gup-fast */
  	flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
e2cda3226   Andrea Arcangeli   thp: add pmd mang...
143
  }
b3697c025   Andrea Arcangeli   fix non-x86 build...
144
  #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
e2cda3226   Andrea Arcangeli   thp: add pmd mang...
145
  #endif
e3ebcf643   Gerald Schaefer   thp: remove assum...
146
147
148
  
  #ifndef __HAVE_ARCH_PGTABLE_DEPOSIT
  #ifdef CONFIG_TRANSPARENT_HUGEPAGE
6b0b50b06   Aneesh Kumar K.V   mm/THP: add pmd a...
149
150
  void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
  				pgtable_t pgtable)
e3ebcf643   Gerald Schaefer   thp: remove assum...
151
  {
c4088ebdc   Kirill A. Shutemov   mm: convert the r...
152
  	assert_spin_locked(pmd_lockptr(mm, pmdp));
e3ebcf643   Gerald Schaefer   thp: remove assum...
153
154
  
  	/* FIFO */
c389a250a   Kirill A. Shutemov   mm, thp: do not a...
155
  	if (!pmd_huge_pte(mm, pmdp))
e3ebcf643   Gerald Schaefer   thp: remove assum...
156
157
  		INIT_LIST_HEAD(&pgtable->lru);
  	else
c389a250a   Kirill A. Shutemov   mm, thp: do not a...
158
159
  		list_add(&pgtable->lru, &pmd_huge_pte(mm, pmdp)->lru);
  	pmd_huge_pte(mm, pmdp) = pgtable;
e3ebcf643   Gerald Schaefer   thp: remove assum...
160
161
162
163
164
165
166
  }
  #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
  #endif
  
  #ifndef __HAVE_ARCH_PGTABLE_WITHDRAW
  #ifdef CONFIG_TRANSPARENT_HUGEPAGE
  /* no "address" argument so destroys page coloring of some arch */
6b0b50b06   Aneesh Kumar K.V   mm/THP: add pmd a...
167
  pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp)
e3ebcf643   Gerald Schaefer   thp: remove assum...
168
169
  {
  	pgtable_t pgtable;
c4088ebdc   Kirill A. Shutemov   mm: convert the r...
170
  	assert_spin_locked(pmd_lockptr(mm, pmdp));
e3ebcf643   Gerald Schaefer   thp: remove assum...
171
172
  
  	/* FIFO */
c389a250a   Kirill A. Shutemov   mm, thp: do not a...
173
  	pgtable = pmd_huge_pte(mm, pmdp);
e3ebcf643   Gerald Schaefer   thp: remove assum...
174
  	if (list_empty(&pgtable->lru))
c389a250a   Kirill A. Shutemov   mm, thp: do not a...
175
  		pmd_huge_pte(mm, pmdp) = NULL;
e3ebcf643   Gerald Schaefer   thp: remove assum...
176
  	else {
c389a250a   Kirill A. Shutemov   mm, thp: do not a...
177
  		pmd_huge_pte(mm, pmdp) = list_entry(pgtable->lru.next,
e3ebcf643   Gerald Schaefer   thp: remove assum...
178
179
180
181
182
183
184
  					      struct page, lru);
  		list_del(&pgtable->lru);
  	}
  	return pgtable;
  }
  #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
  #endif
46dcde735   Gerald Schaefer   thp: introduce pm...
185
186
187
188
189
190
  
  #ifndef __HAVE_ARCH_PMDP_INVALIDATE
  #ifdef CONFIG_TRANSPARENT_HUGEPAGE
  void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
  		     pmd_t *pmdp)
  {
67f87463d   Mel Gorman   mm: clear pmd_num...
191
192
193
  	pmd_t entry = *pmdp;
  	if (pmd_numa(entry))
  		entry = pmd_mknonnuma(entry);
46dcde735   Gerald Schaefer   thp: introduce pm...
194
195
196
197
198
  	set_pmd_at(vma->vm_mm, address, pmdp, pmd_mknotpresent(*pmdp));
  	flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
  }
  #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
  #endif