Skip to content

Commit 4239c19

Browse files
Qi Zhengakpm00
authored andcommitted
riscv: pgtable: unconditionally use tlb_remove_ptdesc()
To support fast gup, the commit 69be3fb ("riscv: enable MMU_GATHER_RCU_TABLE_FREE for SMP && MMU") did the following: 1) use tlb_remove_page_ptdesc() for those platforms which use IPI to perform TLB shootdown 2) use tlb_remove_ptdesc() for those platforms which use SBI to perform TLB shootdown The tlb_remove_page_ptdesc() is the wrapper of the tlb_remove_page(). By design, the tlb_remove_page() should be used to remove a normal page from a page table entry, and should not be used for page table pages. The tlb_remove_ptdesc() is the wrapper of the tlb_remove_table(), which is designed specifically for freeing page table pages. If the CONFIG_MMU_GATHER_TABLE_FREE is enabled, the tlb_remove_table() will use semi RCU to free page table pages, that is: - batch table freeing: asynchronous free by RCU - single table freeing: IPI + synchronous free If the CONFIG_MMU_GATHER_TABLE_FREE is disabled, the tlb_remove_table() will fall back to pagetable_dtor() + tlb_remove_page(). For case 1), since we need to perform TLB shootdown before freeing the page table page, the local_irq_save() in fast gup can block the freeing and protect the fast gup page walker. Therefore we can ensure safety by just using tlb_remove_page_ptdesc(). In addition, we can also the tlb_remove_ptdesc()/tlb_remove_table() to achieve it, and it doesn't matter whether CONFIG_MMU_GATHER_RCU_TABLE_FREE is selected. And in theory, the performance of freeing pages asynchronously via RCU will not be lower than synchronous free. For case 2), since local_irq_save() only disable S-privilege IPI irq but not M-privilege's, which is used by the SBI implementation to perform TLB shootdown, so we must select CONFIG_MMU_GATHER_RCU_TABLE_FREE and use tlb_remove_ptdesc() to ensure safety. The riscv selects this config for SMP && MMU, the CONFIG_RISCV_SBI is dependent on MMU. Therefore, only the UP system may have the situation where CONFIG_MMU_GATHER_RCU_TABLE_FREE is disabled but CONFIG_RISCV_SBI is enabled. But there is no freeing vs fast gup race in the UP system. So, in summary, we can use tlb_remove_ptdesc() to support fast gup in all cases, and this interface is specifically designed for page table pages. So let's use it unconditionally. Link: https://lkml.kernel.org/r/9025595e895515515c95e48db54b29afa489c41d.1740454179.git.zhengqi.arch@bytedance.com Signed-off-by: Qi Zheng <[email protected]> Suggested-by: Peter Zijlstra (Intel) <[email protected]> Cc: Alexandre Ghiti <[email protected]> Cc: "Aneesh Kumar K.V" <[email protected]> Cc: Arnd Bergmann <[email protected]> Cc: Dave Hansen <[email protected]> Cc: David Hildenbrand <[email protected]> Cc: Hugh Dickens <[email protected]> Cc: Jann Horn <[email protected]> Cc: Kevin Brodsky <[email protected]> Cc: Matthew Wilcow (Oracle) <[email protected]> Cc: "Mike Rapoport (IBM)" <[email protected]> Cc: Muchun Song <[email protected]> Cc: Nicholas Piggin <[email protected]> Cc: Rik van Riel <[email protected]> Cc: Vishal Moola (Oracle) <[email protected]> Cc: Will Deacon <[email protected]> Cc: Yu Zhao <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent e3ecf7c commit 4239c19

File tree

1 file changed

+4
-22
lines changed

1 file changed

+4
-22
lines changed

arch/riscv/include/asm/pgalloc.h

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,6 @@
1515
#define __HAVE_ARCH_PUD_FREE
1616
#include <asm-generic/pgalloc.h>
1717

18-
/*
19-
* While riscv platforms with riscv_ipi_for_rfence as true require an IPI to
20-
* perform TLB shootdown, some platforms with riscv_ipi_for_rfence as false use
21-
* SBI to perform TLB shootdown. To keep software pagetable walkers safe in this
22-
* case we switch to RCU based table free (MMU_GATHER_RCU_TABLE_FREE). See the
23-
* comment below 'ifdef CONFIG_MMU_GATHER_RCU_TABLE_FREE' in include/asm-generic/tlb.h
24-
* for more details.
25-
*/
26-
static inline void riscv_tlb_remove_ptdesc(struct mmu_gather *tlb, void *pt)
27-
{
28-
if (riscv_use_sbi_for_rfence()) {
29-
tlb_remove_ptdesc(tlb, pt);
30-
} else {
31-
pagetable_dtor(pt);
32-
tlb_remove_page_ptdesc(tlb, pt);
33-
}
34-
}
35-
3618
static inline void pmd_populate_kernel(struct mm_struct *mm,
3719
pmd_t *pmd, pte_t *pte)
3820
{
@@ -108,14 +90,14 @@ static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
10890
unsigned long addr)
10991
{
11092
if (pgtable_l4_enabled)
111-
riscv_tlb_remove_ptdesc(tlb, virt_to_ptdesc(pud));
93+
tlb_remove_ptdesc(tlb, virt_to_ptdesc(pud));
11294
}
11395

11496
static inline void __p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d,
11597
unsigned long addr)
11698
{
11799
if (pgtable_l5_enabled)
118-
riscv_tlb_remove_ptdesc(tlb, virt_to_ptdesc(p4d));
100+
tlb_remove_ptdesc(tlb, virt_to_ptdesc(p4d));
119101
}
120102
#endif /* __PAGETABLE_PMD_FOLDED */
121103

@@ -143,15 +125,15 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
143125
static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
144126
unsigned long addr)
145127
{
146-
riscv_tlb_remove_ptdesc(tlb, virt_to_ptdesc(pmd));
128+
tlb_remove_ptdesc(tlb, virt_to_ptdesc(pmd));
147129
}
148130

149131
#endif /* __PAGETABLE_PMD_FOLDED */
150132

151133
static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
152134
unsigned long addr)
153135
{
154-
riscv_tlb_remove_ptdesc(tlb, page_ptdesc(pte));
136+
tlb_remove_ptdesc(tlb, page_ptdesc(pte));
155137
}
156138
#endif /* CONFIG_MMU */
157139

0 commit comments

Comments
 (0)