Patchwork [02/23] bsd-user: add initial support for mips/mips64

login
register
mail settings
Submitter Stacey Son
Date June 24, 2013, 2:03 a.m.
Message ID <1372039435-41921-3-git-send-email-sson@FreeBSD.org>
Download mbox | patch
Permalink /patch/253916/
State New
Headers show

Comments

Stacey Son - June 24, 2013, 2:03 a.m.
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
Peter Maydell - June 24, 2013, 5:15 p.m.
On 24 June 2013 03:03, Stacey Son <sson@freebsd.org> wrote:
> Add the main cpu loop, cpu_loop(), for mips and mips64 architecture.  Set the
> cpu model. Add some stubs for future code.
>
> --- 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)

I suspect you'd do better in the long term to restructure
to pull cpu_loop out into a per-architecture source file
and avoid the ifdefs. (This is something I'd like to do to
the linux-user/ code, which is currently even more ifdef-ridden
than bsd-user/.)

> --- 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

This looks a little fishy -- could you give some rationale?
Why does only BSD need to do this? Why do you need to
change the TARGET_PHYS_ADDR_SPACE_BITS for a -user target?
Where do the numbers come from?

thanks
-- PMM
Stacey Son - June 24, 2013, 8:09 p.m.
On Jun 24, 2013, at 12:15 PM, Peter Maydell wrote:

>> 
>> +#if defined(TARGET_MIPS)
>> +
>> +/* Compare to sys/mips/mips/trap.c */
>> +
>> +void cpu_loop(CPUMIPSState *env)
> 
> I suspect you'd do better in the long term to restructure
> to pull cpu_loop out into a per-architecture source file
> and avoid the ifdefs. (This is something I'd like to do to
> the linux-user/ code, which is currently even more ifdef-ridden
> than bsd-user/.)


Yes, the cpu_loop()'s and the cpu initialization code is actually separated out in the arm arch patch for all the arch's.

> 
>> --- 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
> 
> This looks a little fishy -- could you give some rationale?
> Why does only BSD need to do this? Why do you need to
> change the TARGET_PHYS_ADDR_SPACE_BITS for a -user target?
> Where do the numbers come from?


If I remember correctly these:

>> +#  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

come from the See Mips Run book.

The reason they were changed for the bsd-user is FreeBSD puts the text segment in something like 0x12000000 (plus or minus a zero) and the stack at 0x8000000000 (- minus a page or two) for mips64 which didn't work as defined originally.

-stacey.

Patch

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