syscalls.c 26 KB

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