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