qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 02/23] bsd-user: add initial support for mips/mips64


From: Stacey Son
Subject: [Qemu-devel] [PATCH 02/23] bsd-user: add initial support for mips/mips64
Date: Sun, 23 Jun 2013 21:03:34 -0500

Add the main cpu loop, cpu_loop(), for mips and mips64 architecture.  Set the
cpu model. Add some stubs for future code.

Signed-off-by: Stacey Son <address@hidden>
---
 bsd-user/errno_defs.h                 |    5 +
 bsd-user/main.c                       |  189 +++++++++++++++++++++++++++++++++
 bsd-user/mips/syscall.h               |   42 +++++++
 bsd-user/mips/target_signal.h         |   38 +++++++
 bsd-user/mips64/syscall.h             |   42 +++++++
 bsd-user/mips64/target_signal.h       |   38 +++++++
 bsd-user/syscall.c                    |    8 ++
 default-configs/mips-bsd-user.mak     |    1 +
 default-configs/mips64-bsd-user.mak   |    1 +
 default-configs/mips64el-bsd-user.mak |    1 +
 default-configs/mipsel-bsd-user.mak   |    1 +
 target-mips/mips-defs.h               |   13 ++-
 12 files changed, 377 insertions(+), 2 deletions(-)
 create mode 100644 bsd-user/mips/syscall.h
 create mode 100644 bsd-user/mips/target_signal.h
 create mode 100644 bsd-user/mips64/syscall.h
 create mode 100644 bsd-user/mips64/target_signal.h
 create mode 100644 default-configs/mips-bsd-user.mak
 create mode 100644 default-configs/mips64-bsd-user.mak
 create mode 100644 default-configs/mips64el-bsd-user.mak
 create mode 100644 default-configs/mipsel-bsd-user.mak

diff --git a/bsd-user/errno_defs.h b/bsd-user/errno_defs.h
index fcf95d3..f01181d 100644
--- a/bsd-user/errno_defs.h
+++ b/bsd-user/errno_defs.h
@@ -148,4 +148,9 @@
 #define TARGET_ENOMSG           90              /* No message of desired type 
*/
 #define TARGET_ELAST            90              /* Must be equal largest errno 
*/
 
+/* Internal errors: */
+#define TARGET_EJUSTRETURN      254             /* Just return without
+                                                   modifing regs */
+#define TARGET_ERESTART         255             /* Restart syscall */
+
 #endif /* !  _ERRNO_DEFS_H_ */
diff --git a/bsd-user/main.c b/bsd-user/main.c
index 572aa14..e64a3ba 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -2,6 +2,7 @@
  *  qemu user main
  *
  *  Copyright (c) 2003-2008 Fabrice Bellard
+ *  Copyright (c) 2013 Stacey Son
  *
  *  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
@@ -23,6 +24,7 @@
 #include <errno.h>
 #include <unistd.h>
 #include <machine/trap.h>
+#include <sys/syscall.h>
 #include <sys/types.h>
 #include <sys/mman.h>
 
@@ -387,6 +389,172 @@ void cpu_loop(CPUX86State *env)
 }
 #endif
 
+#if defined(TARGET_MIPS)
+
+/* Compare to sys/mips/mips/trap.c */
+
+void cpu_loop(CPUMIPSState *env)
+{
+#if 0 /* not yet */
+    target_siginfo_t info;
+#endif
+    int trapnr;
+    abi_long ret;
+    unsigned int syscall_num;
+
+    for (;;) {
+        cpu_exec_start(env);
+        trapnr = cpu_mips_exec(env);
+        cpu_exec_end(env);
+        switch (trapnr) {
+        case EXCP_SYSCALL: /* syscall exception */
+            syscall_num = env->active_tc.gpr[2]; /* v0 */
+            env->active_tc.PC += TARGET_INSN_SIZE;
+            if (syscall_num >= SYS_MAXSYSCALL) {
+                ret = -TARGET_ENOSYS;
+            } else {
+                if (SYS_syscall == syscall_num ||
+                    SYS___syscall == syscall_num) {
+#if defined(TARGET_MIPS64)
+                    ret = do_freebsd_syscall(env,
+                        env->active_tc.gpr[4],/* syscall #*/
+                        env->active_tc.gpr[5], /* arg0 */
+                        env->active_tc.gpr[6], /* arg1 */
+                        env->active_tc.gpr[7], /* arg2 */
+                        env->active_tc.gpr[8], /* arg3 */
+                        env->active_tc.gpr[9], /* arg4 */
+                        env->active_tc.gpr[10],/* arg5 */
+                        env->active_tc.gpr[11],/* arg6 */
+                        0 /* no arg 7 */);
+                } else {
+                    ret = do_freebsd_syscall(env,
+                        syscall_num,
+                        env->active_tc.gpr[4],
+                        env->active_tc.gpr[5],
+                        env->active_tc.gpr[6],
+                        env->active_tc.gpr[7],
+                        env->active_tc.gpr[8],
+                        env->active_tc.gpr[9],
+                        env->active_tc.gpr[10],
+                        env->active_tc.gpr[11]
+                        );
+
+#else /* ! TARGET_MIPS64 */
+                    /* indirect syscall */
+                    ret = do_freebsd_syscall(env,
+                        env->active_tc.gpr[4],/* syscall #*/
+                        env->active_tc.gpr[5], /* a1/arg0 */
+                        env->active_tc.gpr[6], /* a2/arg1 */
+                        env->active_tc.gpr[7], /* a3/arg2 */
+                        env->active_tc.gpr[12],/* t4/arg3 */
+                        env->active_tc.gpr[13],/* t5/arg4 */
+                        env->active_tc.gpr[14],/* t6/arg5 */
+                        env->active_tc.gpr[15],/* t7/arg6 */
+                        0  /* no arg7 */
+                        );
+
+                } else {
+                    /* direct syscall */
+                    ret = do_freebsd_syscall(env,
+                        syscall_num,
+                        env->active_tc.gpr[4], /* a0/arg0 */
+                        env->active_tc.gpr[5], /* a1/arg1 */
+                        env->active_tc.gpr[6], /* a2/arg2 */
+                        env->active_tc.gpr[7], /* a3/arg3 */
+                        env->active_tc.gpr[12],/* t4/arg4 */
+                        env->active_tc.gpr[13],/* t5/arg5 */
+                        env->active_tc.gpr[14],/* t6/arg6 */
+                        env->active_tc.gpr[15] /* t7/arg7 */
+                        );
+#endif /* ! TARGET_MIPS64 */
+                }
+            }
+
+            /* Compare to mips/mips/vm_machdep.c  cpu_set_syscall_retval() */
+            if (-TARGET_EJUSTRETURN == ret) {
+                /*
+                 * Returning from a successful sigreturn
+                 * syscall.  Avoid clobbering register state.
+                 */
+                break;
+            }
+            if (-TARGET_ERESTART == ret) {
+                /* Backup the pc to point at the swi. */
+                env->active_tc.PC -= TARGET_INSN_SIZE;
+                break;
+            }
+            if ((unsigned int)ret >= (unsigned int)(-1133)) {
+                env->active_tc.gpr[7] = 1;
+                ret = -ret;
+            } else {
+                env->active_tc.gpr[7] = 0;
+            }
+            env->active_tc.gpr[2] = ret; /* v0 <- ret */
+            break;
+
+#if 0 /* not yet */
+        case EXCP_TLBL: /* TLB miss on load */
+        case EXCP_TLBS: /* TLB miss on store */
+        case EXCP_AdEL: /* bad address on load */
+        case EXCP_AdES: /* bad address on store */
+            info.target_si_signo = TARGET_SIGSEGV;
+            info.target_si_errno = 0;
+            /* XXX: check env->error_code */
+            info.target_si_code = TARGET_SEGV_MAPERR;
+            info.target_si_addr = env->CP0_BadVAddr;
+            queue_signal(env, info.si_signo, &info);
+            break;
+
+        case EXCP_CpU: /* coprocessor unusable */
+        case EXCP_RI:  /* reserved instruction */
+            info.target_si_signo = TARGET_SIGILL;
+            info.target_si_errno = 0;
+            info.target_si_code = 0;
+            queue_signal(env, info.target_si_signo, &info);
+            break;
+#endif /* not yet */
+
+        case EXCP_INTERRUPT: /* async interrupt */
+            /* just indicate that signals should be handled asap */
+            break;
+
+#if 0 /* not yet */
+        case EXCP_DEBUG: /* cpu stopped after a breakpoint */
+            {
+                int sig;
+
+                sig = gdb_handlesig(env, TARGET_SIGTRAP);
+                if (sig) {
+                    info.target_si_signo = sig;
+                    info.target_si_errno = 0;
+                    info.target_si_code = TARGET_TRAP_BRKPT;
+                    queue_signal(env, info.target_si_signo, &info);
+                }
+            }
+            break;
+
+        case EXCP_SC:
+            if (do_store_exclusive(env)) {
+                info.target_si_signo = TARGET_SIGSEGV;
+                info.target_si_errno = 0;
+                info.target_si_code = TARGET_SEGV_MAPERR;
+                info.target_si_addr = env->active_tc.PC;
+                queue_signal(env, info.target_si_signo, &info);
+            }
+            break;
+#endif /* not yet */
+
+        default:
+            fprintf(stderr, "qemu: unhandled CPU exception "
+                "0x%x - aborting\n", trapnr);
+            cpu_dump_state(env, stderr, fprintf, 0);
+            abort();
+        }
+        process_pending_signals(env);
+    }
+}
+#endif /* TARGET_MIPS */
+
 #ifdef TARGET_SPARC
 #define SPARC64_STACK_BIAS 2047
 
@@ -892,6 +1060,12 @@ int main(int argc, char **argv)
 #else
         cpu_model = "qemu32";
 #endif
+#elif defined(TARGET_MIPS)
+#if defined(TARGET_MIPS) || defined(TARGET_MIPS64)
+        cpu_model = "20Kc";
+#else
+        cpu_model = "24Kf";
+#endif
 #elif defined(TARGET_SPARC)
 #ifdef TARGET_SPARC64
         cpu_model = "TI UltraSparc II";
@@ -1116,6 +1290,21 @@ int main(int argc, char **argv)
     cpu_x86_load_seg(env, R_FS, 0);
     cpu_x86_load_seg(env, R_GS, 0);
 #endif
+#elif defined(TARGET_MIPS)
+    {
+        int i;
+
+        for (i = 0; i < 32; i++) {
+            env->active_tc.gpr[i] = regs->regs[i];
+        }
+        env->active_tc.PC = regs->cp0_epc & ~(target_ulong)1;
+        if (regs->cp0_epc & 1) {
+            env->hflags |= MIPS_HFLAG_M16;
+        }
+#if defined(TARGET_MIPS64)
+        env->hflags |= MIPS_HFLAG_UX | MIPS_HFLAG_64;
+#endif
+    }
 #elif defined(TARGET_SPARC)
     {
         int i;
diff --git a/bsd-user/mips/syscall.h b/bsd-user/mips/syscall.h
new file mode 100644
index 0000000..149970a
--- /dev/null
+++ b/bsd-user/mips/syscall.h
@@ -0,0 +1,42 @@
+/*
+ *  mips system call definitions
+ *
+ *
+ *  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/>.
+ */
+#ifndef _MIPS_SYSCALL_H_
+#define _MIPS_SYSCALL_H_
+
+/*
+ * struct target_pt_regs defines the way the registers are stored on the stack
+ * during a system call.
+ */
+
+struct target_pt_regs {
+    /* Saved main processor registers. */
+    abi_ulong regs[32];
+
+    /* Saved special registers. */
+    abi_ulong cp0_status;
+    abi_ulong lo;
+    abi_ulong hi;
+    abi_ulong cp0_badvaddr;
+    abi_ulong cp0_cause;
+    abi_ulong cp0_epc;
+};
+
+
+#define UNAME_MACHINE "mips"
+
+#endif /* !_MIPS_SYSCALL_H_ */
diff --git a/bsd-user/mips/target_signal.h b/bsd-user/mips/target_signal.h
new file mode 100644
index 0000000..8ac3a2f
--- /dev/null
+++ b/bsd-user/mips/target_signal.h
@@ -0,0 +1,38 @@
+/*
+ *  mips signal definitions
+ *
+ *
+ *  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/>.
+ */
+#ifndef _MIPS_TARGET_SIGNAL_H_
+#define _MIPS_TARGET_SIGNAL_H_
+
+#include "cpu.h"
+
+#define TARGET_INSN_SIZE    4       /* mips instruction size */
+
+/* this struct defines a stack used during syscall handling */
+
+typedef struct target_sigaltstack {
+    abi_ulong ss_sp;
+    abi_long ss_flags;
+    abi_ulong ss_size;
+} target_stack_t;
+
+static inline abi_ulong get_sp_from_cpustate(CPUMIPSState *state)
+{
+    return state->active_tc.gpr[29];
+}
+
+#endif /* !_MIP64_TARGET_SIGNAL_H_ */
diff --git a/bsd-user/mips64/syscall.h b/bsd-user/mips64/syscall.h
new file mode 100644
index 0000000..300ed9b
--- /dev/null
+++ b/bsd-user/mips64/syscall.h
@@ -0,0 +1,42 @@
+/*
+ *  mips64 system call definitions
+ *
+ *
+ *  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/>.
+ */
+#ifndef _MIPS64_SYSCALL_H_
+#define _MIPS64_SYSCALL_H_
+
+/*
+ * struct target_pt_regs defines the way the registers are stored on the stack
+ * during a system call.
+ */
+
+struct target_pt_regs {
+    /* Saved main processor registers. */
+    abi_ulong regs[32];
+
+    /* Saved special registers. */
+    abi_ulong cp0_status;
+    abi_ulong lo;
+    abi_ulong hi;
+    abi_ulong cp0_badvaddr;
+    abi_ulong cp0_cause;
+    abi_ulong cp0_epc;
+};
+
+
+#define UNAME_MACHINE "mips64"
+
+#endif /* !_MIPS64_SYSCALL_H_ */
diff --git a/bsd-user/mips64/target_signal.h b/bsd-user/mips64/target_signal.h
new file mode 100644
index 0000000..fc8674d
--- /dev/null
+++ b/bsd-user/mips64/target_signal.h
@@ -0,0 +1,38 @@
+/*
+ *  mips64 signal definitions
+ *
+ *
+ *  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/>.
+ */
+#ifndef _MIPS64_TARGET_SIGNAL_H_
+#define _MIPS64_TARGET_SIGNAL_H_
+
+#include "cpu.h"
+
+#define TARGET_INSN_SIZE        4       /* mips64 instruction size */
+
+/* this struct defines a stack used during syscall handling */
+
+typedef struct target_sigaltstack {
+    abi_ulong ss_sp;
+    abi_long ss_flags;
+    abi_ulong ss_size;
+} target_stack_t;
+
+static inline abi_ulong get_sp_from_cpustate(CPUMIPSState *state)
+{
+    return state->active_tc.gpr[29];
+}
+
+#endif /* !_MIP64_TARGET_SIGNAL_H_ */
diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
index 8e8107b..02740d5 100644
--- a/bsd-user/syscall.c
+++ b/bsd-user/syscall.c
@@ -146,6 +146,14 @@ static abi_long do_freebsd_sysarch(CPUX86State *env, int 
op, abi_ulong parms)
 }
 #endif
 
+#ifdef TARGET_MIPS
+static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms)
+{
+
+    return -TARGET_EINVAL;
+}
+#endif /* TARGET_MIPS */
+
 #ifdef TARGET_SPARC
 static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms)
 {
diff --git a/default-configs/mips-bsd-user.mak 
b/default-configs/mips-bsd-user.mak
new file mode 100644
index 0000000..3fb129a
--- /dev/null
+++ b/default-configs/mips-bsd-user.mak
@@ -0,0 +1 @@
+# Default configuration for mips-bsd-user
diff --git a/default-configs/mips64-bsd-user.mak 
b/default-configs/mips64-bsd-user.mak
new file mode 100644
index 0000000..d4e72a6
--- /dev/null
+++ b/default-configs/mips64-bsd-user.mak
@@ -0,0 +1 @@
+# Default configuration for mips64-bsd-user
diff --git a/default-configs/mips64el-bsd-user.mak 
b/default-configs/mips64el-bsd-user.mak
new file mode 100644
index 0000000..b879228
--- /dev/null
+++ b/default-configs/mips64el-bsd-user.mak
@@ -0,0 +1 @@
+# Default configuration for mips64el-bsd-user
diff --git a/default-configs/mipsel-bsd-user.mak 
b/default-configs/mipsel-bsd-user.mak
new file mode 100644
index 0000000..312b9d5
--- /dev/null
+++ b/default-configs/mipsel-bsd-user.mak
@@ -0,0 +1 @@
+# Default configuration for mipsel-bsd-user
diff --git a/target-mips/mips-defs.h b/target-mips/mips-defs.h
index bf094a3..7ec9d20 100644
--- a/target-mips/mips-defs.h
+++ b/target-mips/mips-defs.h
@@ -10,8 +10,17 @@
 
 #if defined(TARGET_MIPS64)
 #define TARGET_LONG_BITS 64
-#define TARGET_PHYS_ADDR_SPACE_BITS 36
-#define TARGET_VIRT_ADDR_SPACE_BITS 42
+#  if defined(CONFIG_BSD) && defined(CONFIG_USER_ONLY)
+#    define TARGET_PHYS_ADDR_SPACE_BITS 59
+#    ifdef TARGET_ABI32
+#       define TARGET_VIRT_ADDR_SPACE_BITS 32
+#    else
+#       define TARGET_VIRT_ADDR_SPACE_BITS 62
+#    endif
+#  else
+#    define TARGET_PHYS_ADDR_SPACE_BITS 36
+#    define TARGET_VIRT_ADDR_SPACE_BITS 42
+#  endif
 #else
 #define TARGET_LONG_BITS 32
 #define TARGET_PHYS_ADDR_SPACE_BITS 36
-- 
1.7.8




reply via email to

[Prev in Thread] Current Thread [Next in Thread]