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