Mercurial > hg > Members > innparusu > xv6-rpi
comparison src/start.c @ 0:83c23a36980d
Init
author | Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 26 May 2017 23:11:05 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:83c23a36980d |
---|---|
1 // initialize section | |
2 #include "types.h" | |
3 #include "param.h" | |
4 #include "arm.h" | |
5 #include "mmu.h" | |
6 #include "defs.h" | |
7 #include "memlayout.h" | |
8 | |
9 void _uart_putc(int c) | |
10 { | |
11 volatile uint8 * uart0 = (uint8*)UART0; | |
12 *uart0 = c; | |
13 } | |
14 | |
15 | |
16 void _puts (char *s) | |
17 { | |
18 while (*s != '\0') { | |
19 _uart_putc(*s); | |
20 s++; | |
21 } | |
22 } | |
23 | |
24 void _putint (char *prefix, uint val, char* suffix) | |
25 { | |
26 char* arr = "0123456789ABCDEF"; | |
27 int idx; | |
28 | |
29 if (prefix) { | |
30 _puts(prefix); | |
31 } | |
32 | |
33 for (idx = sizeof(val) * 8 - 4; idx >= 0; idx -= 4) { | |
34 _uart_putc(arr[(val >> idx) & 0x0F]); | |
35 } | |
36 | |
37 if (suffix) { | |
38 _puts(suffix); | |
39 } | |
40 } | |
41 | |
42 | |
43 // kernel page table, reserved in the kernel.ld | |
44 extern uint32 _kernel_pgtbl; | |
45 extern uint32 _user_pgtbl; | |
46 | |
47 uint32 *kernel_pgtbl = &_kernel_pgtbl; | |
48 uint32 *user_pgtbl = &_user_pgtbl; | |
49 | |
50 #define PDE_SHIFT 20 | |
51 | |
52 uint32 get_pde (uint32 virt) | |
53 { | |
54 virt >>= PDE_SHIFT; | |
55 return kernel_pgtbl[virt]; | |
56 } | |
57 | |
58 // setup the boot page table: dev_mem whether it is device memory | |
59 void set_bootpgtbl (uint32 virt, uint32 phy, uint len, int dev_mem ) | |
60 { | |
61 uint32 pde; | |
62 int idx; | |
63 | |
64 // convert all the parameters to indexes | |
65 virt >>= PDE_SHIFT; | |
66 phy >>= PDE_SHIFT; | |
67 len >>= PDE_SHIFT; | |
68 | |
69 for (idx = 0; idx < len; idx++) { | |
70 pde = (phy << PDE_SHIFT); | |
71 | |
72 if (!dev_mem) { | |
73 // normal memory, make it kernel-only, cachable, bufferable | |
74 pde |= (AP_KO << 10) | PE_CACHE | PE_BUF | KPDE_TYPE; | |
75 } else { | |
76 // device memory, make it non-cachable and non-bufferable | |
77 pde |= (AP_KO << 10) | KPDE_TYPE; | |
78 } | |
79 | |
80 // use different page table for user/kernel space | |
81 if (virt < NUM_UPDE) { | |
82 user_pgtbl[virt] = pde; | |
83 } else { | |
84 kernel_pgtbl[virt] = pde; | |
85 } | |
86 | |
87 virt++; | |
88 phy++; | |
89 } | |
90 } | |
91 | |
92 static void _flush_all (void) | |
93 { | |
94 uint val = 0; | |
95 | |
96 // flush all TLB | |
97 asm("MCR p15, 0, %[r], c8, c7, 0" : :[r]"r" (val):); | |
98 | |
99 // invalid entire data and instruction cache | |
100 // asm ("MCR p15,0,%[r],c7,c5,0": :[r]"r" (val):); | |
101 // asm ("MCR p15,0,%[r],c7,c6,0": :[r]"r" (val):); | |
102 } | |
103 | |
104 void load_pgtlb (uint32* kern_pgtbl, uint32* user_pgtbl) | |
105 { | |
106 uint ret; | |
107 char arch; | |
108 uint val; | |
109 | |
110 // read the main id register to make sure we are running on ARMv6 | |
111 asm("MRC p15, 0, %[r], c0, c0, 0": [r]"=r" (ret)::); | |
112 | |
113 if (ret >> 24 == 0x41) { | |
114 //_puts ("ARM-based CPU\n"); | |
115 } | |
116 | |
117 arch = (ret >> 16) & 0x0F; | |
118 | |
119 if ((arch != 7) && (arch != 0xF)) { | |
120 _puts ("need AARM v6 or higher\n"); | |
121 } | |
122 | |
123 // we need to check the cache/tlb etc., but let's skip it for now | |
124 | |
125 // set domain access control: all domain will be checked for permission | |
126 val = 0x55555555; | |
127 asm("MCR p15, 0, %[v], c3, c0, 0": :[v]"r" (val):); | |
128 | |
129 // set the page table base registers. We use two page tables: TTBR0 | |
130 // for user space and TTBR1 for kernel space | |
131 val = 32 - UADDR_BITS; | |
132 asm("MCR p15, 0, %[v], c2, c0, 2": :[v]"r" (val):); | |
133 | |
134 // set the kernel page table | |
135 val = (uint)kernel_pgtbl | 0x00; | |
136 asm("MCR p15, 0, %[v], c2, c0, 1": :[v]"r" (val):); | |
137 | |
138 // set the user page table | |
139 val = (uint)user_pgtbl | 0x00; | |
140 asm("MCR p15, 0, %[v], c2, c0, 0": :[v]"r" (val):); | |
141 | |
142 // ok, enable paging using read/modify/write | |
143 asm("MRC p15, 0, %[r], c1, c0, 0": [r]"=r" (val)::); | |
144 | |
145 val |= 0x80300D; // enable MMU, cache, write buffer, high vector tbl, | |
146 // disable subpage | |
147 asm("MCR p15, 0, %[r], c1, c0, 0": :[r]"r" (val):); | |
148 | |
149 _flush_all(); | |
150 } | |
151 | |
152 extern void * edata_entry; | |
153 extern void * svc_stktop; | |
154 extern void kmain (void); | |
155 extern void jump_stack (void); | |
156 | |
157 extern void * edata; | |
158 extern void * end; | |
159 | |
160 // clear the BSS section for the main kernel, see kernel.ld | |
161 void clear_bss (void) | |
162 { | |
163 memset(&edata, 0x00, (uint)&end-(uint)&edata); | |
164 } | |
165 | |
166 void start (void) | |
167 { | |
168 uint32 vectbl; | |
169 _puts("starting xv6 for ARM...\n"); | |
170 | |
171 // double map the low memory, required to enable paging | |
172 // we do not map all the physical memory | |
173 set_bootpgtbl(0, 0, INIT_KERNMAP, 0); | |
174 set_bootpgtbl(KERNBASE, 0, INIT_KERNMAP, 0); | |
175 | |
176 // vector table is in the middle of first 1MB (0xF000) | |
177 vectbl = P2V_WO (VEC_TBL & PDE_MASK); | |
178 | |
179 if (vectbl <= (uint)&end) { | |
180 cprintf ("error: vector table overlaps kernel\n"); | |
181 } | |
182 | |
183 set_bootpgtbl(VEC_TBL, 0, 1 << PDE_SHIFT, 0); | |
184 set_bootpgtbl(KERNBASE+DEVBASE, DEVBASE, DEV_MEM_SZ, 1); | |
185 | |
186 load_pgtlb (kernel_pgtbl, user_pgtbl); | |
187 jump_stack (); | |
188 | |
189 // We can now call normal kernel functions at high memory | |
190 clear_bss (); | |
191 | |
192 kmain (); | |
193 } |