cleanup
[linux-2.4.21-pre4.git] / include / asm-m68k / sun3_pgalloc.h
1 /* sun3_pgalloc.h --
2  * reorganization around 2.3.39, routines moved from sun3_pgtable.h 
3  *
4  * moved 1/26/2000 Sam Creasey
5  */
6
7 #ifndef _SUN3_PGALLOC_H
8 #define _SUN3_PGALLOC_H
9
10 /* Pagetable caches. */
11 //todo: should implement for at least ptes. --m
12 #define pgd_quicklist ((unsigned long *) 0)
13 #define pmd_quicklist ((unsigned long *) 0)
14 #define pte_quicklist ((unsigned long *) 0)
15 #define pgtable_cache_size (0L)
16
17 /* Allocation and deallocation of various flavours of pagetables. */
18 extern inline int free_pmd_fast (pmd_t *pmdp) { return 0; }
19 extern inline int free_pmd_slow (pmd_t *pmdp) { return 0; }
20 extern inline pmd_t *get_pmd_fast (void) { return (pmd_t *) 0; }
21
22 //todo: implement the following properly.
23 #define get_pte_fast() ((pte_t *) 0)
24 #define get_pte_slow pte_alloc
25 #define free_pte_fast(pte)
26 #define free_pte_slow pte_free
27
28 /* FIXME - when we get this compiling */
29 /* erm, now that it's compiling, what do we do with it? */
30 #define _KERNPG_TABLE 0
31
32 extern inline void pte_free_kernel(pte_t * pte)
33 {
34         free_page((unsigned long) pte);
35 }
36
37 extern const char bad_pmd_string[];
38
39 extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address)
40 {
41         address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
42         if (pmd_none(*pmd)) {
43                 pte_t * page = (pte_t *) get_free_page(GFP_KERNEL);
44                 if (pmd_none(*pmd)) {
45                         if (page) {
46                                 pmd_val(*pmd) = _KERNPG_TABLE + __pa(page);
47                                 return page + address;
48                         }
49                         pmd_val(*pmd) = _KERNPG_TABLE + __pa((unsigned long)BAD_PAGETABLE);
50                         return NULL;
51                 }
52                 free_page((unsigned long) page);
53         }
54         if (pmd_bad(*pmd)) {
55                 printk(bad_pmd_string, pmd_val(*pmd));
56                 printk("at kernel pgd off %08x\n", (unsigned int)pmd);
57                 pmd_val(*pmd) = _KERNPG_TABLE + __pa((unsigned long)BAD_PAGETABLE);
58                 return NULL;
59         }
60         return (pte_t *) __pmd_page(*pmd) + address;
61 }
62
63 /*
64  * allocating and freeing a pmd is trivial: the 1-entry pmd is
65  * inside the pgd, so has no extra memory associated with it.
66  */
67 extern inline void pmd_free_kernel(pmd_t * pmd)
68 {
69 //        pmd_val(*pmd) = 0;
70 }
71
72 extern inline pmd_t * pmd_alloc_kernel(pgd_t * pgd, unsigned long address)
73 {
74         return (pmd_t *) pgd;
75 }
76
77 #define pmd_alloc_one_fast(mm, address) ({ BUG(); ((pmd_t *)1); })
78 #define pmd_alloc_one(mm,address)       ({ BUG(); ((pmd_t *)2); })
79
80 extern inline void pte_free(pte_t * pte)
81 {
82         free_page((unsigned long) pte);
83 }
84
85 static inline pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address)
86 {
87         unsigned long page = __get_free_page(GFP_KERNEL);
88
89         if (!page)
90                 return NULL;
91                 
92         memset((void *)page, 0, PAGE_SIZE);
93 //      pmd_val(*pmd) = SUN3_PMD_MAGIC + __pa(page);
94 /*      pmd_val(*pmd) = __pa(page); */
95         return (pte_t *) (page);
96 }
97
98 #define pte_alloc_one_fast(mm,addr) pte_alloc_one(mm,addr)
99
100 #define pmd_populate(mm, pmd, pte) (pmd_val(*pmd) = __pa((unsigned long)pte))
101
102 /*
103  * allocating and freeing a pmd is trivial: the 1-entry pmd is
104  * inside the pgd, so has no extra memory associated with it.
105  */
106 extern inline void pmd_free(pmd_t * pmd)
107 {
108         pmd_val(*pmd) = 0;
109 }
110
111 extern inline void pgd_free(pgd_t * pgd)
112 {
113         free_page((unsigned long) pgd);
114 }
115
116 extern inline pgd_t * pgd_alloc(struct mm_struct *mm)
117 {
118      pgd_t *new_pgd;
119
120      new_pgd = (pgd_t *)get_free_page(GFP_KERNEL);
121      memcpy(new_pgd, swapper_pg_dir, PAGE_SIZE);
122      memset(new_pgd, 0, (PAGE_OFFSET >> PGDIR_SHIFT));
123      return new_pgd;
124 }
125
126 #define pgd_populate(mm, pmd, pte) BUG()
127
128 /* FIXME: the sun3 doesn't have a page table cache! 
129    (but the motorola routine should just return 0) */
130
131 extern int do_check_pgt_cache(int, int);
132
133 extern inline void set_pgdir(unsigned long address, pgd_t entry)
134 {
135 }
136
137 /* Reserved PMEGs. */
138 extern char sun3_reserved_pmeg[SUN3_PMEGS_NUM];
139 extern unsigned long pmeg_vaddr[SUN3_PMEGS_NUM];
140 extern unsigned char pmeg_alloc[SUN3_PMEGS_NUM];
141 extern unsigned char pmeg_ctx[SUN3_PMEGS_NUM];
142
143 /* Flush all userspace mappings one by one...  (why no flush command,
144    sun?) */
145 static inline void flush_tlb_all(void)
146 {
147        unsigned long addr;
148        unsigned char ctx, oldctx;
149
150        oldctx = sun3_get_context();
151        for(addr = 0x00000000; addr < TASK_SIZE; addr += SUN3_PMEG_SIZE) {
152                for(ctx = 0; ctx < 8; ctx++) {
153                        sun3_put_context(ctx);
154                        sun3_put_segmap(addr, SUN3_INVALID_PMEG);
155                }
156        }
157
158        sun3_put_context(oldctx);
159        /* erase all of the userspace pmeg maps, we've clobbered them
160           all anyway */
161        for(addr = 0; addr < SUN3_INVALID_PMEG; addr++) {
162                if(pmeg_alloc[addr] == 1) {
163                        pmeg_alloc[addr] = 0;
164                        pmeg_ctx[addr] = 0;
165                        pmeg_vaddr[addr] = 0;
166                }
167        }
168
169 }
170
171 /* Clear user TLB entries within the context named in mm */
172 static inline void flush_tlb_mm (struct mm_struct *mm)
173 {
174      unsigned char oldctx;
175      unsigned char seg;
176      unsigned long i;
177
178      oldctx = sun3_get_context();
179      sun3_put_context(mm->context);
180
181      for(i = 0; i < TASK_SIZE; i += SUN3_PMEG_SIZE) {
182              seg = sun3_get_segmap(i);
183              if(seg == SUN3_INVALID_PMEG)
184                      continue;
185              
186              sun3_put_segmap(i, SUN3_INVALID_PMEG);
187              pmeg_alloc[seg] = 0;
188              pmeg_ctx[seg] = 0;
189              pmeg_vaddr[seg] = 0;
190      }
191
192      sun3_put_context(oldctx);
193                      
194 }
195
196 /* Flush a single TLB page. In this case, we're limited to flushing a
197    single PMEG */
198 static inline void flush_tlb_page (struct vm_area_struct *vma,
199                                    unsigned long addr)
200 {
201         unsigned char oldctx;
202         unsigned char i;
203
204         oldctx = sun3_get_context();
205         sun3_put_context(vma->vm_mm->context);
206         addr &= ~SUN3_PMEG_MASK;
207         if((i = sun3_get_segmap(addr)) != SUN3_INVALID_PMEG)
208         {
209                 pmeg_alloc[i] = 0;
210                 pmeg_ctx[i] = 0;
211                 pmeg_vaddr[i] = 0;
212                 sun3_put_segmap (addr,  SUN3_INVALID_PMEG);     
213         }
214         sun3_put_context(oldctx);
215
216 }
217 /* Flush a range of pages from TLB. */
218
219 static inline void flush_tlb_range (struct mm_struct *mm,
220                       unsigned long start, unsigned long end)
221 {
222         unsigned char seg, oldctx;
223         
224         start &= ~SUN3_PMEG_MASK;
225
226         oldctx = sun3_get_context();
227         sun3_put_context(mm->context);
228
229         while(start < end)
230         {
231                 if((seg = sun3_get_segmap(start)) == SUN3_INVALID_PMEG) 
232                      goto next;
233                 if(pmeg_ctx[seg] == mm->context) {
234                         pmeg_alloc[seg] = 0;
235                         pmeg_ctx[seg] = 0;
236                         pmeg_vaddr[seg] = 0;
237                 }
238                 sun3_put_segmap(start, SUN3_INVALID_PMEG);
239         next:
240                 start += SUN3_PMEG_SIZE;
241         }
242 }
243
244 /* Flush kernel page from TLB. */
245 static inline void flush_tlb_kernel_page (unsigned long addr)
246 {
247         sun3_put_segmap (addr & ~(SUN3_PMEG_SIZE - 1), SUN3_INVALID_PMEG);
248 }
249
250 extern inline void flush_tlb_pgtables(struct mm_struct *mm,
251                                       unsigned long start, unsigned long end)
252 {
253 }
254
255 #endif /* SUN3_PGALLOC_H */