0
|
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 }
|