syscall.cpp 29 KB

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