예제 #1
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 "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;
}
예제 #2
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;
}
예제 #3
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();
}