process.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. #include <asm/port_io.h>
  2. #include <asm/sys.h>
  3. #include <kernel/mm.hpp>
  4. #include <kernel/process.hpp>
  5. #include <kernel/stdio.h>
  6. #include <kernel_main.h>
  7. #include <types/types.h>
  8. extern "C" void NORETURN go_user_space(void* eip);
  9. static inline void* align_down_to_16byte(void* addr)
  10. {
  11. return (void*)((uint32_t)addr & 0xfffffff0);
  12. }
  13. static bool is_scheduler_ready;
  14. static types::list<process>* processes;
  15. static types::list<thread*>* ready_thds;
  16. thread* current_thread;
  17. process* current_process;
  18. process::process(process&& val)
  19. : mms(types::move(val.mms))
  20. , thds(types::move(val.thds))
  21. {
  22. if (current_process == &val)
  23. current_process = this;
  24. attr.system = val.attr.system;
  25. k_esp = val.k_esp;
  26. for (auto& item : thds)
  27. item.owner = this;
  28. val.k_esp = nullptr;
  29. val.attr.system = 0;
  30. }
  31. process::process(void* start_eip, uint8_t* image, size_t image_size, bool system)
  32. : mms(*kernel_mms)
  33. , thds {}
  34. , attr { .system = system }
  35. {
  36. k_esp = align_down_to_16byte((char*)k_malloc(THREAD_KERNEL_STACK_SIZE) + THREAD_KERNEL_STACK_SIZE);
  37. memset((char*)k_esp - THREAD_KERNEL_STACK_SIZE, 0x00, THREAD_KERNEL_STACK_SIZE);
  38. page_directory_entry* pd = alloc_pd();
  39. memcpy(pd, mms_get_pd(kernel_mms), PAGE_SIZE);
  40. for (auto& item : mms)
  41. item.pd = pd;
  42. auto user_mm = mms.emplace_back(0x40000000U, pd, 1, system);
  43. auto thd = thds.emplace_back(thread {
  44. .eip = start_eip,
  45. .owner = this,
  46. .regs {},
  47. .eflags {},
  48. // TODO: change this
  49. .esp = 0x40100000U,
  50. });
  51. ready_thds->push_back(thd.ptr());
  52. // TODO: change this
  53. for (int i = 0; i < 1 * 1024 * 1024 / PAGE_SIZE; ++i)
  54. k_map(user_mm.ptr(), &empty_page, 1, 1, 0, 1);
  55. auto* old_pd = reinterpret_cast<page_directory_entry*>(p_ptr_to_v_ptr(current_pd()));
  56. auto* old_proc = current_process;
  57. auto* old_thd = current_thread;
  58. current_process = this;
  59. current_thread = thd.ptr();
  60. asm_switch_pd(pd);
  61. // TODO: change this
  62. memcpy((void*)0x40000000U, image, image_size);
  63. current_process = old_proc;
  64. current_thread = old_thd;
  65. asm_switch_pd(old_pd);
  66. }
  67. void NORETURN init_scheduler()
  68. {
  69. processes = types::kernel_allocator_new<types::list<process>>();
  70. ready_thds = types::kernel_allocator_new<types::list<thread*>>();
  71. // movl $0x01919810, %eax
  72. // movl $0x00114514, %ebx
  73. // movl $0x00000001, %eax
  74. // int $0x80
  75. unsigned char instruction1[] = {
  76. 0xb8, 0x10, 0x98, 0x91, 0x01, 0xbb, 0x14, 0x45, 0x11, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0xcd, 0x80
  77. };
  78. // movl $0x19198100, %eax
  79. // movl $0x11451400, %ebx
  80. // jmp $.
  81. uint8_t instruction2[] = {
  82. 0xb8, 0x00, 0x81, 0x19, 0x19, 0xbb, 0x00, 0x14, 0x45, 0x11, 0xeb, 0xfe
  83. };
  84. void* user_space_start = reinterpret_cast<void*>(0x40000000U);
  85. processes->emplace_back(user_space_start, instruction1, sizeof(instruction1), false);
  86. processes->emplace_back(user_space_start, instruction2, sizeof(instruction2), false);
  87. // we need interrupts enabled for cow mapping
  88. asm_cli();
  89. auto init_process = processes->begin();
  90. current_process = init_process.ptr();
  91. current_thread = init_process->thds.begin().ptr();
  92. tss.ss0 = KERNEL_DATA_SEGMENT;
  93. tss.esp0 = (uint32_t)init_process->k_esp;
  94. asm_switch_pd(mms_get_pd(&current_process->mms));
  95. is_scheduler_ready = true;
  96. go_user_space(user_space_start);
  97. }
  98. void context_switch(irq0_data* intrpt_data)
  99. {
  100. if (!is_scheduler_ready)
  101. return;
  102. thread* thd = *ready_thds->begin();
  103. if (current_thread == thd) {
  104. ready_thds->erase(ready_thds->begin());
  105. // check if the thread is ready
  106. ready_thds->push_back(thd);
  107. return;
  108. }
  109. process* pro = thd->owner;
  110. if (current_process != pro) {
  111. if (!pro->attr.system) {
  112. tss.esp0 = (uint32_t)pro->k_esp;
  113. }
  114. current_process = pro;
  115. asm_switch_pd(pro->mms.begin()->pd);
  116. }
  117. // save current thread info
  118. current_thread->eflags = intrpt_data->eflags;
  119. current_thread->eip = intrpt_data->v_eip;
  120. memcpy(&current_thread->regs, &intrpt_data->s_regs, sizeof(regs_32));
  121. // load ready thread info
  122. intrpt_data->eflags = thd->eflags;
  123. intrpt_data->eflags |= 0x200; // sti
  124. intrpt_data->v_eip = thd->eip;
  125. memcpy(&intrpt_data->s_regs, &thd->regs, sizeof(regs_32));
  126. if (!pro->attr.system) {
  127. // user mode
  128. current_thread->esp = intrpt_data->esp;
  129. intrpt_data->cs = USER_CODE_SELECTOR;
  130. intrpt_data->ss = USER_DATA_SELECTOR;
  131. intrpt_data->esp = thd->esp;
  132. } else {
  133. // supervisor mode
  134. intrpt_data->cs = KERNEL_CODE_SEGMENT;
  135. }
  136. ready_thds->erase(ready_thds->begin());
  137. // check if the thread is ready
  138. ready_thds->push_back(thd);
  139. current_thread = thd;
  140. }