Skip to content

Commit 8cc8b15

Browse files
ryanhrobmrphilcox
authored andcommitted
arm64: mm: Batch dsb and isb when populating pgtables
BugLink: https://bugs.launchpad.net/bugs/2069352 After removing uneccessary TLBIs, the next bottleneck when creating the page tables for the linear map is DSB and ISB, which were previously issued per-pte in __set_pte(). Since we are writing multiple ptes in a given pte table, we can elide these barriers and insert them once we have finished writing to the table. Execution time of map_mem(), which creates the kernel linear map page tables, was measured on different machines with different RAM configs: | Apple M2 VM | Ampere Altra| Ampere Altra| Ampere Altra | VM, 16G | VM, 64G | VM, 256G | Metal, 512G ---------------|-------------|-------------|-------------|------------- | ms (%) | ms (%) | ms (%) | ms (%) ---------------|-------------|-------------|-------------|------------- before | 78 (0%) | 435 (0%) | 1723 (0%) | 3779 (0%) after | 11 (-86%) | 161 (-63%) | 656 (-62%) | 1654 (-56%) Signed-off-by: Ryan Roberts <ryan.roberts@arm.com> Tested-by: Itaru Kitayama <itaru.kitayama@fujitsu.com> Tested-by: Eric Chanudet <echanude@redhat.com> Reviewed-by: Mark Rutland <mark.rutland@arm.com> Reviewed-by: Ard Biesheuvel <ardb@kernel.org> Link: https://lore.kernel.org/r/20240412131908.433043-3-ryan.roberts@arm.com Signed-off-by: Will Deacon <will@kernel.org> (backported from commit 1fcb7ce [context changes in init_pte(), replaced __set_pte() with set_pte()]) Signed-off-by: Philip Cox <philip.cox@canonical.com> Acked-by: Manuel Diewald <manuel.diewald at canonical.com> Acked-by: Thibault Ferrante <thibault.ferrante at canonical.com>
1 parent c9496cf commit 8cc8b15

2 files changed

Lines changed: 16 additions & 2 deletions

File tree

‎arch/arm64/include/asm/pgtable.h‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,9 +252,14 @@ static inline pte_t pte_mkdevmap(pte_t pte)
252252
return set_pte_bit(pte, __pgprot(PTE_DEVMAP | PTE_SPECIAL));
253253
}
254254

255-
static inline void set_pte(pte_t *ptep, pte_t pte)
255+
static inline void __set_pte_nosync(pte_t *ptep, pte_t pte)
256256
{
257257
WRITE_ONCE(*ptep, pte);
258+
}
259+
260+
static inline void set_pte(pte_t *ptep, pte_t pte)
261+
{
262+
__set_pte_nosync(ptep, pte);
258263

259264
/*
260265
* Only if the new pte is valid and kernel, otherwise TLB maintenance

‎arch/arm64/mm/mmu.c‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,11 @@ static void init_pte(pte_t *ptep, unsigned long addr, unsigned long end,
159159
do {
160160
pte_t old_pte = READ_ONCE(*ptep);
161161

162-
set_pte(ptep, pfn_pte(__phys_to_pfn(phys), prot));
162+
/*
163+
* Required barriers to make this visible to the table walker
164+
* are deferred to the end of alloc_init_cont_pte().
165+
*/
166+
__set_pte_nosync(ptep, pfn_pte(__phys_to_pfn(phys), prot));
163167

164168
/*
165169
* After the PTE entry has been populated once, we
@@ -213,6 +217,11 @@ static void alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr,
213217
phys += next - addr;
214218
} while (addr = next, addr != end);
215219

220+
/*
221+
* Note: barriers and maintenance necessary to clear the fixmap slot
222+
* ensure that all previous pgtable writes are visible to the table
223+
* walker.
224+
*/
216225
pte_clear_fixmap();
217226
}
218227

0 commit comments

Comments
 (0)