@@ -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_ */
@@ -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;
new file mode 100644
@@ -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_ */
new file mode 100644
@@ -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_ */
new file mode 100644
@@ -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_ */
new file mode 100644
@@ -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_ */
@@ -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)
{
new file mode 100644
@@ -0,0 +1 @@
+# Default configuration for mips-bsd-user
new file mode 100644
@@ -0,0 +1 @@
+# Default configuration for mips64-bsd-user
new file mode 100644
@@ -0,0 +1 @@
+# Default configuration for mips64el-bsd-user
new file mode 100644
@@ -0,0 +1 @@
+# Default configuration for mipsel-bsd-user
@@ -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
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 <sson@FreeBSD.org> --- 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