コード例 #1
0
ファイル: main-ia32.cpp プロジェクト: laborjack/L4Re
static
void
exit_question()
{
  Proc::cli();
  exit_question_active = 1;

  Unsigned16 irqs = Pic::disable_all_save();
  if (Config::getchar_does_hlt_works_ok)
    {
      Timer_tick::set_vectors_stop();
      Timer_tick::enable(Cpu_number::boot_cpu()); // hmexit alway on CPU 0
      Proc::sti();
    }

  // make sure that we don't acknowledg the exit question automatically
  Kconsole::console()->change_state(Console::PUSH, 0, ~Console::INENABLED, 0);
  puts("\nReturn reboots, \"k\" enters L4 kernel debugger...");

  char c = Kconsole::console()->getchar();

  if (c == 'k' || c == 'K') 
    {
      Pic::restore_all(irqs);
      kdb_ke("_exit");
    }
  else
    {
      // It may be better to not call all the destruction stuff because of
      // unresolved static destructor dependency problems. So just do the
      // reset at this point.
      puts("\033[1mRebooting.\033[m");
    }
}
コード例 #2
0
/** Page fault handler.
    This handler suspends any ongoing IPC, then sets up page-fault IPC.
    Finally, the ongoing IPC's state (if any) is restored.
    @param pfa page-fault virtual address
    @param error_code page-fault error code.
 */
PRIVATE
bool
Thread::handle_page_fault_pager(Thread_ptr const &_pager,
                                Address pfa, Mword error_code,
                                L4_msg_tag::Protocol protocol)
{
#ifndef NDEBUG
  // do not handle user space page faults from kernel mode if we're
  // already handling a request
  if (EXPECT_FALSE(!PF::is_usermode_error(error_code)
		   && thread_lock()->test() == Thread_lock::Locked))
    {
      kdb_ke("Fiasco BUG: page fault, under lock");
      panic("page fault in locked operation");
    }
#endif

  if (EXPECT_FALSE((state() & Thread_alien)))
    return false;

  Lock_guard<Cpu_lock> guard(&cpu_lock);

  unsigned char rights;
  Kobject_iface *pager = _pager.ptr(space(), &rights);

  if (!pager)
    {
      WARN("CPU%d: Pager of %lx is invalid (pfa=" L4_PTR_FMT
	   ", errorcode=" L4_PTR_FMT ") to %lx (pc=%lx)\n",
	   current_cpu(), dbg_id(), pfa, error_code,
           _pager.raw(), regs()->ip());


      LOG_TRACE("Page fault invalid pager", "pf", this,
                __fmt_page_fault_invalid_pager,
                Log_pf_invalid *l = tbe->payload<Log_pf_invalid>();
                l->cap_idx = _pager.raw();
                l->err     = error_code;
                l->pfa     = pfa);

      pager = this; // block on ourselves
    }
コード例 #3
0
IMPLEMENT
void*
Vmem_alloc::page_alloc (void *address, Zero_fill zf, unsigned mode)
{
  void *vpage = 0;
  Address page;

  vpage = Mapped_allocator::allocator()->alloc(Config::PAGE_SHIFT);

  if (EXPECT_FALSE(!vpage))
    return 0;

  // insert page into master page table
  Pdir::Iter e = Kmem::kdir->walk(Virt_addr(address), 100,
                                  Mapped_allocator::allocator());
  if (EXPECT_FALSE(e.e->valid()))
    {
      kdb_ke("page_alloc: address already mapped");
      goto error;
    }

  if (e.shift() != Config::PAGE_SHIFT)
    goto error;

  if (zf == ZERO_FILL)
    memset(vpage, 0, Config::PAGE_SIZE);

  page = Mem_layout::pmem_to_phys((Address)vpage);

  *e.e = page | Pt_entry::Writable | Pt_entry::Dirty
    | Pt_entry::Valid | Pt_entry::Referenced | Pt_entry::global();
  page_map (address, 0, zf, page);

  if (mode & User)
    e.e->add_attr(Pt_entry::User);

  return address;

error:
  Mapped_allocator::allocator()->free(Config::PAGE_SHIFT, vpage); // 2^0 = 1 page
  return 0;
}
コード例 #4
0
// the kernel bootstrap routine
PUBLIC
void 
kernel_thread_t::bootstrap()
{
  // Initializations done -- helping_lock_t can now use helping lock
  helping_lock_t::threading_system_active = true;

  //
  // set up my own thread control block
  //
  state_change (0, Thread_running);

  sched()->set_prio (config::kernel_prio);
  sched()->set_mcp (config::kernel_mcp);
  sched()->set_timeslice (config::default_time_slice);
  sched()->set_ticks_left (config::default_time_slice);

  present_next = present_prev = this;
  ready_next = ready_prev = this;

  //
  // set up class variables
  //
  for (int i = 0; i < 256; i++) prio_next[i] = prio_first[i] = 0;
  prio_next[config::kernel_prio] = prio_first[config::kernel_prio] = this;
  prio_highest = config::kernel_prio;

  timeslice_ticks_left = config::default_time_slice;
  timeslice_owner = this;

  // 
  // install our slow trap handler
  //
  nested_trap_handler = base_trap_handler;
  base_trap_handler = thread_handle_trap;

  // 
  // initialize FPU
  // 
  set_ts();			// FPU ops -> exception

  //
  // initialize interrupts
  //
  irq_t::lookup(2)->alloc(this, false); // reserve cascade irq
  irq_t::lookup(8)->alloc(this, false); // reserve timer irq

  pic_enable_irq(2);		// allow cascaded irqs

  // set up serial console
  if (! strstr(kmem::cmdline(), " -I-") 
      && !strstr(kmem::cmdline(), " -irqcom"))
    {
      int com_port = console::serial_com_port;
      int com_irq = com_port & 1 ? 4 : 3;

      irq_t::lookup(com_irq)->alloc(this, false); // the remote-gdb interrupt
      pic_enable_irq(com_irq);

      // for some reason, we have to re-enable the com irq here
      if (config::serial_esc)
	com_cons_enable_receive_interrupt();
    }

  // initialize the profiling timer
  bool user_irq0 = strstr(kmem::cmdline(), "irq0");

  if (config::profiling)
    {
      if (user_irq0)
	{
	  kdb_ke("options `-profile' and `-irq0' don't mix "
		  "-- disabling `-irq0'");
	}
      irq_t::lookup(0)->alloc(this, false);

      profile::init();

      if (strstr(kmem::cmdline(), " -profstart"))
	profile::start();
    }
  else if (! user_irq0)
    irq_t::lookup(0)->alloc(this, false); // reserve irq0 even though
                                          // we don't use it

  // 
  // set up timer interrupt (~ 1ms)
  //
  while (rtcin(RTC_STATUSA) & RTCSA_TUP) ; // wait till RTC ready
  rtcout(RTC_STATUSA, RTCSA_DIVIDER | RTCSA_1024); // 1024 Hz
  // set up 1024 Hz interrupt
  rtcout(RTC_STATUSB, rtcin(RTC_STATUSB) | RTCSB_PINTR | RTCSB_SQWE); 
  rtcin(RTC_INTR);		// reset

  pic_enable_irq(8);		// allow this interrupt

  //
  // set PCE-Flag in CR4 to enable read of performace measurement counters
  // in usermode. PMC were introduced in Pentium MMX and PPro processors.
  //
  #ifndef CPUF_MMX
  #define CPUF_MMX 0x00800000
  #endif
  if(strncmp(cpu.vendor_id, "GenuineIntel", 12) == 0
     && (cpu.family == CPU_FAMILY_PENTIUM_PRO ||
	 cpu.feature_flags & CPUF_MMX))
    {
      set_cr4(get_cr4() | CR4_PCE);
    }
  
  //
  // allow the boot task to create more tasks
  //
  for (unsigned i = config::boot_taskno + 1; 
       i < space_index_t::max_space_number;
       i++)
    {
      check(space_index_t(i).set_chief(space_index(), 
				       space_index_t(config::boot_taskno)));
    }

  //
  // create sigma0
  //

  // sigma0's chief is the boot task
  space_index_t(config::sigma0_id.id.task).
    set_chief(space_index(), space_index_t(config::sigma0_id.id.chief));

  sigma0 = new space_t(config::sigma0_id.id.task);
  sigma0_thread = 
    new (&config::sigma0_id) thread_t (sigma0, &config::sigma0_id, 
				       config::sigma0_prio, 
				       config::sigma0_mcp);
  
  // push address of kernel info page to sigma0's stack
  vm_offset_t esp = kmem::info()->sigma0_esp;

  * reinterpret_cast<vm_offset_t*>(kmem::phys_to_virt(--esp)) 
    = kmem::virt_to_phys(kmem::info());

  sigma0_thread->initialize(kmem::info()->sigma0_eip, esp,
			    0, 0);

  //
  // create the boot task
  //

  // the boot task's chief is the boot task itself
  space_index_t(config::boot_id.id.task).
    set_chief(space_index(), space_index_t(config::boot_id.id.chief));

  space_t *boot = new space_t(config::boot_id.id.task);
  thread_t *boot_thread
    = new (&config::boot_id) thread_t (boot, &config::boot_id, 
				       config::boot_prio, 
				       config::boot_mcp);

  boot_thread->initialize(0x200000,
			  0x200000,
			  sigma0_thread, 0);

  //
  // the idle loop
  //
  for (;;) 
    {
      // printf("I");

      sti();			// enable irqs, otherwise idling is fatal

      if (config::hlt_works_ok)
	asm("hlt");		// stop the CPU, waiting for an int

      while (ready_next != this) // are there any other threads ready?
	schedule();
    }
}