diff options
Diffstat (limited to 'arch/x86/include/asm/pgtable-3level.h')
-rw-r--r-- | arch/x86/include/asm/pgtable-3level.h | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h index 177b0165ea0..94b979d1b58 100644 --- a/arch/x86/include/asm/pgtable-3level.h +++ b/arch/x86/include/asm/pgtable-3level.h | |||
@@ -104,6 +104,29 @@ static inline pte_t native_ptep_get_and_clear(pte_t *ptep) | |||
104 | #define native_ptep_get_and_clear(xp) native_local_ptep_get_and_clear(xp) | 104 | #define native_ptep_get_and_clear(xp) native_local_ptep_get_and_clear(xp) |
105 | #endif | 105 | #endif |
106 | 106 | ||
107 | #ifdef CONFIG_SMP | ||
108 | union split_pmd { | ||
109 | struct { | ||
110 | u32 pmd_low; | ||
111 | u32 pmd_high; | ||
112 | }; | ||
113 | pmd_t pmd; | ||
114 | }; | ||
115 | static inline pmd_t native_pmdp_get_and_clear(pmd_t *pmdp) | ||
116 | { | ||
117 | union split_pmd res, *orig = (union split_pmd *)pmdp; | ||
118 | |||
119 | /* xchg acts as a barrier before setting of the high bits */ | ||
120 | res.pmd_low = xchg(&orig->pmd_low, 0); | ||
121 | res.pmd_high = orig->pmd_high; | ||
122 | orig->pmd_high = 0; | ||
123 | |||
124 | return res.pmd; | ||
125 | } | ||
126 | #else | ||
127 | #define native_pmdp_get_and_clear(xp) native_local_pmdp_get_and_clear(xp) | ||
128 | #endif | ||
129 | |||
107 | /* | 130 | /* |
108 | * Bits 0, 6 and 7 are taken in the low part of the pte, | 131 | * Bits 0, 6 and 7 are taken in the low part of the pte, |
109 | * put the 32 bits of offset into the high part. | 132 | * put the 32 bits of offset into the high part. |