FreeBSD-specific porting work.

cgo/libmach remain unimplemented. However, compilers, runtime,
and packages are 100%. I still need to go through and implement
missing syscalls (at least make sure they're all listed), but
for all shipped functionality, this is done. Ship! ;)

R=rsc, VenkateshSrinivas
https://golang.org/cl/152142
diff --git a/src/pkg/runtime/freebsd/amd64/defs.h b/src/pkg/runtime/freebsd/amd64/defs.h
new file mode 100644
index 0000000..06efcc2
--- /dev/null
+++ b/src/pkg/runtime/freebsd/amd64/defs.h
@@ -0,0 +1,157 @@
+// godefs -f -m64 freebsd/defs.c
+
+// MACHINE GENERATED - DO NOT EDIT.
+
+// Constants
+enum {
+	PROT_NONE = 0,
+	PROT_READ = 0x1,
+	PROT_WRITE = 0x2,
+	PROT_EXEC = 0x4,
+	MAP_ANON = 0x1000,
+	MAP_PRIVATE = 0x2,
+	SA_SIGINFO = 0x40,
+	SA_RESTART = 0x2,
+	SA_ONSTACK = 0x1,
+	UMTX_OP_WAIT = 0x2,
+	UMTX_OP_WAKE = 0x3,
+	EINTR = 0x4,
+};
+
+// Types
+#pragma pack on
+
+typedef struct Sigaltstack Sigaltstack;
+struct Sigaltstack {
+	int8 *ss_sp;
+	uint64 ss_size;
+	int32 ss_flags;
+	byte pad0[4];
+};
+
+typedef struct Sigset Sigset;
+struct Sigset {
+	uint32 __bits[4];
+};
+
+typedef union Sigval Sigval;
+union Sigval {
+	int32 sival_int;
+	void *sival_ptr;
+	int32 sigval_int;
+	void *sigval_ptr;
+};
+
+typedef struct StackT StackT;
+struct StackT {
+	int8 *ss_sp;
+	uint64 ss_size;
+	int32 ss_flags;
+	byte pad0[4];
+};
+
+typedef struct Siginfo Siginfo;
+struct Siginfo {
+	int32 si_signo;
+	int32 si_errno;
+	int32 si_code;
+	int32 si_pid;
+	uint32 si_uid;
+	int32 si_status;
+	void *si_addr;
+	Sigval si_value;
+	byte _reason[40];
+};
+
+typedef struct Mcontext Mcontext;
+struct Mcontext {
+	int64 mc_onstack;
+	int64 mc_rdi;
+	int64 mc_rsi;
+	int64 mc_rdx;
+	int64 mc_rcx;
+	int64 mc_r8;
+	int64 mc_r9;
+	int64 mc_rax;
+	int64 mc_rbx;
+	int64 mc_rbp;
+	int64 mc_r10;
+	int64 mc_r11;
+	int64 mc_r12;
+	int64 mc_r13;
+	int64 mc_r14;
+	int64 mc_r15;
+	uint32 mc_trapno;
+	uint16 mc_fs;
+	uint16 mc_gs;
+	int64 mc_addr;
+	uint32 mc_flags;
+	uint16 mc_es;
+	uint16 mc_ds;
+	int64 mc_err;
+	int64 mc_rip;
+	int64 mc_cs;
+	int64 mc_rflags;
+	int64 mc_rsp;
+	int64 mc_ss;
+	int64 mc_len;
+	int64 mc_fpformat;
+	int64 mc_ownedfp;
+	int64 mc_fpstate[64];
+	int64 mc_fsbase;
+	int64 mc_gsbase;
+	int64 mc_spare[6];
+};
+
+typedef struct Ucontext Ucontext;
+struct Ucontext {
+	Sigset uc_sigmask;
+	Mcontext uc_mcontext;
+	Ucontext *uc_link;
+	StackT uc_stack;
+	int32 uc_flags;
+	int32 __spare__[4];
+	byte pad0[12];
+};
+
+typedef struct Sigcontext Sigcontext;
+struct Sigcontext {
+	Sigset sc_mask;
+	int64 sc_onstack;
+	int64 sc_rdi;
+	int64 sc_rsi;
+	int64 sc_rdx;
+	int64 sc_rcx;
+	int64 sc_r8;
+	int64 sc_r9;
+	int64 sc_rax;
+	int64 sc_rbx;
+	int64 sc_rbp;
+	int64 sc_r10;
+	int64 sc_r11;
+	int64 sc_r12;
+	int64 sc_r13;
+	int64 sc_r14;
+	int64 sc_r15;
+	int32 sc_trapno;
+	int16 sc_fs;
+	int16 sc_gs;
+	int64 sc_addr;
+	int32 sc_flags;
+	int16 sc_es;
+	int16 sc_ds;
+	int64 sc_err;
+	int64 sc_rip;
+	int64 sc_cs;
+	int64 sc_rflags;
+	int64 sc_rsp;
+	int64 sc_ss;
+	int64 sc_len;
+	int64 sc_fpformat;
+	int64 sc_ownedfp;
+	int64 sc_fpstate[64];
+	int64 sc_fsbase;
+	int64 sc_gsbase;
+	int64 sc_spare[6];
+};
+#pragma pack off
diff --git a/src/pkg/runtime/freebsd/amd64/rt0.s b/src/pkg/runtime/freebsd/amd64/rt0.s
new file mode 100644
index 0000000..7903b7c
--- /dev/null
+++ b/src/pkg/runtime/freebsd/amd64/rt0.s
@@ -0,0 +1,9 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Darwin and Linux use the same linkage to main
+
+TEXT	_rt0_amd64_freebsd(SB),7,$-8
+	MOVQ	$_rt0_amd64(SB), DX
+	JMP	DX
diff --git a/src/pkg/runtime/freebsd/amd64/signal.c b/src/pkg/runtime/freebsd/amd64/signal.c
new file mode 100644
index 0000000..08d8972
--- /dev/null
+++ b/src/pkg/runtime/freebsd/amd64/signal.c
@@ -0,0 +1,117 @@
+#include "runtime.h"
+#include "defs.h"
+#include "signals.h"
+#include "os.h"
+
+extern void sigtramp(void);
+
+typedef struct sigaction {
+	union {
+		void    (*__sa_handler)(int32);
+		void    (*__sa_sigaction)(int32, Siginfo*, void *);
+	} __sigaction_u;		/* signal handler */
+	int32	sa_flags;		/* see signal options below */
+	int64	sa_mask;		/* signal mask to apply */
+} Sigaction;
+
+void
+dumpregs(Sigcontext *r)
+{
+	printf("rax     %X\n", r->sc_rax);
+	printf("rbx     %X\n", r->sc_rbx);
+	printf("rcx     %X\n", r->sc_rcx);
+	printf("rdx     %X\n", r->sc_rdx);
+	printf("rdi     %X\n", r->sc_rdi);
+	printf("rsi     %X\n", r->sc_rsi);
+	printf("rbp     %X\n", r->sc_rbp);
+	printf("rsp     %X\n", r->sc_rsp);
+	printf("r8      %X\n", r->sc_r8 );
+	printf("r9      %X\n", r->sc_r9 );
+	printf("r10     %X\n", r->sc_r10);
+	printf("r11     %X\n", r->sc_r11);
+	printf("r12     %X\n", r->sc_r12);
+	printf("r13     %X\n", r->sc_r13);
+	printf("r14     %X\n", r->sc_r14);
+	printf("r15     %X\n", r->sc_r15);
+	printf("rip     %X\n", r->sc_rip);
+	printf("rflags  %X\n", r->sc_flags);
+	printf("cs      %X\n", (uint64)r->sc_cs);
+	printf("fs      %X\n", (uint64)r->sc_fsbase);
+	printf("gs      %X\n", (uint64)r->sc_gsbase);
+}
+
+void
+sighandler(int32 sig, Siginfo* info, void* context)
+{
+	Ucontext *uc;
+	Mcontext *mc;
+	Sigcontext *sc;
+
+	if(panicking)	// traceback already printed
+		exit(2);
+	panicking = 1;
+
+	uc = context;
+	mc = &uc->uc_mcontext;
+	sc = (Sigcontext*)mc;	// same layout, more conveient names
+
+	if(sig < 0 || sig >= NSIG)
+		printf("Signal %d\n", sig);
+	else
+		printf("%s\n", sigtab[sig].name);
+
+	printf("Faulting address: %p\n", info->si_addr);
+	printf("PC=%X\n", sc->sc_rip);
+	printf("\n");
+
+	if(gotraceback()){
+		traceback((void*)sc->sc_rip, (void*)sc->sc_rsp, (void*)sc->sc_r15);
+		tracebackothers((void*)sc->sc_r15);
+		dumpregs(sc);
+	}
+
+	breakpoint();
+	exit(2);
+}
+
+void
+sigignore(void)
+{
+}
+
+void
+signalstack(byte *p, int32 n)
+{
+	Sigaltstack st;
+
+	st.ss_sp = (int8*)p;
+	st.ss_size = n;
+	st.ss_flags = 0;
+	sigaltstack(&st, nil);
+}
+
+void
+initsig(void)
+{
+	static Sigaction sa;
+
+	int32 i;
+	sa.sa_flags |= SA_ONSTACK | SA_SIGINFO;
+	sa.sa_mask = ~0x0ull;
+	
+	for(i = 0; i < NSIG; i++) {
+		if(sigtab[i].flags) {
+			if(sigtab[i].flags & SigCatch)
+				sa.__sigaction_u.__sa_handler = (void*) sigtramp;
+			else
+				sa.__sigaction_u.__sa_handler = (void*) sigignore;
+
+			if(sigtab[i].flags & SigRestart)
+				sa.sa_flags |= SA_RESTART;
+			else
+				sa.sa_flags &= ~SA_RESTART;
+
+			sigaction(i, &sa, nil);
+		}
+	}
+}
diff --git a/src/pkg/runtime/freebsd/amd64/sys.s b/src/pkg/runtime/freebsd/amd64/sys.s
new file mode 100644
index 0000000..1b62468
--- /dev/null
+++ b/src/pkg/runtime/freebsd/amd64/sys.s
@@ -0,0 +1,125 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+//
+// System calls and other sys.stuff for AMD64, FreeBSD
+// /usr/src/sys/kern/syscalls.master for syscall numbers.
+//
+
+#include "amd64/asm.h"
+	
+TEXT sys_umtx_op(SB),7,$0
+	MOVQ 8(SP), DI
+	MOVL 16(SP), SI
+	MOVL 20(SP), DX
+	MOVQ 24(SP), R10
+	MOVQ 32(SP), R8
+	MOVL $454, AX
+	SYSCALL
+	RET
+
+TEXT thr_new(SB),7,$0
+	MOVQ 8(SP), DI
+	MOVQ 16(SP), SI
+	MOVL $455, AX
+	SYSCALL
+	RET
+
+TEXT thr_start(SB),7,$0
+	MOVQ DI, m
+	MOVQ m_g0(m), g
+	CALL mstart(SB)
+	MOVQ 0, AX			// crash (not reached)
+
+
+// Exit the entire program (like C exit)
+TEXT	exit(SB),7,$-8
+	MOVL	8(SP), DI		// arg 1 exit status
+	MOVL	$1, AX
+	SYSCALL
+	CALL	notok(SB)
+	RET
+
+TEXT	exit1(SB),7,$-8
+	MOVQ	8(SP), DI		// arg 1 exit status
+	MOVL	$431, AX
+	SYSCALL
+	CALL	notok(SB)
+	RET
+
+TEXT	write(SB),7,$-8
+	MOVL	8(SP), DI		// arg 1 fd
+	MOVQ	16(SP), SI		// arg 2 buf
+	MOVL	24(SP), DX		// arg 3 count
+	MOVL	$4, AX
+	SYSCALL
+	JCC	2(PC)
+	CALL	notok(SB)
+	RET
+
+TEXT	sigaction(SB),7,$-8
+	MOVL	8(SP), DI		// arg 1 sig
+	MOVQ	16(SP), SI		// arg 2 act
+	MOVQ	24(SP), DX		// arg 3 oact
+	MOVL	$416, AX
+	SYSCALL
+	JCC	2(PC)
+	CALL	notok(SB)
+	RET
+
+TEXT	sigtramp(SB),7,$24-16
+	MOVQ	m_gsignal(m), g
+	MOVQ	DI, 0(SP)
+	MOVQ	SI, 8(SP)
+	MOVQ	DX, 16(SP)
+	CALL	sighandler(SB)
+	RET
+
+TEXT	runtime·mmap(SB),7,$-8
+	MOVQ	8(SP), DI		// arg 1 addr
+	MOVL	16(SP), SI		// arg 2 len
+	MOVL	20(SP), DX		// arg 3 prot
+	MOVL	24(SP), R10		// arg 4 flags
+	MOVL	28(SP), R8		// arg 5 fid
+	MOVL	32(SP), R9		// arg 6 offset
+	MOVL	$477, AX
+	SYSCALL
+	JCC	2(PC)
+	CALL	notok(SB)
+	RET
+
+TEXT	notok(SB),7,$-8
+	MOVL	$0xf1, BP
+	MOVQ	BP, (BP)
+	RET
+
+TEXT	runtime·memclr(SB),7,$-8
+	MOVQ	8(SP), DI		// arg 1 addr
+	MOVL	16(SP), CX		// arg 2 count
+	ADDL	$7, CX
+	SHRL	$3, CX
+	MOVQ	$0, AX
+	CLD
+	REP
+	STOSQ
+	RET
+
+TEXT	runtime·getcallerpc+0(SB),7,$0
+	MOVQ	x+0(FP),AX		// addr of first arg
+	MOVQ	-8(AX),AX		// get calling pc
+	RET
+
+TEXT	runtime·setcallerpc+0(SB),7,$0
+	MOVQ	x+0(FP),AX		// addr of first arg
+	MOVQ	x+8(FP), BX
+	MOVQ	BX, -8(AX)		// set calling pc
+	RET
+
+TEXT sigaltstack(SB),7,$-8
+	MOVQ	new+8(SP), DI
+	MOVQ	old+16(SP), SI
+	MOVQ	$53, AX
+	SYSCALL
+	JCC	2(PC)
+	CALL	notok(SB)
+	RET
diff --git a/src/pkg/runtime/freebsd/defs.c b/src/pkg/runtime/freebsd/defs.c
new file mode 100644
index 0000000..414e7cd
--- /dev/null
+++ b/src/pkg/runtime/freebsd/defs.c
@@ -0,0 +1,49 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+ * Input to godefs.
+ *
+	godefs -f -m64 defs.c >amd64/defs.h
+	godefs defs.c >386/defs.h
+ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <sys/ucontext.h>
+#include <sys/umtx.h>
+#include <sys/_sigset.h>
+
+enum {
+	$PROT_NONE = PROT_NONE,
+	$PROT_READ = PROT_READ,
+	$PROT_WRITE = PROT_WRITE,
+	$PROT_EXEC = PROT_EXEC,
+
+	$MAP_ANON = MAP_ANON,
+	$MAP_PRIVATE = MAP_PRIVATE,
+
+	$SA_SIGINFO = SA_SIGINFO,
+	$SA_RESTART = SA_RESTART,
+	$SA_ONSTACK = SA_ONSTACK,
+
+	$UMTX_OP_WAIT = UMTX_OP_WAIT,
+	$UMTX_OP_WAKE = UMTX_OP_WAKE,
+
+	$EINTR = EINTR,
+};
+
+typedef struct sigaltstack $Sigaltstack;
+typedef struct __sigset $Sigset;
+typedef union sigval $Sigval;
+typedef stack_t	$StackT;
+
+typedef siginfo_t $Siginfo;
+
+typedef mcontext_t $Mcontext;
+typedef ucontext_t $Ucontext;
+typedef struct sigcontext $Sigcontext;
diff --git a/src/pkg/runtime/freebsd/os.h b/src/pkg/runtime/freebsd/os.h
new file mode 100644
index 0000000..ec91500
--- /dev/null
+++ b/src/pkg/runtime/freebsd/os.h
@@ -0,0 +1,19 @@
+// FreeBSD-specific system calls
+int32 ksem_init(uint64 *, uint32);
+int32 ksem_wait(uint32);
+int32 ksem_destroy(uint32);
+int32 ksem_post(uint32);
+
+struct thr_param {
+    void	(*start_func)(void *);	/* thread entry function. */
+    void	*arg;			/* argument for entry function. */
+    byte	*stack_base;		/* stack base address. */
+    int64	stack_size;		/* stack size. */
+    byte	*tls_base;		/* tls base address. */
+    int64	tls_size;		/* tls size. */
+    int64	*child_tid;		/* address to store new TID. */
+    int64	*parent_tid;		/* parent accesses the new TID here. */
+    int32		flags;			/* thread flags. */
+    void	*spare[4];		/* TODO: cpu affinity mask etc. */
+};
+int32 thr_new(struct thr_param*, uint64);
diff --git a/src/pkg/runtime/freebsd/signals.h b/src/pkg/runtime/freebsd/signals.h
new file mode 100644
index 0000000..c566481
--- /dev/null
+++ b/src/pkg/runtime/freebsd/signals.h
@@ -0,0 +1,48 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#define C SigCatch
+#define I SigIgnore
+#define R SigRestart
+
+static SigTab sigtab[] = {
+	/* 0 */		0, "SIGNONE: no trap",
+	/* 1 */		0, "SIGHUP: terminal line hangup",
+	/* 2 */		0, "SIGINT: interrupt",
+	/* 3 */		C, "SIGQUIT: quit",
+	/* 4 */		C, "SIGILL: illegal instruction",
+	/* 5 */		C, "SIGTRAP: trace trap",
+	/* 6 */		C, "SIGABRT: abort",
+	/* 7 */		C, "SIGEMT: EMT instruction",
+	/* 8 */		C, "SIGFPE: floating-point exception",
+	/* 9 */		0, "SIGKILL: kill",
+	/* 10 */	C, "SIGBUS: bus error",
+	/* 11 */	C, "SIGSEGV: segmentation violation",
+	/* 12 */	C, "SIGSYS: bad system call",
+	/* 13 */	I, "SIGPIPE: write to broken pipe",
+	/* 14 */	0, "SIGALRM: alarm clock",
+	/* 15 */	0, "SIGTERM: termination",
+	/* 16 */	0, "SIGURG: urgent condition on socket",
+	/* 17 */	0, "SIGSTOP: stop, unblockable",
+	/* 18 */	0, "SIGTSTP: stop from tty",
+	/* 19 */	0, "SIGCONT: continue",
+	/* 20 */	I+R, "SIGCHLD: child status has changed",
+	/* 21 */	0, "SIGTTIN: background read from tty",
+	/* 22 */	0, "SIGTTOU: background write to tty",
+	/* 23 */	0, "SIGIO: i/o now possible",
+	/* 24 */	0, "SIGXCPU: cpu limit exceeded",
+	/* 25 */	0, "SIGXFSZ: file size limit exceeded",
+	/* 26 */	0, "SIGVTALRM: virtual alarm clock",
+	/* 27 */	0, "SIGPROF: profiling alarm clock",
+	/* 28 */	I+R, "SIGWINCH: window size change",
+	/* 29 */	0, "SIGINFO: information request",
+	/* 30 */	0, "SIGUSR1: user-defined signal 1",
+	/* 31 */	0, "SIGUSR2: user-defined signal 2",
+	/* 32 */	0, "SIGTHR: reserved",
+};
+#undef C
+#undef I
+#undef R
+
+#define	NSIG 33
diff --git a/src/pkg/runtime/freebsd/thread.c b/src/pkg/runtime/freebsd/thread.c
new file mode 100644
index 0000000..e7cd707
--- /dev/null
+++ b/src/pkg/runtime/freebsd/thread.c
@@ -0,0 +1,162 @@
+// Use of this source file is governed by a BSD-style
+// license that can be found in the LICENSE file.`
+
+#include "runtime.h"
+#include "defs.h"
+#include "signals.h"
+#include "os.h"
+
+// FreeBSD's umtx_op syscall is effectively the same as Linux's futex, and
+// thus the code is largely similar. See linux/thread.c for comments.
+
+static void
+umtx_wait(uint32 *addr, uint32 val)
+{
+	int32 ret;
+
+	ret = sys_umtx_op(addr, UMTX_OP_WAIT, val, nil, nil);
+	if(ret >= 0 || ret == -EINTR)
+		return;
+
+	printf("umtx_wait addr=%p val=%d ret=%d\n", addr, val, ret);
+	*(int32*)0x1005 = 0x1005;
+}
+
+static void
+umtx_wake(uint32 *addr)
+{
+	int32 ret;
+
+	ret = sys_umtx_op(addr, UMTX_OP_WAKE, 1, nil, nil);
+	if(ret >= 0)
+		return;
+
+	printf("umtx_wake addr=%p ret=%d\n", addr, ret);
+	*(int32*)0x1006 = 0x1006;
+}
+
+// See linux/thread.c for comments about the algorithm.
+static void
+umtx_lock(Lock *l)
+{
+	uint32 v;
+
+again:
+	v = l->key;
+	if((v&1) == 0){
+		if(cas(&l->key, v, v|1))
+			return;
+		goto again;
+	}
+
+	if(!cas(&l->key, v, v+2))
+		goto again;
+
+	umtx_wait(&l->key, v+2);
+
+	for(;;){
+		v = l->key;
+		if(v < 2)
+			throw("bad lock key");
+		if(cas(&l->key, v, v-2))
+			break;
+	}
+
+	goto again;
+}
+
+static void
+umtx_unlock(Lock *l)
+{
+	uint32 v;
+
+again:
+	v = l->key;
+	if((v&1) == 0)
+		throw("unlock of unlocked lock");
+	if(!cas(&l->key, v, v&~1))
+		goto again;
+
+	if(v&~1)
+		umtx_wake(&l->key);
+}
+
+void
+lock(Lock *l)
+{
+	if(m->locks < 0)
+		throw("lock count");
+	m->locks++;
+	umtx_lock(l);
+}
+
+void 
+unlock(Lock *l)
+{
+	m->locks--;
+	if(m->locks < 0)
+		throw("lock count");
+	umtx_unlock(l);
+}
+
+// Event notifications.
+void
+noteclear(Note *n)
+{
+	n->lock.key = 0;
+	umtx_lock(&n->lock);
+}
+
+void
+notesleep(Note *n)
+{
+	umtx_lock(&n->lock);
+	umtx_unlock(&n->lock);
+}
+
+void
+notewakeup(Note *n)
+{
+	umtx_unlock(&n->lock);
+}
+
+void thr_start(void*);
+
+void
+newosproc(M *m, G *g, void *stk, void (*fn)(void))
+{
+	struct thr_param param;
+
+	USED(fn);	// thr_start assumes fn == mstart
+	USED(g);	// thr_start assumes g == m->g0
+
+	if(0){
+		printf("newosproc stk=%p m=%p g=%p fn=%p id=%d/%d ostk=%p\n",
+			stk, m, g, fn, m->id, m->tls[0], &m);
+	}
+
+	runtime_memclr((byte*)&param, sizeof param);
+
+	param.start_func = thr_start;
+	param.arg = m;
+	param.stack_base = stk;
+	param.stack_size = g->stackbase - g->stackguard + 256;
+	param.child_tid = (int64*)&m->procid;
+	param.parent_tid = nil;
+
+	thr_new(&param, sizeof param);
+}
+
+void
+osinit(void)
+{
+}
+
+// Called to initialize a new m (including the bootstrap m).
+void
+minit(void)
+{
+	// Initialize signal handling
+	m->gsignal = malg(32*1024);
+	signalstack(m->gsignal->stackguard, 32*1024);
+}