qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL 0/4] lm32: semihosting support
@ 2014-05-24 17:57 Michael Walle
  2014-05-24 17:57 ` [Qemu-devel] [PULL 1/4] test: lm32: make test cases independent Michael Walle
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Michael Walle @ 2014-05-24 17:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Michael Walle

Hi Peter,

Please pull.

As suggested by you, system calls are now intercepted in
lm32_cpu_do_interrupt(). Apart from that i've rebased the submitted
patches to the latest master.


The following changes since commit 178ac111bca16c08a79b2609ebdc75197bea976a:

  Merge remote-tracking branch 'remotes/qmp-unstable/queue/qmp' into staging (2014-05-22 19:04:49 +0100)

are available in the git repository at:


  git://github.com/mwalle/qemu tags/lm32-semihosting/20140524

for you to fetch changes up to 25156d10617794f9399d676ccd9a20f52e0c9f21:

  lm32: remove lm32_sys (2014-05-24 19:43:52 +0200)

----------------------------------------------------------------
Michael Walle (4):
      test: lm32: make test cases independent
      target-lm32: add semihosting support
      test: lm32: use semihosting for testing
      lm32: remove lm32_sys

 hw/misc/Makefile.objs       |    1 -
 hw/misc/lm32_sys.c          |  179 -----------------------------------
 qemu-options.hx             |    3 +-
 target-lm32/Makefile.objs   |    1 +
 target-lm32/README          |   15 ++-
 target-lm32/cpu.h           |    1 +
 target-lm32/helper.c        |   14 ++-
 target-lm32/lm32-semi.c     |  215 +++++++++++++++++++++++++++++++++++++++++++
 tests/tcg/lm32/Makefile     |   15 +--
 tests/tcg/lm32/crt.S        |    4 +-
 tests/tcg/lm32/helper.S     |   65 +++++++++++++
 tests/tcg/lm32/macros.inc   |   37 +++++---
 tests/tcg/lm32/test_lb.S    |    4 +
 tests/tcg/lm32/test_lbu.S   |    4 +
 tests/tcg/lm32/test_lh.S    |    4 +
 tests/tcg/lm32/test_lhu.S   |    4 +
 tests/tcg/lm32/test_lw.S    |    2 +
 tests/tcg/lm32/test_sb.S    |    2 +
 tests/tcg/lm32/test_scall.S |    4 +
 tests/tcg/lm32/test_sh.S    |    2 +
 tests/tcg/lm32/test_sw.S    |    3 +
 trace-events                |    3 -
 22 files changed, 366 insertions(+), 216 deletions(-)
 delete mode 100644 hw/misc/lm32_sys.c
 create mode 100644 target-lm32/lm32-semi.c
 create mode 100644 tests/tcg/lm32/helper.S

-- 
1.7.10.4

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

* [Qemu-devel] [PULL 1/4] test: lm32: make test cases independent
  2014-05-24 17:57 [Qemu-devel] [PULL 0/4] lm32: semihosting support Michael Walle
@ 2014-05-24 17:57 ` Michael Walle
  2014-05-24 17:57 ` [Qemu-devel] [PULL 2/4] target-lm32: add semihosting support Michael Walle
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Michael Walle @ 2014-05-24 17:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Michael Walle

Make test cases independent from from each other. Eg. if a test case needs
a specific value in register A, don't rely on the fact that it is already
set by the preceding test case.

Signed-off-by: Michael Walle <michael@walle.cc>
---
 tests/tcg/lm32/test_lb.S  |    4 ++++
 tests/tcg/lm32/test_lbu.S |    4 ++++
 tests/tcg/lm32/test_lh.S  |    4 ++++
 tests/tcg/lm32/test_lhu.S |    4 ++++
 tests/tcg/lm32/test_lw.S  |    2 ++
 tests/tcg/lm32/test_sb.S  |    2 ++
 tests/tcg/lm32/test_sh.S  |    2 ++
 tests/tcg/lm32/test_sw.S  |    3 +++
 8 files changed, 25 insertions(+)

diff --git a/tests/tcg/lm32/test_lb.S b/tests/tcg/lm32/test_lb.S
index f84d21e..d677eea 100644
--- a/tests/tcg/lm32/test_lb.S
+++ b/tests/tcg/lm32/test_lb.S
@@ -8,10 +8,12 @@ lb r3, (r1+0)
 check_r3 0x7e
 
 test_name LB_2
+load r1 data
 lb r3, (r1+1)
 check_r3 0x7f
 
 test_name LB_3
+load r1 data
 lb r3, (r1+-1)
 check_r3 0x7d
 
@@ -21,10 +23,12 @@ lb r3, (r1+0)
 check_r3 0xfffffffe
 
 test_name LB_5
+load r1 data_msb
 lb r3, (r1+1)
 check_r3 0xffffffff
 
 test_name LB_6
+load r1 data_msb
 lb r3, (r1+-1)
 check_r3 0xfffffffd
 
diff --git a/tests/tcg/lm32/test_lbu.S b/tests/tcg/lm32/test_lbu.S
index 4c1786a..dc5d5f6 100644
--- a/tests/tcg/lm32/test_lbu.S
+++ b/tests/tcg/lm32/test_lbu.S
@@ -8,10 +8,12 @@ lbu r3, (r1+0)
 check_r3 0x7e
 
 test_name LBU_2
+load r1 data
 lbu r3, (r1+1)
 check_r3 0x7f
 
 test_name LBU_3
+load r1 data
 lbu r3, (r1+-1)
 check_r3 0x7d
 
@@ -21,10 +23,12 @@ lbu r3, (r1+0)
 check_r3 0xfe
 
 test_name LBU_5
+load r1 data_msb
 lbu r3, (r1+1)
 check_r3 0xff
 
 test_name LBU_6
+load r1 data_msb
 lbu r3, (r1+-1)
 check_r3 0xfd
 
diff --git a/tests/tcg/lm32/test_lh.S b/tests/tcg/lm32/test_lh.S
index e57d9e3..397996b 100644
--- a/tests/tcg/lm32/test_lh.S
+++ b/tests/tcg/lm32/test_lh.S
@@ -8,10 +8,12 @@ lh r3, (r1+0)
 check_r3 0x7e7f
 
 test_name LH_2
+load r1 data
 lh r3, (r1+2)
 check_r3 0x7071
 
 test_name LH_3
+load r1 data
 lh r3, (r1+-2)
 check_r3 0x7c7d
 
@@ -21,10 +23,12 @@ lh r3, (r1+0)
 check_r3 0xfffffeff
 
 test_name LH_5
+load r1 data_msb
 lh r3, (r1+2)
 check_r3 0xfffff0f1
 
 test_name LH_6
+load r1 data_msb
 lh r3, (r1+-2)
 check_r3 0xfffffcfd
 
diff --git a/tests/tcg/lm32/test_lhu.S b/tests/tcg/lm32/test_lhu.S
index e648775..8de7c52 100644
--- a/tests/tcg/lm32/test_lhu.S
+++ b/tests/tcg/lm32/test_lhu.S
@@ -8,10 +8,12 @@ lhu r3, (r1+0)
 check_r3 0x7e7f
 
 test_name LHU_2
+load r1 data
 lhu r3, (r1+2)
 check_r3 0x7071
 
 test_name LHU_3
+load r1 data
 lhu r3, (r1+-2)
 check_r3 0x7c7d
 
@@ -21,10 +23,12 @@ lhu r3, (r1+0)
 check_r3 0xfeff
 
 test_name LHU_5
+load r1 data_msb
 lhu r3, (r1+2)
 check_r3 0xf0f1
 
 test_name LHU_6
+load r1 data_msb
 lhu r3, (r1+-2)
 check_r3 0xfcfd
 
diff --git a/tests/tcg/lm32/test_lw.S b/tests/tcg/lm32/test_lw.S
index f8c919d..996e5f8 100644
--- a/tests/tcg/lm32/test_lw.S
+++ b/tests/tcg/lm32/test_lw.S
@@ -8,10 +8,12 @@ lw r3, (r1+0)
 check_r3 0x7e7f7071
 
 test_name LW_2
+load r1 data
 lw r3, (r1+4)
 check_r3 0x72737475
 
 test_name LW_3
+load r1 data
 lw r3, (r1+-4)
 check_r3 0x7a7b7c7d
 
diff --git a/tests/tcg/lm32/test_sb.S b/tests/tcg/lm32/test_sb.S
index 89e39d6..b15a89d 100644
--- a/tests/tcg/lm32/test_sb.S
+++ b/tests/tcg/lm32/test_sb.S
@@ -9,11 +9,13 @@ sb (r1+0), r2
 check_mem data 0xaa000000
 
 test_name SB_2
+load r1 data
 load r2 0xf0f1f2bb
 sb (r1+1), r2
 check_mem data 0xaabb0000
 
 test_name SB_3
+load r1 data
 load r2 0xf0f1f2cc
 sb (r1+-1), r2
 check_mem data0 0x000000cc
diff --git a/tests/tcg/lm32/test_sh.S b/tests/tcg/lm32/test_sh.S
index ea8b3f2..bba1022 100644
--- a/tests/tcg/lm32/test_sh.S
+++ b/tests/tcg/lm32/test_sh.S
@@ -9,11 +9,13 @@ sh (r1+0), r2
 check_mem data 0xaaaa0000
 
 test_name SH_2
+load r1 data
 load r2 0xf0f1bbbb
 sh (r1+2), r2
 check_mem data 0xaaaabbbb
 
 test_name SH_3
+load r1 data
 load r2 0xf0f1cccc
 sh (r1+-2), r2
 check_mem data0 0x0000cccc
diff --git a/tests/tcg/lm32/test_sw.S b/tests/tcg/lm32/test_sw.S
index d1fdadc..2b1c017 100644
--- a/tests/tcg/lm32/test_sw.S
+++ b/tests/tcg/lm32/test_sw.S
@@ -9,16 +9,19 @@ sw (r1+0), r2
 check_mem data 0xaabbccdd
 
 test_name SW_2
+load r1 data
 load r2 0x00112233
 sw (r1+4), r2
 check_mem data1 0x00112233
 
 test_name SW_3
+load r1 data
 load r2 0x44556677
 sw (r1+-4), r2
 check_mem data0 0x44556677
 
 test_name SW_4
+load r1 data
 sw (r1+0), r1
 lw r3, (r1+0)
 check_r3 data
-- 
1.7.10.4

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

* [Qemu-devel] [PULL 2/4] target-lm32: add semihosting support
  2014-05-24 17:57 [Qemu-devel] [PULL 0/4] lm32: semihosting support Michael Walle
  2014-05-24 17:57 ` [Qemu-devel] [PULL 1/4] test: lm32: make test cases independent Michael Walle
@ 2014-05-24 17:57 ` Michael Walle
  2014-05-24 17:57 ` [Qemu-devel] [PULL 3/4] test: lm32: use semihosting for testing Michael Walle
  2014-05-24 17:57 ` [Qemu-devel] [PULL 4/4] lm32: remove lm32_sys Michael Walle
  3 siblings, 0 replies; 5+ messages in thread
From: Michael Walle @ 2014-05-24 17:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Michael Walle

Intercept certain system calls if semihosting is enabled. This should
behave like the GDB simulator.

Signed-off-by: Michael Walle <michael@walle.cc>
---
 qemu-options.hx           |    3 +-
 target-lm32/Makefile.objs |    1 +
 target-lm32/README        |    9 ++
 target-lm32/cpu.h         |    1 +
 target-lm32/helper.c      |   14 ++-
 target-lm32/lm32-semi.c   |  215 +++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 240 insertions(+), 3 deletions(-)
 create mode 100644 target-lm32/lm32-semi.c

diff --git a/qemu-options.hx b/qemu-options.hx
index c2c0823..4011d46 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3071,7 +3071,8 @@ STEXI
 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)
+    "-semihosting    semihosting mode\n",
+    QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA | QEMU_ARCH_LM32)
 STEXI
 @item -semihosting
 @findex -semihosting
diff --git a/target-lm32/Makefile.objs b/target-lm32/Makefile.objs
index 4023687..c3e1bd6 100644
--- a/target-lm32/Makefile.objs
+++ b/target-lm32/Makefile.objs
@@ -1,3 +1,4 @@
 obj-y += translate.o op_helper.o helper.o cpu.o
 obj-y += gdbstub.o
+obj-y += lm32-semi.o
 obj-$(CONFIG_SOFTMMU) += machine.o
diff --git a/target-lm32/README b/target-lm32/README
index a1c2c7e..03ddbff 100644
--- a/target-lm32/README
+++ b/target-lm32/README
@@ -26,6 +26,15 @@ first BSP which instantiate this model. A (32 bit) write to 0xfff0000
 causes a vm shutdown.
 
 
+Semihosting
+-----------
+Semihosting on this target is supported. Some system calls like read, write
+and exit are executed on the host if semihosting is enabled. See
+target/lm32-semi.c for all supported system calls. Emulation aware programs
+can use this mechanism to shut down the virtual machine and print to the
+host console. See the tcg tests for an example.
+
+
 Special instructions
 --------------------
 The translation recognizes one special instruction to halt the cpu:
diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h
index 24bde78..70600aa 100644
--- a/target-lm32/cpu.h
+++ b/target-lm32/cpu.h
@@ -217,6 +217,7 @@ void lm32_breakpoint_remove(CPULM32State *env, int index);
 void lm32_watchpoint_insert(CPULM32State *env, int index, target_ulong address,
         lm32_wp_t wp_type);
 void lm32_watchpoint_remove(CPULM32State *env, int index);
+bool lm32_cpu_do_semihosting(CPUState *cs);
 
 static inline CPULM32State *cpu_init(const char *cpu_model)
 {
diff --git a/target-lm32/helper.c b/target-lm32/helper.c
index 783aa16..1bca196 100644
--- a/target-lm32/helper.c
+++ b/target-lm32/helper.c
@@ -1,7 +1,7 @@
 /*
  *  LatticeMico32 helper routines.
  *
- *  Copyright (c) 2010 Michael Walle <michael@walle.cc>
+ *  Copyright (c) 2010-2014 Michael Walle <michael@walle.cc>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -19,6 +19,7 @@
 
 #include "cpu.h"
 #include "qemu/host-utils.h"
+#include "sysemu/sysemu.h"
 
 int lm32_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
                               int mmu_idx)
@@ -159,11 +160,20 @@ void lm32_cpu_do_interrupt(CPUState *cs)
             "exception at pc=%x type=%x\n", env->pc, cs->exception_index);
 
     switch (cs->exception_index) {
+    case EXCP_SYSTEMCALL:
+        if (unlikely(semihosting_enabled)) {
+            /* do_semicall() returns true if call was handled. Otherwise
+             * do the normal exception handling. */
+            if (lm32_cpu_do_semihosting(cs)) {
+                env->pc += 4;
+                break;
+            }
+        }
+        /* fall through */
     case EXCP_INSN_BUS_ERROR:
     case EXCP_DATA_BUS_ERROR:
     case EXCP_DIVIDE_BY_ZERO:
     case EXCP_IRQ:
-    case EXCP_SYSTEMCALL:
         /* non-debug exceptions */
         env->regs[R_EA] = env->pc;
         env->ie |= (env->ie & IE_IE) ? IE_EIE : 0;
diff --git a/target-lm32/lm32-semi.c b/target-lm32/lm32-semi.c
new file mode 100644
index 0000000..fc9d2d1
--- /dev/null
+++ b/target-lm32/lm32-semi.c
@@ -0,0 +1,215 @@
+/*
+ *  Lattice Mico32 semihosting syscall interface
+ *
+ *  Copyright (c) 2014 Michael Walle <michael@walle.cc>
+ *
+ * Based on target-m68k/m68k-semi.c, which is
+ *  Copyright (c) 2005-2007 CodeSourcery.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <stddef.h>
+#include "cpu.h"
+#include "helper.h"
+#include "qemu/log.h"
+#include "exec/softmmu-semi.h"
+
+enum {
+    TARGET_SYS_exit    = 1,
+    TARGET_SYS_open    = 2,
+    TARGET_SYS_close   = 3,
+    TARGET_SYS_read    = 4,
+    TARGET_SYS_write   = 5,
+    TARGET_SYS_lseek   = 6,
+    TARGET_SYS_fstat   = 10,
+    TARGET_SYS_stat    = 15,
+};
+
+enum {
+    NEWLIB_O_RDONLY    =   0x0,
+    NEWLIB_O_WRONLY    =   0x1,
+    NEWLIB_O_RDWR      =   0x2,
+    NEWLIB_O_APPEND    =   0x8,
+    NEWLIB_O_CREAT     = 0x200,
+    NEWLIB_O_TRUNC     = 0x400,
+    NEWLIB_O_EXCL      = 0x800,
+};
+
+static int translate_openflags(int flags)
+{
+    int hf;
+
+    if (flags & NEWLIB_O_WRONLY) {
+        hf = O_WRONLY;
+    } else if (flags & NEWLIB_O_RDWR) {
+        hf = O_RDWR;
+    } else {
+        hf = O_RDONLY;
+    }
+
+    if (flags & NEWLIB_O_APPEND) {
+        hf |= O_APPEND;
+    }
+
+    if (flags & NEWLIB_O_CREAT) {
+        hf |= O_CREAT;
+    }
+
+    if (flags & NEWLIB_O_TRUNC) {
+        hf |= O_TRUNC;
+    }
+
+    if (flags & NEWLIB_O_EXCL) {
+        hf |= O_EXCL;
+    }
+
+    return hf;
+}
+
+struct newlib_stat {
+    int16_t     newlib_st_dev;     /* device */
+    uint16_t    newlib_st_ino;     /* inode */
+    uint16_t    newlib_st_mode;    /* protection */
+    uint16_t    newlib_st_nlink;   /* number of hard links */
+    uint16_t    newlib_st_uid;     /* user ID of owner */
+    uint16_t    newlib_st_gid;     /* group ID of owner */
+    int16_t     newlib_st_rdev;    /* device type (if inode device) */
+    int32_t     newlib_st_size;    /* total size, in bytes */
+    int32_t     newlib_st_atime;   /* time of last access */
+    uint32_t    newlib_st_spare1;
+    int32_t     newlib_st_mtime;   /* time of last modification */
+    uint32_t    newlib_st_spare2;
+    int32_t     newlib_st_ctime;   /* time of last change */
+    uint32_t    newlib_st_spare3;
+} QEMU_PACKED;
+
+static int translate_stat(CPULM32State *env, target_ulong addr,
+        struct stat *s)
+{
+    struct newlib_stat *p;
+
+    p = lock_user(VERIFY_WRITE, addr, sizeof(struct newlib_stat), 0);
+    if (!p) {
+        return 0;
+    }
+    p->newlib_st_dev = cpu_to_be16(s->st_dev);
+    p->newlib_st_ino = cpu_to_be16(s->st_ino);
+    p->newlib_st_mode = cpu_to_be16(s->st_mode);
+    p->newlib_st_nlink = cpu_to_be16(s->st_nlink);
+    p->newlib_st_uid = cpu_to_be16(s->st_uid);
+    p->newlib_st_gid = cpu_to_be16(s->st_gid);
+    p->newlib_st_rdev = cpu_to_be16(s->st_rdev);
+    p->newlib_st_size = cpu_to_be32(s->st_size);
+    p->newlib_st_atime = cpu_to_be32(s->st_atime);
+    p->newlib_st_mtime = cpu_to_be32(s->st_mtime);
+    p->newlib_st_ctime = cpu_to_be32(s->st_ctime);
+    unlock_user(p, addr, sizeof(struct newlib_stat));
+
+    return 1;
+}
+
+bool lm32_cpu_do_semihosting(CPUState *cs)
+{
+    LM32CPU *cpu = LM32_CPU(cs);
+    CPULM32State *env = &cpu->env;
+
+    int ret = -1;
+    target_ulong nr, arg0, arg1, arg2;
+    void *p;
+    struct stat s;
+
+    nr = env->regs[R_R8];
+    arg0 = env->regs[R_R1];
+    arg1 = env->regs[R_R2];
+    arg2 = env->regs[R_R3];
+
+    switch (nr) {
+    case TARGET_SYS_exit:
+        /* void _exit(int rc) */
+        exit(arg0);
+
+    case TARGET_SYS_open:
+        /* int open(const char *pathname, int flags) */
+        p = lock_user_string(arg0);
+        if (!p) {
+            ret = -1;
+        } else {
+            ret = open(p, translate_openflags(arg2));
+            unlock_user(p, arg0, 0);
+        }
+        break;
+
+    case TARGET_SYS_read:
+        /* ssize_t read(int fd, const void *buf, size_t count) */
+        p = lock_user(VERIFY_WRITE, arg1, arg2, 0);
+        if (!p) {
+            ret = -1;
+        } else {
+            ret = read(arg0, p, arg2);
+            unlock_user(p, arg1, arg2);
+        }
+        break;
+
+    case TARGET_SYS_write:
+        /* ssize_t write(int fd, const void *buf, size_t count) */
+        p = lock_user(VERIFY_READ, arg1, arg2, 1);
+        if (!p) {
+            ret = -1;
+        } else {
+            ret = write(arg0, p, arg2);
+            unlock_user(p, arg1, 0);
+        }
+        break;
+
+    case TARGET_SYS_close:
+        /* int close(int fd) */
+        /* don't close stdin/stdout/stderr */
+        if (arg0 > 2) {
+            ret = close(arg0);
+        } else {
+            ret = 0;
+        }
+        break;
+
+    case TARGET_SYS_lseek:
+        /* off_t lseek(int fd, off_t offset, int whence */
+        ret = lseek(arg0, arg1, arg2);
+        break;
+
+    case TARGET_SYS_stat:
+        /* int stat(const char *path, struct stat *buf) */
+        p = lock_user_string(arg0);
+        if (!p) {
+            ret = -1;
+        } else {
+            ret = stat(p, &s);
+            unlock_user(p, arg0, 0);
+            if (translate_stat(env, arg1, &s) == 0) {
+                ret = -1;
+            }
+        }
+        break;
+
+    case TARGET_SYS_fstat:
+        /* int stat(int fd, struct stat *buf) */
+        ret = fstat(arg0, &s);
+        if (ret == 0) {
+            if (translate_stat(env, arg1, &s) == 0) {
+                ret = -1;
+            }
+        }
+        break;
+
+    default:
+        /* unhandled */
+        return false;
+    }
+
+    env->regs[R_R1] = ret;
+    return true;
+}
-- 
1.7.10.4

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

* [Qemu-devel] [PULL 3/4] test: lm32: use semihosting for testing
  2014-05-24 17:57 [Qemu-devel] [PULL 0/4] lm32: semihosting support Michael Walle
  2014-05-24 17:57 ` [Qemu-devel] [PULL 1/4] test: lm32: make test cases independent Michael Walle
  2014-05-24 17:57 ` [Qemu-devel] [PULL 2/4] target-lm32: add semihosting support Michael Walle
@ 2014-05-24 17:57 ` Michael Walle
  2014-05-24 17:57 ` [Qemu-devel] [PULL 4/4] lm32: remove lm32_sys Michael Walle
  3 siblings, 0 replies; 5+ messages in thread
From: Michael Walle @ 2014-05-24 17:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Michael Walle

Instead of the lm32-sys device, use semihosting to print to the host
console and exit the test.

Signed-off-by: Michael Walle <michael@walle.cc>
---
 tests/tcg/lm32/Makefile     |   15 +++++-----
 tests/tcg/lm32/crt.S        |    4 +--
 tests/tcg/lm32/helper.S     |   65 +++++++++++++++++++++++++++++++++++++++++++
 tests/tcg/lm32/macros.inc   |   37 +++++++++++++++---------
 tests/tcg/lm32/test_scall.S |    4 +++
 5 files changed, 103 insertions(+), 22 deletions(-)
 create mode 100644 tests/tcg/lm32/helper.S

diff --git a/tests/tcg/lm32/Makefile b/tests/tcg/lm32/Makefile
index 8e5d405..57e7363 100644
--- a/tests/tcg/lm32/Makefile
+++ b/tests/tcg/lm32/Makefile
@@ -3,7 +3,7 @@
 CROSS=lm32-elf-
 
 SIM = qemu-system-lm32
-SIMFLAGS = -M lm32-evr -nographic -device lm32-sys -net none -kernel
+SIMFLAGS = -M lm32-evr -nographic -semihosting -net none -kernel
 
 CC      = $(CROSS)gcc
 AS      = $(CROSS)as
@@ -18,6 +18,7 @@ LDFLAGS = -T$(TSRC_PATH)/linker.ld
 ASFLAGS += -Wa,-I,$(TSRC_PATH)/
 
 CRT        = crt.o
+HELPER     = helper.o
 TESTCASES += test_add.tst
 TESTCASES += test_addi.tst
 TESTCASES += test_and.tst
@@ -91,15 +92,15 @@ all: build
 %.o: $(TSRC_PATH)/%.S
 	$(AS) $(ASFLAGS) -c $< -o $@
 
-%.tst: %.o $(TSRC_PATH)/macros.inc $(CRT)
-	$(LD) $(LDFLAGS) $(NOSTDFLAGS) $(CRT) $< -o $@
+%.tst: %.o $(TSRC_PATH)/macros.inc $(CRT) $(HELPER)
+	$(LD) $(LDFLAGS) $(NOSTDFLAGS) $(CRT) $(HELPER) $< -o $@
 
-build: $(CRT) $(TESTCASES)
+build: $(TESTCASES)
 
 check: $(TESTCASES:test_%.tst=check_%)
 
-check_%: test_%.tst $(CRT) $(SYS)
-	$(SIM) $(SIMFLAGS) $<
+check_%: test_%.tst
+	@$(SIM) $(SIMFLAGS) $<
 
 clean:
-	$(RM) -fr $(TESTCASES) $(CRT)
+	$(RM) -fr $(TESTCASES) $(CRT) $(HELPER)
diff --git a/tests/tcg/lm32/crt.S b/tests/tcg/lm32/crt.S
index 5f9cfd9..fc437a3 100644
--- a/tests/tcg/lm32/crt.S
+++ b/tests/tcg/lm32/crt.S
@@ -8,9 +8,9 @@ _reset_handler:
 	ori r1, r1, lo(_start)
 	wcsr eba, r1
 	wcsr deba, r1
+	mvhi sp, hi(_fstack)
+	ori sp, sp, lo(_fstack)
 	bi _main
-	nop
-	nop
 
 _breakpoint_handler:
 	ori r25, r25, 1
diff --git a/tests/tcg/lm32/helper.S b/tests/tcg/lm32/helper.S
new file mode 100644
index 0000000..3351d41
--- /dev/null
+++ b/tests/tcg/lm32/helper.S
@@ -0,0 +1,65 @@
+.text
+.global _start, _write, _exit
+.global _tc_fail, _tc_pass
+
+_write:
+	addi sp, sp, -4
+	sw (sp+4), r8
+	mvi r8, 5
+	scall
+	lw r8, (sp+4)
+	addi sp, sp, 4
+	ret
+
+_exit:
+	mvi r8, 1
+	scall
+1:
+	bi 1b
+
+_tc_pass:
+.data
+1:
+	.ascii "OK\n"
+2:
+.text
+	addi sp, sp, -16
+	sw (sp+4), ra
+	sw (sp+8), r1
+	sw (sp+12), r2
+	sw (sp+16), r3
+	mvi r1, 1
+	mvhi r2, hi(1b)
+	ori r2, r2, lo(1b)
+	mvi r3, (2b - 1b)
+	calli _write
+	lw r3, (sp+16)
+	lw r2, (sp+12)
+	lw r1, (sp+8)
+	lw ra, (sp+4)
+	addi sp, sp, 16
+	ret
+
+_tc_fail:
+.data
+1:
+	.ascii "FAILED\n"
+2:
+.text
+	addi sp, sp, -16
+	sw (sp+4), ra
+	sw (sp+8), r1
+	sw (sp+12), r2
+	sw (sp+16), r3
+	sw (sp+4), ra
+	mvi r1, 1
+	mvhi r2, hi(1b)
+	ori r2, r2, lo(1b)
+	mvi r3, (2b - 1b)
+	calli _write
+	lw r3, (sp+16)
+	lw r2, (sp+12)
+	lw r1, (sp+8)
+	lw ra, (sp+4)
+	addi sp, sp, 16
+	ret
diff --git a/tests/tcg/lm32/macros.inc b/tests/tcg/lm32/macros.inc
index 367c7c5..360ad53 100644
--- a/tests/tcg/lm32/macros.inc
+++ b/tests/tcg/lm32/macros.inc
@@ -1,12 +1,26 @@
 
+.equ MAX_TESTNAME_LEN, 32
 .macro test_name name
 	.data
 tn_\name:
-	.asciz "\name"
+	.ascii "\name"
+	.space MAX_TESTNAME_LEN - (. - tn_\name), ' '
 	.text
-	mvhi r13, hi(tn_\name)
-	ori r13, r13, lo(tn_\name)
-	sw (r12+8), r13
+	.global \name
+\name:
+	addi sp, sp, -12
+	sw (sp+4), r1
+	sw (sp+8), r2
+	sw (sp+12), r3
+	mvi r1, 1
+	mvhi r2, hi(tn_\name)
+	ori r2, r2, lo(tn_\name)
+	mvi r3, MAX_TESTNAME_LEN
+	calli _write
+	lw r3, (sp+12)
+	lw r2, (sp+8)
+	lw r1, (sp+4)
+	addi sp, sp, 12
 .endm
 
 .macro load reg val
@@ -15,13 +29,12 @@ tn_\name:
 .endm
 
 .macro tc_pass
-	mvi r13, 0
-	sw (r12+4), r13
+	calli _tc_pass
 .endm
 
 .macro tc_fail
-	mvi r13, 1
-	sw (r12+4), r13
+	addi r12, r12, 1
+	calli _tc_fail
 .endm
 
 .macro check_r3 val
@@ -63,14 +76,12 @@ tn_\name:
 	.global _main
 	.text
 _main:
-	mvhi r12, hi(0xffff0000)      # base address of test block
-	ori r12, r12, lo(0xffff0000)
+	mvi r12, 0
 .endm
 
 .macro end
-	sw (r12+0), r0
-1:
-	bi 1b
+	mv r1, r12
+	calli _exit
 .endm
 
 # base +
diff --git a/tests/tcg/lm32/test_scall.S b/tests/tcg/lm32/test_scall.S
index b442e32..46032f8 100644
--- a/tests/tcg/lm32/test_scall.S
+++ b/tests/tcg/lm32/test_scall.S
@@ -5,6 +5,10 @@ start
 test_name SCALL_1
 mvi r1, 1
 wcsr IE, r1
+# we are running in a semi hosted environment
+# therefore we have to set r8 to some unused system
+# call
+mvi r8, 0
 insn:
 scall
 check_excp 64
-- 
1.7.10.4

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

* [Qemu-devel] [PULL 4/4] lm32: remove lm32_sys
  2014-05-24 17:57 [Qemu-devel] [PULL 0/4] lm32: semihosting support Michael Walle
                   ` (2 preceding siblings ...)
  2014-05-24 17:57 ` [Qemu-devel] [PULL 3/4] test: lm32: use semihosting for testing Michael Walle
@ 2014-05-24 17:57 ` Michael Walle
  3 siblings, 0 replies; 5+ messages in thread
From: Michael Walle @ 2014-05-24 17:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Michael Walle

Since we have now semihosting on the lm32 target, this device is no longer
needed. Remove it.

Signed-off-by: Michael Walle <michael@walle.cc>
---
 hw/misc/Makefile.objs |    1 -
 hw/misc/lm32_sys.c    |  179 -------------------------------------------------
 target-lm32/README    |   10 ---
 trace-events          |    3 -
 4 files changed, 193 deletions(-)
 delete mode 100644 hw/misc/lm32_sys.c

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index f674365..979e532 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -29,7 +29,6 @@ obj-$(CONFIG_NSERIES) += cbus.o
 obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o
 obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o
 obj-$(CONFIG_IMX) += imx_ccm.o
-obj-$(CONFIG_LM32) += lm32_sys.o
 obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
 obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
 obj-$(CONFIG_MAINSTONE) += mst_fpga.o
diff --git a/hw/misc/lm32_sys.c b/hw/misc/lm32_sys.c
deleted file mode 100644
index 778eb6e..0000000
--- a/hw/misc/lm32_sys.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- *  QEMU model of the LatticeMico32 system control block.
- *
- *  Copyright (c) 2010 Michael Walle <michael@walle.cc>
- *
- * 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/>.
- */
-
-/*
- * This model is mainly intended for testing purposes and doesn't fit to any
- * real hardware. On the one hand it provides a control register (R_CTRL) on
- * the other hand it supports the lm32 tests.
- *
- * A write to the control register causes a system shutdown.
- * Tests first write the pointer to a test name to the test name register
- * (R_TESTNAME) and then write a zero to the pass/fail register (R_PASSFAIL) if
- * the test is passed or any non-zero value to it if the test is failed.
- */
-
-#include "hw/hw.h"
-#include "hw/sysbus.h"
-#include "trace.h"
-#include "qemu/log.h"
-#include "qemu/error-report.h"
-#include "sysemu/sysemu.h"
-
-enum {
-    R_CTRL = 0,
-    R_PASSFAIL,
-    R_TESTNAME,
-    R_MAX
-};
-
-#define MAX_TESTNAME_LEN 32
-
-#define TYPE_LM32_SYS "lm32-sys"
-#define LM32_SYS(obj) OBJECT_CHECK(LM32SysState, (obj), TYPE_LM32_SYS)
-
-struct LM32SysState {
-    SysBusDevice parent_obj;
-
-    MemoryRegion iomem;
-    uint32_t base;
-    uint32_t regs[R_MAX];
-    uint8_t testname[MAX_TESTNAME_LEN];
-};
-typedef struct LM32SysState LM32SysState;
-
-static void copy_testname(LM32SysState *s)
-{
-    cpu_physical_memory_read(s->regs[R_TESTNAME], s->testname,
-            MAX_TESTNAME_LEN);
-    s->testname[MAX_TESTNAME_LEN - 1] = '\0';
-}
-
-static void sys_write(void *opaque, hwaddr addr,
-                      uint64_t value, unsigned size)
-{
-    LM32SysState *s = opaque;
-    char *testname;
-
-    trace_lm32_sys_memory_write(addr, value);
-
-    addr >>= 2;
-    switch (addr) {
-    case R_CTRL:
-        qemu_system_shutdown_request();
-        break;
-    case R_PASSFAIL:
-        s->regs[addr] = value;
-        testname = (char *)s->testname;
-        fprintf(stderr, "TC  %-*s %s\n", MAX_TESTNAME_LEN,
-                testname, (value) ? "FAILED" : "OK");
-        if (value) {
-            cpu_dump_state(qemu_get_cpu(0), stderr, fprintf, 0);
-        }
-        break;
-    case R_TESTNAME:
-        s->regs[addr] = value;
-        copy_testname(s);
-        break;
-
-    default:
-        error_report("lm32_sys: write access to unknown register 0x"
-                TARGET_FMT_plx, addr << 2);
-        break;
-    }
-}
-
-static bool sys_ops_accepts(void *opaque, hwaddr addr,
-                            unsigned size, bool is_write)
-{
-    return is_write && size == 4;
-}
-
-static const MemoryRegionOps sys_ops = {
-    .write = sys_write,
-    .valid.accepts = sys_ops_accepts,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void sys_reset(DeviceState *d)
-{
-    LM32SysState *s = LM32_SYS(d);
-    int i;
-
-    for (i = 0; i < R_MAX; i++) {
-        s->regs[i] = 0;
-    }
-    memset(s->testname, 0, MAX_TESTNAME_LEN);
-}
-
-static int lm32_sys_init(SysBusDevice *dev)
-{
-    LM32SysState *s = LM32_SYS(dev);
-
-    memory_region_init_io(&s->iomem, OBJECT(dev), &sys_ops , s,
-                          "sys", R_MAX * 4);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    /* Note: This device is not created in the board initialization,
-     * instead it has to be added with the -device parameter. Therefore,
-     * the device maps itself. */
-    sysbus_mmio_map(dev, 0, s->base);
-
-    return 0;
-}
-
-static const VMStateDescription vmstate_lm32_sys = {
-    .name = "lm32-sys",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT32_ARRAY(regs, LM32SysState, R_MAX),
-        VMSTATE_BUFFER(testname, LM32SysState),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static Property lm32_sys_properties[] = {
-    DEFINE_PROP_UINT32("base", LM32SysState, base, 0xffff0000),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void lm32_sys_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = lm32_sys_init;
-    dc->reset = sys_reset;
-    dc->vmsd = &vmstate_lm32_sys;
-    dc->props = lm32_sys_properties;
-}
-
-static const TypeInfo lm32_sys_info = {
-    .name          = TYPE_LM32_SYS,
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(LM32SysState),
-    .class_init    = lm32_sys_class_init,
-};
-
-static void lm32_sys_register_types(void)
-{
-    type_register_static(&lm32_sys_info);
-}
-
-type_init(lm32_sys_register_types)
diff --git a/target-lm32/README b/target-lm32/README
index 03ddbff..ba3508a 100644
--- a/target-lm32/README
+++ b/target-lm32/README
@@ -16,16 +16,6 @@ This will make serial0 (the lm32_uart) and serial1 (the JTAG UART)
 available as virtual consoles.
 
 
-Programmatically terminate the emulator
-----------------------------------------
-Originally neither the LatticeMico32 nor its peripherals support a
-mechanism to shut down the machine. Emulation aware programs can write to a
-to a special register within the system control block to shut down the
-virtual machine.  For more details see hw/lm32_sys.c. The lm32-evr is the
-first BSP which instantiate this model. A (32 bit) write to 0xfff0000
-causes a vm shutdown.
-
-
 Semihosting
 -----------
 Semihosting on this target is supported. Some system calls like read, write
diff --git a/trace-events b/trace-events
index b6d289d..7a415d9 100644
--- a/trace-events
+++ b/trace-events
@@ -627,9 +627,6 @@ lm32_uart_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
 lm32_uart_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
 lm32_uart_irq_state(int level) "irq state %d"
 
-# hw/misc/lm32_sys.c
-lm32_sys_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
-
 # hw/scsi/megasas.c
 megasas_init_firmware(uint64_t pa) "pa %" PRIx64 " "
 megasas_init_queue(uint64_t queue_pa, int queue_len, uint64_t head, uint64_t tail, uint32_t flags) "queue at %" PRIx64 " len %d head %" PRIx64 " tail %" PRIx64 " flags %x"
-- 
1.7.10.4

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

end of thread, other threads:[~2014-05-24 17:58 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-05-24 17:57 [Qemu-devel] [PULL 0/4] lm32: semihosting support Michael Walle
2014-05-24 17:57 ` [Qemu-devel] [PULL 1/4] test: lm32: make test cases independent Michael Walle
2014-05-24 17:57 ` [Qemu-devel] [PULL 2/4] target-lm32: add semihosting support Michael Walle
2014-05-24 17:57 ` [Qemu-devel] [PULL 3/4] test: lm32: use semihosting for testing Michael Walle
2014-05-24 17:57 ` [Qemu-devel] [PULL 4/4] lm32: remove lm32_sys Michael Walle

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).