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 | 75 ++++++++++++++++++++++++++++++++++-------
 1 file changed, 63 insertions(+), 12 deletions(-)

diff --git a/target/hexagon/hexswi.c b/target/hexagon/hexswi.c
index 564a11e557a..d93789e39c7 100644
--- a/target/hexagon/hexswi.c
+++ b/target/hexagon/hexswi.c
@@ -154,12 +154,63 @@ static void do_preload(CPUHexagonState *env, target_ulong 
swi_info, bool load)
     hexagon_peek_memory_range(env, addr, count, retaddr);
 }
 
+/* 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)
+
+/* Map host errno to hexagon semihosting errno */
+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);
+}
+
 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)
@@ -378,7 +429,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;
         }
 
@@ -395,7 +446,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;
         }
 
@@ -414,7 +465,7 @@ static void sim_handle_trap0(CPUHexagonState *env)
                 ret = guestfd;
             }
         }
-        common_semi_cb(cs, ret, err);
+        semi_cb(cs, ret, err);
     }
     break;
 
@@ -433,7 +484,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;
 
@@ -503,7 +554,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;
 
@@ -513,7 +564,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;
 
@@ -537,7 +588,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;
 
@@ -565,14 +616,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;
 
@@ -611,7 +662,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",
@@ -622,7 +673,7 @@ static void sim_handle_trap0(CPUHexagonState *env)
         qemu_log_mask(LOG_GUEST_ERROR,
                       "unknown swi request: 0x%" PRIx32 "\n",
                       (uint32_t)what_swi);
-        common_semi_cb(cs, -1, ENOSYS);
+        semi_cb(cs, -1, ENOSYS);
     }
 }
 
-- 
2.37.2


Reply via email to