Skip to content

Commit 7eb43fb

Browse files
committed
mm: remove follow_pte()
jira LE-3557 Rebuild_History Non-Buildable kernel-5.14.0-570.26.1.el9_6 commit-author Peter Xu <[email protected]> commit b0a1c0d Empty-Commit: Cherry-Pick Conflicts during history rebuild. Will be included in final tarball splat. Ref for failed cherry-pick at: ciq/ciq_backports/kernel-5.14.0-570.26.1.el9_6/b0a1c0d0.failed follow_pte() users have been converted to follow_pfnmap*(). Remove the API. Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Peter Xu <[email protected]> Cc: Alexander Gordeev <[email protected]> Cc: Alex Williamson <[email protected]> Cc: Aneesh Kumar K.V <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: Catalin Marinas <[email protected]> Cc: Christian Borntraeger <[email protected]> Cc: Dave Hansen <[email protected]> Cc: David Hildenbrand <[email protected]> Cc: Gavin Shan <[email protected]> Cc: Gerald Schaefer <[email protected]> Cc: Heiko Carstens <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Jason Gunthorpe <[email protected]> Cc: Matthew Wilcox <[email protected]> Cc: Niklas Schnelle <[email protected]> Cc: Paolo Bonzini <[email protected]> Cc: Ryan Roberts <[email protected]> Cc: Sean Christopherson <[email protected]> Cc: Sven Schnelle <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Vasily Gorbik <[email protected]> Cc: Will Deacon <[email protected]> Cc: Zi Yan <[email protected]> Signed-off-by: Andrew Morton <[email protected]> (cherry picked from commit b0a1c0d) Signed-off-by: Jonathan Maple <[email protected]> # Conflicts: # include/linux/mm.h # mm/memory.c
1 parent 5de61c7 commit 7eb43fb

File tree

1 file changed

+335
-0
lines changed

1 file changed

+335
-0
lines changed
Lines changed: 335 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,335 @@
1+
mm: remove follow_pte()
2+
3+
jira LE-3557
4+
Rebuild_History Non-Buildable kernel-5.14.0-570.26.1.el9_6
5+
commit-author Peter Xu <[email protected]>
6+
commit b0a1c0d0edcd75a0f8ec5fd19dbd64b8d097f534
7+
Empty-Commit: Cherry-Pick Conflicts during history rebuild.
8+
Will be included in final tarball splat. Ref for failed cherry-pick at:
9+
ciq/ciq_backports/kernel-5.14.0-570.26.1.el9_6/b0a1c0d0.failed
10+
11+
follow_pte() users have been converted to follow_pfnmap*(). Remove the
12+
API.
13+
14+
Link: https://lkml.kernel.org/r/[email protected]
15+
Signed-off-by: Peter Xu <[email protected]>
16+
Cc: Alexander Gordeev <[email protected]>
17+
Cc: Alex Williamson <[email protected]>
18+
Cc: Aneesh Kumar K.V <[email protected]>
19+
Cc: Borislav Petkov <[email protected]>
20+
Cc: Catalin Marinas <[email protected]>
21+
Cc: Christian Borntraeger <[email protected]>
22+
Cc: Dave Hansen <[email protected]>
23+
Cc: David Hildenbrand <[email protected]>
24+
Cc: Gavin Shan <[email protected]>
25+
Cc: Gerald Schaefer <[email protected]>
26+
Cc: Heiko Carstens <[email protected]>
27+
Cc: Ingo Molnar <[email protected]>
28+
Cc: Jason Gunthorpe <[email protected]>
29+
Cc: Matthew Wilcox <[email protected]>
30+
Cc: Niklas Schnelle <[email protected]>
31+
Cc: Paolo Bonzini <[email protected]>
32+
Cc: Ryan Roberts <[email protected]>
33+
Cc: Sean Christopherson <[email protected]>
34+
Cc: Sven Schnelle <[email protected]>
35+
Cc: Thomas Gleixner <[email protected]>
36+
Cc: Vasily Gorbik <[email protected]>
37+
Cc: Will Deacon <[email protected]>
38+
Cc: Zi Yan <[email protected]>
39+
Signed-off-by: Andrew Morton <[email protected]>
40+
(cherry picked from commit b0a1c0d0edcd75a0f8ec5fd19dbd64b8d097f534)
41+
Signed-off-by: Jonathan Maple <[email protected]>
42+
43+
# Conflicts:
44+
# include/linux/mm.h
45+
# mm/memory.c
46+
diff --cc include/linux/mm.h
47+
index 196c481ec160,d750be768121..000000000000
48+
--- a/include/linux/mm.h
49+
+++ b/include/linux/mm.h
50+
@@@ -2427,12 -2368,6 +2427,15 @@@ void free_pgd_range(struct mmu_gather *
51+
unsigned long end, unsigned long floor, unsigned long ceiling);
52+
int
53+
copy_page_range(struct vm_area_struct *dst_vma, struct vm_area_struct *src_vma);
54+
++<<<<<<< HEAD
55+
+int follow_pte(struct mm_struct *mm, unsigned long address,
56+
+ pte_t **ptepp, spinlock_t **ptlp);
57+
+int follow_pfn(struct vm_area_struct *vma, unsigned long address,
58+
+ unsigned long *pfn);
59+
+int follow_phys(struct vm_area_struct *vma, unsigned long address,
60+
+ unsigned int flags, unsigned long *prot, resource_size_t *phys);
61+
++=======
62+
++>>>>>>> b0a1c0d0edcd (mm: remove follow_pte())
63+
int generic_access_phys(struct vm_area_struct *vma, unsigned long addr,
64+
void *buf, int len, int write);
65+
66+
diff --cc mm/memory.c
67+
index e2794e3b8919,42674c0748cb..000000000000
68+
--- a/mm/memory.c
69+
+++ b/mm/memory.c
70+
@@@ -5607,130 -6099,157 +5607,159 @@@ int __pmd_alloc(struct mm_struct *mm, p
71+
}
72+
#endif /* __PAGETABLE_PMD_FOLDED */
73+
74+
++<<<<<<< HEAD
75+
+/**
76+
+ * follow_pte - look up PTE at a user virtual address
77+
+ * @mm: the mm_struct of the target address space
78+
+ * @address: user virtual address
79+
+ * @ptepp: location to store found PTE
80+
+ * @ptlp: location to store the lock for the PTE
81+
+ *
82+
+ * On a successful return, the pointer to the PTE is stored in @ptepp;
83+
+ * the corresponding lock is taken and its location is stored in @ptlp.
84+
+ * The contents of the PTE are only stable until @ptlp is released;
85+
+ * any further use, if any, must be protected against invalidation
86+
+ * with MMU notifiers.
87+
+ *
88+
+ * Only IO mappings and raw PFN mappings are allowed. The mmap semaphore
89+
+ * should be taken for read.
90+
+ *
91+
+ * KVM uses this function. While it is arguably less bad than ``follow_pfn``,
92+
+ * it is not a good general-purpose API.
93+
+ *
94+
+ * Return: zero on success, -ve otherwise.
95+
+ */
96+
+int follow_pte(struct mm_struct *mm, unsigned long address,
97+
+ pte_t **ptepp, spinlock_t **ptlp)
98+
+{
99+
+ pgd_t *pgd;
100+
+ p4d_t *p4d;
101+
+ pud_t *pud;
102+
+ pmd_t *pmd;
103+
+ pte_t *ptep;
104+
+
105+
+ pgd = pgd_offset(mm, address);
106+
+ if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
107+
+ goto out;
108+
+
109+
+ p4d = p4d_offset(pgd, address);
110+
+ if (p4d_none(*p4d) || unlikely(p4d_bad(*p4d)))
111+
+ goto out;
112+
+
113+
+ pud = pud_offset(p4d, address);
114+
+ if (pud_none(*pud) || unlikely(pud_bad(*pud)))
115+
+ goto out;
116+
+
117+
+ pmd = pmd_offset(pud, address);
118+
+ VM_BUG_ON(pmd_trans_huge(*pmd));
119+
+
120+
+ ptep = pte_offset_map_lock(mm, pmd, address, ptlp);
121+
+ if (!ptep)
122+
+ goto out;
123+
+ if (!pte_present(ptep_get(ptep)))
124+
+ goto unlock;
125+
+ *ptepp = ptep;
126+
+ return 0;
127+
+unlock:
128+
+ pte_unmap_unlock(ptep, *ptlp);
129+
+out:
130+
+ return -EINVAL;
131+
+}
132+
+EXPORT_SYMBOL_GPL(follow_pte);
133+
++=======
134+
+ static inline void pfnmap_args_setup(struct follow_pfnmap_args *args,
135+
+ spinlock_t *lock, pte_t *ptep,
136+
+ pgprot_t pgprot, unsigned long pfn_base,
137+
+ unsigned long addr_mask, bool writable,
138+
+ bool special)
139+
+ {
140+
+ args->lock = lock;
141+
+ args->ptep = ptep;
142+
+ args->pfn = pfn_base + ((args->address & ~addr_mask) >> PAGE_SHIFT);
143+
+ args->pgprot = pgprot;
144+
+ args->writable = writable;
145+
+ args->special = special;
146+
+ }
147+
+
148+
+ static inline void pfnmap_lockdep_assert(struct vm_area_struct *vma)
149+
+ {
150+
+ #ifdef CONFIG_LOCKDEP
151+
+ struct address_space *mapping = vma->vm_file->f_mapping;
152+
+
153+
+ if (mapping)
154+
+ lockdep_assert(lockdep_is_held(&vma->vm_file->f_mapping->i_mmap_rwsem) ||
155+
+ lockdep_is_held(&vma->vm_mm->mmap_lock));
156+
+ else
157+
+ lockdep_assert(lockdep_is_held(&vma->vm_mm->mmap_lock));
158+
+ #endif
159+
+ }
160+
++>>>>>>> b0a1c0d0edcd (mm: remove follow_pte())
161+
162+
/**
163+
- * follow_pfnmap_start() - Look up a pfn mapping at a user virtual address
164+
- * @args: Pointer to struct @follow_pfnmap_args
165+
+ * follow_pfn - look up PFN at a user virtual address
166+
+ * @vma: memory mapping
167+
+ * @address: user virtual address
168+
+ * @pfn: location to store found PFN
169+
*
170+
- * The caller needs to setup args->vma and args->address to point to the
171+
- * virtual address as the target of such lookup. On a successful return,
172+
- * the results will be put into other output fields.
173+
+ * Only IO mappings and raw PFN mappings are allowed.
174+
*
175+
- * After the caller finished using the fields, the caller must invoke
176+
- * another follow_pfnmap_end() to proper releases the locks and resources
177+
- * of such look up request.
178+
+ * This function does not allow the caller to read the permissions
179+
+ * of the PTE. Do not use it.
180+
*
181+
- * During the start() and end() calls, the results in @args will be valid
182+
- * as proper locks will be held. After the end() is called, all the fields
183+
- * in @follow_pfnmap_args will be invalid to be further accessed. Further
184+
- * use of such information after end() may require proper synchronizations
185+
- * by the caller with page table updates, otherwise it can create a
186+
- * security bug.
187+
- *
188+
- * If the PTE maps a refcounted page, callers are responsible to protect
189+
- * against invalidation with MMU notifiers; otherwise access to the PFN at
190+
- * a later point in time can trigger use-after-free.
191+
- *
192+
- * Only IO mappings and raw PFN mappings are allowed. The mmap semaphore
193+
- * should be taken for read, and the mmap semaphore cannot be released
194+
- * before the end() is invoked.
195+
- *
196+
- * This function must not be used to modify PTE content.
197+
- *
198+
- * Return: zero on success, negative otherwise.
199+
+ * Return: zero and the pfn at @pfn on success, -ve otherwise.
200+
*/
201+
-int follow_pfnmap_start(struct follow_pfnmap_args *args)
202+
+int follow_pfn(struct vm_area_struct *vma, unsigned long address,
203+
+ unsigned long *pfn)
204+
{
205+
- struct vm_area_struct *vma = args->vma;
206+
- unsigned long address = args->address;
207+
- struct mm_struct *mm = vma->vm_mm;
208+
- spinlock_t *lock;
209+
- pgd_t *pgdp;
210+
- p4d_t *p4dp, p4d;
211+
- pud_t *pudp, pud;
212+
- pmd_t *pmdp, pmd;
213+
- pte_t *ptep, pte;
214+
+ int ret = -EINVAL;
215+
+ spinlock_t *ptl;
216+
+ pte_t *ptep;
217+
218+
- pfnmap_lockdep_assert(vma);
219+
+ if (!(vma->vm_flags & (VM_IO | VM_PFNMAP)))
220+
+ return ret;
221+
222+
- if (unlikely(address < vma->vm_start || address >= vma->vm_end))
223+
- goto out;
224+
+ ret = follow_pte(vma->vm_mm, address, &ptep, &ptl);
225+
+ if (ret)
226+
+ return ret;
227+
+ *pfn = pte_pfn(ptep_get(ptep));
228+
+ pte_unmap_unlock(ptep, ptl);
229+
+ return 0;
230+
+}
231+
+EXPORT_SYMBOL(follow_pfn);
232+
233+
- if (!(vma->vm_flags & (VM_IO | VM_PFNMAP)))
234+
- goto out;
235+
-retry:
236+
- pgdp = pgd_offset(mm, address);
237+
- if (pgd_none(*pgdp) || unlikely(pgd_bad(*pgdp)))
238+
- goto out;
239+
+#ifdef CONFIG_HAVE_IOREMAP_PROT
240+
+int follow_phys(struct vm_area_struct *vma,
241+
+ unsigned long address, unsigned int flags,
242+
+ unsigned long *prot, resource_size_t *phys)
243+
+{
244+
+ int ret = -EINVAL;
245+
+ pte_t *ptep, pte;
246+
+ spinlock_t *ptl;
247+
248+
- p4dp = p4d_offset(pgdp, address);
249+
- p4d = READ_ONCE(*p4dp);
250+
- if (p4d_none(p4d) || unlikely(p4d_bad(p4d)))
251+
+ if (!(vma->vm_flags & (VM_IO | VM_PFNMAP)))
252+
goto out;
253+
254+
- pudp = pud_offset(p4dp, address);
255+
- pud = READ_ONCE(*pudp);
256+
- if (pud_none(pud))
257+
+ if (follow_pte(vma->vm_mm, address, &ptep, &ptl))
258+
goto out;
259+
- if (pud_leaf(pud)) {
260+
- lock = pud_lock(mm, pudp);
261+
- if (!unlikely(pud_leaf(pud))) {
262+
- spin_unlock(lock);
263+
- goto retry;
264+
- }
265+
- pfnmap_args_setup(args, lock, NULL, pud_pgprot(pud),
266+
- pud_pfn(pud), PUD_MASK, pud_write(pud),
267+
- pud_special(pud));
268+
- return 0;
269+
- }
270+
+ pte = ptep_get(ptep);
271+
272+
- pmdp = pmd_offset(pudp, address);
273+
- pmd = pmdp_get_lockless(pmdp);
274+
- if (pmd_leaf(pmd)) {
275+
- lock = pmd_lock(mm, pmdp);
276+
- if (!unlikely(pmd_leaf(pmd))) {
277+
- spin_unlock(lock);
278+
- goto retry;
279+
- }
280+
- pfnmap_args_setup(args, lock, NULL, pmd_pgprot(pmd),
281+
- pmd_pfn(pmd), PMD_MASK, pmd_write(pmd),
282+
- pmd_special(pmd));
283+
- return 0;
284+
- }
285+
+ /* Never return PFNs of anon folios in COW mappings. */
286+
+ if (vm_normal_folio(vma, address, pte))
287+
+ goto unlock;
288+
289+
- ptep = pte_offset_map_lock(mm, pmdp, address, &lock);
290+
- if (!ptep)
291+
- goto out;
292+
- pte = ptep_get(ptep);
293+
- if (!pte_present(pte))
294+
+ if ((flags & FOLL_WRITE) && !pte_write(pte))
295+
goto unlock;
296+
- pfnmap_args_setup(args, lock, ptep, pte_pgprot(pte),
297+
- pte_pfn(pte), PAGE_MASK, pte_write(pte),
298+
- pte_special(pte));
299+
- return 0;
300+
+
301+
+ *prot = pgprot_val(pte_pgprot(pte));
302+
+ *phys = (resource_size_t)pte_pfn(pte) << PAGE_SHIFT;
303+
+
304+
+ ret = 0;
305+
unlock:
306+
- pte_unmap_unlock(ptep, lock);
307+
+ pte_unmap_unlock(ptep, ptl);
308+
out:
309+
- return -EINVAL;
310+
-}
311+
-EXPORT_SYMBOL_GPL(follow_pfnmap_start);
312+
-
313+
-/**
314+
- * follow_pfnmap_end(): End a follow_pfnmap_start() process
315+
- * @args: Pointer to struct @follow_pfnmap_args
316+
- *
317+
- * Must be used in pair of follow_pfnmap_start(). See the start() function
318+
- * above for more information.
319+
- */
320+
-void follow_pfnmap_end(struct follow_pfnmap_args *args)
321+
-{
322+
- if (args->lock)
323+
- spin_unlock(args->lock);
324+
- if (args->ptep)
325+
- pte_unmap(args->ptep);
326+
+ return ret;
327+
}
328+
-EXPORT_SYMBOL_GPL(follow_pfnmap_end);
329+
330+
-#ifdef CONFIG_HAVE_IOREMAP_PROT
331+
/**
332+
* generic_access_phys - generic implementation for iomem mmap access
333+
* @vma: the vma to access
334+
* Unmerged path include/linux/mm.h
335+
* Unmerged path mm/memory.c

0 commit comments

Comments
 (0)