All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 0/5] target-mips: add UHI semihosting support
@ 2015-05-12 22:01 Leon Alrae
  2015-05-12 22:01 ` [Qemu-devel] [PATCH v2 1/5] include/softmmu-semi.h: Make semihosting support 64-bit clean Leon Alrae
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Leon Alrae @ 2015-05-12 22:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: matthew.fortune, aurelien

Hi,

This patch series introduces the Unified Hosting Interface support to QEMU.

This is second version which uses new -semihosting-config arg and addresses
Matthew's review comments.

Regards,
Leon

v2:
* use new -semihosting arg option, thus it applies on top of
  https://lists.gnu.org/archive/html/qemu-devel/2015-05/msg01417.html
* if semihosting args are not present, then fall back to old-style
  -kernel/-append
* clean up SDBBP and remove identical code in different branch
* fix overlooked microMIPS SDBBP
* translate errno values which don't map 1:1
* update dates in the licence header
* return -1 and fake errno when lock_user() fails in write_to_file() and
  read_from_file()

Leon Alrae (3):
  target-mips: remove identical code in different branch
  target-mips: add Unified Hosting Interface (UHI) support
  target-mips: convert host to MIPS errno values when required

Maciej W. Rozycki (1):
  include/softmmu-semi.h: Make semihosting support 64-bit clean

Matthew Fortune (1):
  hw/mips: Do not clear BEV for MIPS malta kernel load

 hw/mips/mips_malta.c        |  11 +-
 include/exec/softmmu-semi.h |  13 +-
 qemu-options.hx             |  10 +-
 target-mips/Makefile.objs   |   2 +-
 target-mips/helper.h        |   2 +
 target-mips/mips-semi.c     | 358 ++++++++++++++++++++++++++++++++++++++++++++
 target-mips/translate.c     |  70 +++++----
 7 files changed, 428 insertions(+), 38 deletions(-)
 create mode 100644 target-mips/mips-semi.c

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH v2 1/5] include/softmmu-semi.h: Make semihosting support 64-bit clean
  2015-05-12 22:01 [Qemu-devel] [PATCH v2 0/5] target-mips: add UHI semihosting support Leon Alrae
@ 2015-05-12 22:01 ` Leon Alrae
  2015-05-12 22:01 ` [Qemu-devel] [PATCH v2 2/5] hw/mips: Do not clear BEV for MIPS malta kernel load Leon Alrae
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Leon Alrae @ 2015-05-12 22:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: Maciej W. Rozycki, matthew.fortune, aurelien

From: "Maciej W. Rozycki" <macro@codesourcery.com>

Correct addresses passed around in semihosting to use a data type suitable
for both 32-bit and 64-bit targets.

Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
 include/exec/softmmu-semi.h | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/include/exec/softmmu-semi.h b/include/exec/softmmu-semi.h
index 8401f7d..1819cc2 100644
--- a/include/exec/softmmu-semi.h
+++ b/include/exec/softmmu-semi.h
@@ -9,14 +9,14 @@
 #ifndef SOFTMMU_SEMI_H
 #define SOFTMMU_SEMI_H 1
 
-static inline uint32_t softmmu_tget32(CPUArchState *env, uint32_t addr)
+static inline uint32_t softmmu_tget32(CPUArchState *env, target_ulong addr)
 {
     uint32_t val;
 
     cpu_memory_rw_debug(ENV_GET_CPU(env), addr, (uint8_t *)&val, 4, 0);
     return tswap32(val);
 }
-static inline uint32_t softmmu_tget8(CPUArchState *env, uint32_t addr)
+static inline uint32_t softmmu_tget8(CPUArchState *env, target_ulong addr)
 {
     uint8_t val;
 
@@ -28,7 +28,8 @@ static inline uint32_t softmmu_tget8(CPUArchState *env, uint32_t addr)
 #define get_user_u8(arg, p) ({ arg = softmmu_tget8(env, p) ; 0; })
 #define get_user_ual(arg, p) get_user_u32(arg, p)
 
-static inline void softmmu_tput32(CPUArchState *env, uint32_t addr, uint32_t val)
+static inline void softmmu_tput32(CPUArchState *env,
+                                  target_ulong addr, uint32_t val)
 {
     val = tswap32(val);
     cpu_memory_rw_debug(ENV_GET_CPU(env), addr, (uint8_t *)&val, 4, 1);
@@ -36,8 +37,8 @@ static inline void softmmu_tput32(CPUArchState *env, uint32_t addr, uint32_t val
 #define put_user_u32(arg, p) ({ softmmu_tput32(env, p, arg) ; 0; })
 #define put_user_ual(arg, p) put_user_u32(arg, p)
 
-static void *softmmu_lock_user(CPUArchState *env, uint32_t addr, uint32_t len,
-                               int copy)
+static void *softmmu_lock_user(CPUArchState *env,
+                               target_ulong addr, target_ulong len, int copy)
 {
     uint8_t *p;
     /* TODO: Make this something that isn't fixed size.  */
@@ -48,7 +49,7 @@ static void *softmmu_lock_user(CPUArchState *env, uint32_t addr, uint32_t len,
     return p;
 }
 #define lock_user(type, p, len, copy) softmmu_lock_user(env, p, len, copy)
-static char *softmmu_lock_user_string(CPUArchState *env, uint32_t addr)
+static char *softmmu_lock_user_string(CPUArchState *env, target_ulong addr)
 {
     char *p;
     char *s;

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH v2 2/5] hw/mips: Do not clear BEV for MIPS malta kernel load
  2015-05-12 22:01 [Qemu-devel] [PATCH v2 0/5] target-mips: add UHI semihosting support Leon Alrae
  2015-05-12 22:01 ` [Qemu-devel] [PATCH v2 1/5] include/softmmu-semi.h: Make semihosting support 64-bit clean Leon Alrae
@ 2015-05-12 22:01 ` Leon Alrae
  2015-05-12 22:01 ` [Qemu-devel] [PATCH v2 3/5] target-mips: remove identical code in different branch Leon Alrae
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Leon Alrae @ 2015-05-12 22:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: matthew.fortune, aurelien

From: Matthew Fortune <matthew.fortune@imgtec.com>

The BEV flag controls whether the boot exception vector is still
in place when starting a kernel.  When cleared the exception vector
at EBASE (or hard coded address of 0x80000000) is used instead.

The early stages of the linux kernel would benefit from BEV still
being set to ensure any faults get handled by the boot rom exception
handlers.  This is a moot point for system qemu as there aren't really
any BEV handlers, but there are other good reasons to change this...

The UHI (semi-hosting interface) defines special behaviours depending
on whether an application starts in an environment with BEV set or
cleared. When BEV is set then UHI assumes that a bootloader is
relatively dumb and has no advanced exception handling logic.
However, when BEV is cleared then UHI assumes that the bootloader
has the ability to handle UHI exceptions with its exception handlers
and will unwind and forward UHI SYSCALL exceptions to the exception
vector that was installed prior to running the application.

Signed-off-by: Matthew Fortune <matthew.fortune@imgtec.com>
Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
 hw/mips/mips_malta.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index d3f2cd3..e1b2e20 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -885,7 +885,7 @@ static void main_cpu_reset(void *opaque)
        read only location. The kernel location and the arguments table
        location does not change. */
     if (loaderparams.kernel_filename) {
-        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
+        env->CP0_Status &= ~(1 << CP0St_ERL);
     }
 
     malta_mips_config(cpu);

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH v2 3/5] target-mips: remove identical code in different branch
  2015-05-12 22:01 [Qemu-devel] [PATCH v2 0/5] target-mips: add UHI semihosting support Leon Alrae
  2015-05-12 22:01 ` [Qemu-devel] [PATCH v2 1/5] include/softmmu-semi.h: Make semihosting support 64-bit clean Leon Alrae
  2015-05-12 22:01 ` [Qemu-devel] [PATCH v2 2/5] hw/mips: Do not clear BEV for MIPS malta kernel load Leon Alrae
@ 2015-05-12 22:01 ` Leon Alrae
  2015-05-12 22:01 ` [Qemu-devel] [PATCH v2 4/5] target-mips: add Unified Hosting Interface (UHI) support Leon Alrae
  2015-05-12 22:01 ` [Qemu-devel] [PATCH v2 5/5] target-mips: convert host to MIPS errno values when required Leon Alrae
  4 siblings, 0 replies; 6+ messages in thread
From: Leon Alrae @ 2015-05-12 22:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: matthew.fortune, aurelien

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
 target-mips/translate.c | 25 ++++---------------------
 1 file changed, 4 insertions(+), 21 deletions(-)

diff --git a/target-mips/translate.c b/target-mips/translate.c
index a41fc98..94f17a9 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -11800,11 +11800,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
              *      when in debug mode...
              */
             check_insn(ctx, ISA_MIPS32);
-            if (!(ctx->hflags & MIPS_HFLAG_DM)) {
-                generate_exception(ctx, EXCP_DBp);
-            } else {
-                generate_exception(ctx, EXCP_DBp);
-            }
+            generate_exception(ctx, EXCP_DBp);
             break;
         case RR_SLT:
             gen_slt(ctx, OPC_SLT, 24, rx, ry);
@@ -12655,11 +12651,7 @@ static void gen_pool16c_insn(DisasContext *ctx)
          *      when in debug mode...
          */
         check_insn(ctx, ISA_MIPS32);
-        if (!(ctx->hflags & MIPS_HFLAG_DM)) {
-            generate_exception(ctx, EXCP_DBp);
-        } else {
-            generate_exception(ctx, EXCP_DBp);
-        }
+        generate_exception(ctx, EXCP_DBp);
         break;
     case JRADDIUSP + 0:
     case JRADDIUSP + 1:
@@ -13024,11 +13016,7 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
             break;
         case SDBBP:
             check_insn(ctx, ISA_MIPS32);
-            if (!(ctx->hflags & MIPS_HFLAG_DM)) {
-                generate_exception(ctx, EXCP_DBp);
-            } else {
-                generate_exception(ctx, EXCP_DBp);
-            }
+            generate_exception(ctx, EXCP_DBp);
             break;
         default:
             goto pool32axf_invalid;
@@ -16797,12 +16785,7 @@ static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
          *      when in debug mode...
          */
         check_insn(ctx, ISA_MIPS32);
-        if (!(ctx->hflags & MIPS_HFLAG_DM)) {
-            generate_exception(ctx, EXCP_DBp);
-        } else {
-            generate_exception(ctx, EXCP_DBp);
-        }
-        /* Treat as NOP. */
+        generate_exception(ctx, EXCP_DBp);
         break;
 #if defined(TARGET_MIPS64)
     case OPC_DCLO:

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH v2 4/5] target-mips: add Unified Hosting Interface (UHI) support
  2015-05-12 22:01 [Qemu-devel] [PATCH v2 0/5] target-mips: add UHI semihosting support Leon Alrae
                   ` (2 preceding siblings ...)
  2015-05-12 22:01 ` [Qemu-devel] [PATCH v2 3/5] target-mips: remove identical code in different branch Leon Alrae
@ 2015-05-12 22:01 ` Leon Alrae
  2015-05-12 22:01 ` [Qemu-devel] [PATCH v2 5/5] target-mips: convert host to MIPS errno values when required Leon Alrae
  4 siblings, 0 replies; 6+ messages in thread
From: Leon Alrae @ 2015-05-12 22:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: matthew.fortune, aurelien

Add UHI semihosting support for MIPS. QEMU run with "-semihosting" option
will alter the behaviour of SDBBP 1 instruction -- UHI operation will be
called instead of generating a debug exception.

Also tweak Malta's pseudo-bootloader. On CPU reset the $4 register is set
to -1 if semihosting arguments are passed to indicate that the UHI
operations should be used to obtain input arguments.

Still support old-style -kernel/-append if -semihosting-config args have not
been specified.

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
 hw/mips/mips_malta.c      |   9 +-
 qemu-options.hx           |  10 +-
 target-mips/Makefile.objs |   2 +-
 target-mips/helper.h      |   2 +
 target-mips/mips-semi.c   | 336 ++++++++++++++++++++++++++++++++++++++++++++++
 target-mips/translate.c   |  77 ++++++++---
 6 files changed, 410 insertions(+), 26 deletions(-)
 create mode 100644 target-mips/mips-semi.c

diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index e1b2e20..425e7a0 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -53,6 +53,7 @@
 #include "qemu/error-report.h"
 #include "hw/empty_slot.h"
 #include "sysemu/kvm.h"
+#include "exec/semihost.h"
 
 //#define DEBUG_BOARD_INIT
 
@@ -634,7 +635,13 @@ static void write_bootloader (CPUMIPSState *env, uint8_t *base,
 
     /* Second part of the bootloader */
     p = (uint32_t *) (base + 0x580);
-    stl_p(p++, 0x24040002);                                      /* addiu a0, zero, 2 */
+
+    if (semihosting_get_argc()) {
+        /* Preserve a0 content as arguments have been passed */
+        stl_p(p++, 0x00000000);                         /* nop */
+    } else {
+        stl_p(p++, 0x24040002);                         /* addiu a0, zero, 2 */
+    }
     stl_p(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */
     stl_p(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff));        /* ori sp, sp, low(ENVP_ADDR) */
     stl_p(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
diff --git a/qemu-options.hx b/qemu-options.hx
index 84ae6c2..bb7cb7b 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3289,20 +3289,22 @@ Set OpenBIOS nvram @var{variable} to given @var{value} (PPC, SPARC only).
 ETEXI
 DEF("semihosting", 0, QEMU_OPTION_semihosting,
     "-semihosting    semihosting mode\n",
-    QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA | QEMU_ARCH_LM32)
+    QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA | QEMU_ARCH_LM32 |
+    QEMU_ARCH_MIPS)
 STEXI
 @item -semihosting
 @findex -semihosting
-Enable semihosting mode (ARM, M68K, Xtensa only).
+Enable semihosting mode (ARM, M68K, Xtensa, MIPS only).
 ETEXI
 DEF("semihosting-config", HAS_ARG, QEMU_OPTION_semihosting_config,
     "-semihosting-config [enable=on|off][,target=native|gdb|auto][,arg=str[,...]]\n" \
     "                semihosting configuration\n",
-QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA | QEMU_ARCH_LM32)
+QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA | QEMU_ARCH_LM32 |
+QEMU_ARCH_MIPS)
 STEXI
 @item -semihosting-config [enable=on|off][,target=native|gdb|auto][,arg=str[,...]]
 @findex -semihosting-config
-Enable and configure semihosting (ARM, M68K, Xtensa only).
+Enable and configure semihosting (ARM, M68K, Xtensa, MIPS only).
 @table @option
 @item target=@code{native|gdb|auto}
 Defines where the semihosting calls will be addressed, to QEMU (@code{native})
diff --git a/target-mips/Makefile.objs b/target-mips/Makefile.objs
index 108fd9b..bc5ed85 100644
--- a/target-mips/Makefile.objs
+++ b/target-mips/Makefile.objs
@@ -1,4 +1,4 @@
 obj-y += translate.o dsp_helper.o op_helper.o lmi_helper.o helper.o cpu.o
-obj-y += gdbstub.o msa_helper.o
+obj-y += gdbstub.o msa_helper.o mips-semi.o
 obj-$(CONFIG_SOFTMMU) += machine.o
 obj-$(CONFIG_KVM) += kvm.o
diff --git a/target-mips/helper.h b/target-mips/helper.h
index 3bd0b02..7c7582f 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -1,6 +1,8 @@
 DEF_HELPER_3(raise_exception_err, noreturn, env, i32, int)
 DEF_HELPER_2(raise_exception, noreturn, env, i32)
 
+DEF_HELPER_1(do_semihosting, void, env)
+
 #ifdef TARGET_MIPS64
 DEF_HELPER_4(sdl, void, env, tl, tl, int)
 DEF_HELPER_4(sdr, void, env, tl, tl, int)
diff --git a/target-mips/mips-semi.c b/target-mips/mips-semi.c
new file mode 100644
index 0000000..971bbff
--- /dev/null
+++ b/target-mips/mips-semi.c
@@ -0,0 +1,336 @@
+/*
+ * Unified Hosting Interface syscalls.
+ *
+ * Copyright (c) 2015 Imagination Technologies
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/stat.h>
+#include "cpu.h"
+#include "exec/helper-proto.h"
+#include "exec/softmmu-semi.h"
+#include "exec/semihost.h"
+
+typedef enum UHIOp {
+    UHI_exit = 1,
+    UHI_open = 2,
+    UHI_close = 3,
+    UHI_read = 4,
+    UHI_write = 5,
+    UHI_lseek = 6,
+    UHI_unlink = 7,
+    UHI_fstat = 8,
+    UHI_argc = 9,
+    UHI_argnlen = 10,
+    UHI_argn = 11,
+    UHI_plog = 13,
+    UHI_assert = 14,
+    UHI_pread = 19,
+    UHI_pwrite = 20,
+    UHI_link = 22
+} UHIOp;
+
+typedef struct UHIStat {
+    int16_t uhi_st_dev;
+    uint16_t uhi_st_ino;
+    uint32_t uhi_st_mode;
+    uint16_t uhi_st_nlink;
+    uint16_t uhi_st_uid;
+    uint16_t uhi_st_gid;
+    int16_t uhi_st_rdev;
+    uint64_t uhi_st_size;
+    uint64_t uhi_st_atime;
+    uint64_t uhi_st_spare1;
+    uint64_t uhi_st_mtime;
+    uint64_t uhi_st_spare2;
+    uint64_t uhi_st_ctime;
+    uint64_t uhi_st_spare3;
+    uint64_t uhi_st_blksize;
+    uint64_t uhi_st_blocks;
+    uint64_t uhi_st_spare4[2];
+} UHIStat;
+
+enum UHIOpenFlags {
+    UHIOpen_RDONLY = 0x0,
+    UHIOpen_WRONLY = 0x1,
+    UHIOpen_RDWR   = 0x2,
+    UHIOpen_APPEND = 0x8,
+    UHIOpen_CREAT  = 0x200,
+    UHIOpen_TRUNC  = 0x400,
+    UHIOpen_EXCL   = 0x800
+};
+
+static int copy_stat_to_target(CPUMIPSState *env, const struct stat *src,
+                               target_ulong vaddr)
+{
+    hwaddr len = sizeof(struct UHIStat);
+    UHIStat *dst = lock_user(VERIFY_WRITE, vaddr, len, 0);
+    if (!dst) {
+        return -1;
+        errno = EFAULT;
+    }
+
+    dst->uhi_st_dev = tswap16(src->st_dev);
+    dst->uhi_st_ino = tswap16(src->st_ino);
+    dst->uhi_st_mode = tswap32(src->st_mode);
+    dst->uhi_st_nlink = tswap16(src->st_nlink);
+    dst->uhi_st_uid = tswap16(src->st_uid);
+    dst->uhi_st_gid = tswap16(src->st_gid);
+    dst->uhi_st_rdev = tswap16(src->st_rdev);
+    dst->uhi_st_size = tswap64(src->st_size);
+    dst->uhi_st_atime = tswap64(src->st_atime);
+    dst->uhi_st_mtime = tswap64(src->st_mtime);
+    dst->uhi_st_ctime = tswap64(src->st_ctime);
+#ifdef _WIN32
+    dst->uhi_st_blksize = 0;
+    dst->uhi_st_blocks = 0;
+#else
+    dst->uhi_st_blksize = tswap64(src->st_blksize);
+    dst->uhi_st_blocks = tswap64(src->st_blocks);
+#endif
+    unlock_user(dst, vaddr, len);
+    return 0;
+}
+
+static int get_open_flags(target_ulong target_flags)
+{
+    int open_flags = 0;
+
+    if (target_flags & UHIOpen_RDWR) {
+        open_flags |= O_RDWR;
+    } else if (target_flags & UHIOpen_WRONLY) {
+        open_flags |= O_WRONLY;
+    } else {
+        open_flags |= O_RDONLY;
+    }
+
+    open_flags |= (target_flags & UHIOpen_APPEND) ? O_APPEND : 0;
+    open_flags |= (target_flags & UHIOpen_CREAT)  ? O_CREAT  : 0;
+    open_flags |= (target_flags & UHIOpen_TRUNC)  ? O_TRUNC  : 0;
+    open_flags |= (target_flags & UHIOpen_EXCL)   ? O_EXCL   : 0;
+
+    return open_flags;
+}
+
+static int write_to_file(CPUMIPSState *env, target_ulong fd, target_ulong vaddr,
+                         target_ulong len, target_ulong offset)
+{
+    int num_of_bytes;
+    void *dst = lock_user(VERIFY_READ, vaddr, len, 1);
+    if (!dst) {
+        return -1;
+        errno = EFAULT;
+    }
+
+    if (offset) {
+#ifdef _WIN32
+        num_of_bytes = 0;
+#else
+        num_of_bytes = pwrite(fd, dst, len, offset);
+#endif
+    } else {
+        num_of_bytes = write(fd, dst, len);
+    }
+
+    unlock_user(dst, vaddr, 0);
+    return num_of_bytes;
+}
+
+static int read_from_file(CPUMIPSState *env, target_ulong fd,
+                          target_ulong vaddr, target_ulong len,
+                          target_ulong offset)
+{
+    int num_of_bytes;
+    void *dst = lock_user(VERIFY_WRITE, vaddr, len, 0);
+    if (!dst) {
+        return -1;
+        errno = EFAULT;
+    }
+
+    if (offset) {
+#ifdef _WIN32
+        num_of_bytes = 0;
+#else
+        num_of_bytes = pread(fd, dst, len, offset);
+#endif
+    } else {
+        num_of_bytes = read(fd, dst, len);
+    }
+
+    unlock_user(dst, vaddr, len);
+    return num_of_bytes;
+}
+
+static int copy_argn_to_target(CPUMIPSState *env, int arg_num,
+                               target_ulong vaddr)
+{
+    int strsize = strlen(semihosting_get_arg(arg_num)) + 1;
+    char *dst = lock_user(VERIFY_WRITE, vaddr, strsize, 0);
+    if (!dst) {
+        return -1;
+    }
+
+    strcpy(dst, semihosting_get_arg(arg_num));
+
+    unlock_user(dst, vaddr, strsize);
+    return 0;
+}
+
+#define GET_TARGET_STRING(p, addr)              \
+    do {                                        \
+        p = lock_user_string(addr);             \
+        if (!p) {                               \
+            gpr[2] = -1;                        \
+            gpr[3] = EFAULT;                    \
+            goto uhi_done;                      \
+        }                                       \
+    } while (0)
+
+#define FREE_TARGET_STRING(p, gpr)              \
+    do {                                        \
+        unlock_user(p, gpr, 0);                 \
+    } while (0)
+
+void helper_do_semihosting(CPUMIPSState *env)
+{
+    target_ulong *gpr = env->active_tc.gpr;
+    const UHIOp op = gpr[25];
+    char *p, *p2;
+
+    switch (op) {
+    case UHI_exit:
+        qemu_log("UHI(%d): exit(%d)\n", op, (int)gpr[4]);
+        exit(gpr[4]);
+    case UHI_open:
+        GET_TARGET_STRING(p, gpr[4]);
+        if (!strcmp("/dev/stdin", p)) {
+            gpr[2] = 0;
+        } else if (!strcmp("/dev/stdout", p)) {
+            gpr[2] = 1;
+        } else if (!strcmp("/dev/stderr", p)) {
+            gpr[2] = 2;
+        } else {
+            gpr[2] = open(p, get_open_flags(gpr[5]), gpr[6]);
+            gpr[3] = errno;
+        }
+        FREE_TARGET_STRING(p, gpr[4]);
+        break;
+    case UHI_close:
+        if (gpr[4] < 3) {
+            /* ignore closing stdin/stdout/stderr */
+            gpr[2] = 0;
+            goto uhi_done;
+        }
+        gpr[2] = close(gpr[4]);
+        gpr[3] = errno;
+        break;
+    case UHI_read:
+        gpr[2] = read_from_file(env, gpr[4], gpr[5], gpr[6], 0);
+        gpr[3] = errno;
+        break;
+    case UHI_write:
+        gpr[2] = write_to_file(env, gpr[4], gpr[5], gpr[6], 0);
+        gpr[3] = errno;
+        break;
+    case UHI_lseek:
+        gpr[2] = lseek(gpr[4], gpr[5], gpr[6]);
+        gpr[3] = errno;
+        break;
+    case UHI_unlink:
+        GET_TARGET_STRING(p, gpr[4]);
+        gpr[2] = remove(p);
+        gpr[3] = errno;
+        FREE_TARGET_STRING(p, gpr[4]);
+        break;
+    case UHI_fstat:
+        {
+            struct stat sbuf;
+            memset(&sbuf, 0, sizeof(sbuf));
+            gpr[2] = fstat(gpr[4], &sbuf);
+            gpr[3] = errno;
+            if (gpr[2]) {
+                goto uhi_done;
+            }
+            gpr[2] = copy_stat_to_target(env, &sbuf, gpr[5]);
+            gpr[3] = errno;
+        }
+        break;
+    case UHI_argc:
+        gpr[2] = semihosting_get_argc();
+        break;
+    case UHI_argnlen:
+        if (gpr[4] >= semihosting_get_argc()) {
+            gpr[2] = -1;
+            goto uhi_done;
+        }
+        gpr[2] = strlen(semihosting_get_arg(gpr[4]));
+        break;
+    case UHI_argn:
+        if (gpr[4] >= semihosting_get_argc()) {
+            gpr[2] = -1;
+            goto uhi_done;
+        }
+        gpr[2] = copy_argn_to_target(env, gpr[4], gpr[5]);
+        break;
+    case UHI_plog:
+        GET_TARGET_STRING(p, gpr[4]);
+        p2 = strstr(p, "%d");
+        if (p2) {
+            int char_num = p2 - p;
+            char *buf = g_malloc(char_num + 1);
+            strncpy(buf, p, char_num);
+            buf[char_num] = '\0';
+            gpr[2] = printf("%s%d%s", buf, (int)gpr[5], p2 + 2);
+            g_free(buf);
+        } else {
+            gpr[2] = printf("%s", p);
+        }
+        FREE_TARGET_STRING(p, gpr[4]);
+        break;
+    case UHI_assert:
+        GET_TARGET_STRING(p, gpr[4]);
+        GET_TARGET_STRING(p2, gpr[5]);
+        printf("assertion '");
+        printf("\"%s\"", p);
+        printf("': file \"%s\", line %d\n", p2, (int)gpr[6]);
+        FREE_TARGET_STRING(p2, gpr[5]);
+        FREE_TARGET_STRING(p, gpr[4]);
+        abort();
+        break;
+    case UHI_pread:
+        gpr[2] = read_from_file(env, gpr[4], gpr[5], gpr[6], gpr[7]);
+        gpr[3] = errno;
+        break;
+    case UHI_pwrite:
+        gpr[2] = write_to_file(env, gpr[4], gpr[5], gpr[6], gpr[7]);
+        gpr[3] = errno;
+        break;
+#ifndef _WIN32
+    case UHI_link:
+        GET_TARGET_STRING(p, gpr[4]);
+        GET_TARGET_STRING(p2, gpr[5]);
+        gpr[2] = link(p, p2);
+        gpr[3] = errno;
+        FREE_TARGET_STRING(p2, gpr[5]);
+        FREE_TARGET_STRING(p, gpr[4]);
+        break;
+#endif
+    default:
+        fprintf(stderr, "Unknown UHI operation %d\n", op);
+        abort();
+    }
+uhi_done:
+    return;
+}
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 94f17a9..32c1f66 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -29,6 +29,7 @@
 #include "exec/helper-proto.h"
 #include "exec/helper-gen.h"
 #include "sysemu/kvm.h"
+#include "exec/semihost.h"
 
 #include "trace-tcg.h"
 
@@ -11497,6 +11498,15 @@ static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
     return 4;
 }
 
+static inline bool is_uhi(int sdbbp_code)
+{
+#ifdef CONFIG_USER_ONLY
+    return false;
+#else
+    return semihosting_enabled() && sdbbp_code == 1;
+#endif
+}
+
 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
 {
     int rx, ry;
@@ -11796,11 +11806,15 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
             }
             break;
         case RR_SDBBP:
-            /* XXX: not clear which exception should be raised
-             *      when in debug mode...
-             */
-            check_insn(ctx, ISA_MIPS32);
-            generate_exception(ctx, EXCP_DBp);
+            if (is_uhi(extract32(ctx->opcode, 5, 6))) {
+                gen_helper_do_semihosting(cpu_env);
+            } else {
+                /* XXX: not clear which exception should be raised
+                 *      when in debug mode...
+                 */
+                check_insn(ctx, ISA_MIPS32);
+                generate_exception(ctx, EXCP_DBp);
+            }
             break;
         case RR_SLT:
             gen_slt(ctx, OPC_SLT, 24, rx, ry);
@@ -12647,11 +12661,15 @@ static void gen_pool16c_insn(DisasContext *ctx)
         generate_exception(ctx, EXCP_BREAK);
         break;
     case SDBBP16:
-        /* XXX: not clear which exception should be raised
-         *      when in debug mode...
-         */
-        check_insn(ctx, ISA_MIPS32);
-        generate_exception(ctx, EXCP_DBp);
+        if (is_uhi(extract32(ctx->opcode, 0, 4))) {
+            gen_helper_do_semihosting(cpu_env);
+        } else {
+            /* XXX: not clear which exception should be raised
+             *      when in debug mode...
+             */
+            check_insn(ctx, ISA_MIPS32);
+            generate_exception(ctx, EXCP_DBp);
+        }
         break;
     case JRADDIUSP + 0:
     case JRADDIUSP + 1:
@@ -13015,8 +13033,12 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
             ctx->bstate = BS_STOP;
             break;
         case SDBBP:
-            check_insn(ctx, ISA_MIPS32);
-            generate_exception(ctx, EXCP_DBp);
+            if (is_uhi(extract32(ctx->opcode, 16, 10))) {
+                gen_helper_do_semihosting(cpu_env);
+            } else {
+                check_insn(ctx, ISA_MIPS32);
+                generate_exception(ctx, EXCP_DBp);
+            }
             break;
         default:
             goto pool32axf_invalid;
@@ -16408,10 +16430,14 @@ static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
         }
         break;
     case R6_OPC_SDBBP:
-        if (ctx->hflags & MIPS_HFLAG_SBRI) {
-            generate_exception(ctx, EXCP_RI);
+        if (is_uhi(extract32(ctx->opcode, 6, 20))) {
+            gen_helper_do_semihosting(cpu_env);
         } else {
-            generate_exception(ctx, EXCP_DBp);
+            if (ctx->hflags & MIPS_HFLAG_SBRI) {
+                generate_exception(ctx, EXCP_RI);
+            } else {
+                generate_exception(ctx, EXCP_DBp);
+            }
         }
         break;
 #if defined(TARGET_MIPS64)
@@ -16781,11 +16807,15 @@ static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
         gen_cl(ctx, op1, rd, rs);
         break;
     case OPC_SDBBP:
-        /* XXX: not clear which exception should be raised
-         *      when in debug mode...
-         */
-        check_insn(ctx, ISA_MIPS32);
-        generate_exception(ctx, EXCP_DBp);
+        if (is_uhi(extract32(ctx->opcode, 6, 20))) {
+            gen_helper_do_semihosting(cpu_env);
+        } else {
+            /* XXX: not clear which exception should be raised
+             *      when in debug mode...
+             */
+            check_insn(ctx, ISA_MIPS32);
+            generate_exception(ctx, EXCP_DBp);
+        }
         break;
 #if defined(TARGET_MIPS64)
     case OPC_DCLO:
@@ -19848,6 +19878,13 @@ void cpu_state_reset(CPUMIPSState *env)
     restore_flush_mode(env);
     restore_pamask(env);
     cs->exception_index = EXCP_NONE;
+
+#ifndef CONFIG_USER_ONLY
+    if (semihosting_get_argc()) {
+        /* UHI interface should be used to obtain argc and argv */
+        env->active_tc.gpr[4] = -1;
+    }
+#endif
 }
 
 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH v2 5/5] target-mips: convert host to MIPS errno values when required
  2015-05-12 22:01 [Qemu-devel] [PATCH v2 0/5] target-mips: add UHI semihosting support Leon Alrae
                   ` (3 preceding siblings ...)
  2015-05-12 22:01 ` [Qemu-devel] [PATCH v2 4/5] target-mips: add Unified Hosting Interface (UHI) support Leon Alrae
@ 2015-05-12 22:01 ` Leon Alrae
  4 siblings, 0 replies; 6+ messages in thread
From: Leon Alrae @ 2015-05-12 22:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: matthew.fortune, aurelien

Convert only errno values which can be returned by system calls in
mips-semi.c and are not generic to all archs.

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
 target-mips/mips-semi.c | 44 +++++++++++++++++++++++++++++++++-----------
 1 file changed, 33 insertions(+), 11 deletions(-)

diff --git a/target-mips/mips-semi.c b/target-mips/mips-semi.c
index 971bbff..eaea104 100644
--- a/target-mips/mips-semi.c
+++ b/target-mips/mips-semi.c
@@ -72,6 +72,28 @@ enum UHIOpenFlags {
     UHIOpen_EXCL   = 0x800
 };
 
+/* Errno values taken from asm-mips/errno.h */
+static uint16_t host_to_mips_errno[] = {
+    [ENAMETOOLONG] = 78,
+#ifdef EOVERFLOW
+    [EOVERFLOW]    = 79,
+#endif
+#ifdef ELOOP
+    [ELOOP]        = 90,
+#endif
+};
+
+static int errno_mips(int err)
+{
+    if (err < 0 || err >= ARRAY_SIZE(host_to_mips_errno)) {
+        return EINVAL;
+    } else if (host_to_mips_errno[err]) {
+        return host_to_mips_errno[err];
+    } else {
+        return err;
+    }
+}
+
 static int copy_stat_to_target(CPUMIPSState *env, const struct stat *src,
                                target_ulong vaddr)
 {
@@ -223,7 +245,7 @@ void helper_do_semihosting(CPUMIPSState *env)
             gpr[2] = 2;
         } else {
             gpr[2] = open(p, get_open_flags(gpr[5]), gpr[6]);
-            gpr[3] = errno;
+            gpr[3] = errno_mips(errno);
         }
         FREE_TARGET_STRING(p, gpr[4]);
         break;
@@ -234,24 +256,24 @@ void helper_do_semihosting(CPUMIPSState *env)
             goto uhi_done;
         }
         gpr[2] = close(gpr[4]);
-        gpr[3] = errno;
+        gpr[3] = errno_mips(errno);
         break;
     case UHI_read:
         gpr[2] = read_from_file(env, gpr[4], gpr[5], gpr[6], 0);
-        gpr[3] = errno;
+        gpr[3] = errno_mips(errno);
         break;
     case UHI_write:
         gpr[2] = write_to_file(env, gpr[4], gpr[5], gpr[6], 0);
-        gpr[3] = errno;
+        gpr[3] = errno_mips(errno);
         break;
     case UHI_lseek:
         gpr[2] = lseek(gpr[4], gpr[5], gpr[6]);
-        gpr[3] = errno;
+        gpr[3] = errno_mips(errno);
         break;
     case UHI_unlink:
         GET_TARGET_STRING(p, gpr[4]);
         gpr[2] = remove(p);
-        gpr[3] = errno;
+        gpr[3] = errno_mips(errno);
         FREE_TARGET_STRING(p, gpr[4]);
         break;
     case UHI_fstat:
@@ -259,12 +281,12 @@ void helper_do_semihosting(CPUMIPSState *env)
             struct stat sbuf;
             memset(&sbuf, 0, sizeof(sbuf));
             gpr[2] = fstat(gpr[4], &sbuf);
-            gpr[3] = errno;
+            gpr[3] = errno_mips(errno);
             if (gpr[2]) {
                 goto uhi_done;
             }
             gpr[2] = copy_stat_to_target(env, &sbuf, gpr[5]);
-            gpr[3] = errno;
+            gpr[3] = errno_mips(errno);
         }
         break;
     case UHI_argc:
@@ -311,18 +333,18 @@ void helper_do_semihosting(CPUMIPSState *env)
         break;
     case UHI_pread:
         gpr[2] = read_from_file(env, gpr[4], gpr[5], gpr[6], gpr[7]);
-        gpr[3] = errno;
+        gpr[3] = errno_mips(errno);
         break;
     case UHI_pwrite:
         gpr[2] = write_to_file(env, gpr[4], gpr[5], gpr[6], gpr[7]);
-        gpr[3] = errno;
+        gpr[3] = errno_mips(errno);
         break;
 #ifndef _WIN32
     case UHI_link:
         GET_TARGET_STRING(p, gpr[4]);
         GET_TARGET_STRING(p2, gpr[5]);
         gpr[2] = link(p, p2);
-        gpr[3] = errno;
+        gpr[3] = errno_mips(errno);
         FREE_TARGET_STRING(p2, gpr[5]);
         FREE_TARGET_STRING(p, gpr[4]);
         break;

^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2015-05-12 22:03 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-12 22:01 [Qemu-devel] [PATCH v2 0/5] target-mips: add UHI semihosting support Leon Alrae
2015-05-12 22:01 ` [Qemu-devel] [PATCH v2 1/5] include/softmmu-semi.h: Make semihosting support 64-bit clean Leon Alrae
2015-05-12 22:01 ` [Qemu-devel] [PATCH v2 2/5] hw/mips: Do not clear BEV for MIPS malta kernel load Leon Alrae
2015-05-12 22:01 ` [Qemu-devel] [PATCH v2 3/5] target-mips: remove identical code in different branch Leon Alrae
2015-05-12 22:01 ` [Qemu-devel] [PATCH v2 4/5] target-mips: add Unified Hosting Interface (UHI) support Leon Alrae
2015-05-12 22:01 ` [Qemu-devel] [PATCH v2 5/5] target-mips: convert host to MIPS errno values when required Leon Alrae

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.