2 IMPLEMENTATION[ia32,amd64]:
10 #include "mem_layout.h"
13 #include "trap_state.h"
16 IMPLEMENT inline NEEDS["mem_layout.h"]
18 Kernel_thread::free_initcall_section()
20 // just fill up with invalid opcodes
21 for (unsigned short *i = (unsigned short *) &Mem_layout::initcall_start;
22 i < (unsigned short *) &Mem_layout::initcall_end; i++)
23 *i = 0x0b0f; // UD2 opcode
29 Kernel_thread::bootstrap_arch()
32 // install our slow trap handler
34 nested_trap_handler = Trap_state::base_handler;
35 Trap_state::base_handler = thread_handle_trap;
38 // initialize interrupts
40 if (!Io_apic::active())
42 Irq_chip::hw_chip->reserve(2); // reserve cascade irq
43 Pic::enable_locked(2); // allow cascaded irqs
46 // initialize the profiling timer
47 bool user_irq0 = Koptions::o()->opt(Koptions::F_irq0);
49 if (Config::scheduler_mode == Config::SCHED_PIT && user_irq0)
50 panic("option -irq0 not possible since irq 0 is used for scheduling");
52 if (Config::profiling)
55 panic("options -profile and -irq0 don't mix");
56 if (Config::scheduler_mode == Config::SCHED_PIT)
57 panic("option -profile' not available since PIT is used as "
58 "source for timer tick");
60 Irq_chip::hw_chip->reserve(0); // reserve IRQ 0
62 if (Koptions::o()->opt(Koptions::F_profstart))
67 if (!Io_apic::active() && !user_irq0
68 && !Config::scheduler_mode == Config::SCHED_PIT)
69 Irq_chip::hw_chip->reserve(0); // reserve irq0 even though
75 //--------------------------------------------------------------------------
79 Kernel_thread::boot_app_cpus()
83 //--------------------------------------------------------------------------
84 IMPLEMENTATION [mp && amd64]:
86 PRIVATE inline NOEXPORT
88 Kernel_thread::get_startup_pbdr()
90 // for amd64 we need to make sure that our boot-up page directory is below
91 // 4GB in physical memory
92 static char _boot_pdir_page[Config::PAGE_SIZE] __attribute__((aligned(4096)));
93 memcpy(_boot_pdir_page, Kmem::dir(), sizeof(_boot_pdir_page));
95 return Kmem::virt_to_phys(_boot_pdir_page);
98 //--------------------------------------------------------------------------
99 IMPLEMENTATION [mp && ia32]:
101 PRIVATE inline NOEXPORT
103 Kernel_thread::get_startup_pbdr()
105 return Mem_layout::pmem_to_phys(Kmem::dir());
108 //--------------------------------------------------------------------------
112 Kernel_thread::boot_app_cpus()
114 // sending (INIT-)IPIs on non-MP systems might not work
115 if ( Cpu::boot_cpu()->vendor() == Cpu::Vendor_amd
116 && Cpu::amd_cpuid_mnc() < 2)
119 // where to start the APs for detection of the APIC-IDs
120 extern char _tramp_mp_entry[];
122 // feature enabling flags (esp. cache enabled flag and paging enabled flag)
123 extern volatile Mword _tramp_mp_startup_cr0;
125 // feature enabling flags (esp. needed for big pages)
126 extern volatile Mword _tramp_mp_startup_cr4;
128 // physical address of the page table directory to use
129 extern volatile Address _tramp_mp_startup_pdbr;
131 // pseudo descriptor for the gdt to load
132 extern Pseudo_descriptor _tramp_mp_startup_gdt_pdesc;
136 _tramp_mp_startup_pdbr = get_startup_pbdr();
137 _tramp_mp_startup_cr4 = Cpu::get_cr4();
138 _tramp_mp_startup_cr0 = Cpu::get_cr0();
139 _tramp_mp_startup_gdt_pdesc
140 = Pseudo_descriptor((Address)Cpu::boot_cpu()->get_gdt(), Gdt::gdt_max -1);
142 __asm__ __volatile__ ("" : : : "memory");
145 printf("MP: detecting APs...\n");
147 // broadcast an AP startup via the APIC (let run the self-registration code)
148 tramp_page = (Address)&(_tramp_mp_entry[0]);
150 // Send IPI-Sequency to startup the APs
151 Apic::mp_startup(Cpu::boot_cpu(), Apic::APIC_IPI_OTHERS, tramp_page);