summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-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