Blame view

mm/pgtable-generic.c 4.6 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
11
12
13
  #include <asm/tlb.h>
  #include <asm-generic/pgtable.h>
  
  #ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
  /*
cef23d9db   Rik van Riel   mm,generic: only ...
14
15
   * 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...
16
17
18
19
20
21
22
23
24
25
26
27
28
   * 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 ...
29
  		flush_tlb_fix_spurious_fault(vma, address);
e2cda3226   Andrea Arcangeli   thp: add pmd mang...
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
  	}
  	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...
72
73
74
  #ifdef CONFIG_TRANSPARENT_HUGEPAGE
  	VM_BUG_ON(address & ~HPAGE_PMD_MASK);
  #else
e2cda3226   Andrea Arcangeli   thp: add pmd mang...
75
76
  	BUG();
  #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
e2cda3226   Andrea Arcangeli   thp: add pmd mang...
77
78
79
80
81
82
83
84
85
86
87
88
89
  	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)
  {
  	pte_t pte;
  	pte = ptep_get_and_clear((vma)->vm_mm, address, ptep);
8d1acce45   Rik van Riel   mm: Only flush th...
90
91
  	if (pte_accessible(pte))
  		flush_tlb_page(vma, address);
e2cda3226   Andrea Arcangeli   thp: add pmd mang...
92
93
94
95
96
  	return pte;
  }
  #endif
  
  #ifndef __HAVE_ARCH_PMDP_CLEAR_FLUSH
b3697c025   Andrea Arcangeli   fix non-x86 build...
97
  #ifdef CONFIG_TRANSPARENT_HUGEPAGE
e2cda3226   Andrea Arcangeli   thp: add pmd mang...
98
99
100
101
  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...
102
103
104
105
106
  	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...
107
  #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
e2cda3226   Andrea Arcangeli   thp: add pmd mang...
108
109
110
  #endif
  
  #ifndef __HAVE_ARCH_PMDP_SPLITTING_FLUSH
b3697c025   Andrea Arcangeli   fix non-x86 build...
111
  #ifdef CONFIG_TRANSPARENT_HUGEPAGE
73636b1aa   Chris Metcalf   arch/tile: allow ...
112
113
  void pmdp_splitting_flush(struct vm_area_struct *vma, unsigned long address,
  			  pmd_t *pmdp)
e2cda3226   Andrea Arcangeli   thp: add pmd mang...
114
  {
e2cda3226   Andrea Arcangeli   thp: add pmd mang...
115
116
117
118
119
  	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...
120
  }
b3697c025   Andrea Arcangeli   fix non-x86 build...
121
  #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
e2cda3226   Andrea Arcangeli   thp: add pmd mang...
122
  #endif
e3ebcf643   Gerald Schaefer   thp: remove assum...
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
  
  #ifndef __HAVE_ARCH_PGTABLE_DEPOSIT
  #ifdef CONFIG_TRANSPARENT_HUGEPAGE
  void pgtable_trans_huge_deposit(struct mm_struct *mm, pgtable_t pgtable)
  {
  	assert_spin_locked(&mm->page_table_lock);
  
  	/* FIFO */
  	if (!mm->pmd_huge_pte)
  		INIT_LIST_HEAD(&pgtable->lru);
  	else
  		list_add(&pgtable->lru, &mm->pmd_huge_pte->lru);
  	mm->pmd_huge_pte = pgtable;
  }
  #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
  #endif
  
  #ifndef __HAVE_ARCH_PGTABLE_WITHDRAW
  #ifdef CONFIG_TRANSPARENT_HUGEPAGE
  /* no "address" argument so destroys page coloring of some arch */
  pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm)
  {
  	pgtable_t pgtable;
  
  	assert_spin_locked(&mm->page_table_lock);
  
  	/* FIFO */
  	pgtable = mm->pmd_huge_pte;
  	if (list_empty(&pgtable->lru))
  		mm->pmd_huge_pte = NULL;
  	else {
  		mm->pmd_huge_pte = list_entry(pgtable->lru.next,
  					      struct page, lru);
  		list_del(&pgtable->lru);
  	}
  	return pgtable;
  }
  #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
  #endif
46dcde735   Gerald Schaefer   thp: introduce pm...
162
163
164
165
166
167
168
169
170
171
172
  
  #ifndef __HAVE_ARCH_PMDP_INVALIDATE
  #ifdef CONFIG_TRANSPARENT_HUGEPAGE
  void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
  		     pmd_t *pmdp)
  {
  	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