Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 3 Mar 2012 08:19:18 +0000 (UTC)
From:      Juli Mallett <jmallett@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r232449 - in head/sys: compat/freebsd32 conf kern mips/include mips/mips net sys
Message-ID:  <201203030819.q238JIh1071157@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jmallett
Date: Sat Mar  3 08:19:18 2012
New Revision: 232449
URL: http://svn.freebsd.org/changeset/base/232449

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

Added:
  head/sys/mips/mips/freebsd32_machdep.c   (contents, props changed)
Modified:
  head/sys/compat/freebsd32/freebsd32.h
  head/sys/compat/freebsd32/freebsd32_misc.c
  head/sys/compat/freebsd32/freebsd32_proto.h
  head/sys/compat/freebsd32/freebsd32_syscall.h
  head/sys/compat/freebsd32/freebsd32_syscalls.c
  head/sys/compat/freebsd32/freebsd32_sysent.c
  head/sys/compat/freebsd32/freebsd32_systrace_args.c
  head/sys/compat/freebsd32/syscalls.master
  head/sys/conf/files.mips
  head/sys/conf/options.mips
  head/sys/kern/kern_tc.c
  head/sys/mips/include/elf.h
  head/sys/mips/include/md_var.h
  head/sys/mips/include/param.h
  head/sys/mips/include/proc.h
  head/sys/mips/include/reg.h
  head/sys/mips/include/sigframe.h
  head/sys/mips/include/ucontext.h
  head/sys/mips/include/vmparam.h
  head/sys/mips/mips/genassym.c
  head/sys/mips/mips/swtch.S
  head/sys/mips/mips/trap.c
  head/sys/mips/mips/vm_machdep.c
  head/sys/net/bpf.c
  head/sys/sys/sysctl.h

Modified: head/sys/compat/freebsd32/freebsd32.h
==============================================================================
--- head/sys/compat/freebsd32/freebsd32.h	Sat Mar  3 08:11:04 2012	(r232448)
+++ head/sys/compat/freebsd32/freebsd32.h	Sat Mar  3 08:19:18 2012	(r232449)
@@ -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 {			\

Modified: head/sys/compat/freebsd32/freebsd32_misc.c
==============================================================================
--- head/sys/compat/freebsd32/freebsd32_misc.c	Sat Mar  3 08:11:04 2012	(r232448)
+++ head/sys/compat/freebsd32/freebsd32_misc.c	Sat Mar  3 08:19:18 2012	(r232449)
@@ -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);

Modified: head/sys/compat/freebsd32/freebsd32_proto.h
==============================================================================
--- head/sys/compat/freebsd32/freebsd32_proto.h	Sat Mar  3 08:11:04 2012	(r232448)
+++ head/sys/compat/freebsd32/freebsd32_proto.h	Sat Mar  3 08:19:18 2012	(r232449)
@@ -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 threa
 
 #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 thre
 
 #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 
 
 #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 
 
 #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 {

Modified: head/sys/compat/freebsd32/freebsd32_syscall.h
==============================================================================
--- head/sys/compat/freebsd32/freebsd32_syscall.h	Sat Mar  3 08:11:04 2012	(r232448)
+++ head/sys/compat/freebsd32/freebsd32_syscall.h	Sat Mar  3 08:19:18 2012	(r232449)
@@ -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

Modified: head/sys/compat/freebsd32/freebsd32_syscalls.c
==============================================================================
--- head/sys/compat/freebsd32/freebsd32_syscalls.c	Sat Mar  3 08:11:04 2012	(r232448)
+++ head/sys/compat/freebsd32/freebsd32_syscalls.c	Sat Mar  3 08:19:18 2012	(r232449)
@@ -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 */

Modified: head/sys/compat/freebsd32/freebsd32_sysent.c
==============================================================================
--- head/sys/compat/freebsd32/freebsd32_sysent.c	Sat Mar  3 08:11:04 2012	(r232448)
+++ head/sys/compat/freebsd32/freebsd32_sysent.c	Sat Mar  3 08:19:18 2012	(r232449)
@@ -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 */

Modified: head/sys/compat/freebsd32/freebsd32_systrace_args.c
==============================================================================
--- head/sys/compat/freebsd32/freebsd32_systrace_args.c	Sat Mar  3 08:11:04 2012	(r232448)
+++ head/sys/compat/freebsd32/freebsd32_systrace_args.c	Sat Mar  3 08:19:18 2012	(r232449)
@@ -11,7 +11,7 @@ systrace_args(int sysnum, void *params, 
 {
 	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, in
 {
 	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, i
 {
 	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 */

Modified: head/sys/compat/freebsd32/syscalls.master
==============================================================================
--- head/sys/compat/freebsd32/syscalls.master	Sat Mar  3 08:11:04 2012	(r232448)
+++ head/sys/compat/freebsd32/syscalls.master	Sat Mar  3 08:19:18 2012	(r232449)
@@ -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
 

Modified: head/sys/conf/files.mips
==============================================================================
--- head/sys/conf/files.mips	Sat Mar  3 08:11:04 2012	(r232448)
+++ head/sys/conf/files.mips	Sat Mar  3 08:19:18 2012	(r232449)
@@ -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
 

Modified: head/sys/conf/options.mips
==============================================================================
--- head/sys/conf/options.mips	Sat Mar  3 08:11:04 2012	(r232448)
+++ head/sys/conf/options.mips	Sat Mar  3 08:19:18 2012	(r232449)
@@ -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

Modified: head/sys/kern/kern_tc.c
==============================================================================
--- head/sys/kern/kern_tc.c	Sat Mar  3 08:11:04 2012	(r232448)
+++ head/sys/kern/kern_tc.c	Sat Mar  3 08:19:18 2012	(r232449)
@@ -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));
 }
 

Modified: head/sys/mips/include/elf.h
==============================================================================
--- head/sys/mips/include/elf.h	Sat Mar  3 08:11:04 2012	(r232448)
+++ head/sys/mips/include/elf.h	Sat Mar  3 08:19:18 2012	(r232449)
@@ -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 */

Modified: head/sys/mips/include/md_var.h
==============================================================================
--- head/sys/mips/include/md_var.h	Sat Mar  3 08:11:04 2012	(r232448)
+++ head/sys/mips/include/md_var.h	Sat Mar  3 08:19:18 2012	(r232449)
@@ -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;
 

Modified: head/sys/mips/include/param.h
==============================================================================
--- head/sys/mips/include/param.h	Sat Mar  3 08:11:04 2012	(r232448)
+++ head/sys/mips/include/param.h	Sat Mar  3 08:19:18 2012	(r232449)
@@ -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

Modified: head/sys/mips/include/proc.h
==============================================================================
--- head/sys/mips/include/proc.h	Sat Mar  3 08:11:04 2012	(r232448)
+++ head/sys/mips/include/proc.h	Sat Mar  3 08:19:18 2012	(r232449)
@@ -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

Modified: head/sys/mips/include/reg.h
==============================================================================
--- head/sys/mips/include/reg.h	Sat Mar  3 08:11:04 2012	(r232448)
+++ head/sys/mips/include/reg.h	Sat Mar  3 08:19:18 2012	(r232449)
@@ -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 
 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_ */

Modified: head/sys/mips/include/sigframe.h
==============================================================================
--- head/sys/mips/include/sigframe.h	Sat Mar  3 08:11:04 2012	(r232448)
+++ head/sys/mips/include/sigframe.h	Sat Mar  3 08:19:18 2012	(r232449)
@@ -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_ */

Modified: head/sys/mips/include/ucontext.h
==============================================================================
--- head/sys/mips/include/ucontext.h	Sat Mar  3 08:11:04 2012	(r232448)
+++ head/sys/mips/include/ucontext.h	Sat Mar  3 08:19:18 2012	(r232449)
@@ -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

Modified: head/sys/mips/include/vmparam.h
==============================================================================
--- head/sys/mips/include/vmparam.h	Sat Mar  3 08:11:04 2012	(r232448)
+++ head/sys/mips/include/vmparam.h	Sat Mar  3 08:19:18 2012	(r232449)
@@ -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.
  */

Added: head/sys/mips/mips/freebsd32_machdep.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/mips/mips/freebsd32_machdep.c	Sat Mar  3 08:19:18 2012	(r232449)
@@ -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)
+{
+}

Modified: head/sys/mips/mips/genassym.c
==============================================================================
--- head/sys/mips/mips/genassym.c	Sat Mar  3 08:11:04 2012	(r232448)
+++ head/sys/mips/mips/genassym.c	Sat Mar  3 08:19:18 2012	(r232449)
@@ -92,6 +92,9 @@ ASSYM(PC_CURPMAP, offsetof(struct pcpu, 
 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);

Modified: head/sys/mips/mips/swtch.S
==============================================================================
--- head/sys/mips/mips/swtch.S	Sat Mar  3 08:11:04 2012	(r232448)
+++ head/sys/mips/mips/swtch.S	Sat Mar  3 08:19:18 2012	(r232449)
@@ -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):
+

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201203030819.q238JIh1071157>