blob: a00ee002cd1165f9eb298a4112a4a74712c05966 [file] [log] [blame]
Paul Mackerras047ea782005-11-19 20:17:32 +11001#ifndef _ASM_POWERPC_PGALLOC_H
2#define _ASM_POWERPC_PGALLOC_H
Arnd Bergmann88ced032005-12-16 22:43:46 +01003#ifdef __KERNEL__
Paul Mackerras047ea782005-11-19 20:17:32 +11004
5#ifndef CONFIG_PPC64
6#include <asm-ppc/pgalloc.h>
7#else
Linus Torvalds1da177e2005-04-16 15:20:36 -07008
9#include <linux/mm.h>
10#include <linux/slab.h>
11#include <linux/cpumask.h>
12#include <linux/percpu.h>
13
David Gibsone28f7fa2005-08-05 19:39:06 +100014extern kmem_cache_t *pgtable_cache[];
15
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +110016#ifdef CONFIG_PPC_64K_PAGES
17#define PTE_CACHE_NUM 0
Benjamin Herrenschmidt87655ff2005-11-10 14:53:16 +110018#define PMD_CACHE_NUM 1
19#define PGD_CACHE_NUM 2
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +110020#else
David Gibsone28f7fa2005-08-05 19:39:06 +100021#define PTE_CACHE_NUM 0
22#define PMD_CACHE_NUM 1
23#define PUD_CACHE_NUM 1
24#define PGD_CACHE_NUM 0
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +110025#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070026
27/*
28 * This program is free software; you can redistribute it and/or
29 * modify it under the terms of the GNU General Public License
30 * as published by the Free Software Foundation; either version
31 * 2 of the License, or (at your option) any later version.
32 */
33
David Gibsone28f7fa2005-08-05 19:39:06 +100034static inline pgd_t *pgd_alloc(struct mm_struct *mm)
Linus Torvalds1da177e2005-04-16 15:20:36 -070035{
David Gibsone28f7fa2005-08-05 19:39:06 +100036 return kmem_cache_alloc(pgtable_cache[PGD_CACHE_NUM], GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070037}
38
David Gibsone28f7fa2005-08-05 19:39:06 +100039static inline void pgd_free(pgd_t *pgd)
Linus Torvalds1da177e2005-04-16 15:20:36 -070040{
David Gibsone28f7fa2005-08-05 19:39:06 +100041 kmem_cache_free(pgtable_cache[PGD_CACHE_NUM], pgd);
42}
43
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +110044#ifndef CONFIG_PPC_64K_PAGES
45
David Gibsone28f7fa2005-08-05 19:39:06 +100046#define pgd_populate(MM, PGD, PUD) pgd_set(PGD, PUD)
47
48static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
49{
50 return kmem_cache_alloc(pgtable_cache[PUD_CACHE_NUM],
51 GFP_KERNEL|__GFP_REPEAT);
52}
53
54static inline void pud_free(pud_t *pud)
55{
56 kmem_cache_free(pgtable_cache[PUD_CACHE_NUM], pud);
Linus Torvalds1da177e2005-04-16 15:20:36 -070057}
58
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +110059static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
60{
61 pud_set(pud, (unsigned long)pmd);
62}
63
64#define pmd_populate(mm, pmd, pte_page) \
65 pmd_populate_kernel(mm, pmd, page_address(pte_page))
66#define pmd_populate_kernel(mm, pmd, pte) pmd_set(pmd, (unsigned long)(pte))
67
68
69#else /* CONFIG_PPC_64K_PAGES */
70
71#define pud_populate(mm, pud, pmd) pud_set(pud, (unsigned long)pmd)
72
73static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
74 pte_t *pte)
75{
76 pmd_set(pmd, (unsigned long)pte);
77}
78
79#define pmd_populate(mm, pmd, pte_page) \
80 pmd_populate_kernel(mm, pmd, page_address(pte_page))
81
82#endif /* CONFIG_PPC_64K_PAGES */
Linus Torvalds1da177e2005-04-16 15:20:36 -070083
David Gibsone28f7fa2005-08-05 19:39:06 +100084static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070085{
David Gibsone28f7fa2005-08-05 19:39:06 +100086 return kmem_cache_alloc(pgtable_cache[PMD_CACHE_NUM],
87 GFP_KERNEL|__GFP_REPEAT);
Linus Torvalds1da177e2005-04-16 15:20:36 -070088}
89
David Gibsone28f7fa2005-08-05 19:39:06 +100090static inline void pmd_free(pmd_t *pmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -070091{
David Gibsone28f7fa2005-08-05 19:39:06 +100092 kmem_cache_free(pgtable_cache[PMD_CACHE_NUM], pmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070093}
94
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +110095static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
96 unsigned long address)
Linus Torvalds1da177e2005-04-16 15:20:36 -070097{
David Gibsone28f7fa2005-08-05 19:39:06 +100098 return kmem_cache_alloc(pgtable_cache[PTE_CACHE_NUM],
99 GFP_KERNEL|__GFP_REPEAT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100}
101
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100102static inline struct page *pte_alloc_one(struct mm_struct *mm,
103 unsigned long address)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104{
David Gibsone28f7fa2005-08-05 19:39:06 +1000105 return virt_to_page(pte_alloc_one_kernel(mm, address));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106}
107
108static inline void pte_free_kernel(pte_t *pte)
109{
David Gibsone28f7fa2005-08-05 19:39:06 +1000110 kmem_cache_free(pgtable_cache[PTE_CACHE_NUM], pte);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111}
112
113static inline void pte_free(struct page *ptepage)
114{
David Gibsone28f7fa2005-08-05 19:39:06 +1000115 pte_free_kernel(page_address(ptepage));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116}
117
David Gibsone28f7fa2005-08-05 19:39:06 +1000118#define PGF_CACHENUM_MASK 0xf
119
120typedef struct pgtable_free {
121 unsigned long val;
122} pgtable_free_t;
123
124static inline pgtable_free_t pgtable_free_cache(void *p, int cachenum,
125 unsigned long mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126{
David Gibsone28f7fa2005-08-05 19:39:06 +1000127 BUG_ON(cachenum > PGF_CACHENUM_MASK);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128
David Gibsone28f7fa2005-08-05 19:39:06 +1000129 return (pgtable_free_t){.val = ((unsigned long) p & ~mask) | cachenum};
130}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131
David Gibsone28f7fa2005-08-05 19:39:06 +1000132static inline void pgtable_free(pgtable_free_t pgf)
133{
134 void *p = (void *)(pgf.val & ~PGF_CACHENUM_MASK);
135 int cachenum = pgf.val & PGF_CACHENUM_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136
David Gibsone28f7fa2005-08-05 19:39:06 +1000137 kmem_cache_free(pgtable_cache[cachenum], p);
138}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100140extern void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf);
David Gibsone28f7fa2005-08-05 19:39:06 +1000141
142#define __pte_free_tlb(tlb, ptepage) \
143 pgtable_free_tlb(tlb, pgtable_free_cache(page_address(ptepage), \
144 PTE_CACHE_NUM, PTE_TABLE_SIZE-1))
145#define __pmd_free_tlb(tlb, pmd) \
146 pgtable_free_tlb(tlb, pgtable_free_cache(pmd, \
147 PMD_CACHE_NUM, PMD_TABLE_SIZE-1))
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100148#ifndef CONFIG_PPC_64K_PAGES
David Gibson200a4552006-02-17 13:52:56 -0800149#define __pud_free_tlb(tlb, pud) \
David Gibsone28f7fa2005-08-05 19:39:06 +1000150 pgtable_free_tlb(tlb, pgtable_free_cache(pud, \
151 PUD_CACHE_NUM, PUD_TABLE_SIZE-1))
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100152#endif /* CONFIG_PPC_64K_PAGES */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153
154#define check_pgt_cache() do { } while (0)
155
Paul Mackerras047ea782005-11-19 20:17:32 +1100156#endif /* CONFIG_PPC64 */
Arnd Bergmann88ced032005-12-16 22:43:46 +0100157#endif /* __KERNEL__ */
Paul Mackerras047ea782005-11-19 20:17:32 +1100158#endif /* _ASM_POWERPC_PGALLOC_H */