aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm64/include/asm/pgtable.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm64/include/asm/pgtable.h')
-rw-r--r--arch/arm64/include/asm/pgtable.h23
1 files changed, 13 insertions, 10 deletions
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 094374c82db0..7e2c27e63cd8 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -218,7 +218,7 @@ static inline pmd_t pmd_mkcont(pmd_t pmd)
218 218
219static inline void set_pte(pte_t *ptep, pte_t pte) 219static inline void set_pte(pte_t *ptep, pte_t pte)
220{ 220{
221 *ptep = pte; 221 WRITE_ONCE(*ptep, pte);
222 222
223 /* 223 /*
224 * Only if the new pte is valid and kernel, otherwise TLB maintenance 224 * Only if the new pte is valid and kernel, otherwise TLB maintenance
@@ -250,6 +250,8 @@ extern void __sync_icache_dcache(pte_t pteval, unsigned long addr);
250static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, 250static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
251 pte_t *ptep, pte_t pte) 251 pte_t *ptep, pte_t pte)
252{ 252{
253 pte_t old_pte;
254
253 if (pte_present(pte) && pte_user_exec(pte) && !pte_special(pte)) 255 if (pte_present(pte) && pte_user_exec(pte) && !pte_special(pte))
254 __sync_icache_dcache(pte, addr); 256 __sync_icache_dcache(pte, addr);
255 257
@@ -258,14 +260,15 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
258 * hardware updates of the pte (ptep_set_access_flags safely changes 260 * hardware updates of the pte (ptep_set_access_flags safely changes
259 * valid ptes without going through an invalid entry). 261 * valid ptes without going through an invalid entry).
260 */ 262 */
261 if (IS_ENABLED(CONFIG_DEBUG_VM) && pte_valid(*ptep) && pte_valid(pte) && 263 old_pte = READ_ONCE(*ptep);
264 if (IS_ENABLED(CONFIG_DEBUG_VM) && pte_valid(old_pte) && pte_valid(pte) &&
262 (mm == current->active_mm || atomic_read(&mm->mm_users) > 1)) { 265 (mm == current->active_mm || atomic_read(&mm->mm_users) > 1)) {
263 VM_WARN_ONCE(!pte_young(pte), 266 VM_WARN_ONCE(!pte_young(pte),
264 "%s: racy access flag clearing: 0x%016llx -> 0x%016llx", 267 "%s: racy access flag clearing: 0x%016llx -> 0x%016llx",
265 __func__, pte_val(*ptep), pte_val(pte)); 268 __func__, pte_val(old_pte), pte_val(pte));
266 VM_WARN_ONCE(pte_write(*ptep) && !pte_dirty(pte), 269 VM_WARN_ONCE(pte_write(old_pte) && !pte_dirty(pte),
267 "%s: racy dirty state clearing: 0x%016llx -> 0x%016llx", 270 "%s: racy dirty state clearing: 0x%016llx -> 0x%016llx",
268 __func__, pte_val(*ptep), pte_val(pte)); 271 __func__, pte_val(old_pte), pte_val(pte));
269 } 272 }
270 273
271 set_pte(ptep, pte); 274 set_pte(ptep, pte);
@@ -431,7 +434,7 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
431 434
432static inline void set_pmd(pmd_t *pmdp, pmd_t pmd) 435static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
433{ 436{
434 *pmdp = pmd; 437 WRITE_ONCE(*pmdp, pmd);
435 dsb(ishst); 438 dsb(ishst);
436 isb(); 439 isb();
437} 440}
@@ -482,7 +485,7 @@ static inline phys_addr_t pmd_page_paddr(pmd_t pmd)
482 485
483static inline void set_pud(pud_t *pudp, pud_t pud) 486static inline void set_pud(pud_t *pudp, pud_t pud)
484{ 487{
485 *pudp = pud; 488 WRITE_ONCE(*pudp, pud);
486 dsb(ishst); 489 dsb(ishst);
487 isb(); 490 isb();
488} 491}
@@ -500,7 +503,7 @@ static inline phys_addr_t pud_page_paddr(pud_t pud)
500/* Find an entry in the second-level page table. */ 503/* Find an entry in the second-level page table. */
501#define pmd_index(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) 504#define pmd_index(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
502 505
503#define pmd_offset_phys(dir, addr) (pud_page_paddr(*(dir)) + pmd_index(addr) * sizeof(pmd_t)) 506#define pmd_offset_phys(dir, addr) (pud_page_paddr(READ_ONCE(*(dir))) + pmd_index(addr) * sizeof(pmd_t))
504#define pmd_offset(dir, addr) ((pmd_t *)__va(pmd_offset_phys((dir), (addr)))) 507#define pmd_offset(dir, addr) ((pmd_t *)__va(pmd_offset_phys((dir), (addr))))
505 508
506#define pmd_set_fixmap(addr) ((pmd_t *)set_fixmap_offset(FIX_PMD, addr)) 509#define pmd_set_fixmap(addr) ((pmd_t *)set_fixmap_offset(FIX_PMD, addr))
@@ -535,7 +538,7 @@ static inline phys_addr_t pud_page_paddr(pud_t pud)
535 538
536static inline void set_pgd(pgd_t *pgdp, pgd_t pgd) 539static inline void set_pgd(pgd_t *pgdp, pgd_t pgd)
537{ 540{
538 *pgdp = pgd; 541 WRITE_ONCE(*pgdp, pgd);
539 dsb(ishst); 542 dsb(ishst);
540} 543}
541 544
@@ -552,7 +555,7 @@ static inline phys_addr_t pgd_page_paddr(pgd_t pgd)
552/* Find an entry in the frst-level page table. */ 555/* Find an entry in the frst-level page table. */
553#define pud_index(addr) (((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1)) 556#define pud_index(addr) (((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1))
554 557
555#define pud_offset_phys(dir, addr) (pgd_page_paddr(*(dir)) + pud_index(addr) * sizeof(pud_t)) 558#define pud_offset_phys(dir, addr) (pgd_page_paddr(READ_ONCE(*(dir))) + pud_index(addr) * sizeof(pud_t))
556#define pud_offset(dir, addr) ((pud_t *)__va(pud_offset_phys((dir), (addr)))) 559#define pud_offset(dir, addr) ((pud_t *)__va(pud_offset_phys((dir), (addr))))
557 560
558#define pud_set_fixmap(addr) ((pud_t *)set_fixmap_offset(FIX_PUD, addr)) 561#define pud_set_fixmap(addr) ((pud_t *)set_fixmap_offset(FIX_PUD, addr))