INTERFACE [sparc]:
#include <cstddef>

//---------------------------------------------------------------------------
IMPLEMENTATION [sparc]:

#include <cstdlib>
#include <cstdio>
#include <cstring>

#include <cxx/defensive>

#include "config.h"
#include "globals.h"
#include "kip_init.h"
#include "kdb_ke.h"
#include "kernel_thread.h"
#include "kernel_task.h"
#include "kernel_console.h"
#include "processor.h"
#include "reset.h"
#include "space.h"
#include "terminate.h"
#include "thread_state.h"

static int exit_question_active = 0;

extern "C" [[noreturn]] void
_exit(int)
{
  if (exit_question_active)
    platform_reset();

  while (1)
    {
      Proc::halt();
      Proc::pause();
    }
}


static void exit_question()
{
  exit_question_active = 1;

  while (1)
    {
      puts("\nReturn reboots, \"k\" enters L4 kernel debugger...");

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

      if (c == 'k' || c == 'K')
	{
	  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[0m");
	  cxx::check_noreturn<platform_reset>();
	}
    }
}

int main()
{
  // caution: no stack variables in this function because we're going
  // to change the stack pointer!

  // make some basic initializations, then create and run the kernel
  // thread
  set_exit_question(&exit_question);

  // disallow all interrupts before we selectively enable them
  //  pic_disable_all();

  // create kernel thread
  Kernel_thread *kernel = Kernel_thread::create_for_boot_cpu();
  assert((reinterpret_cast<>Mword>(kernel->init_stack()) & 7) == 0);

  Mem_unit::tlb_flush();

  // switch to stack of kernel thread and bootstrap the kernel
  asm volatile
    ("  mov %0, %%sp         \n"  // switch stack
     "  ba  call_bootstrap   \n"
     "   mov %1, %%o0        \n"  // push "this" pointer
     : : "r" (kernel->init_stack()), "r" (kernel) : "memory");

  // No return from Kernel_thread::bootstrap().
  __builtin_unreachable();
}
