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
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/cover.1783973054.git.matheus.bernardino@oss.qualcomm.com/
v2: https://lore.kernel.org/qemu-devel/3cd3a419-ee2c-4d7a-9396-60eab8d26908@oss.qualcomm.com/T/#m9e966877cda81c5661838fedadf4e69bd912cbb5
v3: https://lore.kernel.org/qemu-devel/cover.1784568922.git.matheus.bernardino@oss.qualcomm.com/
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 <pierrick.bouvier@oss.qualcomm.com>
Signed-off-by: Matheus Tavares Bernardino <matheus.bernardino@oss.qualcomm.com>
+ ## 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
© 2016 - 2026 Red Hat, Inc.