From: Brian Cain <[email protected]> The Hexagon semihosting ABI defines its own errno values which may differ from the host's. Translate host errno to the Hexagon-specific values before returning results to the guest so that baremetal programs see the expected error codes.
Signed-off-by: Brian Cain <[email protected]> Reviewed-by: Pierrick Bouvier <[email protected]> Signed-off-by: Matheus Tavares Bernardino <[email protected]> --- target/hexagon/hexswi.c | 105 +++++++++++++++++++++++++++++++++++----- 1 file changed, 93 insertions(+), 12 deletions(-) diff --git a/target/hexagon/hexswi.c b/target/hexagon/hexswi.c index 5e7f655a41..a50ab22554 100644 --- a/target/hexagon/hexswi.c +++ b/target/hexagon/hexswi.c @@ -154,12 +154,93 @@ static void do_preload(CPUHexagonState *env, target_ulong swi_info, bool load) hexagon_peek_memory_range(env, addr, count, retaddr); } +/* Hexagon semihosting errno values */ +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) +{ + common_semi_cb(cs, ret, errno_h2g(err)); +} + static void common_semi_ftell_cb(CPUState *cs, uint64_t ret, int err) { if (err) { ret = -1; } - common_semi_cb(cs, ret, err); + semi_cb(cs, ret, err); } static void coredump(CPUHexagonState *env) @@ -371,7 +452,7 @@ static void sim_handle_trap0(CPUHexagonState *env) qemu_log_mask(LOG_GUEST_ERROR, "%s: filename too large (%d)\n", __func__, length); - common_semi_cb(cs, -1, ENAMETOOLONG); + semi_cb(cs, -1, ENAMETOOLONG); break; } @@ -388,7 +469,7 @@ static void sim_handle_trap0(CPUHexagonState *env) qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid OPEN mode: %u\n", __func__, filemode); - common_semi_cb(cs, -1, EINVAL); + semi_cb(cs, -1, EINVAL); break; } @@ -407,7 +488,7 @@ static void sim_handle_trap0(CPUHexagonState *env) ret = guestfd; } } - common_semi_cb(cs, ret, err); + semi_cb(cs, ret, err); } break; @@ -426,7 +507,7 @@ static void sim_handle_trap0(CPUHexagonState *env) { int fd; hexagon_read_memory(env, swi_info, 4, &fd, retaddr); - common_semi_cb(cs, isatty(fd), 0); + semi_cb(cs, isatty(fd), 0); } break; @@ -490,7 +571,7 @@ static void sim_handle_trap0(CPUHexagonState *env) hexagon_write_memory(env, statBufferAddr + i, 1, st_bufptr[i], retaddr); } - common_semi_cb(cs, rc, rc == 0 ? 0 : err); + semi_cb(cs, rc, rc == 0 ? 0 : err); } break; @@ -500,7 +581,7 @@ static void sim_handle_trap0(CPUHexagonState *env) off_t size_limit; hexagon_read_memory(env, swi_info, 4, &fd, retaddr); hexagon_read_memory(env, swi_info + 4, 8, &size_limit, retaddr); - semihost_sys_ftruncate(cs, common_semi_cb, fd, size_limit); + semihost_sys_ftruncate(cs, semi_cb, fd, size_limit); } break; @@ -524,7 +605,7 @@ static void sim_handle_trap0(CPUHexagonState *env) hexagon_read_memory(env, swi_info + 4, 4, &BufferMode, retaddr); rc = access(filename, BufferMode); - common_semi_cb(cs, rc, rc == 0 ? 0 : errno); + semi_cb(cs, rc, rc == 0 ? 0 : errno); } break; @@ -552,14 +633,14 @@ static void sim_handle_trap0(CPUHexagonState *env) rc = BufferAddr; } } - common_semi_cb(cs, rc, rc != 0 ? 0 : err); + semi_cb(cs, rc, rc != 0 ? 0 : err); break; } case HEX_SYS_EXEC: { qemu_log_mask(LOG_UNIMP, "SYS_EXEC is deprecated\n"); - common_semi_cb(cs, -1, ENOSYS); + semi_cb(cs, -1, ENOSYS); } break; @@ -596,7 +677,7 @@ static void sim_handle_trap0(CPUHexagonState *env) case HEX_SYS_PROF_STATSRESET: case HEX_SYS_DUMP_PMU_STATS: case HEX_SYS_HEAPINFO: - common_semi_cb(cs, -1, ENOSYS); + semi_cb(cs, -1, ENOSYS); qemu_log_mask(LOG_UNIMP, "SWI call %" PRIx32 " is unimplemented in QEMU\n", @@ -607,7 +688,7 @@ static void sim_handle_trap0(CPUHexagonState *env) qemu_log_mask(LOG_UNIMP, "unknown swi request: 0x%" PRIx32 "\n", (uint32_t)what_swi); - common_semi_cb(cs, -1, ENOSYS); + semi_cb(cs, -1, ENOSYS); } } -- 2.37.2
