]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/arm/bootstrap.cpp
8b97c2d1c47b67ff5583edf2a75b959487404875
[l4.git] / kernel / fiasco / src / kern / arm / bootstrap.cpp
1 INTERFACE [arm]:
2
3 #include <cstddef>
4 #include "types.h"
5 #include "mem_layout.h"
6
7 //---------------------------------------------------------------------------
8 IMPLEMENTATION [arm]:
9
10 #include "cpu.h"
11 #include "kmem_space.h"
12
13
14 extern char kernel_page_directory[];
15
16 namespace Bootstrap {
17
18 struct Order_t;
19 struct Phys_addr_t;
20 struct Virt_addr_t;
21
22 typedef cxx::int_type<unsigned, Order_t> Order;
23 typedef cxx::int_type_order<Unsigned32, Virt_addr_t, Order> Virt_addr;
24
25 enum
26 {
27   Virt_ofs = Mem_layout::Sdram_phys_base - Mem_layout::Map_base,
28 };
29
30 }
31
32 //---------------------------------------------------------------------------
33 INTERFACE [arm && armv5]:
34
35 namespace Bootstrap {
36 inline void set_asid()
37 {}
38 }
39
40 //---------------------------------------------------------------------------
41 INTERFACE [arm && (armv6 || armv7)]:
42
43 namespace Bootstrap {
44 inline void
45 set_asid()
46 {
47   asm volatile ("mcr p15, 0, %0, c13, c0, 1" : : "r" (0)); // ASID 0
48 }
49 }
50
51 //---------------------------------------------------------------------------
52 INTERFACE [arm && !arm_lpae]:
53
54 namespace Bootstrap {
55 inline void
56 set_ttbr(Mword pdir)
57 {
58   asm volatile("mcr p15, 0, %[pdir], c2, c0" // TTBR0
59                : : [pdir] "r" (pdir));
60 }
61 }
62
63 //---------------------------------------------------------------------------
64 INTERFACE [arm && arm_lpae]:
65
66 namespace Bootstrap {
67 inline void
68 set_ttbr(Mword pdir)
69 {
70   asm volatile("mcrr p15, 0, %[pdir], %[null], c2" // TTBR0
71                : :
72                [pdir]  "r" (pdir),
73                [null]  "r" (0));
74 }
75 }
76
77 //---------------------------------------------------------------------------
78 IMPLEMENTATION [arm && arm1176_cache_alias_fix]:
79
80 namespace Bootstrap {
81 static void
82 do_arm_1176_cache_alias_workaround()
83 {
84   Mword v;
85   asm volatile ("mrc p15, 0, %0, c0, c0, 1   \n" : "=r" (v));
86   if (v & ((1 << 23) | (1 << 11)))
87     { // P bits set
88       asm volatile ("mrc p15, 0, r0, c1, c0, 1   \n"
89                     "orr r0, r0, #(1 << 6)       \n"
90                     "mcr p15, 0, r0, c1, c0, 1   \n"
91                     : : : "r0");
92     }
93 }
94 }
95
96 //---------------------------------------------------------------------------
97 IMPLEMENTATION [arm && !arm1176_cache_alias_fix]:
98
99 namespace Bootstrap {
100 static void do_arm_1176_cache_alias_workaround() {}
101 }
102
103
104 //---------------------------------------------------------------------------
105 IMPLEMENTATION [arm && arm_lpae]:
106
107 #include <cxx/cxx_int>
108
109 extern char kernel_lpae_dir[];
110
111 namespace Bootstrap {
112 typedef cxx::int_type_order<Unsigned64, Phys_addr_t, Order> Phys_addr;
113 inline Order map_page_order() { return Order(21); }
114
115 inline Phys_addr pt_entry(Phys_addr pa, bool cache, bool local)
116 {
117   Phys_addr res = cxx::mask_lsb(pa, map_page_order()) | Phys_addr(1); // this is a block
118
119   if (local)
120     res |= Phys_addr(1 << 11); // nG flag
121
122   if (cache)
123     res |= Phys_addr(8);
124
125   res |= Phys_addr(1 << 10); // AF
126   res |= Phys_addr(3 << 8);  // Inner sharable
127   return res;
128 }
129
130 inline Phys_addr init_paging(void *const page_dir)
131 {
132   Phys_addr *const lpae = reinterpret_cast<Phys_addr*>(kernel_lpae_dir + Virt_ofs);
133
134   for (unsigned i = 0; i < 4; ++i)
135     lpae[i] = Phys_addr(((Address)page_dir + 0x1000 * i) | 3);;
136
137   asm volatile ("mcr p15, 0, %0, c10, c2, 0 \n" // MAIR0
138                 : : "r"(Page::Mair0_bits));
139
140   return Phys_addr((Mword)lpae);
141 }
142
143 };
144
145 //---------------------------------------------------------------------------
146 IMPLEMENTATION [arm && !arm_lpae]:
147
148 #include <cxx/cxx_int>
149
150 namespace Bootstrap {
151 typedef cxx::int_type_order<Unsigned32, Phys_addr_t, Order> Phys_addr;
152 inline Order map_page_order() { return Order(20); }
153
154 inline Phys_addr pt_entry(Phys_addr pa, bool cache, bool local)
155 {
156   return cxx::mask_lsb(pa, map_page_order())
157                 | Phys_addr(cache ? Page::Section_cachable : Page::Section_no_cache)
158                 | Phys_addr(local ? Page::Section_local : Page::Section_global);
159 }
160
161 inline Phys_addr init_paging(void *const page_dir)
162 {
163   return Phys_addr((Mword)page_dir);
164 }
165
166 };
167
168 //---------------------------------------------------------------------------
169 IMPLEMENTATION [arm]:
170
171 namespace Bootstrap {
172
173 inline Phys_addr map_page_size_phys() { return Phys_addr(1) << map_page_order(); }
174 inline Virt_addr map_page_size() { return Virt_addr(1) << map_page_order(); }
175
176 static void
177 map_memory(void volatile *pd, Virt_addr va, Phys_addr pa,
178            bool cache, bool local)
179 {
180   Phys_addr *const p = (Phys_addr*)pd;
181   p[cxx::int_value<Virt_addr>(va >> map_page_order())]
182     = pt_entry(pa, cache, local);
183 }
184
185 static void
186 create_initial_mappings(void *const page_dir)
187 {
188   typedef Bootstrap::Phys_addr Phys_addr;
189   typedef Bootstrap::Virt_addr Virt_addr;
190
191   Virt_addr va;
192   Phys_addr pa;
193
194   // map sdram linear from 0xf0000000
195   for (va = Virt_addr(Mem_layout::Map_base), pa = Phys_addr(Mem_layout::Sdram_phys_base);
196        va < Virt_addr(Mem_layout::Map_base + (4 << 20));
197        va += Bootstrap::map_page_size(), pa += Bootstrap::map_page_size_phys())
198     Bootstrap::map_memory(page_dir, va, pa, true, false);
199
200   // map sdram 1:1
201   for (va = Virt_addr(Mem_layout::Sdram_phys_base);
202        va < Virt_addr(Mem_layout::Sdram_phys_base + (4 << 20));
203        va += Bootstrap::map_page_size())
204     Bootstrap::map_memory(page_dir, va, Phys_addr(cxx::int_value<Virt_addr>(va)), true, true);
205 }
206
207 static void
208 add_initial_pmem()
209 {
210   // The first 4MB of phys memory are always mapped to Map_base
211   Mem_layout::add_pmem(Mem_layout::Sdram_phys_base, Mem_layout::Map_base,
212                        4 << 20);
213 }
214 }
215
216 asm
217 (
218 ".section .text.init,#alloc,#execinstr \n"
219 ".global _start                        \n"
220 "_start:                               \n"
221 "     ldr sp, __init_data              \n"
222 "     bl        bootstrap_main         \n"
223
224 "__init_data:                          \n"
225 ".long _stack                          \n"
226 ".previous                             \n"
227 ".section .bss                         \n"
228 "       .space  2048                   \n"
229 "_stack:                               \n"
230 ".previous                             \n"
231 );
232
233
234 #include "mmu.h"
235
236 #include "globalconfig.h"
237
238 extern char bootstrap_bss_start[];
239 extern char bootstrap_bss_end[];
240 extern char __bss_start[];
241 extern char __bss_end[];
242
243 extern "C" void _start_kernel(void) __attribute__((long_call));
244
245 extern "C" void bootstrap_main()
246 {
247   void *const page_dir = kernel_page_directory + Bootstrap::Virt_ofs;
248
249   Unsigned32 tbbr = cxx::int_value<Bootstrap::Phys_addr>(Bootstrap::init_paging(page_dir))
250                     | Page::Ttbr_bits;
251
252   Bootstrap::create_initial_mappings(page_dir);
253
254   unsigned domains = 0x55555555; // client for all domains
255   unsigned control = Config::Cache_enabled
256                      ? Cpu::Cp15_c1_cache_enabled : Cpu::Cp15_c1_cache_disabled;
257
258   Mmu<Bootstrap::Cache_flush_area, true>::flush_cache();
259
260   Bootstrap::do_arm_1176_cache_alias_workaround();
261   Bootstrap::set_asid();
262
263   asm volatile("mcr p15, 0, %[ttbcr], c2, c0, 2" // TTBCR
264                : : [ttbcr] "r" (Page::Ttbcr_bits));
265   Mem::dsb();
266   asm volatile("mcr p15, 0, %[null], c8, c7, 0" // TLBIALL
267                : : [null]  "r" (0));
268   Mem::dsb();
269   asm volatile("mcr p15, 0, %[doms], c3, c0" // domains
270                : : [doms]  "r" (domains));
271
272   Bootstrap::set_ttbr(tbbr | Page::Ttbr_bits);
273
274   asm volatile("mcr p15, 0, %[control], c1, c0" // control
275                : : [control] "r" (control));
276   Mem::isb();
277
278   Bootstrap::add_initial_pmem();
279
280   _start_kernel();
281
282   while(1)
283     ;
284 }