diff options
Diffstat (limited to 'arch/tile/include/asm/pgalloc.h')
| -rw-r--r-- | arch/tile/include/asm/pgalloc.h | 99 | 
1 files changed, 72 insertions, 27 deletions
diff --git a/arch/tile/include/asm/pgalloc.h b/arch/tile/include/asm/pgalloc.h index cf52791a550..1b902508b66 100644 --- a/arch/tile/include/asm/pgalloc.h +++ b/arch/tile/include/asm/pgalloc.h @@ -19,45 +19,45 @@  #include <linux/mm.h>  #include <linux/mmzone.h>  #include <asm/fixmap.h> +#include <asm/page.h>  #include <hv/hypervisor.h>  /* Bits for the size of the second-level page table. */ -#define L2_KERNEL_PGTABLE_SHIFT \ -  (HV_LOG2_PAGE_SIZE_LARGE - HV_LOG2_PAGE_SIZE_SMALL + HV_LOG2_PTE_SIZE) +#define L2_KERNEL_PGTABLE_SHIFT _HV_LOG2_L2_SIZE(HPAGE_SHIFT, PAGE_SHIFT) + +/* How big is a kernel L2 page table? */ +#define L2_KERNEL_PGTABLE_SIZE (1UL << L2_KERNEL_PGTABLE_SHIFT)  /* We currently allocate user L2 page tables by page (unlike kernel L2s). */ -#if L2_KERNEL_PGTABLE_SHIFT < HV_LOG2_PAGE_SIZE_SMALL -#define L2_USER_PGTABLE_SHIFT HV_LOG2_PAGE_SIZE_SMALL +#if L2_KERNEL_PGTABLE_SHIFT < PAGE_SHIFT +#define L2_USER_PGTABLE_SHIFT PAGE_SHIFT  #else  #define L2_USER_PGTABLE_SHIFT L2_KERNEL_PGTABLE_SHIFT  #endif  /* How many pages do we need, as an "order", for a user L2 page table? */ -#define L2_USER_PGTABLE_ORDER (L2_USER_PGTABLE_SHIFT - HV_LOG2_PAGE_SIZE_SMALL) - -/* How big is a kernel L2 page table? */ -#define L2_KERNEL_PGTABLE_SIZE (1 << L2_KERNEL_PGTABLE_SHIFT) +#define L2_USER_PGTABLE_ORDER (L2_USER_PGTABLE_SHIFT - PAGE_SHIFT)  static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)  {  #ifdef CONFIG_64BIT -	set_pte_order(pmdp, pmd, L2_USER_PGTABLE_ORDER); +	set_pte(pmdp, pmd);  #else -	set_pte_order(&pmdp->pud.pgd, pmd.pud.pgd, L2_USER_PGTABLE_ORDER); +	set_pte(&pmdp->pud.pgd, pmd.pud.pgd);  #endif  }  static inline void pmd_populate_kernel(struct mm_struct *mm,  				       pmd_t *pmd, pte_t *ptep)  { -	set_pmd(pmd, ptfn_pmd(__pa(ptep) >> HV_LOG2_PAGE_TABLE_ALIGN, +	set_pmd(pmd, ptfn_pmd(HV_CPA_TO_PTFN(__pa(ptep)),  			      __pgprot(_PAGE_PRESENT)));  }  static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,  				pgtable_t page)  { -	set_pmd(pmd, ptfn_pmd(HV_PFN_TO_PTFN(page_to_pfn(page)), +	set_pmd(pmd, ptfn_pmd(HV_CPA_TO_PTFN(PFN_PHYS(page_to_pfn(page))),  			      __pgprot(_PAGE_PRESENT)));  } @@ -68,8 +68,20 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,  extern pgd_t *pgd_alloc(struct mm_struct *mm);  extern void pgd_free(struct mm_struct *mm, pgd_t *pgd); -extern pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address); -extern void pte_free(struct mm_struct *mm, struct page *pte); +extern pgtable_t pgtable_alloc_one(struct mm_struct *mm, unsigned long address, +				   int order); +extern void pgtable_free(struct mm_struct *mm, struct page *pte, int order); + +static inline pgtable_t pte_alloc_one(struct mm_struct *mm, +				      unsigned long address) +{ +	return pgtable_alloc_one(mm, address, L2_USER_PGTABLE_ORDER); +} + +static inline void pte_free(struct mm_struct *mm, struct page *pte) +{ +	pgtable_free(mm, pte, L2_USER_PGTABLE_ORDER); +}  #define pmd_pgtable(pmd) pmd_page(pmd) @@ -85,8 +97,13 @@ static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)  	pte_free(mm, virt_to_page(pte));  } -extern void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte, -			   unsigned long address); +extern void __pgtable_free_tlb(struct mmu_gather *tlb, struct page *pte, +			       unsigned long address, int order); +static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte, +				  unsigned long address) +{ +	__pgtable_free_tlb(tlb, pte, address, L2_USER_PGTABLE_ORDER); +}  #define check_pgt_cache()	do { } while (0) @@ -100,20 +117,48 @@ pte_t *get_prealloc_pte(unsigned long pfn);  /* During init, we can shatter kernel huge pages if needed. */  void shatter_pmd(pmd_t *pmd); +/* After init, a more complex technique is required. */ +void shatter_huge_page(unsigned long addr); +  #ifdef __tilegx__ -/* We share a single page allocator for both L1 and L2 page tables. */ -#if HV_L1_SIZE != HV_L2_SIZE -# error Rework assumption that L1 and L2 page tables are same size. -#endif -#define L1_USER_PGTABLE_ORDER L2_USER_PGTABLE_ORDER +  #define pud_populate(mm, pud, pmd) \    pmd_populate_kernel((mm), (pmd_t *)(pud), (pte_t *)(pmd)) -#define pmd_alloc_one(mm, addr) \ -  ((pmd_t *)page_to_virt(pte_alloc_one((mm), (addr)))) -#define pmd_free(mm, pmdp) \ -  pte_free((mm), virt_to_page(pmdp)) -#define __pmd_free_tlb(tlb, pmdp, address) \ -  __pte_free_tlb((tlb), virt_to_page(pmdp), (address)) + +/* Bits for the size of the L1 (intermediate) page table. */ +#define L1_KERNEL_PGTABLE_SHIFT _HV_LOG2_L1_SIZE(HPAGE_SHIFT) + +/* How big is a kernel L2 page table? */ +#define L1_KERNEL_PGTABLE_SIZE (1UL << L1_KERNEL_PGTABLE_SHIFT) + +/* We currently allocate L1 page tables by page. */ +#if L1_KERNEL_PGTABLE_SHIFT < PAGE_SHIFT +#define L1_USER_PGTABLE_SHIFT PAGE_SHIFT +#else +#define L1_USER_PGTABLE_SHIFT L1_KERNEL_PGTABLE_SHIFT  #endif +/* How many pages do we need, as an "order", for an L1 page table? */ +#define L1_USER_PGTABLE_ORDER (L1_USER_PGTABLE_SHIFT - PAGE_SHIFT) + +static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address) +{ +	struct page *p = pgtable_alloc_one(mm, address, L1_USER_PGTABLE_ORDER); +	return (pmd_t *)page_to_virt(p); +} + +static inline void pmd_free(struct mm_struct *mm, pmd_t *pmdp) +{ +	pgtable_free(mm, virt_to_page(pmdp), L1_USER_PGTABLE_ORDER); +} + +static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp, +				  unsigned long address) +{ +	__pgtable_free_tlb(tlb, virt_to_page(pmdp), address, +			   L1_USER_PGTABLE_ORDER); +} + +#endif /* __tilegx__ */ +  #endif /* _ASM_TILE_PGALLOC_H */  | 
