xref: /openbmc/linux/arch/loongarch/mm/hugetlbpage.c (revision c718a0ba)
1*09cfefb7SHuacai Chen // SPDX-License-Identifier: GPL-2.0
2*09cfefb7SHuacai Chen /*
3*09cfefb7SHuacai Chen  * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
4*09cfefb7SHuacai Chen  */
5*09cfefb7SHuacai Chen 
6*09cfefb7SHuacai Chen #include <linux/fs.h>
7*09cfefb7SHuacai Chen #include <linux/mm.h>
8*09cfefb7SHuacai Chen #include <linux/hugetlb.h>
9*09cfefb7SHuacai Chen #include <linux/pagemap.h>
10*09cfefb7SHuacai Chen #include <linux/err.h>
11*09cfefb7SHuacai Chen #include <linux/sysctl.h>
12*09cfefb7SHuacai Chen #include <asm/mman.h>
13*09cfefb7SHuacai Chen #include <asm/tlb.h>
14*09cfefb7SHuacai Chen #include <asm/tlbflush.h>
15*09cfefb7SHuacai Chen 
huge_pte_alloc(struct mm_struct * mm,struct vm_area_struct * vma,unsigned long addr,unsigned long sz)16*09cfefb7SHuacai Chen pte_t *huge_pte_alloc(struct mm_struct *mm, struct vm_area_struct *vma,
17*09cfefb7SHuacai Chen 		      unsigned long addr, unsigned long sz)
18*09cfefb7SHuacai Chen {
19*09cfefb7SHuacai Chen 	pgd_t *pgd;
20*09cfefb7SHuacai Chen 	p4d_t *p4d;
21*09cfefb7SHuacai Chen 	pud_t *pud;
22*09cfefb7SHuacai Chen 	pte_t *pte = NULL;
23*09cfefb7SHuacai Chen 
24*09cfefb7SHuacai Chen 	pgd = pgd_offset(mm, addr);
25*09cfefb7SHuacai Chen 	p4d = p4d_alloc(mm, pgd, addr);
26*09cfefb7SHuacai Chen 	pud = pud_alloc(mm, p4d, addr);
27*09cfefb7SHuacai Chen 	if (pud)
28*09cfefb7SHuacai Chen 		pte = (pte_t *)pmd_alloc(mm, pud, addr);
29*09cfefb7SHuacai Chen 
30*09cfefb7SHuacai Chen 	return pte;
31*09cfefb7SHuacai Chen }
32*09cfefb7SHuacai Chen 
huge_pte_offset(struct mm_struct * mm,unsigned long addr,unsigned long sz)33*09cfefb7SHuacai Chen pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr,
34*09cfefb7SHuacai Chen 		       unsigned long sz)
35*09cfefb7SHuacai Chen {
36*09cfefb7SHuacai Chen 	pgd_t *pgd;
37*09cfefb7SHuacai Chen 	p4d_t *p4d;
38*09cfefb7SHuacai Chen 	pud_t *pud;
39*09cfefb7SHuacai Chen 	pmd_t *pmd = NULL;
40*09cfefb7SHuacai Chen 
41*09cfefb7SHuacai Chen 	pgd = pgd_offset(mm, addr);
42*09cfefb7SHuacai Chen 	if (pgd_present(*pgd)) {
43*09cfefb7SHuacai Chen 		p4d = p4d_offset(pgd, addr);
44*09cfefb7SHuacai Chen 		if (p4d_present(*p4d)) {
45*09cfefb7SHuacai Chen 			pud = pud_offset(p4d, addr);
46*09cfefb7SHuacai Chen 			if (pud_present(*pud))
47*09cfefb7SHuacai Chen 				pmd = pmd_offset(pud, addr);
48*09cfefb7SHuacai Chen 		}
49*09cfefb7SHuacai Chen 	}
50*09cfefb7SHuacai Chen 	return (pte_t *) pmd;
51*09cfefb7SHuacai Chen }
52*09cfefb7SHuacai Chen 
pmd_huge(pmd_t pmd)53*09cfefb7SHuacai Chen int pmd_huge(pmd_t pmd)
54*09cfefb7SHuacai Chen {
55*09cfefb7SHuacai Chen 	return (pmd_val(pmd) & _PAGE_HUGE) != 0;
56*09cfefb7SHuacai Chen }
57*09cfefb7SHuacai Chen 
pud_huge(pud_t pud)58*09cfefb7SHuacai Chen int pud_huge(pud_t pud)
59*09cfefb7SHuacai Chen {
60*09cfefb7SHuacai Chen 	return (pud_val(pud) & _PAGE_HUGE) != 0;
61*09cfefb7SHuacai Chen }
62*09cfefb7SHuacai Chen 
pmd_to_entrylo(unsigned long pmd_val)63*09cfefb7SHuacai Chen uint64_t pmd_to_entrylo(unsigned long pmd_val)
64*09cfefb7SHuacai Chen {
65*09cfefb7SHuacai Chen 	uint64_t val;
66*09cfefb7SHuacai Chen 	/* PMD as PTE. Must be huge page */
67*09cfefb7SHuacai Chen 	if (!pmd_huge(__pmd(pmd_val)))
68*09cfefb7SHuacai Chen 		panic("%s", __func__);
69*09cfefb7SHuacai Chen 
70*09cfefb7SHuacai Chen 	val = pmd_val ^ _PAGE_HUGE;
71*09cfefb7SHuacai Chen 	val |= ((val & _PAGE_HGLOBAL) >>
72*09cfefb7SHuacai Chen 		(_PAGE_HGLOBAL_SHIFT - _PAGE_GLOBAL_SHIFT));
73*09cfefb7SHuacai Chen 
74*09cfefb7SHuacai Chen 	return val;
75*09cfefb7SHuacai Chen }
76