1*07037db5SPalmer Dabbelt /* 2*07037db5SPalmer Dabbelt * Copyright (C) 2009 Chen Liqin <liqin.chen@sunplusct.com> 3*07037db5SPalmer Dabbelt * Copyright (C) 2012 Regents of the University of California 4*07037db5SPalmer Dabbelt * 5*07037db5SPalmer Dabbelt * This program is free software; you can redistribute it and/or 6*07037db5SPalmer Dabbelt * modify it under the terms of the GNU General Public License 7*07037db5SPalmer Dabbelt * as published by the Free Software Foundation, version 2. 8*07037db5SPalmer Dabbelt * 9*07037db5SPalmer Dabbelt * This program is distributed in the hope that it will be useful, 10*07037db5SPalmer Dabbelt * but WITHOUT ANY WARRANTY; without even the implied warranty of 11*07037db5SPalmer Dabbelt * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12*07037db5SPalmer Dabbelt * GNU General Public License for more details. 13*07037db5SPalmer Dabbelt */ 14*07037db5SPalmer Dabbelt 15*07037db5SPalmer Dabbelt #ifndef _ASM_RISCV_PGALLOC_H 16*07037db5SPalmer Dabbelt #define _ASM_RISCV_PGALLOC_H 17*07037db5SPalmer Dabbelt 18*07037db5SPalmer Dabbelt #include <linux/mm.h> 19*07037db5SPalmer Dabbelt #include <asm/tlb.h> 20*07037db5SPalmer Dabbelt 21*07037db5SPalmer Dabbelt static inline void pmd_populate_kernel(struct mm_struct *mm, 22*07037db5SPalmer Dabbelt pmd_t *pmd, pte_t *pte) 23*07037db5SPalmer Dabbelt { 24*07037db5SPalmer Dabbelt unsigned long pfn = virt_to_pfn(pte); 25*07037db5SPalmer Dabbelt 26*07037db5SPalmer Dabbelt set_pmd(pmd, __pmd((pfn << _PAGE_PFN_SHIFT) | _PAGE_TABLE)); 27*07037db5SPalmer Dabbelt } 28*07037db5SPalmer Dabbelt 29*07037db5SPalmer Dabbelt static inline void pmd_populate(struct mm_struct *mm, 30*07037db5SPalmer Dabbelt pmd_t *pmd, pgtable_t pte) 31*07037db5SPalmer Dabbelt { 32*07037db5SPalmer Dabbelt unsigned long pfn = virt_to_pfn(page_address(pte)); 33*07037db5SPalmer Dabbelt 34*07037db5SPalmer Dabbelt set_pmd(pmd, __pmd((pfn << _PAGE_PFN_SHIFT) | _PAGE_TABLE)); 35*07037db5SPalmer Dabbelt } 36*07037db5SPalmer Dabbelt 37*07037db5SPalmer Dabbelt #ifndef __PAGETABLE_PMD_FOLDED 38*07037db5SPalmer Dabbelt static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) 39*07037db5SPalmer Dabbelt { 40*07037db5SPalmer Dabbelt unsigned long pfn = virt_to_pfn(pmd); 41*07037db5SPalmer Dabbelt 42*07037db5SPalmer Dabbelt set_pud(pud, __pud((pfn << _PAGE_PFN_SHIFT) | _PAGE_TABLE)); 43*07037db5SPalmer Dabbelt } 44*07037db5SPalmer Dabbelt #endif /* __PAGETABLE_PMD_FOLDED */ 45*07037db5SPalmer Dabbelt 46*07037db5SPalmer Dabbelt #define pmd_pgtable(pmd) pmd_page(pmd) 47*07037db5SPalmer Dabbelt 48*07037db5SPalmer Dabbelt static inline pgd_t *pgd_alloc(struct mm_struct *mm) 49*07037db5SPalmer Dabbelt { 50*07037db5SPalmer Dabbelt pgd_t *pgd; 51*07037db5SPalmer Dabbelt 52*07037db5SPalmer Dabbelt pgd = (pgd_t *)__get_free_page(GFP_KERNEL); 53*07037db5SPalmer Dabbelt if (likely(pgd != NULL)) { 54*07037db5SPalmer Dabbelt memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t)); 55*07037db5SPalmer Dabbelt /* Copy kernel mappings */ 56*07037db5SPalmer Dabbelt memcpy(pgd + USER_PTRS_PER_PGD, 57*07037db5SPalmer Dabbelt init_mm.pgd + USER_PTRS_PER_PGD, 58*07037db5SPalmer Dabbelt (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); 59*07037db5SPalmer Dabbelt } 60*07037db5SPalmer Dabbelt return pgd; 61*07037db5SPalmer Dabbelt } 62*07037db5SPalmer Dabbelt 63*07037db5SPalmer Dabbelt static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) 64*07037db5SPalmer Dabbelt { 65*07037db5SPalmer Dabbelt free_page((unsigned long)pgd); 66*07037db5SPalmer Dabbelt } 67*07037db5SPalmer Dabbelt 68*07037db5SPalmer Dabbelt #ifndef __PAGETABLE_PMD_FOLDED 69*07037db5SPalmer Dabbelt 70*07037db5SPalmer Dabbelt static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) 71*07037db5SPalmer Dabbelt { 72*07037db5SPalmer Dabbelt return (pmd_t *)__get_free_page( 73*07037db5SPalmer Dabbelt GFP_KERNEL | __GFP_RETRY_MAYFAIL | __GFP_ZERO); 74*07037db5SPalmer Dabbelt } 75*07037db5SPalmer Dabbelt 76*07037db5SPalmer Dabbelt static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) 77*07037db5SPalmer Dabbelt { 78*07037db5SPalmer Dabbelt free_page((unsigned long)pmd); 79*07037db5SPalmer Dabbelt } 80*07037db5SPalmer Dabbelt 81*07037db5SPalmer Dabbelt #define __pmd_free_tlb(tlb, pmd, addr) pmd_free((tlb)->mm, pmd) 82*07037db5SPalmer Dabbelt 83*07037db5SPalmer Dabbelt #endif /* __PAGETABLE_PMD_FOLDED */ 84*07037db5SPalmer Dabbelt 85*07037db5SPalmer Dabbelt static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, 86*07037db5SPalmer Dabbelt unsigned long address) 87*07037db5SPalmer Dabbelt { 88*07037db5SPalmer Dabbelt return (pte_t *)__get_free_page( 89*07037db5SPalmer Dabbelt GFP_KERNEL | __GFP_RETRY_MAYFAIL | __GFP_ZERO); 90*07037db5SPalmer Dabbelt } 91*07037db5SPalmer Dabbelt 92*07037db5SPalmer Dabbelt static inline struct page *pte_alloc_one(struct mm_struct *mm, 93*07037db5SPalmer Dabbelt unsigned long address) 94*07037db5SPalmer Dabbelt { 95*07037db5SPalmer Dabbelt struct page *pte; 96*07037db5SPalmer Dabbelt 97*07037db5SPalmer Dabbelt pte = alloc_page(GFP_KERNEL | __GFP_RETRY_MAYFAIL | __GFP_ZERO); 98*07037db5SPalmer Dabbelt if (likely(pte != NULL)) 99*07037db5SPalmer Dabbelt pgtable_page_ctor(pte); 100*07037db5SPalmer Dabbelt return pte; 101*07037db5SPalmer Dabbelt } 102*07037db5SPalmer Dabbelt 103*07037db5SPalmer Dabbelt static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) 104*07037db5SPalmer Dabbelt { 105*07037db5SPalmer Dabbelt free_page((unsigned long)pte); 106*07037db5SPalmer Dabbelt } 107*07037db5SPalmer Dabbelt 108*07037db5SPalmer Dabbelt static inline void pte_free(struct mm_struct *mm, pgtable_t pte) 109*07037db5SPalmer Dabbelt { 110*07037db5SPalmer Dabbelt pgtable_page_dtor(pte); 111*07037db5SPalmer Dabbelt __free_page(pte); 112*07037db5SPalmer Dabbelt } 113*07037db5SPalmer Dabbelt 114*07037db5SPalmer Dabbelt #define __pte_free_tlb(tlb, pte, buf) \ 115*07037db5SPalmer Dabbelt do { \ 116*07037db5SPalmer Dabbelt pgtable_page_dtor(pte); \ 117*07037db5SPalmer Dabbelt tlb_remove_page((tlb), pte); \ 118*07037db5SPalmer Dabbelt } while (0) 119*07037db5SPalmer Dabbelt 120*07037db5SPalmer Dabbelt static inline void check_pgt_cache(void) 121*07037db5SPalmer Dabbelt { 122*07037db5SPalmer Dabbelt } 123*07037db5SPalmer Dabbelt 124*07037db5SPalmer Dabbelt #endif /* _ASM_RISCV_PGALLOC_H */ 125