This series adds semihosting support to hexagon system emulation,
together with functional tests for the added operations.

The Hexagon semihosting spec can be found at:
https://docs.qualcomm.com/doc/80-N2040-101_102648/topic/semihosting-specification.html

v1: 
https://lore.kernel.org/qemu-devel/[email protected]/
v2: 
https://lore.kernel.org/qemu-devel/[email protected]/T/#m9e966877cda81c5661838fedadf4e69bd912cbb5
v3: 
https://lore.kernel.org/qemu-devel/[email protected]/

Changes in v4:
- Added patches 1 and 2: a couple hexagon fixes for big-endian hosts
- Patch 3: fix unaligned pc reporting on linux-user mode
- Patch 5: fix big-endian issues
- Patch 8 and 11: drop arch_[gs]et_(thread|system)_reg()
- Patch 10: avoid OS-specific ifdefs and fixes for big-endian
- Patch 12: define target errnos in a more readable way
- Patch 14: drop unuseful code comments

Changes in v3:
- Reworded semihosting section at Hexagon docs
- Rebased, added Reviewed-by's, dropped already merged patch

Changes in v2:
- Added patch 1, a fix for an existing bug that appeared with the new
  test semantics from the last patch.
- Patch 3: s/hexagon_touch_memory/hexagon_peek_memory_range/
- Patch 7:
  * Add semihosting spec link to docs
  * Fixed HEX_SYS_EXCEPTION
- Patch 10:
  * Moved tables to static definition
  * Fixed compilation for Windows
- Dropped patch 11 (OPEN/READ/CLOSE_DIR support): for now we don't have
  dirent semantics for Windows, so leave these ops to a followup series.
- Patch 14:
  * Update test version
  * Don't change directory
  * Don't use os.path, use scratch_file

Brian Cain (4):
  semihosting: add APIs for chardev-aware guest fd routing
  target/hexagon: Add an errno mapping
  python/machine: support routing semihosting output to the test console
  tests/functional: Add hexagon semihosting systests

Matheus Tavares Bernardino (10):
  disas/hexagon: honour target byte order when printing instructions
  target/hexagon: fix store-conditional on big-endian hosts
  target/hexagon: fix improper assign of cause code to exception index
  target/hexagon: fix PC advancement for non-COF TB terminators
  target/hexagon: add aux functions for guest mem load/store
  semihosting: add callback to set error
  target/hexagon: add semihosting support
  semihosting: add ftruncate helper (to be used for hexagon)
  target/hexagon: add main arch-specific semihosting operations
  target/hexagon: add COREDUMP semihosting operation

 configs/targets/hexagon-softmmu.mak       |   2 +
 disas/hexagon.c                           |   6 +-
 docs/system/target-hexagon.rst            |   8 +-
 hw/hexagon/Kconfig                        |   1 +
 hw/hexagon/hexagon_dsp.c                  |   2 +
 include/semihosting/common-semi.h         |   2 +
 include/semihosting/console.h             |   9 +
 include/semihosting/guestfd.h             |   9 +
 include/semihosting/syscalls.h            |   2 +
 linux-user/hexagon/cpu_loop.c             |   5 +-
 python/qemu/machine/machine.py            |  10 +-
 qemu-options.hx                           |   8 +-
 semihosting/arm-compat-semi.c             |   3 +-
 semihosting/console.c                     |   5 +
 semihosting/guestfd.c                     |   8 +
 semihosting/syscalls.c                    |  29 +
 target/arm/common-semi-target.c           |   4 +
 target/hexagon/common-semi-target.c       |  51 ++
 target/hexagon/cpu.c                      |   5 +-
 target/hexagon/cpu_helper.c               | 100 ++++
 target/hexagon/cpu_helper.h               |   6 +
 target/hexagon/genptr.c                   |   4 +-
 target/hexagon/hexswi.c                   | 672 +++++++++++++++++++++-
 target/hexagon/internal.h                 |   1 +
 target/hexagon/meson.build                |   1 +
 target/hexagon/translate.c                |  17 +-
 target/riscv/common-semi-target.c         |   4 +
 tests/functional/hexagon/meson.build      |   5 +
 tests/functional/hexagon/test_systests.py |  94 +++
 29 files changed, 1046 insertions(+), 27 deletions(-)
 create mode 100644 target/hexagon/common-semi-target.c
 create mode 100755 tests/functional/hexagon/test_systests.py

Range-diff against v3:
 -:  ---------- >  1:  16f730778f disas/hexagon: honour target byte order when 
printing instructions
 -:  ---------- >  2:  4fc8afeddf target/hexagon: fix store-conditional on 
big-endian hosts
 1:  3f809b51ae !  3:  5403f0e70b target/hexagon: fix improper assign of cause 
code to exception index
    @@ Commit message
         Reviewed-by: Pierrick Bouvier <[email protected]>
         Signed-off-by: Matheus Tavares Bernardino 
<[email protected]>
     
    + ## linux-user/hexagon/cpu_loop.c ##
    +@@ linux-user/hexagon/cpu_loop.c: void cpu_loop(CPUHexagonState *env)
    +             break;
    +             case HEX_CAUSE_MISALIGNED_LOAD:
    +             case HEX_CAUSE_MISALIGNED_STORE:
    ++            case HEX_CAUSE_PC_NOT_ALIGNED:
    +             force_sig_fault(TARGET_SIGBUS, TARGET_BUS_ADRALN,
    +                     env->gpr[HEX_REG_PC]);
    +             break;
    +@@ linux-user/hexagon/cpu_loop.c: void cpu_loop(CPUHexagonState *env)
    +                 exit(EXIT_FAILURE);
    +             }
    +             break;
    +-        case HEX_CAUSE_PC_NOT_ALIGNED:
    +-            force_sig_fault(TARGET_SIGBUS, TARGET_BUS_ADRALN,
    +-                            env->gpr[HEX_REG_R31]);
    +-            break;
    +         case HEX_CAUSE_INVALID_PACKET:
    +         case HEX_CAUSE_REG_WRITE_CONFLICT:
    +             force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC,
    +
      ## target/hexagon/cpu.c ##
     @@ target/hexagon/cpu.c: static TCGTBCPUState 
hexagon_get_tb_cpu_state(CPUState *cs)
              hex_flags = FIELD_DP32(hex_flags, TB_FLAGS, IS_TIGHT_LOOP, 1);
 2:  903af8b645 =  4:  c1dad05e0a target/hexagon: fix PC advancement for 
non-COF TB terminators
 3:  334bb76346 !  5:  a1f63c8909 target/hexagon: add aux functions for guest 
mem load/store
    @@ target/hexagon/cpu_helper.c
     +#ifndef CONFIG_USER_ONLY
     +
     +static bool hexagon_read_memory_small(CPUHexagonState *env, target_ulong 
addr,
    -+                                      int byte_count, unsigned char 
*dstbuf,
    ++                                      int byte_count, uint64_t *data,
     +                                      int mmu_idx, uintptr_t retaddr)
     + {
     +    /* handle small sizes */
     +    switch (byte_count) {
     +    case 1:
    -+        *dstbuf = cpu_ldub_mmuidx_ra(env, addr, mmu_idx, retaddr);
    ++        *data = cpu_ldub_mmuidx_ra(env, addr, mmu_idx, retaddr);
     +        return true;
     +
     +    case 2:
    -+        if (QEMU_IS_ALIGNED(addr, 2)) {
    -+            *(unsigned short *)dstbuf =
    -+                cpu_lduw_le_mmuidx_ra(env, addr, mmu_idx, retaddr);
    -+            return true;
    -+        }
    -+        break;
    ++        *data = cpu_lduw_le_mmuidx_ra(env, addr, mmu_idx, retaddr);
    ++        return true;
     +
     +    case 4:
    -+        if (QEMU_IS_ALIGNED(addr, 4)) {
    -+            *(uint32_t *)dstbuf =
    -+                cpu_ldl_le_mmuidx_ra(env, addr, mmu_idx, retaddr);
    -+            return true;
    -+        }
    -+        break;
    ++        *data = cpu_ldl_le_mmuidx_ra(env, addr, mmu_idx, retaddr);
    ++        return true;
     +
     +    case 8:
    -+        if (QEMU_IS_ALIGNED(addr, 8)) {
    -+            *(uint64_t *)dstbuf =
    -+                cpu_ldq_le_mmuidx_ra(env, addr, mmu_idx, retaddr);
    -+            return true;
    -+        }
    -+        break;
    ++        *data = cpu_ldq_le_mmuidx_ra(env, addr, mmu_idx, retaddr);
    ++        return true;
     +
     +    default:
     +        /* larger request, handle elsewhere */
     +        return false;
     +    }
    -+
    -+    /* not aligned, copy bytes */
    -+    for (int i = 0; i < byte_count; ++i) {
    -+        *dstbuf++ = cpu_ldub_mmuidx_ra(env, addr++, mmu_idx, retaddr);
    -+    }
    -+    return true;
     +}
     +
     +void hexagon_read_memory(CPUHexagonState *env, target_ulong vaddr, int 
size,
    @@ target/hexagon/cpu_helper.c
     +    BQL_LOCK_GUARD();
     +    CPUState *cs = env_cpu(env);
     +    unsigned mmu_idx = cpu_mmu_index(cs, false);
    -+    if (!hexagon_read_memory_small(env, vaddr, size, retptr, mmu_idx,
    -+                                   retaddr)) {
    ++    uint64_t data;
    ++    if (hexagon_read_memory_small(env, vaddr, size, &data, mmu_idx, 
retaddr)) {
    ++        stn_he_p(retptr, size, data);
    ++    } else {
     +        cpu_abort(cs, "%s: ERROR: bad size = %d!\n", __func__, size);
     +    }
     +}
     +
     +static bool hexagon_write_memory_small(CPUHexagonState *env, target_ulong 
addr,
    -+                                       int byte_count, unsigned char 
*srcbuf,
    ++                                       int byte_count, uint64_t data,
     +                                       int mmu_idx, uintptr_t retaddr)
     +{
     +    /* handle small sizes */
     +    switch (byte_count) {
     +    case 1:
    -+        cpu_stb_mmuidx_ra(env, addr, *srcbuf, mmu_idx, retaddr);
    ++        cpu_stb_mmuidx_ra(env, addr, (uint8_t)data, mmu_idx, retaddr);
     +        return true;
     +
     +    case 2:
    -+        if (QEMU_IS_ALIGNED(addr, 2)) {
    -+            cpu_stw_le_mmuidx_ra(env, addr, *(uint16_t *)srcbuf, mmu_idx, 
retaddr);
    -+            return true;
    -+        }
    -+        break;
    ++        cpu_stw_le_mmuidx_ra(env, addr, (uint16_t)data, mmu_idx, retaddr);
    ++        return true;
     +
     +    case 4:
    -+        if (QEMU_IS_ALIGNED(addr, 4)) {
    -+            cpu_stl_le_mmuidx_ra(env, addr, *(uint32_t *)srcbuf, mmu_idx, 
retaddr);
    -+            return true;
    -+        }
    -+        break;
    ++        cpu_stl_le_mmuidx_ra(env, addr, (uint32_t)data, mmu_idx, retaddr);
    ++        return true;
     +
     +    case 8:
    -+        if (QEMU_IS_ALIGNED(addr, 8)) {
    -+            cpu_stq_le_mmuidx_ra(env, addr, *(uint64_t *)srcbuf, mmu_idx, 
retaddr);
    -+            return true;
    -+        }
    -+        break;
    ++        cpu_stq_le_mmuidx_ra(env, addr, (uint64_t)data, mmu_idx, retaddr);
    ++        return true;
     +
     +    default:
     +        /* larger request, handle elsewhere */
     +        return false;
     +    }
    -+
    -+    /* not aligned, copy bytes */
    -+    for (int i = 0; i < byte_count; ++i) {
    -+        cpu_stb_mmuidx_ra(env, addr++, *srcbuf++, mmu_idx, retaddr);
    -+    }
    -+
    -+    return true;
     +}
     +
     +void hexagon_write_memory(CPUHexagonState *env, target_ulong vaddr,
    @@ target/hexagon/cpu_helper.c
     +{
     +    CPUState *cs = env_cpu(env);
     +    unsigned mmu_idx = cpu_mmu_index(cs, false);
    -+    if (!hexagon_write_memory_small(env, vaddr, size, (unsigned char 
*)&data,
    -+                                   mmu_idx, retaddr)) {
    ++    if (!hexagon_write_memory_small(env, vaddr, size, data, mmu_idx, 
retaddr)) {
     +        cpu_abort(cs, "%s: ERROR: bad size = %d!\n", __func__, size);
     +    }
     +}
 4:  f2fc7ed466 <  -:  ---------- hexagon: cpu_helper: add reg reading/writing 
helpers
 5:  c8f8868aa7 =  6:  47eb2ef70d semihosting: add APIs for chardev-aware guest 
fd routing
 6:  ef17701179 =  7:  a37971603c semihosting: add callback to set error
 7:  f0d35e6115 !  8:  7529648c78 target/hexagon: add semihosting support
    @@ target/hexagon/common-semi-target.c (new)
     +uint64_t common_semi_arg(CPUState *cs, int argno)
     +{
     +    CPUHexagonState *env = cpu_env(cs);
    -+    return arch_get_thread_reg(env, HEX_REG_R00 + argno);
    ++    return env->gpr[HEX_REG_R00 + argno];
     +}
     +
     +void common_semi_set_ret(CPUState *cs, uint64_t ret)
     +{
     +    CPUHexagonState *env = cpu_env(cs);
    -+    arch_set_thread_reg(env, HEX_REG_R00, ret);
    ++    env->gpr[HEX_REG_R00] = ret;
     +}
     +
     +void common_semi_set_err(CPUState *cs, int err)
     +{
     +    CPUHexagonState *env = cpu_env(cs);
    -+    arch_set_thread_reg(env, HEX_REG_R01, err);
    ++    env->gpr[HEX_REG_R01] = err;
     +}
     +
     +bool common_semi_sys_exit_is_extended(CPUState *cs)
    @@ target/hexagon/common-semi-target.c (new)
     +uint64_t common_semi_stack_bottom(CPUState *cs)
     +{
     +    CPUHexagonState *env = cpu_env(cs);
    -+    return arch_get_thread_reg(env, HEX_REG_SP);
    ++    return env->gpr[HEX_REG_SP];
     +}
     +
     +bool common_semi_has_synccache(CPUArchState *env)
    @@ target/hexagon/hexswi.c
     +    g_assert(bql_locked());
     +    init_semihosting_guestfds();
     +
    -+    what_swi = arch_get_thread_reg(env, HEX_REG_R00);
    -+    swi_info = arch_get_thread_reg(env, HEX_REG_R01);
    ++    what_swi = env->gpr[HEX_REG_R00];
    ++    swi_info = env->gpr[HEX_REG_R01];
     +
     +    qemu_log_mask(CPU_LOG_INT,
     +                  "sim_handle_trap0: swi=0x%" PRIx32
     +                  " info=0x%" PRIx32 " PC=0x%" PRIx32
     +                  " thread=%" PRId32 "\n",
     +                  (uint32_t)what_swi, (uint32_t)swi_info,
    -+                  (uint32_t)arch_get_thread_reg(env, HEX_REG_PC),
    ++                  (uint32_t)env->gpr[HEX_REG_PC],
     +                  (uint32_t)env->threadId);
     +
     +    if (!is_hexagon_specific_swi_flag(what_swi)) {
    @@ target/hexagon/hexswi.c
     +
     +    case HEX_SYS_EXCEPTION:
     +    {
    -+        uint32_t ret = arch_get_thread_reg(env, HEX_REG_R02);
    -+        arch_set_system_reg(env, HEX_SREG_MODECTL, 0);
    ++        uint32_t ret = env->gpr[HEX_REG_R02];
    ++        env->gpr[HEX_SREG_MODECTL] = 0;
     +        gdb_exit(ret);
     +        exit(ret);
     +    }
    @@ target/hexagon/hexswi.c
     +    /* TODO: implement other hexagon-specific semihosting calls */
     +
     +    default:
    -+        qemu_log_mask(LOG_GUEST_ERROR,
    ++        qemu_log_mask(LOG_UNIMP,
     +                      "unknown swi request: 0x%" PRIx32 "\n",
     +                      (uint32_t)what_swi);
     +        common_semi_cb(cs, -1, ENOSYS);
    @@ target/hexagon/hexswi.c: void hexagon_cpu_do_interrupt(CPUState *cs)
     
      ## target/hexagon/meson.build ##
     @@ target/hexagon/meson.build: hexagon_softmmu_ss.add(files(
    +     'hex_interrupts.c',
    +     'hexswi.c',
          'machine.c',
    ++    'common-semi-target.c',
      ))
      
    -+hexagon_softmmu_ss.add(when: 'CONFIG_ARM_COMPATIBLE_SEMIHOSTING',
    -+                       if_true: files('common-semi-target.c'))
    -+
      #
    - # Step 4.5
    - # We use flex/bison based idef-parser to generate TCG code for a lot
 8:  35d0c39f75 =  9:  2b36fa4993 semihosting: add ftruncate helper (to be used 
for hexagon)
 9:  924d0069ad ! 10:  dde7923648 target/hexagon: add main arch-specific 
semihosting operations
    @@ target/hexagon/hexswi.c: static void sim_handle_trap0(CPUHexagonState 
*env)
     +            err = errno;
     +        }
     +        if (rc == 0) {
    -+            sys_stat.dev   = st_buf.st_dev;
    -+            sys_stat.ino   = st_buf.st_ino;
    -+            sys_stat.mode  = st_buf.st_mode;
    -+            sys_stat.nlink = (uint32_t) st_buf.st_nlink;
    -+            sys_stat.rdev  = st_buf.st_rdev;
    -+            sys_stat.size  = (uint32_t) st_buf.st_size;
    -+#if defined(__linux__)
    -+            sys_stat.atime = (uint32_t) st_buf.st_atim.tv_sec;
    -+            sys_stat.mtime = (uint32_t) st_buf.st_mtim.tv_sec;
    -+            sys_stat.ctime = (uint32_t) st_buf.st_ctim.tv_sec;
    -+#elif defined(_WIN32)
    -+            sys_stat.atime = st_buf.st_atime;
    -+            sys_stat.mtime = st_buf.st_mtime;
    -+            sys_stat.ctime = st_buf.st_ctime;
    -+#endif
    ++            sys_stat.dev   = cpu_to_le64(st_buf.st_dev);
    ++            sys_stat.ino   = cpu_to_le64(st_buf.st_ino);
    ++            sys_stat.mode  = cpu_to_le32(st_buf.st_mode);
    ++            sys_stat.nlink = cpu_to_le32((uint32_t) st_buf.st_nlink);
    ++            sys_stat.rdev  = cpu_to_le64(st_buf.st_rdev);
    ++            sys_stat.size  = cpu_to_le32((uint32_t) st_buf.st_size);
    ++            sys_stat.atime = cpu_to_le32(st_buf.st_atime);
    ++            sys_stat.mtime = cpu_to_le32(st_buf.st_mtime);
    ++            sys_stat.ctime = cpu_to_le32(st_buf.st_ctime);
     +        }
     +        hexagon_read_memory(env, swi_info + 4, 4, &statBufferAddr, 
retaddr);
     +
    @@ target/hexagon/hexswi.c: static void sim_handle_trap0(CPUHexagonState 
*env)
     +    case HEX_SYS_READ_TCYCLES:
     +    case HEX_SYS_READ_ICOUNT:
     +    {
    -+        arch_set_thread_reg(env, HEX_REG_R00, 0);
    -+        arch_set_thread_reg(env, HEX_REG_R01, 0);
    ++        env->gpr[HEX_REG_R00] = 0;
    ++        env->gpr[HEX_REG_R01] = 0;
     +        break;
     +    }
     +
     +    case HEX_SYS_READ_PCYCLES:
     +    {
    -+        arch_set_thread_reg(env, HEX_REG_R00,
    -+            arch_get_system_reg(env, HEX_SREG_PCYCLELO));
    -+        arch_set_thread_reg(env, HEX_REG_R01,
    -+            arch_get_system_reg(env, HEX_SREG_PCYCLEHI));
    ++        env->gpr[HEX_REG_R00] = hexagon_get_sys_pcycle_count_low(env);
    ++        env->gpr[HEX_REG_R01] = hexagon_get_sys_pcycle_count_high(env);
     +        break;
     +    }
     +
    @@ target/hexagon/hexswi.c: static void sim_handle_trap0(CPUHexagonState 
*env)
     +        break;
      
          default:
    -         qemu_log_mask(LOG_GUEST_ERROR,
    +         qemu_log_mask(LOG_UNIMP,
10:  a81c46b955 ! 11:  0664a4a5a9 target/hexagon: add COREDUMP semihosting 
operation
    @@ target/hexagon/hexswi.c: static void common_semi_ftell_cb(CPUState *cs, 
uint64_t
      
     +static void coredump(CPUHexagonState *env)
     +{
    -+    uint32_t ssr = arch_get_system_reg(env, HEX_SREG_SSR);
    ++    uint32_t ssr = env->t_sreg[HEX_SREG_SSR];
     +    FILE *f = qemu_log_trylock();
     +
     +    if (!f) {
    @@ target/hexagon/hexswi.c: static void common_semi_ftell_cb(CPUState *cs, 
uint64_t
     +        break;
     +    case HEX_CAUSE_MISALIGNED_LOAD:
     +        fprintf(f, "0x%x, Misaligned Load @ 0x%" PRIx32,
    -+                HEX_CAUSE_MISALIGNED_LOAD,
    -+                arch_get_system_reg(env, HEX_SREG_BADVA));
    ++                HEX_CAUSE_MISALIGNED_LOAD, env->t_sreg[HEX_SREG_BADVA]);
     +        break;
     +    case HEX_CAUSE_MISALIGNED_STORE:
     +        fprintf(f, "0x%x, Misaligned Store @ 0x%" PRIx32,
    -+                HEX_CAUSE_MISALIGNED_STORE,
    -+                arch_get_system_reg(env, HEX_SREG_BADVA));
    ++                HEX_CAUSE_MISALIGNED_STORE, env->t_sreg[HEX_SREG_BADVA]);
     +        break;
     +    case HEX_CAUSE_PRIV_NO_READ:
     +        fprintf(f, "0x%x, Privilege violation: "
     +                "user/guest read permission @ 0x%" PRIx32,
    -+                HEX_CAUSE_PRIV_NO_READ,
    -+                arch_get_system_reg(env, HEX_SREG_BADVA));
    ++                HEX_CAUSE_PRIV_NO_READ, env->t_sreg[HEX_SREG_BADVA]);
     +        break;
     +    case HEX_CAUSE_PRIV_NO_WRITE:
     +        fprintf(f, "0x%x, Privilege violation: "
     +                "user/guest write permission @ 0x%" PRIx32,
    -+                HEX_CAUSE_PRIV_NO_WRITE,
    -+                arch_get_system_reg(env, HEX_SREG_BADVA));
    ++                HEX_CAUSE_PRIV_NO_WRITE, env->t_sreg[HEX_SREG_BADVA]);
     +        break;
     +    case HEX_CAUSE_PRIV_NO_UREAD:
     +        fprintf(f, "0x%x, Privilege violation:"
     +                " user read permission @ 0x%" PRIx32,
    -+                HEX_CAUSE_PRIV_NO_UREAD,
    -+                arch_get_system_reg(env, HEX_SREG_BADVA));
    ++                HEX_CAUSE_PRIV_NO_UREAD, env->t_sreg[HEX_SREG_BADVA]);
     +        break;
     +    case HEX_CAUSE_PRIV_NO_UWRITE:
     +        fprintf(f, "0x%x, Privilege violation:"
     +                " user write permission @ 0x%" PRIx32,
    -+                HEX_CAUSE_PRIV_NO_UWRITE,
    -+                arch_get_system_reg(env, HEX_SREG_BADVA));
    ++                HEX_CAUSE_PRIV_NO_UWRITE, env->t_sreg[HEX_SREG_BADVA]);
     +        break;
     +    case HEX_CAUSE_COPROC_LDST:
     +        fprintf(f, "0x%x, Coprocessor VMEM address error @ 0x%" PRIx32,
    -+                HEX_CAUSE_COPROC_LDST,
    -+                arch_get_system_reg(env, HEX_SREG_BADVA));
    ++                HEX_CAUSE_COPROC_LDST, env->t_sreg[HEX_SREG_BADVA]);
     +        break;
     +    case HEX_CAUSE_STACK_LIMIT:
     +        fprintf(f, "0x%x, Stack limit check error",
11:  289e5cb2d9 ! 12:  71b686df7f target/hexagon: Add an errno mapping
    @@ target/hexagon/hexswi.c: static void do_preload(CPUHexagonState *env, 
target_ulo
      }
      
     +/* Hexagon semihosting errno values */
    -+#define HEX_EINVAL          22
    -+#define HEX_ERRNOS \
    -+    HEX_ERRNO(EPERM,        1) \
    -+    HEX_ERRNO(ENOENT,       2) \
    -+    HEX_ERRNO(EINTR,        4) \
    -+    HEX_ERRNO(EIO,          5) \
    -+    HEX_ERRNO(ENXIO,        6) \
    -+    HEX_ERRNO(EBADF,        9) \
    -+    HEX_ERRNO(EAGAIN,       11) \
    -+    HEX_ERRNO(ENOMEM,       12) \
    -+    HEX_ERRNO(EACCES,       13) \
    -+    HEX_ERRNO(EFAULT,       14) \
    -+    HEX_ERRNO(EBUSY,        16) \
    -+    HEX_ERRNO(EEXIST,       17) \
    -+    HEX_ERRNO(EXDEV,        18) \
    -+    HEX_ERRNO(ENODEV,       19) \
    -+    HEX_ERRNO(ENOTDIR,      20) \
    -+    HEX_ERRNO(EISDIR,       21) \
    -+    HEX_ERRNO(EINVAL,       HEX_EINVAL) \
    -+    HEX_ERRNO(ENFILE,       23) \
    -+    HEX_ERRNO(EMFILE,       24) \
    -+    HEX_ERRNO(ENOTTY,       25) \
    -+    HEX_ERRNO(ETXTBSY,      26) \
    -+    HEX_ERRNO(EFBIG,        27) \
    -+    HEX_ERRNO(ENOSPC,       28) \
    -+    HEX_ERRNO(ESPIPE,       29) \
    -+    HEX_ERRNO(EROFS,        30) \
    -+    HEX_ERRNO(EMLINK,       31) \
    -+    HEX_ERRNO(EPIPE,        32) \
    -+    HEX_ERRNO(ERANGE,       34) \
    -+    HEX_ERRNO(ENAMETOOLONG, 36) \
    -+    HEX_ERRNO(ENOSYS,       38) \
    -+    HEX_ERRNO(ELOOP,        40) \
    -+    HEX_ERRNO(EOVERFLOW,    75)
    ++enum {
    ++    TARGET_EPERM        =  1,
    ++    TARGET_ENOENT       =  2,
    ++    TARGET_EINTR        =  4,
    ++    TARGET_EIO          =  5,
    ++    TARGET_ENXIO        =  6,
    ++    TARGET_EBADF        =  9,
    ++    TARGET_EAGAIN       = 11,
    ++    TARGET_ENOMEM       = 12,
    ++    TARGET_EACCES       = 13,
    ++    TARGET_EFAULT       = 14,
    ++    TARGET_EBUSY        = 16,
    ++    TARGET_EEXIST       = 17,
    ++    TARGET_EXDEV        = 18,
    ++    TARGET_ENODEV       = 19,
    ++    TARGET_ENOTDIR      = 20,
    ++    TARGET_EISDIR       = 21,
    ++    TARGET_EINVAL       = 22,
    ++    TARGET_ENFILE       = 23,
    ++    TARGET_EMFILE       = 24,
    ++    TARGET_ENOTTY       = 25,
    ++    TARGET_ETXTBSY      = 26,
    ++    TARGET_EFBIG        = 27,
    ++    TARGET_ENOSPC       = 28,
    ++    TARGET_ESPIPE       = 29,
    ++    TARGET_EROFS        = 30,
    ++    TARGET_EMLINK       = 31,
    ++    TARGET_EPIPE        = 32,
    ++    TARGET_ERANGE       = 34,
    ++    TARGET_ENAMETOOLONG = 36,
    ++    TARGET_ENOSYS       = 38,
    ++    TARGET_ELOOP        = 40,
    ++    TARGET_EOVERFLOW    = 75,
    ++};
     +
     +/* Map host errno to hexagon semihosting errno */
    ++static uint32_t errno_h2g(uint32_t err) {
    ++    switch (err) {
    ++    case 0:            return 0;
    ++    case EPERM:        return TARGET_EPERM;
    ++    case ENOENT:       return TARGET_ENOENT;
    ++    case EINTR:        return TARGET_EINTR;
    ++    case EIO:          return TARGET_EIO;
    ++    case ENXIO:        return TARGET_ENXIO;
    ++    case EBADF:        return TARGET_EBADF;
    ++    case EAGAIN:       return TARGET_EAGAIN;
    ++    case ENOMEM:       return TARGET_ENOMEM;
    ++    case EACCES:       return TARGET_EACCES;
    ++    case EFAULT:       return TARGET_EFAULT;
    ++    case EBUSY:        return TARGET_EBUSY;
    ++    case EEXIST:       return TARGET_EEXIST;
    ++    case EXDEV:        return TARGET_EXDEV;
    ++    case ENODEV:       return TARGET_ENODEV;
    ++    case ENOTDIR:      return TARGET_ENOTDIR;
    ++    case EISDIR:       return TARGET_EISDIR;
    ++    case EINVAL:       return TARGET_EINVAL;
    ++    case ENFILE:       return TARGET_ENFILE;
    ++    case EMFILE:       return TARGET_EMFILE;
    ++    case ENOTTY:       return TARGET_ENOTTY;
    ++    case ETXTBSY:      return TARGET_ETXTBSY;
    ++    case EFBIG:        return TARGET_EFBIG;
    ++    case ENOSPC:       return TARGET_ENOSPC;
    ++    case ESPIPE:       return TARGET_ESPIPE;
    ++    case EROFS:        return TARGET_EROFS;
    ++    case EMLINK:       return TARGET_EMLINK;
    ++    case EPIPE:        return TARGET_EPIPE;
    ++    case ERANGE:       return TARGET_ERANGE;
    ++    case ENAMETOOLONG: return TARGET_ENAMETOOLONG;
    ++    case ENOSYS:       return TARGET_ENOSYS;
    ++    case ELOOP:        return TARGET_ELOOP;
    ++    case EOVERFLOW:    return TARGET_EOVERFLOW;
    ++    }
    ++    return TARGET_EINVAL;
    ++}
    ++
     +static void semi_cb(CPUState *cs, uint64_t ret, int err)
     +{
    -+#define HEX_ERRNO(NAME, CODE) case NAME: err = CODE; break;
    -+    switch (err) {
    -+    case 0:
    -+        break;
    -+    HEX_ERRNOS
    -+    default:
    -+        err = HEX_EINVAL;
    -+        break;
    -+    }
    -+    common_semi_cb(cs, ret, err);
    ++    common_semi_cb(cs, ret, errno_h2g(err));
     +}
     +
      static void common_semi_ftell_cb(CPUState *cs, uint64_t ret, int err)
    @@ target/hexagon/hexswi.c: static void sim_handle_trap0(CPUHexagonState 
*env)
                            "SWI call %" PRIx32
                            " is unimplemented in QEMU\n",
     @@ target/hexagon/hexswi.c: static void sim_handle_trap0(CPUHexagonState 
*env)
    -         qemu_log_mask(LOG_GUEST_ERROR,
    +         qemu_log_mask(LOG_UNIMP,
                            "unknown swi request: 0x%" PRIx32 "\n",
                            (uint32_t)what_swi);
     -        common_semi_cb(cs, -1, ENOSYS);
12:  61d0585371 = 13:  abcd31dac2 python/machine: support routing semihosting 
output to the test console
13:  12b2448ce3 ! 14:  0aab35393d tests/functional: Add hexagon semihosting 
systests
    @@ tests/functional/hexagon/test_systests.py (new)
     +        self.archive_extract(self.ASSET_TARBALL)
     +
     +    def binary(self, name):
    -+        """Return the full path to binary *name* inside bin dir."""
     +        path = self.scratch_file(*_TARBALL_BIN_PATH, name)
     +        self.assertTrue(os.path.exists(path))
     +        return path
     +
     +    def run_exit_zero(self, binary_name, *extra_args, 
machine="V66G_1024"):
    -+        """Launch *binary_name* and assert it exits with code 0.
    -+
    -+        :param binary_name: name of the binary inside bin dir.
    -+        :param extra_args: optional pairs of (flag, value) strings passed
    -+            to set_vm_arg(), e.g. ('-append', 'myarg').
    -+        :param machine: QEMU machine type (default "V66G_1024").
    -+        """
     +        self.set_machine(machine)
     +        self.set_vm_arg("-display", "none")
     +        self.set_vm_arg("-kernel", self.binary(binary_name))
    @@ tests/functional/hexagon/test_systests.py (new)
     +
     +    def run_console_pattern(self, binary_name, pattern, *extra_args,
     +                            machine="V66G_1024"):
    -+        """Launch *binary_name* and wait for *pattern* on the semihosting 
console.
    -+
    -+        :param binary_name: name of the binary inside bin dir.
    -+        :param pattern: string pattern to wait for via 
wait_for_console_pattern.
    -+        :param extra_args: optional pairs of (flag, value) strings passed
    -+            to set_vm_arg(), e.g. ('-append', 'myarg').
    -+        :param machine: QEMU machine type (default "V66G_1024").
    -+        """
     +        self.set_machine(machine)
     +        self.set_vm_arg("-display", "none")
     +        self.set_vm_arg("-kernel", self.binary(binary_name))
-- 
2.37.2


Reply via email to