All of lore.kernel.org
 help / color / mirror / Atom feed
From: Nathan Froyd <froydnj@codesourcery.com>
To: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH 3/6] add implementation of MIPS semihosting
Date: Mon, 20 Jul 2009 08:24:20 -0700	[thread overview]
Message-ID: <20090720152420.GF26319@codesourcery.com> (raw)
In-Reply-To: <f43fc5580907180022x1d8b4944x115857a609eb3c76@mail.gmail.com>

Later patches will call into this file via do_mips_semihosting.

Signed-off-by: Nathan Froyd <froydnj@codesourcery.com>
---
 Makefile.target   |    1 +
 mips-semi.c       |  216 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 target-mips/cpu.h |    1 +
 3 files changed, 218 insertions(+), 0 deletions(-)
 create mode 100644 mips-semi.c

v2: point at FSF website for copies of GPL

diff --git a/Makefile.target b/Makefile.target
index f9cd42a..7230c44 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -534,6 +534,7 @@ obj-mips-y += piix_pci.o parallel.o cirrus_vga.o pcspk.o $(sound-obj-y)
 obj-mips-y += mipsnet.o
 obj-mips-y += pflash_cfi01.o
 obj-mips-y += vmware_vga.o
+obj-mips-y += mips-semi.o
 
 ifeq ($(TARGET_BASE_ARCH), mips)
 CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
diff --git a/mips-semi.c b/mips-semi.c
new file mode 100644
index 0000000..77ecff3
--- /dev/null
+++ b/mips-semi.c
@@ -0,0 +1,216 @@
+
+/*
+ * MIPS MDI semihosting syscalls
+ *
+ * Copyright (c) 2009 CodeSourcery.
+ * Written by Nathan Froyd.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <time.h>
+
+#include "cpu.h"
+#include "qemu-common.h"
+#include "sysemu.h"
+#include "gdbstub.h"
+#include "softmmu-semi.h"
+
+#define HOSTED_OPEN 0
+#define HOSTED_CLOSE 1
+#define HOSTED_READ 2
+#define HOSTED_WRITE 3
+#define HOSTED_GETCHAR 4
+#define HOSTED_PUTCHAR 5
+#define HOSTED_LSEEK32 6
+#define HOSTED_GETTIME 7
+#define HOSTED_EXIT 8
+#define HOSTED_MOVED 9
+#define HOSTED_GETARGS 10
+#define HOSTED_ISATTY 11
+#define HOSTED_PROFIL 12
+#define HOSTED_SIGHOOK 13
+
+#define ARG(n) env->active_tc.gpr[4 + n]
+
+static void mips_store_result(CPUState *env, target_ulong ret, target_ulong err)
+{
+    env->active_tc.PC = env->active_tc.gpr[31];
+    env->active_tc.gpr[2] = ret;
+    env->active_tc.gpr[3] = err;
+}
+
+static void mips_semi_cb(CPUState *env, target_ulong ret, target_ulong err)
+{
+    mips_store_result(env, ret, err);
+}
+
+#define GDB_O_RDONLY   0x0
+#define GDB_O_WRONLY   0x1
+#define GDB_O_RDWR     0x2
+#define GDB_O_APPEND   0x8
+#define GDB_O_CREAT  0x200
+#define GDB_O_TRUNC  0x400
+#define GDB_O_EXCL   0x800
+
+static int translate_openflags(int flags)
+{
+    int hf;
+
+    if (flags & GDB_O_WRONLY)
+        hf = O_WRONLY;
+    else if (flags & GDB_O_RDWR)
+        hf = O_RDWR;
+    else
+        hf = O_RDONLY;
+
+    if (flags & GDB_O_APPEND) hf |= O_APPEND;
+    if (flags & GDB_O_CREAT) hf |= O_CREAT;
+    if (flags & GDB_O_TRUNC) hf |= O_TRUNC;
+    if (flags & GDB_O_EXCL) hf |= O_EXCL;
+
+    return hf;
+}
+
+void do_mips_semihosting(CPUState *env)
+{
+    target_ulong result;
+    void *p;
+    uint32_t len;
+    target_ulong err = 0;
+    char *s;
+
+    switch (env->active_tc.gpr[2]) {
+    case HOSTED_OPEN:
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(mips_semi_cb, "open,%s,%x,%x", ARG(0),
+                           target_strlen(ARG(0))+1, ARG(1), ARG(2));
+            return;
+        } else {
+            if (!(s = lock_user_string(ARG(0)))) {
+                result = -1;
+            } else {
+                result = open(s, translate_openflags(ARG(1)), ARG(2));
+            }
+            unlock_user(s, ARG(0), 0);
+        }
+        break;
+    case HOSTED_CLOSE:
+        /* Ignore attempts to close stdin/out/err */
+        if (ARG(0) > 2) {
+            if (use_gdb_syscalls()) {
+                gdb_do_syscall(mips_semi_cb, "close,%x", ARG(0));
+                return;
+            } else {
+                result = close(ARG(0));
+            }
+        } else {
+            result = 0;
+        }
+        break;
+    case HOSTED_READ:
+        len = ARG(2);
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(mips_semi_cb, "read,%x,%x,%x",
+                           ARG(0), ARG(1), len);
+            return;
+        } else {
+            if (!(p = lock_user(VERIFY_WRITE, ARG(1), len, 0))) {
+                result = -1;
+            } else {
+                result = read(ARG(0), p, len);
+                unlock_user(p, ARG(1), len);
+            }
+        }
+        break;
+    case HOSTED_WRITE:
+        len = ARG(2);
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(mips_semi_cb, "write,%x,%x,%x",
+                           ARG(0), ARG(1), len);
+            return;
+        } else {
+            if (!(p = lock_user(VERIFY_READ, ARG(1), len, 1))) {
+                result = -1;
+            } else {
+                result = write(ARG(0), p, len);
+                unlock_user(p, ARG(1), len);
+            }
+        }
+        break;
+    case HOSTED_LSEEK32:
+        {
+            off_t off = (target_long) ARG(1);
+            if (use_gdb_syscalls()) {
+                gdb_do_syscall(mips_semi_cb, "lseek,%x,%lx,%x",
+                               ARG(0), off, ARG(2));
+                return;
+            } else {
+                off = lseek(ARG(0), off, ARG(2));
+                result = (uint32_t) off;
+            }
+        }
+        break;
+    case HOSTED_GETTIME:
+        {
+            qemu_timeval tv;
+            result = qemu_gettimeofday(&tv);
+            if (!result) {
+                result = tv.tv_sec;
+                err = tv.tv_usec;
+            } else {
+                result = -1;
+                err = errno;
+            }
+        }
+        break;
+    case HOSTED_EXIT:
+        exit(ARG(0));
+        break;
+    case HOSTED_ISATTY:
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(mips_semi_cb, "isatty,%x", ARG(0));
+            return;
+        } else {
+            result = isatty(ARG(0));
+        }
+        break;
+    case HOSTED_GETARGS:
+        /* argc gets placed in A0, argv gets copied onto the stack and
+           the address of the copy placed in A1.  We have nothing to
+           provide in terms of argc/argv, so just stuff NULL in
+           each.  */
+        ARG(1) = ARG(0) = 0;
+        result = 0;
+        break;
+    case HOSTED_GETCHAR:
+    case HOSTED_PUTCHAR:
+    case HOSTED_MOVED:
+    case HOSTED_PROFIL:
+    case HOSTED_SIGHOOK:
+    default:
+        result = -1;
+        err = 88;               /* ENOSYS */
+        break;
+    }
+
+    mips_store_result(env, result, err);
+}
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index bb9a49b..44420a1 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -587,6 +587,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
 void do_interrupt (CPUState *env);
 void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra);
 
+void do_mips_semihosting(CPUState *env);
 static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
 {
     env->active_tc.PC = tb->pc;
-- 
1.6.3.2

  reply	other threads:[~2009-07-20 15:24 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-07-17 20:33 [Qemu-devel] [PATCH 0/6] target-mips: add MDI semihosting Nathan Froyd
2009-07-17 20:33 ` [Qemu-devel] [PATCH 1/6] sysemu: add section_callback argument to ELF loader Nathan Froyd
2009-07-17 20:33 ` [Qemu-devel] [PATCH 2/6] add softmmu_target_strlen Nathan Froyd
2009-07-17 20:33 ` [Qemu-devel] [PATCH 3/6] add implementation of MIPS semihosting Nathan Froyd
2009-07-18  7:22   ` Blue Swirl
2009-07-20 15:24     ` Nathan Froyd [this message]
2009-07-17 20:33 ` [Qemu-devel] [PATCH 4/6] target-mips: add MDI semihosting support to mipssim machine Nathan Froyd
2009-07-17 20:33 ` [Qemu-devel] [PATCH 5/6] enable --semihosting option for TARGET_MIPS Nathan Froyd
2009-07-17 20:33 ` [Qemu-devel] [PATCH 6/6] gdbstub: add qSymbol handling " Nathan Froyd
  -- strict thread matches above, loose matches on Subject: below --
2009-08-03 14:45 [Qemu-devel] [PATCH 0/6] target-mips: add MDI semihosting, v2 Nathan Froyd
2009-08-03 14:45 ` [Qemu-devel] [PATCH 3/6] add implementation of MIPS semihosting Nathan Froyd

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090720152420.GF26319@codesourcery.com \
    --to=froydnj@codesourcery.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.