示例#1
0
文件: os.cpp 项目: binape/IncludeOS
void OS::start() {

  // Initialize serial port
  com1.init();

  // Print a fancy header
  FILLINE('=');
  CAPTION("#include<os> // Literally\n");
  FILLINE('=');

  debug("\t[*] OS class started\n");
  srand(time(NULL));

  // Heap
  extern caddr_t heap_end;
  extern char    _end;

  MYINFO("Heap start: @ %p", heap_end);
  MYINFO("Current end is: @ %p", &_end);

  atexit(default_exit);

  // Set up interrupt handlers
  IRQ_manager::init();

  // Initialize the Interval Timer
  hw::PIT::init();

  // Initialize PCI devices
  PCI_manager::init();

  /** Estimate CPU frequency

      MYINFO("Estimating CPU-frequency");
      INFO2("|");
      INFO2("+--(10 samples, %f sec. interval)",
      (hw::PIT::frequency() / _cpu_sampling_freq_divider_).count());
      INFO2("|");

      // TODO: Debug why actual measurments sometimes causes problems. Issue #246.
      cpu_mhz_ = hw::PIT::CPUFrequency();

      INFO2("+--> %f MHz", cpu_mhz_.count());

  **/

  MYINFO("Starting %s", Service::name().c_str());
  FILLINE('=');

  // Everything is ready
  Service::start();

  event_loop();
}
示例#2
0
void OS::start(uint32_t boot_magic, uint32_t boot_addr) {

  atexit(default_exit);
  default_stdout_handlers();

  // Print a fancy header
  FILLINE('=');
  CAPTION("#include<os> // Literally\n");
  FILLINE('=');

  auto esp = get_cpu_esp();
  MYINFO ("Stack: 0x%x", esp);
  Expects (esp < 0xA0000 and esp > 0x0 and "Stack location OK");

  MYINFO("Boot args: 0x%x (multiboot magic), 0x%x (bootinfo addr)",
         boot_magic, boot_addr);

  MYINFO("Max mem (from linker): %i MiB", reinterpret_cast<size_t>(&_MAX_MEM_MIB_));

  if (boot_magic == MULTIBOOT_BOOTLOADER_MAGIC) {
    OS::multiboot(boot_magic, boot_addr);
  } else {

    // Fetch CMOS memory info (unfortunately this is maximally 10^16 kb)
    auto mem = cmos::meminfo();
    low_memory_size_ = mem.base.total * 1024;
    INFO2("* Low memory: %i Kib", mem.base.total);
    high_memory_size_ = mem.extended.total * 1024;

    // Use memsize provided by Make / linker unless CMOS knows this is wrong
    decltype(high_memory_size_) hardcoded_mem = reinterpret_cast<size_t>(&_MAX_MEM_MIB_ - 0x100000) << 20;
    if (mem.extended.total == 0xffff or hardcoded_mem < mem.extended.total) {
      high_memory_size_ = hardcoded_mem;
      INFO2("* High memory (from linker): %i Kib", high_memory_size_ / 1024);
    } else {
      INFO2("* High memory (from cmos): %i Kib", mem.extended.total);
    }
  }

  MYINFO("Assigning fixed memory ranges (Memory map)");
  auto& memmap = memory_map();

  // @ Todo: The first ~600k of memory is free for use. What can we put there?
  memmap.assign_range({0x0009FC00, 0x0009FFFF,
        "EBDA", "Extended BIOS data area"});
  memmap.assign_range({0x000A0000, 0x000FFFFF,
        "VGA/ROM", "Memory mapped video memory"});
  memmap.assign_range({(uintptr_t)&_LOAD_START_, (uintptr_t)&_end,
        "ELF", "Your service binary including OS"});

  // @note for security we don't want to expose this
  memmap.assign_range({(uintptr_t)&_end + 1, heap_begin - 1,
        "Pre-heap", "Heap randomization area (not for use))"});

  memmap.assign_range({0x8000, 0x9fff, "Statman", "Statistics"});
  memmap.assign_range({0xA000, 0x9fbff, "Kernel / service main stack"});

  // Create ranges for heap and the remaining address space
  // @note : since the maximum size of a span is unsigned (ptrdiff_t) we may need more than one
  uintptr_t addr_max = std::numeric_limits<std::size_t>::max();
  uintptr_t span_max = std::numeric_limits<std::ptrdiff_t>::max();

  // Give the rest of physical memory to heap
  heap_max_ = ((0x100000 + high_memory_size_)  & 0xffff0000) - 1;

  // ...Unless it's more than the maximum for a range
  // @note : this is a stupid way to limit the heap - we'll change it, but not until
  // we have a good solution.
  heap_max_ = std::min(span_max, heap_max_);

  memmap.assign_range({heap_begin, heap_max_,
        "Heap", "Dynamic memory", heap_usage });

  uintptr_t unavail_start = 0x100000 + high_memory_size_;
  size_t interval = std::min(span_max, addr_max - unavail_start) - 1;
  uintptr_t unavail_end = unavail_start + interval;

  while (unavail_end < addr_max){
    INFO2("* Unavailable memory: 0x%x - 0x%x", unavail_start, unavail_end);
    memmap.assign_range({unavail_start, unavail_end,
          "N/A", "Reserved / outside physical range" });
    unavail_start = unavail_end + 1;
    interval = std::min(span_max, addr_max - unavail_start);
    // Increment might wrapped around
    if (unavail_start > unavail_end + interval or unavail_start + interval == addr_max){
      INFO2("* Last chunk of memory: 0x%x - 0x%x", unavail_start, addr_max);
      memmap.assign_range({unavail_start, addr_max,
            "N/A", "Reserved / outside physical range" });
      break;
    }

    unavail_end += interval;
  }


  MYINFO("Printing memory map");

  for (const auto &i : memory_map())
    INFO2("* %s",i.second.to_string().c_str());

  // Set up interrupt and exception handlers
  IRQ_manager::init();

  // read ACPI tables
  hw::ACPI::init();

  // setup APIC, APIC timer, SMP etc.
  hw::APIC::init();

  // enable interrupts
  INFO("BSP", "Enabling interrupts");
  IRQ_manager::enable_interrupts();

  // Initialize the Interval Timer
  hw::PIT::init();

  // Initialize PCI devices
  PCI_manager::init();

  // Print registered devices
  hw::Devices::print_devices();

  // Estimate CPU frequency
  MYINFO("Estimating CPU-frequency");
  INFO2("|");
  INFO2("+--(10 samples, %f sec. interval)",
        (hw::PIT::frequency() / _cpu_sampling_freq_divider_).count());
  INFO2("|");

  // TODO: Debug why actual measurments sometimes causes problems. Issue #246.
  cpu_mhz_ = hw::PIT::CPU_frequency();
  INFO2("+--> %f MHz", cpu_mhz_.count());

  // cpu_mhz must be known before we can start timer system
  /// initialize timers hooked up to APIC timer
  Timers::init(
    // timer start function
    hw::APIC_Timer::oneshot,
    // timer stop function
    hw::APIC_Timer::stop);

  // initialize BSP APIC timer
  hw::APIC_Timer::init(
  [] {
    // set final interrupt handler
    hw::APIC_Timer::set_handler(Timers::timers_handler);
    // signal that kernel is done with everything
    Service::ready();
    // signal ready
    // NOTE: this executes the first timers, so we
    // don't want to run this before calling Service ready
    Timers::ready();
  });

  // Realtime/monotonic clock
  RTC::init();
  booted_at_ = RTC::now();

  // sleep statistics
  os_cycles_hlt = &Statman::get().create(
      Stat::UINT64, std::string("cpu0.cycles_hlt")).get_uint64();
  os_cycles_total = &Statman::get().create(
      Stat::UINT64, std::string("cpu0.cycles_total")).get_uint64();

  // Trying custom initialization functions
  MYINFO("Calling custom initialization functions");
  for (auto init : custom_init_) {
    INFO2("* Calling %s", init.name_);
    try{
      init.func_();
    } catch(std::exception& e){
      MYINFO("Exception thrown when calling custom init: %s", e.what());
    } catch(...){
      MYINFO("Unknown exception when calling custom initialization function");
    }
  }
  // Everything is ready
  MYINFO("Starting %s", Service::name().c_str());
  FILLINE('=');
  // initialize random seed based on cycles since start
  srand(cycles_since_boot() & 0xFFFFFFFF);
  // begin service start
  Service::start(Service::command_line());

  event_loop();
}
示例#3
0
void OS::start(uint32_t boot_magic, uint32_t boot_addr)
{
  OS::cmdline = Service::binary_name();

  // Initialize stdout handlers
  if(os_default_stdout) {
    OS::add_stdout(&OS::default_stdout);
  }

  PROFILE("OS::start");
  // Print a fancy header
  CAPTION("#include<os> // Literally");

  MYINFO("Stack: %p", get_cpu_esp());
  MYINFO("Boot magic: 0x%x, addr: 0x%x", boot_magic, boot_addr);

  // Call global ctors
  PROFILE("Global constructors");
  __libc_init_array();

  // PAGING //
  PROFILE("Enable paging");
  extern void __arch_init_paging();
  __arch_init_paging();

  // BOOT METHOD //
  PROFILE("Multiboot / legacy");
  OS::memory_end_ = 0;
  // Detect memory limits etc. depending on boot type
  if (boot_magic == MULTIBOOT_BOOTLOADER_MAGIC) {
    OS::multiboot(boot_addr);
  } else {

    if (is_softreset_magic(boot_magic) && boot_addr != 0)
        OS::resume_softreset(boot_addr);

    OS::legacy_boot();
  }
  assert(OS::memory_end_ != 0);
  // Give the rest of physical memory to heap
  OS::heap_max_ = OS::memory_end_;

  /// STATMAN ///
  PROFILE("Statman");
  /// initialize on page 9, 8 pages in size
  Statman::get().init(0x8000, 0x8000);

  PROFILE("Memory map");
  // Assign memory ranges used by the kernel
  auto& memmap = memory_map();
  MYINFO("Assigning fixed memory ranges (Memory map)");

  memmap.assign_range({0x8000, 0xffff, "Statman"});
#if defined(ARCH_x86_64)
  /**
   * TODO: Map binary parts using mem::map instead of assigning ranges directly
   * e.g. the .text segment is now mapped individually by __arch_init_paging
   */
  memmap.assign_range({0x1000, 0x6fff, "Pagetables"});
  memmap.assign_range({0x10000, 0x9d3ff, "Stack"});
#elif defined(ARCH_i686)
  memmap.assign_range({0x10000, 0x9d3ff, "Stack"});
#endif

  assert(::heap_begin != 0x0 and OS::heap_max_ != 0x0);
  // @note for security we don't want to expose this
  memmap.assign_range({(uintptr_t)&_end, ::heap_begin - 1,
        "Pre-heap"});

  uintptr_t span_max = std::numeric_limits<std::ptrdiff_t>::max();
  uintptr_t heap_range_max_ = std::min(span_max, OS::heap_max_);

  MYINFO("Assigning heap");
  memmap.assign_range({::heap_begin, heap_range_max_,
        "Dynamic memory", heap_usage });

  MYINFO("Virtual memory map");
  for (const auto &i : memmap)
    INFO2("%s",i.second.to_string().c_str());

  PROFILE("Platform init");
  extern void __platform_init();
  __platform_init();

  PROFILE("RTC init");
  // Realtime/monotonic clock
  RTC::init();
}
示例#4
0
文件: os.cpp 项目: tanisman/IncludeOS
void OS::start(char* _cmdline, uintptr_t mem_size)
{
  // Initialize stdout handlers
  OS::add_stdout(&OS::default_stdout);

  PROFILE("");
  // Print a fancy header
  CAPTION("#include<os> // Literally");

  void* esp = get_cpu_esp();
  MYINFO("Stack: %p", esp);

  /// STATMAN ///
  /// initialize on page 7, 2 pages in size
  Statman::get().init(0x6000, 0x3000);

  OS::cmdline = _cmdline;

  // setup memory and heap end
  OS::memory_end_ = mem_size;
  OS::heap_max_ = OS::memory_end_;

  // Call global ctors
  PROFILE("Global constructors");
  __libc_init_array();


  PROFILE("Memory map");
  // Assign memory ranges used by the kernel
  auto& memmap = memory_map();
  MYINFO("Assigning fixed memory ranges (Memory map)");

  memmap.assign_range({0x500, 0x5fff, "solo5", "solo5"});
  memmap.assign_range({0x6000, 0x8fff, "Statman", "Statistics"});
  memmap.assign_range({0xA000, 0x9fbff, "Stack", "Kernel / service main stack"});
  memmap.assign_range({(uintptr_t)&_LOAD_START_, (uintptr_t)&_end,
        "ELF", "Your service binary including OS"});

  Expects(::heap_begin and heap_max_);
  // @note for security we don't want to expose this
  memmap.assign_range({(uintptr_t)&_end + 1, ::heap_begin - 1,
        "Pre-heap", "Heap randomization area"});

  uintptr_t span_max = std::numeric_limits<std::ptrdiff_t>::max();
  uintptr_t heap_range_max_ = std::min(span_max, heap_max_);

  MYINFO("Assigning heap");
  memmap.assign_range({::heap_begin, heap_range_max_,
        "Heap", "Dynamic memory", heap_usage });

  MYINFO("Printing memory map");
  for (const auto &i : memmap)
    INFO2("* %s",i.second.to_string().c_str());

  extern void __platform_init();
  __platform_init();

  MYINFO("Booted at monotonic_ns=%lld walltime_ns=%lld",
         solo5_clock_monotonic(), solo5_clock_wall());

  Solo5_manager::init();

  // We don't need a start or stop function in solo5.
  Timers::init(
    // timer start function
    [] (std::chrono::microseconds) {},
    // timer stop function
    [] () {});

  // Some tests are asserting there is at least one timer that is always ON
  // (the RTC calibration timer). Let's fake some timer so those tests pass.
  Timers::oneshot(std::chrono::hours(1000000), [] (auto) {});

  Timers::ready();
}