File: /usr/src/linux/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 */
256