kinit.cpp 4.7 KB

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