//------------------------------------------------------------------------ IMPLEMENTATION[(ia32,amd64) && mp]: #include <cstdio> #include "apic.h" #include "app_cpu_thread.h" #include "config.h" #include "cpu.h" #include "div32.h" #include "fpu.h" #include "globals.h" #include "ipi.h" #include "kernel_task.h" #include "processor.h" #include "per_cpu_data_alloc.h" #include "perf_cnt.h" #include "spin_lock.h" #include "utcb_init.h" int FIASCO_FASTCALL boot_ap_cpu(unsigned _cpu) __asm__("BOOT_AP_CPU"); int FIASCO_FASTCALL boot_ap_cpu(unsigned _cpu) { if (!Per_cpu_data_alloc::alloc(_cpu)) { extern Spin_lock<Mword> _tramp_mp_spinlock; printf("CPU allocation failed for CPU%u, disabling CPU.\n", _cpu); _tramp_mp_spinlock.clear(); while (1) Proc::halt(); } Per_cpu_data::run_ctors(_cpu); Cpu &cpu = Cpu::cpus.cpu(_cpu); Kmem::init_cpu(cpu); Idt::load(); Utcb_init::init_ap(cpu); Apic::init_ap(); Ipi::cpu(_cpu).init(); Timer::init(); Apic::check_still_getting_interrupts(); // caution: no stack variables in this function because we're going // to change the stack pointer! cpu.print(); cpu.show_cache_tlb_info(""); if (Koptions::o()->opt(Koptions::F_loadcnt)) Perf_cnt::init_ap(); puts(""); // create kernel thread App_cpu_thread *kernel = new (Ram_quota::root) App_cpu_thread(); set_cpu_of(kernel, _cpu); check(kernel->bind(Kernel_task::kernel_task(), User<Utcb>::Ptr(0))); main_switch_ap_cpu_stack(kernel); return 0; }
//------------------------------------------------------------------------ IMPLEMENTATION[(ia32,amd64) && mp]: #include <cstdio> #include "apic.h" #include "app_cpu_thread.h" #include "config.h" #include "cpu.h" #include "div32.h" #include "fpu.h" #include "globals.h" #include "ipi.h" #include "kernel_task.h" #include "processor.h" #include "per_cpu_data_alloc.h" #include "perf_cnt.h" #include "platform_control.h" #include "spin_lock.h" #include "utcb_init.h" int FIASCO_FASTCALL boot_ap_cpu() __asm__("BOOT_AP_CPU"); int FIASCO_FASTCALL boot_ap_cpu() { Cpu_number _cpu = Apic::find_cpu(Apic::get_id()); bool cpu_is_new = false; static Cpu_number last_cpu; // keep track of the last cpu ever appeared if (_cpu == Cpu_number::nil()) { _cpu = ++last_cpu; // 0 is the boot cpu, so pre increment cpu_is_new = true; } if (cpu_is_new && !Per_cpu_data_alloc::alloc(_cpu)) { extern Spin_lock<Mword> _tramp_mp_spinlock; printf("CPU allocation failed for CPU%u, disabling CPU.\n", cxx::int_value<Cpu_number>(_cpu)); _tramp_mp_spinlock.clear(); while (1) Proc::halt(); } if (cpu_is_new) Per_cpu_data::run_ctors(_cpu); Cpu &cpu = Cpu::cpus.cpu(_cpu); Idt::load(); if (cpu_is_new) { Kmem::init_cpu(cpu); Apic::init_ap(); Apic::apic.cpu(_cpu).construct(_cpu); Ipi::init(_cpu); } else { cpu.pm_resume(); Pm_object::run_on_resume_hooks(_cpu); } Timer::init(_cpu); if (cpu_is_new) { Apic::check_still_getting_interrupts(); Platform_control::init(_cpu); } if (Koptions::o()->opt(Koptions::F_loadcnt)) Perf_cnt::init_ap(); // create kernel thread Kernel_thread *kernel = App_cpu_thread::may_be_create(_cpu, cpu_is_new); main_switch_ap_cpu_stack(kernel, !cpu_is_new); return 0; }
IMPLEMENTATION [mp]: #include <cstdlib> #include <cstdio> #include "config.h" #include "delayloop.h" #include "fpu.h" #include "globals.h" #include "helping_lock.h" #include "kernel_task.h" #include "processor.h" #include "scheduler.h" #include "task.h" #include "thread.h" #include "thread_state.h" #include "timer.h" #include "timer_tick.h" #include "spin_lock.h" PUBLIC static Kernel_thread * App_cpu_thread::may_be_create(Cpu_number cpu, bool cpu_never_seen_before) { if (!cpu_never_seen_before) { kernel_context(cpu)->reset_kernel_sp(); return static_cast<Kernel_thread *>(kernel_context(cpu)); } Kernel_thread *t = new (Ram_quota::root) App_cpu_thread; assert (t); set_cpu_of(t, cpu); check(t->bind(Kernel_task::kernel_task(), User<Utcb>::Ptr(0))); return t; } // the kernel bootstrap routine IMPLEMENT void App_cpu_thread::bootstrap() { extern Spin_lock<Mword> _tramp_mp_spinlock; state_change_dirty(0, Thread_ready); // Set myself ready Fpu::init(cpu(true)); // initialize the current_mem_space function to point to the kernel space Kernel_task::kernel_task()->make_current(); Mem_unit::tlb_flush(); Cpu::cpus.current().set_online(1); _tramp_mp_spinlock.set(1); kernel_context(cpu(true), this); Sched_context::rq.current().set_idle(this->sched()); Rcu::leave_idle(cpu(true)); Timer_tick::setup(cpu(true)); Timer_tick::enable(cpu(true)); enable_tlb(cpu(true)); // Setup initial timeslice Sched_context::rq.current().set_current_sched(sched()); Per_cpu_data::run_late_ctors(cpu(true)); Scheduler::scheduler.trigger_hotplug_event(); cpu_lock.clear(); printf("CPU[%u]: goes to idle loop\n", cxx::int_value<Cpu_number>(cpu(true))); for (;;) idle_op(); }