[v3 02/11] mm/thp: zone_device awareness in THP handling code
kernel test robot
lkp at intel.com
Tue Aug 12 14:47:38 UTC 2025
Hi Balbir,
kernel test robot noticed the following build warnings:
[auto build test WARNING on akpm-mm/mm-everything]
url: https://github.com/intel-lab-lkp/linux/commits/Balbir-Singh/mm-zone_device-support-large-zone-device-private-folios/20250812-105145
base: https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
patch link: https://lore.kernel.org/r/20250812024036.690064-3-balbirs%40nvidia.com
patch subject: [v3 02/11] mm/thp: zone_device awareness in THP handling code
config: x86_64-randconfig-001-20250812 (https://download.01.org/0day-ci/archive/20250812/202508122212.qjsfr5Wf-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250812/202508122212.qjsfr5Wf-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202508122212.qjsfr5Wf-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> mm/migrate_device.c:154:19: warning: variable 'new_folio' set but not used [-Wunused-but-set-variable]
154 | struct folio *new_folio;
| ^
1 warning generated.
vim +/new_folio +154 mm/migrate_device.c
56
57 static int migrate_vma_collect_pmd(pmd_t *pmdp,
58 unsigned long start,
59 unsigned long end,
60 struct mm_walk *walk)
61 {
62 struct migrate_vma *migrate = walk->private;
63 struct folio *fault_folio = migrate->fault_page ?
64 page_folio(migrate->fault_page) : NULL;
65 struct vm_area_struct *vma = walk->vma;
66 struct mm_struct *mm = vma->vm_mm;
67 unsigned long addr = start, unmapped = 0;
68 spinlock_t *ptl;
69 pte_t *ptep;
70
71 again:
72 if (pmd_none(*pmdp))
73 return migrate_vma_collect_hole(start, end, -1, walk);
74
75 if (pmd_trans_huge(*pmdp)) {
76 struct folio *folio;
77
78 ptl = pmd_lock(mm, pmdp);
79 if (unlikely(!pmd_trans_huge(*pmdp))) {
80 spin_unlock(ptl);
81 goto again;
82 }
83
84 folio = pmd_folio(*pmdp);
85 if (is_huge_zero_folio(folio)) {
86 spin_unlock(ptl);
87 split_huge_pmd(vma, pmdp, addr);
88 } else {
89 int ret;
90
91 folio_get(folio);
92 spin_unlock(ptl);
93 /* FIXME: we don't expect THP for fault_folio */
94 if (WARN_ON_ONCE(fault_folio == folio))
95 return migrate_vma_collect_skip(start, end,
96 walk);
97 if (unlikely(!folio_trylock(folio)))
98 return migrate_vma_collect_skip(start, end,
99 walk);
100 ret = split_folio(folio);
101 if (fault_folio != folio)
102 folio_unlock(folio);
103 folio_put(folio);
104 if (ret)
105 return migrate_vma_collect_skip(start, end,
106 walk);
107 }
108 }
109
110 ptep = pte_offset_map_lock(mm, pmdp, addr, &ptl);
111 if (!ptep)
112 goto again;
113 arch_enter_lazy_mmu_mode();
114
115 for (; addr < end; addr += PAGE_SIZE, ptep++) {
116 struct dev_pagemap *pgmap;
117 unsigned long mpfn = 0, pfn;
118 struct folio *folio;
119 struct page *page;
120 swp_entry_t entry;
121 pte_t pte;
122
123 pte = ptep_get(ptep);
124
125 if (pte_none(pte)) {
126 if (vma_is_anonymous(vma)) {
127 mpfn = MIGRATE_PFN_MIGRATE;
128 migrate->cpages++;
129 }
130 goto next;
131 }
132
133 if (!pte_present(pte)) {
134 /*
135 * Only care about unaddressable device page special
136 * page table entry. Other special swap entries are not
137 * migratable, and we ignore regular swapped page.
138 */
139 struct folio *folio;
140
141 entry = pte_to_swp_entry(pte);
142 if (!is_device_private_entry(entry))
143 goto next;
144
145 page = pfn_swap_entry_to_page(entry);
146 pgmap = page_pgmap(page);
147 if (!(migrate->flags &
148 MIGRATE_VMA_SELECT_DEVICE_PRIVATE) ||
149 pgmap->owner != migrate->pgmap_owner)
150 goto next;
151
152 folio = page_folio(page);
153 if (folio_test_large(folio)) {
> 154 struct folio *new_folio;
155 struct folio *new_fault_folio = NULL;
156
157 /*
158 * The reason for finding pmd present with a
159 * device private pte and a large folio for the
160 * pte is partial unmaps. Split the folio now
161 * for the migration to be handled correctly
162 */
163 pte_unmap_unlock(ptep, ptl);
164
165 folio_get(folio);
166 if (folio != fault_folio)
167 folio_lock(folio);
168 if (split_folio(folio)) {
169 if (folio != fault_folio)
170 folio_unlock(folio);
171 ptep = pte_offset_map_lock(mm, pmdp, addr, &ptl);
172 goto next;
173 }
174
175 new_folio = page_folio(page);
176 if (fault_folio)
177 new_fault_folio = page_folio(migrate->fault_page);
178
179 /*
180 * Ensure the lock is held on the correct
181 * folio after the split
182 */
183 if (!new_fault_folio) {
184 folio_unlock(folio);
185 folio_put(folio);
186 } else if (folio != new_fault_folio) {
187 folio_get(new_fault_folio);
188 folio_lock(new_fault_folio);
189 folio_unlock(folio);
190 folio_put(folio);
191 }
192
193 addr = start;
194 goto again;
195 }
196
197 mpfn = migrate_pfn(page_to_pfn(page)) |
198 MIGRATE_PFN_MIGRATE;
199 if (is_writable_device_private_entry(entry))
200 mpfn |= MIGRATE_PFN_WRITE;
201 } else {
202 pfn = pte_pfn(pte);
203 if (is_zero_pfn(pfn) &&
204 (migrate->flags & MIGRATE_VMA_SELECT_SYSTEM)) {
205 mpfn = MIGRATE_PFN_MIGRATE;
206 migrate->cpages++;
207 goto next;
208 }
209 page = vm_normal_page(migrate->vma, addr, pte);
210 if (page && !is_zone_device_page(page) &&
211 !(migrate->flags & MIGRATE_VMA_SELECT_SYSTEM)) {
212 goto next;
213 } else if (page && is_device_coherent_page(page)) {
214 pgmap = page_pgmap(page);
215
216 if (!(migrate->flags &
217 MIGRATE_VMA_SELECT_DEVICE_COHERENT) ||
218 pgmap->owner != migrate->pgmap_owner)
219 goto next;
220 }
221 mpfn = migrate_pfn(pfn) | MIGRATE_PFN_MIGRATE;
222 mpfn |= pte_write(pte) ? MIGRATE_PFN_WRITE : 0;
223 }
224
225 /* FIXME support THP */
226 if (!page || !page->mapping || PageTransCompound(page)) {
227 mpfn = 0;
228 goto next;
229 }
230
231 /*
232 * By getting a reference on the folio we pin it and that blocks
233 * any kind of migration. Side effect is that it "freezes" the
234 * pte.
235 *
236 * We drop this reference after isolating the folio from the lru
237 * for non device folio (device folio are not on the lru and thus
238 * can't be dropped from it).
239 */
240 folio = page_folio(page);
241 folio_get(folio);
242
243 /*
244 * We rely on folio_trylock() to avoid deadlock between
245 * concurrent migrations where each is waiting on the others
246 * folio lock. If we can't immediately lock the folio we fail this
247 * migration as it is only best effort anyway.
248 *
249 * If we can lock the folio it's safe to set up a migration entry
250 * now. In the common case where the folio is mapped once in a
251 * single process setting up the migration entry now is an
252 * optimisation to avoid walking the rmap later with
253 * try_to_migrate().
254 */
255 if (fault_folio == folio || folio_trylock(folio)) {
256 bool anon_exclusive;
257 pte_t swp_pte;
258
259 flush_cache_page(vma, addr, pte_pfn(pte));
260 anon_exclusive = folio_test_anon(folio) &&
261 PageAnonExclusive(page);
262 if (anon_exclusive) {
263 pte = ptep_clear_flush(vma, addr, ptep);
264
265 if (folio_try_share_anon_rmap_pte(folio, page)) {
266 set_pte_at(mm, addr, ptep, pte);
267 if (fault_folio != folio)
268 folio_unlock(folio);
269 folio_put(folio);
270 mpfn = 0;
271 goto next;
272 }
273 } else {
274 pte = ptep_get_and_clear(mm, addr, ptep);
275 }
276
277 migrate->cpages++;
278
279 /* Set the dirty flag on the folio now the pte is gone. */
280 if (pte_dirty(pte))
281 folio_mark_dirty(folio);
282
283 /* Setup special migration page table entry */
284 if (mpfn & MIGRATE_PFN_WRITE)
285 entry = make_writable_migration_entry(
286 page_to_pfn(page));
287 else if (anon_exclusive)
288 entry = make_readable_exclusive_migration_entry(
289 page_to_pfn(page));
290 else
291 entry = make_readable_migration_entry(
292 page_to_pfn(page));
293 if (pte_present(pte)) {
294 if (pte_young(pte))
295 entry = make_migration_entry_young(entry);
296 if (pte_dirty(pte))
297 entry = make_migration_entry_dirty(entry);
298 }
299 swp_pte = swp_entry_to_pte(entry);
300 if (pte_present(pte)) {
301 if (pte_soft_dirty(pte))
302 swp_pte = pte_swp_mksoft_dirty(swp_pte);
303 if (pte_uffd_wp(pte))
304 swp_pte = pte_swp_mkuffd_wp(swp_pte);
305 } else {
306 if (pte_swp_soft_dirty(pte))
307 swp_pte = pte_swp_mksoft_dirty(swp_pte);
308 if (pte_swp_uffd_wp(pte))
309 swp_pte = pte_swp_mkuffd_wp(swp_pte);
310 }
311 set_pte_at(mm, addr, ptep, swp_pte);
312
313 /*
314 * This is like regular unmap: we remove the rmap and
315 * drop the folio refcount. The folio won't be freed, as
316 * we took a reference just above.
317 */
318 folio_remove_rmap_pte(folio, page, vma);
319 folio_put(folio);
320
321 if (pte_present(pte))
322 unmapped++;
323 } else {
324 folio_put(folio);
325 mpfn = 0;
326 }
327
328 next:
329 migrate->dst[migrate->npages] = 0;
330 migrate->src[migrate->npages++] = mpfn;
331 }
332
333 /* Only flush the TLB if we actually modified any entries */
334 if (unmapped)
335 flush_tlb_range(walk->vma, start, end);
336
337 arch_leave_lazy_mmu_mode();
338 pte_unmap_unlock(ptep - 1, ptl);
339
340 return 0;
341 }
342
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
More information about the dri-devel
mailing list