From 49abcdddf671603675bc368d989c059d804d800e Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Sat, 25 May 2013 22:58:57 -0500 Subject: [PATCH 02/23] bsd-user: add initial support for mips/mips64 To: Cc: 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 --- 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 #include #include +#include #include #include @@ -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 . + */ +#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 . + */ +#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 . + */ +#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 . + */ +#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