summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjmallett <jmallett@FreeBSD.org>2012-03-03 08:19:18 +0000
committerjmallett <jmallett@FreeBSD.org>2012-03-03 08:19:18 +0000
commit50c253779ff59b0d64f2cfbb7efedabe19a620d8 (patch)
tree84d0a513be42586ec703acf6b5a531bc9d48d09c
parent402a0f9de41a1a087445529e59d3183a11d266b9 (diff)
downloadFreeBSD-src-50c253779ff59b0d64f2cfbb7efedabe19a620d8.zip
FreeBSD-src-50c253779ff59b0d64f2cfbb7efedabe19a620d8.tar.gz
o) Add COMPAT_FREEBSD32 support for MIPS kernels using the n64 ABI with userlands
using the o32 ABI. This mostly follows nwhitehorn's lead in implementing COMPAT_FREEBSD32 on powerpc64. o) Add a new type to the freebsd32 compat layer, time32_t, which is time_t in the 32-bit ABI being used. Since the MIPS port is relatively-new, even the 32-bit ABIs use a 64-bit time_t. o) Because time{spec,val}32 has the same size and layout as time{spec,val} on MIPS with 32-bit compatibility, then, disable some code which assumes otherwise wrongly when built for MIPS. A more general macro to check in this case would seem like a good idea eventually. If someone adds support for using n32 userland with n64 kernels on MIPS, then they will have to add a variety of flags related to each piece of the ABI that can vary. That's probably the right time to generalize further. o) Add MIPS to the list of architectures which use PAD64_REQUIRED in the freebsd32 compat code. Probably this should be generalized at some point. Reviewed by: gonzo
-rw-r--r--sys/compat/freebsd32/freebsd32.h13
-rw-r--r--sys/compat/freebsd32/freebsd32_misc.c6
-rw-r--r--sys/compat/freebsd32/freebsd32_proto.h14
-rw-r--r--sys/compat/freebsd32/freebsd32_syscall.h2
-rw-r--r--sys/compat/freebsd32/freebsd32_syscalls.c4
-rw-r--r--sys/compat/freebsd32/freebsd32_sysent.c4
-rw-r--r--sys/compat/freebsd32/freebsd32_systrace_args.c6
-rw-r--r--sys/compat/freebsd32/syscalls.master2
-rw-r--r--sys/conf/files.mips7
-rw-r--r--sys/conf/options.mips3
-rw-r--r--sys/kern/kern_tc.c2
-rw-r--r--sys/mips/include/elf.h3
-rw-r--r--sys/mips/include/md_var.h6
-rw-r--r--sys/mips/include/param.h6
-rw-r--r--sys/mips/include/proc.h1
-rw-r--r--sys/mips/include/reg.h31
-rw-r--r--sys/mips/include/sigframe.h18
-rw-r--r--sys/mips/include/ucontext.h30
-rw-r--r--sys/mips/include/vmparam.h5
-rw-r--r--sys/mips/mips/freebsd32_machdep.c496
-rw-r--r--sys/mips/mips/genassym.c3
-rw-r--r--sys/mips/mips/swtch.S19
-rw-r--r--sys/mips/mips/trap.c117
-rw-r--r--sys/mips/mips/vm_machdep.c14
-rw-r--r--sys/net/bpf.c14
-rw-r--r--sys/sys/sysctl.h3
26 files changed, 761 insertions, 68 deletions
diff --git a/sys/compat/freebsd32/freebsd32.h b/sys/compat/freebsd32/freebsd32.h
index 1d8f149..e263f0d 100644
--- a/sys/compat/freebsd32/freebsd32.h
+++ b/sys/compat/freebsd32/freebsd32.h
@@ -42,8 +42,17 @@
#define PTROUT_CP(src,dst,fld) \
do { (dst).fld = PTROUT((src).fld); } while (0)
+/*
+ * Being a newer port, 32-bit FreeBSD/MIPS uses 64-bit time_t.
+ */
+#ifdef __mips__
+typedef int64_t time32_t;
+#else
+typedef int32_t time32_t;
+#endif
+
struct timeval32 {
- int32_t tv_sec;
+ time32_t tv_sec;
int32_t tv_usec;
};
#define TV_CP(src,dst,fld) do { \
@@ -52,7 +61,7 @@ struct timeval32 {
} while (0)
struct timespec32 {
- int32_t tv_sec;
+ time32_t tv_sec;
int32_t tv_nsec;
};
#define TS_CP(src,dst,fld) do { \
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
index aff280a..3938e99 100644
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -104,16 +104,22 @@ __FBSDID("$FreeBSD$");
#include <compat/freebsd32/freebsd32_signal.h>
#include <compat/freebsd32/freebsd32_proto.h>
+#ifndef __mips__
CTASSERT(sizeof(struct timeval32) == 8);
CTASSERT(sizeof(struct timespec32) == 8);
CTASSERT(sizeof(struct itimerval32) == 16);
+#endif
CTASSERT(sizeof(struct statfs32) == 256);
+#ifndef __mips__
CTASSERT(sizeof(struct rusage32) == 72);
+#endif
CTASSERT(sizeof(struct sigaltstack32) == 12);
CTASSERT(sizeof(struct kevent32) == 20);
CTASSERT(sizeof(struct iovec32) == 8);
CTASSERT(sizeof(struct msghdr32) == 28);
+#ifndef __mips__
CTASSERT(sizeof(struct stat32) == 96);
+#endif
CTASSERT(sizeof(struct sigaction32) == 24);
static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
diff --git a/sys/compat/freebsd32/freebsd32_proto.h b/sys/compat/freebsd32/freebsd32_proto.h
index 1d6310b..48c6f2e 100644
--- a/sys/compat/freebsd32/freebsd32_proto.h
+++ b/sys/compat/freebsd32/freebsd32_proto.h
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 227691 2011-11-19 06:35:15Z ed
+ * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 227776 2011-11-21 01:26:10Z lstewart
*/
#ifndef _FREEBSD32_SYSPROTO_H_
@@ -33,7 +33,7 @@ struct thread;
#define PADR_(t) 0
#endif
-#if !defined(PAD64_REQUIRED) && defined(__powerpc__)
+#if !defined(PAD64_REQUIRED) && (defined(__powerpc__) || defined(__mips__))
#define PAD64_REQUIRED
#endif
struct freebsd32_wait4_args {
@@ -589,7 +589,7 @@ struct freebsd32_posix_fadvise_args {
char len2_l_[PADL_(uint32_t)]; uint32_t len2; char len2_r_[PADR_(uint32_t)];
char advice_l_[PADL_(int)]; int advice; char advice_r_[PADR_(int)];
};
-#if !defined(PAD64_REQUIRED) && defined(__powerpc__)
+#if !defined(PAD64_REQUIRED) && (defined(__powerpc__) || defined(__mips__))
#define PAD64_REQUIRED
#endif
int freebsd32_wait4(struct thread *, struct freebsd32_wait4_args *);
@@ -703,7 +703,7 @@ int freebsd32_posix_fadvise(struct thread *, struct freebsd32_posix_fadvise_args
#ifdef COMPAT_43
-#if !defined(PAD64_REQUIRED) && defined(__powerpc__)
+#if !defined(PAD64_REQUIRED) && (defined(__powerpc__) || defined(__mips__))
#define PAD64_REQUIRED
#endif
struct ofreebsd32_lseek_args {
@@ -789,7 +789,7 @@ int ofreebsd32_getdirentries(struct thread *, struct ofreebsd32_getdirentries_ar
#ifdef COMPAT_FREEBSD4
-#if !defined(PAD64_REQUIRED) && defined(__powerpc__)
+#if !defined(PAD64_REQUIRED) && (defined(__powerpc__) || defined(__mips__))
#define PAD64_REQUIRED
#endif
struct freebsd4_freebsd32_getfsstat_args {
@@ -846,7 +846,7 @@ int freebsd4_freebsd32_sigreturn(struct thread *, struct freebsd4_freebsd32_sigr
#ifdef COMPAT_FREEBSD6
-#if !defined(PAD64_REQUIRED) && defined(__powerpc__)
+#if !defined(PAD64_REQUIRED) && (defined(__powerpc__) || defined(__mips__))
#define PAD64_REQUIRED
#endif
struct freebsd6_freebsd32_pread_args {
@@ -912,7 +912,7 @@ int freebsd6_freebsd32_ftruncate(struct thread *, struct freebsd6_freebsd32_ftru
#ifdef COMPAT_FREEBSD7
-#if !defined(PAD64_REQUIRED) && defined(__powerpc__)
+#if !defined(PAD64_REQUIRED) && (defined(__powerpc__) || defined(__mips__))
#define PAD64_REQUIRED
#endif
struct freebsd7_freebsd32_semctl_args {
diff --git a/sys/compat/freebsd32/freebsd32_syscall.h b/sys/compat/freebsd32/freebsd32_syscall.h
index d21b583..ad3d986 100644
--- a/sys/compat/freebsd32/freebsd32_syscall.h
+++ b/sys/compat/freebsd32/freebsd32_syscall.h
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 227691 2011-11-19 06:35:15Z ed
+ * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 227776 2011-11-21 01:26:10Z lstewart
*/
#define FREEBSD32_SYS_syscall 0
diff --git a/sys/compat/freebsd32/freebsd32_syscalls.c b/sys/compat/freebsd32/freebsd32_syscalls.c
index c58a414..faba864 100644
--- a/sys/compat/freebsd32/freebsd32_syscalls.c
+++ b/sys/compat/freebsd32/freebsd32_syscalls.c
@@ -3,11 +3,11 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 227691 2011-11-19 06:35:15Z ed
+ * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 227776 2011-11-21 01:26:10Z lstewart
*/
const char *freebsd32_syscallnames[] = {
-#if !defined(PAD64_REQUIRED) && defined(__powerpc__)
+#if !defined(PAD64_REQUIRED) && (defined(__powerpc__) || defined(__mips__))
#define PAD64_REQUIRED
#endif
"syscall", /* 0 = syscall */
diff --git a/sys/compat/freebsd32/freebsd32_sysent.c b/sys/compat/freebsd32/freebsd32_sysent.c
index 4371d16..590ed41 100644
--- a/sys/compat/freebsd32/freebsd32_sysent.c
+++ b/sys/compat/freebsd32/freebsd32_sysent.c
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 227691 2011-11-19 06:35:15Z ed
+ * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 227776 2011-11-21 01:26:10Z lstewart
*/
#include "opt_compat.h"
@@ -44,7 +44,7 @@
/* The casts are bogus but will do for now. */
struct sysent freebsd32_sysent[] = {
-#if !defined(PAD64_REQUIRED) && defined(__powerpc__)
+#if !defined(PAD64_REQUIRED) && (defined(__powerpc__) || defined(__mips__))
#define PAD64_REQUIRED
#endif
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 0 = syscall */
diff --git a/sys/compat/freebsd32/freebsd32_systrace_args.c b/sys/compat/freebsd32/freebsd32_systrace_args.c
index 7f6bf68..13df961 100644
--- a/sys/compat/freebsd32/freebsd32_systrace_args.c
+++ b/sys/compat/freebsd32/freebsd32_systrace_args.c
@@ -11,7 +11,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
{
int64_t *iarg = (int64_t *) uarg;
switch (sysnum) {
-#if !defined(PAD64_REQUIRED) && defined(__powerpc__)
+#if !defined(PAD64_REQUIRED) && (defined(__powerpc__) || defined(__mips__))
#define PAD64_REQUIRED
#endif
/* nosys */
@@ -3077,7 +3077,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
{
const char *p = NULL;
switch (sysnum) {
-#if !defined(PAD64_REQUIRED) && defined(__powerpc__)
+#if !defined(PAD64_REQUIRED) && (defined(__powerpc__) || defined(__mips__))
#define PAD64_REQUIRED
#endif
/* nosys */
@@ -8192,7 +8192,7 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
{
const char *p = NULL;
switch (sysnum) {
-#if !defined(PAD64_REQUIRED) && defined(__powerpc__)
+#if !defined(PAD64_REQUIRED) && (defined(__powerpc__) || defined(__mips__))
#define PAD64_REQUIRED
#endif
/* nosys */
diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master
index b80fd9c..11476ed 100644
--- a/sys/compat/freebsd32/syscalls.master
+++ b/sys/compat/freebsd32/syscalls.master
@@ -52,7 +52,7 @@
#include <compat/freebsd32/freebsd32.h>
#include <compat/freebsd32/freebsd32_proto.h>
-#if !defined(PAD64_REQUIRED) && defined(__powerpc__)
+#if !defined(PAD64_REQUIRED) && (defined(__powerpc__) || defined(__mips__))
#define PAD64_REQUIRED
#endif
diff --git a/sys/conf/files.mips b/sys/conf/files.mips
index b5062ae..f148cbf 100644
--- a/sys/conf/files.mips
+++ b/sys/conf/files.mips
@@ -90,6 +90,13 @@ libkern/umoddi3.c optional isa_mips32
#libkern/mips/strcmp.S standard
#libkern/mips/strncmp.S standard
+compat/freebsd32/freebsd32_ioctl.c optional compat_freebsd32
+compat/freebsd32/freebsd32_misc.c optional compat_freebsd32
+compat/freebsd32/freebsd32_syscalls.c optional compat_freebsd32
+compat/freebsd32/freebsd32_sysent.c optional compat_freebsd32
+kern/imgact_elf32.c optional compat_freebsd32
+mips/mips/freebsd32_machdep.c optional compat_freebsd32
+
kern/kern_clocksource.c standard
kern/link_elf_obj.c standard
diff --git a/sys/conf/options.mips b/sys/conf/options.mips
index 0384283..4cf9344 100644
--- a/sys/conf/options.mips
+++ b/sys/conf/options.mips
@@ -38,6 +38,7 @@ CPU_CNMIPS opt_global.h
CPU_RMI opt_global.h
CPU_NLM opt_global.h
+# XXX These are bogus and should be replaced by proper ABI or ISA checks.
ISA_MIPS1 opt_cputype.h
ISA_MIPS3 opt_cputype.h
ISA_MIPS32 opt_cputype.h
@@ -45,6 +46,8 @@ ISA_MIPS32v2 opt_cputype.h
ISA_MIPS64 opt_cputype.h
ISA_MIPS64v2 opt_cputype.h
+COMPAT_FREEBSD32 opt_compat.h
+
YAMON opt_global.h
CFE opt_global.h
CFE_CONSOLE opt_global.h
diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c
index 8f08df5..e272fdd 100644
--- a/sys/kern/kern_tc.c
+++ b/sys/kern/kern_tc.c
@@ -123,6 +123,7 @@ static void cpu_tick_calibrate(int);
static int
sysctl_kern_boottime(SYSCTL_HANDLER_ARGS)
{
+#ifndef __mips__
#ifdef SCTL_MASK32
int tv[2];
@@ -132,6 +133,7 @@ sysctl_kern_boottime(SYSCTL_HANDLER_ARGS)
return SYSCTL_OUT(req, tv, sizeof(tv));
} else
#endif
+#endif
return SYSCTL_OUT(req, &boottime, sizeof(boottime));
}
diff --git a/sys/mips/include/elf.h b/sys/mips/include/elf.h
index 39efeee..1c3d44d 100644
--- a/sys/mips/include/elf.h
+++ b/sys/mips/include/elf.h
@@ -52,6 +52,9 @@
#include <sys/elf_generic.h>
#define ELF_ARCH EM_MIPS
+#if __ELF_WORD_SIZE == 32
+#define ELF_ARCH32 EM_MIPS
+#endif
#define ELF_MACHINE_OK(x) ((x) == EM_MIPS || (x) == EM_MIPS_RS4_BE)
/* Architecture dependent Segment types - p_type */
diff --git a/sys/mips/include/md_var.h b/sys/mips/include/md_var.h
index 6f65a0f..00ff95a 100644
--- a/sys/mips/include/md_var.h
+++ b/sys/mips/include/md_var.h
@@ -41,7 +41,11 @@
*/
extern long Maxmem;
extern char sigcode[];
-extern int szsigcode, szosigcode;
+extern int szsigcode;
+#if defined(__mips_n32) || defined(__mips_n64)
+extern char sigcode32[];
+extern int szsigcode32;
+#endif
extern uint32_t *vm_page_dump;
extern int vm_page_dump_size;
diff --git a/sys/mips/include/param.h b/sys/mips/include/param.h
index 608d802..bd6d800 100644
--- a/sys/mips/include/param.h
+++ b/sys/mips/include/param.h
@@ -60,6 +60,9 @@
#if _BYTE_ORDER == _BIG_ENDIAN
#ifdef __mips_n64
#define MACHINE_ARCH "mips64eb"
+#ifndef MACHINE_ARCH32
+#define MACHINE_ARCH32 "mipseb"
+#endif
#elif defined(__mips_n32)
#define MACHINE_ARCH "mipsn32eb"
#else
@@ -68,6 +71,9 @@
#else
#ifdef __mips_n64
#define MACHINE_ARCH "mips64el"
+#ifndef MACHINE_ARCH32
+#define MACHINE_ARCH32 "mipsel"
+#endif
#elif defined(__mips_n32)
#define MACHINE_ARCH "mipsn32el"
#else
diff --git a/sys/mips/include/proc.h b/sys/mips/include/proc.h
index beba9167..42d08d9 100644
--- a/sys/mips/include/proc.h
+++ b/sys/mips/include/proc.h
@@ -96,6 +96,7 @@ struct syscall_args {
#ifdef __mips_n64
#define KINFO_PROC_SIZE 1088
+#define KINFO_PROC32_SIZE 816
#else
#define KINFO_PROC_SIZE 816
#endif
diff --git a/sys/mips/include/reg.h b/sys/mips/include/reg.h
index 6510db6..c240506 100644
--- a/sys/mips/include/reg.h
+++ b/sys/mips/include/reg.h
@@ -42,6 +42,10 @@
#ifndef _MACHINE_REG_H_
#define _MACHINE_REG_H_
+#if defined(_KERNEL) && !defined(KLD_MODULE) && !defined(_STANDALONE)
+#include "opt_compat.h"
+#endif
+
/*
* Location of the users' stored registers relative to ZERO.
* must be visible to assembly code.
@@ -66,6 +70,21 @@ struct dbreg {
unsigned long junk;
};
+#ifdef COMPAT_FREEBSD32
+/* Must match struct trapframe */
+struct reg32 {
+ uint32_t r_regs[NUMSAVEREGS];
+};
+
+struct fpreg32 {
+ int32_t r_regs[NUMFPREGS];
+};
+
+struct dbreg32 {
+ uint32_t junk;
+};
+#endif
+
#ifdef _KERNEL
int fill_fpregs(struct thread *, struct fpreg *);
int fill_regs(struct thread *, struct reg *);
@@ -75,4 +94,16 @@ int fill_dbregs(struct thread *, struct dbreg *);
int set_dbregs(struct thread *, struct dbreg *);
#endif
+#ifdef COMPAT_FREEBSD32
+struct image_params;
+
+int fill_regs32(struct thread *, struct reg32 *);
+int set_regs32(struct thread *, struct reg32 *);
+int fill_fpregs32(struct thread *, struct fpreg32 *);
+int set_fpregs32(struct thread *, struct fpreg32 *);
+
+#define fill_dbregs32(td, reg) 0
+#define set_dbregs32(td, reg) 0
+#endif
+
#endif /* !_MACHINE_REG_H_ */
diff --git a/sys/mips/include/sigframe.h b/sys/mips/include/sigframe.h
index 6919882..69c7c02 100644
--- a/sys/mips/include/sigframe.h
+++ b/sys/mips/include/sigframe.h
@@ -32,6 +32,10 @@
#ifndef _MACHINE_SIGFRAME_H_
#define _MACHINE_SIGFRAME_H_
+#if defined(_KERNEL) && !defined(KLD_MODULE) && !defined(_STANDALONE)
+#include "opt_compat.h"
+#endif
+
/*
* WARNING: code in locore.s assumes the layout shown for sf_signum
* thru sf_addr so... don't alter them!
@@ -46,4 +50,18 @@ struct sigframe {
unsigned long __spare__[2];
};
+#if (defined(__mips_n32) || defined(__mips_n64)) && defined(COMPAT_FREEBSD32)
+#include <compat/freebsd32/freebsd32_signal.h>
+
+struct sigframe32 {
+ int32_t sf_signum;
+ int32_t sf_siginfo; /* code or pointer to sf_si */
+ int32_t sf_ucontext; /* points to sf_uc */
+ int32_t sf_addr; /* undocumented 4th arg */
+ ucontext32_t sf_uc; /* = *sf_ucontext */
+ struct siginfo32 sf_si; /* = *sf_siginfo (SA_SIGINFO case) */
+ uint32_t __spare__[2];
+};
+#endif
+
#endif /* !_MACHINE_SIGFRAME_H_ */
diff --git a/sys/mips/include/ucontext.h b/sys/mips/include/ucontext.h
index 72f07b4..aafd1dc 100644
--- a/sys/mips/include/ucontext.h
+++ b/sys/mips/include/ucontext.h
@@ -39,6 +39,10 @@
#ifndef _LOCORE
+#if defined(_KERNEL) && !defined(KLD_MODULE) && !defined(_STANDALONE)
+#include "opt_compat.h"
+#endif
+
typedef struct __mcontext {
/*
* These fields must match the corresponding fields in struct
@@ -56,6 +60,32 @@ typedef struct __mcontext {
void *mc_tls; /* pointer to TLS area */
int __spare__[8]; /* XXX reserved */
} mcontext_t;
+
+#if (defined(__mips_n32) || defined(__mips_n64)) && defined(COMPAT_FREEBSD32)
+#include <compat/freebsd32/freebsd32_signal.h>
+
+typedef struct __mcontext32 {
+ int mc_onstack;
+ int32_t mc_pc;
+ int32_t mc_regs[32];
+ int32_t sr;
+ int32_t mullo, mulhi;
+ int mc_fpused;
+ int32_t mc_fpregs[33];
+ int32_t mc_fpc_eir;
+ void *mc_tls;
+ int __spare__[8];
+} mcontext32_t;
+
+typedef struct __ucontext32 {
+ sigset_t uc_sigmask;
+ mcontext32_t uc_mcontext;
+ uint32_t uc_link;
+ struct sigaltstack32 uc_stack;
+ uint32_t uc_flags;
+ uint32_t __spare__[4];
+} ucontext32_t;
+#endif
#endif
#ifndef SZREG
diff --git a/sys/mips/include/vmparam.h b/sys/mips/include/vmparam.h
index 4a702f5..aa0a5d7 100644
--- a/sys/mips/include/vmparam.h
+++ b/sys/mips/include/vmparam.h
@@ -96,7 +96,10 @@
* offset is calculated.
*/
#define USRSTACK (VM_MAXUSER_ADDRESS - PAGE_SIZE)
-
+#ifdef __mips_n64
+#define FREEBSD32_USRSTACK (((vm_offset_t)0x80000000) - PAGE_SIZE)
+#endif
+
/*
* Only one memory domain.
*/
diff --git a/sys/mips/mips/freebsd32_machdep.c b/sys/mips/mips/freebsd32_machdep.c
new file mode 100644
index 0000000..3fe8991
--- /dev/null
+++ b/sys/mips/mips/freebsd32_machdep.c
@@ -0,0 +1,496 @@
+/*-
+ * Copyright (c) 2012 Juli Mallett <jmallett@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Based on nwhitehorn's COMPAT_FREEBSD32 support code for PowerPC64.
+ */
+
+#include "opt_compat.h"
+#include "opt_cputype.h"
+
+#define __ELF_WORD_SIZE 32
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/sysent.h>
+#include <sys/exec.h>
+#include <sys/imgact.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/namei.h>
+#include <sys/fcntl.h>
+#include <sys/sysent.h>
+#include <sys/imgact_elf.h>
+#include <sys/syscall.h>
+#include <sys/syscallsubr.h>
+#include <sys/sysproto.h>
+#include <sys/signalvar.h>
+#include <sys/vnode.h>
+#include <sys/linker.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+
+#include <machine/md_var.h>
+#include <machine/reg.h>
+#include <machine/sigframe.h>
+#include <machine/sysarch.h>
+
+#include <compat/freebsd32/freebsd32_signal.h>
+#include <compat/freebsd32/freebsd32_util.h>
+#include <compat/freebsd32/freebsd32_proto.h>
+
+static void freebsd32_exec_setregs(struct thread *, struct image_params *, u_long);
+static int get_mcontext32(struct thread *, mcontext32_t *, int);
+static int set_mcontext32(struct thread *, const mcontext32_t *);
+static void freebsd32_sendsig(sig_t, ksiginfo_t *, sigset_t *);
+
+extern const char *freebsd32_syscallnames[];
+
+struct sysentvec elf32_freebsd_sysvec = {
+ .sv_size = SYS_MAXSYSCALL,
+ .sv_table = freebsd32_sysent,
+ .sv_mask = 0,
+ .sv_sigsize = 0,
+ .sv_sigtbl = NULL,
+ .sv_errsize = 0,
+ .sv_errtbl = NULL,
+ .sv_transtrap = NULL,
+ .sv_fixup = __elfN(freebsd_fixup),
+ .sv_sendsig = freebsd32_sendsig,
+ .sv_sigcode = sigcode32,
+ .sv_szsigcode = &szsigcode32,
+ .sv_prepsyscall = NULL,
+ .sv_name = "FreeBSD ELF32",
+ .sv_coredump = __elfN(coredump),
+ .sv_imgact_try = NULL,
+ .sv_minsigstksz = MINSIGSTKSZ,
+ .sv_pagesize = PAGE_SIZE,
+ .sv_minuser = VM_MIN_ADDRESS,
+ .sv_maxuser = ((vm_offset_t)0x80000000),
+ .sv_usrstack = FREEBSD32_USRSTACK,
+ .sv_psstrings = FREEBSD32_PS_STRINGS,
+ .sv_stackprot = VM_PROT_ALL,
+ .sv_copyout_strings = freebsd32_copyout_strings,
+ .sv_setregs = freebsd32_exec_setregs,
+ .sv_fixlimit = NULL,
+ .sv_maxssiz = NULL,
+ .sv_flags = SV_ABI_FREEBSD | SV_ILP32,
+ .sv_set_syscall_retval = cpu_set_syscall_retval,
+ .sv_fetch_syscall_args = cpu_fetch_syscall_args,
+ .sv_syscallnames = freebsd32_syscallnames,
+ .sv_schedtail = NULL,
+};
+INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec);
+
+static Elf32_Brandinfo freebsd_brand_info = {
+ .brand = ELFOSABI_FREEBSD,
+ .machine = EM_MIPS,
+ .compat_3_brand = "FreeBSD",
+ .emul_path = NULL,
+ .interp_path = "/libexec/ld-elf.so.1",
+ .sysvec = &elf32_freebsd_sysvec,
+ .interp_newpath = "/libexec/ld-elf32.so.1",
+ .flags = 0
+};
+
+SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_FIRST,
+ (sysinit_cfunc_t) elf32_insert_brand_entry,
+ &freebsd_brand_info);
+
+static void
+freebsd32_exec_setregs(struct thread *td, struct image_params *imgp, u_long stack)
+{
+ exec_setregs(td, imgp, stack);
+
+ /*
+ * See comment in exec_setregs about running 32-bit binaries with 64-bit
+ * registers.
+ */
+ td->td_frame->sp -= 65536;
+
+ /*
+ * Clear extended address space bit for userland.
+ */
+ td->td_frame->sr &= ~MIPS_SR_UX;
+}
+
+int
+set_regs32(struct thread *td, struct reg32 *regs)
+{
+ struct reg r;
+ unsigned i;
+
+ for (i = 0; i < NUMSAVEREGS; i++)
+ r.r_regs[i] = regs->r_regs[i];
+
+ return (set_regs(td, &r));
+}
+
+int
+fill_regs32(struct thread *td, struct reg32 *regs)
+{
+ struct reg r;
+ unsigned i;
+ int error;
+
+ error = fill_regs(td, &r);
+ if (error != 0)
+ return (error);
+
+ for (i = 0; i < NUMSAVEREGS; i++)
+ regs->r_regs[i] = r.r_regs[i];
+
+ return (0);
+}
+
+int
+set_fpregs32(struct thread *td, struct fpreg32 *fpregs)
+{
+ struct fpreg fp;
+ unsigned i;
+
+ for (i = 0; i < NUMFPREGS; i++)
+ fp.r_regs[i] = fpregs->r_regs[i];
+
+ return (set_fpregs(td, &fp));
+}
+
+int
+fill_fpregs32(struct thread *td, struct fpreg32 *fpregs)
+{
+ struct fpreg fp;
+ unsigned i;
+ int error;
+
+ error = fill_fpregs(td, &fp);
+ if (error != 0)
+ return (error);
+
+ for (i = 0; i < NUMFPREGS; i++)
+ fpregs->r_regs[i] = fp.r_regs[i];
+
+ return (0);
+}
+
+static int
+get_mcontext32(struct thread *td, mcontext32_t *mcp, int flags)
+{
+ mcontext_t mcp64;
+ unsigned i;
+ int error;
+
+ error = get_mcontext(td, &mcp64, flags);
+ if (error != 0)
+ return (error);
+
+ mcp->mc_onstack = mcp64.mc_onstack;
+ mcp->mc_pc = mcp64.mc_pc;
+ for (i = 0; i < 32; i++)
+ mcp->mc_regs[i] = mcp64.mc_regs[i];
+ mcp->sr = mcp64.sr;
+ mcp->mullo = mcp64.mullo;
+ mcp->mulhi = mcp64.mulhi;
+ mcp->mc_fpused = mcp64.mc_fpused;
+ for (i = 0; i < 33; i++)
+ mcp->mc_fpregs[i] = mcp64.mc_fpregs[i];
+ mcp->mc_fpc_eir = mcp64.mc_fpc_eir;
+ mcp->mc_tls = mcp64.mc_tls;
+
+ return (0);
+}
+
+static int
+set_mcontext32(struct thread *td, const mcontext32_t *mcp)
+{
+ mcontext_t mcp64;
+ unsigned i;
+
+ mcp64.mc_onstack = mcp->mc_onstack;
+ mcp64.mc_pc = mcp->mc_pc;
+ for (i = 0; i < 32; i++)
+ mcp64.mc_regs[i] = mcp->mc_regs[i];
+ mcp64.sr = mcp->sr;
+ mcp64.mullo = mcp->mullo;
+ mcp64.mulhi = mcp->mulhi;
+ mcp64.mc_fpused = mcp->mc_fpused;
+ for (i = 0; i < 33; i++)
+ mcp64.mc_fpregs[i] = mcp->mc_fpregs[i];
+ mcp64.mc_fpc_eir = mcp->mc_fpc_eir;
+ mcp64.mc_tls = mcp->mc_tls;
+
+ return (set_mcontext(td, &mcp64));
+}
+
+int
+freebsd32_sigreturn(struct thread *td, struct freebsd32_sigreturn_args *uap)
+{
+ ucontext32_t uc;
+ int error;
+
+ CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp);
+
+ if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) {
+ CTR1(KTR_SIG, "sigreturn: efault td=%p", td);
+ return (EFAULT);
+ }
+
+ error = set_mcontext32(td, &uc.uc_mcontext);
+ if (error != 0)
+ return (error);
+
+ kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0);
+
+#if 0
+ CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x",
+ td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]);
+#endif
+
+ return (EJUSTRETURN);
+}
+
+/*
+ * The first two fields of a ucontext_t are the signal mask and the machine
+ * context. The next field is uc_link; we want to avoid destroying the link
+ * when copying out contexts.
+ */
+#define UC32_COPY_SIZE offsetof(ucontext32_t, uc_link)
+
+int
+freebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap)
+{
+ ucontext32_t uc;
+ int ret;
+
+ if (uap->ucp == NULL)
+ ret = EINVAL;
+ else {
+ get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
+ PROC_LOCK(td->td_proc);
+ uc.uc_sigmask = td->td_sigmask;
+ PROC_UNLOCK(td->td_proc);
+ ret = copyout(&uc, uap->ucp, UC32_COPY_SIZE);
+ }
+ return (ret);
+}
+
+int
+freebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap)
+{
+ ucontext32_t uc;
+ int ret;
+
+ if (uap->ucp == NULL)
+ ret = EINVAL;
+ else {
+ ret = copyin(uap->ucp, &uc, UC32_COPY_SIZE);
+ if (ret == 0) {
+ ret = set_mcontext32(td, &uc.uc_mcontext);
+ if (ret == 0) {
+ kern_sigprocmask(td, SIG_SETMASK,
+ &uc.uc_sigmask, NULL, 0);
+ }
+ }
+ }
+ return (ret == 0 ? EJUSTRETURN : ret);
+}
+
+int
+freebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap)
+{
+ ucontext32_t uc;
+ int ret;
+
+ if (uap->oucp == NULL || uap->ucp == NULL)
+ ret = EINVAL;
+ else {
+ get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
+ PROC_LOCK(td->td_proc);
+ uc.uc_sigmask = td->td_sigmask;
+ PROC_UNLOCK(td->td_proc);
+ ret = copyout(&uc, uap->oucp, UC32_COPY_SIZE);
+ if (ret == 0) {
+ ret = copyin(uap->ucp, &uc, UC32_COPY_SIZE);
+ if (ret == 0) {
+ ret = set_mcontext32(td, &uc.uc_mcontext);
+ if (ret == 0) {
+ kern_sigprocmask(td, SIG_SETMASK,
+ &uc.uc_sigmask, NULL, 0);
+ }
+ }
+ }
+ }
+ return (ret == 0 ? EJUSTRETURN : ret);
+}
+
+#define UCONTEXT_MAGIC 0xACEDBADE
+
+/*
+ * Send an interrupt to process.
+ *
+ * Stack is set up to allow sigcode stored
+ * at top to call routine, followed by kcall
+ * to sigreturn routine below. After sigreturn
+ * resets the signal mask, the stack, and the
+ * frame pointer, it returns to the user
+ * specified pc, psl.
+ */
+static void
+freebsd32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
+{
+ struct proc *p;
+ struct thread *td;
+ struct fpreg32 fpregs;
+ struct reg32 regs;
+ struct sigacts *psp;
+ struct sigframe32 sf, *sfp;
+ int sig;
+ int oonstack;
+ unsigned i;
+
+ td = curthread;
+ p = td->td_proc;
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+ sig = ksi->ksi_signo;
+ psp = p->p_sigacts;
+ mtx_assert(&psp->ps_mtx, MA_OWNED);
+
+ fill_regs32(td, &regs);
+ oonstack = sigonstack(td->td_frame->sp);
+
+ /* save user context */
+ bzero(&sf, sizeof sf);
+ sf.sf_uc.uc_sigmask = *mask;
+ sf.sf_uc.uc_stack.ss_sp = (int32_t)(intptr_t)td->td_sigstk.ss_sp;
+ sf.sf_uc.uc_stack.ss_size = td->td_sigstk.ss_size;
+ sf.sf_uc.uc_stack.ss_flags = td->td_sigstk.ss_flags;
+ sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
+ sf.sf_uc.uc_mcontext.mc_pc = regs.r_regs[PC];
+ sf.sf_uc.uc_mcontext.mullo = regs.r_regs[MULLO];
+ sf.sf_uc.uc_mcontext.mulhi = regs.r_regs[MULHI];
+ sf.sf_uc.uc_mcontext.mc_regs[0] = UCONTEXT_MAGIC; /* magic number */
+ for (i = 1; i < 32; i++)
+ sf.sf_uc.uc_mcontext.mc_regs[i] = regs.r_regs[i];
+ sf.sf_uc.uc_mcontext.mc_fpused = td->td_md.md_flags & MDTD_FPUSED;
+ if (sf.sf_uc.uc_mcontext.mc_fpused) {
+ /* if FPU has current state, save it first */
+ if (td == PCPU_GET(fpcurthread))
+ MipsSaveCurFPState(td);
+ fill_fpregs32(td, &fpregs);
+ for (i = 0; i < 33; i++)
+ sf.sf_uc.uc_mcontext.mc_fpregs[i] = fpregs.r_regs[i];
+ }
+
+ /* Allocate and validate space for the signal handler context. */
+ if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
+ SIGISMEMBER(psp->ps_sigonstack, sig)) {
+ sfp = (struct sigframe32 *)((vm_offset_t)(td->td_sigstk.ss_sp +
+ td->td_sigstk.ss_size - sizeof(struct sigframe32))
+ & ~(sizeof(__int64_t) - 1));
+ } else
+ sfp = (struct sigframe32 *)((vm_offset_t)(td->td_frame->sp -
+ sizeof(struct sigframe32)) & ~(sizeof(__int64_t) - 1));
+
+ /* Translate the signal if appropriate */
+ if (p->p_sysent->sv_sigtbl) {
+ if (sig <= p->p_sysent->sv_sigsize)
+ sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
+ }
+
+ /* Build the argument list for the signal handler. */
+ td->td_frame->a0 = sig;
+ td->td_frame->a2 = (register_t)(intptr_t)&sfp->sf_uc;
+ if (SIGISMEMBER(psp->ps_siginfo, sig)) {
+ /* Signal handler installed with SA_SIGINFO. */
+ td->td_frame->a1 = (register_t)(intptr_t)&sfp->sf_si;
+ /* sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher; */
+
+ /* fill siginfo structure */
+ sf.sf_si.si_signo = sig;
+ sf.sf_si.si_code = ksi->ksi_code;
+ sf.sf_si.si_addr = td->td_frame->badvaddr;
+ } else {
+ /* Old FreeBSD-style arguments. */
+ td->td_frame->a1 = ksi->ksi_code;
+ td->td_frame->a3 = td->td_frame->badvaddr;
+ /* sf.sf_ahu.sf_handler = catcher; */
+ }
+
+ mtx_unlock(&psp->ps_mtx);
+ PROC_UNLOCK(p);
+
+ /*
+ * Copy the sigframe out to the user's stack.
+ */
+ if (copyout(&sf, sfp, sizeof(struct sigframe32)) != 0) {
+ /*
+ * Something is wrong with the stack pointer.
+ * ...Kill the process.
+ */
+ PROC_LOCK(p);
+ sigexit(td, SIGILL);
+ }
+
+ td->td_frame->pc = (register_t)(intptr_t)catcher;
+ td->td_frame->t9 = (register_t)(intptr_t)catcher;
+ td->td_frame->sp = (register_t)(intptr_t)sfp;
+ /*
+ * Signal trampoline code is at base of user stack.
+ */
+ td->td_frame->ra = (register_t)(intptr_t)FREEBSD32_PS_STRINGS - *(p->p_sysent->sv_szsigcode);
+ PROC_LOCK(p);
+ mtx_lock(&psp->ps_mtx);
+}
+
+int
+freebsd32_sysarch(struct thread *td, struct freebsd32_sysarch_args *uap)
+{
+ int error;
+ int32_t tlsbase;
+
+ switch (uap->op) {
+ case MIPS_SET_TLS:
+ td->td_md.md_tls = (void *)(intptr_t)uap->parms;
+ return (0);
+ case MIPS_GET_TLS:
+ tlsbase = (int32_t)(intptr_t)td->td_md.md_tls;
+ error = copyout(&tlsbase, uap->parms, sizeof(tlsbase));
+ return (error);
+ default:
+ break;
+ }
+ return (EINVAL);
+}
+
+void
+elf32_dump_thread(struct thread *td __unused, void *dst __unused,
+ size_t *off __unused)
+{
+}
diff --git a/sys/mips/mips/genassym.c b/sys/mips/mips/genassym.c
index 58b1d86..b53cb5b 100644
--- a/sys/mips/mips/genassym.c
+++ b/sys/mips/mips/genassym.c
@@ -92,6 +92,9 @@ ASSYM(PC_CURPMAP, offsetof(struct pcpu, pc_curpmap));
ASSYM(VM_MAX_KERNEL_ADDRESS, VM_MAX_KERNEL_ADDRESS);
ASSYM(VM_MAXUSER_ADDRESS, VM_MAXUSER_ADDRESS);
ASSYM(SIGF_UC, offsetof(struct sigframe, sf_uc));
+#ifdef COMPAT_FREEBSD32
+ASSYM(SIGF32_UC, offsetof(struct sigframe32, sf_uc));
+#endif
ASSYM(SIGFPE, SIGFPE);
ASSYM(PAGE_SHIFT, PAGE_SHIFT);
ASSYM(PAGE_SIZE, PAGE_SIZE);
diff --git a/sys/mips/mips/swtch.S b/sys/mips/mips/swtch.S
index 8b285dd..e18f412 100644
--- a/sys/mips/mips/swtch.S
+++ b/sys/mips/mips/swtch.S
@@ -55,6 +55,7 @@
* assembly language support routines.
*/
+#include "opt_compat.h"
#include "opt_cputype.h"
#include <sys/syscall.h>
#include <machine/asm.h>
@@ -636,3 +637,21 @@ _C_LABEL(esigcode):
szsigcode:
.long esigcode-sigcode
.text
+
+#if (defined(__mips_n32) || defined(__mips_n64)) && defined(COMPAT_FREEBSD32)
+ .globl _C_LABEL(sigcode32)
+_C_LABEL(sigcode32):
+ addu a0, sp, SIGF32_UC # address of ucontext
+ li v0, SYS_sigreturn
+# sigreturn (ucp)
+ syscall
+ break 0 # just in case sigreturn fails
+ .globl _C_LABEL(esigcode32)
+_C_LABEL(esigcode32):
+
+ .data
+ .globl szsigcode32
+szsigcode32:
+ .long esigcode32-sigcode32
+ .text
+#endif
diff --git a/sys/mips/mips/trap.c b/sys/mips/mips/trap.c
index 77cfcd0..b162a18 100644
--- a/sys/mips/mips/trap.c
+++ b/sys/mips/mips/trap.c
@@ -41,6 +41,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_compat.h"
#include "opt_ddb.h"
#include "opt_global.h"
#include "opt_ktrace.h"
@@ -282,19 +283,30 @@ cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
sa->code = locr0->v0;
switch (sa->code) {
-#if defined(__mips_n32) || defined(__mips_n64)
case SYS___syscall:
+ case SYS_syscall:
/*
- * Quads fit in a single register in
- * new ABIs.
- *
- * XXX o64?
+ * This is an indirect syscall, in which the code is the first argument.
*/
+#if (!defined(__mips_n32) && !defined(__mips_n64)) || defined(COMPAT_FREEBSD32)
+ if (sa->code == SYS___syscall && SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
+ /*
+ * Like syscall, but code is a quad, so as to maintain alignment
+ * for the rest of the arguments.
+ */
+ if (_QUAD_LOWWORD == 0)
+ sa->code = locr0->a0;
+ else
+ sa->code = locr0->a1;
+ sa->args[0] = locr0->a2;
+ sa->args[1] = locr0->a3;
+ nsaved = 2;
+ break;
+ }
#endif
- case SYS_syscall:
/*
- * Code is first argument, followed by
- * actual args.
+ * This is either not a quad syscall, or is a quad syscall with a
+ * new ABI in which quads fit in a single register.
*/
sa->code = locr0->a0;
sa->args[0] = locr0->a1;
@@ -302,52 +314,60 @@ cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
sa->args[2] = locr0->a3;
nsaved = 3;
#if defined(__mips_n32) || defined(__mips_n64)
- sa->args[3] = locr0->t4;
- sa->args[4] = locr0->t5;
- sa->args[5] = locr0->t6;
- sa->args[6] = locr0->t7;
- nsaved += 4;
+#ifdef COMPAT_FREEBSD32
+ if (!SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
+#endif
+ /*
+ * Non-o32 ABIs support more arguments in registers.
+ */
+ sa->args[3] = locr0->t4;
+ sa->args[4] = locr0->t5;
+ sa->args[5] = locr0->t6;
+ sa->args[6] = locr0->t7;
+ nsaved += 4;
+#ifdef COMPAT_FREEBSD32
+ }
+#endif
#endif
break;
-
-#if defined(__mips_o32)
- case SYS___syscall:
+ default:
/*
- * Like syscall, but code is a quad, so as
- * to maintain quad alignment for the rest
- * of the arguments.
+ * A direct syscall, arguments are just parameters to the syscall.
*/
- if (_QUAD_LOWWORD == 0)
- sa->code = locr0->a0;
- else
- sa->code = locr0->a1;
- sa->args[0] = locr0->a2;
- sa->args[1] = locr0->a3;
- nsaved = 2;
- break;
-#endif
-
- default:
sa->args[0] = locr0->a0;
sa->args[1] = locr0->a1;
sa->args[2] = locr0->a2;
sa->args[3] = locr0->a3;
nsaved = 4;
#if defined (__mips_n32) || defined(__mips_n64)
- sa->args[4] = locr0->t4;
- sa->args[5] = locr0->t5;
- sa->args[6] = locr0->t6;
- sa->args[7] = locr0->t7;
- nsaved += 4;
+#ifdef COMPAT_FREEBSD32
+ if (!SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
+#endif
+ /*
+ * Non-o32 ABIs support more arguments in registers.
+ */
+ sa->args[4] = locr0->t4;
+ sa->args[5] = locr0->t5;
+ sa->args[6] = locr0->t6;
+ sa->args[7] = locr0->t7;
+ nsaved += 4;
+#if defined (__mips_n32) || defined(__mips_n64)
+ }
+#endif
#endif
break;
}
+
#ifdef TRAP_DEBUG
if (trap_debug)
- printf("SYSCALL #%d pid:%u\n", code, p->p_pid);
+ printf("SYSCALL #%d pid:%u\n", sa->code, td->td_proc->p_pid);
#endif
se = td->td_proc->p_sysent;
+ /*
+ * XXX
+ * Shouldn't this go before switching on the code?
+ */
if (se->sv_mask)
sa->code &= se->sv_mask;
@@ -366,8 +386,27 @@ cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
* should be 8, size there are 8 registers to skip,
* not 4, but I'm not certain.
*/
- printf("SYSCALL #%u pid:%u, nargs > nsaved.\n", sa->code,
- td->td_proc->p_pid);
+#ifdef COMPAT_FREEBSD32
+ if (!SV_PROC_FLAG(td->td_proc, SV_ILP32))
+#endif
+ printf("SYSCALL #%u pid:%u, narg (%u) > nsaved (%u).\n",
+ sa->code, td->td_proc->p_pid, sa->narg, nsaved);
+#endif
+#if (defined(__mips_n32) || defined(__mips_n64)) && defined(COMPAT_FREEBSD32)
+ if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
+ unsigned i;
+ int32_t arg;
+
+ error = 0; /* XXX GCC is awful. */
+ for (i = nsaved; i < sa->narg; i++) {
+ error = copyin((caddr_t)(intptr_t)(locr0->sp +
+ (4 + (i - nsaved)) * sizeof(int32_t)),
+ (caddr_t)&arg, sizeof arg);
+ if (error != 0)
+ break;
+ sa->args[i] = arg;
+ }
+ } else
#endif
error = copyin((caddr_t)(intptr_t)(locr0->sp +
4 * sizeof(register_t)), (caddr_t)&sa->args[nsaved],
@@ -539,7 +578,7 @@ trap(struct trapframe *trapframe)
goto err;
}
- /*
+ /*
* It is an error for the kernel to access user space except
* through the copyin/copyout routines.
*/
diff --git a/sys/mips/mips/vm_machdep.c b/sys/mips/mips/vm_machdep.c
index faff43b..34dcea8 100644
--- a/sys/mips/mips/vm_machdep.c
+++ b/sys/mips/mips/vm_machdep.c
@@ -41,6 +41,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_compat.h"
#include "opt_cputype.h"
#include "opt_ddb.h"
@@ -49,6 +50,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/proc.h>
#include <sys/syscall.h>
+#include <sys/sysent.h>
#include <sys/buf.h>
#include <sys/vnode.h>
#include <sys/vmmeter.h>
@@ -301,7 +303,12 @@ cpu_set_syscall_retval(struct thread *td, int error)
code = locr0->v0;
quad_syscall = 0;
-#if defined(__mips_o32)
+#if defined(__mips_n32) || defined(__mips_n64)
+#ifdef COMPAT_FREEBSD32
+ if (code == SYS___syscall && SV_PROC_FLAG(td->td_proc, SV_ILP32))
+ quad_syscall = 1;
+#endif
+#else
if (code == SYS___syscall)
quad_syscall = 1;
#endif
@@ -608,7 +615,12 @@ cpu_set_user_tls(struct thread *td, void *tls_base)
* to make it the same way TLS base is passed to
* MIPS_SET_TLS/MIPS_GET_TLS API
*/
+
#ifdef __mips_n64
+#ifdef COMPAT_FREEBSD32
+ if (SV_PROC_FLAG(td->td_proc, SV_ILP32))
+ td->td_md.md_tls = (char*)tls_base + 0x7008;
+#endif
td->td_md.md_tls = (char*)tls_base + 0x7010;
#else
td->td_md.md_tls = (char*)tls_base + 0x7008;
diff --git a/sys/net/bpf.c b/sys/net/bpf.c
index 80f5636..4f163d9 100644
--- a/sys/net/bpf.c
+++ b/sys/net/bpf.c
@@ -1055,7 +1055,7 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
#endif
case BIOCGETIF:
case BIOCGRTIMEOUT:
-#ifdef COMPAT_FREEBSD32
+#if defined(COMPAT_FREEBSD32) && !defined(__mips__)
case BIOCGRTIMEOUT32:
#endif
case BIOCGSTATS:
@@ -1067,7 +1067,7 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
case FIONREAD:
case BIOCLOCK:
case BIOCSRTIMEOUT:
-#ifdef COMPAT_FREEBSD32
+#if defined(COMPAT_FREEBSD32) && !defined(__mips__)
case BIOCSRTIMEOUT32:
#endif
case BIOCIMMEDIATE:
@@ -1262,12 +1262,12 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
* Set read timeout.
*/
case BIOCSRTIMEOUT:
-#ifdef COMPAT_FREEBSD32
+#if defined(COMPAT_FREEBSD32) && !defined(__mips__)
case BIOCSRTIMEOUT32:
#endif
{
struct timeval *tv = (struct timeval *)addr;
-#ifdef COMPAT_FREEBSD32
+#if defined(COMPAT_FREEBSD32) && !defined(__mips__)
struct timeval32 *tv32;
struct timeval tv64;
@@ -1293,12 +1293,12 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
* Get read timeout.
*/
case BIOCGRTIMEOUT:
-#ifdef COMPAT_FREEBSD32
+#if defined(COMPAT_FREEBSD32) && !defined(__mips__)
case BIOCGRTIMEOUT32:
#endif
{
struct timeval *tv;
-#ifdef COMPAT_FREEBSD32
+#if defined(COMPAT_FREEBSD32) && !defined(__mips__)
struct timeval32 *tv32;
struct timeval tv64;
@@ -1310,7 +1310,7 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
tv->tv_sec = d->bd_rtout / hz;
tv->tv_usec = (d->bd_rtout % hz) * tick;
-#ifdef COMPAT_FREEBSD32
+#if defined(COMPAT_FREEBSD32) && !defined(__mips__)
if (cmd == BIOCGRTIMEOUT32) {
tv32 = (struct timeval32 *)addr;
tv32->tv_sec = tv->tv_sec;
diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h
index 9000a51..64255ee 100644
--- a/sys/sys/sysctl.h
+++ b/sys/sys/sysctl.h
@@ -128,7 +128,8 @@ struct ctlname {
#define REQ_WIRED 2
/* definitions for sysctl_req 'flags' member */
-#if defined(__amd64__) || defined(__ia64__) || defined(__powerpc64__)
+#if defined(__amd64__) || defined(__ia64__) || defined(__powerpc64__) || \
+ (defined(__mips__) && defined(__mips_n64))
#define SCTL_MASK32 1 /* 32 bit emulation */
#endif
OpenPOWER on IntegriCloud