Skip to content

Commit c3cc2a4

Browse files
Alexandre Ghitipalmer-dabbelt
authored andcommitted
riscv: Add support for PUD THP
Add the necessary page table functions to deal with PUD THP, this enables the use of PUD pfnmap. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexandre Ghiti <[email protected]> Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent 850d7b1 commit c3cc2a4

File tree

6 files changed

+120
-2
lines changed

6 files changed

+120
-2
lines changed

arch/riscv/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ config RISCV
143143
select HAVE_ARCH_THREAD_STRUCT_WHITELIST
144144
select HAVE_ARCH_TRACEHOOK
145145
select HAVE_ARCH_TRANSPARENT_HUGEPAGE if 64BIT && MMU
146+
select HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD if 64BIT && MMU
146147
select HAVE_ARCH_USERFAULTFD_MINOR if 64BIT && USERFAULTFD
147148
select HAVE_ARCH_VMAP_STACK if MMU && 64BIT
148149
select HAVE_ASM_MODVERSIONS

arch/riscv/include/asm/pgtable-64.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ static inline int pud_none(pud_t pud)
184184

185185
static inline int pud_bad(pud_t pud)
186186
{
187-
return !pud_present(pud);
187+
return !pud_present(pud) || (pud_val(pud) & _PAGE_LEAF);
188188
}
189189

190190
#define pud_leaf pud_leaf
@@ -401,6 +401,7 @@ p4d_t *p4d_offset(pgd_t *pgd, unsigned long address);
401401
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
402402
static inline int pte_devmap(pte_t pte);
403403
static inline pte_t pmd_pte(pmd_t pmd);
404+
static inline pte_t pud_pte(pud_t pud);
404405

405406
static inline int pmd_devmap(pmd_t pmd)
406407
{
@@ -409,7 +410,7 @@ static inline int pmd_devmap(pmd_t pmd)
409410

410411
static inline int pud_devmap(pud_t pud)
411412
{
412-
return 0;
413+
return pte_devmap(pud_pte(pud));
413414
}
414415

415416
static inline int pgd_devmap(pgd_t pgd)

arch/riscv/include/asm/pgtable.h

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -902,6 +902,103 @@ static inline pmd_t pmdp_establish(struct vm_area_struct *vma,
902902
#define pmdp_collapse_flush pmdp_collapse_flush
903903
extern pmd_t pmdp_collapse_flush(struct vm_area_struct *vma,
904904
unsigned long address, pmd_t *pmdp);
905+
906+
static inline pud_t pud_wrprotect(pud_t pud)
907+
{
908+
return pte_pud(pte_wrprotect(pud_pte(pud)));
909+
}
910+
911+
static inline int pud_trans_huge(pud_t pud)
912+
{
913+
return pud_leaf(pud);
914+
}
915+
916+
static inline int pud_dirty(pud_t pud)
917+
{
918+
return pte_dirty(pud_pte(pud));
919+
}
920+
921+
static inline pud_t pud_mkyoung(pud_t pud)
922+
{
923+
return pte_pud(pte_mkyoung(pud_pte(pud)));
924+
}
925+
926+
static inline pud_t pud_mkold(pud_t pud)
927+
{
928+
return pte_pud(pte_mkold(pud_pte(pud)));
929+
}
930+
931+
static inline pud_t pud_mkdirty(pud_t pud)
932+
{
933+
return pte_pud(pte_mkdirty(pud_pte(pud)));
934+
}
935+
936+
static inline pud_t pud_mkclean(pud_t pud)
937+
{
938+
return pte_pud(pte_mkclean(pud_pte(pud)));
939+
}
940+
941+
static inline pud_t pud_mkwrite(pud_t pud)
942+
{
943+
return pte_pud(pte_mkwrite_novma(pud_pte(pud)));
944+
}
945+
946+
static inline pud_t pud_mkhuge(pud_t pud)
947+
{
948+
return pud;
949+
}
950+
951+
static inline pud_t pud_mkdevmap(pud_t pud)
952+
{
953+
return pte_pud(pte_mkdevmap(pud_pte(pud)));
954+
}
955+
956+
static inline int pudp_set_access_flags(struct vm_area_struct *vma,
957+
unsigned long address, pud_t *pudp,
958+
pud_t entry, int dirty)
959+
{
960+
return ptep_set_access_flags(vma, address, (pte_t *)pudp, pud_pte(entry), dirty);
961+
}
962+
963+
static inline int pudp_test_and_clear_young(struct vm_area_struct *vma,
964+
unsigned long address, pud_t *pudp)
965+
{
966+
return ptep_test_and_clear_young(vma, address, (pte_t *)pudp);
967+
}
968+
969+
static inline int pud_young(pud_t pud)
970+
{
971+
return pte_young(pud_pte(pud));
972+
}
973+
974+
static inline void update_mmu_cache_pud(struct vm_area_struct *vma,
975+
unsigned long address, pud_t *pudp)
976+
{
977+
pte_t *ptep = (pte_t *)pudp;
978+
979+
update_mmu_cache(vma, address, ptep);
980+
}
981+
982+
static inline pud_t pudp_establish(struct vm_area_struct *vma,
983+
unsigned long address, pud_t *pudp, pud_t pud)
984+
{
985+
page_table_check_pud_set(vma->vm_mm, pudp, pud);
986+
return __pud(atomic_long_xchg((atomic_long_t *)pudp, pud_val(pud)));
987+
}
988+
989+
static inline pud_t pud_mkinvalid(pud_t pud)
990+
{
991+
return __pud(pud_val(pud) & ~(_PAGE_PRESENT | _PAGE_PROT_NONE));
992+
}
993+
994+
extern pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,
995+
pud_t *pudp);
996+
997+
static inline pud_t pud_modify(pud_t pud, pgprot_t newprot)
998+
{
999+
return pte_pud(pte_modify(pud_pte(pud), newprot));
1000+
}
1001+
9051002
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
9061003

9071004
/*

arch/riscv/include/asm/tlbflush.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end);
5656
#define __HAVE_ARCH_FLUSH_PMD_TLB_RANGE
5757
void flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start,
5858
unsigned long end);
59+
void flush_pud_tlb_range(struct vm_area_struct *vma, unsigned long start,
60+
unsigned long end);
5961
#endif
6062

6163
bool arch_tlbbatch_should_defer(struct mm_struct *mm);

arch/riscv/mm/pgtable.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,4 +154,14 @@ pmd_t pmdp_collapse_flush(struct vm_area_struct *vma,
154154
flush_tlb_mm(vma->vm_mm);
155155
return pmd;
156156
}
157+
158+
pud_t pudp_invalidate(struct vm_area_struct *vma, unsigned long address,
159+
pud_t *pudp)
160+
{
161+
VM_WARN_ON_ONCE(!pud_present(*pudp));
162+
pud_t old = pudp_establish(vma, address, pudp, pud_mkinvalid(*pudp));
163+
164+
flush_pud_tlb_range(vma, address, address + HPAGE_PUD_SIZE);
165+
return old;
166+
}
157167
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */

arch/riscv/mm/tlbflush.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,13 @@ void flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start,
182182
__flush_tlb_range(vma->vm_mm, mm_cpumask(vma->vm_mm),
183183
start, end - start, PMD_SIZE);
184184
}
185+
186+
void flush_pud_tlb_range(struct vm_area_struct *vma, unsigned long start,
187+
unsigned long end)
188+
{
189+
__flush_tlb_range(vma->vm_mm, mm_cpumask(vma->vm_mm),
190+
start, end - start, PUD_SIZE);
191+
}
185192
#endif
186193

187194
bool arch_tlbbatch_should_defer(struct mm_struct *mm)

0 commit comments

Comments
 (0)