4 //---------------------------------------------------------------------------
13 #include "initcalls.h"
14 #include "kmem_alloc.h"
17 #include "kernel_thread.h"
18 #include "kernel_task.h"
19 #include "kernel_console.h"
22 #include "terminate.h"
24 #include "processor.h"
26 static int exit_question_active = 0;
28 extern "C" void __attribute__ ((noreturn))
31 if (exit_question_active)
42 static void exit_question()
44 exit_question_active = 1;
48 puts("\nReturn reboots, \"k\" enters L4 kernel debugger...");
50 char c = Kconsole::console()->getchar();
52 if (c == 'k' || c == 'K')
58 // it may be better to not call all the destruction stuff
59 // because of unresolved static destructor dependency
61 // SO just do the reset at this point.
62 puts("\033[1mRebooting...\033[0m");
72 // caution: no stack variables in this function because we're going
73 // to change the stack pointer!
75 // make some basic initializations, then create and run the kernel
77 set_exit_question(&exit_question);
79 printf("%s\n", Kip::k()->version_string());
81 // disallow all interrupts before we selectively enable them
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)));
89 Mem_unit::tlb_flush();
91 // switch to stack of kernel thread and bootstrap the kernel
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));
99 //------------------------------------------------------------------------
100 IMPLEMENTATION[arm && mp]:
106 #include "app_cpu_thread.h"
108 #include "per_cpu_data_alloc.h"
109 #include "perf_cnt.h"
111 #include "platform_control.h"
112 #include "spin_lock.h"
114 #include "utcb_init.h"
116 int boot_ap_cpu() __asm__("BOOT_AP_CPU");
120 static Cpu_number last_cpu; // keep track of the last cpu ever appeared
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())
126 _cpu = ++last_cpu; // 0 is the boot cpu, so pre increment
130 assert (_cpu != Cpu_number::boot_cpu());
132 if (cpu_is_new && !Per_cpu_data_alloc::alloc(_cpu))
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();
139 // FIXME: use a Platform_control API to stop the CPU
144 Per_cpu_data::run_ctors(_cpu);
145 Cpu &cpu = Cpu::cpus.cpu(_cpu);
149 Thread::init_per_cpu(_cpu);
150 Platform_control::init(_cpu);
155 // create kernel thread
156 Kernel_thread *kernel = App_cpu_thread::may_be_create(_cpu, cpu_is_new);
158 // switch to stack of kernel thread and continue thread init
160 (" mov sp,%0 \n" // switch stack
161 " mov r0,%1 \n" // push "this" pointer
162 " bl call_ap_bootstrap \n"
164 : "r" (kernel->init_stack()), "r" (kernel));