process.cpp 10 KB

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