process.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. #include <assert.h>
  2. #include <bits/alltypes.h>
  3. #include <stdint.h>
  4. #include <sys/mount.h>
  5. #include <sys/wait.h>
  6. #include <types/allocator.hpp>
  7. #include <types/cplusplus.hpp>
  8. #include <types/elf.hpp>
  9. #include <types/types.h>
  10. #include <kernel/async/lock.hpp>
  11. #include <kernel/log.hpp>
  12. #include <kernel/mem/paging.hpp>
  13. #include <kernel/module.hpp>
  14. #include <kernel/process.hpp>
  15. #include <kernel/signal.hpp>
  16. #include <kernel/task/readyqueue.hpp>
  17. #include <kernel/task/thread.hpp>
  18. #include <kernel/user/thread_local.hpp>
  19. #include <kernel/vfs.hpp>
  20. #include <kernel/vfs/dentry.hpp>
  21. extern "C" fs::rust_file_array::handle* r_filearray_new_for_init();
  22. extern "C" fs::rust_fs_context::handle* r_fs_context_new_for_init();
  23. extern "C" fs::rust_file_array::handle* r_filearray_new_cloned(
  24. struct fs::rust_file_array::handle* other);
  25. extern "C" fs::rust_fs_context::handle* r_fs_context_new_cloned(
  26. struct fs::rust_fs_context::handle* other);
  27. extern "C" void r_filearray_drop(struct fs::rust_file_array::handle* other);
  28. extern "C" void r_fs_context_drop(struct fs::rust_fs_context::handle* other);
  29. fs::rust_fs_context::rust_fs_context(rust_fs_context::handle* handle) : m_handle(handle) {}
  30. fs::rust_file_array::rust_file_array(rust_file_array::handle* handle) : m_handle(handle) {}
  31. fs::rust_fs_context::~rust_fs_context() {
  32. drop();
  33. }
  34. fs::rust_file_array::~rust_file_array() {
  35. drop();
  36. }
  37. void fs::rust_fs_context::drop() {
  38. if (m_handle) {
  39. r_fs_context_drop(m_handle);
  40. m_handle = nullptr;
  41. }
  42. }
  43. void fs::rust_file_array::drop() {
  44. if (m_handle) {
  45. r_filearray_drop(m_handle);
  46. m_handle = nullptr;
  47. }
  48. }
  49. fs::rust_fs_context::handle* fs::rust_fs_context::get() const {
  50. assert(m_handle);
  51. return m_handle;
  52. }
  53. fs::rust_file_array::handle* fs::rust_file_array::get() const {
  54. assert(m_handle);
  55. return m_handle;
  56. }
  57. process::process(const process& parent, pid_t pid)
  58. : mms{parent.mms}
  59. , attr{parent.attr}
  60. , files{r_filearray_new_cloned(parent.files.get())}
  61. , fs_context{r_fs_context_new_cloned(parent.fs_context.get())}
  62. , pid{pid}
  63. , ppid{parent.pid}
  64. , pgid{parent.pgid}
  65. , sid{parent.sid}
  66. , control_tty{parent.control_tty} {}
  67. process::process(pid_t pid, pid_t ppid)
  68. : attr{.system = true}
  69. , files{r_filearray_new_for_init()}
  70. , fs_context{r_fs_context_new_for_init()}
  71. , pid{pid}
  72. , ppid{ppid} {
  73. bool inserted;
  74. std::tie(std::ignore, inserted) = thds.emplace("", pid);
  75. assert(inserted);
  76. }
  77. using signo_type = kernel::signal_list::signo_type;
  78. void process::send_signal(signo_type signal) {
  79. for (auto& thd : thds)
  80. thd.send_signal(signal);
  81. }
  82. void kernel_threadd_main(void) {
  83. kmsg("[kernel] kthread daemon started");
  84. // TODO: create new kthread
  85. for (;;)
  86. asm volatile("hlt");
  87. }
  88. static inline void __spawn(kernel::task::thread& thd, uintptr_t entry) {
  89. auto prev_sp = thd.kstack.sp;
  90. // return(start) address
  91. thd.kstack.pushq(entry);
  92. thd.kstack.pushq(0x200); // flags
  93. thd.kstack.pushq(0); // r15
  94. thd.kstack.pushq(0); // r14
  95. thd.kstack.pushq(0); // r13
  96. thd.kstack.pushq(0); // r12
  97. thd.kstack.pushq(0); // rbp
  98. thd.kstack.pushq(0); // rbx
  99. thd.kstack.pushq(0); // 0 for alignment
  100. thd.kstack.pushq(prev_sp); // previous sp
  101. }
  102. SECTION(".text.kinit")
  103. proclist::proclist() {
  104. // init process has no parent
  105. auto& init = real_emplace(1, 0);
  106. assert(init.pid == 1 && init.ppid == 0);
  107. auto thd = init.thds.begin();
  108. thd->name.assign("[kernel init]");
  109. init.attr.system = 0;
  110. thd->attr &= ~kernel::task::thread::SYSTEM;
  111. current_process = &init;
  112. current_thread = &thd;
  113. kernel::task::dispatcher::enqueue(current_thread);
  114. current_thread->kstack.load_interrupt_stack();
  115. current_process->mms.switch_pd();
  116. if (1) {
  117. // pid 0 is kernel thread daemon
  118. auto& proc = real_emplace(0, 0);
  119. assert(proc.pid == 0 && proc.ppid == 0);
  120. // create thread
  121. auto thd = proc.thds.begin();
  122. thd->name.assign("[kernel thread daemon]");
  123. __spawn(*thd, (uintptr_t)kernel_threadd_main);
  124. kernel::task::dispatcher::setup_idle(&thd);
  125. }
  126. }
  127. process& proclist::real_emplace(pid_t pid, pid_t ppid) {
  128. auto [iter, inserted] = m_procs.try_emplace(pid, pid, ppid);
  129. assert(inserted);
  130. return iter->second;
  131. }
  132. void proclist::kill(pid_t pid, int exit_code) {
  133. auto& proc = this->find(pid);
  134. // init should never exit
  135. if (proc.ppid == 0) {
  136. kmsg("kernel panic: init exited!");
  137. freeze();
  138. }
  139. kernel::async::preempt_disable();
  140. // put all threads into sleep
  141. for (auto& thd : proc.thds)
  142. thd.set_attr(kernel::task::thread::ZOMBIE);
  143. // TODO: CHANGE THIS
  144. // files should only be closed when this is the last thread
  145. //
  146. // write back mmap'ped files and close them
  147. proc.files.drop();
  148. // free fs_context
  149. proc.fs_context.drop();
  150. // unmap all user memory areas
  151. proc.mms.clear();
  152. // make child processes orphans (children of init)
  153. this->make_children_orphans(pid);
  154. proc.attr.zombie = 1;
  155. // notify parent process and init
  156. auto& parent = this->find(proc.ppid);
  157. auto& init = this->find(1);
  158. using kernel::async::lock_guard;
  159. bool flag = false;
  160. if (1) {
  161. lock_guard lck(init.mtx_waitprocs);
  162. if (1) {
  163. lock_guard lck(proc.mtx_waitprocs);
  164. for (const auto& item : proc.waitprocs) {
  165. if (WIFSTOPPED(item.code) || WIFCONTINUED(item.code))
  166. continue;
  167. init.waitprocs.push_back(item);
  168. flag = true;
  169. }
  170. proc.waitprocs.clear();
  171. }
  172. }
  173. if (flag)
  174. init.waitlist.notify_all();
  175. if (1) {
  176. lock_guard lck(parent.mtx_waitprocs);
  177. parent.waitprocs.push_back({pid, exit_code});
  178. }
  179. parent.waitlist.notify_all();
  180. kernel::async::preempt_enable();
  181. }
  182. static void release_kinit() {
  183. // free .kinit
  184. using namespace kernel::mem::paging;
  185. extern uintptr_t volatile KINIT_START_ADDR, KINIT_END_ADDR, KINIT_PAGES;
  186. std::size_t pages = KINIT_PAGES;
  187. auto range = vaddr_range{KERNEL_PML4, KINIT_START_ADDR, KINIT_END_ADDR, true};
  188. for (auto pte : range)
  189. pte.clear();
  190. create_zone(KERNEL_IMAGE_PADDR, KERNEL_IMAGE_PADDR + 0x1000 * pages);
  191. }
  192. extern "C" void late_init_rust(uintptr_t* out_sp, uintptr_t* out_ip);
  193. void NORETURN _kernel_init(kernel::mem::paging::pfn_t kernel_stack_pfn) {
  194. kernel::mem::paging::free_pages(kernel_stack_pfn, 9);
  195. release_kinit();
  196. kernel::kmod::load_internal_modules();
  197. uintptr_t sp, ip;
  198. late_init_rust(&sp, &ip);
  199. asm volatile("sti");
  200. // ------------------------------------------
  201. // interrupt enabled
  202. // ------------------------------------------
  203. int ds = 0x33, cs = 0x2b;
  204. asm volatile(
  205. "mov %0, %%rax\n"
  206. "mov %%ax, %%ds\n"
  207. "mov %%ax, %%es\n"
  208. "mov %%ax, %%fs\n"
  209. "mov %%ax, %%gs\n"
  210. "push %%rax\n"
  211. "push %2\n"
  212. "push $0x200\n"
  213. "push %1\n"
  214. "push %3\n"
  215. "iretq\n"
  216. :
  217. : "g"(ds), "g"(cs), "g"(sp), "g"(ip)
  218. : "eax", "memory");
  219. freeze();
  220. }
  221. SECTION(".text.kinit")
  222. void NORETURN init_scheduler(kernel::mem::paging::pfn_t kernel_stack_pfn) {
  223. procs = new proclist;
  224. asm volatile(
  225. "mov %2, %%rdi\n"
  226. "mov %0, %%rsp\n"
  227. "sub $24, %%rsp\n"
  228. "mov %=f, %%rbx\n"
  229. "mov %%rbx, (%%rsp)\n" // return address
  230. "mov %%rbx, 16(%%rsp)\n" // previous frame return address
  231. "xor %%rbx, %%rbx\n"
  232. "mov %%rbx, 8(%%rsp)\n" // previous frame rbp
  233. "mov %%rsp, %%rbp\n" // current frame rbp
  234. "push %1\n"
  235. "mov $0x10, %%ax\n"
  236. "mov %%ax, %%ss\n"
  237. "mov %%ax, %%ds\n"
  238. "mov %%ax, %%es\n"
  239. "mov %%ax, %%fs\n"
  240. "mov %%ax, %%gs\n"
  241. "push $0x0\n"
  242. "popf\n"
  243. "ret\n"
  244. "%=:\n"
  245. "ud2"
  246. :
  247. : "a"(current_thread->kstack.sp), "c"(_kernel_init), "g"(kernel_stack_pfn)
  248. : "memory");
  249. freeze();
  250. }
  251. extern "C" void asm_ctx_switch(uintptr_t* curr_sp, uintptr_t* next_sp);
  252. extern "C" void after_ctx_switch() {
  253. current_thread->kstack.load_interrupt_stack();
  254. current_thread->load_thread_area32();
  255. kernel::async::preempt_enable();
  256. }
  257. // call this with preempt_count == 1
  258. // after this function returns, preempt_count will be 0
  259. static bool do_schedule() {
  260. asm volatile("" : : : "memory");
  261. auto* next_thd = kernel::task::dispatcher::next();
  262. if (current_thread != next_thd) {
  263. auto* proc = &procs->find(next_thd->owner);
  264. if (current_process != proc) {
  265. proc->mms.switch_pd();
  266. current_process = proc;
  267. }
  268. auto* curr_thd = current_thread;
  269. current_thread = next_thd;
  270. // this implies preempt_enable()
  271. asm_ctx_switch(&curr_thd->kstack.sp, &next_thd->kstack.sp);
  272. } else {
  273. kernel::async::preempt_enable();
  274. }
  275. return current_thread->signals.pending_signal() == 0;
  276. }
  277. static inline void check_preempt_count(kernel::async::preempt_count_t n) {
  278. if (kernel::async::preempt_count() != n) [[unlikely]] {
  279. kmsgf(
  280. "[kernel:fatal] trying to call schedule_now() with preempt count "
  281. "%d, expected %d",
  282. kernel::async::preempt_count(), n);
  283. assert(kernel::async::preempt_count() == n);
  284. }
  285. }
  286. bool schedule_now() {
  287. check_preempt_count(0);
  288. kernel::async::preempt_disable();
  289. bool result = do_schedule();
  290. return result;
  291. }
  292. // call this with preempt_count == 1
  293. bool schedule_now_preempt_disabled() {
  294. check_preempt_count(1);
  295. return do_schedule();
  296. }
  297. void NORETURN schedule_noreturn(void) {
  298. schedule_now();
  299. kmsgf("[kernel:fatal] an schedule_noreturn() DOES return");
  300. freeze();
  301. }
  302. void NORETURN freeze(void) {
  303. for (;;)
  304. asm volatile("cli\n\thlt");
  305. }
  306. // TODO!!!: make sure we call this after having done all clean up works
  307. void NORETURN kill_current(int signo) {
  308. procs->kill(current_process->pid, (signo + 128) << 8 | (signo & 0xff));
  309. schedule_noreturn();
  310. }