|
23 | 23 | #include <mm/mmu_decl.h> |
24 | 24 | #include <trace/events/thp.h> |
25 | 25 |
|
26 | | -#include "internal.h" |
27 | | - |
28 | 26 | struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; |
29 | 27 | EXPORT_SYMBOL_GPL(mmu_psize_defs); |
30 | 28 |
|
@@ -150,31 +148,6 @@ void set_pud_at(struct mm_struct *mm, unsigned long addr, |
150 | 148 | return set_pte_at_unchecked(mm, addr, pudp_ptep(pudp), pud_pte(pud)); |
151 | 149 | } |
152 | 150 |
|
153 | | -static void do_serialize(void *arg) |
154 | | -{ |
155 | | - /* We've taken the IPI, so try to trim the mask while here */ |
156 | | - if (radix_enabled()) { |
157 | | - struct mm_struct *mm = arg; |
158 | | - exit_lazy_flush_tlb(mm, false); |
159 | | - } |
160 | | -} |
161 | | - |
162 | | -/* |
163 | | - * Serialize against __find_linux_pte() which does lock-less |
164 | | - * lookup in page tables with local interrupts disabled. For huge pages |
165 | | - * it casts pmd_t to pte_t. Since format of pte_t is different from |
166 | | - * pmd_t we want to prevent transit from pmd pointing to page table |
167 | | - * to pmd pointing to huge page (and back) while interrupts are disabled. |
168 | | - * We clear pmd to possibly replace it with page table pointer in |
169 | | - * different code paths. So make sure we wait for the parallel |
170 | | - * __find_linux_pte() to finish. |
171 | | - */ |
172 | | -void serialize_against_pte_lookup(struct mm_struct *mm) |
173 | | -{ |
174 | | - smp_mb(); |
175 | | - smp_call_function_many(mm_cpumask(mm), do_serialize, mm, 1); |
176 | | -} |
177 | | - |
178 | 151 | /* |
179 | 152 | * We use this to invalidate a pmdp entry before switching from a |
180 | 153 | * hugepte to regular pmd entry. |
@@ -209,16 +182,21 @@ pmd_t pmdp_huge_get_and_clear_full(struct vm_area_struct *vma, |
209 | 182 | unsigned long addr, pmd_t *pmdp, int full) |
210 | 183 | { |
211 | 184 | pmd_t pmd; |
| 185 | + bool was_present = pmd_present(*pmdp); |
| 186 | + |
212 | 187 | VM_BUG_ON(addr & ~HPAGE_PMD_MASK); |
213 | | - VM_BUG_ON((pmd_present(*pmdp) && !pmd_trans_huge(*pmdp)) || |
214 | | - !pmd_present(*pmdp)); |
| 188 | + VM_BUG_ON(was_present && !pmd_trans_huge(*pmdp)); |
| 189 | + /* |
| 190 | + * Check pmdp_huge_get_and_clear() for non-present pmd case. |
| 191 | + */ |
215 | 192 | pmd = pmdp_huge_get_and_clear(vma->vm_mm, addr, pmdp); |
216 | 193 | /* |
217 | 194 | * if it not a fullmm flush, then we can possibly end up converting |
218 | 195 | * this PMD pte entry to a regular level 0 PTE by a parallel page fault. |
219 | | - * Make sure we flush the tlb in this case. |
| 196 | + * Make sure we flush the tlb in this case. TLB flush not needed for |
| 197 | + * non-present case. |
220 | 198 | */ |
221 | | - if (!full) |
| 199 | + if (was_present && !full) |
222 | 200 | flush_pmd_tlb_range(vma, addr, addr + HPAGE_PMD_SIZE); |
223 | 201 | return pmd; |
224 | 202 | } |
|
0 commit comments