Import 1.3.87
[davej-history.git] / arch / mips / mm / init.c
blob9da156c396f8cd7ead012519c4609ea02dd2e186
1 /*
2 * arch/mips/mm/init.c
4 * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
5 * Ported to MIPS by Ralf Baechle
6 */
7 #include <linux/config.h>
8 #include <linux/signal.h>
9 #include <linux/sched.h>
10 #include <linux/head.h>
11 #include <linux/kernel.h>
12 #include <linux/errno.h>
13 #include <linux/string.h>
14 #include <linux/types.h>
15 #include <linux/ptrace.h>
16 #include <linux/mman.h>
17 #include <linux/mm.h>
19 #include <asm/cachectl.h>
20 #include <asm/jazzdma.h>
21 #include <asm/vector.h>
22 #include <asm/system.h>
23 #include <asm/segment.h>
24 #include <asm/pgtable.h>
26 externvoiddeskstation_tyne_dma_init(void);
27 externvoidsound_mem_init(void);
28 externvoiddie_if_kernel(char*,struct pt_regs *,long);
29 externvoidshow_net_buffers(void);
31 externchar empty_zero_page[PAGE_SIZE];
34 * BAD_PAGE is the page that is used for page faults when linux
35 * is out-of-memory. Older versions of linux just did a
36 * do_exit(), but using this instead means there is less risk
37 * for a process dying in kernel mode, possibly leaving a inode
38 * unused etc..
40 * BAD_PAGETABLE is the accompanying page-table: it is initialized
41 * to point to BAD_PAGE entries.
43 * ZERO_PAGE is a special page that is used for zero-initialized
44 * data and COW.
46 pte_t *__bad_pagetable(void)
48 externchar empty_bad_page_table[PAGE_SIZE];
49 unsigned long page;
50 unsigned long dummy1, dummy2;
52 page = ((unsigned long)empty_bad_page_table) + (PT_OFFSET - PAGE_OFFSET);
53 #if __mips__ >= 3
55 * Use 64bit code even for Linux/MIPS 32bit on R4000
57 __asm__ __volatile__(
58 ".set\tnoreorder\n"
59 ".set\tnoat\n\t"
60 ".set\tmips3\n\t"
61 "dsll32\t$1,%2,0\n\t"
62 "dsrl32\t%2,$1,0\n\t"
63 "or\t%2,$1\n"
64 "1:\tsd\t%2,(%0)\n\t"
65 "subu\t%1,1\n\t"
66 "bnez\t%1,1b\n\t"
67 "addiu\t%0,8\n\t"
68 ".set\tmips0\n\t"
69 ".set\tat\n"
70 ".set\treorder"
71 :"=r"(dummy1),
72 "=r"(dummy2)
73 :"r"(pte_val(BAD_PAGE)),
74 "0"(page),
75 "1"(PAGE_SIZE/8));
76 #else
77 __asm__ __volatile__(
78 ".set\tnoreorder\n"
79 "1:\tsw\t%2,(%0)\n\t"
80 "subu\t%1,1\n\t"
81 "bnez\t%1,1b\n\t"
82 "addiu\t%0,4\n\t"
83 ".set\treorder"
84 :"=r"(dummy1),
85 "=r"(dummy2)
86 :"r"(pte_val(BAD_PAGE)),
87 "0"(page),
88 "1"(PAGE_SIZE/4));
89 #endif
91 return(pte_t *)page;
94 staticinlinevoid
95 __zeropage(unsigned long page)
97 unsigned long dummy1, dummy2;
99 #ifdef __R4000__
101 * Use 64bit code even for Linux/MIPS 32bit on R4000
103 __asm__ __volatile__(
104 ".set\tnoreorder\n"
105 ".set\tnoat\n\t"
106 ".set\tmips3\n"
107 "1:\tsd\t$0,(%0)\n\t"
108 "subu\t%1,1\n\t"
109 "bnez\t%1,1b\n\t"
110 "addiu\t%0,8\n\t"
111 ".set\tmips0\n\t"
112 ".set\tat\n"
113 ".set\treorder"
114 :"=r"(dummy1),
115 "=r"(dummy2)
116 :"0"(page),
117 "1"(PAGE_SIZE/8));
118 #else
119 __asm__ __volatile__(
120 ".set\tnoreorder\n"
121 "1:\tsw\t$0,(%0)\n\t"
122 "subu\t%1,1\n\t"
123 "bnez\t%1,1b\n\t"
124 "addiu\t%0,4\n\t"
125 ".set\treorder"
126 :"=r"(dummy1),
127 "=r"(dummy2)
128 :"0"(page),
129 "1"(PAGE_SIZE/4));
130 #endif
133 staticinlinevoid
134 zeropage(unsigned long page)
136 sys_cacheflush((void*)page, PAGE_SIZE, BCACHE);
137 sync_mem();
138 __zeropage(page + (PT_OFFSET - PAGE_OFFSET));
141 pte_t __bad_page(void)
143 externchar empty_bad_page[PAGE_SIZE];
144 unsigned long page = (unsigned long)empty_bad_page;
146 zeropage(page);
147 returnpte_mkdirty(mk_pte(page, PAGE_SHARED));
150 unsigned long__zero_page(void)
152 unsigned long page = (unsigned long) empty_zero_page;
154 zeropage(page);
155 return page;
159 * This is horribly inefficient ...
161 void__copy_page(unsigned long from,unsigned long to)
164 * Now copy page from uncached KSEG1 to KSEG0. The copy destination
165 * is in KSEG0 so that we keep stupid L2 caches happy.
167 if(from == (unsigned long) empty_zero_page)
170 * The page copied most is the COW empty_zero_page. Since we
171 * know it's contents we can avoid the writeback reading of
172 * the page. Speeds up the standard case a lot.
174 __zeropage(to);
176 else
179 * Force writeback of old page to memory. We don't know the
180 * virtual address, so we have to flush the entire cache ...
182 sys_cacheflush(0, ~0, DCACHE);
183 sync_mem();
184 memcpy((void*) to,
185 (void*) (from + (PT_OFFSET - PAGE_OFFSET)), PAGE_SIZE);
188 * Now writeback the page again if colour has changed.
189 * Actually this does a Hit_Writeback, but due to an artifact in
190 * the R4xx0 implementation this should be slightly faster.
191 * Then sweep chipset controlled secondary caches and the ICACHE.
193 if(page_colour(from) !=page_colour(to))
194 sys_cacheflush(0, ~0, DCACHE);
195 sys_cacheflush(0, ~0, ICACHE);
198 voidshow_mem(void)
200 int i, free =0, total =0, reserved =0;
201 int shared =0;
203 printk("Mem-info:\n");
204 show_free_areas();
205 printk("Free swap: %6dkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
206 i = (high_memory - PAGE_OFFSET) >> PAGE_SHIFT;
207 while(i-- >0) {
208 total++;
209 if(mem_map[i].reserved)
210 reserved++;
211 else if(!mem_map[i].count)
212 free++;
213 else
214 shared += mem_map[i].count-1;
216 printk("%d pages of RAM\n", total);
217 printk("%d free pages\n", free);
218 printk("%d reserved pages\n", reserved);
219 printk("%d pages shared\n", shared);
220 show_buffers();
221 #ifdef CONFIG_NET
222 show_net_buffers();
223 #endif
226 externunsigned longfree_area_init(unsigned long,unsigned long);
228 unsigned longpaging_init(unsigned long start_mem,unsigned long end_mem)
230 pgd_init((unsigned long)swapper_pg_dir - (PT_OFFSET - PAGE_OFFSET));
231 returnfree_area_init(start_mem, end_mem);
234 voidmem_init(unsigned long start_mem,unsigned long end_mem)
236 int codepages =0;
237 int datapages =0;
238 unsigned long tmp;
239 externint _etext;
241 #ifdef CONFIG_MIPS_JAZZ
242 start_mem =vdma_init(start_mem, end_mem);
243 #endif
245 end_mem &= PAGE_MASK;
246 high_memory = end_mem;
248 /* mark usable pages in the mem_map[] */
249 start_mem =PAGE_ALIGN(start_mem);
251 tmp = start_mem;
252 while(tmp < high_memory) {
253 mem_map[MAP_NR(tmp)].reserved =0;
254 tmp += PAGE_SIZE;
257 #ifdef CONFIG_DESKSTATION_TYNE
258 deskstation_tyne_dma_init();
259 #endif
260 #ifdef CONFIG_SOUND
261 sound_mem_init();
262 #endif
263 for(tmp = PAGE_OFFSET ; tmp < high_memory ; tmp += PAGE_SIZE) {
264 if(mem_map[MAP_NR(tmp)].reserved) {
265 if(tmp < (unsigned long) &_etext)
266 codepages++;
267 else if(tmp < start_mem)
268 datapages++;
269 continue;
271 mem_map[MAP_NR(tmp)].count =1;
272 free_page(tmp);
274 tmp = nr_free_pages << PAGE_SHIFT;
275 printk("Memory: %luk/%luk available (%dk kernel code, %dk data)\n",
276 tmp >>10,
277 (high_memory - PAGE_OFFSET) >>10,
278 codepages << (PAGE_SHIFT-10),
279 datapages << (PAGE_SHIFT-10));
281 return;
284 voidsi_meminfo(struct sysinfo *val)
286 int i;
288 i = high_memory >> PAGE_SHIFT;
289 val->totalram =0;
290 val->sharedram =0;
291 val->freeram = nr_free_pages << PAGE_SHIFT;
292 val->bufferram = buffermem;
293 while(i-- >0) {
294 if(mem_map[i].reserved)
295 continue;
296 val->totalram++;
297 if(!mem_map[i].count)
298 continue;
299 val->sharedram += mem_map[i].count-1;
301 val->totalram <<= PAGE_SHIFT;
302 val->sharedram <<= PAGE_SHIFT;
303 return;
close