made some fixes to support gcc3 on sparc
[akaros.git] / kern / arch / sparc / boot.c
1 #include <multiboot.h>
2 #include <arch/mmu.h>
3 #include <arch/arch.h>
4 #include <ros/common.h>
5 #include <ros/memlayout.h>
6 #include <string.h>
7
8 #ifdef __SHARC__
9 #pragma nosharc
10 #endif
11
12 #ifdef __DEPUTY__
13 #pragma nodeputy
14 #endif
15
16 void
17 build_multiboot_info(multiboot_info_t* mbi)
18 {
19         uint32_t memsize_kb = memsize_mb()*1024;
20         uint32_t basemem_kb = EXTPHYSMEM/1024;
21
22         memset(mbi,0,sizeof(mbi));
23
24         mbi->flags = 0x00000001;
25         mbi->mem_lower = basemem_kb;
26         mbi->mem_upper = memsize_kb-basemem_kb;
27 }
28
29 // set up a basic virtual -> physical mapping so we can boot the kernel
30 void
31 build_boot_pgdir(void)
32 {
33         extern uintptr_t l1_page_table[NL1ENTRIES];
34
35         // relocate symbols
36         uintptr_t* l1 = (uintptr_t*)((uint8_t*)l1_page_table-KERNBASE);
37
38         uintptr_t kernsize = /* 4GB */ - KERNBASE;
39
40         // make all L1 PTEs invalid by default
41         int i;
42         for(i = 0; i < NL1ENTRIES; i++)
43                 l1[i] = 0;
44
45         // Retain the identity mapping
46         // [0,4GB-KERNBASE] -> [0,4GB-KERNBASE]
47         // so we don't nuke ourselveswhen we turn on protection!!
48         for(i = 0; i < kernsize/L1PGSIZE; i++)
49                 l1[i] = (i << 20) | PTE_KERN_RW | PTE_PTE;
50
51         // make the relocated mapping
52         // [KERNBASE,4GB] -> [0,4GB-KERNBASE]
53         for(i = 0; i < kernsize/L1PGSIZE; i++)
54                 l1[i+KERNBASE/L1PGSIZE] = (i << 20) | PTE_KERN_RW | PTE_PTE;
55 }
56
57 void
58 mmu_init(void)
59 {
60         extern uintptr_t l1_page_table[NL1ENTRIES];
61         uintptr_t* l1 = (uintptr_t*)((uint8_t*)l1_page_table-KERNBASE);
62
63         int zero = 0;
64         uintptr_t* mmuctxtbl = (uintptr_t*)((uint8_t*)(mmu_context_tables[core_id()])-KERNBASE);
65
66         // make all context table entries invalid
67         int i;
68         for(i = 0; i < NCONTEXTS; i++)
69                 mmuctxtbl[i] = 0;
70
71         // except for the zeroth one, which points to our L1 PT
72         *mmuctxtbl = PTD((uintptr_t)l1);
73
74         // set current context (== 0)
75         store_alternate(0x200,4,zero);
76
77         // set physical address of context table
78         store_alternate(0x100,4,(uintptr_t)mmuctxtbl>>4);
79
80         // turn on MMU
81         tlbflush();
82         store_alternate(0x000,4,1);
83 }
84
85 // delete temporary mappings used by the entry code
86 void
87 mmu_boot_cleanup(void)
88 {
89         extern uintptr_t l1_page_table[NL1ENTRIES];
90         uintptr_t kernsize = -KERNBASE;
91
92         // make the temporary mapping invalid
93         int i;
94         for(i = 0; i < kernsize/L1PGSIZE; i++)
95                 l1_page_table[i] = 0;
96 }
97
98 void
99 mmu_boot(void)
100 {
101         int id = core_id(), i, ncores = num_cores();
102
103         static volatile int done_0 = 0;
104         volatile int* done0 = (int*)((uintptr_t)&done_0 - KERNBASE); 
105
106         if(id == 0)
107         {
108                 build_boot_pgdir();
109                 *done0 = 1;
110         }
111         else
112                 while(!*done0);
113
114         mmu_init();
115 }
116
117 void
118 mmu_boot_finish(void)
119 {
120         int id = core_id(), i, ncores = num_cores();
121
122         static volatile int barrier[MAX_NUM_CPUS] = {0};
123         static volatile int done1 = 0;
124
125         if(id == 0)
126         {
127                 for(i = 1; i < ncores; i++)
128                         while(!barrier[i]);
129                 mmu_boot_cleanup();
130                 done1 = 1;
131         }
132         else
133         {
134                 barrier[id] = 1;
135                 while(!done1);
136         }
137
138         tlbflush();
139 }