1
2
3
4
5
6
7
8
9#include <linux/pagemap.h>
10#include <linux/signal.h>
11#include <linux/sched.h>
12#include <linux/kernel.h>
13#include <linux/errno.h>
14#include <linux/string.h>
15#include <linux/types.h>
16#include <linux/ptrace.h>
17#include <linux/mman.h>
18#include <linux/mm.h>
19#include <linux/swap.h>
20#include <linux/init.h>
21#include <linux/bootmem.h>
22#include <linux/vmalloc.h>
23
24#include <asm/system.h>
25#include <asm/uaccess.h>
26#include <asm/pgtable.h>
27#include <asm/pgalloc.h>
28#include <asm/hwrpb.h>
29#include <asm/dma.h>
30#include <asm/mmu_context.h>
31#include <asm/console.h>
32#include <asm/tlb.h>
33
34DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
35
36extern void die_if_kernel(char *,struct pt_regs *,long);
37
38static struct pcb_struct original_pcb;
39
40pgd_t *
41pgd_alloc(struct mm_struct *mm)
42{
43 pgd_t *ret, *init;
44
45 ret = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
46 init = pgd_offset(&init_mm, 0UL);
47 if (ret) {
48#ifdef CONFIG_ALPHA_LARGE_VMALLOC
49 memcpy (ret + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
50 (PTRS_PER_PGD - USER_PTRS_PER_PGD - 1)*sizeof(pgd_t));
51#else
52 pgd_val(ret[PTRS_PER_PGD-2]) = pgd_val(init[PTRS_PER_PGD-2]);
53#endif
54
55
56 pgd_val(ret[PTRS_PER_PGD-1])
57 = pte_val(mk_pte(virt_to_page(ret), PAGE_KERNEL));
58 }
59 return ret;
60}
61
62pte_t *
63pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
64{
65 pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
66 return pte;
67}
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83pmd_t *
84__bad_pagetable(void)
85{
86 memset((void *) EMPTY_PGT, 0, PAGE_SIZE);
87 return (pmd_t *) EMPTY_PGT;
88}
89
90pte_t
91__bad_page(void)
92{
93 memset((void *) EMPTY_PGE, 0, PAGE_SIZE);
94 return pte_mkdirty(mk_pte(virt_to_page(EMPTY_PGE), PAGE_SHARED));
95}
96
97#ifndef CONFIG_DISCONTIGMEM
98void
99show_mem(void)
100{
101 long i,free = 0,total = 0,reserved = 0;
102 long shared = 0, cached = 0;
103
104 printk("\nMem-info:\n");
105 show_free_areas();
106 printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
107 i = max_mapnr;
108 while (i-- > 0) {
109 total++;
110 if (PageReserved(mem_map+i))
111 reserved++;
112 else if (PageSwapCache(mem_map+i))
113 cached++;
114 else if (!page_count(mem_map+i))
115 free++;
116 else
117 shared += page_count(mem_map + i) - 1;
118 }
119 printk("%ld pages of RAM\n",total);
120 printk("%ld free pages\n",free);
121 printk("%ld reserved pages\n",reserved);
122 printk("%ld pages shared\n",shared);
123 printk("%ld pages swap cached\n",cached);
124}
125#endif
126
127static inline unsigned long
128load_PCB(struct pcb_struct *pcb)
129{
130 register unsigned long sp __asm__("$30");
131 pcb->ksp = sp;
132 return __reload_thread(pcb);
133}
134
135
136
137static inline void
138switch_to_system_map(void)
139{
140 unsigned long newptbr;
141 unsigned long original_pcb_ptr;
142
143
144
145 memset(swapper_pg_dir, 0, PAGE_SIZE);
146 newptbr = ((unsigned long) swapper_pg_dir - PAGE_OFFSET) >> PAGE_SHIFT;
147 pgd_val(swapper_pg_dir[1023]) =
148 (newptbr << 32) | pgprot_val(PAGE_KERNEL);
149
150
151
152 if (hwrpb->vptb != 0xfffffffe00000000UL) {
153 wrvptptr(0xfffffffe00000000UL);
154 hwrpb->vptb = 0xfffffffe00000000UL;
155 hwrpb_update_checksum(hwrpb);
156 }
157
158
159 init_thread_info.pcb.ptbr = newptbr;
160 init_thread_info.pcb.flags = 1;
161 original_pcb_ptr = load_PCB(&init_thread_info.pcb);
162 tbia();
163
164
165
166
167
168
169
170
171 if (original_pcb_ptr < PAGE_OFFSET) {
172 original_pcb_ptr = (unsigned long)
173 phys_to_virt(original_pcb_ptr);
174 }
175 original_pcb = *(struct pcb_struct *) original_pcb_ptr;
176}
177
178int callback_init_done;
179
180void * __init
181callback_init(void * kernel_end)
182{
183 struct crb_struct * crb;
184 pgd_t *pgd;
185 pmd_t *pmd;
186 void *two_pages;
187
188
189 crb = (struct crb_struct *)((char *)hwrpb + hwrpb->crb_offset);
190
191 if (alpha_using_srm) {
192
193 if (srm_fixup(VMALLOC_START, (unsigned long)hwrpb))
194 __halt();
195
196
197 crb->dispatch_va = (struct procdesc_struct *)
198 (VMALLOC_START + (unsigned long)crb->dispatch_va
199 - crb->map[0].va);
200 crb->fixup_va = (struct procdesc_struct *)
201 (VMALLOC_START + (unsigned long)crb->fixup_va
202 - crb->map[0].va);
203 }
204
205 switch_to_system_map();
206
207
208
209
210
211
212
213
214
215
216
217 two_pages = (void *)
218 (((unsigned long)kernel_end + ~PAGE_MASK) & PAGE_MASK);
219 kernel_end = two_pages + 2*PAGE_SIZE;
220 memset(two_pages, 0, 2*PAGE_SIZE);
221
222 pgd = pgd_offset_k(VMALLOC_START);
223 pgd_set(pgd, (pmd_t *)two_pages);
224 pmd = pmd_offset(pgd, VMALLOC_START);
225 pmd_set(pmd, (pte_t *)(two_pages + PAGE_SIZE));
226
227 if (alpha_using_srm) {
228 static struct vm_struct console_remap_vm;
229 unsigned long vaddr = VMALLOC_START;
230 unsigned long i, j;
231
232
233
234 for (i = 0; i < crb->map_entries; ++i) {
235 unsigned long pfn = crb->map[i].pa >> PAGE_SHIFT;
236 crb->map[i].va = vaddr;
237 for (j = 0; j < crb->map[i].count; ++j) {
238
239
240
241 if (pmd != pmd_offset(pgd, vaddr)) {
242 memset(kernel_end, 0, PAGE_SIZE);
243 pmd = pmd_offset(pgd, vaddr);
244 pmd_set(pmd, (pte_t *)kernel_end);
245 kernel_end += PAGE_SIZE;
246 }
247 set_pte(pte_offset_kernel(pmd, vaddr),
248 pfn_pte(pfn, PAGE_KERNEL));
249 pfn++;
250 vaddr += PAGE_SIZE;
251 }
252 }
253
254
255 console_remap_vm.flags = VM_ALLOC;
256 console_remap_vm.addr = (void *) VMALLOC_START;
257 console_remap_vm.size = vaddr - VMALLOC_START;
258 vmlist = &console_remap_vm;
259 }
260
261 callback_init_done = 1;
262 return kernel_end;
263}
264
265
266#ifndef CONFIG_DISCONTIGMEM
267
268
269
270void
271paging_init(void)
272{
273 unsigned long zones_size[MAX_NR_ZONES] = {0, };
274 unsigned long dma_pfn, high_pfn;
275
276 dma_pfn = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
277 high_pfn = max_pfn = max_low_pfn;
278
279 if (dma_pfn >= high_pfn)
280 zones_size[ZONE_DMA] = high_pfn;
281 else {
282 zones_size[ZONE_DMA] = dma_pfn;
283 zones_size[ZONE_NORMAL] = high_pfn - dma_pfn;
284 }
285
286
287 free_area_init(zones_size);
288
289
290 memset((void *)ZERO_PGE, 0, PAGE_SIZE);
291}
292#endif
293
294#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM)
295void
296srm_paging_stop (void)
297{
298
299 swapper_pg_dir[1] = swapper_pg_dir[1023];
300 tbia();
301 wrvptptr(0x200000000UL);
302 hwrpb->vptb = 0x200000000UL;
303 hwrpb_update_checksum(hwrpb);
304
305
306 load_PCB(&original_pcb);
307 tbia();
308}
309#endif
310
311#ifndef CONFIG_DISCONTIGMEM
312static void __init
313printk_memory_info(void)
314{
315 unsigned long codesize, reservedpages, datasize, initsize, tmp;
316 extern int page_is_ram(unsigned long) __init;
317 extern char _text, _etext, _data, _edata;
318 extern char __init_begin, __init_end;
319
320
321 reservedpages = 0;
322 for (tmp = 0; tmp < max_low_pfn; tmp++)
323
324
325
326 if (page_is_ram(tmp) && PageReserved(mem_map+tmp))
327 reservedpages++;
328
329 codesize = (unsigned long) &_etext - (unsigned long) &_text;
330 datasize = (unsigned long) &_edata - (unsigned long) &_data;
331 initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin;
332
333 printk("Memory: %luk/%luk available (%luk kernel code, %luk reserved, %luk data, %luk init)\n",
334 (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
335 max_mapnr << (PAGE_SHIFT-10),
336 codesize >> 10,
337 reservedpages << (PAGE_SHIFT-10),
338 datasize >> 10,
339 initsize >> 10);
340}
341
342void __init
343mem_init(void)
344{
345 max_mapnr = num_physpages = max_low_pfn;
346 totalram_pages += free_all_bootmem();
347 high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
348
349 printk_memory_info();
350}
351#endif
352
353void
354free_reserved_mem(void *start, void *end)
355{
356 void *__start = start;
357 for (; __start < end; __start += PAGE_SIZE) {
358 ClearPageReserved(virt_to_page(__start));
359 init_page_count(virt_to_page(__start));
360 free_page((long)__start);
361 totalram_pages++;
362 }
363}
364
365void
366free_initmem(void)
367{
368 extern char __init_begin, __init_end;
369
370 free_reserved_mem(&__init_begin, &__init_end);
371 printk ("Freeing unused kernel memory: %ldk freed\n",
372 (&__init_end - &__init_begin) >> 10);
373}
374
375#ifdef CONFIG_BLK_DEV_INITRD
376void
377free_initrd_mem(unsigned long start, unsigned long end)
378{
379 free_reserved_mem((void *)start, (void *)end);
380 printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
381}
382#endif
383