1
2
3
4
5
6
7
8#include <linux/config.h>
9#include <linux/kernel.h>
10#include <linux/sched.h>
11#include <linux/string.h>
12#include <linux/init.h>
13#include <linux/bootmem.h>
14#include <linux/mm.h>
15#include <linux/hugetlb.h>
16#include <linux/slab.h>
17#include <linux/initrd.h>
18#include <linux/swap.h>
19#include <linux/pagemap.h>
20#include <linux/fs.h>
21#include <linux/seq_file.h>
22
23#include <asm/head.h>
24#include <asm/system.h>
25#include <asm/page.h>
26#include <asm/pgalloc.h>
27#include <asm/pgtable.h>
28#include <asm/oplib.h>
29#include <asm/iommu.h>
30#include <asm/io.h>
31#include <asm/uaccess.h>
32#include <asm/mmu_context.h>
33#include <asm/tlbflush.h>
34#include <asm/dma.h>
35#include <asm/starfire.h>
36#include <asm/tlb.h>
37#include <asm/spitfire.h>
38#include <asm/sections.h>
39
40extern void device_scan(void);
41
42struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS];
43
44unsigned long *sparc64_valid_addr_bitmap;
45
46
47unsigned long phys_base;
48unsigned long kern_base;
49unsigned long kern_size;
50unsigned long pfn_base;
51
52
53
54
55
56
57
58
59static unsigned long bootmap_base;
60
61
62DEFINE_SPINLOCK(ctx_alloc_lock);
63unsigned long tlb_context_cache = CTX_FIRST_VERSION - 1;
64#define CTX_BMAP_SLOTS (1UL << (CTX_VERSION_SHIFT - 6))
65unsigned long mmu_context_bmap[CTX_BMAP_SLOTS];
66
67
68extern char _start[], _end[];
69
70
71extern unsigned long sparc_ramdisk_image64;
72extern unsigned int sparc_ramdisk_image;
73extern unsigned int sparc_ramdisk_size;
74
75struct page *mem_map_zero;
76
77int bigkernel = 0;
78
79
80#define PGT_CACHE_LOW 25
81#define PGT_CACHE_HIGH 50
82
83void check_pgt_cache(void)
84{
85 preempt_disable();
86 if (pgtable_cache_size > PGT_CACHE_HIGH) {
87 do {
88#ifdef CONFIG_SMP
89 if (pgd_quicklist)
90 free_pgd_slow(get_pgd_fast());
91#endif
92 if (pte_quicklist[0])
93 free_pte_slow(pte_alloc_one_fast(NULL, 0));
94 if (pte_quicklist[1])
95 free_pte_slow(pte_alloc_one_fast(NULL, 1 << (PAGE_SHIFT + 10)));
96 } while (pgtable_cache_size > PGT_CACHE_LOW);
97 }
98#ifndef CONFIG_SMP
99 if (pgd_cache_size > PGT_CACHE_HIGH / 4) {
100 struct page *page, *page2;
101 for (page2 = NULL, page = (struct page *)pgd_quicklist; page;) {
102 if ((unsigned long)page->lru.prev == 3) {
103 if (page2)
104 page2->lru.next = page->lru.next;
105 else
106 pgd_quicklist = (void *) page->lru.next;
107 pgd_cache_size -= 2;
108 __free_page(page);
109 if (page2)
110 page = (struct page *)page2->lru.next;
111 else
112 page = (struct page *)pgd_quicklist;
113 if (pgd_cache_size <= PGT_CACHE_LOW / 4)
114 break;
115 continue;
116 }
117 page2 = page;
118 page = (struct page *)page->lru.next;
119 }
120 }
121#endif
122 preempt_enable();
123}
124
125#ifdef CONFIG_DEBUG_DCFLUSH
126atomic_t dcpage_flushes = ATOMIC_INIT(0);
127#ifdef CONFIG_SMP
128atomic_t dcpage_flushes_xcall = ATOMIC_INIT(0);
129#endif
130#endif
131
132__inline__ void flush_dcache_page_impl(struct page *page)
133{
134#ifdef CONFIG_DEBUG_DCFLUSH
135 atomic_inc(&dcpage_flushes);
136#endif
137
138#if (L1DCACHE_SIZE > PAGE_SIZE)
139 __flush_dcache_page(page_address(page),
140 ((tlb_type == spitfire) &&
141 page_mapping(page) != NULL));
142#else
143 if (page_mapping(page) != NULL &&
144 tlb_type == spitfire)
145 __flush_icache_page(__pa(page_address(page)));
146#endif
147}
148
149#define PG_dcache_dirty PG_arch_1
150
151#define dcache_dirty_cpu(page) \
152 (((page)->flags >> 24) & (NR_CPUS - 1UL))
153
154static __inline__ void set_dcache_dirty(struct page *page, int this_cpu)
155{
156 unsigned long mask = this_cpu;
157 unsigned long non_cpu_bits = ~((NR_CPUS - 1UL) << 24UL);
158 mask = (mask << 24) | (1UL << PG_dcache_dirty);
159 __asm__ __volatile__("1:\n\t"
160 "ldx [%2], %%g7\n\t"
161 "and %%g7, %1, %%g5\n\t"
162 "or %%g5, %0, %%g5\n\t"
163 "casx [%2], %%g7, %%g5\n\t"
164 "cmp %%g7, %%g5\n\t"
165 "bne,pn %%xcc, 1b\n\t"
166 " membar #StoreLoad | #StoreStore"
167 :
168 : "r" (mask), "r" (non_cpu_bits), "r" (&page->flags)
169 : "g5", "g7");
170}
171
172static __inline__ void clear_dcache_dirty_cpu(struct page *page, unsigned long cpu)
173{
174 unsigned long mask = (1UL << PG_dcache_dirty);
175
176 __asm__ __volatile__("! test_and_clear_dcache_dirty\n"
177 "1:\n\t"
178 "ldx [%2], %%g7\n\t"
179 "srlx %%g7, 24, %%g5\n\t"
180 "and %%g5, %3, %%g5\n\t"
181 "cmp %%g5, %0\n\t"
182 "bne,pn %%icc, 2f\n\t"
183 " andn %%g7, %1, %%g5\n\t"
184 "casx [%2], %%g7, %%g5\n\t"
185 "cmp %%g7, %%g5\n\t"
186 "bne,pn %%xcc, 1b\n\t"
187 " membar #StoreLoad | #StoreStore\n"
188 "2:"
189 :
190 : "r" (cpu), "r" (mask), "r" (&page->flags),
191 "i" (NR_CPUS - 1UL)
192 : "g5", "g7");
193}
194
195extern void __update_mmu_cache(unsigned long mmu_context_hw, unsigned long address, pte_t pte, int code);
196
197void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte)
198{
199 struct page *page;
200 unsigned long pfn;
201 unsigned long pg_flags;
202
203 pfn = pte_pfn(pte);
204 if (pfn_valid(pfn) &&
205 (page = pfn_to_page(pfn), page_mapping(page)) &&
206 ((pg_flags = page->flags) & (1UL << PG_dcache_dirty))) {
207 int cpu = ((pg_flags >> 24) & (NR_CPUS - 1UL));
208 int this_cpu = get_cpu();
209
210
211
212
213 if (cpu == this_cpu)
214 flush_dcache_page_impl(page);
215 else
216 smp_flush_dcache_page_impl(page, cpu);
217
218 clear_dcache_dirty_cpu(page, cpu);
219
220 put_cpu();
221 }
222 if (get_thread_fault_code())
223 __update_mmu_cache(vma->vm_mm->context & TAG_CONTEXT_BITS,
224 address, pte, get_thread_fault_code());
225}
226
227void flush_dcache_page(struct page *page)
228{
229 struct address_space *mapping = page_mapping(page);
230 int dirty = test_bit(PG_dcache_dirty, &page->flags);
231 int dirty_cpu = dcache_dirty_cpu(page);
232 int this_cpu = get_cpu();
233
234 if (mapping && !mapping_mapped(mapping)) {
235 if (dirty) {
236 if (dirty_cpu == this_cpu)
237 goto out;
238 smp_flush_dcache_page_impl(page, dirty_cpu);
239 }
240 set_dcache_dirty(page, this_cpu);
241 } else {
242
243
244
245
246
247 flush_dcache_page_impl(page);
248 }
249
250out:
251 put_cpu();
252}
253
254void flush_icache_range(unsigned long start, unsigned long end)
255{
256
257 if (tlb_type == spitfire) {
258 unsigned long kaddr;
259
260 for (kaddr = start; kaddr < end; kaddr += PAGE_SIZE)
261 __flush_icache_page(__get_phys(kaddr));
262 }
263}
264
265unsigned long page_to_pfn(struct page *page)
266{
267 return (unsigned long) ((page - mem_map) + pfn_base);
268}
269
270struct page *pfn_to_page(unsigned long pfn)
271{
272 return (mem_map + (pfn - pfn_base));
273}
274
275void show_mem(void)
276{
277 printk("Mem-info:\n");
278 show_free_areas();
279 printk("Free swap: %6ldkB\n",
280 nr_swap_pages << (PAGE_SHIFT-10));
281 printk("%ld pages of RAM\n", num_physpages);
282 printk("%d free pages\n", nr_free_pages());
283 printk("%d pages in page table cache\n",pgtable_cache_size);
284#ifndef CONFIG_SMP
285 printk("%d entries in page dir cache\n",pgd_cache_size);
286#endif
287}
288
289void mmu_info(struct seq_file *m)
290{
291 if (tlb_type == cheetah)
292 seq_printf(m, "MMU Type\t: Cheetah\n");
293 else if (tlb_type == cheetah_plus)
294 seq_printf(m, "MMU Type\t: Cheetah+\n");
295 else if (tlb_type == spitfire)
296 seq_printf(m, "MMU Type\t: Spitfire\n");
297 else
298 seq_printf(m, "MMU Type\t: ???\n");
299
300#ifdef CONFIG_DEBUG_DCFLUSH
301 seq_printf(m, "DCPageFlushes\t: %d\n",
302 atomic_read(&dcpage_flushes));
303#ifdef CONFIG_SMP
304 seq_printf(m, "DCPageFlushesXC\t: %d\n",
305 atomic_read(&dcpage_flushes_xcall));
306#endif
307#endif
308}
309
310struct linux_prom_translation {
311 unsigned long virt;
312 unsigned long size;
313 unsigned long data;
314};
315
316extern unsigned long prom_boot_page;
317extern void prom_remap(unsigned long physpage, unsigned long virtpage, int mmu_ihandle);
318extern int prom_get_mmu_ihandle(void);
319extern void register_prom_callbacks(void);
320
321
322unsigned long kern_locked_tte_data;
323
324void __init early_pgtable_allocfail(char *type)
325{
326 prom_printf("inherit_prom_mappings: Cannot alloc kernel %s.\n", type);
327 prom_halt();
328}
329
330#define BASE_PAGE_SIZE 8192
331static pmd_t *prompmd;
332
333
334
335
336
337unsigned long prom_virt_to_phys(unsigned long promva, int *error)
338{
339 pmd_t *pmdp = prompmd + ((promva >> 23) & 0x7ff);
340 pte_t *ptep;
341 unsigned long base;
342
343 if (pmd_none(*pmdp)) {
344 if (error)
345 *error = 1;
346 return(0);
347 }
348 ptep = (pte_t *)__pmd_page(*pmdp) + ((promva >> 13) & 0x3ff);
349 if (!pte_present(*ptep)) {
350 if (error)
351 *error = 1;
352 return(0);
353 }
354 if (error) {
355 *error = 0;
356 return(pte_val(*ptep));
357 }
358 base = pte_val(*ptep) & _PAGE_PADDR;
359 return(base + (promva & (BASE_PAGE_SIZE - 1)));
360}
361
362static void inherit_prom_mappings(void)
363{
364 struct linux_prom_translation *trans;
365 unsigned long phys_page, tte_vaddr, tte_data;
366 void (*remap_func)(unsigned long, unsigned long, int);
367 pmd_t *pmdp;
368 pte_t *ptep;
369 int node, n, i, tsz;
370 extern unsigned int obp_iaddr_patch[2], obp_daddr_patch[2];
371
372 node = prom_finddevice("/virtual-memory");
373 n = prom_getproplen(node, "translations");
374 if (n == 0 || n == -1) {
375 prom_printf("Couldn't get translation property\n");
376 prom_halt();
377 }
378 n += 5 * sizeof(struct linux_prom_translation);
379 for (tsz = 1; tsz < n; tsz <<= 1)
380 ;
381 trans = __alloc_bootmem(tsz, SMP_CACHE_BYTES, bootmap_base);
382 if (trans == NULL) {
383 prom_printf("inherit_prom_mappings: Cannot alloc translations.\n");
384 prom_halt();
385 }
386 memset(trans, 0, tsz);
387
388 if ((n = prom_getproperty(node, "translations", (char *)trans, tsz)) == -1) {
389 prom_printf("Couldn't get translation property\n");
390 prom_halt();
391 }
392 n = n / sizeof(*trans);
393
394
395
396
397
398
399
400#define OBP_PMD_SIZE 2048
401 prompmd = __alloc_bootmem(OBP_PMD_SIZE, OBP_PMD_SIZE, bootmap_base);
402 if (prompmd == NULL)
403 early_pgtable_allocfail("pmd");
404 memset(prompmd, 0, OBP_PMD_SIZE);
405 for (i = 0; i < n; i++) {
406 unsigned long vaddr;
407
408 if (trans[i].virt >= LOW_OBP_ADDRESS && trans[i].virt < HI_OBP_ADDRESS) {
409 for (vaddr = trans[i].virt;
410 ((vaddr < trans[i].virt + trans[i].size) &&
411 (vaddr < HI_OBP_ADDRESS));
412 vaddr += BASE_PAGE_SIZE) {
413 unsigned long val;
414
415 pmdp = prompmd + ((vaddr >> 23) & 0x7ff);
416 if (pmd_none(*pmdp)) {
417 ptep = __alloc_bootmem(BASE_PAGE_SIZE,
418 BASE_PAGE_SIZE,
419 bootmap_base);
420 if (ptep == NULL)
421 early_pgtable_allocfail("pte");
422 memset(ptep, 0, BASE_PAGE_SIZE);
423 pmd_set(pmdp, ptep);
424 }
425 ptep = (pte_t *)__pmd_page(*pmdp) +
426 ((vaddr >> 13) & 0x3ff);
427
428 val = trans[i].data;
429
430
431 if (tlb_type == spitfire)
432 val &= ~0x0003fe0000000000UL;
433
434 set_pte (ptep, __pte(val | _PAGE_MODIFIED));
435 trans[i].data += BASE_PAGE_SIZE;
436 }
437 }
438 }
439 phys_page = __pa(prompmd);
440 obp_iaddr_patch[0] |= (phys_page >> 10);
441 obp_iaddr_patch[1] |= (phys_page & 0x3ff);
442 flushi((long)&obp_iaddr_patch[0]);
443 obp_daddr_patch[0] |= (phys_page >> 10);
444 obp_daddr_patch[1] |= (phys_page & 0x3ff);
445 flushi((long)&obp_daddr_patch[0]);
446
447
448 prom_printf("Remapping the kernel... ");
449
450
451 __asm__ __volatile__("stxa %0, [%1] %2\n\t"
452 "flush %%g6"
453 :
454 : "r" (0),
455 "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
456
457 switch (tlb_type) {
458 default:
459 case spitfire:
460 phys_page = spitfire_get_dtlb_data(sparc64_highest_locked_tlbent());
461 break;
462
463 case cheetah:
464 case cheetah_plus:
465 phys_page = cheetah_get_litlb_data(sparc64_highest_locked_tlbent());
466 break;
467 };
468
469 phys_page &= _PAGE_PADDR;
470 phys_page += ((unsigned long)&prom_boot_page -
471 (unsigned long)KERNBASE);
472
473 if (tlb_type == spitfire) {
474
475 __asm__ __volatile__(
476 "stxa %%g0, [%2] %3\n\t"
477 "stxa %0, [%1] %4\n\t"
478 "membar #Sync\n\t"
479 "flush %%g6\n\t"
480 "stxa %%g0, [%2] %5\n\t"
481 "stxa %0, [%1] %6\n\t"
482 "membar #Sync\n\t"
483 "flush %%g6"
484 : : "r" (phys_page | _PAGE_VALID | _PAGE_SZ8K | _PAGE_CP |
485 _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W),
486 "r" (59 << 3), "r" (TLB_TAG_ACCESS),
487 "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS),
488 "i" (ASI_IMMU), "i" (ASI_ITLB_DATA_ACCESS)
489 : "memory");
490 } else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
491
492 __asm__ __volatile__(
493 "stxa %%g0, [%2] %3\n\t"
494 "stxa %0, [%1] %4\n\t"
495 "membar #Sync\n\t"
496 "flush %%g6\n\t"
497 "stxa %%g0, [%2] %5\n\t"
498 "stxa %0, [%1] %6\n\t"
499 "membar #Sync\n\t"
500 "flush %%g6"
501 : : "r" (phys_page | _PAGE_VALID | _PAGE_SZ8K | _PAGE_CP |
502 _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W),
503 "r" ((0 << 16) | (11 << 3)), "r" (TLB_TAG_ACCESS),
504 "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS),
505 "i" (ASI_IMMU), "i" (ASI_ITLB_DATA_ACCESS)
506 : "memory");
507 } else {
508
509 BUG();
510 }
511
512 tte_vaddr = (unsigned long) KERNBASE;
513
514
515 __asm__ __volatile__("stxa %0, [%1] %2\n\t"
516 "flush %%g6"
517 :
518 : "r" (0),
519 "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
520
521 if (tlb_type == spitfire)
522 tte_data = spitfire_get_dtlb_data(sparc64_highest_locked_tlbent());
523 else
524 tte_data = cheetah_get_ldtlb_data(sparc64_highest_locked_tlbent());
525
526 kern_locked_tte_data = tte_data;
527
528 remap_func = (void *) ((unsigned long) &prom_remap -
529 (unsigned long) &prom_boot_page);
530
531
532
533 __asm__ __volatile__("stxa %0, [%1] %2\n\t"
534 "flush %%g6"
535 :
536 : "r" (0),
537 "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
538
539 remap_func((tlb_type == spitfire ?
540 (spitfire_get_dtlb_data(sparc64_highest_locked_tlbent()) & _PAGE_PADDR) :
541 (cheetah_get_litlb_data(sparc64_highest_locked_tlbent()) & _PAGE_PADDR)),
542 (unsigned long) KERNBASE,
543 prom_get_mmu_ihandle());
544
545 if (bigkernel)
546 remap_func(((tte_data + 0x400000) & _PAGE_PADDR),
547 (unsigned long) KERNBASE + 0x400000, prom_get_mmu_ihandle());
548
549
550 spitfire_flush_dtlb_nucleus_page(0x0);
551 spitfire_flush_itlb_nucleus_page(0x0);
552
553
554 prom_dtlb_load(sparc64_highest_locked_tlbent(), tte_data, tte_vaddr);
555 prom_itlb_load(sparc64_highest_locked_tlbent(), tte_data, tte_vaddr);
556 if (bigkernel) {
557 prom_dtlb_load(sparc64_highest_locked_tlbent()-1, tte_data + 0x400000,
558 tte_vaddr + 0x400000);
559 prom_itlb_load(sparc64_highest_locked_tlbent()-1, tte_data + 0x400000,
560 tte_vaddr + 0x400000);
561 }
562
563
564 if ((n = prom_getproperty(node, "translations", (char *)trans, tsz)) == -1) {
565 prom_printf("Couldn't get translation property\n");
566 prom_halt();
567 }
568 n = n / sizeof(*trans);
569
570 for (i = 0; i < n; i++) {
571 unsigned long vaddr = trans[i].virt;
572 unsigned long size = trans[i].size;
573
574 if (vaddr < 0xf0000000UL) {
575 unsigned long avoid_start = (unsigned long) KERNBASE;
576 unsigned long avoid_end = avoid_start + (4 * 1024 * 1024);
577
578 if (bigkernel)
579 avoid_end += (4 * 1024 * 1024);
580 if (vaddr < avoid_start) {
581 unsigned long top = vaddr + size;
582
583 if (top > avoid_start)
584 top = avoid_start;
585 prom_unmap(top - vaddr, vaddr);
586 }
587 if ((vaddr + size) > avoid_end) {
588 unsigned long bottom = vaddr;
589
590 if (bottom < avoid_end)
591 bottom = avoid_end;
592 prom_unmap((vaddr + size) - bottom, bottom);
593 }
594 }
595 }
596
597 prom_printf("done.\n");
598
599 register_prom_callbacks();
600}
601
602
603
604
605
606
607
608static void __flush_nucleus_vptes(void)
609{
610 unsigned long prom_reserved_base = 0xfffffffc00000000UL;
611 int i;
612
613
614 if (tlb_type == spitfire) {
615 for (i = 0; i < 63; i++) {
616 unsigned long tag;
617
618
619 __asm__ __volatile__("stxa %0, [%1] %2\n\t"
620 "flush %%g6"
621 :
622 : "r" (0),
623 "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
624
625 tag = spitfire_get_dtlb_tag(i);
626 if (((tag & ~(PAGE_MASK)) == 0) &&
627 ((tag & (PAGE_MASK)) >= prom_reserved_base)) {
628 __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
629 "membar #Sync"
630 :
631 : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU));
632 spitfire_put_dtlb_data(i, 0x0UL);
633 }
634 }
635 } else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
636 for (i = 0; i < 512; i++) {
637 unsigned long tag = cheetah_get_dtlb_tag(i, 2);
638
639 if ((tag & ~PAGE_MASK) == 0 &&
640 (tag & PAGE_MASK) >= prom_reserved_base) {
641 __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
642 "membar #Sync"
643 :
644 : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU));
645 cheetah_put_dtlb_data(i, 0x0UL, 2);
646 }
647
648 if (tlb_type != cheetah_plus)
649 continue;
650
651 tag = cheetah_get_dtlb_tag(i, 3);
652
653 if ((tag & ~PAGE_MASK) == 0 &&
654 (tag & PAGE_MASK) >= prom_reserved_base) {
655 __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
656 "membar #Sync"
657 :
658 : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU));
659 cheetah_put_dtlb_data(i, 0x0UL, 3);
660 }
661 }
662 } else {
663
664 BUG();
665 }
666}
667
668static int prom_ditlb_set;
669struct prom_tlb_entry {
670 int tlb_ent;
671 unsigned long tlb_tag;
672 unsigned long tlb_data;
673};
674struct prom_tlb_entry prom_itlb[16], prom_dtlb[16];
675
676void prom_world(int enter)
677{
678 unsigned long pstate;
679 int i;
680
681 if (!enter)
682 set_fs((mm_segment_t) { get_thread_current_ds() });
683
684 if (!prom_ditlb_set)
685 return;
686
687
688 __asm__ __volatile__("flushw\n\t"
689 "rdpr %%pstate, %0\n\t"
690 "wrpr %0, %1, %%pstate"
691 : "=r" (pstate)
692 : "i" (PSTATE_IE));
693
694 if (enter) {
695
696 __flush_nucleus_vptes();
697
698
699 for (i = 0; i < 16; i++) {
700 if (prom_dtlb[i].tlb_ent != -1) {
701 __asm__ __volatile__("stxa %0, [%1] %2\n\t"
702 "membar #Sync"
703 : : "r" (prom_dtlb[i].tlb_tag), "r" (TLB_TAG_ACCESS),
704 "i" (ASI_DMMU));
705 if (tlb_type == spitfire)
706 spitfire_put_dtlb_data(prom_dtlb[i].tlb_ent,
707 prom_dtlb[i].tlb_data);
708 else if (tlb_type == cheetah || tlb_type == cheetah_plus)
709 cheetah_put_ldtlb_data(prom_dtlb[i].tlb_ent,
710 prom_dtlb[i].tlb_data);
711 }
712 if (prom_itlb[i].tlb_ent != -1) {
713 __asm__ __volatile__("stxa %0, [%1] %2\n\t"
714 "membar #Sync"
715 : : "r" (prom_itlb[i].tlb_tag),
716 "r" (TLB_TAG_ACCESS),
717 "i" (ASI_IMMU));
718 if (tlb_type == spitfire)
719 spitfire_put_itlb_data(prom_itlb[i].tlb_ent,
720 prom_itlb[i].tlb_data);
721 else if (tlb_type == cheetah || tlb_type == cheetah_plus)
722 cheetah_put_litlb_data(prom_itlb[i].tlb_ent,
723 prom_itlb[i].tlb_data);
724 }
725 }
726 } else {
727 for (i = 0; i < 16; i++) {
728 if (prom_dtlb[i].tlb_ent != -1) {
729 __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
730 "membar #Sync"
731 : : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU));
732 if (tlb_type == spitfire)
733 spitfire_put_dtlb_data(prom_dtlb[i].tlb_ent, 0x0UL);
734 else
735 cheetah_put_ldtlb_data(prom_dtlb[i].tlb_ent, 0x0UL);
736 }
737 if (prom_itlb[i].tlb_ent != -1) {
738 __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
739 "membar #Sync"
740 : : "r" (TLB_TAG_ACCESS),
741 "i" (ASI_IMMU));
742 if (tlb_type == spitfire)
743 spitfire_put_itlb_data(prom_itlb[i].tlb_ent, 0x0UL);
744 else
745 cheetah_put_litlb_data(prom_itlb[i].tlb_ent, 0x0UL);
746 }
747 }
748 }
749 __asm__ __volatile__("wrpr %0, 0, %%pstate"
750 : : "r" (pstate));
751}
752
753void inherit_locked_prom_mappings(int save_p)
754{
755 int i;
756 int dtlb_seen = 0;
757 int itlb_seen = 0;
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773 if (save_p) {
774 for (i = 0; i < 16; i++) {
775 prom_itlb[i].tlb_ent = -1;
776 prom_dtlb[i].tlb_ent = -1;
777 }
778 }
779 if (tlb_type == spitfire) {
780 int high = SPITFIRE_HIGHEST_LOCKED_TLBENT - bigkernel;
781 for (i = 0; i < high; i++) {
782 unsigned long data;
783
784
785 __asm__ __volatile__("stxa %0, [%1] %2\n\t"
786 "flush %%g6"
787 :
788 : "r" (0),
789 "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
790
791 data = spitfire_get_dtlb_data(i);
792 if ((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) {
793 unsigned long tag;
794
795
796 __asm__ __volatile__("stxa %0, [%1] %2\n\t"
797 "flush %%g6"
798 :
799 : "r" (0),
800 "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
801
802 tag = spitfire_get_dtlb_tag(i);
803 if (save_p) {
804 prom_dtlb[dtlb_seen].tlb_ent = i;
805 prom_dtlb[dtlb_seen].tlb_tag = tag;
806 prom_dtlb[dtlb_seen].tlb_data = data;
807 }
808 __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
809 "membar #Sync"
810 : : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU));
811 spitfire_put_dtlb_data(i, 0x0UL);
812
813 dtlb_seen++;
814 if (dtlb_seen > 15)
815 break;
816 }
817 }
818
819 for (i = 0; i < high; i++) {
820 unsigned long data;
821
822
823 __asm__ __volatile__("stxa %0, [%1] %2\n\t"
824 "flush %%g6"
825 :
826 : "r" (0),
827 "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
828
829 data = spitfire_get_itlb_data(i);
830 if ((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) {
831 unsigned long tag;
832
833
834 __asm__ __volatile__("stxa %0, [%1] %2\n\t"
835 "flush %%g6"
836 :
837 : "r" (0),
838 "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
839
840 tag = spitfire_get_itlb_tag(i);
841 if (save_p) {
842 prom_itlb[itlb_seen].tlb_ent = i;
843 prom_itlb[itlb_seen].tlb_tag = tag;
844 prom_itlb[itlb_seen].tlb_data = data;
845 }
846 __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
847 "membar #Sync"
848 : : "r" (TLB_TAG_ACCESS), "i" (ASI_IMMU));
849 spitfire_put_itlb_data(i, 0x0UL);
850
851 itlb_seen++;
852 if (itlb_seen > 15)
853 break;
854 }
855 }
856 } else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
857 int high = CHEETAH_HIGHEST_LOCKED_TLBENT - bigkernel;
858
859 for (i = 0; i < high; i++) {
860 unsigned long data;
861
862 data = cheetah_get_ldtlb_data(i);
863 if ((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) {
864 unsigned long tag;
865
866 tag = cheetah_get_ldtlb_tag(i);
867 if (save_p) {
868 prom_dtlb[dtlb_seen].tlb_ent = i;
869 prom_dtlb[dtlb_seen].tlb_tag = tag;
870 prom_dtlb[dtlb_seen].tlb_data = data;
871 }
872 __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
873 "membar #Sync"
874 : : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU));
875 cheetah_put_ldtlb_data(i, 0x0UL);
876
877 dtlb_seen++;
878 if (dtlb_seen > 15)
879 break;
880 }
881 }
882
883 for (i = 0; i < high; i++) {
884 unsigned long data;
885
886 data = cheetah_get_litlb_data(i);
887 if ((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) {
888 unsigned long tag;
889
890 tag = cheetah_get_litlb_tag(i);
891 if (save_p) {
892 prom_itlb[itlb_seen].tlb_ent = i;
893 prom_itlb[itlb_seen].tlb_tag = tag;
894 prom_itlb[itlb_seen].tlb_data = data;
895 }
896 __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
897 "membar #Sync"
898 : : "r" (TLB_TAG_ACCESS), "i" (ASI_IMMU));
899 cheetah_put_litlb_data(i, 0x0UL);
900
901 itlb_seen++;
902 if (itlb_seen > 15)
903 break;
904 }
905 }
906 } else {
907
908 BUG();
909 }
910 if (save_p)
911 prom_ditlb_set = 1;
912}
913
914
915void prom_reload_locked(void)
916{
917 int i;
918
919 for (i = 0; i < 16; i++) {
920 if (prom_dtlb[i].tlb_ent != -1) {
921 __asm__ __volatile__("stxa %0, [%1] %2\n\t"
922 "membar #Sync"
923 : : "r" (prom_dtlb[i].tlb_tag), "r" (TLB_TAG_ACCESS),
924 "i" (ASI_DMMU));
925 if (tlb_type == spitfire)
926 spitfire_put_dtlb_data(prom_dtlb[i].tlb_ent,
927 prom_dtlb[i].tlb_data);
928 else if (tlb_type == cheetah || tlb_type == cheetah_plus)
929 cheetah_put_ldtlb_data(prom_dtlb[i].tlb_ent,
930 prom_dtlb[i].tlb_data);
931 }
932
933 if (prom_itlb[i].tlb_ent != -1) {
934 __asm__ __volatile__("stxa %0, [%1] %2\n\t"
935 "membar #Sync"
936 : : "r" (prom_itlb[i].tlb_tag),
937 "r" (TLB_TAG_ACCESS),
938 "i" (ASI_IMMU));
939 if (tlb_type == spitfire)
940 spitfire_put_itlb_data(prom_itlb[i].tlb_ent,
941 prom_itlb[i].tlb_data);
942 else
943 cheetah_put_litlb_data(prom_itlb[i].tlb_ent,
944 prom_itlb[i].tlb_data);
945 }
946 }
947}
948
949void __flush_dcache_range(unsigned long start, unsigned long end)
950{
951 unsigned long va;
952
953 if (tlb_type == spitfire) {
954 int n = 0;
955
956 for (va = start; va < end; va += 32) {
957 spitfire_put_dcache_tag(va & 0x3fe0, 0x0);
958 if (++n >= 512)
959 break;
960 }
961 } else {
962 start = __pa(start);
963 end = __pa(end);
964 for (va = start; va < end; va += 32)
965 __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
966 "membar #Sync"
967 :
968 : "r" (va),
969 "i" (ASI_DCACHE_INVALIDATE));
970 }
971}
972
973
974void __flush_tlb_all(void)
975{
976 unsigned long pstate;
977 int i;
978
979 __asm__ __volatile__("flushw\n\t"
980 "rdpr %%pstate, %0\n\t"
981 "wrpr %0, %1, %%pstate"
982 : "=r" (pstate)
983 : "i" (PSTATE_IE));
984 if (tlb_type == spitfire) {
985 for (i = 0; i < 64; i++) {
986
987 __asm__ __volatile__("stxa %0, [%1] %2\n\t"
988 "flush %%g6"
989 :
990 : "r" (0),
991 "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
992
993 if (!(spitfire_get_dtlb_data(i) & _PAGE_L)) {
994 __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
995 "membar #Sync"
996 :
997 : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU));
998 spitfire_put_dtlb_data(i, 0x0UL);
999 }
1000
1001
1002 __asm__ __volatile__("stxa %0, [%1] %2\n\t"
1003 "flush %%g6"
1004 :
1005 : "r" (0),
1006 "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
1007
1008 if (!(spitfire_get_itlb_data(i) & _PAGE_L)) {
1009 __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
1010 "membar #Sync"
1011 :
1012 : "r" (TLB_TAG_ACCESS), "i" (ASI_IMMU));
1013 spitfire_put_itlb_data(i, 0x0UL);
1014 }
1015 }
1016 } else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
1017 cheetah_flush_dtlb_all();
1018 cheetah_flush_itlb_all();
1019 }
1020 __asm__ __volatile__("wrpr %0, 0, %%pstate"
1021 : : "r" (pstate));
1022}
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032void get_new_mmu_context(struct mm_struct *mm)
1033{
1034 unsigned long ctx, new_ctx;
1035
1036 spin_lock(&ctx_alloc_lock);
1037 ctx = CTX_HWBITS(tlb_context_cache + 1);
1038 new_ctx = find_next_zero_bit(mmu_context_bmap, 1UL << CTX_VERSION_SHIFT, ctx);
1039 if (new_ctx >= (1UL << CTX_VERSION_SHIFT)) {
1040 new_ctx = find_next_zero_bit(mmu_context_bmap, ctx, 1);
1041 if (new_ctx >= ctx) {
1042 int i;
1043 new_ctx = (tlb_context_cache & CTX_VERSION_MASK) +
1044 CTX_FIRST_VERSION;
1045 if (new_ctx == 1)
1046 new_ctx = CTX_FIRST_VERSION;
1047
1048
1049
1050
1051 mmu_context_bmap[0] = 3;
1052 mmu_context_bmap[1] = 0;
1053 mmu_context_bmap[2] = 0;
1054 mmu_context_bmap[3] = 0;
1055 for (i = 4; i < CTX_BMAP_SLOTS; i += 4) {
1056 mmu_context_bmap[i + 0] = 0;
1057 mmu_context_bmap[i + 1] = 0;
1058 mmu_context_bmap[i + 2] = 0;
1059 mmu_context_bmap[i + 3] = 0;
1060 }
1061 goto out;
1062 }
1063 }
1064 mmu_context_bmap[new_ctx>>6] |= (1UL << (new_ctx & 63));
1065 new_ctx |= (tlb_context_cache & CTX_VERSION_MASK);
1066out:
1067 tlb_context_cache = new_ctx;
1068 spin_unlock(&ctx_alloc_lock);
1069
1070 mm->context = new_ctx;
1071}
1072
1073#ifndef CONFIG_SMP
1074struct pgtable_cache_struct pgt_quicklists;
1075#endif
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089#if (L1DCACHE_SIZE > PAGE_SIZE)
1090#define DC_ALIAS_SHIFT 1
1091#else
1092#define DC_ALIAS_SHIFT 0
1093#endif
1094pte_t *__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
1095{
1096 struct page *page;
1097 unsigned long color;
1098
1099 {
1100 pte_t *ptep = pte_alloc_one_fast(mm, address);
1101
1102 if (ptep)
1103 return ptep;
1104 }
1105
1106 color = VPTE_COLOR(address);
1107 page = alloc_pages(GFP_KERNEL|__GFP_REPEAT, DC_ALIAS_SHIFT);
1108 if (page) {
1109 unsigned long *to_free;
1110 unsigned long paddr;
1111 pte_t *pte;
1112
1113#if (L1DCACHE_SIZE > PAGE_SIZE)
1114 set_page_count(page, 1);
1115 ClearPageCompound(page);
1116
1117 set_page_count((page + 1), 1);
1118 ClearPageCompound(page + 1);
1119#endif
1120 paddr = (unsigned long) page_address(page);
1121 memset((char *)paddr, 0, (PAGE_SIZE << DC_ALIAS_SHIFT));
1122
1123 if (!color) {
1124 pte = (pte_t *) paddr;
1125 to_free = (unsigned long *) (paddr + PAGE_SIZE);
1126 } else {
1127 pte = (pte_t *) (paddr + PAGE_SIZE);
1128 to_free = (unsigned long *) paddr;
1129 }
1130
1131#if (L1DCACHE_SIZE > PAGE_SIZE)
1132
1133 preempt_disable();
1134 *to_free = (unsigned long) pte_quicklist[color ^ 0x1];
1135 pte_quicklist[color ^ 0x1] = to_free;
1136 pgtable_cache_size++;
1137 preempt_enable();
1138#endif
1139
1140 return pte;
1141 }
1142 return NULL;
1143}
1144
1145void sparc_ultra_dump_itlb(void)
1146{
1147 int slot;
1148
1149 if (tlb_type == spitfire) {
1150 printk ("Contents of itlb: ");
1151 for (slot = 0; slot < 14; slot++) printk (" ");
1152 printk ("%2x:%016lx,%016lx\n",
1153 0,
1154 spitfire_get_itlb_tag(0), spitfire_get_itlb_data(0));
1155 for (slot = 1; slot < 64; slot+=3) {
1156 printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx %2x:%016lx,%016lx\n",
1157 slot,
1158 spitfire_get_itlb_tag(slot), spitfire_get_itlb_data(slot),
1159 slot+1,
1160 spitfire_get_itlb_tag(slot+1), spitfire_get_itlb_data(slot+1),
1161 slot+2,
1162 spitfire_get_itlb_tag(slot+2), spitfire_get_itlb_data(slot+2));
1163 }
1164 } else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
1165 printk ("Contents of itlb0:\n");
1166 for (slot = 0; slot < 16; slot+=2) {
1167 printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n",
1168 slot,
1169 cheetah_get_litlb_tag(slot), cheetah_get_litlb_data(slot),
1170 slot+1,
1171 cheetah_get_litlb_tag(slot+1), cheetah_get_litlb_data(slot+1));
1172 }
1173 printk ("Contents of itlb2:\n");
1174 for (slot = 0; slot < 128; slot+=2) {
1175 printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n",
1176 slot,
1177 cheetah_get_itlb_tag(slot), cheetah_get_itlb_data(slot),
1178 slot+1,
1179 cheetah_get_itlb_tag(slot+1), cheetah_get_itlb_data(slot+1));
1180 }
1181 }
1182}
1183
1184void sparc_ultra_dump_dtlb(void)
1185{
1186 int slot;
1187
1188 if (tlb_type == spitfire) {
1189 printk ("Contents of dtlb: ");
1190 for (slot = 0; slot < 14; slot++) printk (" ");
1191 printk ("%2x:%016lx,%016lx\n", 0,
1192 spitfire_get_dtlb_tag(0), spitfire_get_dtlb_data(0));
1193 for (slot = 1; slot < 64; slot+=3) {
1194 printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx %2x:%016lx,%016lx\n",
1195 slot,
1196 spitfire_get_dtlb_tag(slot), spitfire_get_dtlb_data(slot),
1197 slot+1,
1198 spitfire_get_dtlb_tag(slot+1), spitfire_get_dtlb_data(slot+1),
1199 slot+2,
1200 spitfire_get_dtlb_tag(slot+2), spitfire_get_dtlb_data(slot+2));
1201 }
1202 } else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
1203 printk ("Contents of dtlb0:\n");
1204 for (slot = 0; slot < 16; slot+=2) {
1205 printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n",
1206 slot,
1207 cheetah_get_ldtlb_tag(slot), cheetah_get_ldtlb_data(slot),
1208 slot+1,
1209 cheetah_get_ldtlb_tag(slot+1), cheetah_get_ldtlb_data(slot+1));
1210 }
1211 printk ("Contents of dtlb2:\n");
1212 for (slot = 0; slot < 512; slot+=2) {
1213 printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n",
1214 slot,
1215 cheetah_get_dtlb_tag(slot, 2), cheetah_get_dtlb_data(slot, 2),
1216 slot+1,
1217 cheetah_get_dtlb_tag(slot+1, 2), cheetah_get_dtlb_data(slot+1, 2));
1218 }
1219 if (tlb_type == cheetah_plus) {
1220 printk ("Contents of dtlb3:\n");
1221 for (slot = 0; slot < 512; slot+=2) {
1222 printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n",
1223 slot,
1224 cheetah_get_dtlb_tag(slot, 3), cheetah_get_dtlb_data(slot, 3),
1225 slot+1,
1226 cheetah_get_dtlb_tag(slot+1, 3), cheetah_get_dtlb_data(slot+1, 3));
1227 }
1228 }
1229 }
1230}
1231
1232extern unsigned long cmdline_memory_size;
1233
1234unsigned long __init bootmem_init(unsigned long *pages_avail)
1235{
1236 unsigned long bootmap_size, start_pfn, end_pfn;
1237 unsigned long end_of_phys_memory = 0UL;
1238 unsigned long bootmap_pfn, bytes_avail, size;
1239 int i;
1240
1241#ifdef CONFIG_DEBUG_BOOTMEM
1242 prom_printf("bootmem_init: Scan sp_banks, ");
1243#endif
1244
1245 bytes_avail = 0UL;
1246 for (i = 0; sp_banks[i].num_bytes != 0; i++) {
1247 end_of_phys_memory = sp_banks[i].base_addr +
1248 sp_banks[i].num_bytes;
1249 bytes_avail += sp_banks[i].num_bytes;
1250 if (cmdline_memory_size) {
1251 if (bytes_avail > cmdline_memory_size) {
1252 unsigned long slack = bytes_avail - cmdline_memory_size;
1253
1254 bytes_avail -= slack;
1255 end_of_phys_memory -= slack;
1256
1257 sp_banks[i].num_bytes -= slack;
1258 if (sp_banks[i].num_bytes == 0) {
1259 sp_banks[i].base_addr = 0xdeadbeef;
1260 } else {
1261 sp_banks[i+1].num_bytes = 0;
1262 sp_banks[i+1].base_addr = 0xdeadbeef;
1263 }
1264 break;
1265 }
1266 }
1267 }
1268
1269 *pages_avail = bytes_avail >> PAGE_SHIFT;
1270
1271
1272
1273
1274
1275 start_pfn = PAGE_ALIGN(kern_base + kern_size) >> PAGE_SHIFT;
1276
1277 bootmap_pfn = start_pfn;
1278
1279 end_pfn = end_of_phys_memory >> PAGE_SHIFT;
1280
1281#ifdef CONFIG_BLK_DEV_INITRD
1282
1283 if (sparc_ramdisk_image || sparc_ramdisk_image64) {
1284 unsigned long ramdisk_image = sparc_ramdisk_image ?
1285 sparc_ramdisk_image : sparc_ramdisk_image64;
1286 if (ramdisk_image >= (unsigned long)_end - 2 * PAGE_SIZE)
1287 ramdisk_image -= KERNBASE;
1288 initrd_start = ramdisk_image + phys_base;
1289 initrd_end = initrd_start + sparc_ramdisk_size;
1290 if (initrd_end > end_of_phys_memory) {
1291 printk(KERN_CRIT "initrd extends beyond end of memory "
1292 "(0x%016lx > 0x%016lx)\ndisabling initrd\n",
1293 initrd_end, end_of_phys_memory);
1294 initrd_start = 0;
1295 }
1296 if (initrd_start) {
1297 if (initrd_start >= (start_pfn << PAGE_SHIFT) &&
1298 initrd_start < (start_pfn << PAGE_SHIFT) + 2 * PAGE_SIZE)
1299 bootmap_pfn = PAGE_ALIGN (initrd_end) >> PAGE_SHIFT;
1300 }
1301 }
1302#endif
1303
1304 max_pfn = max_low_pfn = end_pfn;
1305 min_low_pfn = pfn_base;
1306
1307#ifdef CONFIG_DEBUG_BOOTMEM
1308 prom_printf("init_bootmem(min[%lx], bootmap[%lx], max[%lx])\n",
1309 min_low_pfn, bootmap_pfn, max_low_pfn);
1310#endif
1311 bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap_pfn, pfn_base, end_pfn);
1312
1313 bootmap_base = bootmap_pfn << PAGE_SHIFT;
1314
1315
1316
1317
1318 for (i = 0; sp_banks[i].num_bytes != 0; i++) {
1319#ifdef CONFIG_DEBUG_BOOTMEM
1320 prom_printf("free_bootmem(sp_banks:%d): base[%lx] size[%lx]\n",
1321 i, sp_banks[i].base_addr, sp_banks[i].num_bytes);
1322#endif
1323 free_bootmem(sp_banks[i].base_addr, sp_banks[i].num_bytes);
1324 }
1325
1326#ifdef CONFIG_BLK_DEV_INITRD
1327 if (initrd_start) {
1328 size = initrd_end - initrd_start;
1329
1330
1331#ifdef CONFIG_DEBUG_BOOTMEM
1332 prom_printf("reserve_bootmem(initrd): base[%llx] size[%lx]\n",
1333 initrd_start, initrd_end);
1334#endif
1335 reserve_bootmem(initrd_start, size);
1336 *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT;
1337
1338 initrd_start += PAGE_OFFSET;
1339 initrd_end += PAGE_OFFSET;
1340 }
1341#endif
1342
1343#ifdef CONFIG_DEBUG_BOOTMEM
1344 prom_printf("reserve_bootmem(kernel): base[%lx] size[%lx]\n", kern_base, kern_size);
1345#endif
1346 reserve_bootmem(kern_base, kern_size);
1347 *pages_avail -= PAGE_ALIGN(kern_size) >> PAGE_SHIFT;
1348
1349
1350
1351
1352
1353 size = bootmap_size;
1354#ifdef CONFIG_DEBUG_BOOTMEM
1355 prom_printf("reserve_bootmem(bootmap): base[%lx] size[%lx]\n",
1356 (bootmap_pfn << PAGE_SHIFT), size);
1357#endif
1358 reserve_bootmem((bootmap_pfn << PAGE_SHIFT), size);
1359 *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT;
1360
1361 return end_pfn;
1362}
1363
1364
1365
1366extern void cheetah_ecache_flush_init(void);
1367
1368static unsigned long last_valid_pfn;
1369
1370void __init paging_init(void)
1371{
1372 extern pmd_t swapper_pmd_dir[1024];
1373 extern unsigned int sparc64_vpte_patchme1[1];
1374 extern unsigned int sparc64_vpte_patchme2[1];
1375 unsigned long alias_base = kern_base + PAGE_OFFSET;
1376 unsigned long second_alias_page = 0;
1377 unsigned long pt, flags, end_pfn, pages_avail;
1378 unsigned long shift = alias_base - ((unsigned long)KERNBASE);
1379 unsigned long real_end;
1380
1381 set_bit(0, mmu_context_bmap);
1382
1383 real_end = (unsigned long)_end;
1384 if ((real_end > ((unsigned long)KERNBASE + 0x400000)))
1385 bigkernel = 1;
1386#ifdef CONFIG_BLK_DEV_INITRD
1387 if (sparc_ramdisk_image || sparc_ramdisk_image64)
1388 real_end = (PAGE_ALIGN(real_end) + PAGE_ALIGN(sparc_ramdisk_size));
1389#endif
1390
1391
1392
1393
1394
1395 pt = kern_base | _PAGE_VALID | _PAGE_SZ4MB;
1396 pt |= _PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W;
1397 local_irq_save(flags);
1398 if (tlb_type == spitfire) {
1399 __asm__ __volatile__(
1400 " stxa %1, [%0] %3\n"
1401 " stxa %2, [%5] %4\n"
1402 " membar #Sync\n"
1403 " flush %%g6\n"
1404 " nop\n"
1405 " nop\n"
1406 " nop\n"
1407 :
1408 : "r" (TLB_TAG_ACCESS), "r" (alias_base), "r" (pt),
1409 "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" (61 << 3)
1410 : "memory");
1411 if (real_end >= KERNBASE + 0x340000) {
1412 second_alias_page = alias_base + 0x400000;
1413 __asm__ __volatile__(
1414 " stxa %1, [%0] %3\n"
1415 " stxa %2, [%5] %4\n"
1416 " membar #Sync\n"
1417 " flush %%g6\n"
1418 " nop\n"
1419 " nop\n"
1420 " nop\n"
1421 :
1422 : "r" (TLB_TAG_ACCESS), "r" (second_alias_page), "r" (pt + 0x400000),
1423 "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" (60 << 3)
1424 : "memory");
1425 }
1426 } else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
1427 __asm__ __volatile__(
1428 " stxa %1, [%0] %3\n"
1429 " stxa %2, [%5] %4\n"
1430 " membar #Sync\n"
1431 " flush %%g6\n"
1432 " nop\n"
1433 " nop\n"
1434 " nop\n"
1435 :
1436 : "r" (TLB_TAG_ACCESS), "r" (alias_base), "r" (pt),
1437 "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" ((0<<16) | (13<<3))
1438 : "memory");
1439 if (real_end >= KERNBASE + 0x340000) {
1440 second_alias_page = alias_base + 0x400000;
1441 __asm__ __volatile__(
1442 " stxa %1, [%0] %3\n"
1443 " stxa %2, [%5] %4\n"
1444 " membar #Sync\n"
1445 " flush %%g6\n"
1446 " nop\n"
1447 " nop\n"
1448 " nop\n"
1449 :
1450 : "r" (TLB_TAG_ACCESS), "r" (second_alias_page), "r" (pt + 0x400000),
1451 "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" ((0<<16) | (12<<3))
1452 : "memory");
1453 }
1454 }
1455 local_irq_restore(flags);
1456
1457
1458
1459
1460 init_mm.pgd += ((shift) / (sizeof(pgd_t)));
1461
1462 memset(swapper_pmd_dir, 0, sizeof(swapper_pmd_dir));
1463
1464
1465 pud_set(pud_offset(&swapper_pg_dir[0], 0),
1466 swapper_pmd_dir + (shift / sizeof(pgd_t)));
1467
1468 sparc64_vpte_patchme1[0] |=
1469 (((unsigned long)pgd_val(init_mm.pgd[0])) >> 10);
1470 sparc64_vpte_patchme2[0] |=
1471 (((unsigned long)pgd_val(init_mm.pgd[0])) & 0x3ff);
1472 flushi((long)&sparc64_vpte_patchme1[0]);
1473
1474
1475 pages_avail = 0;
1476 last_valid_pfn = end_pfn = bootmem_init(&pages_avail);
1477
1478
1479 inherit_prom_mappings();
1480
1481
1482
1483
1484
1485
1486 {
1487 extern void setup_tba(int);
1488 setup_tba(this_is_starfire);
1489 }
1490
1491 inherit_locked_prom_mappings(1);
1492
1493
1494 spitfire_flush_dtlb_nucleus_page(alias_base);
1495 if (second_alias_page)
1496 spitfire_flush_dtlb_nucleus_page(second_alias_page);
1497
1498 __flush_tlb_all();
1499
1500 {
1501 unsigned long zones_size[MAX_NR_ZONES];
1502 unsigned long zholes_size[MAX_NR_ZONES];
1503 unsigned long npages;
1504 int znum;
1505
1506 for (znum = 0; znum < MAX_NR_ZONES; znum++)
1507 zones_size[znum] = zholes_size[znum] = 0;
1508
1509 npages = end_pfn - pfn_base;
1510 zones_size[ZONE_DMA] = npages;
1511 zholes_size[ZONE_DMA] = npages - pages_avail;
1512
1513 free_area_init_node(0, &contig_page_data, zones_size,
1514 phys_base >> PAGE_SHIFT, zholes_size);
1515 mem_map = contig_page_data.node_mem_map;
1516 }
1517
1518 device_scan();
1519}
1520
1521
1522
1523
1524
1525
1526
1527static void __init sort_memlist(struct linux_mlist_p1275 *thislist)
1528{
1529 int swapi = 0;
1530 int i, mitr;
1531 unsigned long tmpaddr, tmpsize;
1532 unsigned long lowest;
1533
1534 for (i = 0; thislist[i].theres_more != 0; i++) {
1535 lowest = thislist[i].start_adr;
1536 for (mitr = i+1; thislist[mitr-1].theres_more != 0; mitr++)
1537 if (thislist[mitr].start_adr < lowest) {
1538 lowest = thislist[mitr].start_adr;
1539 swapi = mitr;
1540 }
1541 if (lowest == thislist[i].start_adr)
1542 continue;
1543 tmpaddr = thislist[swapi].start_adr;
1544 tmpsize = thislist[swapi].num_bytes;
1545 for (mitr = swapi; mitr > i; mitr--) {
1546 thislist[mitr].start_adr = thislist[mitr-1].start_adr;
1547 thislist[mitr].num_bytes = thislist[mitr-1].num_bytes;
1548 }
1549 thislist[i].start_adr = tmpaddr;
1550 thislist[i].num_bytes = tmpsize;
1551 }
1552}
1553
1554void __init rescan_sp_banks(void)
1555{
1556 struct linux_prom64_registers memlist[64];
1557 struct linux_mlist_p1275 avail[64], *mlist;
1558 unsigned long bytes, base_paddr;
1559 int num_regs, node = prom_finddevice("/memory");
1560 int i;
1561
1562 num_regs = prom_getproperty(node, "available",
1563 (char *) memlist, sizeof(memlist));
1564 num_regs = (num_regs / sizeof(struct linux_prom64_registers));
1565 for (i = 0; i < num_regs; i++) {
1566 avail[i].start_adr = memlist[i].phys_addr;
1567 avail[i].num_bytes = memlist[i].reg_size;
1568 avail[i].theres_more = &avail[i + 1];
1569 }
1570 avail[i - 1].theres_more = NULL;
1571 sort_memlist(avail);
1572
1573 mlist = &avail[0];
1574 i = 0;
1575 bytes = mlist->num_bytes;
1576 base_paddr = mlist->start_adr;
1577
1578 sp_banks[0].base_addr = base_paddr;
1579 sp_banks[0].num_bytes = bytes;
1580
1581 while (mlist->theres_more != NULL){
1582 i++;
1583 mlist = mlist->theres_more;
1584 bytes = mlist->num_bytes;
1585 if (i >= SPARC_PHYS_BANKS-1) {
1586 printk ("The machine has more banks than "
1587 "this kernel can support\n"
1588 "Increase the SPARC_PHYS_BANKS "
1589 "setting (currently %d)\n",
1590 SPARC_PHYS_BANKS);
1591 i = SPARC_PHYS_BANKS-1;
1592 break;
1593 }
1594
1595 sp_banks[i].base_addr = mlist->start_adr;
1596 sp_banks[i].num_bytes = mlist->num_bytes;
1597 }
1598
1599 i++;
1600 sp_banks[i].base_addr = 0xdeadbeefbeefdeadUL;
1601 sp_banks[i].num_bytes = 0;
1602
1603 for (i = 0; sp_banks[i].num_bytes != 0; i++)
1604 sp_banks[i].num_bytes &= PAGE_MASK;
1605}
1606
1607static void __init taint_real_pages(void)
1608{
1609 struct sparc_phys_banks saved_sp_banks[SPARC_PHYS_BANKS];
1610 int i;
1611
1612 for (i = 0; i < SPARC_PHYS_BANKS; i++) {
1613 saved_sp_banks[i].base_addr =
1614 sp_banks[i].base_addr;
1615 saved_sp_banks[i].num_bytes =
1616 sp_banks[i].num_bytes;
1617 }
1618
1619 rescan_sp_banks();
1620
1621
1622
1623
1624 for (i = 0; saved_sp_banks[i].num_bytes; i++) {
1625 unsigned long old_start, old_end;
1626
1627 old_start = saved_sp_banks[i].base_addr;
1628 old_end = old_start +
1629 saved_sp_banks[i].num_bytes;
1630 while (old_start < old_end) {
1631 int n;
1632
1633 for (n = 0; sp_banks[n].num_bytes; n++) {
1634 unsigned long new_start, new_end;
1635
1636 new_start = sp_banks[n].base_addr;
1637 new_end = new_start + sp_banks[n].num_bytes;
1638
1639 if (new_start <= old_start &&
1640 new_end >= (old_start + PAGE_SIZE)) {
1641 set_bit (old_start >> 22,
1642 sparc64_valid_addr_bitmap);
1643 goto do_next_page;
1644 }
1645 }
1646 reserve_bootmem(old_start, PAGE_SIZE);
1647
1648 do_next_page:
1649 old_start += PAGE_SIZE;
1650 }
1651 }
1652}
1653
1654void __init mem_init(void)
1655{
1656 unsigned long codepages, datapages, initpages;
1657 unsigned long addr, last;
1658 int i;
1659
1660 i = last_valid_pfn >> ((22 - PAGE_SHIFT) + 6);
1661 i += 1;
1662 sparc64_valid_addr_bitmap = (unsigned long *)
1663 __alloc_bootmem(i << 3, SMP_CACHE_BYTES, bootmap_base);
1664 if (sparc64_valid_addr_bitmap == NULL) {
1665 prom_printf("mem_init: Cannot alloc valid_addr_bitmap.\n");
1666 prom_halt();
1667 }
1668 memset(sparc64_valid_addr_bitmap, 0, i << 3);
1669
1670 addr = PAGE_OFFSET + kern_base;
1671 last = PAGE_ALIGN(kern_size) + addr;
1672 while (addr < last) {
1673 set_bit(__pa(addr) >> 22, sparc64_valid_addr_bitmap);
1674 addr += PAGE_SIZE;
1675 }
1676
1677 taint_real_pages();
1678
1679 max_mapnr = last_valid_pfn - pfn_base;
1680 high_memory = __va(last_valid_pfn << PAGE_SHIFT);
1681
1682#ifdef CONFIG_DEBUG_BOOTMEM
1683 prom_printf("mem_init: Calling free_all_bootmem().\n");
1684#endif
1685 totalram_pages = num_physpages = free_all_bootmem() - 1;
1686
1687
1688
1689
1690
1691 mem_map_zero = alloc_pages(GFP_KERNEL|__GFP_ZERO, 0);
1692 if (mem_map_zero == NULL) {
1693 prom_printf("paging_init: Cannot alloc zero page.\n");
1694 prom_halt();
1695 }
1696 SetPageReserved(mem_map_zero);
1697
1698 codepages = (((unsigned long) _etext) - ((unsigned long) _start));
1699 codepages = PAGE_ALIGN(codepages) >> PAGE_SHIFT;
1700 datapages = (((unsigned long) _edata) - ((unsigned long) _etext));
1701 datapages = PAGE_ALIGN(datapages) >> PAGE_SHIFT;
1702 initpages = (((unsigned long) __init_end) - ((unsigned long) __init_begin));
1703 initpages = PAGE_ALIGN(initpages) >> PAGE_SHIFT;
1704
1705#ifndef CONFIG_SMP
1706 {
1707
1708 extern pgd_t empty_pg_dir[1024];
1709 unsigned long addr = (unsigned long)empty_pg_dir;
1710 unsigned long alias_base = kern_base + PAGE_OFFSET -
1711 (long)(KERNBASE);
1712
1713 memset(empty_pg_dir, 0, sizeof(empty_pg_dir));
1714 addr += alias_base;
1715 free_pgd_fast((pgd_t *)addr);
1716 num_physpages++;
1717 totalram_pages++;
1718 }
1719#endif
1720
1721 printk("Memory: %uk available (%ldk kernel code, %ldk data, %ldk init) [%016lx,%016lx]\n",
1722 nr_free_pages() << (PAGE_SHIFT-10),
1723 codepages << (PAGE_SHIFT-10),
1724 datapages << (PAGE_SHIFT-10),
1725 initpages << (PAGE_SHIFT-10),
1726 PAGE_OFFSET, (last_valid_pfn << PAGE_SHIFT));
1727
1728 if (tlb_type == cheetah || tlb_type == cheetah_plus)
1729 cheetah_ecache_flush_init();
1730}
1731
1732void free_initmem (void)
1733{
1734 unsigned long addr, initend;
1735
1736
1737
1738
1739 addr = PAGE_ALIGN((unsigned long)(__init_begin));
1740 initend = (unsigned long)(__init_end) & PAGE_MASK;
1741 for (; addr < initend; addr += PAGE_SIZE) {
1742 unsigned long page;
1743 struct page *p;
1744
1745 page = (addr +
1746 ((unsigned long) __va(kern_base)) -
1747 ((unsigned long) KERNBASE));
1748 memset((void *)addr, 0xcc, PAGE_SIZE);
1749 p = virt_to_page(page);
1750
1751 ClearPageReserved(p);
1752 set_page_count(p, 1);
1753 __free_page(p);
1754 num_physpages++;
1755 totalram_pages++;
1756 }
1757}
1758
1759#ifdef CONFIG_BLK_DEV_INITRD
1760void free_initrd_mem(unsigned long start, unsigned long end)
1761{
1762 if (start < end)
1763 printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
1764 for (; start < end; start += PAGE_SIZE) {
1765 struct page *p = virt_to_page(start);
1766
1767 ClearPageReserved(p);
1768 set_page_count(p, 1);
1769 __free_page(p);
1770 num_physpages++;
1771 totalram_pages++;
1772 }
1773}
1774#endif
1775