18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * MIPS Huge TLB Page Support for Kernel. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 58c2ecf20Sopenharmony_ci * License. See the file "COPYING" in the main directory of this archive 68c2ecf20Sopenharmony_ci * for more details. 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Copyright (C) 2002, Rohit Seth <rohit.seth@intel.com> 98c2ecf20Sopenharmony_ci * Copyright 2005, Embedded Alley Solutions, Inc. 108c2ecf20Sopenharmony_ci * Matt Porter <mporter@embeddedalley.com> 118c2ecf20Sopenharmony_ci * Copyright (C) 2008, 2009 Cavium Networks, Inc. 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <linux/fs.h> 158c2ecf20Sopenharmony_ci#include <linux/mm.h> 168c2ecf20Sopenharmony_ci#include <linux/hugetlb.h> 178c2ecf20Sopenharmony_ci#include <linux/pagemap.h> 188c2ecf20Sopenharmony_ci#include <linux/err.h> 198c2ecf20Sopenharmony_ci#include <linux/sysctl.h> 208c2ecf20Sopenharmony_ci#include <asm/mman.h> 218c2ecf20Sopenharmony_ci#include <asm/tlb.h> 228c2ecf20Sopenharmony_ci#include <asm/tlbflush.h> 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cipte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr, 258c2ecf20Sopenharmony_ci unsigned long sz) 268c2ecf20Sopenharmony_ci{ 278c2ecf20Sopenharmony_ci pgd_t *pgd; 288c2ecf20Sopenharmony_ci p4d_t *p4d; 298c2ecf20Sopenharmony_ci pud_t *pud; 308c2ecf20Sopenharmony_ci pte_t *pte = NULL; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci pgd = pgd_offset(mm, addr); 338c2ecf20Sopenharmony_ci p4d = p4d_alloc(mm, pgd, addr); 348c2ecf20Sopenharmony_ci pud = pud_alloc(mm, p4d, addr); 358c2ecf20Sopenharmony_ci if (pud) 368c2ecf20Sopenharmony_ci pte = (pte_t *)pmd_alloc(mm, pud, addr); 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci return pte; 398c2ecf20Sopenharmony_ci} 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_cipte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr, 428c2ecf20Sopenharmony_ci unsigned long sz) 438c2ecf20Sopenharmony_ci{ 448c2ecf20Sopenharmony_ci pgd_t *pgd; 458c2ecf20Sopenharmony_ci p4d_t *p4d; 468c2ecf20Sopenharmony_ci pud_t *pud; 478c2ecf20Sopenharmony_ci pmd_t *pmd = NULL; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci pgd = pgd_offset(mm, addr); 508c2ecf20Sopenharmony_ci if (pgd_present(*pgd)) { 518c2ecf20Sopenharmony_ci p4d = p4d_offset(pgd, addr); 528c2ecf20Sopenharmony_ci if (p4d_present(*p4d)) { 538c2ecf20Sopenharmony_ci pud = pud_offset(p4d, addr); 548c2ecf20Sopenharmony_ci if (pud_present(*pud)) 558c2ecf20Sopenharmony_ci pmd = pmd_offset(pud, addr); 568c2ecf20Sopenharmony_ci } 578c2ecf20Sopenharmony_ci } 588c2ecf20Sopenharmony_ci return (pte_t *) pmd; 598c2ecf20Sopenharmony_ci} 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci/* 628c2ecf20Sopenharmony_ci * This function checks for proper alignment of input addr and len parameters. 638c2ecf20Sopenharmony_ci */ 648c2ecf20Sopenharmony_ciint is_aligned_hugepage_range(unsigned long addr, unsigned long len) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci if (len & ~HPAGE_MASK) 678c2ecf20Sopenharmony_ci return -EINVAL; 688c2ecf20Sopenharmony_ci if (addr & ~HPAGE_MASK) 698c2ecf20Sopenharmony_ci return -EINVAL; 708c2ecf20Sopenharmony_ci return 0; 718c2ecf20Sopenharmony_ci} 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ciint pmd_huge(pmd_t pmd) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci return (pmd_val(pmd) & _PAGE_HUGE) != 0; 768c2ecf20Sopenharmony_ci} 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ciint pud_huge(pud_t pud) 798c2ecf20Sopenharmony_ci{ 808c2ecf20Sopenharmony_ci return (pud_val(pud) & _PAGE_HUGE) != 0; 818c2ecf20Sopenharmony_ci} 82