kinit.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. #include <assert.h>
  2. #include <stdint.h>
  3. #include <sys/utsname.h>
  4. #include <types/allocator.hpp>
  5. #include <types/types.h>
  6. #include <kernel/hw/acpi.hpp>
  7. #include <kernel/hw/pci.hpp>
  8. #include <kernel/hw/timer.hpp>
  9. #include <kernel/interrupt.hpp>
  10. #include <kernel/log.hpp>
  11. #include <kernel/mem/paging.hpp>
  12. #include <kernel/mem/phys.hpp>
  13. #include <kernel/mem/types.hpp>
  14. #include <kernel/process.hpp>
  15. #include <kernel/syscall.hpp>
  16. #include <kernel/utsname.hpp>
  17. using constructor = void (*)();
  18. extern "C" constructor const start_ctors, end_ctors;
  19. extern "C" uint64_t BSS_ADDR, BSS_LENGTH;
  20. struct PACKED bootloader_data {
  21. uint32_t meminfo_entry_count;
  22. uint32_t meminfo_entry_length;
  23. // don't forget to add the initial 1m to the total
  24. uint32_t meminfo_1k_blocks;
  25. uint32_t meminfo_64k_blocks;
  26. // meminfo entries
  27. kernel::mem::e820_mem_map_entry meminfo_entries[(1024 - 4 * 4) / 24];
  28. };
  29. namespace kernel::kinit {
  30. SECTION(".text.kinit")
  31. static inline void enable_sse() {
  32. asm volatile(
  33. "mov %%cr0, %%rax\n\t"
  34. "and $(~0xc), %%rax\n\t"
  35. "or $0x22, %%rax\n\t"
  36. "mov %%rax, %%cr0\n\t"
  37. "\n\t"
  38. "mov %%cr4, %%rax\n\t"
  39. "or $0x600, %%rax\n\t"
  40. "mov %%rax, %%cr4\n\t"
  41. "fninit\n\t" ::
  42. : "rax");
  43. }
  44. SECTION(".text.kinit")
  45. static inline void set_uname() {
  46. kernel::sys_utsname = new new_utsname;
  47. strcpy(kernel::sys_utsname->sysname, "Linux"); // linux compatible
  48. strcpy(kernel::sys_utsname->nodename, "(none)");
  49. strcpy(kernel::sys_utsname->release, "1.0.0");
  50. strcpy(kernel::sys_utsname->version, "1.0.0");
  51. strcpy(kernel::sys_utsname->machine, "x86");
  52. strcpy(kernel::sys_utsname->domainname, "(none)");
  53. }
  54. extern "C" void r_init_vfs();
  55. SECTION(".text.kinit")
  56. void NORETURN real_kernel_init(mem::paging::pfn_t kernel_stack_pfn) {
  57. // call global constructors
  58. // NOTE: the initializer of global objects MUST NOT contain
  59. // all kinds of memory allocations
  60. for (auto* ctor = &start_ctors; ctor != &end_ctors; ++ctor)
  61. (*ctor)();
  62. set_uname();
  63. init_interrupt();
  64. hw::timer::init_pit();
  65. hw::acpi::parse_acpi_tables();
  66. init_pci();
  67. init_syscall_table();
  68. r_init_vfs();
  69. init_scheduler(kernel_stack_pfn);
  70. }
  71. SECTION(".text.kinit")
  72. static inline void setup_early_kernel_page_table() {
  73. using namespace kernel::mem::paging;
  74. // remove temporary mapping
  75. KERNEL_PAGE_TABLE[0x000].clear();
  76. constexpr auto idx = idx_all(0xffffffffc0200000ULL);
  77. auto pdpt = KERNEL_PAGE_TABLE[std::get<1>(idx)].parse();
  78. auto pd = pdpt[std::get<2>(idx)].parse();
  79. // kernel bss, size 2M
  80. pd[std::get<3>(idx)].set(PA_KERNEL_DATA_HUGE, KERNEL_BSS_HUGE_PAGE);
  81. // clear kernel bss
  82. memset((void*)BSS_ADDR, 0x00, BSS_LENGTH);
  83. // clear empty page
  84. memset(mem::physaddr<void>{(uintptr_t)EMPTY_PAGE_PFN}, 0x00, 0x1000);
  85. }
  86. extern "C" uintptr_t KIMAGE_PAGES_VALUE;
  87. SECTION(".text.kinit")
  88. static inline void setup_buddy(uintptr_t addr_max) {
  89. using namespace kernel::mem;
  90. using namespace kernel::mem::paging;
  91. constexpr auto idx = idx_all(0xffffff8040000000ULL);
  92. addr_max += 0xfff;
  93. addr_max >>= 12;
  94. int count = (addr_max * sizeof(page) + 0x200000 - 1) / 0x200000;
  95. pfn_t real_start_pfn = KERNEL_IMAGE_PADDR + KIMAGE_PAGES_VALUE * 0x1000;
  96. pfn_t aligned_start_pfn = real_start_pfn + 0x200000 - 1;
  97. aligned_start_pfn &= ~0x1fffff;
  98. pfn_t saved_start_pfn = aligned_start_pfn;
  99. memset(physaddr<void>{KERNEL_PD_STRUCT_PAGE_ARR}, 0x00, 4096);
  100. auto pdpte = KERNEL_PAGE_TABLE[std::get<1>(idx)].parse()[std::get<2>(idx)];
  101. pdpte.set(PA_KERNEL_PAGE_TABLE, KERNEL_PD_STRUCT_PAGE_ARR);
  102. auto pd = pdpte.parse();
  103. for (int i = 0; i < count; ++i, aligned_start_pfn += 0x200000)
  104. pd[std::get<3>(idx) + i].set(PA_KERNEL_DATA_HUGE, aligned_start_pfn);
  105. PAGE_ARRAY = (page*)0xffffff8040000000ULL;
  106. memset(PAGE_ARRAY, 0x00, addr_max * sizeof(page));
  107. for (int i = 0; i < (int)info::e820_entry_count; ++i) {
  108. auto& ent = info::e820_entries[i];
  109. if (ent.type != 1) // type == 1: free area
  110. continue;
  111. mark_present(ent.base, ent.base + ent.len);
  112. auto start = ent.base;
  113. auto end = start + ent.len;
  114. if (end <= aligned_start_pfn)
  115. continue;
  116. if (start < aligned_start_pfn)
  117. start = aligned_start_pfn;
  118. if (start > end)
  119. continue;
  120. mem::paging::create_zone(start, end);
  121. }
  122. // free .stage1
  123. create_zone(0x1000, 0x2000);
  124. // unused space
  125. create_zone(0x9000, 0x80000);
  126. create_zone(0x100000, 0x200000);
  127. create_zone(real_start_pfn, saved_start_pfn);
  128. }
  129. SECTION(".text.kinit")
  130. static inline void save_memory_info(bootloader_data* data) {
  131. kernel::mem::info::memory_size = 1ULL * 1024ULL * 1024ULL + // initial 1M
  132. 1024ULL * data->meminfo_1k_blocks +
  133. 64ULL * 1024ULL * data->meminfo_64k_blocks;
  134. kernel::mem::info::e820_entry_count = data->meminfo_entry_count;
  135. kernel::mem::info::e820_entry_length = data->meminfo_entry_length;
  136. memcpy(kernel::mem::info::e820_entries, data->meminfo_entries,
  137. sizeof(kernel::mem::info::e820_entries));
  138. }
  139. SECTION(".text.kinit")
  140. void setup_gdt() {
  141. // user code
  142. mem::gdt[3] = 0x0020'fa00'0000'0000;
  143. // user data
  144. mem::gdt[4] = 0x0000'f200'0000'0000;
  145. // user code32
  146. mem::gdt[5] = 0x00cf'fa00'0000'ffff;
  147. // user data32
  148. mem::gdt[6] = 0x00cf'f200'0000'ffff;
  149. // thread load 32bit
  150. mem::gdt[7] = 0x0000'0000'0000'0000;
  151. // TSS descriptor
  152. mem::gdt[8] = 0x0000'8900'0070'0067;
  153. mem::gdt[9] = 0x0000'0000'ffff'ff00;
  154. // LDT descriptor
  155. mem::gdt[10] = 0x0000'8200'0060'001f;
  156. mem::gdt[11] = 0x0000'0000'ffff'ff00;
  157. // null segment
  158. mem::gdt[12] = 0x0000'0000'0000'0000;
  159. // thread local 64bit
  160. mem::gdt[13] = 0x0000'0000'0000'0000;
  161. uint64_t descriptor[] = {0x005f'0000'0000'0000,
  162. (uintptr_t)(uint64_t*)mem::gdt};
  163. asm volatile(
  164. "lgdt (%0)\n\t"
  165. "mov $0x50, %%ax\n\t"
  166. "lldt %%ax\n\t"
  167. "mov $0x40, %%ax\n\t"
  168. "ltr %%ax\n\t"
  169. :
  170. : "r"((uintptr_t)descriptor + 6)
  171. : "ax", "memory");
  172. }
  173. extern "C" SECTION(".text.kinit") void NORETURN
  174. kernel_init(bootloader_data* data) {
  175. enable_sse();
  176. setup_early_kernel_page_table();
  177. setup_gdt();
  178. save_memory_info(data);
  179. uintptr_t addr_max = 0;
  180. for (int i = 0; i < (int)kernel::mem::info::e820_entry_count; ++i) {
  181. auto& ent = kernel::mem::info::e820_entries[i];
  182. if (ent.type != 1)
  183. continue;
  184. addr_max = std::max(addr_max, ent.base + ent.len);
  185. }
  186. setup_buddy(addr_max);
  187. init_allocator();
  188. using namespace mem::paging;
  189. auto kernel_stack_pfn = page_to_pfn(alloc_pages(9));
  190. auto kernel_stack_ptr =
  191. mem::physaddr<std::byte>{kernel_stack_pfn} + (1 << 9) * 0x1000;
  192. asm volatile(
  193. "mov %1, %%rdi\n\t"
  194. "mov %2, %%rsp\n\t"
  195. "xor %%rbp, %%rbp\n\t"
  196. "call *%0\n\t"
  197. :
  198. : "r"(real_kernel_init), "g"(kernel_stack_pfn), "g"(kernel_stack_ptr)
  199. :);
  200. freeze();
  201. }
  202. } // namespace kernel::kinit