@@ -76,9 +76,9 @@ static void undo_dev_pagemap(int *nr, int nr_start, struct page **pages)
76
76
}
77
77
78
78
/*
79
- * 'pteval' can come from a pte, pmd or pud . We only check
79
+ * 'pteval' can come from a pte, pmd, pud or p4d . We only check
80
80
* _PAGE_PRESENT, _PAGE_USER, and _PAGE_RW in here which are the
81
- * same value on all 3 types.
81
+ * same value on all 4 types.
82
82
*/
83
83
static inline int pte_allows_gup (unsigned long pteval , int write )
84
84
{
@@ -295,13 +295,13 @@ static noinline int gup_huge_pud(pud_t pud, unsigned long addr,
295
295
return 1 ;
296
296
}
297
297
298
- static int gup_pud_range (pgd_t pgd , unsigned long addr , unsigned long end ,
298
+ static int gup_pud_range (p4d_t p4d , unsigned long addr , unsigned long end ,
299
299
int write , struct page * * pages , int * nr )
300
300
{
301
301
unsigned long next ;
302
302
pud_t * pudp ;
303
303
304
- pudp = pud_offset (& pgd , addr );
304
+ pudp = pud_offset (& p4d , addr );
305
305
do {
306
306
pud_t pud = * pudp ;
307
307
@@ -320,6 +320,27 @@ static int gup_pud_range(pgd_t pgd, unsigned long addr, unsigned long end,
320
320
return 1 ;
321
321
}
322
322
323
+ static int gup_p4d_range (pgd_t pgd , unsigned long addr , unsigned long end ,
324
+ int write , struct page * * pages , int * nr )
325
+ {
326
+ unsigned long next ;
327
+ p4d_t * p4dp ;
328
+
329
+ p4dp = p4d_offset (& pgd , addr );
330
+ do {
331
+ p4d_t p4d = * p4dp ;
332
+
333
+ next = p4d_addr_end (addr , end );
334
+ if (p4d_none (p4d ))
335
+ return 0 ;
336
+ BUILD_BUG_ON (p4d_large (p4d ));
337
+ if (!gup_pud_range (p4d , addr , next , write , pages , nr ))
338
+ return 0 ;
339
+ } while (p4dp ++ , addr = next , addr != end );
340
+
341
+ return 1 ;
342
+ }
343
+
323
344
/*
324
345
* Like get_user_pages_fast() except its IRQ-safe in that it won't fall
325
346
* back to the regular GUP.
@@ -368,7 +389,7 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
368
389
next = pgd_addr_end (addr , end );
369
390
if (pgd_none (pgd ))
370
391
break ;
371
- if (!gup_pud_range (pgd , addr , next , write , pages , & nr ))
392
+ if (!gup_p4d_range (pgd , addr , next , write , pages , & nr ))
372
393
break ;
373
394
} while (pgdp ++ , addr = next , addr != end );
374
395
local_irq_restore (flags );
@@ -440,7 +461,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
440
461
next = pgd_addr_end (addr , end );
441
462
if (pgd_none (pgd ))
442
463
goto slow ;
443
- if (!gup_pud_range (pgd , addr , next , write , pages , & nr ))
464
+ if (!gup_p4d_range (pgd , addr , next , write , pages , & nr ))
444
465
goto slow ;
445
466
} while (pgdp ++ , addr = next , addr != end );
446
467
local_irq_enable ();
0 commit comments