kinit.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. #include <stdint.h>
  2. #include <sys/utsname.h>
  3. #include <types/allocator.hpp>
  4. #include <types/types.h>
  5. #include <kernel/hw/acpi.hpp>
  6. #include <kernel/hw/pci.hpp>
  7. #include <kernel/interrupt.hpp>
  8. #include <kernel/log.hpp>
  9. #include <kernel/mem/paging.hpp>
  10. #include <kernel/mem/phys.hpp>
  11. #include <kernel/mem/types.hpp>
  12. #include <kernel/process.hpp>
  13. #include <kernel/utsname.hpp>
  14. using constructor = void (*)();
  15. extern "C" constructor const start_ctors, end_ctors;
  16. extern "C" uint64_t BSS_ADDR, BSS_LENGTH;
  17. struct PACKED bootloader_data {
  18. uint32_t meminfo_entry_count;
  19. uint32_t meminfo_entry_length;
  20. // don't forget to add the initial 1m to the total
  21. uint32_t meminfo_1k_blocks;
  22. uint32_t meminfo_64k_blocks;
  23. // meminfo entries
  24. kernel::mem::e820_mem_map_entry meminfo_entries[(1024 - 4 * 4) / 24];
  25. };
  26. namespace kernel::kinit {
  27. static inline void enable_sse() {
  28. asm volatile(
  29. "mov %%cr0, %%rax\n\t"
  30. "and $(~0xc), %%rax\n\t"
  31. "or $0x22, %%rax\n\t"
  32. "mov %%rax, %%cr0\n\t"
  33. "\n\t"
  34. "mov %%cr4, %%rax\n\t"
  35. "or $0x600, %%rax\n\t"
  36. "mov %%rax, %%cr4\n\t"
  37. "fninit\n\t" ::
  38. : "rax");
  39. }
  40. static inline void setup_early_kernel_page_table() {
  41. using namespace kernel::mem::paging;
  42. constexpr auto idx = idx_all(0xffffffffc0200000ULL);
  43. auto pdpt = KERNEL_PAGE_TABLE[std::get<1>(idx)].parse();
  44. auto pd = pdpt[std::get<2>(idx)].parse();
  45. // kernel bss, size 2M
  46. pd[std::get<3>(idx)].set(PA_KERNEL_DATA_HUGE, KERNEL_BSS_HUGE_PAGE);
  47. // clear kernel bss
  48. memset((void*)BSS_ADDR, 0x00, BSS_LENGTH);
  49. }
  50. extern "C" char KIMAGE_PAGES[];
  51. static inline void setup_buddy(uintptr_t addr_max) {
  52. using namespace kernel::mem;
  53. using namespace kernel::mem::paging;
  54. constexpr auto idx = idx_all(0xffffff8040000000ULL);
  55. addr_max += 0xfff;
  56. addr_max >>= 12;
  57. int count = (addr_max * sizeof(page) + 0x200000 - 1) / 0x200000;
  58. auto KIMAGE_PAGES_VALUE = (size_t)KIMAGE_PAGES;
  59. pfn_t real_start_pfn = KERNEL_IMAGE_PADDR + KIMAGE_PAGES_VALUE * 0x1000;
  60. pfn_t aligned_start_pfn = real_start_pfn + 0x200000 - 1;
  61. aligned_start_pfn &= ~0x1fffff;
  62. pfn_t saved_start_pfn = aligned_start_pfn;
  63. memset(physaddr<void>{KERNEL_PD_STRUCT_PAGE_ARR}, 0x00, 4096);
  64. auto pdpte = KERNEL_PAGE_TABLE[std::get<1>(idx)].parse()[std::get<2>(idx)];
  65. pdpte.set(PA_KERNEL_PAGE_TABLE, KERNEL_PD_STRUCT_PAGE_ARR);
  66. auto pd = pdpte.parse();
  67. for (int i = 0; i < count; ++i, aligned_start_pfn += 0x200000)
  68. pd[std::get<3>(idx) + i].set(PA_KERNEL_DATA_HUGE, aligned_start_pfn);
  69. PAGE_ARRAY = (page*)0xffffff8040000000ULL;
  70. memset(PAGE_ARRAY, 0x00, addr_max * sizeof(page));
  71. for (int i = 0; i < (int)info::e820_entry_count; ++i) {
  72. auto& ent = info::e820_entries[i];
  73. if (ent.type != 1) // type == 1: free area
  74. continue;
  75. mark_present(ent.base, ent.base + ent.len);
  76. auto start = ent.base;
  77. auto end = start + ent.len;
  78. if (end <= aligned_start_pfn)
  79. continue;
  80. if (start < aligned_start_pfn)
  81. start = aligned_start_pfn;
  82. if (start > end)
  83. continue;
  84. mem::paging::create_zone(start, end);
  85. }
  86. // unused space
  87. create_zone(0x9000, 0x80000);
  88. create_zone(0x100000, 0x200000);
  89. create_zone(real_start_pfn, saved_start_pfn);
  90. }
  91. static inline void save_memory_info(bootloader_data* data) {
  92. kernel::mem::info::memory_size = 1ULL * 1024ULL * 1024ULL + // initial 1M
  93. 1024ULL * data->meminfo_1k_blocks +
  94. 64ULL * 1024ULL * data->meminfo_64k_blocks;
  95. kernel::mem::info::e820_entry_count = data->meminfo_entry_count;
  96. kernel::mem::info::e820_entry_length = data->meminfo_entry_length;
  97. memcpy(kernel::mem::info::e820_entries, data->meminfo_entries,
  98. sizeof(kernel::mem::info::e820_entries));
  99. }
  100. extern "C" void rust_kinit(uintptr_t early_kstack_vaddr);
  101. extern "C" void NORETURN kernel_init(bootloader_data* data) {
  102. enable_sse();
  103. setup_early_kernel_page_table();
  104. save_memory_info(data);
  105. uintptr_t addr_max = 0;
  106. for (int i = 0; i < (int)kernel::mem::info::e820_entry_count; ++i) {
  107. auto& ent = kernel::mem::info::e820_entries[i];
  108. if (ent.type != 1)
  109. continue;
  110. addr_max = std::max(addr_max, ent.base + ent.len);
  111. }
  112. setup_buddy(addr_max);
  113. init_allocator();
  114. using namespace mem::paging;
  115. auto kernel_stack_pfn = page_to_pfn(alloc_pages(9));
  116. auto kernel_stack_ptr = mem::physaddr<std::byte>{kernel_stack_pfn} + (1 << 9) * 0x1000;
  117. asm volatile(
  118. "mov %1, %%rdi\n\t"
  119. "lea -8(%2), %%rsp\n\t"
  120. "xor %%rbp, %%rbp\n\t"
  121. "mov %%rbp, (%%rsp)\n\t" // Clear previous frame pointer
  122. "jmp *%0\n\t"
  123. :
  124. : "r"(rust_kinit), "g"(kernel_stack_pfn), "r"(kernel_stack_ptr)
  125. : "memory");
  126. freeze();
  127. }
  128. } // namespace kernel::kinit