diff options
Diffstat (limited to 'include/asm-generic/pgtable.h')
-rw-r--r-- | include/asm-generic/pgtable.h | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h index e2768f188f55..6f2b45a9b6bc 100644 --- a/include/asm-generic/pgtable.h +++ b/include/asm-generic/pgtable.h | |||
@@ -445,6 +445,18 @@ static inline int pmd_write(pmd_t pmd) | |||
445 | #endif /* __HAVE_ARCH_PMD_WRITE */ | 445 | #endif /* __HAVE_ARCH_PMD_WRITE */ |
446 | #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ | 446 | #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ |
447 | 447 | ||
448 | #ifndef pmd_read_atomic | ||
449 | static inline pmd_t pmd_read_atomic(pmd_t *pmdp) | ||
450 | { | ||
451 | /* | ||
452 | * Depend on compiler for an atomic pmd read. NOTE: this is | ||
453 | * only going to work, if the pmdval_t isn't larger than | ||
454 | * an unsigned long. | ||
455 | */ | ||
456 | return *pmdp; | ||
457 | } | ||
458 | #endif | ||
459 | |||
448 | /* | 460 | /* |
449 | * This function is meant to be used by sites walking pagetables with | 461 | * This function is meant to be used by sites walking pagetables with |
450 | * the mmap_sem hold in read mode to protect against MADV_DONTNEED and | 462 | * the mmap_sem hold in read mode to protect against MADV_DONTNEED and |
@@ -458,11 +470,17 @@ static inline int pmd_write(pmd_t pmd) | |||
458 | * undefined so behaving like if the pmd was none is safe (because it | 470 | * undefined so behaving like if the pmd was none is safe (because it |
459 | * can return none anyway). The compiler level barrier() is critically | 471 | * can return none anyway). The compiler level barrier() is critically |
460 | * important to compute the two checks atomically on the same pmdval. | 472 | * important to compute the two checks atomically on the same pmdval. |
473 | * | ||
474 | * For 32bit kernels with a 64bit large pmd_t this automatically takes | ||
475 | * care of reading the pmd atomically to avoid SMP race conditions | ||
476 | * against pmd_populate() when the mmap_sem is hold for reading by the | ||
477 | * caller (a special atomic read not done by "gcc" as in the generic | ||
478 | * version above, is also needed when THP is disabled because the page | ||
479 | * fault can populate the pmd from under us). | ||
461 | */ | 480 | */ |
462 | static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd) | 481 | static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd) |
463 | { | 482 | { |
464 | /* depend on compiler for an atomic pmd read */ | 483 | pmd_t pmdval = pmd_read_atomic(pmd); |
465 | pmd_t pmdval = *pmd; | ||
466 | /* | 484 | /* |
467 | * The barrier will stabilize the pmdval in a register or on | 485 | * The barrier will stabilize the pmdval in a register or on |
468 | * the stack so that it will stop changing under the code. | 486 | * the stack so that it will stop changing under the code. |