diff options
Diffstat (limited to 'src/pkg/runtime')
-rw-r--r-- | src/pkg/runtime/freebsd/386/defs.h | 160 | ||||
-rwxr-xr-x | src/pkg/runtime/freebsd/386/rt0.s | 9 | ||||
-rw-r--r-- | src/pkg/runtime/freebsd/386/signal.c | 109 | ||||
-rw-r--r-- | src/pkg/runtime/freebsd/386/sys.s | 180 | ||||
-rw-r--r-- | src/pkg/runtime/freebsd/amd64/defs.h | 24 | ||||
-rw-r--r-- | src/pkg/runtime/freebsd/defs.c | 4 | ||||
-rw-r--r-- | src/pkg/runtime/freebsd/os.h | 20 | ||||
-rw-r--r-- | src/pkg/runtime/freebsd/thread.c | 8 |
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(¶m, sizeof param); } |