cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

arm-compat-semi.c (37587B)


      1/*
      2 *  Semihosting support for systems modeled on the Arm "Angel"
      3 *  semihosting syscalls design. This includes Arm and RISC-V processors
      4 *
      5 *  Copyright (c) 2005, 2007 CodeSourcery.
      6 *  Copyright (c) 2019 Linaro
      7 *  Written by Paul Brook.
      8 *
      9 *  Copyright © 2020 by Keith Packard <keithp@keithp.com>
     10 *  Adapted for systems other than ARM, including RISC-V, by Keith Packard
     11 *
     12 *  This program is free software; you can redistribute it and/or modify
     13 *  it under the terms of the GNU General Public License as published by
     14 *  the Free Software Foundation; either version 2 of the License, or
     15 *  (at your option) any later version.
     16 *
     17 *  This program is distributed in the hope that it will be useful,
     18 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     19 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     20 *  GNU General Public License for more details.
     21 *
     22 *  You should have received a copy of the GNU General Public License
     23 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
     24 *
     25 *  ARM Semihosting is documented in:
     26 *     Semihosting for AArch32 and AArch64 Release 2.0
     27 *     https://static.docs.arm.com/100863/0200/semihosting.pdf
     28 *
     29 *  RISC-V Semihosting is documented in:
     30 *     RISC-V Semihosting
     31 *     https://github.com/riscv/riscv-semihosting-spec/blob/main/riscv-semihosting-spec.adoc
     32 */
     33
     34#include "qemu/osdep.h"
     35
     36#include "semihosting/semihost.h"
     37#include "semihosting/console.h"
     38#include "semihosting/common-semi.h"
     39#include "qemu/timer.h"
     40#include "exec/gdbstub.h"
     41#ifdef CONFIG_USER_ONLY
     42#include "qemu.h"
     43
     44#define COMMON_SEMI_HEAP_SIZE (128 * 1024 * 1024)
     45#else
     46#include "qemu/cutils.h"
     47#ifdef TARGET_ARM
     48#include "hw/arm/boot.h"
     49#endif
     50#include "hw/boards.h"
     51#endif
     52
     53#define TARGET_SYS_OPEN        0x01
     54#define TARGET_SYS_CLOSE       0x02
     55#define TARGET_SYS_WRITEC      0x03
     56#define TARGET_SYS_WRITE0      0x04
     57#define TARGET_SYS_WRITE       0x05
     58#define TARGET_SYS_READ        0x06
     59#define TARGET_SYS_READC       0x07
     60#define TARGET_SYS_ISERROR     0x08
     61#define TARGET_SYS_ISTTY       0x09
     62#define TARGET_SYS_SEEK        0x0a
     63#define TARGET_SYS_FLEN        0x0c
     64#define TARGET_SYS_TMPNAM      0x0d
     65#define TARGET_SYS_REMOVE      0x0e
     66#define TARGET_SYS_RENAME      0x0f
     67#define TARGET_SYS_CLOCK       0x10
     68#define TARGET_SYS_TIME        0x11
     69#define TARGET_SYS_SYSTEM      0x12
     70#define TARGET_SYS_ERRNO       0x13
     71#define TARGET_SYS_GET_CMDLINE 0x15
     72#define TARGET_SYS_HEAPINFO    0x16
     73#define TARGET_SYS_EXIT        0x18
     74#define TARGET_SYS_SYNCCACHE   0x19
     75#define TARGET_SYS_EXIT_EXTENDED 0x20
     76#define TARGET_SYS_ELAPSED     0x30
     77#define TARGET_SYS_TICKFREQ    0x31
     78
     79/* ADP_Stopped_ApplicationExit is used for exit(0),
     80 * anything else is implemented as exit(1) */
     81#define ADP_Stopped_ApplicationExit     (0x20026)
     82
     83#ifndef O_BINARY
     84#define O_BINARY 0
     85#endif
     86
     87#define GDB_O_RDONLY  0x000
     88#define GDB_O_WRONLY  0x001
     89#define GDB_O_RDWR    0x002
     90#define GDB_O_APPEND  0x008
     91#define GDB_O_CREAT   0x200
     92#define GDB_O_TRUNC   0x400
     93#define GDB_O_BINARY  0
     94
     95static int gdb_open_modeflags[12] = {
     96    GDB_O_RDONLY,
     97    GDB_O_RDONLY | GDB_O_BINARY,
     98    GDB_O_RDWR,
     99    GDB_O_RDWR | GDB_O_BINARY,
    100    GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC,
    101    GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC | GDB_O_BINARY,
    102    GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC,
    103    GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC | GDB_O_BINARY,
    104    GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND,
    105    GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND | GDB_O_BINARY,
    106    GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND,
    107    GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND | GDB_O_BINARY
    108};
    109
    110static int open_modeflags[12] = {
    111    O_RDONLY,
    112    O_RDONLY | O_BINARY,
    113    O_RDWR,
    114    O_RDWR | O_BINARY,
    115    O_WRONLY | O_CREAT | O_TRUNC,
    116    O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
    117    O_RDWR | O_CREAT | O_TRUNC,
    118    O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
    119    O_WRONLY | O_CREAT | O_APPEND,
    120    O_WRONLY | O_CREAT | O_APPEND | O_BINARY,
    121    O_RDWR | O_CREAT | O_APPEND,
    122    O_RDWR | O_CREAT | O_APPEND | O_BINARY
    123};
    124
    125typedef enum GuestFDType {
    126    GuestFDUnused = 0,
    127    GuestFDHost = 1,
    128    GuestFDGDB = 2,
    129    GuestFDFeatureFile = 3,
    130} GuestFDType;
    131
    132/*
    133 * Guest file descriptors are integer indexes into an array of
    134 * these structures (we will dynamically resize as necessary).
    135 */
    136typedef struct GuestFD {
    137    GuestFDType type;
    138    union {
    139        int hostfd;
    140        target_ulong featurefile_offset;
    141    };
    142} GuestFD;
    143
    144static GArray *guestfd_array;
    145
    146#ifndef CONFIG_USER_ONLY
    147#include "exec/address-spaces.h"
    148/*
    149 * Find the base of a RAM region containing the specified address
    150 */
    151static inline hwaddr
    152common_semi_find_region_base(hwaddr addr)
    153{
    154    MemoryRegion *subregion;
    155
    156    /*
    157     * Find the chunk of R/W memory containing the address.  This is
    158     * used for the SYS_HEAPINFO semihosting call, which should
    159     * probably be using information from the loaded application.
    160     */
    161    QTAILQ_FOREACH(subregion, &get_system_memory()->subregions,
    162                   subregions_link) {
    163        if (subregion->ram && !subregion->readonly) {
    164            Int128 top128 = int128_add(int128_make64(subregion->addr),
    165                                       subregion->size);
    166            Int128 addr128 = int128_make64(addr);
    167            if (subregion->addr <= addr && int128_lt(addr128, top128)) {
    168                return subregion->addr;
    169            }
    170        }
    171    }
    172    return 0;
    173}
    174#endif
    175
    176#ifdef TARGET_ARM
    177static inline target_ulong
    178common_semi_arg(CPUState *cs, int argno)
    179{
    180    ARMCPU *cpu = ARM_CPU(cs);
    181    CPUARMState *env = &cpu->env;
    182    if (is_a64(env)) {
    183        return env->xregs[argno];
    184    } else {
    185        return env->regs[argno];
    186    }
    187}
    188
    189static inline void
    190common_semi_set_ret(CPUState *cs, target_ulong ret)
    191{
    192    ARMCPU *cpu = ARM_CPU(cs);
    193    CPUARMState *env = &cpu->env;
    194    if (is_a64(env)) {
    195        env->xregs[0] = ret;
    196    } else {
    197        env->regs[0] = ret;
    198    }
    199}
    200
    201static inline bool
    202common_semi_sys_exit_extended(CPUState *cs, int nr)
    203{
    204    return (nr == TARGET_SYS_EXIT_EXTENDED || is_a64(cs->env_ptr));
    205}
    206
    207#ifndef CONFIG_USER_ONLY
    208#include "hw/arm/boot.h"
    209static inline target_ulong
    210common_semi_rambase(CPUState *cs)
    211{
    212    CPUArchState *env = cs->env_ptr;
    213    const struct arm_boot_info *info = env->boot_info;
    214    target_ulong sp;
    215
    216    if (info) {
    217        return info->loader_start;
    218    }
    219
    220    if (is_a64(env)) {
    221        sp = env->xregs[31];
    222    } else {
    223        sp = env->regs[13];
    224    }
    225    return common_semi_find_region_base(sp);
    226}
    227#endif
    228
    229#endif /* TARGET_ARM */
    230
    231#ifdef TARGET_RISCV
    232static inline target_ulong
    233common_semi_arg(CPUState *cs, int argno)
    234{
    235    RISCVCPU *cpu = RISCV_CPU(cs);
    236    CPURISCVState *env = &cpu->env;
    237    return env->gpr[xA0 + argno];
    238}
    239
    240static inline void
    241common_semi_set_ret(CPUState *cs, target_ulong ret)
    242{
    243    RISCVCPU *cpu = RISCV_CPU(cs);
    244    CPURISCVState *env = &cpu->env;
    245    env->gpr[xA0] = ret;
    246}
    247
    248static inline bool
    249common_semi_sys_exit_extended(CPUState *cs, int nr)
    250{
    251    return (nr == TARGET_SYS_EXIT_EXTENDED || sizeof(target_ulong) == 8);
    252}
    253
    254#ifndef CONFIG_USER_ONLY
    255
    256static inline target_ulong
    257common_semi_rambase(CPUState *cs)
    258{
    259    RISCVCPU *cpu = RISCV_CPU(cs);
    260    CPURISCVState *env = &cpu->env;
    261    return common_semi_find_region_base(env->gpr[xSP]);
    262}
    263#endif
    264
    265#endif
    266
    267/*
    268 * Allocate a new guest file descriptor and return it; if we
    269 * couldn't allocate a new fd then return -1.
    270 * This is a fairly simplistic implementation because we don't
    271 * expect that most semihosting guest programs will make very
    272 * heavy use of opening and closing fds.
    273 */
    274static int alloc_guestfd(void)
    275{
    276    guint i;
    277
    278    if (!guestfd_array) {
    279        /* New entries zero-initialized, i.e. type GuestFDUnused */
    280        guestfd_array = g_array_new(FALSE, TRUE, sizeof(GuestFD));
    281    }
    282
    283    /* SYS_OPEN should return nonzero handle on success. Start guestfd from 1 */
    284    for (i = 1; i < guestfd_array->len; i++) {
    285        GuestFD *gf = &g_array_index(guestfd_array, GuestFD, i);
    286
    287        if (gf->type == GuestFDUnused) {
    288            return i;
    289        }
    290    }
    291
    292    /* All elements already in use: expand the array */
    293    g_array_set_size(guestfd_array, i + 1);
    294    return i;
    295}
    296
    297/*
    298 * Look up the guestfd in the data structure; return NULL
    299 * for out of bounds, but don't check whether the slot is unused.
    300 * This is used internally by the other guestfd functions.
    301 */
    302static GuestFD *do_get_guestfd(int guestfd)
    303{
    304    if (!guestfd_array) {
    305        return NULL;
    306    }
    307
    308    if (guestfd <= 0 || guestfd >= guestfd_array->len) {
    309        return NULL;
    310    }
    311
    312    return &g_array_index(guestfd_array, GuestFD, guestfd);
    313}
    314
    315/*
    316 * Associate the specified guest fd (which must have been
    317 * allocated via alloc_fd() and not previously used) with
    318 * the specified host/gdb fd.
    319 */
    320static void associate_guestfd(int guestfd, int hostfd)
    321{
    322    GuestFD *gf = do_get_guestfd(guestfd);
    323
    324    assert(gf);
    325    gf->type = use_gdb_syscalls() ? GuestFDGDB : GuestFDHost;
    326    gf->hostfd = hostfd;
    327}
    328
    329/*
    330 * Deallocate the specified guest file descriptor. This doesn't
    331 * close the host fd, it merely undoes the work of alloc_fd().
    332 */
    333static void dealloc_guestfd(int guestfd)
    334{
    335    GuestFD *gf = do_get_guestfd(guestfd);
    336
    337    assert(gf);
    338    gf->type = GuestFDUnused;
    339}
    340
    341/*
    342 * Given a guest file descriptor, get the associated struct.
    343 * If the fd is not valid, return NULL. This is the function
    344 * used by the various semihosting calls to validate a handle
    345 * from the guest.
    346 * Note: calling alloc_guestfd() or dealloc_guestfd() will
    347 * invalidate any GuestFD* obtained by calling this function.
    348 */
    349static GuestFD *get_guestfd(int guestfd)
    350{
    351    GuestFD *gf = do_get_guestfd(guestfd);
    352
    353    if (!gf || gf->type == GuestFDUnused) {
    354        return NULL;
    355    }
    356    return gf;
    357}
    358
    359/*
    360 * The semihosting API has no concept of its errno being thread-safe,
    361 * as the API design predates SMP CPUs and was intended as a simple
    362 * real-hardware set of debug functionality. For QEMU, we make the
    363 * errno be per-thread in linux-user mode; in softmmu it is a simple
    364 * global, and we assume that the guest takes care of avoiding any races.
    365 */
    366#ifndef CONFIG_USER_ONLY
    367static target_ulong syscall_err;
    368
    369#include "exec/softmmu-semi.h"
    370#endif
    371
    372static inline uint32_t set_swi_errno(CPUState *cs, uint32_t code)
    373{
    374    if (code == (uint32_t)-1) {
    375#ifdef CONFIG_USER_ONLY
    376        TaskState *ts = cs->opaque;
    377
    378        ts->swi_errno = errno;
    379#else
    380        syscall_err = errno;
    381#endif
    382    }
    383    return code;
    384}
    385
    386static inline uint32_t get_swi_errno(CPUState *cs)
    387{
    388#ifdef CONFIG_USER_ONLY
    389    TaskState *ts = cs->opaque;
    390
    391    return ts->swi_errno;
    392#else
    393    return syscall_err;
    394#endif
    395}
    396
    397static target_ulong common_semi_syscall_len;
    398
    399static void common_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
    400{
    401    target_ulong reg0 = common_semi_arg(cs, 0);
    402
    403    if (ret == (target_ulong)-1) {
    404        errno = err;
    405        set_swi_errno(cs, -1);
    406        reg0 = ret;
    407    } else {
    408        /* Fixup syscalls that use nonstardard return conventions.  */
    409        switch (reg0) {
    410        case TARGET_SYS_WRITE:
    411        case TARGET_SYS_READ:
    412            reg0 = common_semi_syscall_len - ret;
    413            break;
    414        case TARGET_SYS_SEEK:
    415            reg0 = 0;
    416            break;
    417        default:
    418            reg0 = ret;
    419            break;
    420        }
    421    }
    422    common_semi_set_ret(cs, reg0);
    423}
    424
    425static target_ulong common_semi_flen_buf(CPUState *cs)
    426{
    427    target_ulong sp;
    428#ifdef TARGET_ARM
    429    /* Return an address in target memory of 64 bytes where the remote
    430     * gdb should write its stat struct. (The format of this structure
    431     * is defined by GDB's remote protocol and is not target-specific.)
    432     * We put this on the guest's stack just below SP.
    433     */
    434    ARMCPU *cpu = ARM_CPU(cs);
    435    CPUARMState *env = &cpu->env;
    436
    437    if (is_a64(env)) {
    438        sp = env->xregs[31];
    439    } else {
    440        sp = env->regs[13];
    441    }
    442#endif
    443#ifdef TARGET_RISCV
    444    RISCVCPU *cpu = RISCV_CPU(cs);
    445    CPURISCVState *env = &cpu->env;
    446
    447    sp = env->gpr[xSP];
    448#endif
    449
    450    return sp - 64;
    451}
    452
    453static void
    454common_semi_flen_cb(CPUState *cs, target_ulong ret, target_ulong err)
    455{
    456    /* The size is always stored in big-endian order, extract
    457       the value. We assume the size always fit in 32 bits.  */
    458    uint32_t size;
    459    cpu_memory_rw_debug(cs, common_semi_flen_buf(cs) + 32,
    460                        (uint8_t *)&size, 4, 0);
    461    size = be32_to_cpu(size);
    462    common_semi_set_ret(cs, size);
    463    errno = err;
    464    set_swi_errno(cs, -1);
    465}
    466
    467static int common_semi_open_guestfd;
    468
    469static void
    470common_semi_open_cb(CPUState *cs, target_ulong ret, target_ulong err)
    471{
    472    if (ret == (target_ulong)-1) {
    473        errno = err;
    474        set_swi_errno(cs, -1);
    475        dealloc_guestfd(common_semi_open_guestfd);
    476    } else {
    477        associate_guestfd(common_semi_open_guestfd, ret);
    478        ret = common_semi_open_guestfd;
    479    }
    480    common_semi_set_ret(cs, ret);
    481}
    482
    483static target_ulong
    484common_semi_gdb_syscall(CPUState *cs, gdb_syscall_complete_cb cb,
    485                        const char *fmt, ...)
    486{
    487    va_list va;
    488
    489    va_start(va, fmt);
    490    gdb_do_syscallv(cb, fmt, va);
    491    va_end(va);
    492
    493    /*
    494     * FIXME: in softmmu mode, the gdbstub will schedule our callback
    495     * to occur, but will not actually call it to complete the syscall
    496     * until after this function has returned and we are back in the
    497     * CPU main loop. Therefore callers to this function must not
    498     * do anything with its return value, because it is not necessarily
    499     * the result of the syscall, but could just be the old value of X0.
    500     * The only thing safe to do with this is that the callers of
    501     * do_common_semihosting() will write it straight back into X0.
    502     * (In linux-user mode, the callback will have happened before
    503     * gdb_do_syscallv() returns.)
    504     *
    505     * We should tidy this up so neither this function nor
    506     * do_common_semihosting() return a value, so the mistake of
    507     * doing something with the return value is not possible to make.
    508     */
    509
    510    return common_semi_arg(cs, 0);
    511}
    512
    513/*
    514 * Types for functions implementing various semihosting calls
    515 * for specific types of guest file descriptor. These must all
    516 * do the work and return the required return value for the guest,
    517 * setting the guest errno if appropriate.
    518 */
    519typedef uint32_t sys_closefn(CPUState *cs, GuestFD *gf);
    520typedef uint32_t sys_writefn(CPUState *cs, GuestFD *gf,
    521                             target_ulong buf, uint32_t len);
    522typedef uint32_t sys_readfn(CPUState *cs, GuestFD *gf,
    523                            target_ulong buf, uint32_t len);
    524typedef uint32_t sys_isattyfn(CPUState *cs, GuestFD *gf);
    525typedef uint32_t sys_seekfn(CPUState *cs, GuestFD *gf,
    526                            target_ulong offset);
    527typedef uint32_t sys_flenfn(CPUState *cs, GuestFD *gf);
    528
    529static uint32_t host_closefn(CPUState *cs, GuestFD *gf)
    530{
    531    /*
    532     * Only close the underlying host fd if it's one we opened on behalf
    533     * of the guest in SYS_OPEN.
    534     */
    535    if (gf->hostfd == STDIN_FILENO ||
    536        gf->hostfd == STDOUT_FILENO ||
    537        gf->hostfd == STDERR_FILENO) {
    538        return 0;
    539    }
    540    return set_swi_errno(cs, close(gf->hostfd));
    541}
    542
    543static uint32_t host_writefn(CPUState *cs, GuestFD *gf,
    544                             target_ulong buf, uint32_t len)
    545{
    546    CPUArchState *env = cs->env_ptr;
    547    uint32_t ret;
    548    char *s = lock_user(VERIFY_READ, buf, len, 1);
    549    (void) env; /* Used in arm softmmu lock_user implicitly */
    550    if (!s) {
    551        /* Return bytes not written on error */
    552        return len;
    553    }
    554    ret = set_swi_errno(cs, write(gf->hostfd, s, len));
    555    unlock_user(s, buf, 0);
    556    if (ret == (uint32_t)-1) {
    557        ret = 0;
    558    }
    559    /* Return bytes not written */
    560    return len - ret;
    561}
    562
    563static uint32_t host_readfn(CPUState *cs, GuestFD *gf,
    564                            target_ulong buf, uint32_t len)
    565{
    566    CPUArchState *env = cs->env_ptr;
    567    uint32_t ret;
    568    char *s = lock_user(VERIFY_WRITE, buf, len, 0);
    569    (void) env; /* Used in arm softmmu lock_user implicitly */
    570    if (!s) {
    571        /* return bytes not read */
    572        return len;
    573    }
    574    do {
    575        ret = set_swi_errno(cs, read(gf->hostfd, s, len));
    576    } while (ret == -1 && errno == EINTR);
    577    unlock_user(s, buf, len);
    578    if (ret == (uint32_t)-1) {
    579        ret = 0;
    580    }
    581    /* Return bytes not read */
    582    return len - ret;
    583}
    584
    585static uint32_t host_isattyfn(CPUState *cs, GuestFD *gf)
    586{
    587    return isatty(gf->hostfd);
    588}
    589
    590static uint32_t host_seekfn(CPUState *cs, GuestFD *gf, target_ulong offset)
    591{
    592    uint32_t ret = set_swi_errno(cs, lseek(gf->hostfd, offset, SEEK_SET));
    593    if (ret == (uint32_t)-1) {
    594        return -1;
    595    }
    596    return 0;
    597}
    598
    599static uint32_t host_flenfn(CPUState *cs, GuestFD *gf)
    600{
    601    struct stat buf;
    602    uint32_t ret = set_swi_errno(cs, fstat(gf->hostfd, &buf));
    603    if (ret == (uint32_t)-1) {
    604        return -1;
    605    }
    606    return buf.st_size;
    607}
    608
    609static uint32_t gdb_closefn(CPUState *cs, GuestFD *gf)
    610{
    611    return common_semi_gdb_syscall(cs, common_semi_cb, "close,%x", gf->hostfd);
    612}
    613
    614static uint32_t gdb_writefn(CPUState *cs, GuestFD *gf,
    615                            target_ulong buf, uint32_t len)
    616{
    617    common_semi_syscall_len = len;
    618    return common_semi_gdb_syscall(cs, common_semi_cb, "write,%x,%x,%x",
    619                                   gf->hostfd, buf, len);
    620}
    621
    622static uint32_t gdb_readfn(CPUState *cs, GuestFD *gf,
    623                           target_ulong buf, uint32_t len)
    624{
    625    common_semi_syscall_len = len;
    626    return common_semi_gdb_syscall(cs, common_semi_cb, "read,%x,%x,%x",
    627                                   gf->hostfd, buf, len);
    628}
    629
    630static uint32_t gdb_isattyfn(CPUState *cs, GuestFD *gf)
    631{
    632    return common_semi_gdb_syscall(cs, common_semi_cb, "isatty,%x", gf->hostfd);
    633}
    634
    635static uint32_t gdb_seekfn(CPUState *cs, GuestFD *gf, target_ulong offset)
    636{
    637    return common_semi_gdb_syscall(cs, common_semi_cb, "lseek,%x,%x,0",
    638                                   gf->hostfd, offset);
    639}
    640
    641static uint32_t gdb_flenfn(CPUState *cs, GuestFD *gf)
    642{
    643    return common_semi_gdb_syscall(cs, common_semi_flen_cb, "fstat,%x,%x",
    644                                   gf->hostfd, common_semi_flen_buf(cs));
    645}
    646
    647#define SHFB_MAGIC_0 0x53
    648#define SHFB_MAGIC_1 0x48
    649#define SHFB_MAGIC_2 0x46
    650#define SHFB_MAGIC_3 0x42
    651
    652/* Feature bits reportable in feature byte 0 */
    653#define SH_EXT_EXIT_EXTENDED (1 << 0)
    654#define SH_EXT_STDOUT_STDERR (1 << 1)
    655
    656static const uint8_t featurefile_data[] = {
    657    SHFB_MAGIC_0,
    658    SHFB_MAGIC_1,
    659    SHFB_MAGIC_2,
    660    SHFB_MAGIC_3,
    661    SH_EXT_EXIT_EXTENDED | SH_EXT_STDOUT_STDERR, /* Feature byte 0 */
    662};
    663
    664static void init_featurefile_guestfd(int guestfd)
    665{
    666    GuestFD *gf = do_get_guestfd(guestfd);
    667
    668    assert(gf);
    669    gf->type = GuestFDFeatureFile;
    670    gf->featurefile_offset = 0;
    671}
    672
    673static uint32_t featurefile_closefn(CPUState *cs, GuestFD *gf)
    674{
    675    /* Nothing to do */
    676    return 0;
    677}
    678
    679static uint32_t featurefile_writefn(CPUState *cs, GuestFD *gf,
    680                                    target_ulong buf, uint32_t len)
    681{
    682    /* This fd can never be open for writing */
    683
    684    errno = EBADF;
    685    return set_swi_errno(cs, -1);
    686}
    687
    688static uint32_t featurefile_readfn(CPUState *cs, GuestFD *gf,
    689                                   target_ulong buf, uint32_t len)
    690{
    691    CPUArchState *env = cs->env_ptr;
    692    uint32_t i;
    693    char *s;
    694
    695    (void) env; /* Used in arm softmmu lock_user implicitly */
    696    s = lock_user(VERIFY_WRITE, buf, len, 0);
    697    if (!s) {
    698        return len;
    699    }
    700
    701    for (i = 0; i < len; i++) {
    702        if (gf->featurefile_offset >= sizeof(featurefile_data)) {
    703            break;
    704        }
    705        s[i] = featurefile_data[gf->featurefile_offset];
    706        gf->featurefile_offset++;
    707    }
    708
    709    unlock_user(s, buf, len);
    710
    711    /* Return number of bytes not read */
    712    return len - i;
    713}
    714
    715static uint32_t featurefile_isattyfn(CPUState *cs, GuestFD *gf)
    716{
    717    return 0;
    718}
    719
    720static uint32_t featurefile_seekfn(CPUState *cs, GuestFD *gf,
    721                                   target_ulong offset)
    722{
    723    gf->featurefile_offset = offset;
    724    return 0;
    725}
    726
    727static uint32_t featurefile_flenfn(CPUState *cs, GuestFD *gf)
    728{
    729    return sizeof(featurefile_data);
    730}
    731
    732typedef struct GuestFDFunctions {
    733    sys_closefn *closefn;
    734    sys_writefn *writefn;
    735    sys_readfn *readfn;
    736    sys_isattyfn *isattyfn;
    737    sys_seekfn *seekfn;
    738    sys_flenfn *flenfn;
    739} GuestFDFunctions;
    740
    741static const GuestFDFunctions guestfd_fns[] = {
    742    [GuestFDHost] = {
    743        .closefn = host_closefn,
    744        .writefn = host_writefn,
    745        .readfn = host_readfn,
    746        .isattyfn = host_isattyfn,
    747        .seekfn = host_seekfn,
    748        .flenfn = host_flenfn,
    749    },
    750    [GuestFDGDB] = {
    751        .closefn = gdb_closefn,
    752        .writefn = gdb_writefn,
    753        .readfn = gdb_readfn,
    754        .isattyfn = gdb_isattyfn,
    755        .seekfn = gdb_seekfn,
    756        .flenfn = gdb_flenfn,
    757    },
    758    [GuestFDFeatureFile] = {
    759        .closefn = featurefile_closefn,
    760        .writefn = featurefile_writefn,
    761        .readfn = featurefile_readfn,
    762        .isattyfn = featurefile_isattyfn,
    763        .seekfn = featurefile_seekfn,
    764        .flenfn = featurefile_flenfn,
    765    },
    766};
    767
    768/*
    769 * Read the input value from the argument block; fail the semihosting
    770 * call if the memory read fails. Eventually we could use a generic
    771 * CPUState helper function here.
    772 */
    773static inline bool is_64bit_semihosting(CPUArchState *env)
    774{
    775#if defined(TARGET_ARM)
    776    return is_a64(env);
    777#elif defined(TARGET_RISCV)
    778    return !riscv_cpu_is_32bit(env);
    779#else
    780#error un-handled architecture
    781#endif
    782}
    783
    784
    785#define GET_ARG(n) do {                                 \
    786    if (is_64bit_semihosting(env)) {                    \
    787        if (get_user_u64(arg ## n, args + (n) * 8)) {   \
    788            errno = EFAULT;                             \
    789            return set_swi_errno(cs, -1);               \
    790        }                                               \
    791    } else {                                            \
    792        if (get_user_u32(arg ## n, args + (n) * 4)) {   \
    793            errno = EFAULT;                             \
    794            return set_swi_errno(cs, -1);              \
    795        }                                               \
    796    }                                                   \
    797} while (0)
    798
    799#define SET_ARG(n, val)                                 \
    800    (is_64bit_semihosting(env) ?                        \
    801     put_user_u64(val, args + (n) * 8) :                \
    802     put_user_u32(val, args + (n) * 4))
    803
    804
    805/*
    806 * Do a semihosting call.
    807 *
    808 * The specification always says that the "return register" either
    809 * returns a specific value or is corrupted, so we don't need to
    810 * report to our caller whether we are returning a value or trying to
    811 * leave the register unchanged. We use 0xdeadbeef as the return value
    812 * when there isn't a defined return value for the call.
    813 */
    814target_ulong do_common_semihosting(CPUState *cs)
    815{
    816    CPUArchState *env = cs->env_ptr;
    817    target_ulong args;
    818    target_ulong arg0, arg1, arg2, arg3;
    819    target_ulong ul_ret;
    820    char * s;
    821    int nr;
    822    uint32_t ret;
    823    uint32_t len;
    824    GuestFD *gf;
    825    int64_t elapsed;
    826
    827    (void) env; /* Used implicitly by arm lock_user macro */
    828    nr = common_semi_arg(cs, 0) & 0xffffffffU;
    829    args = common_semi_arg(cs, 1);
    830
    831    switch (nr) {
    832    case TARGET_SYS_OPEN:
    833    {
    834        int guestfd;
    835
    836        GET_ARG(0);
    837        GET_ARG(1);
    838        GET_ARG(2);
    839        s = lock_user_string(arg0);
    840        if (!s) {
    841            errno = EFAULT;
    842            return set_swi_errno(cs, -1);
    843        }
    844        if (arg1 >= 12) {
    845            unlock_user(s, arg0, 0);
    846            errno = EINVAL;
    847            return set_swi_errno(cs, -1);
    848        }
    849
    850        guestfd = alloc_guestfd();
    851        if (guestfd < 0) {
    852            unlock_user(s, arg0, 0);
    853            errno = EMFILE;
    854            return set_swi_errno(cs, -1);
    855        }
    856
    857        if (strcmp(s, ":tt") == 0) {
    858            int result_fileno;
    859
    860            /*
    861             * We implement SH_EXT_STDOUT_STDERR, so:
    862             *  open for read == stdin
    863             *  open for write == stdout
    864             *  open for append == stderr
    865             */
    866            if (arg1 < 4) {
    867                result_fileno = STDIN_FILENO;
    868            } else if (arg1 < 8) {
    869                result_fileno = STDOUT_FILENO;
    870            } else {
    871                result_fileno = STDERR_FILENO;
    872            }
    873            associate_guestfd(guestfd, result_fileno);
    874            unlock_user(s, arg0, 0);
    875            return guestfd;
    876        }
    877        if (strcmp(s, ":semihosting-features") == 0) {
    878            unlock_user(s, arg0, 0);
    879            /* We must fail opens for modes other than 0 ('r') or 1 ('rb') */
    880            if (arg1 != 0 && arg1 != 1) {
    881                dealloc_guestfd(guestfd);
    882                errno = EACCES;
    883                return set_swi_errno(cs, -1);
    884            }
    885            init_featurefile_guestfd(guestfd);
    886            return guestfd;
    887        }
    888
    889        if (use_gdb_syscalls()) {
    890            common_semi_open_guestfd = guestfd;
    891            ret = common_semi_gdb_syscall(cs, common_semi_open_cb,
    892                                          "open,%s,%x,1a4", arg0, (int)arg2 + 1,
    893                                          gdb_open_modeflags[arg1]);
    894        } else {
    895            ret = set_swi_errno(cs, open(s, open_modeflags[arg1], 0644));
    896            if (ret == (uint32_t)-1) {
    897                dealloc_guestfd(guestfd);
    898            } else {
    899                associate_guestfd(guestfd, ret);
    900                ret = guestfd;
    901            }
    902        }
    903        unlock_user(s, arg0, 0);
    904        return ret;
    905    }
    906    case TARGET_SYS_CLOSE:
    907        GET_ARG(0);
    908
    909        gf = get_guestfd(arg0);
    910        if (!gf) {
    911            errno = EBADF;
    912            return set_swi_errno(cs, -1);
    913        }
    914
    915        ret = guestfd_fns[gf->type].closefn(cs, gf);
    916        dealloc_guestfd(arg0);
    917        return ret;
    918    case TARGET_SYS_WRITEC:
    919        qemu_semihosting_console_outc(cs->env_ptr, args);
    920        return 0xdeadbeef;
    921    case TARGET_SYS_WRITE0:
    922        return qemu_semihosting_console_outs(cs->env_ptr, args);
    923    case TARGET_SYS_WRITE:
    924        GET_ARG(0);
    925        GET_ARG(1);
    926        GET_ARG(2);
    927        len = arg2;
    928
    929        gf = get_guestfd(arg0);
    930        if (!gf) {
    931            errno = EBADF;
    932            return set_swi_errno(cs, -1);
    933        }
    934
    935        return guestfd_fns[gf->type].writefn(cs, gf, arg1, len);
    936    case TARGET_SYS_READ:
    937        GET_ARG(0);
    938        GET_ARG(1);
    939        GET_ARG(2);
    940        len = arg2;
    941
    942        gf = get_guestfd(arg0);
    943        if (!gf) {
    944            errno = EBADF;
    945            return set_swi_errno(cs, -1);
    946        }
    947
    948        return guestfd_fns[gf->type].readfn(cs, gf, arg1, len);
    949    case TARGET_SYS_READC:
    950        return qemu_semihosting_console_inc(cs->env_ptr);
    951    case TARGET_SYS_ISERROR:
    952        GET_ARG(0);
    953        return (target_long) arg0 < 0 ? 1 : 0;
    954    case TARGET_SYS_ISTTY:
    955        GET_ARG(0);
    956
    957        gf = get_guestfd(arg0);
    958        if (!gf) {
    959            errno = EBADF;
    960            return set_swi_errno(cs, -1);
    961        }
    962
    963        return guestfd_fns[gf->type].isattyfn(cs, gf);
    964    case TARGET_SYS_SEEK:
    965        GET_ARG(0);
    966        GET_ARG(1);
    967
    968        gf = get_guestfd(arg0);
    969        if (!gf) {
    970            errno = EBADF;
    971            return set_swi_errno(cs, -1);
    972        }
    973
    974        return guestfd_fns[gf->type].seekfn(cs, gf, arg1);
    975    case TARGET_SYS_FLEN:
    976        GET_ARG(0);
    977
    978        gf = get_guestfd(arg0);
    979        if (!gf) {
    980            errno = EBADF;
    981            return set_swi_errno(cs, -1);
    982        }
    983
    984        return guestfd_fns[gf->type].flenfn(cs, gf);
    985    case TARGET_SYS_TMPNAM:
    986        GET_ARG(0);
    987        GET_ARG(1);
    988        GET_ARG(2);
    989        if (asprintf(&s, "/tmp/qemu-%x%02x", getpid(),
    990                     (int) (arg1 & 0xff)) < 0) {
    991            return -1;
    992        }
    993        ul_ret = (target_ulong) -1;
    994
    995        /* Make sure there's enough space in the buffer */
    996        if (strlen(s) < arg2) {
    997            char *output = lock_user(VERIFY_WRITE, arg0, arg2, 0);
    998            strcpy(output, s);
    999            unlock_user(output, arg0, arg2);
   1000            ul_ret = 0;
   1001        }
   1002        free(s);
   1003        return ul_ret;
   1004    case TARGET_SYS_REMOVE:
   1005        GET_ARG(0);
   1006        GET_ARG(1);
   1007        if (use_gdb_syscalls()) {
   1008            ret = common_semi_gdb_syscall(cs, common_semi_cb, "unlink,%s",
   1009                                          arg0, (int)arg1 + 1);
   1010        } else {
   1011            s = lock_user_string(arg0);
   1012            if (!s) {
   1013                errno = EFAULT;
   1014                return set_swi_errno(cs, -1);
   1015            }
   1016            ret =  set_swi_errno(cs, remove(s));
   1017            unlock_user(s, arg0, 0);
   1018        }
   1019        return ret;
   1020    case TARGET_SYS_RENAME:
   1021        GET_ARG(0);
   1022        GET_ARG(1);
   1023        GET_ARG(2);
   1024        GET_ARG(3);
   1025        if (use_gdb_syscalls()) {
   1026            return common_semi_gdb_syscall(cs, common_semi_cb, "rename,%s,%s",
   1027                                           arg0, (int)arg1 + 1, arg2,
   1028                                           (int)arg3 + 1);
   1029        } else {
   1030            char *s2;
   1031            s = lock_user_string(arg0);
   1032            s2 = lock_user_string(arg2);
   1033            if (!s || !s2) {
   1034                errno = EFAULT;
   1035                ret = set_swi_errno(cs, -1);
   1036            } else {
   1037                ret = set_swi_errno(cs, rename(s, s2));
   1038            }
   1039            if (s2)
   1040                unlock_user(s2, arg2, 0);
   1041            if (s)
   1042                unlock_user(s, arg0, 0);
   1043            return ret;
   1044        }
   1045    case TARGET_SYS_CLOCK:
   1046        return clock() / (CLOCKS_PER_SEC / 100);
   1047    case TARGET_SYS_TIME:
   1048        return set_swi_errno(cs, time(NULL));
   1049    case TARGET_SYS_SYSTEM:
   1050        GET_ARG(0);
   1051        GET_ARG(1);
   1052        if (use_gdb_syscalls()) {
   1053            return common_semi_gdb_syscall(cs, common_semi_cb, "system,%s",
   1054                                           arg0, (int)arg1 + 1);
   1055        } else {
   1056            s = lock_user_string(arg0);
   1057            if (!s) {
   1058                errno = EFAULT;
   1059                return set_swi_errno(cs, -1);
   1060            }
   1061            ret = set_swi_errno(cs, system(s));
   1062            unlock_user(s, arg0, 0);
   1063            return ret;
   1064        }
   1065    case TARGET_SYS_ERRNO:
   1066        return get_swi_errno(cs);
   1067    case TARGET_SYS_GET_CMDLINE:
   1068        {
   1069            /* Build a command-line from the original argv.
   1070             *
   1071             * The inputs are:
   1072             *     * arg0, pointer to a buffer of at least the size
   1073             *               specified in arg1.
   1074             *     * arg1, size of the buffer pointed to by arg0 in
   1075             *               bytes.
   1076             *
   1077             * The outputs are:
   1078             *     * arg0, pointer to null-terminated string of the
   1079             *               command line.
   1080             *     * arg1, length of the string pointed to by arg0.
   1081             */
   1082
   1083            char *output_buffer;
   1084            size_t input_size;
   1085            size_t output_size;
   1086            int status = 0;
   1087#if !defined(CONFIG_USER_ONLY)
   1088            const char *cmdline;
   1089#else
   1090            TaskState *ts = cs->opaque;
   1091#endif
   1092            GET_ARG(0);
   1093            GET_ARG(1);
   1094            input_size = arg1;
   1095            /* Compute the size of the output string.  */
   1096#if !defined(CONFIG_USER_ONLY)
   1097            cmdline = semihosting_get_cmdline();
   1098            if (cmdline == NULL) {
   1099                cmdline = ""; /* Default to an empty line. */
   1100            }
   1101            output_size = strlen(cmdline) + 1; /* Count terminating 0. */
   1102#else
   1103            unsigned int i;
   1104
   1105            output_size = ts->info->arg_end - ts->info->arg_start;
   1106            if (!output_size) {
   1107                /*
   1108                 * We special-case the "empty command line" case (argc==0).
   1109                 * Just provide the terminating 0.
   1110                 */
   1111                output_size = 1;
   1112            }
   1113#endif
   1114
   1115            if (output_size > input_size) {
   1116                /* Not enough space to store command-line arguments.  */
   1117                errno = E2BIG;
   1118                return set_swi_errno(cs, -1);
   1119            }
   1120
   1121            /* Adjust the command-line length.  */
   1122            if (SET_ARG(1, output_size - 1)) {
   1123                /* Couldn't write back to argument block */
   1124                errno = EFAULT;
   1125                return set_swi_errno(cs, -1);
   1126            }
   1127
   1128            /* Lock the buffer on the ARM side.  */
   1129            output_buffer = lock_user(VERIFY_WRITE, arg0, output_size, 0);
   1130            if (!output_buffer) {
   1131                errno = EFAULT;
   1132                return set_swi_errno(cs, -1);
   1133            }
   1134
   1135            /* Copy the command-line arguments.  */
   1136#if !defined(CONFIG_USER_ONLY)
   1137            pstrcpy(output_buffer, output_size, cmdline);
   1138#else
   1139            if (output_size == 1) {
   1140                /* Empty command-line.  */
   1141                output_buffer[0] = '\0';
   1142                goto out;
   1143            }
   1144
   1145            if (copy_from_user(output_buffer, ts->info->arg_start,
   1146                               output_size)) {
   1147                errno = EFAULT;
   1148                status = set_swi_errno(cs, -1);
   1149                goto out;
   1150            }
   1151
   1152            /* Separate arguments by white spaces.  */
   1153            for (i = 0; i < output_size - 1; i++) {
   1154                if (output_buffer[i] == 0) {
   1155                    output_buffer[i] = ' ';
   1156                }
   1157            }
   1158        out:
   1159#endif
   1160            /* Unlock the buffer on the ARM side.  */
   1161            unlock_user(output_buffer, arg0, output_size);
   1162
   1163            return status;
   1164        }
   1165    case TARGET_SYS_HEAPINFO:
   1166        {
   1167            target_ulong retvals[4];
   1168            target_ulong limit;
   1169            int i;
   1170#ifdef CONFIG_USER_ONLY
   1171            TaskState *ts = cs->opaque;
   1172#else
   1173            target_ulong rambase = common_semi_rambase(cs);
   1174#endif
   1175
   1176            GET_ARG(0);
   1177
   1178#ifdef CONFIG_USER_ONLY
   1179            /*
   1180             * Some C libraries assume the heap immediately follows .bss, so
   1181             * allocate it using sbrk.
   1182             */
   1183            if (!ts->heap_limit) {
   1184                abi_ulong ret;
   1185
   1186                ts->heap_base = do_brk(0);
   1187                limit = ts->heap_base + COMMON_SEMI_HEAP_SIZE;
   1188                /* Try a big heap, and reduce the size if that fails.  */
   1189                for (;;) {
   1190                    ret = do_brk(limit);
   1191                    if (ret >= limit) {
   1192                        break;
   1193                    }
   1194                    limit = (ts->heap_base >> 1) + (limit >> 1);
   1195                }
   1196                ts->heap_limit = limit;
   1197            }
   1198
   1199            retvals[0] = ts->heap_base;
   1200            retvals[1] = ts->heap_limit;
   1201            retvals[2] = ts->stack_base;
   1202            retvals[3] = 0; /* Stack limit.  */
   1203#else
   1204            limit = current_machine->ram_size;
   1205            /* TODO: Make this use the limit of the loaded application.  */
   1206            retvals[0] = rambase + limit / 2;
   1207            retvals[1] = rambase + limit;
   1208            retvals[2] = rambase + limit; /* Stack base */
   1209            retvals[3] = rambase; /* Stack limit.  */
   1210#endif
   1211
   1212            for (i = 0; i < ARRAY_SIZE(retvals); i++) {
   1213                bool fail;
   1214
   1215                if (is_64bit_semihosting(env)) {
   1216                    fail = put_user_u64(retvals[i], arg0 + i * 8);
   1217                } else {
   1218                    fail = put_user_u32(retvals[i], arg0 + i * 4);
   1219                }
   1220
   1221                if (fail) {
   1222                    /* Couldn't write back to argument block */
   1223                    errno = EFAULT;
   1224                    return set_swi_errno(cs, -1);
   1225                }
   1226            }
   1227            return 0;
   1228        }
   1229    case TARGET_SYS_EXIT:
   1230    case TARGET_SYS_EXIT_EXTENDED:
   1231        if (common_semi_sys_exit_extended(cs, nr)) {
   1232            /*
   1233             * The A64 version of SYS_EXIT takes a parameter block,
   1234             * so the application-exit type can return a subcode which
   1235             * is the exit status code from the application.
   1236             * SYS_EXIT_EXTENDED is an a new-in-v2.0 optional function
   1237             * which allows A32/T32 guests to also provide a status code.
   1238             */
   1239            GET_ARG(0);
   1240            GET_ARG(1);
   1241
   1242            if (arg0 == ADP_Stopped_ApplicationExit) {
   1243                ret = arg1;
   1244            } else {
   1245                ret = 1;
   1246            }
   1247        } else {
   1248            /*
   1249             * The A32/T32 version of SYS_EXIT specifies only
   1250             * Stopped_ApplicationExit as normal exit, but does not
   1251             * allow the guest to specify the exit status code.
   1252             * Everything else is considered an error.
   1253             */
   1254            ret = (args == ADP_Stopped_ApplicationExit) ? 0 : 1;
   1255        }
   1256        gdb_exit(ret);
   1257        exit(ret);
   1258    case TARGET_SYS_ELAPSED:
   1259        elapsed = get_clock() - clock_start;
   1260        if (sizeof(target_ulong) == 8) {
   1261            SET_ARG(0, elapsed);
   1262        } else {
   1263            SET_ARG(0, (uint32_t) elapsed);
   1264            SET_ARG(1, (uint32_t) (elapsed >> 32));
   1265        }
   1266        return 0;
   1267    case TARGET_SYS_TICKFREQ:
   1268        /* qemu always uses nsec */
   1269        return 1000000000;
   1270    case TARGET_SYS_SYNCCACHE:
   1271        /*
   1272         * Clean the D-cache and invalidate the I-cache for the specified
   1273         * virtual address range. This is a nop for us since we don't
   1274         * implement caches. This is only present on A64.
   1275         */
   1276#ifdef TARGET_ARM
   1277        if (is_a64(cs->env_ptr)) {
   1278            return 0;
   1279        }
   1280#endif
   1281#ifdef TARGET_RISCV
   1282        return 0;
   1283#endif
   1284        /* fall through -- invalid for A32/T32 */
   1285    default:
   1286        fprintf(stderr, "qemu: Unsupported SemiHosting SWI 0x%02x\n", nr);
   1287        cpu_dump_state(cs, stderr, 0);
   1288        abort();
   1289    }
   1290}