syscall.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790
  1. #include <asm/port_io.h>
  2. #include <asm/sys.h>
  3. #include <assert.h>
  4. #include <bits/ioctl.h>
  5. #include <sys/prctl.h>
  6. #include <sys/mman.h>
  7. #include <sys/stat.h>
  8. #include <time.h>
  9. #include <kernel/user/thread_local.hpp>
  10. #include <kernel/errno.h>
  11. #include <kernel/interrupt.h>
  12. #include <kernel/log.hpp>
  13. #include <kernel/mem.h>
  14. #include <kernel/mm.hpp>
  15. #include <kernel/process.hpp>
  16. #include <kernel/syscall.hpp>
  17. #include <kernel/tty.hpp>
  18. #include <kernel/vfs.hpp>
  19. #include <kernel/hw/timer.h>
  20. #include <stdint.h>
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <types/allocator.hpp>
  24. #include <types/elf.hpp>
  25. #include <types/lock.hpp>
  26. #include <types/status.h>
  27. #define SYSCALL_NO ((data)->s_regs.eax)
  28. #define SYSCALL_RETVAL ((data)->s_regs.eax)
  29. #define SYSCALL_ARG1(type, name) type name = (type)((data)->s_regs.ebx)
  30. #define SYSCALL_ARG2(type, name) type name = (type)((data)->s_regs.ecx)
  31. #define SYSCALL_ARG3(type, name) type name = (type)((data)->s_regs.edx)
  32. #define SYSCALL_ARG4(type, name) type name = (type)((data)->s_regs.esi)
  33. #define SYSCALL_ARG5(type, name) type name = (type)((data)->s_regs.edi)
  34. #define SYSCALL_ARG6(type, name) type name = (type)((data)->s_regs.ebp)
  35. #define SYSCALL_HANDLERS_SIZE (404)
  36. syscall_handler syscall_handlers[SYSCALL_HANDLERS_SIZE];
  37. extern "C" void _syscall_stub_fork_return(void);
  38. int _syscall_fork(interrupt_stack* data)
  39. {
  40. auto& newproc = procs->copy_from(*current_process);
  41. auto [ iter_newthd, inserted ] = newproc.thds.emplace(*current_thread, newproc.pid);
  42. assert(inserted);
  43. auto* newthd = &*iter_newthd;
  44. readythds->push(newthd);
  45. // create fake interrupt stack
  46. push_stack(&newthd->esp, data->ss);
  47. push_stack(&newthd->esp, data->esp);
  48. push_stack(&newthd->esp, data->eflags);
  49. push_stack(&newthd->esp, data->cs);
  50. push_stack(&newthd->esp, (uint32_t)data->v_eip);
  51. // eax
  52. push_stack(&newthd->esp, 0);
  53. push_stack(&newthd->esp, data->s_regs.ecx);
  54. // edx
  55. push_stack(&newthd->esp, 0);
  56. push_stack(&newthd->esp, data->s_regs.ebx);
  57. push_stack(&newthd->esp, data->s_regs.esp);
  58. push_stack(&newthd->esp, data->s_regs.ebp);
  59. push_stack(&newthd->esp, data->s_regs.esi);
  60. push_stack(&newthd->esp, data->s_regs.edi);
  61. // ctx_switch stack
  62. // return address
  63. push_stack(&newthd->esp, (uint32_t)_syscall_stub_fork_return);
  64. // ebx
  65. push_stack(&newthd->esp, 0);
  66. // edi
  67. push_stack(&newthd->esp, 0);
  68. // esi
  69. push_stack(&newthd->esp, 0);
  70. // ebp
  71. push_stack(&newthd->esp, 0);
  72. // eflags
  73. push_stack(&newthd->esp, 0);
  74. return newproc.pid;
  75. }
  76. int _syscall_write(interrupt_stack* data)
  77. {
  78. SYSCALL_ARG1(int, fd);
  79. SYSCALL_ARG2(const char*, buf);
  80. SYSCALL_ARG3(size_t, n);
  81. auto* file = current_process->files[fd];
  82. if (!file || !file->flags.write)
  83. return -EBADF;
  84. switch (file->type) {
  85. case fs::file::types::ind: {
  86. if (S_ISDIR(file->ptr.ind->mode))
  87. return -EBADF;
  88. int n_wrote = fs::vfs_write(file->ptr.ind, buf, file->cursor, n);
  89. if (n_wrote >= 0)
  90. file->cursor += n_wrote;
  91. return n_wrote;
  92. }
  93. case fs::file::types::pipe:
  94. return file->ptr.pp->write(buf, n);
  95. case fs::file::types::socket:
  96. // TODO
  97. return -EINVAL;
  98. default:
  99. assert(false);
  100. for ( ; ; ) ;
  101. }
  102. }
  103. int _syscall_read(interrupt_stack* data)
  104. {
  105. SYSCALL_ARG1(int, fd);
  106. SYSCALL_ARG2(char*, buf);
  107. SYSCALL_ARG3(size_t, n);
  108. auto* file = current_process->files[fd];
  109. if (!file || !file->flags.read)
  110. return -EBADF;
  111. switch (file->type) {
  112. case fs::file::types::ind: {
  113. if (S_ISDIR(file->ptr.ind->mode))
  114. return -EBADF;
  115. // TODO: copy to user function !IMPORTANT
  116. int n_wrote = fs::vfs_read(file->ptr.ind, buf, n, file->cursor, n);
  117. if (n_wrote >= 0)
  118. file->cursor += n_wrote;
  119. return n_wrote;
  120. }
  121. case fs::file::types::pipe:
  122. return file->ptr.pp->read(buf, n);
  123. case fs::file::types::socket:
  124. // TODO
  125. return -EINVAL;
  126. default:
  127. assert(false);
  128. for ( ; ; ) ;
  129. }
  130. }
  131. // TODO: sleep seconds
  132. int _syscall_sleep(interrupt_stack*)
  133. {
  134. current_thread->attr.ready = 0;
  135. current_thread->attr.wait = 1;
  136. schedule();
  137. return 0;
  138. }
  139. int _syscall_chdir(interrupt_stack* data)
  140. {
  141. SYSCALL_ARG1(const char*, path);
  142. auto* dir = fs::vfs_open(*current_process->root,
  143. current_process->pwd.c_str(), path);
  144. if (!dir)
  145. return -ENOENT;
  146. if (!S_ISDIR(dir->ind->mode))
  147. return -ENOTDIR;
  148. current_process->pwd.clear();
  149. dir->path(*current_process->root, current_process->pwd);
  150. return 0;
  151. }
  152. // syscall_exec(const char* exec, const char** argv)
  153. // @param exec: the path of program to execute
  154. // @param argv: arguments end with nullptr
  155. // @param envp: environment variables end with nullptr
  156. int _syscall_execve(interrupt_stack* data)
  157. {
  158. SYSCALL_ARG1(const char*, exec);
  159. SYSCALL_ARG2(char* const*, argv);
  160. SYSCALL_ARG3(char* const*, envp);
  161. types::elf::elf32_load_data d;
  162. d.argv = argv;
  163. d.envp = envp;
  164. d.system = false;
  165. d.exec_dent = fs::vfs_open(*current_process->root,
  166. current_process->pwd.c_str(), exec);
  167. if (!d.exec_dent)
  168. return -ENOENT;
  169. current_process->files.onexec();
  170. int ret = types::elf::elf32_load(&d);
  171. if (ret != GB_OK)
  172. return -d.errcode;
  173. data->v_eip = d.eip;
  174. data->esp = (uint32_t)d.sp;
  175. return 0;
  176. }
  177. // @param exit_code
  178. int NORETURN _syscall_exit(interrupt_stack* data)
  179. {
  180. SYSCALL_ARG1(int, exit_code);
  181. // TODO: terminating a thread only
  182. if (current_process->thds.size() != 1)
  183. assert(false);
  184. // terminating a whole process:
  185. procs->kill(current_process->pid, exit_code & 0xff);
  186. // switch to new process and continue
  187. schedule_noreturn();
  188. }
  189. // @param pid: pid of the process to wait
  190. // @param status: the exit code of the exited process
  191. // @param options: options for waitpid
  192. // @return pid of the exited process
  193. int _syscall_waitpid(interrupt_stack* data)
  194. {
  195. SYSCALL_ARG1(pid_t, pid_to_wait);
  196. SYSCALL_ARG2(int*, arg1);
  197. SYSCALL_ARG3(int, options);
  198. if (pid_to_wait != -1 || options != 0)
  199. return -EINVAL;
  200. auto& cv = current_process->cv_wait;
  201. auto& mtx = cv.mtx();
  202. types::lock_guard lck(mtx);
  203. auto& waitlist = current_process->waitlist;
  204. while (waitlist.empty()) {
  205. if (!procs->has_child(current_process->pid))
  206. return -ECHILD;
  207. if (!cv.wait(mtx))
  208. return -EINTR;
  209. }
  210. auto iter = waitlist.begin();
  211. assert(iter != waitlist.end());
  212. auto& obj = *iter;
  213. pid_t pid = obj.pid;
  214. // TODO: copy_to_user check privilege
  215. *arg1 = obj.code;
  216. procs->remove(pid);
  217. waitlist.erase(iter);
  218. return pid;
  219. }
  220. int _syscall_getdents(interrupt_stack* data)
  221. {
  222. SYSCALL_ARG1(int, fd);
  223. SYSCALL_ARG2(char*, buf);
  224. SYSCALL_ARG3(size_t, cnt);
  225. auto* dir = current_process->files[fd];
  226. if (dir->type != fs::file::types::ind || !S_ISDIR(dir->ptr.ind->mode))
  227. return -ENOTDIR;
  228. size_t orig_cnt = cnt;
  229. int nread = dir->ptr.ind->fs->inode_readdir(dir->ptr.ind, dir->cursor,
  230. [&buf, &cnt](const char* fn, size_t len, fs::ino_t ino, uint8_t type) -> int {
  231. if (!len)
  232. len = strlen(fn);
  233. size_t reclen = sizeof(fs::user_dirent) + 1 + len;
  234. if (cnt < reclen)
  235. return GB_FAILED;
  236. auto* dirp = (fs::user_dirent*)buf;
  237. dirp->d_ino = ino;
  238. dirp->d_reclen = reclen;
  239. // TODO: show offset
  240. // dirp->d_off = 0;
  241. // TODO: use copy_to_user
  242. memcpy(dirp->d_name, fn, len);
  243. buf[reclen - 2] = 0;
  244. buf[reclen - 1] = type;
  245. buf += reclen;
  246. cnt -= reclen;
  247. return GB_OK;
  248. });
  249. if (nread > 0)
  250. dir->cursor += nread;
  251. return orig_cnt - cnt;
  252. }
  253. int _syscall_open(interrupt_stack* data)
  254. {
  255. SYSCALL_ARG1(const char*, path);
  256. SYSCALL_ARG2(uint32_t, flags);
  257. return current_process->files.open(
  258. *current_process, path, flags);
  259. }
  260. int _syscall_getcwd(interrupt_stack* data)
  261. {
  262. SYSCALL_ARG1(char*, buf);
  263. SYSCALL_ARG2(size_t, bufsize);
  264. // TODO: use copy_to_user
  265. strncpy(buf, current_process->pwd.c_str(), bufsize);
  266. buf[bufsize - 1] = 0;
  267. return (uint32_t)buf;
  268. }
  269. int _syscall_setsid(interrupt_stack*)
  270. {
  271. if (current_process->pid == current_process->pgid)
  272. return -EPERM;
  273. current_process->sid = current_process->pid;
  274. current_process->pgid = current_process->pid;
  275. // TODO: get tty* from fd or block device id
  276. console->set_pgrp(current_process->pid);
  277. current_process->control_tty = console;
  278. return current_process->pid;
  279. }
  280. int _syscall_getsid(interrupt_stack* data)
  281. {
  282. SYSCALL_ARG1(pid_t, pid);
  283. if (!procs->try_find(pid))
  284. return -ESRCH;
  285. auto& proc = procs->find(pid);
  286. if (proc.sid != current_process->sid)
  287. return -EPERM;
  288. return proc.sid;
  289. }
  290. int _syscall_close(interrupt_stack* data)
  291. {
  292. SYSCALL_ARG1(int, fd);
  293. current_process->files.close(fd);
  294. return 0;
  295. }
  296. int _syscall_dup(interrupt_stack* data)
  297. {
  298. SYSCALL_ARG1(int, old_fd);
  299. return current_process->files.dup(old_fd);
  300. }
  301. int _syscall_dup2(interrupt_stack* data)
  302. {
  303. SYSCALL_ARG1(int, old_fd);
  304. SYSCALL_ARG2(int, new_fd);
  305. return current_process->files.dup2(old_fd, new_fd);
  306. }
  307. int _syscall_pipe(interrupt_stack* data)
  308. {
  309. SYSCALL_ARG1(int* __user, pipefd);
  310. return current_process->files.pipe(pipefd);
  311. }
  312. int _syscall_setpgid(interrupt_stack* data)
  313. {
  314. SYSCALL_ARG1(pid_t, pid);
  315. SYSCALL_ARG2(pid_t, pgid);
  316. if (pgid < 0)
  317. return -EINVAL;
  318. if (pid == 0)
  319. pid = current_process->pid;
  320. if (pgid == 0)
  321. pgid = pid;
  322. if (!procs->try_find(pid))
  323. return -ESRCH;
  324. auto& proc = procs->find(pid);
  325. // TODO: check whether pgid and the original
  326. // pgid is in the same session
  327. proc.pgid = pgid;
  328. return 0;
  329. }
  330. int _syscall_ioctl(interrupt_stack* data)
  331. {
  332. SYSCALL_ARG1(int, fd);
  333. SYSCALL_ARG2(unsigned long, request);
  334. // TODO: check fd type and get tty* from fd
  335. //
  336. // we use a trick for now, check whether
  337. // the file that fd points to is a pipe or
  338. // not. and we suppose that stdin will be
  339. // either a tty or a pipe.
  340. auto* file = current_process->files[fd];
  341. if (!file || file->type != fs::file::types::ind)
  342. return -ENOTTY;
  343. switch (request) {
  344. case TIOCGPGRP: {
  345. SYSCALL_ARG3(pid_t*, pgid);
  346. tty* ctrl_tty = current_process->control_tty;
  347. // TODO: copy_to_user
  348. *pgid = ctrl_tty->get_pgrp();
  349. break;
  350. }
  351. case TIOCSPGRP: {
  352. // TODO: copy_from_user
  353. SYSCALL_ARG3(const pid_t*, pgid);
  354. tty* ctrl_tty = current_process->control_tty;
  355. ctrl_tty->set_pgrp(*pgid);
  356. break;
  357. }
  358. case TIOCGWINSZ: {
  359. SYSCALL_ARG3(winsize*, ws);
  360. ws->ws_col = 80;
  361. ws->ws_row = 10;
  362. break;
  363. }
  364. default:
  365. return -EINVAL;
  366. }
  367. return 0;
  368. }
  369. int _syscall_getpid(interrupt_stack*)
  370. {
  371. return current_process->pid;
  372. }
  373. int _syscall_getppid(interrupt_stack*)
  374. {
  375. return current_process->ppid;
  376. }
  377. int _syscall_set_thread_area(interrupt_stack* data)
  378. {
  379. SYSCALL_ARG1(kernel::user::user_desc* __user, ptr);
  380. return kernel::user::set_thread_area(ptr);
  381. }
  382. int _syscall_set_tid_address(interrupt_stack* data)
  383. {
  384. SYSCALL_ARG1(int* __user, tidptr);
  385. current_thread->set_child_tid = tidptr;
  386. return current_thread->tid();
  387. }
  388. // TODO: this operation SHOULD be atomic
  389. ssize_t _syscall_writev(interrupt_stack* data)
  390. {
  391. SYSCALL_ARG1(int, fd);
  392. SYSCALL_ARG2(const iovec* __user, iov);
  393. SYSCALL_ARG3(int, iovcnt);
  394. auto* file = current_process->files[fd];
  395. if (!file || !file->flags.write)
  396. return -EBADF;
  397. switch (file->type) {
  398. case fs::file::types::ind: {
  399. if (S_ISDIR(file->ptr.ind->mode))
  400. return -EBADF;
  401. ssize_t n_wrote = 0;
  402. for (int i = 0; i < iovcnt; ++i) {
  403. int ret = fs::vfs_write(file->ptr.ind,
  404. (const char*)iov[i].iov_base,
  405. file->cursor, iov[i].iov_len);
  406. if (ret < 0)
  407. return ret;
  408. n_wrote += ret;
  409. }
  410. file->cursor += n_wrote;
  411. return n_wrote;
  412. }
  413. case fs::file::types::pipe: {
  414. ssize_t tot = 0;
  415. for (int i = 0; i < iovcnt; ++i) {
  416. int retval = file->ptr.pp->write(
  417. (const char*)iov->iov_base, iovcnt);
  418. if (retval < 0)
  419. return retval;
  420. tot += retval;
  421. }
  422. return tot;
  423. }
  424. case fs::file::types::socket:
  425. // TODO
  426. return -EINVAL;
  427. default:
  428. assert(false);
  429. for ( ; ; ) ;
  430. }
  431. }
  432. int _syscall_prctl(interrupt_stack* data)
  433. {
  434. SYSCALL_ARG1(int, option);
  435. switch (option) {
  436. case PR_SET_NAME: {
  437. // TODO: copy_from_user or check privilege
  438. SYSCALL_ARG2(const char* __user, name);
  439. current_thread->name.assign(name, 15);
  440. break;
  441. }
  442. case PR_GET_NAME: {
  443. SYSCALL_ARG2(char* __user, name);
  444. // TODO: copy_to_user
  445. strncpy(name, current_thread->name.c_str(), 16);
  446. name[15] = 0;
  447. break;
  448. }
  449. default:
  450. return -EINVAL;
  451. }
  452. return 0;
  453. }
  454. int _syscall_clock_gettime64(interrupt_stack* data)
  455. {
  456. SYSCALL_ARG1(clockid_t, clk_id);
  457. SYSCALL_ARG2(timespec* __user, tp);
  458. // TODO: check privilege of tp
  459. if (clk_id != CLOCK_REALTIME || !tp)
  460. return -EINVAL;
  461. tp->tv_sec = 10 + current_ticks();
  462. tp->tv_nsec = 0;
  463. return 0;
  464. }
  465. int _syscall_getuid(interrupt_stack*)
  466. {
  467. return 0; // all user is root for now
  468. }
  469. int _syscall_brk(interrupt_stack* data)
  470. {
  471. SYSCALL_ARG1(void*, addr);
  472. return (int)current_process->mms.set_brk(addr);
  473. }
  474. int _syscall_mmap_pgoff(interrupt_stack* data)
  475. {
  476. SYSCALL_ARG1(void*, addr);
  477. SYSCALL_ARG2(size_t, len);
  478. SYSCALL_ARG3(int, prot);
  479. SYSCALL_ARG4(int, flags);
  480. SYSCALL_ARG5(int, fd);
  481. SYSCALL_ARG6(off_t, pgoffset);
  482. if ((ptr_t)addr % PAGE_SIZE != 0)
  483. return -EINVAL;
  484. if (len == 0)
  485. return -EINVAL;
  486. len = align_up<12>(len);
  487. // TODO: shared mappings
  488. if (flags & MAP_SHARED)
  489. return -ENOMEM;
  490. if (flags & MAP_ANONYMOUS) {
  491. if (fd != -1)
  492. return -EINVAL;
  493. if (pgoffset != 0)
  494. return -EINVAL;
  495. if (!(flags & MAP_PRIVATE))
  496. return -EINVAL;
  497. auto& mms = current_process->mms;
  498. // do unmapping, equal to munmap, MAP_FIXED set
  499. if (prot == PROT_NONE) {
  500. auto ret = mms.unmap(addr, len, false);
  501. if (ret != GB_OK)
  502. return ret;
  503. }
  504. else {
  505. // TODO: add NULL check in mm_list
  506. if (!addr || !mms.is_avail(addr, len)) {
  507. if (flags & MAP_FIXED)
  508. return -ENOMEM;
  509. addr = mms.find_avail(addr, len, false);
  510. }
  511. // TODO: append pages to the end of area if possible
  512. mms.add_empty_area(addr, len / PAGE_SIZE,
  513. PAGE_COW, prot & PROT_WRITE, false);
  514. }
  515. }
  516. return (int)addr;
  517. }
  518. int _syscall_munmap(interrupt_stack* data)
  519. {
  520. SYSCALL_ARG1(void*, addr);
  521. SYSCALL_ARG2(size_t, len);
  522. if ((ptr_t)addr % PAGE_SIZE != 0)
  523. return -EINVAL;
  524. return current_process->mms.unmap(addr, len, false);
  525. }
  526. [[noreturn]] static void not_implemented()
  527. {
  528. console->print("\n[kernel] this function is not implemented\n");
  529. kill_current(-1);
  530. }
  531. int _syscall_sendfile64(interrupt_stack*)
  532. {
  533. not_implemented();
  534. // SYSCALL_ARG1(int, out_fd);
  535. // SYSCALL_ARG2(int, in_fd);
  536. // SYSCALL_ARG3(off_t*, offset);
  537. // SYSCALL_ARG4(size_t, count);
  538. // auto* out_file = current_process->files[out_fd];
  539. // auto* in_file = current_process->files[in_fd];
  540. // if (!out_file || !in_file)
  541. // return -EBADF;
  542. // if (out_file->type != fs::file::types::ind
  543. // || in_file->type != fs::file::types::ind)
  544. // return -EINVAL;
  545. // if (!out_file->flags.write || !in_file->flags.read)
  546. // return -EBADF;
  547. // if (out_file->ptr.ind->flags.in.directory
  548. // || in_file->ptr.ind->flags.in.directory)
  549. // return -EBADF;
  550. // if (offset)
  551. // return -EINVAL;
  552. }
  553. int _syscall_statx(interrupt_stack* data)
  554. {
  555. SYSCALL_ARG1(int, dirfd);
  556. SYSCALL_ARG2(const char* __user, path);
  557. SYSCALL_ARG3(int, flags);
  558. SYSCALL_ARG4(unsigned int, mask);
  559. SYSCALL_ARG5(statx* __user, statxbuf);
  560. // AT_STATX_SYNC_TYPE is the default value
  561. if (flags != 0 && !(flags & AT_STATX_SYNC_TYPE))
  562. not_implemented();
  563. if (dirfd != AT_FDCWD)
  564. not_implemented();
  565. auto* dent = fs::vfs_open(*current_process->root,
  566. current_process->pwd.c_str(), path);
  567. if (!dent)
  568. return -ENOENT;
  569. // TODO: copy to user
  570. auto ret = fs::vfs_stat(dent, statxbuf, mask);
  571. return ret;
  572. }
  573. int _syscall_fcntl64(interrupt_stack* data)
  574. {
  575. SYSCALL_ARG1(int, fd);
  576. SYSCALL_ARG2(int, cmd);
  577. SYSCALL_ARG3(unsigned long, arg);
  578. auto* file = current_process->files[fd];
  579. if (!file)
  580. return -EBADF;
  581. switch (cmd) {
  582. case F_SETFD:
  583. file->flags.close_on_exec = !!(arg & FD_CLOEXEC);
  584. return 0;
  585. default:
  586. not_implemented();
  587. return -EINVAL;
  588. }
  589. }
  590. extern "C" void syscall_entry(interrupt_stack* data)
  591. {
  592. int syscall_no = SYSCALL_NO;
  593. if (syscall_no >= SYSCALL_HANDLERS_SIZE
  594. || !syscall_handlers[syscall_no]) {
  595. char buf[64];
  596. snprintf(buf, 64,
  597. "[kernel] syscall %x not implemented\n", syscall_no);
  598. console->print(buf);
  599. kill_current(-1);
  600. }
  601. int ret = syscall_handlers[syscall_no](data);
  602. SYSCALL_RETVAL = ret;
  603. check_signal();
  604. }
  605. SECTION(".text.kinit")
  606. void init_syscall(void)
  607. {
  608. memset(syscall_handlers, 0x00, sizeof(syscall_handlers));
  609. syscall_handlers[0x01] = _syscall_exit;
  610. syscall_handlers[0x02] = _syscall_fork;
  611. syscall_handlers[0x03] = _syscall_read;
  612. syscall_handlers[0x04] = _syscall_write;
  613. syscall_handlers[0x05] = _syscall_open;
  614. syscall_handlers[0x06] = _syscall_close;
  615. syscall_handlers[0x07] = _syscall_waitpid;
  616. syscall_handlers[0x0b] = _syscall_execve;
  617. syscall_handlers[0x0c] = _syscall_chdir;
  618. syscall_handlers[0x14] = _syscall_getpid;
  619. syscall_handlers[0x29] = _syscall_dup;
  620. syscall_handlers[0x2a] = _syscall_pipe;
  621. syscall_handlers[0x2d] = _syscall_brk;
  622. syscall_handlers[0x36] = _syscall_ioctl;
  623. syscall_handlers[0x39] = _syscall_setpgid;
  624. syscall_handlers[0x3f] = _syscall_dup2;
  625. syscall_handlers[0x40] = _syscall_getppid;
  626. syscall_handlers[0x42] = _syscall_setsid;
  627. syscall_handlers[0x5b] = _syscall_munmap;
  628. syscall_handlers[0x84] = _syscall_getdents;
  629. syscall_handlers[0x92] = _syscall_writev;
  630. syscall_handlers[0x93] = _syscall_getsid;
  631. syscall_handlers[0xac] = _syscall_prctl;
  632. syscall_handlers[0xb7] = _syscall_getcwd;
  633. syscall_handlers[0xc0] = _syscall_mmap_pgoff;
  634. syscall_handlers[0xc7] = _syscall_getuid;
  635. syscall_handlers[0xdd] = _syscall_fcntl64;
  636. syscall_handlers[0xef] = _syscall_sendfile64;
  637. syscall_handlers[0xf3] = _syscall_set_thread_area;
  638. syscall_handlers[0xfc] = _syscall_exit; // we implement exit_group as exit for now
  639. syscall_handlers[0x102] = _syscall_set_tid_address;
  640. syscall_handlers[0x17f] = _syscall_statx;
  641. syscall_handlers[0x193] = _syscall_clock_gettime64;
  642. // syscall_handlers[35] = _syscall_sleep;
  643. }