process.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  1. #include <memory>
  2. #include <queue>
  3. #include <utility>
  4. #include <assert.h>
  5. #include <bits/alltypes.h>
  6. #include <stdint.h>
  7. #include <stdio.h>
  8. #include <sys/mount.h>
  9. #include <sys/wait.h>
  10. #include <types/allocator.hpp>
  11. #include <types/cplusplus.hpp>
  12. #include <types/elf.hpp>
  13. #include <types/types.h>
  14. #include <kernel/async/lock.hpp>
  15. #include <kernel/log.hpp>
  16. #include <kernel/module.hpp>
  17. #include <kernel/process.hpp>
  18. #include <kernel/signal.hpp>
  19. #include <kernel/task/readyqueue.hpp>
  20. #include <kernel/task/thread.hpp>
  21. #include <kernel/user/thread_local.hpp>
  22. #include <kernel/vfs.hpp>
  23. using kernel::async::mutex;
  24. using kernel::async::lock_guard, kernel::async::lock_guard_irq;
  25. static void (*volatile kthreadd_new_thd_func)(void*);
  26. static void* volatile kthreadd_new_thd_data;
  27. static mutex kthreadd_mtx;
  28. namespace kernel {
  29. struct no_irq_guard {
  30. explicit no_irq_guard()
  31. {
  32. asm volatile("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 volatile("sti");
  39. }
  40. };
  41. } // namespace kernel
  42. int filearr::allocate_fd(int from)
  43. {
  44. if (from < min_avail)
  45. from = min_avail;
  46. if (from == min_avail) {
  47. int nextfd = min_avail + 1;
  48. auto iter = arr.find(nextfd);
  49. while (iter != arr.end() && nextfd == iter->first)
  50. ++nextfd, ++iter;
  51. int retval = min_avail;
  52. min_avail = nextfd;
  53. return retval;
  54. }
  55. int fd = from;
  56. auto iter = arr.find(fd);
  57. while (iter != arr.end() && fd == iter->first)
  58. ++fd, ++iter;
  59. return fd;
  60. }
  61. void filearr::release_fd(int fd)
  62. {
  63. if (fd < min_avail)
  64. min_avail = fd;
  65. }
  66. int filearr::dup(int old_fd)
  67. {
  68. return dup2(old_fd, next_fd());
  69. }
  70. int filearr::dup2(int old_fd, int new_fd)
  71. {
  72. close(new_fd);
  73. auto iter = arr.find(old_fd);
  74. if (!iter)
  75. return -EBADF;
  76. int fd = allocate_fd(new_fd);
  77. assert(fd == new_fd);
  78. auto [ newiter, inserted ] = this->arr.emplace(new_fd, iter->second);
  79. assert(inserted);
  80. newiter->second.flags = 0;
  81. return new_fd;
  82. }
  83. int filearr::dupfd(int fd, int minfd, int flags)
  84. {
  85. auto iter = arr.find(fd);
  86. if (!iter)
  87. return -EBADF;
  88. int new_fd = allocate_fd(minfd);
  89. auto [ newiter, inserted ] = arr.emplace(new_fd, iter->second);
  90. assert(inserted);
  91. newiter->second.flags = flags;
  92. return new_fd;
  93. }
  94. int filearr::set_flags(int fd, int flags)
  95. {
  96. auto iter = arr.find(fd);
  97. if (!iter)
  98. return -EBADF;
  99. iter->second.flags |= flags;
  100. return 0;
  101. }
  102. int filearr::clear_flags(int fd, int flags)
  103. {
  104. auto iter = arr.find(fd);
  105. if (!iter)
  106. return -EBADF;
  107. iter->second.flags &= ~flags;
  108. return 0;
  109. }
  110. // TODO: file opening permissions check
  111. int filearr::open(const process &current,
  112. const types::path& filepath, int flags, mode_t mode)
  113. {
  114. auto* dentry = fs::vfs_open(*current.root, filepath);
  115. if (flags & O_CREAT) {
  116. if (!dentry) {
  117. // create file
  118. auto filename = filepath.last_name();
  119. auto parent_path = filepath;
  120. parent_path.remove_last();
  121. auto* parent = fs::vfs_open(*current.root, parent_path);
  122. if (!parent)
  123. return -EINVAL;
  124. int ret = fs::vfs_mkfile(parent, filename.c_str(), mode);
  125. if (ret != 0)
  126. return ret;
  127. dentry = fs::vfs_open(*current.root, filepath);
  128. assert(dentry);
  129. } else {
  130. // file already exists
  131. if (flags & O_EXCL)
  132. return -EEXIST;
  133. }
  134. } else {
  135. if (!dentry)
  136. return -ENOENT;
  137. }
  138. auto filemode = dentry->ind->mode;
  139. // check whether dentry is a file if O_DIRECTORY is set
  140. if (flags & O_DIRECTORY) {
  141. if (!S_ISDIR(filemode))
  142. return -ENOTDIR;
  143. } else {
  144. if (S_ISDIR(filemode) && (flags & (O_WRONLY | O_RDWR)))
  145. return -EISDIR;
  146. }
  147. // truncate file
  148. if (flags & O_TRUNC) {
  149. if ((flags & (O_WRONLY | O_RDWR)) && S_ISREG(filemode)) {
  150. auto ret = fs::vfs_truncate(dentry->ind, 0);
  151. if (ret != 0)
  152. return ret;
  153. }
  154. }
  155. int fdflag = (flags & O_CLOEXEC) ? FD_CLOEXEC : 0;
  156. int fd = next_fd();
  157. auto [ _, inserted ] = arr.emplace(fd, fditem {
  158. fdflag, std::shared_ptr<fs::file> {
  159. new fs::regular_file(dentry->parent, {
  160. .read = !(flags & O_WRONLY),
  161. .write = !!(flags & (O_WRONLY | O_RDWR)),
  162. .append = !!(S_ISREG(filemode) && flags & O_APPEND),
  163. }, 0, dentry->ind),
  164. } } );
  165. assert(inserted);
  166. return fd;
  167. }
  168. process::process(const process& parent, pid_t pid)
  169. : mms { parent.mms }, attr { parent.attr } , files { parent.files }
  170. , pwd { parent.pwd }, umask { parent.umask }, pid { pid }
  171. , ppid { parent.pid }, pgid { parent.pgid } , sid { parent.sid }
  172. , control_tty { parent.control_tty }, root { parent.root } { }
  173. process::process(pid_t pid, pid_t ppid)
  174. : attr { .system = true }
  175. , pwd { "/" } , pid { pid } , ppid { ppid }
  176. {
  177. bool inserted;
  178. std::tie(std::ignore, inserted) = thds.emplace("", pid);
  179. assert(inserted);
  180. }
  181. using signo_type = kernel::signal_list::signo_type;
  182. void process::send_signal(signo_type signal)
  183. {
  184. for (auto& thd : thds)
  185. thd.send_signal(signal);
  186. }
  187. void kernel_threadd_main(void)
  188. {
  189. kmsg("kernel thread daemon started\n");
  190. for (;;) {
  191. if (kthreadd_new_thd_func) {
  192. void (*func)(void*) = nullptr;
  193. void* data = nullptr;
  194. if (1) {
  195. lock_guard lck(kthreadd_mtx);
  196. if (kthreadd_new_thd_func) {
  197. func = std::exchange(kthreadd_new_thd_func, nullptr);
  198. data = std::exchange(kthreadd_new_thd_data, nullptr);
  199. }
  200. }
  201. // TODO
  202. (void)func, (void)data;
  203. assert(false);
  204. // syscall_fork
  205. // int ret = syscall(0x00);
  206. // if (ret == 0) {
  207. // // child process
  208. // func(data);
  209. // // the function shouldn't return here
  210. // assert(false);
  211. // }
  212. }
  213. // TODO: sleep here to wait for new_kernel_thread event
  214. asm volatile("hlt");
  215. }
  216. }
  217. SECTION(".text.kinit")
  218. proclist::proclist()
  219. {
  220. // init process has no parent
  221. auto& init = real_emplace(1, 0);
  222. assert(init.pid == 1 && init.ppid == 0);
  223. auto& thd = *init.thds.begin();
  224. thd.name.assign("[kernel init]");
  225. current_process = &init;
  226. current_thread = &thd;
  227. kernel::task::dispatcher::enqueue(current_thread);
  228. // TODO: LONG MODE
  229. // tss.ss0 = KERNEL_DATA_SEGMENT;
  230. // tss.esp0 = (uint32_t)current_thread->kstack.esp;
  231. current_process->mms.switch_pd();
  232. if (1) {
  233. // pid 0 is kernel thread daemon
  234. auto& proc = real_emplace(0, 0);
  235. assert(proc.pid == 0 && proc.ppid == 0);
  236. // create thread
  237. auto& thd = *proc.thds.begin();
  238. thd.name.assign("[kernel thread daemon]");
  239. // TODO: LONG MODE
  240. // auto* esp = &thd.kstack.esp;
  241. // auto old_esp = (uint32_t)thd.kstack.esp;
  242. // // return(start) address
  243. // push_stack(esp, (uint32_t)kernel_threadd_main);
  244. // // ebx
  245. // push_stack(esp, 0);
  246. // // edi
  247. // push_stack(esp, 0);
  248. // // esi
  249. // push_stack(esp, 0);
  250. // // ebp
  251. // push_stack(esp, 0);
  252. // // eflags
  253. // push_stack(esp, 0x200);
  254. // // original esp
  255. // push_stack(esp, old_esp);
  256. // kernel::task::dispatcher::enqueue(&thd);
  257. }
  258. }
  259. process& proclist::real_emplace(pid_t pid, pid_t ppid)
  260. {
  261. auto [ iter, inserted ] = m_procs.try_emplace(pid, pid, ppid);
  262. assert(inserted);
  263. return iter->second;
  264. }
  265. void proclist::kill(pid_t pid, int exit_code)
  266. {
  267. auto& proc = this->find(pid);
  268. // put all threads into sleep
  269. for (auto& thd : proc.thds)
  270. thd.set_attr(kernel::task::thread::ZOMBIE);
  271. // write back mmap'ped files and close them
  272. proc.files.close_all();
  273. // unmap all user memory areas
  274. proc.mms.clear();
  275. // init should never exit
  276. if (proc.ppid == 0) {
  277. kmsg("kernel panic: init exited!\n");
  278. freeze();
  279. }
  280. // make child processes orphans (children of init)
  281. this->make_children_orphans(pid);
  282. proc.attr.zombie = 1;
  283. // notify parent process and init
  284. auto& parent = this->find(proc.ppid);
  285. auto& init = this->find(1);
  286. bool flag = false;
  287. if (1) {
  288. lock_guard_irq lck(init.mtx_waitprocs);
  289. if (1) {
  290. lock_guard_irq lck(proc.mtx_waitprocs);
  291. for (const auto& item : proc.waitprocs) {
  292. if (WIFSTOPPED(item.code) || WIFCONTINUED(item.code))
  293. continue;
  294. init.waitprocs.push_back(item);
  295. flag = true;
  296. }
  297. proc.waitprocs.clear();
  298. }
  299. }
  300. if (flag)
  301. init.waitlist.notify_all();
  302. if (1) {
  303. lock_guard_irq lck(parent.mtx_waitprocs);
  304. parent.waitprocs.push_back({ pid, exit_code });
  305. }
  306. parent.waitlist.notify_all();
  307. }
  308. static void release_kinit()
  309. {
  310. // TODO: LONG MODE
  311. // kernel::paccess pa(EARLY_KERNEL_PD_PAGE);
  312. // auto pd = (pd_t)pa.ptr();
  313. // assert(pd);
  314. // (*pd)[0].v = 0;
  315. // // free pt#0
  316. // __free_raw_page(0x00002);
  317. // free .stage1 and .kinit
  318. // for (uint32_t i = ((uint32_t)__stage1_start >> 12);
  319. // i < ((uint32_t)__kinit_end >> 12); ++i) {
  320. // __free_raw_page(i);
  321. // }
  322. }
  323. void NORETURN _kernel_init(void)
  324. {
  325. release_kinit();
  326. asm volatile("sti");
  327. // ------------------------------------------
  328. // interrupt enabled
  329. // ------------------------------------------
  330. // load kmods
  331. for (auto loader = kernel::module::KMOD_LOADERS_START; *loader; ++loader) {
  332. auto* mod = (*loader)();
  333. if (!mod)
  334. continue;
  335. auto ret = insmod(mod);
  336. if (ret == kernel::module::MODULE_SUCCESS)
  337. continue;
  338. char buf[256];
  339. snprintf(buf, sizeof(buf),
  340. "[kernel] An error occured while loading \"%s\"\n", mod->name);
  341. kmsg(buf);
  342. }
  343. // mount fat32 /mnt directory
  344. // TODO: parse kernel parameters
  345. if (1) {
  346. auto* mount_point = fs::vfs_open(*fs::fs_root, types::path{"/mnt"});
  347. if (!mount_point) {
  348. int ret = fs::vfs_mkdir(fs::fs_root, "mnt", 0755);
  349. assert(ret == 0);
  350. mount_point = fs::vfs_open(*fs::fs_root, types::path{"/mnt"});
  351. }
  352. assert(mount_point);
  353. int ret = fs::fs_root->ind->fs->mount(mount_point, "/dev/sda", "/mnt",
  354. "fat32", MS_RDONLY | MS_NOATIME | MS_NODEV | MS_NOSUID, "ro,nodev");
  355. assert(ret == 0);
  356. }
  357. current_process->attr.system = 0;
  358. current_thread->attr |= kernel::task::thread::SYSTEM;
  359. types::elf::elf32_load_data d{
  360. .exec_dent{},
  361. .argv{ "/mnt/busybox", "sh", "/mnt/initsh" },
  362. .envp{ "LANG=C", "HOME=/root", "PATH=/mnt", "PWD=/" },
  363. .ip{}, .sp{}
  364. };
  365. d.exec_dent = fs::vfs_open(*fs::fs_root, types::path{d.argv[0].c_str()});
  366. if (!d.exec_dent) {
  367. kmsg("kernel panic: init not found!\n");
  368. freeze();
  369. }
  370. int ret = types::elf::elf32_load(d);
  371. assert(ret == 0);
  372. asm volatile(
  373. "mov $0x23, %%ax\n"
  374. "mov %%ax, %%ds\n"
  375. "mov %%ax, %%es\n"
  376. "mov %%ax, %%fs\n"
  377. "mov %%ax, %%gs\n"
  378. "push $0x23\n"
  379. "push %0\n"
  380. "push $0x200\n"
  381. "push $0x1b\n"
  382. "push %1\n"
  383. "iretq\n"
  384. : : "g"(d.sp), "g"(d.ip) : "eax", "memory");
  385. freeze();
  386. }
  387. void k_new_thread(void (*func)(void*), void* data)
  388. {
  389. lock_guard lck(kthreadd_mtx);
  390. kthreadd_new_thd_func = func;
  391. kthreadd_new_thd_data = data;
  392. }
  393. SECTION(".text.kinit")
  394. void NORETURN init_scheduler(void)
  395. {
  396. procs = new proclist;
  397. asm volatile(
  398. "mov %0, %%rsp\n"
  399. "sub $16, %%rsp\n"
  400. "mov %=f, %%rbx\n"
  401. "mov %%rbx, 8(%%rsp)\n" // return address
  402. "xor %%rbx, %%rbx\n"
  403. "mov %%rbx, (%%rsp)\n" // previous rbp
  404. "mov %%rsp, %%rbp\n"
  405. "push %1\n"
  406. "mov $0x10, %%ax\n"
  407. "mov %%ax, %%ss\n"
  408. "mov %%ax, %%ds\n"
  409. "mov %%ax, %%es\n"
  410. "mov %%ax, %%fs\n"
  411. "mov %%ax, %%gs\n"
  412. "push $0x0\n"
  413. "popf\n"
  414. "ret\n"
  415. "%=:\n"
  416. "ud2"
  417. :
  418. : "a"(current_thread->kstack.sp), "c"(_kernel_init)
  419. : "memory");
  420. freeze();
  421. }
  422. extern "C" void asm_ctx_switch(uint32_t** curr_esp, uint32_t** next_esp);
  423. bool schedule()
  424. {
  425. freeze();
  426. if (kernel::async::preempt_count() != 0)
  427. return true;
  428. auto* next_thd = kernel::task::dispatcher::next();
  429. process* proc = nullptr;
  430. kernel::task::thread* curr_thd = nullptr;
  431. if (current_thread == next_thd)
  432. goto _end;
  433. proc = &procs->find(next_thd->owner);
  434. if (current_process != proc) {
  435. proc->mms.switch_pd();
  436. current_process = proc;
  437. }
  438. curr_thd = current_thread;
  439. // TODO: LONG MODE
  440. // current_thread = next_thd;
  441. // tss.esp0 = (uint32_t)next_thd->kstack.esp;
  442. // next_thd->load_thread_area();
  443. // asm_ctx_switch(&curr_thd->kstack.esp, &next_thd->kstack.esp);
  444. // tss.esp0 = (uint32_t)curr_thd->kstack.esp;
  445. _end:
  446. return current_thread->signals.pending_signal() == 0;
  447. }
  448. void NORETURN schedule_noreturn(void)
  449. {
  450. schedule();
  451. freeze();
  452. }
  453. void NORETURN freeze(void)
  454. {
  455. for (;;)
  456. asm volatile("cli\n\thlt");
  457. }
  458. void NORETURN kill_current(int signo)
  459. {
  460. procs->kill(current_process->pid,
  461. (signo + 128) << 8 | (signo & 0xff));
  462. schedule_noreturn();
  463. }