qemu/semihosting/arm-compat-semi.c
<<
>>
Prefs
   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#ifdef CONFIG_USER_ONLY
  41#include "qemu.h"
  42
  43#define COMMON_SEMI_HEAP_SIZE (128 * 1024 * 1024)
  44#else
  45#include "exec/gdbstub.h"
  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}
1291