Skip to content

Commit f89b399

Browse files
Ryan Robertswilldeacon
authored andcommitted
arm64/mm: Hoist barriers out of set_ptes_anysz() loop
set_ptes_anysz() previously called __set_pte() for each PTE in the range, which would conditionally issue a DSB and ISB to make the new PTE value immediately visible to the table walker if the new PTE was valid and for kernel space. We can do better than this; let's hoist those barriers out of the loop so that they are only issued once at the end of the loop. We then reduce the cost by the number of PTEs in the range. Reviewed-by: Catalin Marinas <[email protected]> Reviewed-by: Anshuman Khandual <[email protected]> Signed-off-by: Ryan Roberts <[email protected]> Tested-by: Luiz Capitulino <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent a899b7d commit f89b399

File tree

1 file changed

+11
-5
lines changed

1 file changed

+11
-5
lines changed

arch/arm64/include/asm/pgtable.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -320,20 +320,24 @@ static inline void __set_pte_nosync(pte_t *ptep, pte_t pte)
320320
WRITE_ONCE(*ptep, pte);
321321
}
322322

323-
static inline void __set_pte(pte_t *ptep, pte_t pte)
323+
static inline void __set_pte_complete(pte_t pte)
324324
{
325-
__set_pte_nosync(ptep, pte);
326-
327325
/*
328326
* Only if the new pte is valid and kernel, otherwise TLB maintenance
329-
* or update_mmu_cache() have the necessary barriers.
327+
* has the necessary barriers.
330328
*/
331329
if (pte_valid_not_user(pte)) {
332330
dsb(ishst);
333331
isb();
334332
}
335333
}
336334

335+
static inline void __set_pte(pte_t *ptep, pte_t pte)
336+
{
337+
__set_pte_nosync(ptep, pte);
338+
__set_pte_complete(pte);
339+
}
340+
337341
static inline pte_t __ptep_get(pte_t *ptep)
338342
{
339343
return READ_ONCE(*ptep);
@@ -658,12 +662,14 @@ static inline void __set_ptes_anysz(struct mm_struct *mm, pte_t *ptep,
658662

659663
for (;;) {
660664
__check_safe_pte_update(mm, ptep, pte);
661-
__set_pte(ptep, pte);
665+
__set_pte_nosync(ptep, pte);
662666
if (--nr == 0)
663667
break;
664668
ptep++;
665669
pte = pte_advance_pfn(pte, stride);
666670
}
671+
672+
__set_pte_complete(pte);
667673
}
668674

669675
static inline void __set_ptes(struct mm_struct *mm,

0 commit comments

Comments
 (0)