summaryrefslogtreecommitdiff
path: root/src/pkg/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/runtime')
-rw-r--r--src/pkg/runtime/freebsd/386/defs.h160
-rwxr-xr-xsrc/pkg/runtime/freebsd/386/rt0.s9
-rw-r--r--src/pkg/runtime/freebsd/386/signal.c109
-rw-r--r--src/pkg/runtime/freebsd/386/sys.s180
-rw-r--r--src/pkg/runtime/freebsd/amd64/defs.h24
-rw-r--r--src/pkg/runtime/freebsd/defs.c4
-rw-r--r--src/pkg/runtime/freebsd/os.h20
-rw-r--r--src/pkg/runtime/freebsd/thread.c8
8 files changed, 492 insertions, 22 deletions
diff --git a/src/pkg/runtime/freebsd/386/defs.h b/src/pkg/runtime/freebsd/386/defs.h
new file mode 100644
index 000000000..a49749311
--- /dev/null
+++ b/src/pkg/runtime/freebsd/386/defs.h
@@ -0,0 +1,160 @@
+// godefs 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 Rtprio Rtprio;
+struct Rtprio {
+ uint16 type;
+ uint16 prio;
+};
+
+typedef struct ThrParam ThrParam;
+struct ThrParam {
+ void *start_func;
+ void *arg;
+ int8 *stack_base;
+ uint32 stack_size;
+ int8 *tls_base;
+ uint32 tls_size;
+ int32 *child_tid;
+ int32 *parent_tid;
+ int32 flags;
+ Rtprio *rtp;
+ void* spare[3];
+};
+
+typedef struct Sigaltstack Sigaltstack;
+struct Sigaltstack {
+ int8 *ss_sp;
+ uint32 ss_size;
+ int32 ss_flags;
+};
+
+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;
+ uint32 ss_size;
+ int32 ss_flags;
+};
+
+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[32];
+};
+
+typedef struct Mcontext Mcontext;
+struct Mcontext {
+ int32 mc_onstack;
+ int32 mc_gs;
+ int32 mc_fs;
+ int32 mc_es;
+ int32 mc_ds;
+ int32 mc_edi;
+ int32 mc_esi;
+ int32 mc_ebp;
+ int32 mc_isp;
+ int32 mc_ebx;
+ int32 mc_edx;
+ int32 mc_ecx;
+ int32 mc_eax;
+ int32 mc_trapno;
+ int32 mc_err;
+ int32 mc_eip;
+ int32 mc_cs;
+ int32 mc_eflags;
+ int32 mc_esp;
+ int32 mc_ss;
+ int32 mc_len;
+ int32 mc_fpformat;
+ int32 mc_ownedfp;
+ int32 mc_spare1[1];
+ int32 mc_fpstate[128];
+ int32 mc_fsbase;
+ int32 mc_gsbase;
+ int32 mc_spare2[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;
+ int32 sc_onstack;
+ int32 sc_gs;
+ int32 sc_fs;
+ int32 sc_es;
+ int32 sc_ds;
+ int32 sc_edi;
+ int32 sc_esi;
+ int32 sc_ebp;
+ int32 sc_isp;
+ int32 sc_ebx;
+ int32 sc_edx;
+ int32 sc_ecx;
+ int32 sc_eax;
+ int32 sc_trapno;
+ int32 sc_err;
+ int32 sc_eip;
+ int32 sc_cs;
+ int32 sc_efl;
+ int32 sc_esp;
+ int32 sc_ss;
+ int32 sc_len;
+ int32 sc_fpformat;
+ int32 sc_ownedfp;
+ int32 sc_spare1[1];
+ int32 sc_fpstate[128];
+ int32 sc_fsbase;
+ int32 sc_gsbase;
+ int32 sc_spare2[6];
+};
+#pragma pack off
diff --git a/src/pkg/runtime/freebsd/386/rt0.s b/src/pkg/runtime/freebsd/386/rt0.s
new file mode 100755
index 000000000..67c5f912c
--- /dev/null
+++ b/src/pkg/runtime/freebsd/386/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_386_freebsd(SB),7,$0
+ JMP _rt0_386(SB)
+
diff --git a/src/pkg/runtime/freebsd/386/signal.c b/src/pkg/runtime/freebsd/386/signal.c
new file mode 100644
index 000000000..ac0e84f13
--- /dev/null
+++ b/src/pkg/runtime/freebsd/386/signal.c
@@ -0,0 +1,109 @@
+#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("eax %x\n", r->sc_eax);
+ printf("ebx %x\n", r->sc_ebx);
+ printf("ecx %x\n", r->sc_ecx);
+ printf("edx %x\n", r->sc_edx);
+ printf("edi %x\n", r->sc_edi);
+ printf("esi %x\n", r->sc_esi);
+ printf("ebp %x\n", r->sc_ebp);
+ printf("esp %x\n", r->sc_esp);
+ printf("eip %x\n", r->sc_eip);
+ printf("eflags %x\n", r->sc_efl);
+ printf("cs %x\n", r->sc_cs);
+ printf("fs %x\n", r->sc_fsbase);
+ printf("gs %x\n", 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_eip);
+ printf("\n");
+
+ if(gotraceback()){
+ traceback((void*)sc->sc_eip, (void*)sc->sc_esp, m->curg);
+ tracebackothers(m->curg);
+ 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/386/sys.s b/src/pkg/runtime/freebsd/386/sys.s
new file mode 100644
index 000000000..1048fea14
--- /dev/null
+++ b/src/pkg/runtime/freebsd/386/sys.s
@@ -0,0 +1,180 @@
+// 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 386, FreeBSD
+// /usr/src/sys/kern/syscalls.master for syscall numbers.
+//
+
+#include "386/asm.h"
+
+TEXT sys_umtx_op(SB),7,$-4
+ MOVL $454, AX
+ INT $0x80
+ RET
+
+TEXT thr_new(SB),7,$-4
+ MOVL $455, AX
+ INT $0x80
+ RET
+
+TEXT thr_start(SB),7,$0
+ MOVL mm+0(FP), AX
+ MOVL m_g0(AX), BX
+ LEAL m_tls(AX), BP
+ MOVL 0(BP), DI
+ ADDL $7, DI
+ PUSHAL
+ PUSHL $32
+ PUSHL BP
+ PUSHL DI
+ CALL setldt(SB)
+ POPL AX
+ POPL AX
+ POPL AX
+ POPAL
+ MOVL BX, g
+ MOVL AX, m
+ CALL mstart(SB)
+ MOVL 0, AX // crash (not reached)
+
+// Exit the entire program (like C exit)
+TEXT exit(SB),7,$-4
+ MOVL $1, AX
+ INT $0x80
+ CALL notok(SB)
+ RET
+
+TEXT exit1(SB),7,$-4
+ MOVL $431, AX
+ INT $0x80
+ JAE 2(PC)
+ CALL notok(SB)
+ RET
+
+TEXT write(SB),7,$-4
+ MOVL $4, AX
+ INT $0x80
+ JAE 2(PC)
+ CALL notok(SB)
+ RET
+
+TEXT notok(SB),7,$0
+ MOVL $0xf1, 0xf1
+ RET
+
+TEXT runtime·mmap(SB),7,$-4
+ MOVL $477, AX
+ INT $0x80
+ JAE 2(PC)
+ CALL notok(SB)
+ RET
+
+TEXT sigaction(SB),7,$-4
+ MOVL $416, AX
+ INT $0x80
+ JAE 2(PC)
+ CALL notok(SB)
+ RET
+
+TEXT sigtramp(SB),7,$40
+ // g = m->gsignal
+ MOVL m, BP
+ MOVL m_gsignal(BP), BP
+ MOVL BP, g
+
+ MOVL signo+0(FP), AX
+ MOVL siginfo+4(FP), BX
+ MOVL context+8(FP), CX
+
+ MOVL AX, 0(SP)
+ MOVL BX, 4(SP)
+ MOVL CX, 8(SP)
+ CALL sighandler(SB)
+
+ // g = m->curg
+ MOVL m, BP
+ MOVL m_curg(BP), BP
+ MOVL BP, g
+
+ MOVL context+8(FP), AX
+
+ MOVL $0, 0(SP) // syscall gap
+ MOVL AX, 4(SP)
+ MOVL $417, AX // sigreturn(ucontext)
+ INT $0x80
+ CALL notok(SB)
+ RET
+
+TEXT sigaltstack(SB),7,$0
+ MOVL $53, AX
+ INT $0x80
+ JAE 2(PC)
+ CALL notok(SB)
+ RET
+
+/*
+descriptor entry format for system call
+is the native machine format, ugly as it is:
+
+ 2-byte limit
+ 3-byte base
+ 1-byte: 0x80=present, 0x60=dpl<<5, 0x1F=type
+ 1-byte: 0x80=limit is *4k, 0x40=32-bit operand size,
+ 0x0F=4 more bits of limit
+ 1 byte: 8 more bits of base
+
+int i386_get_ldt(int, union ldt_entry *, int);
+int i386_set_ldt(int, const union ldt_entry *, int);
+
+*/
+
+// setldt(int entry, int address, int limit)
+TEXT setldt(SB),7,$32
+ MOVL address+4(FP), BX // aka base
+ MOVL limit+8(FP), CX
+
+ // set up data_desc
+ LEAL 16(SP), AX // struct data_desc
+ MOVL $0, 0(AX)
+ MOVL $0, 4(AX)
+
+ MOVW BX, 2(AX)
+ SHRL $16, BX
+ MOVB BX, 4(AX)
+ SHRL $8, BX
+ MOVB BX, 7(AX)
+
+ MOVW CX, 0(AX)
+ SHRL $16, CX
+ ANDL $0x0F, CX
+ ORL $0x40, CX // 32-bit operand size
+ MOVB CX, 6(AX)
+
+ MOVB $0xF2, 5(AX) // r/w data descriptor, dpl=3, present
+
+ // call i386_set_ldt(entry, desc, 1)
+ MOVL $0xffffffff, 0(SP) // auto-allocate entry and return in AX
+ MOVL AX, 4(SP)
+ MOVL $1, 8(SP)
+ CALL i386_set_ldt(SB)
+
+ // compute segment selector - (entry*8+7)
+ SHLL $3, AX
+ ADDL $7, AX
+ MOVW AX, GS
+ RET
+
+TEXT i386_set_ldt(SB),7,$16
+ LEAL args+0(FP), AX // 0(FP) == 4(SP) before SP got moved
+ MOVL $0, 0(SP) // syscall gap
+ MOVL $1, 4(SP)
+ MOVL AX, 8(SP)
+ MOVL $165, AX
+ INT $0x80
+ CMPL AX, $0xfffff001
+ JLS 2(PC)
+ INT $3
+ RET
+
+GLOBL tlsoffset(SB),$4
diff --git a/src/pkg/runtime/freebsd/amd64/defs.h b/src/pkg/runtime/freebsd/amd64/defs.h
index 06efcc27a..83fd40b1c 100644
--- a/src/pkg/runtime/freebsd/amd64/defs.h
+++ b/src/pkg/runtime/freebsd/amd64/defs.h
@@ -1,4 +1,4 @@
-// godefs -f -m64 freebsd/defs.c
+// godefs -f -m64 defs.c
// MACHINE GENERATED - DO NOT EDIT.
@@ -21,6 +21,28 @@ enum {
// Types
#pragma pack on
+typedef struct Rtprio Rtprio;
+struct Rtprio {
+ uint16 type;
+ uint16 prio;
+};
+
+typedef struct ThrParam ThrParam;
+struct ThrParam {
+ void *start_func;
+ void *arg;
+ int8 *stack_base;
+ uint64 stack_size;
+ int8 *tls_base;
+ uint64 tls_size;
+ int64 *child_tid;
+ int64 *parent_tid;
+ int32 flags;
+ byte pad0[4];
+ Rtprio *rtp;
+ void* spare[3];
+};
+
typedef struct Sigaltstack Sigaltstack;
struct Sigaltstack {
int8 *ss_sp;
diff --git a/src/pkg/runtime/freebsd/defs.c b/src/pkg/runtime/freebsd/defs.c
index 414e7cd76..93f3f9d15 100644
--- a/src/pkg/runtime/freebsd/defs.c
+++ b/src/pkg/runtime/freebsd/defs.c
@@ -16,6 +16,8 @@
#include <sys/mman.h>
#include <sys/ucontext.h>
#include <sys/umtx.h>
+#include <sys/rtprio.h>
+#include <sys/thr.h>
#include <sys/_sigset.h>
enum {
@@ -37,6 +39,8 @@ enum {
$EINTR = EINTR,
};
+typedef struct rtprio $Rtprio;
+typedef struct thr_param $ThrParam;
typedef struct sigaltstack $Sigaltstack;
typedef struct __sigset $Sigset;
typedef union sigval $Sigval;
diff --git a/src/pkg/runtime/freebsd/os.h b/src/pkg/runtime/freebsd/os.h
index ec91500b7..441737865 100644
--- a/src/pkg/runtime/freebsd/os.h
+++ b/src/pkg/runtime/freebsd/os.h
@@ -1,19 +1 @@
-// 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);
+int32 thr_new(ThrParam*, int32);
diff --git a/src/pkg/runtime/freebsd/thread.c b/src/pkg/runtime/freebsd/thread.c
index e7cd707d0..a4e1e13e5 100644
--- a/src/pkg/runtime/freebsd/thread.c
+++ b/src/pkg/runtime/freebsd/thread.c
@@ -125,7 +125,7 @@ void thr_start(void*);
void
newosproc(M *m, G *g, void *stk, void (*fn)(void))
{
- struct thr_param param;
+ ThrParam param;
USED(fn); // thr_start assumes fn == mstart
USED(g); // thr_start assumes g == m->g0
@@ -141,8 +141,12 @@ newosproc(M *m, G *g, void *stk, void (*fn)(void))
param.arg = m;
param.stack_base = stk;
param.stack_size = g->stackbase - g->stackguard + 256;
- param.child_tid = (int64*)&m->procid;
+ param.child_tid = (int32*)&m->procid;
param.parent_tid = nil;
+ param.tls_base = (int8*)&m->tls[0];
+ param.tls_size = sizeof m->tls;
+
+ m->tls[0] = m->id; // so 386 asm can find it
thr_new(&param, sizeof param);
}