syscalls.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983
  1. /*
  2. * Syscall implementations for semihosting.
  3. *
  4. * Copyright (c) 2022 Linaro
  5. *
  6. * SPDX-License-Identifier: GPL-2.0-or-later
  7. */
  8. #include "qemu/osdep.h"
  9. #include "cpu.h"
  10. #include "gdbstub/syscalls.h"
  11. #include "semihosting/guestfd.h"
  12. #include "semihosting/syscalls.h"
  13. #include "semihosting/console.h"
  14. #ifdef CONFIG_USER_ONLY
  15. #include "qemu.h"
  16. #else
  17. #include "semihosting/uaccess.h"
  18. #endif
  19. /*
  20. * Validate or compute the length of the string (including terminator).
  21. */
  22. static int validate_strlen(CPUState *cs, target_ulong str, target_ulong tlen)
  23. {
  24. CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
  25. char c;
  26. if (tlen == 0) {
  27. ssize_t slen = target_strlen(str);
  28. if (slen < 0) {
  29. return -EFAULT;
  30. }
  31. if (slen >= INT32_MAX) {
  32. return -ENAMETOOLONG;
  33. }
  34. return slen + 1;
  35. }
  36. if (tlen > INT32_MAX) {
  37. return -ENAMETOOLONG;
  38. }
  39. if (get_user_u8(c, str + tlen - 1)) {
  40. return -EFAULT;
  41. }
  42. if (c != 0) {
  43. return -EINVAL;
  44. }
  45. return tlen;
  46. }
  47. static int validate_lock_user_string(char **pstr, CPUState *cs,
  48. target_ulong tstr, target_ulong tlen)
  49. {
  50. int ret = validate_strlen(cs, tstr, tlen);
  51. CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
  52. char *str = NULL;
  53. if (ret > 0) {
  54. str = lock_user(VERIFY_READ, tstr, ret, true);
  55. ret = str ? 0 : -EFAULT;
  56. }
  57. *pstr = str;
  58. return ret;
  59. }
  60. /*
  61. * TODO: Note that gdb always stores the stat structure big-endian.
  62. * So far, that's ok, as the only two targets using this are also
  63. * big-endian. Until we do something with gdb, also produce the
  64. * same big-endian result from the host.
  65. */
  66. static int copy_stat_to_user(CPUState *cs, target_ulong addr,
  67. const struct stat *s)
  68. {
  69. CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
  70. struct gdb_stat *p;
  71. if (s->st_dev != (uint32_t)s->st_dev ||
  72. s->st_ino != (uint32_t)s->st_ino) {
  73. return -EOVERFLOW;
  74. }
  75. p = lock_user(VERIFY_WRITE, addr, sizeof(struct gdb_stat), 0);
  76. if (!p) {
  77. return -EFAULT;
  78. }
  79. p->gdb_st_dev = cpu_to_be32(s->st_dev);
  80. p->gdb_st_ino = cpu_to_be32(s->st_ino);
  81. p->gdb_st_mode = cpu_to_be32(s->st_mode);
  82. p->gdb_st_nlink = cpu_to_be32(s->st_nlink);
  83. p->gdb_st_uid = cpu_to_be32(s->st_uid);
  84. p->gdb_st_gid = cpu_to_be32(s->st_gid);
  85. p->gdb_st_rdev = cpu_to_be32(s->st_rdev);
  86. p->gdb_st_size = cpu_to_be64(s->st_size);
  87. #ifdef _WIN32
  88. /* Windows stat is missing some fields. */
  89. p->gdb_st_blksize = 0;
  90. p->gdb_st_blocks = 0;
  91. #else
  92. p->gdb_st_blksize = cpu_to_be64(s->st_blksize);
  93. p->gdb_st_blocks = cpu_to_be64(s->st_blocks);
  94. #endif
  95. p->gdb_st_atime = cpu_to_be32(s->st_atime);
  96. p->gdb_st_mtime = cpu_to_be32(s->st_mtime);
  97. p->gdb_st_ctime = cpu_to_be32(s->st_ctime);
  98. unlock_user(p, addr, sizeof(struct gdb_stat));
  99. return 0;
  100. }
  101. /*
  102. * GDB semihosting syscall implementations.
  103. */
  104. static gdb_syscall_complete_cb gdb_open_complete;
  105. static void gdb_open_cb(CPUState *cs, uint64_t ret, int err)
  106. {
  107. if (!err) {
  108. int guestfd = alloc_guestfd();
  109. associate_guestfd(guestfd, ret);
  110. ret = guestfd;
  111. }
  112. gdb_open_complete(cs, ret, err);
  113. }
  114. static void gdb_open(CPUState *cs, gdb_syscall_complete_cb complete,
  115. target_ulong fname, target_ulong fname_len,
  116. int gdb_flags, int mode)
  117. {
  118. int len = validate_strlen(cs, fname, fname_len);
  119. if (len < 0) {
  120. complete(cs, -1, -len);
  121. return;
  122. }
  123. gdb_open_complete = complete;
  124. gdb_do_syscall(gdb_open_cb, "open,%s,%x,%x",
  125. (uint64_t)fname, (uint32_t)len,
  126. (uint32_t)gdb_flags, (uint32_t)mode);
  127. }
  128. static void gdb_close(CPUState *cs, gdb_syscall_complete_cb complete,
  129. GuestFD *gf)
  130. {
  131. gdb_do_syscall(complete, "close,%x", (uint32_t)gf->hostfd);
  132. }
  133. static void gdb_read(CPUState *cs, gdb_syscall_complete_cb complete,
  134. GuestFD *gf, target_ulong buf, target_ulong len)
  135. {
  136. gdb_do_syscall(complete, "read,%x,%lx,%lx",
  137. (uint32_t)gf->hostfd, (uint64_t)buf, (uint64_t)len);
  138. }
  139. static void gdb_write(CPUState *cs, gdb_syscall_complete_cb complete,
  140. GuestFD *gf, target_ulong buf, target_ulong len)
  141. {
  142. gdb_do_syscall(complete, "write,%x,%lx,%lx",
  143. (uint32_t)gf->hostfd, (uint64_t)buf, (uint64_t)len);
  144. }
  145. static void gdb_lseek(CPUState *cs, gdb_syscall_complete_cb complete,
  146. GuestFD *gf, int64_t off, int gdb_whence)
  147. {
  148. gdb_do_syscall(complete, "lseek,%x,%lx,%x",
  149. (uint32_t)gf->hostfd, off, (uint32_t)gdb_whence);
  150. }
  151. static void gdb_isatty(CPUState *cs, gdb_syscall_complete_cb complete,
  152. GuestFD *gf)
  153. {
  154. gdb_do_syscall(complete, "isatty,%x", (uint32_t)gf->hostfd);
  155. }
  156. static void gdb_fstat(CPUState *cs, gdb_syscall_complete_cb complete,
  157. GuestFD *gf, target_ulong addr)
  158. {
  159. gdb_do_syscall(complete, "fstat,%x,%lx",
  160. (uint32_t)gf->hostfd, (uint64_t)addr);
  161. }
  162. static void gdb_stat(CPUState *cs, gdb_syscall_complete_cb complete,
  163. target_ulong fname, target_ulong fname_len,
  164. target_ulong addr)
  165. {
  166. int len = validate_strlen(cs, fname, fname_len);
  167. if (len < 0) {
  168. complete(cs, -1, -len);
  169. return;
  170. }
  171. gdb_do_syscall(complete, "stat,%s,%lx",
  172. (uint64_t)fname, (uint32_t)len, (uint64_t)addr);
  173. }
  174. static void gdb_remove(CPUState *cs, gdb_syscall_complete_cb complete,
  175. target_ulong fname, target_ulong fname_len)
  176. {
  177. int len = validate_strlen(cs, fname, fname_len);
  178. if (len < 0) {
  179. complete(cs, -1, -len);
  180. return;
  181. }
  182. gdb_do_syscall(complete, "unlink,%s", (uint64_t)fname, (uint32_t)len);
  183. }
  184. static void gdb_rename(CPUState *cs, gdb_syscall_complete_cb complete,
  185. target_ulong oname, target_ulong oname_len,
  186. target_ulong nname, target_ulong nname_len)
  187. {
  188. int olen, nlen;
  189. olen = validate_strlen(cs, oname, oname_len);
  190. if (olen < 0) {
  191. complete(cs, -1, -olen);
  192. return;
  193. }
  194. nlen = validate_strlen(cs, nname, nname_len);
  195. if (nlen < 0) {
  196. complete(cs, -1, -nlen);
  197. return;
  198. }
  199. gdb_do_syscall(complete, "rename,%s,%s",
  200. (uint64_t)oname, (uint32_t)olen,
  201. (uint64_t)nname, (uint32_t)nlen);
  202. }
  203. static void gdb_system(CPUState *cs, gdb_syscall_complete_cb complete,
  204. target_ulong cmd, target_ulong cmd_len)
  205. {
  206. int len = validate_strlen(cs, cmd, cmd_len);
  207. if (len < 0) {
  208. complete(cs, -1, -len);
  209. return;
  210. }
  211. gdb_do_syscall(complete, "system,%s", (uint64_t)cmd, (uint32_t)len);
  212. }
  213. static void gdb_gettimeofday(CPUState *cs, gdb_syscall_complete_cb complete,
  214. target_ulong tv_addr, target_ulong tz_addr)
  215. {
  216. gdb_do_syscall(complete, "gettimeofday,%lx,%lx",
  217. (uint64_t)tv_addr, (uint64_t)tz_addr);
  218. }
  219. /*
  220. * Host semihosting syscall implementations.
  221. */
  222. static void host_open(CPUState *cs, gdb_syscall_complete_cb complete,
  223. target_ulong fname, target_ulong fname_len,
  224. int gdb_flags, int mode)
  225. {
  226. CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
  227. char *p;
  228. int ret, host_flags = O_BINARY;
  229. ret = validate_lock_user_string(&p, cs, fname, fname_len);
  230. if (ret < 0) {
  231. complete(cs, -1, -ret);
  232. return;
  233. }
  234. if (gdb_flags & GDB_O_WRONLY) {
  235. host_flags |= O_WRONLY;
  236. } else if (gdb_flags & GDB_O_RDWR) {
  237. host_flags |= O_RDWR;
  238. } else {
  239. host_flags |= O_RDONLY;
  240. }
  241. if (gdb_flags & GDB_O_CREAT) {
  242. host_flags |= O_CREAT;
  243. }
  244. if (gdb_flags & GDB_O_TRUNC) {
  245. host_flags |= O_TRUNC;
  246. }
  247. if (gdb_flags & GDB_O_EXCL) {
  248. host_flags |= O_EXCL;
  249. }
  250. ret = open(p, host_flags, mode);
  251. if (ret < 0) {
  252. complete(cs, -1, errno);
  253. } else {
  254. int guestfd = alloc_guestfd();
  255. associate_guestfd(guestfd, ret);
  256. complete(cs, guestfd, 0);
  257. }
  258. unlock_user(p, fname, 0);
  259. }
  260. static void host_close(CPUState *cs, gdb_syscall_complete_cb complete,
  261. GuestFD *gf)
  262. {
  263. /*
  264. * Only close the underlying host fd if it's one we opened on behalf
  265. * of the guest in SYS_OPEN.
  266. */
  267. if (gf->hostfd != STDIN_FILENO &&
  268. gf->hostfd != STDOUT_FILENO &&
  269. gf->hostfd != STDERR_FILENO &&
  270. close(gf->hostfd) < 0) {
  271. complete(cs, -1, errno);
  272. } else {
  273. complete(cs, 0, 0);
  274. }
  275. }
  276. static void host_read(CPUState *cs, gdb_syscall_complete_cb complete,
  277. GuestFD *gf, target_ulong buf, target_ulong len)
  278. {
  279. CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
  280. void *ptr = lock_user(VERIFY_WRITE, buf, len, 0);
  281. ssize_t ret;
  282. if (!ptr) {
  283. complete(cs, -1, EFAULT);
  284. return;
  285. }
  286. ret = RETRY_ON_EINTR(read(gf->hostfd, ptr, len));
  287. if (ret == -1) {
  288. unlock_user(ptr, buf, 0);
  289. complete(cs, -1, errno);
  290. } else {
  291. unlock_user(ptr, buf, ret);
  292. complete(cs, ret, 0);
  293. }
  294. }
  295. static void host_write(CPUState *cs, gdb_syscall_complete_cb complete,
  296. GuestFD *gf, target_ulong buf, target_ulong len)
  297. {
  298. CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
  299. void *ptr = lock_user(VERIFY_READ, buf, len, 1);
  300. ssize_t ret;
  301. if (!ptr) {
  302. complete(cs, -1, EFAULT);
  303. return;
  304. }
  305. ret = write(gf->hostfd, ptr, len);
  306. unlock_user(ptr, buf, 0);
  307. complete(cs, ret, ret == -1 ? errno : 0);
  308. }
  309. static void host_lseek(CPUState *cs, gdb_syscall_complete_cb complete,
  310. GuestFD *gf, int64_t off, int whence)
  311. {
  312. /* So far, all hosts use the same values. */
  313. QEMU_BUILD_BUG_ON(GDB_SEEK_SET != SEEK_SET);
  314. QEMU_BUILD_BUG_ON(GDB_SEEK_CUR != SEEK_CUR);
  315. QEMU_BUILD_BUG_ON(GDB_SEEK_END != SEEK_END);
  316. off_t ret = off;
  317. int err = 0;
  318. if (ret == off) {
  319. ret = lseek(gf->hostfd, ret, whence);
  320. if (ret == -1) {
  321. err = errno;
  322. }
  323. } else {
  324. ret = -1;
  325. err = EINVAL;
  326. }
  327. complete(cs, ret, err);
  328. }
  329. static void host_isatty(CPUState *cs, gdb_syscall_complete_cb complete,
  330. GuestFD *gf)
  331. {
  332. int ret = isatty(gf->hostfd);
  333. complete(cs, ret, ret ? 0 : errno);
  334. }
  335. static void host_flen(CPUState *cs, gdb_syscall_complete_cb complete,
  336. GuestFD *gf)
  337. {
  338. struct stat buf;
  339. if (fstat(gf->hostfd, &buf) < 0) {
  340. complete(cs, -1, errno);
  341. } else {
  342. complete(cs, buf.st_size, 0);
  343. }
  344. }
  345. static void host_fstat(CPUState *cs, gdb_syscall_complete_cb complete,
  346. GuestFD *gf, target_ulong addr)
  347. {
  348. struct stat buf;
  349. int ret;
  350. ret = fstat(gf->hostfd, &buf);
  351. if (ret) {
  352. complete(cs, -1, errno);
  353. return;
  354. }
  355. ret = copy_stat_to_user(cs, addr, &buf);
  356. complete(cs, ret ? -1 : 0, ret ? -ret : 0);
  357. }
  358. static void host_stat(CPUState *cs, gdb_syscall_complete_cb complete,
  359. target_ulong fname, target_ulong fname_len,
  360. target_ulong addr)
  361. {
  362. CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
  363. struct stat buf;
  364. char *name;
  365. int ret, err;
  366. ret = validate_lock_user_string(&name, cs, fname, fname_len);
  367. if (ret < 0) {
  368. complete(cs, -1, -ret);
  369. return;
  370. }
  371. ret = stat(name, &buf);
  372. if (ret) {
  373. err = errno;
  374. } else {
  375. ret = copy_stat_to_user(cs, addr, &buf);
  376. err = 0;
  377. if (ret < 0) {
  378. err = -ret;
  379. ret = -1;
  380. }
  381. }
  382. unlock_user(name, fname, 0);
  383. complete(cs, ret, err);
  384. }
  385. static void host_remove(CPUState *cs, gdb_syscall_complete_cb complete,
  386. target_ulong fname, target_ulong fname_len)
  387. {
  388. CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
  389. char *p;
  390. int ret;
  391. ret = validate_lock_user_string(&p, cs, fname, fname_len);
  392. if (ret < 0) {
  393. complete(cs, -1, -ret);
  394. return;
  395. }
  396. ret = remove(p);
  397. unlock_user(p, fname, 0);
  398. complete(cs, ret, ret ? errno : 0);
  399. }
  400. static void host_rename(CPUState *cs, gdb_syscall_complete_cb complete,
  401. target_ulong oname, target_ulong oname_len,
  402. target_ulong nname, target_ulong nname_len)
  403. {
  404. CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
  405. char *ostr, *nstr;
  406. int ret;
  407. ret = validate_lock_user_string(&ostr, cs, oname, oname_len);
  408. if (ret < 0) {
  409. complete(cs, -1, -ret);
  410. return;
  411. }
  412. ret = validate_lock_user_string(&nstr, cs, nname, nname_len);
  413. if (ret < 0) {
  414. unlock_user(ostr, oname, 0);
  415. complete(cs, -1, -ret);
  416. return;
  417. }
  418. ret = rename(ostr, nstr);
  419. unlock_user(ostr, oname, 0);
  420. unlock_user(nstr, nname, 0);
  421. complete(cs, ret, ret ? errno : 0);
  422. }
  423. static void host_system(CPUState *cs, gdb_syscall_complete_cb complete,
  424. target_ulong cmd, target_ulong cmd_len)
  425. {
  426. CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
  427. char *p;
  428. int ret;
  429. ret = validate_lock_user_string(&p, cs, cmd, cmd_len);
  430. if (ret < 0) {
  431. complete(cs, -1, -ret);
  432. return;
  433. }
  434. ret = system(p);
  435. unlock_user(p, cmd, 0);
  436. complete(cs, ret, ret == -1 ? errno : 0);
  437. }
  438. static void host_gettimeofday(CPUState *cs, gdb_syscall_complete_cb complete,
  439. target_ulong tv_addr, target_ulong tz_addr)
  440. {
  441. CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
  442. struct gdb_timeval *p;
  443. int64_t rt;
  444. /* GDB fails on non-null TZ, so be consistent. */
  445. if (tz_addr != 0) {
  446. complete(cs, -1, EINVAL);
  447. return;
  448. }
  449. p = lock_user(VERIFY_WRITE, tv_addr, sizeof(struct gdb_timeval), 0);
  450. if (!p) {
  451. complete(cs, -1, EFAULT);
  452. return;
  453. }
  454. /* TODO: Like stat, gdb always produces big-endian results; match it. */
  455. rt = g_get_real_time();
  456. p->tv_sec = cpu_to_be32(rt / G_USEC_PER_SEC);
  457. p->tv_usec = cpu_to_be64(rt % G_USEC_PER_SEC);
  458. unlock_user(p, tv_addr, sizeof(struct gdb_timeval));
  459. }
  460. #ifndef CONFIG_USER_ONLY
  461. static void host_poll_one(CPUState *cs, gdb_syscall_complete_cb complete,
  462. GuestFD *gf, GIOCondition cond, int timeout)
  463. {
  464. /*
  465. * Since this is only used by xtensa in system mode, and stdio is
  466. * handled through GuestFDConsole, and there are no semihosting
  467. * system calls for sockets and the like, that means this descriptor
  468. * must be a normal file. Normal files never block and are thus
  469. * always ready.
  470. */
  471. complete(cs, cond & (G_IO_IN | G_IO_OUT), 0);
  472. }
  473. #endif
  474. /*
  475. * Static file semihosting syscall implementations.
  476. */
  477. static void staticfile_read(CPUState *cs, gdb_syscall_complete_cb complete,
  478. GuestFD *gf, target_ulong buf, target_ulong len)
  479. {
  480. CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
  481. target_ulong rest = gf->staticfile.len - gf->staticfile.off;
  482. void *ptr;
  483. if (len > rest) {
  484. len = rest;
  485. }
  486. ptr = lock_user(VERIFY_WRITE, buf, len, 0);
  487. if (!ptr) {
  488. complete(cs, -1, EFAULT);
  489. return;
  490. }
  491. memcpy(ptr, gf->staticfile.data + gf->staticfile.off, len);
  492. gf->staticfile.off += len;
  493. unlock_user(ptr, buf, len);
  494. complete(cs, len, 0);
  495. }
  496. static void staticfile_lseek(CPUState *cs, gdb_syscall_complete_cb complete,
  497. GuestFD *gf, int64_t off, int gdb_whence)
  498. {
  499. int64_t ret;
  500. switch (gdb_whence) {
  501. case GDB_SEEK_SET:
  502. ret = off;
  503. break;
  504. case GDB_SEEK_CUR:
  505. ret = gf->staticfile.off + off;
  506. break;
  507. case GDB_SEEK_END:
  508. ret = gf->staticfile.len + off;
  509. break;
  510. default:
  511. ret = -1;
  512. break;
  513. }
  514. if (ret >= 0 && ret <= gf->staticfile.len) {
  515. gf->staticfile.off = ret;
  516. complete(cs, ret, 0);
  517. } else {
  518. complete(cs, -1, EINVAL);
  519. }
  520. }
  521. static void staticfile_flen(CPUState *cs, gdb_syscall_complete_cb complete,
  522. GuestFD *gf)
  523. {
  524. complete(cs, gf->staticfile.len, 0);
  525. }
  526. /*
  527. * Console semihosting syscall implementations.
  528. */
  529. static void console_read(CPUState *cs, gdb_syscall_complete_cb complete,
  530. GuestFD *gf, target_ulong buf, target_ulong len)
  531. {
  532. CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
  533. char *ptr;
  534. int ret;
  535. ptr = lock_user(VERIFY_WRITE, buf, len, 0);
  536. if (!ptr) {
  537. complete(cs, -1, EFAULT);
  538. return;
  539. }
  540. ret = qemu_semihosting_console_read(cs, ptr, len);
  541. unlock_user(ptr, buf, ret);
  542. complete(cs, ret, 0);
  543. }
  544. static void console_write(CPUState *cs, gdb_syscall_complete_cb complete,
  545. GuestFD *gf, target_ulong buf, target_ulong len)
  546. {
  547. CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
  548. char *ptr = lock_user(VERIFY_READ, buf, len, 1);
  549. int ret;
  550. if (!ptr) {
  551. complete(cs, -1, EFAULT);
  552. return;
  553. }
  554. ret = qemu_semihosting_console_write(ptr, len);
  555. unlock_user(ptr, buf, 0);
  556. complete(cs, ret ? ret : -1, ret ? 0 : EIO);
  557. }
  558. static void console_fstat(CPUState *cs, gdb_syscall_complete_cb complete,
  559. GuestFD *gf, target_ulong addr)
  560. {
  561. static const struct stat tty_buf = {
  562. .st_mode = 020666, /* S_IFCHR, ugo+rw */
  563. .st_rdev = 5, /* makedev(5, 0) -- linux /dev/tty */
  564. };
  565. int ret;
  566. ret = copy_stat_to_user(cs, addr, &tty_buf);
  567. complete(cs, ret ? -1 : 0, ret ? -ret : 0);
  568. }
  569. #ifndef CONFIG_USER_ONLY
  570. static void console_poll_one(CPUState *cs, gdb_syscall_complete_cb complete,
  571. GuestFD *gf, GIOCondition cond, int timeout)
  572. {
  573. /* The semihosting console does not support urgent data or errors. */
  574. cond &= G_IO_IN | G_IO_OUT;
  575. /*
  576. * Since qemu_semihosting_console_write never blocks, we can
  577. * consider output always ready -- leave G_IO_OUT alone.
  578. * All that remains is to conditionally signal input ready.
  579. * Since output ready causes an immediate return, only block
  580. * for G_IO_IN alone.
  581. *
  582. * TODO: Implement proper timeout. For now, only support
  583. * indefinite wait or immediate poll.
  584. */
  585. if (cond == G_IO_IN && timeout < 0) {
  586. qemu_semihosting_console_block_until_ready(cs);
  587. /* We returned -- input must be ready. */
  588. } else if ((cond & G_IO_IN) && !qemu_semihosting_console_ready()) {
  589. cond &= ~G_IO_IN;
  590. }
  591. complete(cs, cond, 0);
  592. }
  593. #endif
  594. /*
  595. * Syscall entry points.
  596. */
  597. void semihost_sys_open(CPUState *cs, gdb_syscall_complete_cb complete,
  598. target_ulong fname, target_ulong fname_len,
  599. int gdb_flags, int mode)
  600. {
  601. if (use_gdb_syscalls()) {
  602. gdb_open(cs, complete, fname, fname_len, gdb_flags, mode);
  603. } else {
  604. host_open(cs, complete, fname, fname_len, gdb_flags, mode);
  605. }
  606. }
  607. void semihost_sys_close(CPUState *cs, gdb_syscall_complete_cb complete, int fd)
  608. {
  609. GuestFD *gf = get_guestfd(fd);
  610. if (!gf) {
  611. complete(cs, -1, EBADF);
  612. return;
  613. }
  614. switch (gf->type) {
  615. case GuestFDGDB:
  616. gdb_close(cs, complete, gf);
  617. break;
  618. case GuestFDHost:
  619. host_close(cs, complete, gf);
  620. break;
  621. case GuestFDStatic:
  622. case GuestFDConsole:
  623. complete(cs, 0, 0);
  624. break;
  625. default:
  626. g_assert_not_reached();
  627. }
  628. dealloc_guestfd(fd);
  629. }
  630. void semihost_sys_read_gf(CPUState *cs, gdb_syscall_complete_cb complete,
  631. GuestFD *gf, target_ulong buf, target_ulong len)
  632. {
  633. /*
  634. * Bound length for 64-bit guests on 32-bit hosts, not overflowing ssize_t.
  635. * Note the Linux kernel does this with MAX_RW_COUNT, so it's not a bad
  636. * idea to do this unconditionally.
  637. */
  638. if (len > INT32_MAX) {
  639. len = INT32_MAX;
  640. }
  641. switch (gf->type) {
  642. case GuestFDGDB:
  643. gdb_read(cs, complete, gf, buf, len);
  644. break;
  645. case GuestFDHost:
  646. host_read(cs, complete, gf, buf, len);
  647. break;
  648. case GuestFDStatic:
  649. staticfile_read(cs, complete, gf, buf, len);
  650. break;
  651. case GuestFDConsole:
  652. console_read(cs, complete, gf, buf, len);
  653. break;
  654. default:
  655. g_assert_not_reached();
  656. }
  657. }
  658. void semihost_sys_read(CPUState *cs, gdb_syscall_complete_cb complete,
  659. int fd, target_ulong buf, target_ulong len)
  660. {
  661. GuestFD *gf = get_guestfd(fd);
  662. if (gf) {
  663. semihost_sys_read_gf(cs, complete, gf, buf, len);
  664. } else {
  665. complete(cs, -1, EBADF);
  666. }
  667. }
  668. void semihost_sys_write_gf(CPUState *cs, gdb_syscall_complete_cb complete,
  669. GuestFD *gf, target_ulong buf, target_ulong len)
  670. {
  671. /*
  672. * Bound length for 64-bit guests on 32-bit hosts, not overflowing ssize_t.
  673. * Note the Linux kernel does this with MAX_RW_COUNT, so it's not a bad
  674. * idea to do this unconditionally.
  675. */
  676. if (len > INT32_MAX) {
  677. len = INT32_MAX;
  678. }
  679. switch (gf->type) {
  680. case GuestFDGDB:
  681. gdb_write(cs, complete, gf, buf, len);
  682. break;
  683. case GuestFDHost:
  684. host_write(cs, complete, gf, buf, len);
  685. break;
  686. case GuestFDConsole:
  687. console_write(cs, complete, gf, buf, len);
  688. break;
  689. case GuestFDStatic:
  690. /* Static files are never open for writing: EBADF. */
  691. complete(cs, -1, EBADF);
  692. break;
  693. default:
  694. g_assert_not_reached();
  695. }
  696. }
  697. void semihost_sys_write(CPUState *cs, gdb_syscall_complete_cb complete,
  698. int fd, target_ulong buf, target_ulong len)
  699. {
  700. GuestFD *gf = get_guestfd(fd);
  701. if (gf) {
  702. semihost_sys_write_gf(cs, complete, gf, buf, len);
  703. } else {
  704. complete(cs, -1, EBADF);
  705. }
  706. }
  707. void semihost_sys_lseek(CPUState *cs, gdb_syscall_complete_cb complete,
  708. int fd, int64_t off, int gdb_whence)
  709. {
  710. GuestFD *gf = get_guestfd(fd);
  711. if (!gf) {
  712. complete(cs, -1, EBADF);
  713. return;
  714. }
  715. switch (gf->type) {
  716. case GuestFDGDB:
  717. gdb_lseek(cs, complete, gf, off, gdb_whence);
  718. return;
  719. case GuestFDHost:
  720. host_lseek(cs, complete, gf, off, gdb_whence);
  721. break;
  722. case GuestFDStatic:
  723. staticfile_lseek(cs, complete, gf, off, gdb_whence);
  724. break;
  725. case GuestFDConsole:
  726. complete(cs, -1, ESPIPE);
  727. break;
  728. default:
  729. g_assert_not_reached();
  730. }
  731. }
  732. void semihost_sys_isatty(CPUState *cs, gdb_syscall_complete_cb complete, int fd)
  733. {
  734. GuestFD *gf = get_guestfd(fd);
  735. if (!gf) {
  736. complete(cs, 0, EBADF);
  737. return;
  738. }
  739. switch (gf->type) {
  740. case GuestFDGDB:
  741. gdb_isatty(cs, complete, gf);
  742. break;
  743. case GuestFDHost:
  744. host_isatty(cs, complete, gf);
  745. break;
  746. case GuestFDStatic:
  747. complete(cs, 0, ENOTTY);
  748. break;
  749. case GuestFDConsole:
  750. complete(cs, 1, 0);
  751. break;
  752. default:
  753. g_assert_not_reached();
  754. }
  755. }
  756. void semihost_sys_flen(CPUState *cs, gdb_syscall_complete_cb fstat_cb,
  757. gdb_syscall_complete_cb flen_cb, int fd,
  758. target_ulong fstat_addr)
  759. {
  760. GuestFD *gf = get_guestfd(fd);
  761. if (!gf) {
  762. flen_cb(cs, -1, EBADF);
  763. return;
  764. }
  765. switch (gf->type) {
  766. case GuestFDGDB:
  767. gdb_fstat(cs, fstat_cb, gf, fstat_addr);
  768. break;
  769. case GuestFDHost:
  770. host_flen(cs, flen_cb, gf);
  771. break;
  772. case GuestFDStatic:
  773. staticfile_flen(cs, flen_cb, gf);
  774. break;
  775. case GuestFDConsole:
  776. default:
  777. g_assert_not_reached();
  778. }
  779. }
  780. void semihost_sys_fstat(CPUState *cs, gdb_syscall_complete_cb complete,
  781. int fd, target_ulong addr)
  782. {
  783. GuestFD *gf = get_guestfd(fd);
  784. if (!gf) {
  785. complete(cs, -1, EBADF);
  786. return;
  787. }
  788. switch (gf->type) {
  789. case GuestFDGDB:
  790. gdb_fstat(cs, complete, gf, addr);
  791. break;
  792. case GuestFDHost:
  793. host_fstat(cs, complete, gf, addr);
  794. break;
  795. case GuestFDConsole:
  796. console_fstat(cs, complete, gf, addr);
  797. break;
  798. case GuestFDStatic:
  799. default:
  800. g_assert_not_reached();
  801. }
  802. }
  803. void semihost_sys_stat(CPUState *cs, gdb_syscall_complete_cb complete,
  804. target_ulong fname, target_ulong fname_len,
  805. target_ulong addr)
  806. {
  807. if (use_gdb_syscalls()) {
  808. gdb_stat(cs, complete, fname, fname_len, addr);
  809. } else {
  810. host_stat(cs, complete, fname, fname_len, addr);
  811. }
  812. }
  813. void semihost_sys_remove(CPUState *cs, gdb_syscall_complete_cb complete,
  814. target_ulong fname, target_ulong fname_len)
  815. {
  816. if (use_gdb_syscalls()) {
  817. gdb_remove(cs, complete, fname, fname_len);
  818. } else {
  819. host_remove(cs, complete, fname, fname_len);
  820. }
  821. }
  822. void semihost_sys_rename(CPUState *cs, gdb_syscall_complete_cb complete,
  823. target_ulong oname, target_ulong oname_len,
  824. target_ulong nname, target_ulong nname_len)
  825. {
  826. if (use_gdb_syscalls()) {
  827. gdb_rename(cs, complete, oname, oname_len, nname, nname_len);
  828. } else {
  829. host_rename(cs, complete, oname, oname_len, nname, nname_len);
  830. }
  831. }
  832. void semihost_sys_system(CPUState *cs, gdb_syscall_complete_cb complete,
  833. target_ulong cmd, target_ulong cmd_len)
  834. {
  835. if (use_gdb_syscalls()) {
  836. gdb_system(cs, complete, cmd, cmd_len);
  837. } else {
  838. host_system(cs, complete, cmd, cmd_len);
  839. }
  840. }
  841. void semihost_sys_gettimeofday(CPUState *cs, gdb_syscall_complete_cb complete,
  842. target_ulong tv_addr, target_ulong tz_addr)
  843. {
  844. if (use_gdb_syscalls()) {
  845. gdb_gettimeofday(cs, complete, tv_addr, tz_addr);
  846. } else {
  847. host_gettimeofday(cs, complete, tv_addr, tz_addr);
  848. }
  849. }
  850. #ifndef CONFIG_USER_ONLY
  851. void semihost_sys_poll_one(CPUState *cs, gdb_syscall_complete_cb complete,
  852. int fd, GIOCondition cond, int timeout)
  853. {
  854. GuestFD *gf = get_guestfd(fd);
  855. if (!gf) {
  856. complete(cs, G_IO_NVAL, 1);
  857. return;
  858. }
  859. switch (gf->type) {
  860. case GuestFDGDB:
  861. complete(cs, G_IO_NVAL, 1);
  862. break;
  863. case GuestFDHost:
  864. host_poll_one(cs, complete, gf, cond, timeout);
  865. break;
  866. case GuestFDConsole:
  867. console_poll_one(cs, complete, gf, cond, timeout);
  868. break;
  869. case GuestFDStatic:
  870. default:
  871. g_assert_not_reached();
  872. }
  873. }
  874. #endif