]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/arm/main.cpp
update
[l4.git] / kernel / fiasco / src / kern / arm / main.cpp
1 INTERFACE [arm]:
2 #include <cstddef>
3
4 //---------------------------------------------------------------------------
5 IMPLEMENTATION [arm]:
6
7 #include <cstdlib>
8 #include <cstdio>
9 #include <cstring>
10
11 #include "config.h"
12 #include "globals.h"
13 #include "initcalls.h"
14 #include "kmem_alloc.h"
15 #include "kip_init.h"
16 #include "kdb_ke.h"
17 #include "kernel_thread.h"
18 #include "kernel_task.h"
19 #include "kernel_console.h"
20 #include "reset.h"
21 #include "space.h"
22 #include "terminate.h"
23
24 #include "processor.h"
25
26 static int exit_question_active = 0;
27
28 extern "C" void __attribute__ ((noreturn))
29 _exit(int)
30 {
31   if (exit_question_active)
32     platform_reset();
33
34   while (1)
35     {
36       Proc::halt();
37       Proc::pause();
38     }
39 }
40
41
42 static void exit_question()
43 {
44   exit_question_active = 1;
45
46   while (1)
47     {
48       puts("\nReturn reboots, \"k\" enters L4 kernel debugger...");
49
50       char c = Kconsole::console()->getchar();
51
52       if (c == 'k' || c == 'K')
53         {
54           kdb_ke("_exit");
55         }
56       else
57         {
58           // it may be better to not call all the destruction stuff
59           // because of unresolved static destructor dependency
60           // problems.
61           // SO just do the reset at this point.
62           puts("\033[1mRebooting...\033[0m");
63           platform_reset();
64           break;
65         }
66     }
67 }
68
69 void
70 kernel_main()
71 {
72   // caution: no stack variables in this function because we're going
73   // to change the stack pointer!
74
75   // make some basic initializations, then create and run the kernel
76   // thread
77   set_exit_question(&exit_question);
78
79   printf("%s\n", Kip::k()->version_string());
80
81   // disallow all interrupts before we selectively enable them
82   //  pic_disable_all();
83
84   // create kernel thread
85   static Kernel_thread *kernel = new (Ram_quota::root) Kernel_thread;
86   Task *const ktask = Kernel_task::kernel_task();
87   check(kernel->bind(ktask, User<Utcb>::Ptr(0)));
88
89   Mem_unit::tlb_flush();
90
91   // switch to stack of kernel thread and bootstrap the kernel
92   asm volatile
93     ("  mov sp,%0               \n"     // switch stack
94      "  mov r0,%1               \n"     // push "this" pointer
95      "  bl call_bootstrap     \n"
96      : : "r" (kernel->init_stack()), "r" (kernel));
97 }
98
99 //------------------------------------------------------------------------
100 IMPLEMENTATION[arm && mp]:
101
102 #include <cstdio>
103 #include "config.h"
104 #include "cpu.h"
105 #include "globals.h"
106 #include "app_cpu_thread.h"
107 #include "ipi.h"
108 #include "per_cpu_data_alloc.h"
109 #include "perf_cnt.h"
110 #include "pic.h"
111 #include "platform_control.h"
112 #include "spin_lock.h"
113 #include "timer.h"
114 #include "utcb_init.h"
115
116 int boot_ap_cpu() __asm__("BOOT_AP_CPU");
117
118 int boot_ap_cpu()
119 {
120   static Cpu_number last_cpu; // keep track of the last cpu ever appeared
121
122   Cpu_number _cpu = Cpu::cpus.find_cpu(Cpu::By_phys_id(Proc::cpu_id()));
123   bool cpu_is_new = false;
124   if (_cpu == Cpu_number::nil())
125     {
126       _cpu = ++last_cpu; // 0 is the boot cpu, so pre increment
127       cpu_is_new = true;
128     }
129
130   assert (_cpu != Cpu_number::boot_cpu());
131
132   if (cpu_is_new && !Per_cpu_data_alloc::alloc(_cpu))
133     {
134       extern Spin_lock<Mword> _tramp_mp_spinlock;
135       printf("CPU allocation failed for CPU%u, disabling CPU.\n",
136              cxx::int_value<Cpu_number>(_cpu));
137       _tramp_mp_spinlock.clear();
138
139       // FIXME: use a Platform_control API to stop the CPU
140       while (1)
141         Proc::halt();
142     }
143
144   Per_cpu_data::run_ctors(_cpu);
145   Cpu &cpu = Cpu::cpus.cpu(_cpu);
146   cpu.init();
147
148   Pic::init_ap(_cpu);
149   Thread::init_per_cpu(_cpu);
150   Platform_control::init(_cpu);
151   Ipi::init(_cpu);
152   Timer::init(_cpu);
153   Perf_cnt::init_ap();
154
155   // create kernel thread
156   Kernel_thread *kernel = App_cpu_thread::may_be_create(_cpu, cpu_is_new);
157
158   // switch to stack of kernel thread and continue thread init
159   asm volatile
160     ("  mov sp,%0               \n"     // switch stack
161      "  mov r0,%1               \n"     // push "this" pointer
162      "  bl call_ap_bootstrap    \n"
163      :
164      :  "r" (kernel->init_stack()), "r" (kernel));
165   return 0;
166 }