]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/ia32/main-ia32.cpp
6d79716684e72aacdfbcbe860c8418fdb1b97881
[l4.git] / kernel / fiasco / src / kern / ia32 / main-ia32.cpp
1 /*
2  * Fiasco-IA32/AMD64
3  * Architecture specific main startup/shutdown code
4  */
5
6 IMPLEMENTATION[ia32,amd64]:
7
8 #include <cstdio>
9 #include <cstring>
10 #include <cstdlib>
11 #include "config.h"
12 #include "io.h"
13 #include "idt.h"
14 #include "kdb_ke.h"
15 #include "kernel_console.h"
16 #include "koptions.h"
17 #include "pic.h"
18 #include "processor.h"
19 #include "reset.h"
20 #include "timer.h"
21 #include "timer_tick.h"
22 #include "terminate.h"
23
24 static int exit_question_active;
25
26
27 extern "C" void __attribute__ ((noreturn))
28 _exit(int)
29 {
30   if (exit_question_active)
31     platform_reset();
32
33   while (1)
34     {
35       Proc::halt();
36       Proc::pause();
37     }
38 }
39
40
41 static
42 void
43 exit_question()
44 {
45   Proc::cli();
46   exit_question_active = 1;
47
48   Pic::Status irqs = Pic::disable_all_save();
49   if (Config::getchar_does_hlt_works_ok)
50     {
51       Timer_tick::set_vectors_stop();
52       Timer_tick::enable(0); // hmexit alway on CPU 0
53       Proc::sti();
54     }
55
56   // make sure that we don't acknowledg the exit question automatically
57   Kconsole::console()->change_state(Console::PUSH, 0, ~Console::INENABLED, 0);
58   puts("\nReturn reboots, \"k\" enters L4 kernel debugger...");
59
60   char c = Kconsole::console()->getchar();
61
62   if (c == 'k' || c == 'K') 
63     {
64       Pic::restore_all(irqs);
65       kdb_ke("_exit");
66     }
67   else
68     {
69       // It may be better to not call all the destruction stuff because of
70       // unresolved static destructor dependency problems. So just do the
71       // reset at this point.
72       puts("\033[1mRebooting.\033[m");
73     }
74 }
75
76 void
77 main_arch()
78 {
79   // console initialization
80   set_exit_question(&exit_question);
81
82   //Pic::disable_all_save();
83 }
84
85
86 //------------------------------------------------------------------------
87 IMPLEMENTATION[(ia32,amd64) && mp]:
88
89 #include <cstdio>
90 #include "apic.h"
91 #include "app_cpu_thread.h"
92 #include "config.h"
93 #include "cpu.h"
94 #include "div32.h"
95 #include "fpu.h"
96 #include "globals.h"
97 #include "ipi.h"
98 #include "kernel_task.h"
99 #include "processor.h"
100 #include "per_cpu_data_alloc.h"
101 #include "perf_cnt.h"
102 #include "spin_lock.h"
103 #include "utcb_init.h"
104
105 int FIASCO_FASTCALL boot_ap_cpu() __asm__("BOOT_AP_CPU");
106
107 int FIASCO_FASTCALL boot_ap_cpu()
108 {
109   unsigned _cpu = Apic::find_cpu(Apic::get_id());
110   bool cpu_is_new = false;
111   static unsigned last_cpu; // keep track of the last cpu ever appeared
112   if (_cpu == ~0U)
113     {
114       _cpu = ++last_cpu; // 0 is the boot cpu, so pre increment
115       cpu_is_new = true;
116     }
117
118   if (cpu_is_new && !Per_cpu_data_alloc::alloc(_cpu))
119     {
120       extern Spin_lock<Mword> _tramp_mp_spinlock;
121       printf("CPU allocation failed for CPU%u, disabling CPU.\n", _cpu);
122       _tramp_mp_spinlock.clear();
123       while (1)
124         Proc::halt();
125     }
126   Per_cpu_data::run_ctors(_cpu);
127   Cpu &cpu = Cpu::cpus.cpu(_cpu);
128
129   Kmem::init_cpu(cpu);
130   Idt::load();
131
132   Apic::init_ap();
133   Apic::apic.cpu(_cpu).construct();
134   Ipi::init(_cpu);
135   Timer::init(_cpu);
136   Apic::check_still_getting_interrupts();
137
138
139   // caution: no stack variables in this function because we're going
140   // to change the stack pointer!
141   cpu.print();
142   cpu.show_cache_tlb_info("");
143
144   if (Koptions::o()->opt(Koptions::F_loadcnt))
145     Perf_cnt::init_ap();
146
147   puts("");
148
149   // create kernel thread
150   Kernel_thread *kernel = App_cpu_thread::may_be_create(_cpu, cpu_is_new);
151
152   main_switch_ap_cpu_stack(kernel);
153   return 0;
154 }