qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

syscalls.c (26504B)


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