File: /usr/src/linux/arch/parisc/mm/init.c

1     /*
2      *  linux/arch/parisc/mm/init.c
3      *
4      *  Copyright (C) 1995	Linus Torvalds
5      *  Copyright 1999 SuSE GmbH
6      *    changed by Philipp Rumpf
7      *  Copyright 1999 Philipp Rumpf (prumpf@tux.org)
8      *
9      */
10     
11     #include <linux/config.h>
12     
13     #include <linux/mm.h>
14     #include <linux/bootmem.h>
15     #include <linux/delay.h>
16     #include <linux/init.h>
17     #include <linux/pci.h>		/* for hppa_dma_ops and pcxl_dma_ops */
18     #include <linux/swap.h>
19     #include <linux/unistd.h>
20     
21     #include <asm/pgalloc.h>
22     
23     static unsigned long totalram_pages;
24     extern unsigned long max_pfn, mem_max;
25     
26     void free_initmem(void)  {
27     }
28     
29     /*
30      * Just an arbitrary offset to serve as a "hole" between mapping areas
31      * (between top of physical memory and a potential pcxl dma mapping
32      * area, and below the vmalloc mapping area).
33      *
34      * The current 32K value just means that there will be a 32K "hole"
35      * between mapping areas. That means that  any out-of-bounds memory
36      * accesses will hopefully be caught. The vmalloc() routines leaves
37      * a hole of 4kB between each vmalloced area for the same reason.
38      */
39     
40     #define VM_MAP_OFFSET  (32*1024)
41     #define SET_MAP_OFFSET(x) ((void *)(((unsigned long)(x) + VM_MAP_OFFSET) \
42     				     & ~(VM_MAP_OFFSET-1)))
43     
44     void *vmalloc_start;
45     unsigned long pcxl_dma_start;
46     
47     void __init mem_init(void)
48     {
49     	max_mapnr = num_physpages = max_low_pfn;
50     	high_memory = __va(max_low_pfn * PAGE_SIZE);
51     
52     	totalram_pages += free_all_bootmem();
53     	printk("Memory: %luk available\n", totalram_pages << (PAGE_SHIFT-10));
54     
55     	if (hppa_dma_ops == &pcxl_dma_ops) {
56     	    pcxl_dma_start = (unsigned long)SET_MAP_OFFSET(high_memory);
57     	    vmalloc_start = SET_MAP_OFFSET(pcxl_dma_start + PCXL_DMA_MAP_SIZE);
58     	}
59     	else {
60     	    pcxl_dma_start = 0;
61     	    vmalloc_start = SET_MAP_OFFSET(high_memory);
62     	}
63     }
64     
65     void __bad_pgd(pgd_t *pgd)
66     {
67     	printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd));
68     	pgd_val(*pgd) = _PAGE_TABLE + __pa(BAD_PAGETABLE);
69     }
70     
71     void __bad_pmd(pmd_t *pmd)
72     {
73     	printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
74     	pmd_val(*pmd) = _PAGE_TABLE + __pa(BAD_PAGETABLE);
75     }
76     
77     pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
78     {
79     	pte_t *pte;
80     
81     	pte = (pte_t *) __get_free_page(GFP_KERNEL);
82     
83     	if (pmd_none(*pmd)) {
84     		if (pte) {
85     			clear_page(pte);
86     			pmd_val(*pmd) = _PAGE_TABLE + __pa((unsigned long)pte);
87     			return pte + offset;
88     		}
89     		pmd_val(*pmd) = _PAGE_TABLE + __pa(BAD_PAGETABLE);
90     		return NULL;
91     	}
92     
93     	free_page((unsigned long)pte);
94     
95     	if (pmd_bad(*pmd)) {
96     		__bad_pmd(pmd);
97     		return NULL;
98     	}
99     
100     	return (pte_t *) pmd_page(*pmd) + offset;
101     }
102     
103     int do_check_pgt_cache(int low, int high)
104     {
105     	return 0;
106     }
107     
108     /*
109      * BAD_PAGE is the page that is used for page faults when linux
110      * is out-of-memory. Older versions of linux just did a
111      * do_exit(), but using this instead means there is less risk
112      * for a process dying in kernel mode, possibly leaving an inode
113      * unused etc..
114      *
115      * BAD_PAGETABLE is the accompanying page-table: it is initialized
116      * to point to BAD_PAGE entries.
117      *
118      * ZERO_PAGE is a special page that is used for zero-initialized
119      * data and COW.
120      */
121     pte_t * __bad_pagetable(void)
122     {
123     	return (pte_t *) NULL;
124     }
125     
126     unsigned long *empty_zero_page;
127     unsigned long *empty_bad_page;
128     
129     pte_t __bad_page(void)
130     {
131     	return *(pte_t *)NULL;
132     }
133     
134     void show_mem(void)
135     {
136     	int i,free = 0,total = 0,reserved = 0;
137     	int shared = 0, cached = 0;
138     
139     	printk("Mem-info:\n");
140     	show_free_areas();
141     	printk("Free swap:	 %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
142     	i = max_mapnr;
143     	while (i-- > 0) {
144     		total++;
145     		if (PageReserved(mem_map+i))
146     			reserved++;
147     		else if (PageSwapCache(mem_map+i))
148     			cached++;
149     		else if (!atomic_read(&mem_map[i].count))
150     			free++;
151     		else
152     			shared += atomic_read(&mem_map[i].count) - 1;
153     	}
154     	printk("%d pages of RAM\n",total);
155     	printk("%d reserved pages\n",reserved);
156     	printk("%d pages shared\n",shared);
157     	printk("%d pages swap cached\n",cached);
158     	show_buffers();
159     }
160     
161     void set_pte_phys (unsigned long vaddr, unsigned long phys)
162     {
163     }
164     
165     
166     /*
167      * pagetable_init() sets up the page tables
168      *
169      * Note that gateway_init() places the Linux gateway page at page 0.
170      * Since gateway pages cannot be dereferenced this has the desirable
171      * side effect of trapping those pesky NULL-reference errors in the
172      * kernel.
173      */
174     static void __init pagetable_init(void)
175     {
176     	pgd_t *pg_dir;
177     	pmd_t *pmd;
178     	pte_t *pg_table;
179     	unsigned long tmp1;
180     	unsigned long tmp2;
181     	unsigned long address;
182     	unsigned long ro_start;
183     	unsigned long ro_end;
184     	unsigned long fv_addr;
185     	extern  const int stext;
186     	extern  int data_start;
187     	extern  const unsigned long fault_vector_20;
188     
189     	ro_start = __pa((unsigned long)&stext);
190     	ro_end   = __pa((unsigned long)&data_start);
191     	fv_addr  = __pa((unsigned long)&fault_vector_20) & PAGE_MASK;
192     
193     	printk("pagetable_init\n");
194     
195     	/* Map whole memory from PAGE_OFFSET */
196     	pg_dir = (pgd_t *)swapper_pg_dir + USER_PGD_PTRS;
197     
198     	address = 0;
199     	while (address < mem_max) {
200     		/* XXX: BTLB should be done here */
201     
202     #if PTRS_PER_PMD == 1
203     		pmd = (pmd_t *)__pa(pg_dir);
204     #else
205     		pmd = (pmd_t *) (PAGE_MASK & pgd_val(*pg_dir));
206     
207     		/*
208     		 * pmd is physical at this point
209     		 */
210     
211     		if (!pmd) {
212     			pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
213     			pmd = (pmd_t *) __pa(pmd);
214     		}
215     
216     		pgd_val(*pg_dir) = _PAGE_TABLE | (unsigned long) pmd;
217     #endif
218     		pg_dir++;
219     
220     		/* now change pmd to kernel virtual addresses */
221     
222     		pmd = (pmd_t *) __va(pmd);
223     		for (tmp1 = 0 ; tmp1 < PTRS_PER_PMD ; tmp1++,pmd++) {
224     
225     			/*
226     			 * pg_table is physical at this point
227     			 */
228     
229     			pg_table = (pte_t *) (PAGE_MASK & pmd_val(*pmd));
230     			if (!pg_table) {
231     				pg_table = (pte_t *)
232     					alloc_bootmem_low_pages(PAGE_SIZE);
233     				pg_table = (pte_t *) __pa(pg_table);
234     			}
235     
236     			pmd_val(*pmd) = _PAGE_TABLE |
237     					   (unsigned long) pg_table;
238     
239     			/* now change pg_table to kernel virtual addresses */
240     
241     			pg_table = (pte_t *) __va(pg_table);
242     			for (tmp2=0; tmp2 < PTRS_PER_PTE; tmp2++,pg_table++) {
243     				pte_t pte;
244     
245     #if !defined(CONFIG_KWDB) && !defined(CONFIG_STI_CONSOLE)
246     #warning STI console should explicitly allocate executable pages but does not
247     /* KWDB needs to write kernel text when setting break points.
248     **
249     ** The right thing to do seems like KWDB modify only the pte which
250     ** has a break point on it...otherwise we might mask worse bugs.
251     */
252     				if (address >= ro_start && address < ro_end
253     							&& address != fv_addr)
254     				    pte = __mk_pte(address, PAGE_KERNEL_RO);
255     				else
256     #endif
257     				    pte = __mk_pte(address, PAGE_KERNEL);
258     
259     				if (address >= mem_max)
260     					pte_val(pte) = 0;
261     
262     				set_pte(pg_table, pte);
263     
264     				address += PAGE_SIZE;
265     			}
266     
267     			if (address >= mem_max)
268     			    break;
269     		}
270     	}
271     
272     	empty_zero_page = alloc_bootmem_pages(PAGE_SIZE);
273     	memset(empty_zero_page, 0, PAGE_SIZE);
274     }
275     
276     unsigned long gateway_pgd_offset;
277     unsigned long gateway_pgd_entry;
278     
279     static void __init gateway_init(void)
280     {
281     	unsigned long hpux_gateway_page_addr;
282     	unsigned long linux_gateway_page_addr;
283     	pgd_t *pg_dir;
284     	pmd_t *pmd_base;
285     	pmd_t *pmd;
286     	pte_t *pg_table_base;
287     	pte_t *pg_table;
288     	/* FIXME: These are 'const' in order to trick the compiler
289                into not treating them as DP-relative data. */
290     	extern void * const hpux_gateway_page;
291     	extern void * const linux_gateway_page;
292     	pte_t pte;
293     
294     	hpux_gateway_page_addr = HPUX_GATEWAY_ADDR & PAGE_MASK;
295     	linux_gateway_page_addr = LINUX_GATEWAY_ADDR & PAGE_MASK;
296     
297     	gateway_pgd_offset = hpux_gateway_page_addr >> PGDIR_SHIFT;
298     
299     	/*
300     	 * Setup Linux Gateway page.
301     	 *
302     	 * The Linux gateway page will reside in kernel space (on virtual
303     	 * page 0), so it doesn't need to be aliased into user space.
304     	 */
305     
306     	pg_dir = (pgd_t *)swapper_pg_dir;
307     
308     #if PTRS_PER_PMD == 1
309     	pmd_base = (pmd_t *)pg_dir;
310     	pmd = pmd_base +
311     		((linux_gateway_page_addr) >> PGDIR_SHIFT);
312     
313     #else
314     	pmd_base = (pmd_t *) alloc_bootmem_pages(PAGE_SIZE);
315     	pgd_val(*(pg_dir + (linux_gateway_page_addr >> PGDIR_SHIFT))) =
316     		_PAGE_TABLE | __pa(pmd_base);
317     
318     	pmd = pmd_base +
319     		((linux_gateway_page_addr & (PMD_MASK) & (PGDIR_SIZE - 1)) >>
320     								PMD_SHIFT);
321     #endif
322     
323     	pg_table_base = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
324     
325     	pmd_val(*pmd) = _PAGE_TABLE | __pa(pg_table_base);
326     
327     	pte = __mk_pte(__pa(&linux_gateway_page), PAGE_GATEWAY);
328     
329     	pg_table = pg_table_base +
330     		((linux_gateway_page_addr & (PAGE_MASK) & (PMD_SIZE - 1)) >>
331     								PAGE_SHIFT);
332     
333     	set_pte(pg_table,pte);
334     
335     	/*
336     	 * Setup HP-UX gateway page.
337     	 * This page will be aliased into each user address space.
338     	 */
339     
340     	pg_table_base = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
341     
342     	pte = __mk_pte(__pa(&hpux_gateway_page), PAGE_GATEWAY);
343     	pg_table = pg_table_base +
344     		((hpux_gateway_page_addr & (PAGE_MASK) & (PMD_SIZE - 1)) >>
345     								PAGE_SHIFT);
346     
347     	set_pte(pg_table,pte);
348     
349     
350     #if PTRS_PER_PMD == 1
351     	pmd_base = (pmd_t *)pg_table_base;
352     #else
353     	pmd_base = (pmd_t *) alloc_bootmem_pages(PAGE_SIZE);
354     	pmd = pmd_base +
355     		((hpux_gateway_page_addr & (PMD_MASK) & (PGDIR_SIZE - 1)) >>
356     								PMD_SHIFT);
357     	pmd_val(*pmd) = _PAGE_TABLE | __pa(pg_table_base);
358     #endif
359     
360     	gateway_pgd_entry = _PAGE_TABLE | __pa(pmd_base);
361     
362     	/*
363     	 * We will be aliasing the HP-UX gateway page into all HP-UX
364     	 * user spaces at the same address (not counting the space register
365     	 * value) that will be equivalently mapped as long as space register
366     	 * hashing is disabled. It will be a problem if anyone touches
367     	 * the gateway pages at its "kernel" address, since that is
368     	 * NOT equivalently mapped. We'll flush the caches at this
369     	 * point, just in case some code has touched those addresses
370     	 * previous to this, but all bets are off if they get touched
371     	 * after this point.
372     	 */
373     
374     	flush_all_caches();
375     
376     	return;
377     }
378     
379     void __init paging_init(void)
380     {
381     	pagetable_init();
382     	gateway_init();
383     
384     	{
385     		unsigned long zones_size[MAX_NR_ZONES] = { max_pfn/2, max_pfn/2, };
386     
387     		free_area_init(zones_size);
388     	}
389     }
390     
391     #define NR_SPACE_IDS	8192
392     
393     static unsigned long space_id[NR_SPACE_IDS / (8 * sizeof(long))];
394     static unsigned long space_id_index;
395     static unsigned long free_space_ids = NR_SPACE_IDS;
396     
397     /*
398      * XXX: We should probably unfold the set_bit / test_bit / clear_bit
399      * locking out of these two functions and have a single spinlock on the
400      * space_id data structures.
401      *
402      * Don't bother. This is all going to be significantly changed in the
403      * very near future.
404      */
405     
406     #define SPACEID_SHIFT (PAGE_SHIFT + (PT_NLEVELS)*(PAGE_SHIFT - PT_NLEVELS) - 32)
407     
408     unsigned long alloc_sid(void)
409     {
410     	unsigned long index;
411     
412     	if (free_space_ids == 0)
413     		BUG();
414     
415     	free_space_ids--;
416     
417     	do {
418     		index = find_next_zero_bit(space_id, NR_SPACE_IDS, space_id_index);
419     	} while(test_and_set_bit(index, space_id));
420     
421     	space_id_index = index;
422     
423     	return index << SPACEID_SHIFT;
424     }
425     
426     void free_sid(unsigned long spaceid)
427     {
428     	unsigned long index = spaceid >> SPACEID_SHIFT;
429     	if (index < 0)
430     		BUG();
431     
432     	clear_bit(index, space_id);
433     
434     	if (space_id_index > index) {
435     		space_id_index = index;
436     	}
437     	free_space_ids++;
438     }
439     
440     #ifdef CONFIG_BLK_DEV_INITRD
441     void free_initrd_mem(unsigned long start, unsigned long end)
442     {
443     #if 0
444     	for (; start < end; start += PAGE_SIZE) {
445     		ClearPageReserved(mem_map + MAP_NR(start));
446     		set_page_count(mem_map+MAP_NR(start), 1);
447     		free_page(start);
448     		totalram_pages++;
449     	}
450     	printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
451     #endif
452     }
453     #endif
454     
455     void si_meminfo(struct sysinfo *val)
456     {
457     	int i;
458     
459     	i = max_mapnr;
460     	val->totalram = totalram_pages;
461     	val->sharedram = 0;
462     	val->freeram = nr_free_pages();
463     	val->bufferram = atomic_read(&buffermem_pages);
464     #if 0
465     	while (i-- > 0)  {
466     		if (PageReserved(mem_map+i))
467     			continue;
468     		val->totalram++;
469     		if (!atomic_read(&mem_map[i].count))
470     			continue;
471     		val->sharedram += atomic_read(&mem_map[i].count) - 1;
472     	}
473     	val->totalram <<= PAGE_SHIFT;
474     	val->sharedram <<= PAGE_SHIFT;
475     #endif
476     	val->totalhigh = 0;
477     	val->freehigh = 0;
478     	return;
479     }
480