more changes on original files
[linux-2.4.git] / asm-ppc / pgalloc.h
1 #ifdef __KERNEL__
2 #ifndef _PPC_PGALLOC_H
3 #define _PPC_PGALLOC_H
4
5 #include <linux/config.h>
6 #include <linux/threads.h>
7 #include <asm/processor.h>
8
9 #ifdef CONFIG_PTE_64BIT
10 /* 44x uses an 8kB pgdir because it has 8-byte Linux PTEs. */
11 #define PGDIR_ORDER     1
12 #else
13 #define PGDIR_ORDER     0
14 #endif
15
16 /*
17  * This is handled very differently on the PPC since out page tables
18  * are all 0's and I want to be able to use these zero'd pages elsewhere
19  * as well - it gives us quite a speedup.
20  *
21  * Note that the SMP/UP versions are the same but we don't need a
22  * per cpu list of zero pages because we do the zero-ing with the cache
23  * off and the access routines are lock-free but the pgt cache stuff
24  * is per-cpu since it isn't done with any lock-free access routines
25  * (although I think we need arch-specific routines so I can do lock-free).
26  *
27  * I need to generalize this so we can use it for other arch's as well.
28  * -- Cort
29  */
30 #ifdef CONFIG_SMP
31 #define quicklists      cpu_data[smp_processor_id()]
32 #else
33 extern struct pgtable_cache_struct {
34         unsigned long *pgd_cache;
35         unsigned long *pte_cache;
36         unsigned long pgtable_cache_sz;
37 } quicklists;
38 #endif
39
40 #define pgd_quicklist           (quicklists.pgd_cache)
41 #define pmd_quicklist           ((unsigned long *)0)
42 #define pte_quicklist           (quicklists.pte_cache)
43 #define pgtable_cache_size      (quicklists.pgtable_cache_sz)
44
45 extern unsigned long *zero_cache;    /* head linked list of pre-zero'd pages */
46 extern atomic_t zero_sz;             /* # currently pre-zero'd pages */
47 extern atomic_t zeropage_hits;       /* # zero'd pages request that we've done */
48 extern atomic_t zeropage_calls;      /* # zero'd pages request that've been made */
49 extern atomic_t zerototal;           /* # pages zero'd over time */
50
51 #define zero_quicklist          (zero_cache)
52 #define zero_cache_sz           (zero_sz)
53 #define zero_cache_calls        (zeropage_calls)
54 #define zero_cache_hits         (zeropage_hits)
55 #define zero_cache_total        (zerototal)
56
57 /* return a pre-zero'd page from the list, return NULL if none available -- Cort */
58 extern unsigned long get_zero_page_fast(void);
59
60 extern void __bad_pte(pmd_t *pmd);
61
62 extern __inline__ pgd_t *get_pgd_slow(void)
63 {
64         pgd_t *ret;
65
66         if ((ret = (pgd_t *)__get_free_pages(GFP_KERNEL, PGDIR_ORDER)) != NULL)
67                 clear_page(ret);
68         return ret;
69 }
70
71 extern __inline__ pgd_t *get_pgd_fast(void)
72 {
73         unsigned long *ret;
74
75         if ((ret = pgd_quicklist) != NULL) {
76                 pgd_quicklist = (unsigned long *)(*ret);
77                 ret[0] = 0;
78                 pgtable_cache_size--;
79         } else
80                 ret = (unsigned long *)get_pgd_slow();
81         return (pgd_t *)ret;
82 }
83
84 extern __inline__ void free_pgd_fast(pgd_t *pgd)
85 {
86         *(unsigned long **)pgd = pgd_quicklist;
87         pgd_quicklist = (unsigned long *) pgd;
88         pgtable_cache_size++;
89 }
90
91 extern __inline__ void free_pgd_slow(pgd_t *pgd)
92 {
93         free_page((unsigned long)pgd);
94 }
95
96 #define pgd_free(pgd)           free_pgd_fast(pgd)
97 #define pgd_alloc(mm)           get_pgd_fast()
98
99 /*
100  * We don't have any real pmd's, and this code never triggers because
101  * the pgd will always be present..
102  */
103 #define pmd_alloc_one_fast(mm, address) ({ BUG(); ((pmd_t *)1); })
104 #define pmd_alloc_one(mm,address)       ({ BUG(); ((pmd_t *)2); })
105 #define pmd_free(x)                     do { } while (0)
106 #define pgd_populate(mm, pmd, pte)      BUG()
107
108 static inline pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address)
109 {
110         pte_t *pte;
111         extern int mem_init_done;
112         extern void *early_get_page(void);
113
114         if (mem_init_done)
115                 pte = (pte_t *) __get_free_page(GFP_KERNEL);
116         else
117                 pte = (pte_t *) early_get_page();
118         if (pte != NULL)
119                 clear_page(pte);
120         return pte;
121 }
122
123 static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm, unsigned long address)
124 {
125         unsigned long *ret;
126
127         if ((ret = pte_quicklist) != NULL) {
128                 pte_quicklist = (unsigned long *)(*ret);
129                 ret[0] = 0;
130                 pgtable_cache_size--;
131         }
132         return (pte_t *)ret;
133 }
134
135 extern __inline__ void pte_free_fast(pte_t *pte)
136 {
137         *(unsigned long **)pte = pte_quicklist;
138         pte_quicklist = (unsigned long *) pte;
139         pgtable_cache_size++;
140 }
141
142 extern __inline__ void pte_free_slow(pte_t *pte)
143 {
144         free_page((unsigned long)pte);
145 }
146
147 #define pte_free(pte)    pte_free_slow(pte)
148
149 #define pmd_populate(mm, pmd, pte)      (pmd_val(*(pmd)) = (unsigned long) (pte))
150
151 extern int do_check_pgt_cache(int, int);
152
153 #endif /* _PPC_PGALLOC_H */
154 #endif /* __KERNEL__ */