]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/arm/bootstrap.cpp
504fcd26ec335bc20f710458170d09fc104da46c
[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
12 //---------------------------------------------------------------------------
13 IMPLEMENTATION [arm && armv5]:
14
15 enum
16 {
17   Section_cachable = 0x40e,
18   Section_no_cache = 0x402,
19   Section_local    = 0,
20   Section_global   = 0,
21 };
22
23 void
24 set_asid()
25 {}
26
27 //---------------------------------------------------------------------------
28 IMPLEMENTATION [arm && armv6plus && (mpcore || armca9)]:
29
30 enum
31 {
32   Section_shared = 1UL << 16,
33 };
34
35 //---------------------------------------------------------------------------
36 IMPLEMENTATION [arm && armv6plus && !(mpcore || armca9)]:
37
38 enum
39 {
40   Section_shared = 0,
41 };
42
43
44 //---------------------------------------------------------------------------
45 IMPLEMENTATION [arm && (armv6 || armv7)]:
46
47 enum
48 {
49   Section_cachable = 0x5406 | Section_shared,
50   Section_no_cache = 0x0402 | Section_shared,
51   Section_local    = (1 << 17),
52   Section_global   = 0,
53 };
54
55 void
56 set_asid()
57 {
58   asm volatile ("MCR p15, 0, %0, c13, c0, 1" : : "r" (0)); // ASID 0
59 }
60
61 //---------------------------------------------------------------------------
62 IMPLEMENTATION [arm && arm1176_cache_alias_fix]:
63
64 static void
65 do_arm_1176_cache_alias_workaround()
66 {
67   Mword v;
68   asm volatile ("mrc p15, 0, %0, c0, c0, 1   \n" : "=r" (v));
69   if (v & ((1 << 23) | (1 << 11)))
70     { // P bits set
71       asm volatile ("mrc p15, 0, r0, c1, c0, 1   \n"
72                     "orr r0, r0, #(1 << 6)       \n"
73                     "mcr p15, 0, r0, c1, c0, 1   \n"
74                     : : : "r0");
75     }
76 }
77
78 //---------------------------------------------------------------------------
79 IMPLEMENTATION [arm && !arm1176_cache_alias_fix]:
80
81 static void do_arm_1176_cache_alias_workaround() {}
82
83 //---------------------------------------------------------------------------
84 IMPLEMENTATION [arm]:
85
86 #include "kmem_space.h"
87 #include "pagetable.h"
88
89 void
90 map_1mb(void *pd, Address va, Address pa, bool cache, bool local)
91 {
92   Unsigned32 *const p = (Unsigned32*)pd;
93   p[va >> 20] = (pa & 0xfff00000)
94                 | (cache ? Section_cachable : Section_no_cache)
95                 | (local ? Section_local : Section_global);
96 }
97
98 // This is a template so that we can have the static_assertion, checking the
99 // right value at compile time. At runtime we probably won't see anything
100 // as this also affects the UART mapping.
101 template< Address PA >
102 static void inline
103 map_dev(void *pd, unsigned va_slotnr)
104 {
105   static_assert(PA == Invalid_address || (PA & ~0xfff00000) == 0, "Physical address must be 2^20 aligned");
106   if (PA != Invalid_address)
107     map_1mb(pd, Mem_layout::Registers_map_start + va_slotnr * 0x100000, PA,
108             false, false);
109 }
110
111 asm
112 (
113 ".section .text.init,#alloc,#execinstr \n"
114 ".global _start                        \n"
115 "_start:                               \n"
116 "     ldr sp, __init_data              \n"
117 "     bl        bootstrap_main         \n"
118
119 "__init_data:                          \n"
120 ".long _stack                          \n"
121 ".previous                             \n"
122 ".section .bss                         \n"
123 "       .space  2048                   \n"
124 "_stack:                               \n"
125 ".previous                             \n"
126 );
127
128
129 #include "mmu.h"
130
131 #include "globalconfig.h"
132
133 extern char bootstrap_bss_start[];
134 extern char bootstrap_bss_end[];
135 extern char __bss_start[];
136 extern char __bss_end[];
137
138 enum
139 {
140   Virt_ofs = Mem_layout::Sdram_phys_base - Mem_layout::Map_base,
141 };
142
143 extern "C" void bootstrap_main()
144 {
145   extern char kernel_page_directory[];
146   void *const page_dir = kernel_page_directory + Virt_ofs;
147
148   Address va, pa;
149   // map sdram linear from 0xf0000000
150   for (va = Mem_layout::Map_base, pa = Mem_layout::Sdram_phys_base;
151        va < Mem_layout::Map_base + (4 << 20); va += 0x100000, pa += 0x100000)
152     map_1mb(page_dir, va, pa, true, false);
153
154   // map sdram 1:1
155   for (va = Mem_layout::Sdram_phys_base;
156        va < Mem_layout::Sdram_phys_base + (4 << 20); va += 0x100000)
157     map_1mb(page_dir, va, va, true, true);
158
159   map_hw(page_dir);
160
161   unsigned domains      = 0x55555555; // client for all domains
162   unsigned control      = Config::Cache_enabled
163                           ? Cpu::Cp15_c1_cache_enabled : Cpu::Cp15_c1_cache_disabled;
164
165   Mmu<Cache_flush_area, true>::flush_cache();
166
167   extern char _start_kernel[];
168
169   do_arm_1176_cache_alias_workaround();
170   set_asid();
171
172   asm volatile (
173       "mcr p15, 0, %[null], c7, c10, 4\n" // dsb
174       "mcr p15, 0, %[null], c8, c7, 0 \n" // tlb flush
175       "mcr p15, 0, %[null], c7, c10, 4\n" // dsb
176       "mcr p15, 0, %[doms], c3, c0    \n" // domains
177       "mcr p15, 0, %[pdir], c2, c0    \n" // pdbr
178       "mcr p15, 0, %[control], c1, c0 \n" // control
179
180       "mrc p15, 0, r0, c2, c0, 0      \n" // arbitrary read of cp15
181       "mov r0, r0                     \n" // wait for result
182       "sub pc, pc, #4                 \n"
183
184       "mov pc, %[start]               \n"
185       : :
186       [pdir]    "r"((Mword)page_dir | Page_table::Ttbr_bits),
187       [doms]    "r"(domains),
188       [control] "r"(control),
189       [start]   "r"(_start_kernel),
190       [null]    "r"(0)
191       : "r0"
192       );
193
194   while(1)
195     ;
196 }