示例#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
文件: os.cpp 项目: binape/IncludeOS
void OS::event_loop() {
  FILLINE('=');
  printf(" IncludeOS %s\n", version().c_str());
  printf(" +--> Running [ %s ]\n", Service::name().c_str());
  FILLINE('~');

  while (power_) {
    IRQ_manager::notify();
    debug("<OS> Woke up @ t = %li\n", uptime());
  }

  //Cleanup
  //Service::stop();
}
示例#3
0
void OS::event_loop() {
  FILLINE('=');
  printf(" IncludeOS %s\n", version().c_str());
  printf(" +--> Running [ %s ]\n", Service::name().c_str());
  FILLINE('~');

  while (power_) {
    IRQ_manager::get().process_interrupts();
    debug2("OS going to sleep.\n");
    OS::halt();
  }

  // Cleanup
  Service::stop();
  // ACPI shutdown sequence
  hw::ACPI::shutdown();
}
示例#4
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();
}