process.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  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. thread* current_thread;
  14. process* current_process;
  15. static types::list<process>* processes;
  16. static types::list<thread*>* ready_thds;
  17. static inline void create_init_process(void)
  18. {
  19. auto init = processes->emplace_back();
  20. init->kernel_esp = align_down_to_16byte((char*)k_malloc(THREAD_KERNEL_STACK_SIZE) + THREAD_KERNEL_STACK_SIZE);
  21. memset((char*)init->kernel_esp - THREAD_KERNEL_STACK_SIZE, 0x00, THREAD_KERNEL_STACK_SIZE);
  22. init->kernel_ss = 0x10;
  23. init->attr.system = 0;
  24. init->mms = *kernel_mms;
  25. tss.esp0 = (uint32_t)init->kernel_esp;
  26. tss.ss0 = init->kernel_ss;
  27. page_directory_entry* pd = alloc_pd();
  28. memcpy(pd, mms_get_pd(kernel_mms), PAGE_SIZE);
  29. for (auto& item : init->mms) {
  30. item.pd = pd;
  31. }
  32. auto user_mm = init->mms.emplace_back(mm {
  33. .start = 0x40000000,
  34. .attr = {
  35. .read = 1,
  36. .write = 1,
  37. .system = 0,
  38. },
  39. .pgs = types::kernel_allocator_new<page_arr>(),
  40. .pd = pd,
  41. });
  42. auto thd = init->thds.emplace_back(thread {
  43. .eip = (void*)0x40000000U,
  44. .owner = init.ptr(),
  45. .regs {},
  46. .eflags {},
  47. .cs = USER_CODE_SELECTOR,
  48. .ss = USER_DATA_SELECTOR,
  49. .esp = 0x40100000U,
  50. });
  51. ready_thds->push_back(thd.ptr());
  52. for (int i = 0; i < 1 * 1024 * 1024 / PAGE_SIZE; ++i) {
  53. k_map(user_mm.ptr(), &empty_page, 1, 1, 0, 1);
  54. }
  55. current_process = init.ptr();
  56. current_thread = thd.ptr();
  57. asm_switch_pd(pd);
  58. // movl $0x01919810, %eax
  59. // movl $0x00114514, %ebx
  60. // jmp $.
  61. unsigned char instruction[] = {
  62. 0xb8, 0x10, 0x98, 0x91, 0x01, 0xbb, 0x14, 0x45, 0x11, 0x00, 0xeb, 0xfe
  63. };
  64. void* user_mem = (void*)0x40000000U;
  65. memcpy(user_mem, instruction, sizeof(instruction));
  66. }
  67. static inline void create_test_process(void)
  68. {
  69. auto proc = processes->emplace_back();
  70. proc->attr.system = 0;
  71. proc->kernel_esp = align_down_to_16byte((char*)k_malloc(THREAD_KERNEL_STACK_SIZE) + THREAD_KERNEL_STACK_SIZE);
  72. memset((char*)proc->kernel_esp - THREAD_KERNEL_STACK_SIZE, 0x00, THREAD_KERNEL_STACK_SIZE);
  73. proc->kernel_ss = KERNEL_DATA_SEGMENT;
  74. proc->mms = *kernel_mms;
  75. page_directory_entry* pd = alloc_pd();
  76. memcpy(pd, mms_get_pd(kernel_mms), PAGE_SIZE);
  77. for (auto& item : proc->mms)
  78. item.pd = pd;
  79. auto user_mm = proc->mms.emplace_back(mm {
  80. .start = 0x40000000,
  81. .attr = {
  82. .read = 1,
  83. .write = 1,
  84. .system = 0,
  85. },
  86. .pgs = types::kernel_allocator_new<page_arr>(),
  87. .pd = pd,
  88. });
  89. auto thd = proc->thds.emplace_back(thread {
  90. .eip = (void*)0x40000000U,
  91. .owner = proc.ptr(),
  92. .regs {},
  93. .eflags {},
  94. .cs = USER_CODE_SELECTOR,
  95. .ss = USER_DATA_SELECTOR,
  96. .esp = 0x40100000U,
  97. });
  98. ready_thds->push_back(thd.ptr());
  99. for (int i = 0; i < 1 * 1024 * 1024 / PAGE_SIZE; ++i)
  100. k_map(user_mm.ptr(), &empty_page, 1, 1, 0, 1);
  101. page_directory_entry* init_pd = (page_directory_entry*)p_ptr_to_v_ptr(current_pd());
  102. auto old_proc = current_process;
  103. auto old_thd = current_thread;
  104. current_process = proc.ptr();
  105. current_thread = thd.ptr();
  106. asm_switch_pd(pd);
  107. unsigned char instruction[] = {
  108. 0xb8, 0x00, 0x81, 0x19, 0x19, 0xbb, 0x00, 0x14, 0x45, 0x11, 0xeb, 0xfe
  109. };
  110. void* user_mem = (void*)0x40000000U;
  111. memcpy(user_mem, instruction, sizeof(instruction));
  112. current_process = old_proc;
  113. current_thread = old_thd;
  114. asm_switch_pd(init_pd);
  115. }
  116. static bool is_scheduler_ready;
  117. void NORETURN init_scheduler()
  118. {
  119. processes = types::kernel_allocator_new<types::list<process>>();
  120. ready_thds = types::kernel_allocator_new<types::list<thread*>>();
  121. create_init_process();
  122. create_test_process();
  123. asm_cli();
  124. is_scheduler_ready = true;
  125. go_user_space((void*)0x40000000U);
  126. }
  127. void context_switch(irq0_data* intrpt_data)
  128. {
  129. if (!is_scheduler_ready)
  130. return;
  131. thread* thd = *ready_thds->begin();
  132. if (current_thread == thd) {
  133. ready_thds->erase(ready_thds->begin());
  134. // check if the thread is ready
  135. ready_thds->push_back(thd);
  136. return;
  137. }
  138. process* pro = thd->owner;
  139. if (current_process != pro) {
  140. if (!pro->attr.system) {
  141. current_process->kernel_esp = (void*)tss.esp0;
  142. current_process->kernel_ss = tss.ss0;
  143. tss.esp0 = (uint32_t)pro->kernel_esp;
  144. tss.ss0 = pro->kernel_ss;
  145. }
  146. current_process = pro;
  147. asm_switch_pd(pro->mms.begin()->pd);
  148. }
  149. // save current thread info
  150. current_thread->cs = intrpt_data->cs;
  151. current_thread->eflags = intrpt_data->eflags;
  152. current_thread->eip = intrpt_data->v_eip;
  153. memcpy(&current_thread->regs, &intrpt_data->s_regs, sizeof(regs_32));
  154. // load ready thread info
  155. intrpt_data->cs = thd->cs;
  156. intrpt_data->eflags = thd->eflags;
  157. intrpt_data->eflags |= 0x200; // sti
  158. intrpt_data->v_eip = thd->eip;
  159. memcpy(&intrpt_data->s_regs, &thd->regs, sizeof(regs_32));
  160. if (!pro->attr.system) {
  161. // user mode
  162. current_thread->esp = intrpt_data->esp;
  163. current_thread->ss = intrpt_data->ss;
  164. intrpt_data->ss = thd->ss;
  165. intrpt_data->esp = thd->esp;
  166. }
  167. ready_thds->erase(ready_thds->begin());
  168. // check if the thread is ready
  169. ready_thds->push_back(thd);
  170. current_thread = thd;
  171. }