process.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. #include <asm/port_io.h>
  2. #include <asm/sys.h>
  3. #include <assert.h>
  4. #include <fs/fat.hpp>
  5. #include <kernel/hw/ata.hpp>
  6. #include <kernel/interrupt.h>
  7. #include <kernel/log.hpp>
  8. #include <kernel/mem.h>
  9. #include <kernel/mm.hpp>
  10. #include <kernel/process.hpp>
  11. #include <kernel/vfs.hpp>
  12. #include <stdint.h>
  13. #include <stdio.h>
  14. #include <types/allocator.hpp>
  15. #include <types/bitmap.h>
  16. #include <types/cplusplus.hpp>
  17. #include <types/elf.hpp>
  18. #include <types/hash_map.hpp>
  19. #include <types/list.hpp>
  20. #include <types/lock.hpp>
  21. #include <types/size.h>
  22. #include <types/status.h>
  23. #include <types/types.h>
  24. static void (*volatile kthreadd_new_thd_func)(void*);
  25. static void* volatile kthreadd_new_thd_data;
  26. static types::mutex kthreadd_mtx;
  27. namespace kernel {
  28. struct no_irq_guard {
  29. explicit no_irq_guard()
  30. {
  31. asm_cli();
  32. }
  33. no_irq_guard(const no_irq_guard&) = delete;
  34. no_irq_guard& operator=(const no_irq_guard&) = delete;
  35. ~no_irq_guard()
  36. {
  37. asm_sti();
  38. }
  39. };
  40. } // namespace kernel
  41. namespace __thd {
  42. inline uint8_t __kstack_bmp[(0x1000000 - 0xc00000) / 0x2000 / 8];
  43. inline int __allocated;
  44. } // namespace __thd
  45. void thread::alloc_kstack(void)
  46. {
  47. for (int i = 0; i < __thd::__allocated; ++i) {
  48. if (bm_test(__thd::__kstack_bmp, i) == 0) {
  49. pkstack = 0xffc00000 + THREAD_KERNEL_STACK_SIZE * (i + 1);
  50. esp = reinterpret_cast<uint32_t*>(pkstack);
  51. bm_set(__thd::__kstack_bmp, i);
  52. return;
  53. }
  54. }
  55. // kernel stack pt is at page#0x00005
  56. kernel::paccess pa(0x00005);
  57. auto pt = (pt_t)pa.ptr();
  58. assert(pt);
  59. pte_t* pte = *pt + __thd::__allocated * 2;
  60. pte[0].v = 0x3;
  61. pte[0].in.page = __alloc_raw_page();
  62. pte[1].v = 0x3;
  63. pte[1].in.page = __alloc_raw_page();
  64. pkstack = 0xffc00000 + THREAD_KERNEL_STACK_SIZE * (__thd::__allocated + 1);
  65. esp = reinterpret_cast<uint32_t*>(pkstack);
  66. bm_set(__thd::__kstack_bmp, __thd::__allocated);
  67. ++__thd::__allocated;
  68. }
  69. void thread::free_kstack(uint32_t p)
  70. {
  71. p -= 0xffc00000;
  72. p /= THREAD_KERNEL_STACK_SIZE;
  73. p -= 1;
  74. bm_clear(__thd::__kstack_bmp, p);
  75. }
  76. process::process(process&& val)
  77. : mms(types::move(val.mms))
  78. , thds { types::move(val.thds), this }
  79. , wait_lst(types::move(val.wait_lst))
  80. , attr { val.attr }
  81. , pid(val.pid)
  82. , ppid(val.ppid)
  83. , files(types::move(val.files))
  84. , pwd(types::move(val.pwd))
  85. {
  86. if (current_process == &val)
  87. current_process = this;
  88. val.pid = 0;
  89. val.ppid = 0;
  90. val.attr.system = 0;
  91. val.attr.zombie = 0;
  92. }
  93. process::process(const process& parent)
  94. : process { parent.pid, parent.is_system(), types::string<>(parent.pwd) }
  95. {
  96. for (auto& area : parent.mms) {
  97. if (area.is_kernel_space() || area.attr.in.system)
  98. continue;
  99. mms.mirror_area(area);
  100. }
  101. this->files.dup(parent.files);
  102. }
  103. process::process(pid_t _ppid, bool _system, types::string<>&& path)
  104. : mms(*kernel_mms)
  105. , attr { .system = _system }
  106. , pid { process::alloc_pid() }
  107. , ppid { _ppid }
  108. , pwd { path }
  109. {
  110. }
  111. void proclist::kill(pid_t pid, int exit_code)
  112. {
  113. process* proc = this->find(pid);
  114. // remove threads from ready list
  115. for (auto& thd : proc->thds.underlying_list()) {
  116. thd.attr.ready = 0;
  117. readythds->remove_all(&thd);
  118. }
  119. // write back mmap'ped files and close them
  120. proc->files.close_all();
  121. // unmap all user memory areas
  122. proc->mms.clear_user();
  123. // init should never exit
  124. if (proc->ppid == 0) {
  125. console->print("kernel panic: init exited!\n");
  126. assert(false);
  127. }
  128. // make child processes orphans (children of init)
  129. this->make_children_orphans(pid);
  130. proc->attr.zombie = 1;
  131. // notify parent process and init
  132. auto* parent = this->find(proc->ppid);
  133. auto* init = this->find(1);
  134. while (!proc->wait_lst.empty()) {
  135. init->wait_lst.push(proc->wait_lst.front());
  136. }
  137. parent->wait_lst.push({ nullptr, (void*)pid, (void*)exit_code, nullptr });
  138. }
  139. void kernel_threadd_main(void)
  140. {
  141. kmsg("kernel thread daemon started\n");
  142. for (;;) {
  143. if (kthreadd_new_thd_func) {
  144. void (*func)(void*) = nullptr;
  145. void* data = nullptr;
  146. {
  147. types::lock_guard lck(kthreadd_mtx);
  148. func = kthreadd_new_thd_func;
  149. data = kthreadd_new_thd_data;
  150. kthreadd_new_thd_func = nullptr;
  151. kthreadd_new_thd_data = nullptr;
  152. }
  153. // TODO
  154. (void)func, (void)data;
  155. assert(false);
  156. // syscall_fork
  157. // int ret = syscall(0x00);
  158. // if (ret == 0) {
  159. // // child process
  160. // func(data);
  161. // // the function shouldn't return here
  162. // assert(false);
  163. // }
  164. }
  165. // TODO: sleep here to wait for new_kernel_thread event
  166. asm_hlt();
  167. }
  168. }
  169. void NORETURN _kernel_init(void)
  170. {
  171. // pid 2 is kernel thread daemon
  172. auto* proc = &procs->emplace(1)->value;
  173. // create thread
  174. thread thd(proc, true);
  175. auto* esp = &thd.esp;
  176. // return(start) address
  177. push_stack(esp, (uint32_t)kernel_threadd_main);
  178. // ebx
  179. push_stack(esp, 0);
  180. // edi
  181. push_stack(esp, 0);
  182. // esi
  183. push_stack(esp, 0);
  184. // ebp
  185. push_stack(esp, 0);
  186. // eflags
  187. push_stack(esp, 0x200);
  188. readythds->push(&proc->thds.Emplace(types::move(thd)));
  189. // ------------------------------------------
  190. asm_sti();
  191. hw::init_ata();
  192. // TODO: parse kernel parameters
  193. auto* drive = fs::vfs_open("/dev/hda1");
  194. assert(drive);
  195. auto* _new_fs = fs::register_fs(new fs::fat::fat32(drive->ind));
  196. auto* mnt = fs::vfs_open("/mnt");
  197. assert(mnt);
  198. int ret = fs::fs_root->ind->fs->mount(mnt, _new_fs);
  199. assert(ret == GB_OK);
  200. current_process->attr.system = 0;
  201. current_thread->attr.system = 0;
  202. const char* argv[] = { "/mnt/INIT.ELF", "/mnt/SH.ELF", nullptr };
  203. const char* envp[] = { nullptr };
  204. types::elf::elf32_load_data d;
  205. d.exec = "/mnt/INIT.ELF";
  206. d.argv = argv;
  207. d.envp = envp;
  208. d.system = false;
  209. ret = types::elf::elf32_load(&d);
  210. assert(ret == GB_OK);
  211. asm volatile(
  212. "movw $0x23, %%ax\n"
  213. "movw %%ax, %%ds\n"
  214. "movw %%ax, %%es\n"
  215. "movw %%ax, %%fs\n"
  216. "movw %%ax, %%gs\n"
  217. "pushl $0x23\n"
  218. "pushl %0\n"
  219. "pushl $0x200\n"
  220. "pushl $0x1b\n"
  221. "pushl %1\n"
  222. "iret\n"
  223. :
  224. : "c"(d.sp), "d"(d.eip)
  225. : "eax", "memory");
  226. freeze();
  227. }
  228. void k_new_thread(void (*func)(void*), void* data)
  229. {
  230. types::lock_guard lck(kthreadd_mtx);
  231. kthreadd_new_thd_func = func;
  232. kthreadd_new_thd_data = data;
  233. }
  234. void NORETURN init_scheduler(void)
  235. {
  236. {
  237. extern char __stage1_start[];
  238. extern char __kinit_end[];
  239. kernel::paccess pa(EARLY_KERNEL_PD_PAGE);
  240. auto pd = (pd_t)pa.ptr();
  241. assert(pd);
  242. (*pd)[0].v = 0;
  243. // free pt#0
  244. __free_raw_page(0x00002);
  245. // free .stage1 and .kinit
  246. for (uint32_t i = ((uint32_t)__stage1_start >> 12);
  247. i < ((uint32_t)__kinit_end >> 12); ++i) {
  248. __free_raw_page(i);
  249. }
  250. }
  251. procs = new proclist;
  252. readythds = new readyqueue;
  253. process::filearr::init_global_file_container();
  254. // init process has no parent
  255. auto* init = &procs->emplace(0)->value;
  256. init->files.open("/dev/console", 0);
  257. // we need interrupts enabled for cow mapping so now we disable it
  258. // in case timer interrupt mess things up
  259. asm_cli();
  260. current_process = init;
  261. current_thread = &init->thds.Emplace(init, true);
  262. readythds->push(current_thread);
  263. tss.ss0 = KERNEL_DATA_SEGMENT;
  264. tss.esp0 = current_thread->pkstack;
  265. asm_switch_pd(current_process->mms.m_pd);
  266. asm volatile(
  267. "movl %0, %%esp\n"
  268. "pushl %=f\n"
  269. "pushl %1\n"
  270. "movw $0x10, %%ax\n"
  271. "movw %%ax, %%ss\n"
  272. "movw %%ax, %%ds\n"
  273. "movw %%ax, %%es\n"
  274. "movw %%ax, %%fs\n"
  275. "movw %%ax, %%gs\n"
  276. "xorl %%ebp, %%ebp\n"
  277. "xorl %%edx, %%edx\n"
  278. "pushl $0x0\n"
  279. "popfl\n"
  280. "ret\n"
  281. "%=:\n"
  282. "ud2"
  283. :
  284. : "a"(current_thread->esp), "c"(_kernel_init)
  285. : "memory");
  286. freeze();
  287. }
  288. extern "C" void asm_ctx_switch(uint32_t** curr_esp, uint32_t* next_esp);
  289. void schedule()
  290. {
  291. auto thd = readythds->query();
  292. if (current_thread == thd)
  293. return;
  294. process* proc = thd->owner;
  295. if (current_process != proc) {
  296. asm_switch_pd(proc->mms.m_pd);
  297. current_process = proc;
  298. }
  299. auto* curr_thd = current_thread;
  300. current_thread = thd;
  301. tss.esp0 = current_thread->pkstack;
  302. asm_ctx_switch(&curr_thd->esp, thd->esp);
  303. }
  304. void NORETURN schedule_noreturn(void)
  305. {
  306. schedule();
  307. freeze();
  308. }
  309. void NORETURN freeze(void)
  310. {
  311. asm_cli();
  312. asm_hlt();
  313. for (;;)
  314. ;
  315. }
  316. void NORETURN kill_current(int exit_code)
  317. {
  318. procs->kill(current_process->pid, exit_code);
  319. schedule_noreturn();
  320. }