diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index d34112fb3d52640d0ce7465f1927f2765810a7f7..5fd3fe7f741ef8cbc3edc1ad6fff217e3866f63b 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -372,6 +372,13 @@ struct page *alloc_huge_page_vma(struct hstate *h, struct vm_area_struct *vma, int huge_add_to_page_cache(struct page *page, struct address_space *mapping, pgoff_t idx); +#ifdef CONFIG_ARCH_ASCEND +const struct hstate *hugetlb_get_hstate(void); +struct page *hugetlb_alloc_hugepage(int nid); +int hugetlb_insert_hugepage_pte(struct mm_struct *mm, unsigned long addr, + pgprot_t prot, struct page *hpage); +#endif + /* arch callback */ int __init __alloc_bootmem_huge_page(struct hstate *h); int __init alloc_bootmem_huge_page(struct hstate *h); diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 77351a09420cd64663b6702fce8a27036559d2cf..5163775eaa8108ed34ba8cd3019313c41fe3bdd0 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -5122,3 +5122,78 @@ void move_hugetlb_state(struct page *oldpage, struct page *newpage, int reason) spin_unlock(&hugetlb_lock); } } + +#ifdef CONFIG_ARCH_ASCEND + +const struct hstate *hugetlb_get_hstate(void) +{ + return &default_hstate; +} +EXPORT_SYMBOL_GPL(hugetlb_get_hstate); + +/* + * Allocate hugepage without reserve + */ +struct page *hugetlb_alloc_hugepage(int nid) +{ + return alloc_huge_page_node(&default_hstate, nid); +} +EXPORT_SYMBOL_GPL(hugetlb_alloc_hugepage); + +static pte_t *hugetlb_huge_pte_alloc(struct mm_struct *mm, unsigned long addr, + unsigned long size) +{ + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t *pte = NULL; + + pgd = pgd_offset(mm, addr); + + if (pgd_none(*pgd)) + pud = pud_alloc(mm, pgd, addr); + else + pud = pud_offset(pgd, addr); + + if (pud) { + if (!pud_none(*pud)) { + pmd = pmd_offset(pud, addr); + if (pmd) { + if (!pmd_none(*pmd)) + pmd_clear(pmd); + pte = (pte_t *)pmd; + } else { + pte = (pte_t *)pmd_alloc(mm, pud, addr); + } + } else { + pte = (pte_t *)pmd_alloc(mm, pud, addr); + } + } + + return pte; +} + +int hugetlb_insert_hugepage_pte(struct mm_struct *mm, unsigned long addr, + pgprot_t prot, struct page *hpage) +{ + pte_t *ptep, entry; + struct hstate *h = &default_hstate; + + ptep = hugetlb_huge_pte_alloc(mm, addr, huge_page_size(h)); + if (!ptep) + return -ENXIO; + + WARN_ON(ptep && !pte_none(*ptep) && !pte_huge(*ptep)); + + entry = mk_huge_pte(hpage, prot); + entry = huge_pte_mkdirty(entry); + entry = huge_pte_mkwrite(entry); + entry = pte_mkyoung(entry); + entry = pte_mkhuge(entry); + + set_huge_pte_at(mm, addr, ptep, entry); + return 0; +} +EXPORT_SYMBOL_GPL(hugetlb_insert_hugepage_pte); + +#endif