syscall.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994
  1. #include <asm/port_io.h>
  2. #include <asm/sys.h>
  3. #include <assert.h>
  4. #include <errno.h>
  5. #include <stdint.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <time.h>
  9. #include <bits/alltypes.h>
  10. #include <bits/ioctl.h>
  11. #include <sys/types.h>
  12. #include <sys/prctl.h>
  13. #include <sys/mman.h>
  14. #include <sys/stat.h>
  15. #include <sys/utsname.h>
  16. #include <kernel/user/thread_local.hpp>
  17. #include <kernel/interrupt.h>
  18. #include <kernel/log.hpp>
  19. #include <kernel/mem.h>
  20. #include <kernel/mm.hpp>
  21. #include <kernel/process.hpp>
  22. #include <kernel/signal.hpp>
  23. #include <kernel/syscall.hpp>
  24. #include <kernel/tty.hpp>
  25. #include <kernel/utsname.hpp>
  26. #include <kernel/vfs.hpp>
  27. #include <kernel/hw/timer.h>
  28. #include <types/allocator.hpp>
  29. #include <types/elf.hpp>
  30. #include <types/path.hpp>
  31. #include <types/lock.hpp>
  32. #include <types/status.h>
  33. #include <types/string.hpp>
  34. #include <types/types.h>
  35. #define SYSCALL_NO ((data)->s_regs.eax)
  36. #define SYSCALL_RETVAL ((data)->s_regs.eax)
  37. #define SYSCALL_ARG1(type, name) type name = (type)((data)->s_regs.ebx)
  38. #define SYSCALL_ARG2(type, name) type name = (type)((data)->s_regs.ecx)
  39. #define SYSCALL_ARG3(type, name) type name = (type)((data)->s_regs.edx)
  40. #define SYSCALL_ARG4(type, name) type name = (type)((data)->s_regs.esi)
  41. #define SYSCALL_ARG5(type, name) type name = (type)((data)->s_regs.edi)
  42. #define SYSCALL_ARG6(type, name) type name = (type)((data)->s_regs.ebp)
  43. #define SYSCALL_HANDLERS_SIZE (404)
  44. syscall_handler syscall_handlers[SYSCALL_HANDLERS_SIZE];
  45. static void not_implemented()
  46. {
  47. console->print("\n[kernel] this function is not implemented\n");
  48. current_thread->send_signal(SIGSYS);
  49. }
  50. extern "C" void _syscall_stub_fork_return(void);
  51. int _syscall_fork(interrupt_stack* data)
  52. {
  53. auto& newproc = procs->copy_from(*current_process);
  54. auto [ iter_newthd, inserted ] = newproc.thds.emplace(*current_thread, newproc.pid);
  55. assert(inserted);
  56. auto* newthd = &*iter_newthd;
  57. readythds->push(newthd);
  58. uint32_t newthd_oldesp = (uint32_t)newthd->esp;
  59. // create fake interrupt stack
  60. push_stack(&newthd->esp, data->ss);
  61. push_stack(&newthd->esp, data->esp);
  62. push_stack(&newthd->esp, data->eflags);
  63. push_stack(&newthd->esp, data->cs);
  64. push_stack(&newthd->esp, (uint32_t)data->v_eip);
  65. // eax
  66. push_stack(&newthd->esp, 0);
  67. push_stack(&newthd->esp, data->s_regs.ecx);
  68. // edx
  69. push_stack(&newthd->esp, 0);
  70. push_stack(&newthd->esp, data->s_regs.ebx);
  71. push_stack(&newthd->esp, data->s_regs.esp);
  72. push_stack(&newthd->esp, data->s_regs.ebp);
  73. push_stack(&newthd->esp, data->s_regs.esi);
  74. push_stack(&newthd->esp, data->s_regs.edi);
  75. // ctx_switch stack
  76. // return address
  77. push_stack(&newthd->esp, (uint32_t)_syscall_stub_fork_return);
  78. // ebx
  79. push_stack(&newthd->esp, 0);
  80. // edi
  81. push_stack(&newthd->esp, 0);
  82. // esi
  83. push_stack(&newthd->esp, 0);
  84. // ebp
  85. push_stack(&newthd->esp, 0);
  86. // eflags
  87. push_stack(&newthd->esp, 0);
  88. // original esp
  89. push_stack(&newthd->esp, newthd_oldesp);
  90. return newproc.pid;
  91. }
  92. int _syscall_write(interrupt_stack* data)
  93. {
  94. SYSCALL_ARG1(int, fd);
  95. SYSCALL_ARG2(const char* __user, buf);
  96. SYSCALL_ARG3(size_t, n);
  97. auto* file = current_process->files[fd];
  98. if (!file)
  99. return -EBADF;
  100. return file->write(buf, n);
  101. }
  102. int _syscall_read(interrupt_stack* data)
  103. {
  104. SYSCALL_ARG1(int, fd);
  105. SYSCALL_ARG2(char* __user, buf);
  106. SYSCALL_ARG3(size_t, n);
  107. auto* file = current_process->files[fd];
  108. if (!file)
  109. return -EBADF;
  110. return file->read(buf, n);
  111. }
  112. // TODO: sleep seconds
  113. int _syscall_sleep(interrupt_stack*)
  114. {
  115. current_thread->sleep();
  116. schedule();
  117. return 0;
  118. }
  119. int _syscall_chdir(interrupt_stack* data)
  120. {
  121. SYSCALL_ARG1(const char*, path);
  122. auto* dir = fs::vfs_open(*current_process->root,
  123. types::make_path(path, current_process->pwd));
  124. if (!dir)
  125. return -ENOENT;
  126. if (!S_ISDIR(dir->ind->mode))
  127. return -ENOTDIR;
  128. current_process->pwd.clear();
  129. dir->path(*current_process->root, current_process->pwd);
  130. return 0;
  131. }
  132. // syscall_exec(const char* exec, const char** argv)
  133. // @param exec: the path of program to execute
  134. // @param argv: arguments end with nullptr
  135. // @param envp: environment variables end with nullptr
  136. int _syscall_execve(interrupt_stack* data)
  137. {
  138. SYSCALL_ARG1(const char*, exec);
  139. SYSCALL_ARG2(char* const*, argv);
  140. SYSCALL_ARG3(char* const*, envp);
  141. types::elf::elf32_load_data d;
  142. d.argv = argv;
  143. d.envp = envp;
  144. d.system = false;
  145. d.exec_dent = fs::vfs_open(*current_process->root,
  146. types::make_path(exec, current_process->pwd));
  147. if (!d.exec_dent)
  148. return -ENOENT;
  149. current_process->files.onexec();
  150. int ret = types::elf::elf32_load(&d);
  151. if (ret != GB_OK)
  152. return -d.errcode;
  153. data->v_eip = d.eip;
  154. data->esp = (uint32_t)d.sp;
  155. current_thread->signals.on_exec();
  156. return 0;
  157. }
  158. // @param exit_code
  159. int NORETURN _syscall_exit(interrupt_stack* data)
  160. {
  161. SYSCALL_ARG1(int, exit_code);
  162. // TODO: terminating a thread only
  163. if (current_process->thds.size() != 1)
  164. assert(false);
  165. // terminating a whole process:
  166. procs->kill(current_process->pid, exit_code & 0xff);
  167. // switch to new process and continue
  168. schedule_noreturn();
  169. }
  170. // @param pid: pid of the process to wait
  171. // @param status: the exit code of the exited process
  172. // @param options: options for waitpid
  173. // @return pid of the exited process
  174. int _syscall_waitpid(interrupt_stack* data)
  175. {
  176. SYSCALL_ARG1(pid_t, pid_to_wait);
  177. SYSCALL_ARG2(int*, arg1);
  178. SYSCALL_ARG3(int, options);
  179. if (pid_to_wait != -1)
  180. return -EINVAL;
  181. auto& cv = current_process->cv_wait;
  182. auto& mtx = cv.mtx();
  183. types::lock_guard lck(mtx);
  184. auto& waitlist = current_process->waitlist;
  185. // TODO: check if it is waiting for stopped process
  186. (void)options;
  187. while (waitlist.empty()) {
  188. if (current_process->children.empty())
  189. return -ECHILD;
  190. cv.wait(mtx);
  191. // TODO: check WNOHANG
  192. // if (!cv.wait(mtx))
  193. // return -EINTR;
  194. }
  195. auto iter = waitlist.begin();
  196. assert(iter != waitlist.end());
  197. auto& obj = *iter;
  198. pid_t pid = obj.pid;
  199. // TODO: copy_to_user check privilege
  200. *arg1 = obj.code;
  201. procs->remove(pid);
  202. waitlist.erase(iter);
  203. return pid;
  204. }
  205. int _syscall_wait4(interrupt_stack* data)
  206. {
  207. SYSCALL_ARG4(void* __user, rusage);
  208. // TODO: getrusage
  209. if (rusage)
  210. return -EINVAL;
  211. return _syscall_waitpid(data);
  212. }
  213. int _syscall_getdents(interrupt_stack* data)
  214. {
  215. SYSCALL_ARG1(int, fd);
  216. SYSCALL_ARG2(char* __user, buf);
  217. SYSCALL_ARG3(size_t, cnt);
  218. auto* dir = current_process->files[fd];
  219. if (!dir)
  220. return -EBADF;
  221. return dir->getdents(buf, cnt);
  222. }
  223. int _syscall_open(interrupt_stack* data)
  224. {
  225. SYSCALL_ARG1(const char* __user, path);
  226. SYSCALL_ARG2(int, flags);
  227. SYSCALL_ARG3(mode_t, mode);
  228. mode &= ~current_process->umask;
  229. return current_process->files.open(*current_process,
  230. types::make_path(path, current_process->pwd), flags, mode);
  231. }
  232. int _syscall_getcwd(interrupt_stack* data)
  233. {
  234. SYSCALL_ARG1(char*, buf);
  235. SYSCALL_ARG2(size_t, bufsize);
  236. // TODO: use copy_to_user
  237. auto path = current_process->pwd.full_path();
  238. strncpy(buf, path.c_str(), bufsize);
  239. buf[bufsize - 1] = 0;
  240. return (uint32_t)buf;
  241. }
  242. int _syscall_setsid(interrupt_stack*)
  243. {
  244. if (current_process->pid == current_process->pgid)
  245. return -EPERM;
  246. current_process->sid = current_process->pid;
  247. current_process->pgid = current_process->pid;
  248. // TODO: get tty* from fd or block device id
  249. console->set_pgrp(current_process->pid);
  250. current_process->control_tty = console;
  251. return current_process->pid;
  252. }
  253. int _syscall_getsid(interrupt_stack* data)
  254. {
  255. SYSCALL_ARG1(pid_t, pid);
  256. if (!procs->try_find(pid))
  257. return -ESRCH;
  258. auto& proc = procs->find(pid);
  259. if (proc.sid != current_process->sid)
  260. return -EPERM;
  261. return proc.sid;
  262. }
  263. int _syscall_close(interrupt_stack* data)
  264. {
  265. SYSCALL_ARG1(int, fd);
  266. current_process->files.close(fd);
  267. return 0;
  268. }
  269. int _syscall_dup(interrupt_stack* data)
  270. {
  271. SYSCALL_ARG1(int, old_fd);
  272. return current_process->files.dup(old_fd);
  273. }
  274. int _syscall_dup2(interrupt_stack* data)
  275. {
  276. SYSCALL_ARG1(int, old_fd);
  277. SYSCALL_ARG2(int, new_fd);
  278. return current_process->files.dup2(old_fd, new_fd);
  279. }
  280. int _syscall_pipe(interrupt_stack* data)
  281. {
  282. SYSCALL_ARG1(int* __user, pipefd);
  283. return current_process->files.pipe(pipefd);
  284. }
  285. int _syscall_setpgid(interrupt_stack* data)
  286. {
  287. SYSCALL_ARG1(pid_t, pid);
  288. SYSCALL_ARG2(pid_t, pgid);
  289. if (pgid < 0)
  290. return -EINVAL;
  291. if (pid == 0)
  292. pid = current_process->pid;
  293. if (pgid == 0)
  294. pgid = pid;
  295. if (!procs->try_find(pid))
  296. return -ESRCH;
  297. auto& proc = procs->find(pid);
  298. // TODO: check whether pgid and the original
  299. // pgid is in the same session
  300. proc.pgid = pgid;
  301. return 0;
  302. }
  303. int _syscall_ioctl(interrupt_stack* data)
  304. {
  305. SYSCALL_ARG1(int, fd);
  306. SYSCALL_ARG2(unsigned long, request);
  307. // TODO: check fd type and get tty* from fd
  308. //
  309. // we use a trick for now, check whether
  310. // the file that fd points to is a pipe or
  311. // not. and we suppose that stdin will be
  312. // either a tty or a pipe.
  313. auto* file = current_process->files[fd];
  314. if (!file || !S_ISCHR(file->mode))
  315. return -ENOTTY;
  316. switch (request) {
  317. case TIOCGPGRP: {
  318. SYSCALL_ARG3(pid_t*, pgid);
  319. tty* ctrl_tty = current_process->control_tty;
  320. // TODO: copy_to_user
  321. *pgid = ctrl_tty->get_pgrp();
  322. break;
  323. }
  324. case TIOCSPGRP: {
  325. // TODO: copy_from_user
  326. SYSCALL_ARG3(const pid_t*, pgid);
  327. tty* ctrl_tty = current_process->control_tty;
  328. ctrl_tty->set_pgrp(*pgid);
  329. break;
  330. }
  331. case TIOCGWINSZ: {
  332. SYSCALL_ARG3(winsize*, ws);
  333. ws->ws_col = 80;
  334. ws->ws_row = 10;
  335. break;
  336. }
  337. default:
  338. not_implemented();
  339. return -EINVAL;
  340. }
  341. return 0;
  342. }
  343. int _syscall_getpid(interrupt_stack*)
  344. {
  345. return current_process->pid;
  346. }
  347. int _syscall_getppid(interrupt_stack*)
  348. {
  349. return current_process->ppid;
  350. }
  351. int _syscall_set_thread_area(interrupt_stack* data)
  352. {
  353. SYSCALL_ARG1(kernel::user::user_desc* __user, ptr);
  354. return kernel::user::set_thread_area(ptr);
  355. }
  356. int _syscall_set_tid_address(interrupt_stack* data)
  357. {
  358. SYSCALL_ARG1(int* __user, tidptr);
  359. current_thread->set_child_tid = tidptr;
  360. return current_thread->tid();
  361. }
  362. // TODO: this operation SHOULD be atomic
  363. ssize_t _syscall_writev(interrupt_stack* data)
  364. {
  365. SYSCALL_ARG1(int, fd);
  366. SYSCALL_ARG2(const iovec* __user, iov);
  367. SYSCALL_ARG3(int, iovcnt);
  368. auto* file = current_process->files[fd];
  369. if (!file)
  370. return -EBADF;
  371. ssize_t totn = 0;
  372. for (int i = 0; i < iovcnt; ++i) {
  373. ssize_t ret = file->write(
  374. (const char*)iov[i].iov_base, iov[i].iov_len);
  375. if (ret < 0)
  376. return ret;
  377. totn += ret;
  378. }
  379. return totn;
  380. }
  381. int _syscall_prctl(interrupt_stack* data)
  382. {
  383. SYSCALL_ARG1(int, option);
  384. switch (option) {
  385. case PR_SET_NAME: {
  386. // TODO: copy_from_user or check privilege
  387. SYSCALL_ARG2(const char* __user, name);
  388. current_thread->name.assign(name, 15);
  389. break;
  390. }
  391. case PR_GET_NAME: {
  392. SYSCALL_ARG2(char* __user, name);
  393. // TODO: copy_to_user
  394. strncpy(name, current_thread->name.c_str(), 16);
  395. name[15] = 0;
  396. break;
  397. }
  398. default:
  399. return -EINVAL;
  400. }
  401. return 0;
  402. }
  403. int _syscall_clock_gettime64(interrupt_stack* data)
  404. {
  405. SYSCALL_ARG1(clockid_t, clk_id);
  406. SYSCALL_ARG2(timespec* __user, tp);
  407. // TODO: check privilege of tp
  408. if (clk_id != CLOCK_REALTIME || !tp)
  409. return -EINVAL;
  410. tp->tv_sec = 10 + current_ticks();
  411. tp->tv_nsec = 0;
  412. return 0;
  413. }
  414. int _syscall_getuid(interrupt_stack*)
  415. {
  416. return 0; // all user are root for now
  417. }
  418. int _syscall_geteuid(interrupt_stack*)
  419. {
  420. return 0; // all user are root for now
  421. }
  422. int _syscall_brk(interrupt_stack* data)
  423. {
  424. SYSCALL_ARG1(void*, addr);
  425. return (int)current_process->mms.set_brk(addr);
  426. }
  427. int _syscall_mmap_pgoff(interrupt_stack* data)
  428. {
  429. SYSCALL_ARG1(void*, addr);
  430. SYSCALL_ARG2(size_t, len);
  431. SYSCALL_ARG3(int, prot);
  432. SYSCALL_ARG4(int, flags);
  433. SYSCALL_ARG5(int, fd);
  434. SYSCALL_ARG6(off_t, pgoffset);
  435. if ((ptr_t)addr % PAGE_SIZE != 0)
  436. return -EINVAL;
  437. if (len == 0)
  438. return -EINVAL;
  439. len = align_up<12>(len);
  440. // TODO: shared mappings
  441. if (flags & MAP_SHARED)
  442. return -ENOMEM;
  443. if (flags & MAP_ANONYMOUS) {
  444. if (fd != -1)
  445. return -EINVAL;
  446. if (pgoffset != 0)
  447. return -EINVAL;
  448. if (!(flags & MAP_PRIVATE))
  449. return -EINVAL;
  450. auto& mms = current_process->mms;
  451. // do unmapping, equal to munmap, MAP_FIXED set
  452. if (prot == PROT_NONE) {
  453. auto ret = mms.unmap(addr, len, false);
  454. if (ret != GB_OK)
  455. return ret;
  456. }
  457. else {
  458. // TODO: add NULL check in mm_list
  459. if (!addr || !mms.is_avail(addr, len)) {
  460. if (flags & MAP_FIXED)
  461. return -ENOMEM;
  462. addr = mms.find_avail(addr, len, false);
  463. }
  464. // TODO: append pages to the end of area if possible
  465. mms.add_empty_area(addr, len / PAGE_SIZE,
  466. PAGE_COW, prot & PROT_WRITE, false);
  467. }
  468. }
  469. return (int)addr;
  470. }
  471. int _syscall_munmap(interrupt_stack* data)
  472. {
  473. SYSCALL_ARG1(void*, addr);
  474. SYSCALL_ARG2(size_t, len);
  475. if ((ptr_t)addr % PAGE_SIZE != 0)
  476. return -EINVAL;
  477. return current_process->mms.unmap(addr, len, false);
  478. }
  479. int _syscall_sendfile64(interrupt_stack* data)
  480. {
  481. SYSCALL_ARG1(int, out_fd);
  482. SYSCALL_ARG2(int, in_fd);
  483. SYSCALL_ARG3(off64_t*, offset);
  484. SYSCALL_ARG4(size_t, count);
  485. auto* out_file = current_process->files[out_fd];
  486. auto* in_file = current_process->files[in_fd];
  487. if (!out_file || !in_file)
  488. return -EBADF;
  489. // TODO: check whether in_fd supports mmapping
  490. if (!S_ISREG(in_file->mode) && !S_ISBLK(in_file->mode))
  491. return -EINVAL;
  492. if (offset) {
  493. not_implemented();
  494. return -EINVAL;
  495. }
  496. constexpr size_t bufsize = 512;
  497. std::vector<char> buf(bufsize);
  498. size_t totn = 0;
  499. while (totn < count) {
  500. size_t n = std::min(count - totn, bufsize);
  501. ssize_t ret = in_file->read(buf.data(), n);
  502. if (ret < 0)
  503. return ret;
  504. if (ret == 0)
  505. break;
  506. ret = out_file->write(buf.data(), ret);
  507. if (ret < 0)
  508. return ret;
  509. totn += ret;
  510. }
  511. return totn;
  512. }
  513. int _syscall_statx(interrupt_stack* data)
  514. {
  515. SYSCALL_ARG1(int, dirfd);
  516. SYSCALL_ARG2(const char* __user, path);
  517. SYSCALL_ARG3(int, flags);
  518. SYSCALL_ARG4(unsigned int, mask);
  519. SYSCALL_ARG5(statx* __user, statxbuf);
  520. // AT_STATX_SYNC_AS_STAT is the default value
  521. if (flags != AT_STATX_SYNC_AS_STAT && !(flags & AT_SYMLINK_NOFOLLOW)) {
  522. not_implemented();
  523. return -EINVAL;
  524. }
  525. if (dirfd != AT_FDCWD) {
  526. not_implemented();
  527. return -EINVAL;
  528. }
  529. auto* dent = fs::vfs_open(*current_process->root,
  530. types::make_path(path, current_process->pwd));
  531. if (!dent)
  532. return -ENOENT;
  533. // TODO: copy to user
  534. auto ret = fs::vfs_stat(dent, statxbuf, mask);
  535. return ret;
  536. }
  537. int _syscall_fcntl64(interrupt_stack* data)
  538. {
  539. SYSCALL_ARG1(int, fd);
  540. SYSCALL_ARG2(int, cmd);
  541. SYSCALL_ARG3(unsigned long, arg);
  542. auto* file = current_process->files[fd];
  543. if (!file)
  544. return -EBADF;
  545. switch (cmd) {
  546. case F_SETFD:
  547. return current_process->files.set_flags(
  548. fd, (arg & FD_CLOEXEC) ? O_CLOEXEC : 0);
  549. case F_DUPFD:
  550. case F_DUPFD_CLOEXEC: {
  551. int flag = (cmd & F_DUPFD_CLOEXEC) ? O_CLOEXEC : 0;
  552. return current_process->files.dupfd(fd, arg, flag);
  553. }
  554. default:
  555. not_implemented();
  556. return -EINVAL;
  557. }
  558. }
  559. int _syscall_getdents64(interrupt_stack* data)
  560. {
  561. SYSCALL_ARG1(int, fd);
  562. SYSCALL_ARG2(char* __user, buf);
  563. SYSCALL_ARG3(size_t, cnt);
  564. auto* dir = current_process->files[fd];
  565. if (!dir)
  566. return -EBADF;
  567. return dir->getdents64(buf, cnt);
  568. }
  569. /* TODO: implement vfs_stat(stat*)
  570. int _syscall_stat(interrupt_stack* data)
  571. {
  572. SYSCALL_ARG1(const char* __user, pathname);
  573. SYSCALL_ARG2(struct stat* __user, buf);
  574. auto* dent = fs::vfs_open(*current_process->root,
  575. types::make_path(pathname, current_process->pwd));
  576. if (!dent)
  577. return -ENOENT;
  578. return fs::vfs_stat(dent, buf);
  579. }
  580. */
  581. /* TODO: implement vfs_stat(stat*)
  582. int _syscall_fstat(interrupt_stack* data)
  583. {
  584. SYSCALL_ARG1(int, fd);
  585. SYSCALL_ARG2(struct stat* __user, buf);
  586. auto* file = current_process->files[fd];
  587. if (!file)
  588. return -EBADF;
  589. return fs::vfs_stat(file, buf);
  590. }
  591. */
  592. int _syscall_gettimeofday(interrupt_stack* data)
  593. {
  594. SYSCALL_ARG1(timeval* __user, tv);
  595. SYSCALL_ARG2(void* __user, tz);
  596. // TODO: return time of the day, not time from this boot
  597. if (unlikely(tz))
  598. return -EINVAL;
  599. if (likely(tv)) {
  600. // TODO: use copy_to_user
  601. tv->tv_sec = current_ticks() / 100;
  602. tv->tv_usec = current_ticks() * 10 * 1000;
  603. }
  604. return 0;
  605. }
  606. int _syscall_umask(interrupt_stack* data)
  607. {
  608. SYSCALL_ARG1(mode_t, mask);
  609. mode_t old = current_process->umask;
  610. current_process->umask = mask;
  611. return old;
  612. }
  613. int _syscall_kill(interrupt_stack* data)
  614. {
  615. SYSCALL_ARG1(pid_t, pid);
  616. SYSCALL_ARG2(int, sig);
  617. if (!procs->try_find(pid))
  618. return -ESRCH;
  619. if (!kernel::signal_list::check_valid(sig))
  620. return -EINVAL;
  621. if (procs->find(pid).is_system())
  622. return 0;
  623. // TODO: check permission
  624. procs->send_signal(pid, sig);
  625. return 0;
  626. }
  627. int _syscall_rt_sigprocmask(interrupt_stack* data)
  628. {
  629. using kernel::sigmask_type;
  630. SYSCALL_ARG1(int, how);
  631. SYSCALL_ARG2(const sigmask_type* __user, set);
  632. SYSCALL_ARG3(sigmask_type* __user, oldset);
  633. SYSCALL_ARG4(size_t, sigsetsize);
  634. if (sigsetsize != sizeof(sigmask_type))
  635. return -EINVAL;
  636. sigmask_type sigs = current_thread->signals.get_mask();
  637. // TODO: use copy_to_user
  638. if (oldset)
  639. memcpy(oldset, &sigs, sizeof(sigmask_type));
  640. if (!set)
  641. return 0;
  642. // TODO: use copy_from_user
  643. switch (how) {
  644. case SIG_BLOCK:
  645. current_thread->signals.mask(*set);
  646. break;
  647. case SIG_UNBLOCK:
  648. current_thread->signals.unmask(*set);
  649. break;
  650. case SIG_SETMASK:
  651. current_thread->signals.set_mask(*set);
  652. break;
  653. }
  654. return 0;
  655. }
  656. int _syscall_rt_sigaction(interrupt_stack* data)
  657. {
  658. using kernel::sigaction;
  659. using kernel::sigmask_type;
  660. SYSCALL_ARG1(int, signum);
  661. SYSCALL_ARG2(const sigaction* __user, act);
  662. SYSCALL_ARG3(sigaction* __user, oldact);
  663. SYSCALL_ARG4(size_t, sigsetsize);
  664. if (sigsetsize != sizeof(sigmask_type))
  665. return -EINVAL;
  666. if (!kernel::signal_list::check_valid(signum)
  667. || signum == SIGKILL || signum == SIGSTOP)
  668. return -EINVAL;
  669. // TODO: use copy_to_user
  670. if (oldact)
  671. current_thread->signals.get_handler(signum, *oldact);
  672. if (!act)
  673. return 0;
  674. // TODO: use copy_from_user
  675. current_thread->signals.set_handler(signum, *act);
  676. return 0;
  677. }
  678. int _syscall_newuname(interrupt_stack* data)
  679. {
  680. SYSCALL_ARG1(new_utsname* __user, buf);
  681. if (!buf)
  682. return -EFAULT;
  683. // TODO: use copy_to_user
  684. memcpy(buf, kernel::sys_utsname, sizeof(new_utsname));
  685. return 0;
  686. }
  687. pid_t _syscall_getpgid(interrupt_stack* data)
  688. {
  689. SYSCALL_ARG1(pid_t, pid);
  690. if (pid == 0)
  691. return current_process->pgid;
  692. if (!procs->try_find(pid))
  693. return -ESRCH;
  694. return procs->find(pid).pgid;
  695. }
  696. int _syscall_gettid(interrupt_stack* data)
  697. {
  698. // TODO: real tid
  699. (void)data;
  700. return current_process->pid;
  701. }
  702. int _syscall_mkdir(interrupt_stack* data)
  703. {
  704. SYSCALL_ARG1(const char* __user, pathname);
  705. SYSCALL_ARG2(mode_t, mode);
  706. mode &= (~current_process->umask & 0777);
  707. auto path = types::make_path(pathname, current_process->pwd);
  708. auto* dent = fs::vfs_open(*current_process->root, path);
  709. if (dent)
  710. return -EEXIST;
  711. // get parent path
  712. auto dirname = path.last_name();
  713. path.remove_last();
  714. dent = fs::vfs_open(*current_process->root, path);
  715. if (!dent)
  716. return -ENOENT;
  717. if (!S_ISDIR(dent->ind->mode))
  718. return -ENOTDIR;
  719. auto ret = fs::vfs_mkdir(dent, dirname.c_str(), mode);
  720. if (ret != GB_OK)
  721. return ret;
  722. return 0;
  723. }
  724. extern "C" void syscall_entry(interrupt_stack* data)
  725. {
  726. int syscall_no = SYSCALL_NO;
  727. if (syscall_no >= SYSCALL_HANDLERS_SIZE
  728. || !syscall_handlers[syscall_no]) {
  729. char buf[64];
  730. snprintf(buf, 64,
  731. "[kernel] syscall %x not implemented\n", syscall_no);
  732. console->print(buf);
  733. not_implemented();
  734. return;
  735. }
  736. int ret = syscall_handlers[syscall_no](data);
  737. SYSCALL_RETVAL = ret;
  738. current_thread->signals.handle();
  739. }
  740. SECTION(".text.kinit")
  741. void init_syscall(void)
  742. {
  743. memset(syscall_handlers, 0x00, sizeof(syscall_handlers));
  744. syscall_handlers[0x01] = _syscall_exit;
  745. syscall_handlers[0x02] = _syscall_fork;
  746. syscall_handlers[0x03] = _syscall_read;
  747. syscall_handlers[0x04] = _syscall_write;
  748. syscall_handlers[0x05] = _syscall_open;
  749. syscall_handlers[0x06] = _syscall_close;
  750. syscall_handlers[0x07] = _syscall_waitpid;
  751. syscall_handlers[0x0b] = _syscall_execve;
  752. syscall_handlers[0x0c] = _syscall_chdir;
  753. syscall_handlers[0x14] = _syscall_getpid;
  754. syscall_handlers[0x25] = _syscall_kill;
  755. syscall_handlers[0x27] = _syscall_mkdir;
  756. syscall_handlers[0x29] = _syscall_dup;
  757. syscall_handlers[0x2a] = _syscall_pipe;
  758. syscall_handlers[0x2d] = _syscall_brk;
  759. syscall_handlers[0x36] = _syscall_ioctl;
  760. syscall_handlers[0x39] = _syscall_setpgid;
  761. syscall_handlers[0x3c] = _syscall_umask;
  762. syscall_handlers[0x3f] = _syscall_dup2;
  763. syscall_handlers[0x40] = _syscall_getppid;
  764. syscall_handlers[0x42] = _syscall_setsid;
  765. syscall_handlers[0x4e] = _syscall_gettimeofday;
  766. syscall_handlers[0x5b] = _syscall_munmap;
  767. syscall_handlers[0x72] = _syscall_wait4;
  768. syscall_handlers[0x7a] = _syscall_newuname;
  769. syscall_handlers[0x84] = _syscall_getpgid;
  770. syscall_handlers[0x8d] = _syscall_getdents;
  771. syscall_handlers[0x92] = _syscall_writev;
  772. syscall_handlers[0x93] = _syscall_getsid;
  773. syscall_handlers[0xac] = _syscall_prctl;
  774. syscall_handlers[0xae] = _syscall_rt_sigaction;
  775. syscall_handlers[0xaf] = _syscall_rt_sigprocmask;
  776. syscall_handlers[0xb7] = _syscall_getcwd;
  777. syscall_handlers[0xc0] = _syscall_mmap_pgoff;
  778. syscall_handlers[0xc7] = _syscall_getuid;
  779. syscall_handlers[0xc9] = _syscall_geteuid;
  780. syscall_handlers[0xdc] = _syscall_getdents64;
  781. syscall_handlers[0xdd] = _syscall_fcntl64;
  782. syscall_handlers[0xe0] = _syscall_gettid;
  783. syscall_handlers[0xef] = _syscall_sendfile64;
  784. syscall_handlers[0xf3] = _syscall_set_thread_area;
  785. syscall_handlers[0xfc] = _syscall_exit; // we implement exit_group as exit for now
  786. syscall_handlers[0x102] = _syscall_set_tid_address;
  787. syscall_handlers[0x17f] = _syscall_statx;
  788. syscall_handlers[0x193] = _syscall_clock_gettime64;
  789. // syscall_handlers[35] = _syscall_sleep;
  790. }