xref: /linux/arch/loongarch/mm/hugetlbpage.c (revision ab93e0dd72c37d378dd936f031ffb83ff2bd87ce)
109cfefb7SHuacai Chen // SPDX-License-Identifier: GPL-2.0
209cfefb7SHuacai Chen /*
309cfefb7SHuacai Chen  * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
409cfefb7SHuacai Chen  */
509cfefb7SHuacai Chen 
609cfefb7SHuacai Chen #include <linux/fs.h>
709cfefb7SHuacai Chen #include <linux/mm.h>
809cfefb7SHuacai Chen #include <linux/hugetlb.h>
909cfefb7SHuacai Chen #include <linux/pagemap.h>
1009cfefb7SHuacai Chen #include <linux/err.h>
1109cfefb7SHuacai Chen #include <linux/sysctl.h>
1209cfefb7SHuacai Chen #include <asm/mman.h>
1309cfefb7SHuacai Chen #include <asm/tlb.h>
1409cfefb7SHuacai Chen #include <asm/tlbflush.h>
1509cfefb7SHuacai Chen 
huge_pte_alloc(struct mm_struct * mm,struct vm_area_struct * vma,unsigned long addr,unsigned long sz)1609cfefb7SHuacai Chen pte_t *huge_pte_alloc(struct mm_struct *mm, struct vm_area_struct *vma,
1709cfefb7SHuacai Chen 		      unsigned long addr, unsigned long sz)
1809cfefb7SHuacai Chen {
1909cfefb7SHuacai Chen 	pgd_t *pgd;
2009cfefb7SHuacai Chen 	p4d_t *p4d;
2109cfefb7SHuacai Chen 	pud_t *pud;
2209cfefb7SHuacai Chen 	pte_t *pte = NULL;
2309cfefb7SHuacai Chen 
2409cfefb7SHuacai Chen 	pgd = pgd_offset(mm, addr);
2509cfefb7SHuacai Chen 	p4d = p4d_alloc(mm, pgd, addr);
2609cfefb7SHuacai Chen 	pud = pud_alloc(mm, p4d, addr);
2709cfefb7SHuacai Chen 	if (pud)
2809cfefb7SHuacai Chen 		pte = (pte_t *)pmd_alloc(mm, pud, addr);
2909cfefb7SHuacai Chen 
3009cfefb7SHuacai Chen 	return pte;
3109cfefb7SHuacai Chen }
3209cfefb7SHuacai Chen 
huge_pte_offset(struct mm_struct * mm,unsigned long addr,unsigned long sz)3309cfefb7SHuacai Chen pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr,
3409cfefb7SHuacai Chen 		       unsigned long sz)
3509cfefb7SHuacai Chen {
3609cfefb7SHuacai Chen 	pgd_t *pgd;
3709cfefb7SHuacai Chen 	p4d_t *p4d;
3809cfefb7SHuacai Chen 	pud_t *pud;
3909cfefb7SHuacai Chen 	pmd_t *pmd = NULL;
4009cfefb7SHuacai Chen 
4109cfefb7SHuacai Chen 	pgd = pgd_offset(mm, addr);
424574815aSHuacai Chen 	if (pgd_present(pgdp_get(pgd))) {
4309cfefb7SHuacai Chen 		p4d = p4d_offset(pgd, addr);
444574815aSHuacai Chen 		if (p4d_present(p4dp_get(p4d))) {
4509cfefb7SHuacai Chen 			pud = pud_offset(p4d, addr);
464574815aSHuacai Chen 			if (pud_present(pudp_get(pud)))
4709cfefb7SHuacai Chen 				pmd = pmd_offset(pud, addr);
4809cfefb7SHuacai Chen 		}
4909cfefb7SHuacai Chen 	}
50*ee084fa9STianyang Zhang 
51*ee084fa9STianyang Zhang 	return (!pmd || pmd_none(pmdp_get(pmd))) ? NULL : (pte_t *) pmd;
5209cfefb7SHuacai Chen }
5309cfefb7SHuacai Chen 
pmd_to_entrylo(unsigned long pmd_val)5409cfefb7SHuacai Chen uint64_t pmd_to_entrylo(unsigned long pmd_val)
5509cfefb7SHuacai Chen {
5609cfefb7SHuacai Chen 	uint64_t val;
5709cfefb7SHuacai Chen 	/* PMD as PTE. Must be huge page */
581965e933SPeter Xu 	if (!pmd_leaf(__pmd(pmd_val)))
5909cfefb7SHuacai Chen 		panic("%s", __func__);
6009cfefb7SHuacai Chen 
6109cfefb7SHuacai Chen 	val = pmd_val ^ _PAGE_HUGE;
6209cfefb7SHuacai Chen 	val |= ((val & _PAGE_HGLOBAL) >>
6309cfefb7SHuacai Chen 		(_PAGE_HGLOBAL_SHIFT - _PAGE_GLOBAL_SHIFT));
6409cfefb7SHuacai Chen 
6509cfefb7SHuacai Chen 	return val;
6609cfefb7SHuacai Chen }
67