process.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. #include <asm/port_io.h>
  2. #include <asm/sys.h>
  3. #include <fs/fat.hpp>
  4. #include <kernel/hw/ata.hpp>
  5. #include <kernel/interrupt.h>
  6. #include <kernel/mem.h>
  7. #include <kernel/mm.hpp>
  8. #include <kernel/process.hpp>
  9. #include <kernel/stdio.h>
  10. #include <kernel/tty.h>
  11. #include <kernel/vfs.hpp>
  12. #include <kernel_main.h>
  13. #include <types/allocator.hpp>
  14. #include <types/assert.h>
  15. #include <types/elf.hpp>
  16. #include <types/hash_map.hpp>
  17. #include <types/list.hpp>
  18. #include <types/lock.hpp>
  19. #include <types/size.h>
  20. #include <types/status.h>
  21. #include <types/stdint.h>
  22. #include <types/types.h>
  23. static void (*volatile kthreadd_new_thd_func)(void*);
  24. static void* volatile kthreadd_new_thd_data;
  25. static types::mutex kthreadd_mtx;
  26. namespace kernel {
  27. struct no_irq_guard {
  28. explicit no_irq_guard()
  29. {
  30. asm_cli();
  31. }
  32. no_irq_guard(const no_irq_guard&) = delete;
  33. no_irq_guard& operator=(const no_irq_guard&) = delete;
  34. ~no_irq_guard()
  35. {
  36. asm_sti();
  37. }
  38. };
  39. } // namespace kernel
  40. process::process(process&& val)
  41. : mms(types::move(val.mms))
  42. , thds(types::move(val.thds))
  43. , wait_lst(types::move(val.wait_lst))
  44. , pid(val.pid)
  45. , ppid(val.ppid)
  46. {
  47. if (current_process == &val)
  48. current_process = this;
  49. attr.system = val.attr.system;
  50. for (auto& item : thds)
  51. item.owner = this;
  52. val.attr.system = 0;
  53. }
  54. process::process(const process& val, const thread& main_thd)
  55. : mms(*kernel_mms)
  56. , attr { .system = val.attr.system }
  57. , pid { process::alloc_pid() }
  58. , ppid { val.pid }
  59. {
  60. auto* thd = &thds.emplace_back(main_thd);
  61. thd->owner = this;
  62. for (auto& area : val.mms) {
  63. if (area.is_ident())
  64. continue;
  65. mms.mirror_area(area);
  66. }
  67. readythds->push(thd);
  68. }
  69. process::process(pid_t _ppid)
  70. : mms(*kernel_mms)
  71. , attr { .system = 1 }
  72. , pid { process::alloc_pid() }
  73. , ppid { _ppid }
  74. {
  75. auto thd = thds.emplace_back(this, true);
  76. readythds->push(&thd);
  77. }
  78. process::process(void (*func)(void), pid_t _ppid)
  79. : process { _ppid }
  80. {
  81. auto* esp = &thds.begin()->esp;
  82. // return(start) address
  83. push_stack(esp, (uint32_t)func);
  84. // ebx
  85. push_stack(esp, 0);
  86. // edi
  87. push_stack(esp, 0);
  88. // esi
  89. push_stack(esp, 0);
  90. // ebp
  91. push_stack(esp, 0);
  92. // eflags
  93. push_stack(esp, 0x200);
  94. }
  95. process::~process()
  96. {
  97. for (auto iter = thds.begin(); iter != thds.end(); ++iter)
  98. readythds->remove_all(&iter);
  99. }
  100. inline void NORETURN _noreturn_crash(void)
  101. {
  102. for (;;)
  103. assert(false);
  104. }
  105. void kernel_threadd_main(void)
  106. {
  107. tty_print(console, "kernel thread daemon started\n");
  108. for (;;) {
  109. if (kthreadd_new_thd_func) {
  110. void (*func)(void*) = nullptr;
  111. void* data = nullptr;
  112. {
  113. types::lock_guard lck(kthreadd_mtx);
  114. func = kthreadd_new_thd_func;
  115. data = kthreadd_new_thd_data;
  116. kthreadd_new_thd_func = nullptr;
  117. kthreadd_new_thd_data = nullptr;
  118. }
  119. // TODO
  120. (void)func, (void)data;
  121. assert(false);
  122. // syscall_fork
  123. // int ret = syscall(0x00);
  124. // if (ret == 0) {
  125. // // child process
  126. // func(data);
  127. // // the function shouldn't return here
  128. // assert(false);
  129. // }
  130. }
  131. // TODO: sleep here to wait for new_kernel_thread event
  132. asm_hlt();
  133. }
  134. }
  135. void NORETURN _kernel_init(void)
  136. {
  137. procs->emplace(kernel_threadd_main, 1);
  138. asm_sti();
  139. hw::init_ata();
  140. // TODO: parse kernel parameters
  141. auto* _new_fs = fs::register_fs(types::kernel_allocator_new<fs::fat::fat32>(fs::vfs_open("/dev/hda1")->ind));
  142. int ret = fs::fs_root->ind->fs->mount(fs::vfs_open("/mnt"), _new_fs);
  143. assert_likely(ret == GB_OK);
  144. current_process->attr.system = 0;
  145. current_thread->attr.system = 0;
  146. const char* argv[] = { "/mnt/INIT.ELF", nullptr };
  147. types::elf::elf32_load_data d;
  148. d.exec = "/mnt/INIT.ELF";
  149. d.argv = argv;
  150. d.system = false;
  151. assert(types::elf::elf32_load(&d) == GB_OK);
  152. asm volatile(
  153. "movw $0x23, %%ax\n"
  154. "movw %%ax, %%ds\n"
  155. "movw %%ax, %%es\n"
  156. "movw %%ax, %%fs\n"
  157. "movw %%ax, %%gs\n"
  158. "pushl $0x23\n"
  159. "pushl %0\n"
  160. "pushl $0x200\n"
  161. "pushl $0x1b\n"
  162. "pushl %1\n"
  163. "iret\n"
  164. :
  165. : "c"(d.sp), "d"(d.eip)
  166. : "eax", "memory");
  167. _noreturn_crash();
  168. }
  169. void k_new_thread(void (*func)(void*), void* data)
  170. {
  171. types::lock_guard lck(kthreadd_mtx);
  172. kthreadd_new_thd_func = func;
  173. kthreadd_new_thd_data = data;
  174. }
  175. void NORETURN init_scheduler()
  176. {
  177. procs = types::kernel_allocator_pnew(procs);
  178. readythds = types::kernel_ident_allocator_pnew(readythds);
  179. auto* init = &procs->emplace(1);
  180. // we need interrupts enabled for cow mapping so now we disable it
  181. // in case timer interrupt mess things up
  182. asm_cli();
  183. current_process = init;
  184. current_thread = &init->thds.begin();
  185. tss.ss0 = KERNEL_DATA_SEGMENT;
  186. tss.esp0 = current_thread->kstack;
  187. asm_switch_pd(current_process->mms.m_pd);
  188. asm volatile(
  189. "movl %0, %%esp\n"
  190. "pushl %=f\n"
  191. "pushl %1\n"
  192. "movw $0x10, %%ax\n"
  193. "movw %%ax, %%ss\n"
  194. "movw %%ax, %%ds\n"
  195. "movw %%ax, %%es\n"
  196. "movw %%ax, %%fs\n"
  197. "movw %%ax, %%gs\n"
  198. "xorl %%ebp, %%ebp\n"
  199. "xorl %%edx, %%edx\n"
  200. "pushl $0x0\n"
  201. "popfl\n"
  202. "ret\n"
  203. "%=:\n"
  204. "ud2"
  205. :
  206. : "a"(current_thread->esp), "c"(_kernel_init)
  207. : "memory");
  208. _noreturn_crash();
  209. }
  210. extern "C" void asm_ctx_switch(uint32_t** curr_esp, uint32_t* next_esp);
  211. void schedule()
  212. {
  213. auto thd = readythds->query();
  214. if (current_thread == thd)
  215. return;
  216. process* proc = thd->owner;
  217. if (current_process != proc) {
  218. asm_switch_pd(proc->mms.m_pd);
  219. current_process = proc;
  220. }
  221. auto* curr_thd = current_thread;
  222. current_thread = thd;
  223. tss.esp0 = current_thread->kstack;
  224. asm_ctx_switch(&curr_thd->esp, thd->esp);
  225. }