Skip to content

Commit b7301f2

Browse files
Peter Zijlstrahansendc
authored andcommitted
x86/mm/pae: Be consistent with pXXp_get_and_clear()
Given that ptep_get_and_clear() uses cmpxchg8b, and that should be by far the most common case, there's no point in having an optimized variant for pmd/pud. Introduce the pxx_xchg64() helper to implement the common logic once. Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Link: https://lkml.kernel.org/r/20221022114425.103392961%40infradead.org
1 parent f7bcd46 commit b7301f2

File tree

1 file changed

+17
-50
lines changed

1 file changed

+17
-50
lines changed

arch/x86/include/asm/pgtable-3level.h

Lines changed: 17 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -90,34 +90,33 @@ static inline void pud_clear(pud_t *pudp)
9090
*/
9191
}
9292

93+
94+
#define pxx_xchg64(_pxx, _ptr, _val) ({ \
95+
_pxx##val_t *_p = (_pxx##val_t *)_ptr; \
96+
_pxx##val_t _o = *_p; \
97+
do { } while (!try_cmpxchg64(_p, &_o, (_val))); \
98+
native_make_##_pxx(_o); \
99+
})
100+
93101
#ifdef CONFIG_SMP
94102
static inline pte_t native_ptep_get_and_clear(pte_t *ptep)
95103
{
96-
pte_t old = *ptep;
97-
98-
do {
99-
} while (!try_cmpxchg64(&ptep->pte, &old.pte, 0ULL));
100-
101-
return old;
104+
return pxx_xchg64(pte, ptep, 0ULL);
102105
}
103-
#else
104-
#define native_ptep_get_and_clear(xp) native_local_ptep_get_and_clear(xp)
105-
#endif
106106

107-
#ifdef CONFIG_SMP
108107
static inline pmd_t native_pmdp_get_and_clear(pmd_t *pmdp)
109108
{
110-
pmd_t res;
111-
112-
/* xchg acts as a barrier before setting of the high bits */
113-
res.pmd_low = xchg(&pmdp->pmd_low, 0);
114-
res.pmd_high = READ_ONCE(pmdp->pmd_high);
115-
WRITE_ONCE(pmdp->pmd_high, 0);
109+
return pxx_xchg64(pmd, pmdp, 0ULL);
110+
}
116111

117-
return res;
112+
static inline pud_t native_pudp_get_and_clear(pud_t *pudp)
113+
{
114+
return pxx_xchg64(pud, pudp, 0ULL);
118115
}
119116
#else
117+
#define native_ptep_get_and_clear(xp) native_local_ptep_get_and_clear(xp)
120118
#define native_pmdp_get_and_clear(xp) native_local_pmdp_get_and_clear(xp)
119+
#define native_pudp_get_and_clear(xp) native_local_pudp_get_and_clear(xp)
121120
#endif
122121

123122
#ifndef pmdp_establish
@@ -141,42 +140,10 @@ static inline pmd_t pmdp_establish(struct vm_area_struct *vma,
141140
return old;
142141
}
143142

144-
do {
145-
old = *pmdp;
146-
} while (cmpxchg64(&pmdp->pmd, old.pmd, pmd.pmd) != old.pmd);
147-
148-
return old;
143+
return pxx_xchg64(pmd, pmdp, pmd.pmd);
149144
}
150145
#endif
151146

152-
#ifdef CONFIG_SMP
153-
union split_pud {
154-
struct {
155-
u32 pud_low;
156-
u32 pud_high;
157-
};
158-
pud_t pud;
159-
};
160-
161-
static inline pud_t native_pudp_get_and_clear(pud_t *pudp)
162-
{
163-
union split_pud res, *orig = (union split_pud *)pudp;
164-
165-
#ifdef CONFIG_PAGE_TABLE_ISOLATION
166-
pti_set_user_pgtbl(&pudp->p4d.pgd, __pgd(0));
167-
#endif
168-
169-
/* xchg acts as a barrier before setting of the high bits */
170-
res.pud_low = xchg(&orig->pud_low, 0);
171-
res.pud_high = orig->pud_high;
172-
orig->pud_high = 0;
173-
174-
return res.pud;
175-
}
176-
#else
177-
#define native_pudp_get_and_clear(xp) native_local_pudp_get_and_clear(xp)
178-
#endif
179-
180147
/* Encode and de-code a swap entry */
181148
#define SWP_TYPE_BITS 5
182149

0 commit comments

Comments
 (0)